From 1ebd938bed176fbfa4f67d38cfe8af36e40c66f2 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 9 Jan 2012 12:55:24 -0500 Subject: [PATCH 001/881] Adding the unified2 analyzer. - This isn't connected to anything yet. --- src/CMakeLists.txt | 3 + src/unified2-analyzer.pac | 26 +++++++++ src/unified2-file.pac | 118 ++++++++++++++++++++++++++++++++++++++ src/unified2.pac | 21 +++++++ 4 files changed, 168 insertions(+) create mode 100644 src/unified2-analyzer.pac create mode 100644 src/unified2-file.pac create mode 100644 src/unified2.pac diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 47314514f6..8f9da667e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -209,6 +209,9 @@ binpac_target(ssl.pac ssl-defs.pac ssl-protocol.pac ssl-analyzer.pac) binpac_target(syslog.pac syslog-protocol.pac syslog-analyzer.pac) +binpac_target(unified2.pac + unified2-file.pac unified2-analyzer.pac) + ######################################################################## ## bro target diff --git a/src/unified2-analyzer.pac b/src/unified2-analyzer.pac new file mode 100644 index 0000000000..9f4f206562 --- /dev/null +++ b/src/unified2-analyzer.pac @@ -0,0 +1,26 @@ + +refine flow Flow += { + + %member{ + %} + + %init{ + %} + + %eof{ + %} + + %cleanup{ + %} + + function proc_ids_event(ev: IDSEvent) : bool + %{ + printf("woo!\n"); + return true; + %} +}; + + +refine typeattr IDSEvent += &let { + proc : bool = $context.flow.proc_ids_event(this); +}; diff --git a/src/unified2-file.pac b/src/unified2-file.pac new file mode 100644 index 0000000000..26b72b14dd --- /dev/null +++ b/src/unified2-file.pac @@ -0,0 +1,118 @@ + +enum Types { + EVENT = 0, + PACKET = 1, + IDS_EVENT = 2, + IDS_EVENT_IPV6 = 72, + IDS_EVENT_MPLS = 99, + IDS_EVENT_IPV6_MPLS = 100, + IDS_EVENT_VLAN = 104, + IDS_EVENT_IPV6_VLAN = 105, + EXTRA_DATA = 110, +}; + + +type Time = record { + seconds: uint32; + microseconds: uint32; +} &byteorder=bigendian; + +type v4Addr = record { + u1: uint32; +}; + +type v6Addr = record { + u1: uint32; + u2: uint32; + u3: uint32; + u4: uint32; +}; + +type Addr(ip_ver: int) = case ip_ver of { + 4 -> v4: v4Addr; + 6 -> v6: v6Addr; +} &byteorder=bigendian; + +type Record = record { + rtype: uint32; + length: uint32; + data: case rtype of { + # EVENT -> event: Event(this); + PACKET -> packet: Packet(this); + IDS_EVENT -> ids_event: LegacyIDSEvent(this, 4); + IDS_EVENT_IPV6 -> ids_event_ipv6: LegacyIDSEvent(this, 6); + # IDS_EVENT_MPLS -> ids_event_mpls: IDSEvent(this, 4); + # IDS_EVENT_IPV6_MPLS -> ids_event_ipv6_mpls: IDSEvent(this, 6); + IDS_EVENT_VLAN -> ids_event_vlan: IDSEvent(this, 4); + IDS_EVENT_IPV6_VLAN -> ids_event_ipv6_vlan: IDSEvent(this, 6); + EXTRA_DATA -> extra_data: ExtraData(this); + default -> unknown_record_type: UnknownRecordType(this); + }; +} &byteorder=bigendian &length=length+8; + +type LegacyIDSEvent(rec: Record, ip_ver: int) = record { + sensor_id: uint32; + event_id: uint32; + ts: Time; + signature_id: uint32; + generator_id: uint32; + signature_revision: uint32; + classification_id: uint32; + priority_id: uint32; + src_ip: Addr(ip_ver); + dst_ip: Addr(ip_ver); + src_p: uint16; + dst_p: uint16; + protocol: uint8; + packet_action: uint8; +}; + +type IDSEvent(rec: Record, ip_ver: int) = record { + sensor_id: uint32; + event_id: uint32; + ts: Time; + signature_id: uint32; + generator_id: uint32; + signature_revision: uint32; + classification_id: uint32; + priority_id: uint32; + src_ip: Addr(ip_ver); + dst_ip: Addr(ip_ver); + src_p: uint16; + dst_p: uint16; + protocol: uint8; + impact_flag: uint8; + impact: uint8; + blocked: uint8; + mpls_label: uint32; + vlan_id: uint16; + : uint16; +} &byteorder=bigendian; + +type Packet(rec: Record) = record { + sensor_id: uint32; + event_id: uint32; + event_second: uint32; + packet_ts: Time; + link_type: uint32; + packet_len: uint32; + packet_data: bytestring &length=packet_len; +} &byteorder=bigendian &length=rec.length; + +type ExtraData(rec: Record) = record { + sensor_id: uint32; + event_id: uint32; + event_second: uint32; + extra_type: uint32; + data_type: uint32; + blob_len: uint32; + blob: bytestring &length=blob_len; +} &byteorder=bigendian &length=rec.length; + +type UnknownRecordType(rec: Record) = record { + data: bytestring &transient &length=rec.length; +} &byteorder=bigendian &length=rec.length; + +type File = record { + alerts: Record[] &transient &until($element <= 0); +} &byteorder=bigendian; diff --git a/src/unified2.pac b/src/unified2.pac new file mode 100644 index 0000000000..86820eb9f3 --- /dev/null +++ b/src/unified2.pac @@ -0,0 +1,21 @@ + +%include binpac.pac +%include bro.pac + +analyzer Unified2 withcontext { + analyzer: Unified2_Analyzer; + flow: Flow; +}; + +analyzer Unified2_Analyzer { + downflow = Flow; + upflow = Flow; +}; + +%include unified2-file.pac + +flow Flow { + flowunit = File withcontext(connection, this); +}; + +%include unified2-analyzer.pac From a376f2244e9af06e636a47238d25099c1fcbb5c0 Mon Sep 17 00:00:00 2001 From: Soumya Basu Date: Thu, 9 Aug 2012 17:11:57 -0700 Subject: [PATCH 002/881] Initial commit. Everything compiles, but it seg faults when you try adding an element to the cardinality counter. --- src/CMakeLists.txt | 1 + src/bro.bif | 207 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 206 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ce440852d7..56d8faee98 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -332,6 +332,7 @@ set(bro_SRCS HTTP.cc HTTP-binpac.cc Hash.cc + HyperLogLog.cc ICMP.cc ID.cc Ident.cc diff --git a/src/bro.bif b/src/bro.bif index 2a37429ad6..6e41aaad99 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -1,5 +1,3 @@ -##! A collection of built-in functions that implement a variety of things -##! such as general programming algorithms, string processing, math functions, ##! introspection, type conversion, file/directory manipulation, packet ##! filtering, inter-process communication and controlling protocol analyzer ##! behavior. @@ -5860,3 +5858,208 @@ function generate_idmef%(src_ip: addr, src_port: port, return new Val(0, TYPE_BOOL); #endif %} + + +## This is where my code starts... +##Just a note about notation. I'm specifying everything with the prefix hll just +## in case in the future, there's a better way to count cardinalities or something. +## That way, code written that depends on the HyperLogLog algorithm will still be +## working. Though, I'm fairly certain that anything that might be better won't +## be significantly better. + + +%%{ +#include "HyperLogLog.h" +static map hll_counters; +%%} + +## Initializes the hash for the HyperLogLog cardinality counting algorithm. +## It returns true if it was successful in creating a structure and false +## if it wasn't. + +function hll_cardinality_init%(err: double,index: any%): bool + %{ + BroString* s = convert_index_to_string(index); + int status = 0; + + if ( hll_counters.count(*s) < 1 ) + { + hll_counters[*s] = new CardinalityCounter(err); + status = 1; + } + + delete s; + return new Val(status, TYPE_BOOL); + %} + +## Adds an element to the HyperLogLog data structure located at index. + +##elem->Type() to get the type of elem. + +function hll_cardinality_add%(elem: any, index: any%): bool + %{ + BroString* s = convert_index_to_string(index); + int status = 0; + + CompositeHash* hll_hash = new CompositeHash(new TypeList(elem->Type())); + HashKey* key; + if(hll_counters.count(*s) > 0) + { + CardinalityCounter* h = hll_counters[*s]; + key = hll_hash->ComputeHash(elem,1); + (*h).addElement(key->Hash()); + status = 1; + } + + delete s; + return new Val(status, TYPE_BOOL); + %} + +## The data structure at index1 will contain the combined count for the +## elements measured by index1 and index2. +## It returns true if it either cloned the value at index2 into index1 +## or if it merged the two data structures together. + +function hll_cardinality_merge_into%(index1: any, index2: any%): bool + %{ + BroString* s1 = convert_index_to_string(index1); + BroString* s2 = convert_index_to_string(index2); + int status = 0; + + if(hll_counters.count(*s1) < 1) + { + if(hll_counters.count(*s2) < 1) + { + status = 0; + } + else + { + uint64_t m = (*hll_counters[*s2]).getM(); + double error = 1.04/sqrt(m); + CardinalityCounter* newInst = new CardinalityCounter(error); + int i = 0; + while((*newInst).getM() != m) + { + i += 1; + newInst = new CardinalityCounter(error/i); + } + hll_counters[*s1] = newInst; + (*newInst).merge(hll_counters[*s2]); + status = 1; + } + } + else + { + if(hll_counters.count(*s2) < 1) + { + status = 0; + } + else + { + if((*hll_counters[*s2]).getM() == (*hll_counters[*s1]).getM()) + { + status = 1; + (*hll_counters[*s1]).merge(hll_counters[*s2]); + } + } + } + + delete s1; + delete s2; + return new Val(status, TYPE_BOOL); + + %} + +## Returns true if it destroyed something. False if it didn't. +function hll_cardinality_destroy%(index: any%): bool + %{ + BroString* s = convert_index_to_string(index); + int status = 0; + + if(hll_counters.count(*s) > 0) + { + delete hll_counters[*s]; + } + + delete s; + return new Val(status, TYPE_BOOL); + %} + +## Returns the cardinality estimate. Returns -1.0 if there is nothing in that index. +function hll_cardinality_estimate%(index: any%): double + %{ + BroString* s = convert_index_to_string(index); + double estimate = -1.0; + + if(hll_counters.count(*s) > 0) + { + estimate = (*hll_counters[*s]).size(); + } + + delete s; + return new Val(estimate, TYPE_DOUBLE); + %} + +##I'm really not sure about the notation of this function... + +function hll_cardinality_keys%(%): bool + %{ +// TableVal* a = new TableVal(string_set); +// map::iterator it; + +// for(it = hll_counters.begin() ; it != hll_counters.end(); it++) +// { +// a->Assign((*it).first); +// } +// return a; + return new Val(1, TYPE_BOOL); + %} + +## Stores the data structure at index2 into index1. Deletes the data structure at index1 +## if there was any. Returns True if the data structure at index1 was changed in any way. + +function hll_cardinality_clone%(index1: any, index2: any%): bool + %{ + BroString* s1 = convert_index_to_string(index1); + BroString* s2 = convert_index_to_string(index2); + int status = 0; + + if(hll_counters.count(*s2) < 1) + { + if(hll_counters.count(*s1) < 1) + { + status = 0; + } + else + { + delete hll_counters[*s1]; + status = 1; + } + } + else + { + uint64_t m = (*hll_counters[*s2]).getM(); + double error = 1.04/sqrt(m); + CardinalityCounter* newInst = new CardinalityCounter(error); + int i = 0; + while((*newInst).getM() != m) + { + i += 1; + newInst = new CardinalityCounter(error/i); + } + (*newInst).merge(hll_counters[*s2]); + if(hll_counters.count(*s1) < 1) + { + hll_counters[*s1] = newInst; + } + else + { + delete hll_counters[*s1]; + hll_counters[*s1] = newInst; + } + status = 1; + } + delete s1; + delete s2; + return new Val(status, TYPE_BOOL); + %} From bbaa35434b653bd680632b83ffaa0d0b9e71deeb Mon Sep 17 00:00:00 2001 From: Soumya Basu Date: Sat, 11 Aug 2012 16:45:58 -0700 Subject: [PATCH 003/881] Added the HyperLogLog files to the repository, and the size method works as well. The add method has an error with the hashkeys thus far and no other methods outside of init and size have been tested yet. --- mytests.bro | 29 ++++++++++++ src/HyperLogLog.cc | 113 +++++++++++++++++++++++++++++++++++++++++++++ src/HyperLogLog.h | 105 +++++++++++++++++++++++++++++++++++++++++ src/bro.bif | 5 +- 4 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 mytests.bro create mode 100644 src/HyperLogLog.cc create mode 100644 src/HyperLogLog.h diff --git a/mytests.bro b/mytests.bro new file mode 100644 index 0000000000..3e5af497f3 --- /dev/null +++ b/mytests.bro @@ -0,0 +1,29 @@ +event bro_init() + { + local m1 = "measurement1"; + local m2 = "measurement2"; + + hll_cardinality_init(0.01, m1); + + local add1 = "hey"; + local add2 = "hi"; + local add3 = 123; + + hll_cardinality_add(add1, m1); + hll_cardinality_add(add2, m1); + hll_cardinality_add(add3, m1); + hll_cardinality_add("a", m1); + hll_cardinality_add("b", m1); + hll_cardinality_add("c", m1); + hll_cardinality_add("d", m1); + hll_cardinality_add("e", m1); + hll_cardinality_add("f", m1); + hll_cardinality_add("g", m1); + hll_cardinality_add("h", m1); + hll_cardinality_add("i", m1); + hll_cardinality_add("j", m1); + + local e = hll_cardinality_estimate(m1); + print e; + + } diff --git a/src/HyperLogLog.cc b/src/HyperLogLog.cc new file mode 100644 index 0000000000..22f522d1ab --- /dev/null +++ b/src/HyperLogLog.cc @@ -0,0 +1,113 @@ +#include +#include +#include "HyperLogLog.h" +#include + +using namespace std; + + int CardinalityCounter::optimalB(double error){ + double initial_estimate = 2*(log(1.04)-log(error))/log(2); + int answer = (int) floor(initial_estimate); + double k; + + do{ + answer++; + k = pow(2, (answer - initial_estimate)/2); + }while(erf(k/sqrt(2)) < conf); + + return answer; + } + + + CardinalityCounter :: CardinalityCounter(double error_margin){ + int b = optimalB(error_margin); + m = (uint64_t) pow(2, b); + buckets = new uint8_t[m]; + + if(m == 16) + alpha_m = 0.673; + else if(m == 32) + alpha_m = 0.697; + else if(m == 64) + alpha_m = 0.709; + else + alpha_m = 0.7213/(1+1.079/m); + + for(uint64_t i = 0; i < m; i++){ + buckets[i] = 0; + } + + V = m; + } + + CardinalityCounter :: ~CardinalityCounter(){ + delete [] buckets; + delete &m; + delete &V; + delete &alpha_m; + } + + uint8_t CardinalityCounter :: rank(uint64_t hash_modified){ + uint8_t answer = 0; + hash_modified = (uint64_t)(hash_modified/m); + hash_modified *= 2; + do{ + hash_modified = (uint64_t) (hash_modified/2); + answer++; + }while(hash_modified%2 == 0); + return answer; + } + + + + void CardinalityCounter::addElement(uint64_t hash){ + uint64_t index = hash % m; + hash = hash-index; + + if(buckets[index] == 0) + V--; + uint8_t temp = rank(hash); + if(temp > buckets[index]){ + buckets[index] = temp; + } + } + + double CardinalityCounter::size(){ + double answer = 0; + for(int i = 0; i < m; i++){ + answer += pow(2, -(int)buckets[i]); + } + answer = 1/answer; + answer = alpha_m*m*m*answer; + + if(answer <= 5*(double)(m/2)){ + return m*log((double) m/V); + } + else if(answer <= pow(2,64)/30){ + return answer; + } + else{ + return -pow(2,64)*log(1-answer/pow(2,64)); + } + } + + void CardinalityCounter::merge(CardinalityCounter* c){ + uint8_t* temp = (*c).getBuckets(); + V = 0; + for(int i = 0; i < m; i++){ + if(temp[i] > buckets[i]){ + buckets[i] = temp[i]; + } + if(buckets[i] == 0){ + V += 1; + } + } + } + + uint8_t* CardinalityCounter::getBuckets(){ + return buckets; + } + + uint64_t CardinalityCounter::getM(){ + return m; + } diff --git a/src/HyperLogLog.h b/src/HyperLogLog.h new file mode 100644 index 0000000000..3cbe4cfb03 --- /dev/null +++ b/src/HyperLogLog.h @@ -0,0 +1,105 @@ +#include + +/* + * "conf" is how confident the estimate given by the counter is. + * + * In other words, if the cardinality is estimated to be 100 with 2% error margin and conf is + * 0.95, then we are 95% sure that the actual cardinality is between 98 and 102. + */ +#define conf .95 + +class CardinalityCounter { + + private: + /* + * This is the number of buckets that will be stored. The standard error is 1.04/sqrt(m), so the + * actual cardinality will be the estimate +/- 1.04/sqrt(m) with approximately 68% probability. + */ + uint64_t m; + + /* + * These are the actual buckets that are storing an estimate of the cardinality. All these need to + * do is count when the first 1 bit appears in the bitstring and that location is at most 65, so + * not that many bits are needed to store it. + */ + uint8_t* buckets; + + /* + * There are some state constants that need to be kept track of to make the final estimate easier. + * V is the number of values in buckets that are 0 and this is used in the small error correction. + * alpha_m is a multiplicative constant used in the algorithm. + */ + uint64_t V; + double alpha_m; + + /* + * This function will calculate the smallest value of b that will satisfy these the constraints of + * a specified error margin and confidence level. + * + * The exact expression for b is as follows: + * Define x = 2*(log(1.04*k/error)/log(2)). Then b is the ceiling of x + * + * error is the error margin. + * k is the number of standard deviations that we have to go to have a confidence level of conf. + */ + + int optimalB(double error); + + /* + * Computes when the first one appears in the element. It looks at the bitstring from the end though. + * A precondition is that the argument is already divisible by m, so we just ignore the last b bits, + * since m = 2^b and the last b bits will always be 0. + */ + uint8_t rank(uint64_t hash_modified); + + public: + /* + * This will initialize the Cardinality counter.Based on the error_margin, the number of buckets + * that need to be kept will be determined. Based on the max_size, the number of bits that will + * be used from the hash function will be determined. + * + * We need the hash function to return integers that are uniformly distributed from 0 to 2^L-1. + * And if that happens, the maximum cardinality that this counter can handle is approximately 2^L. + * By default, we will assume a value of 64 bits. + */ + + CardinalityCounter(double error_margin); + + /* + * Deletes the class variables. + */ + + ~CardinalityCounter(); + + /* + * This will add an element to the counter. It's responsible for adding an element and updating + * the value of V, if that applies. + */ + void addElement(uint64_t hash); + + /* + * Returns the size estimate of the set. First, it has the "raw" HyperLogLog estimate. And then, we + * check if it's too "large" or "small" because the raw estimate doesn't do well in those cases. + * Thus, we correct for those errors as specified in the paper. + */ + + double size(); + + /* + * Returns the buckets array that holds all of the rough cardinality estimates. + */ + + uint8_t* getBuckets(); + + /* + * Merges the argument cardinality counter with this one. The error margins are assumed to be the same, + * so they have the same number of buckets. If any of the conditions are violated, then the return value + * of size() is meaningless. + */ + void merge(CardinalityCounter* c); + + /* + * Returns the value of m. Should be used only for statistical purposes. + */ + uint64_t getM(); +}; diff --git a/src/bro.bif b/src/bro.bif index 6e41aaad99..49446a1e83 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5900,14 +5900,15 @@ function hll_cardinality_add%(elem: any, index: any%): bool %{ BroString* s = convert_index_to_string(index); int status = 0; - + uint64_t a = 1230123; + CompositeHash* hll_hash = new CompositeHash(new TypeList(elem->Type())); HashKey* key; if(hll_counters.count(*s) > 0) { CardinalityCounter* h = hll_counters[*s]; key = hll_hash->ComputeHash(elem,1); - (*h).addElement(key->Hash()); + h->addElement(a); status = 1; } From a41efd495de3f54457c80436ea3dd409a717abcd Mon Sep 17 00:00:00 2001 From: Soumya Basu Date: Mon, 13 Aug 2012 16:33:27 -0700 Subject: [PATCH 004/881] Still segfaults. No real updates. --- src/bro.bif | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bro.bif b/src/bro.bif index 49446a1e83..4c07053981 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5900,18 +5900,20 @@ function hll_cardinality_add%(elem: any, index: any%): bool %{ BroString* s = convert_index_to_string(index); int status = 0; - uint64_t a = 1230123; + uint64_t a = 123456; CompositeHash* hll_hash = new CompositeHash(new TypeList(elem->Type())); - HashKey* key; if(hll_counters.count(*s) > 0) { CardinalityCounter* h = hll_counters[*s]; - key = hll_hash->ComputeHash(elem,1); + HashKey* key = hll_hash->ComputeHash(elem,1); + a = (key->Hash()); h->addElement(a); status = 1; + delete key; } + delete hll_hash; delete s; return new Val(status, TYPE_BOOL); %} From ae4066dcf8dce6fab8957408595b1ddba9982c38 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 14 Aug 2012 17:16:53 -0700 Subject: [PATCH 005/881] Fixing problem with type list. --- src/bro.bif | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bro.bif b/src/bro.bif index 4c07053981..42191d3b22 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5902,11 +5902,15 @@ function hll_cardinality_add%(elem: any, index: any%): bool int status = 0; uint64_t a = 123456; - CompositeHash* hll_hash = new CompositeHash(new TypeList(elem->Type())); - if(hll_counters.count(*s) > 0) + TypeList* tl = new TypeList(elem->Type()); + tl->Append(elem->Type()); + CompositeHash* hll_hash = new CompositeHash(tl); + Unref(tl); + + if( hll_counters.count(*s) > 0 ) { CardinalityCounter* h = hll_counters[*s]; - HashKey* key = hll_hash->ComputeHash(elem,1); + HashKey* key = hll_hash->ComputeHash(elem, 1); a = (key->Hash()); h->addElement(a); status = 1; From 7e07ce3cb12ed6454d8d6b0320150849997c7470 Mon Sep 17 00:00:00 2001 From: Soumya Basu Date: Mon, 20 Aug 2012 21:57:13 -0700 Subject: [PATCH 006/881] Basic functionality works. Merging two counters, cloning two counters and iterating over all of the counters still needs work. --- mytests.bro | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/bro.bif | 31 +++++---- 2 files changed, 201 insertions(+), 15 deletions(-) diff --git a/mytests.bro b/mytests.bro index 3e5af497f3..4de6f29dab 100644 --- a/mytests.bro +++ b/mytests.bro @@ -3,7 +3,12 @@ event bro_init() local m1 = "measurement1"; local m2 = "measurement2"; - hll_cardinality_init(0.01, m1); + print "This value should be true:"; + print hll_cardinality_init(0.01, m1); + hll_cardinality_init(0.01, m2); + + print "This value should be false:"; + print hll_cardinality_init(0.02, "measurement1"); local add1 = "hey"; local add2 = "hi"; @@ -21,9 +26,181 @@ event bro_init() hll_cardinality_add("g", m1); hll_cardinality_add("h", m1); hll_cardinality_add("i", m1); - hll_cardinality_add("j", m1); - local e = hll_cardinality_estimate(m1); - print e; + print "This value should be true:"; + print hll_cardinality_add("j", m1); + print "This value should be false:"; + print hll_cardinality_add("asdf", "something"); + + + hll_cardinality_add(add1, m2); + hll_cardinality_add(add2, m2); + hll_cardinality_add(add3, m2); + hll_cardinality_add(1, m2); + hll_cardinality_add("b", m2); + hll_cardinality_add(2, m2); + hll_cardinality_add(3, m2); + hll_cardinality_add(4, m2); + hll_cardinality_add(5, m2); + hll_cardinality_add(6, m2); + hll_cardinality_add(7, m2); + hll_cardinality_add(8, m2); + + print "This value should be around 13:"; + print hll_cardinality_estimate("measurement1"); + + print "This value should be -1.0:"; + print hll_cardinality_estimate("m2"); + + hll_cardinality_init(0.02, "m2"); + + print "This value should be around 0:"; + print hll_cardinality_estimate("m2"); + + print "This value should be true:"; + print hll_cardinality_destroy("m2"); + + print "This value should be false:"; + print hll_cardinality_destroy("m2"); + + print "This value should be -1.0:"; + print hll_cardinality_estimate("m2"); + + print "This next thing should be false:"; + print hll_cardinality_clone("m3", "m2"); + + print "This next thing should be true:"; + print hll_cardinality_clone("measurement3", "measurement1"); + + print "This value should be around 13:"; + print hll_cardinality_estimate("measurement3"); + + hll_cardinality_destroy("measurement3"); + + print "This next thing should be equal to -1.0:"; + print hll_cardinality_estimate("measurement3"); + + print "This value should be around 13:"; + print hll_cardinality_estimate("measurement1"); } + +### The data structure at index1 will contain the combined count for the +## elements measured by index1 and index2. +## It returns true if it either cloned the value at index2 into index1 +## or if it merged the two data structures together. + +#function hll_cardinality_merge_into%(index1: any, index2: any%): bool +# %{ +# BroString* s1 = convert_index_to_string(index1); +# BroString* s2 = convert_index_to_string(index2); +# int status = 0; +# +# if(hll_counters.count(*s1) < 1) +# { +# if(hll_counters.count(*s2) < 1) +# { +# status = 0; +# } +# else +# { +# uint64_t m = (*hll_counters[*s2]).getM(); +# double error = 1.04/sqrt(m); +# CardinalityCounter* newInst = new CardinalityCounter(error); +# int i = 0; +# while((*newInst).getM() != m) +# { +# i += 1; +# newInst = new CardinalityCounter(error/i); +# } +# hll_counters[*s1] = newInst; +# (*newInst).merge(hll_counters[*s2]); +# status = 1; +# } +# } +# else +# { +# if(hll_counters.count(*s2) < 1) +# { +# status = 0; +# } +# else +# { +# if((*hll_counters[*s2]).getM() == (*hll_counters[*s1]).getM()) +# { +# status = 1; +## (*hll_counters[*s1]).merge(hll_counters[*s2]); +## } +# } +# } +# +# delete s1; +# delete s2; +# return new Val(status, TYPE_BOOL); +# +# %} + +##I'm really not sure about the notation of this function... +# +#function hll_cardinality_keys%(%): bool +# %{ +#// TableVal* a = new TableVal(string_set); +#// map::iterator it; +# +#// for(it = hll_counters.begin() ; it != hll_counters.end(); it++) +#// { +#// a->Assign((*it).first); +#// } +#// return a; +# return new Val(1, TYPE_BOOL); +# %} + +## Stores the data structure at index2 into index1. Deletes the data structure at index1 +## if there was any. Returns True if the data structure at index1 was changed in any way. + +#function hll_cardinality_clone%(index1: any, index2: any%): bool +# %{ +# BroString* s1 = convert_index_to_string(index1); +# BroString* s2 = convert_index_to_string(index2); +# int status = 0; +# +# if(hll_counters.count(*s2) < 1) +# { +# if(hll_counters.count(*s1) < 1) +## { +# status = 0; +# } +# else +# { +# delete hll_counters[*s1]; +# status = 1; +# } +# } +# else +# { +# uint64_t m = (*hll_counters[*s2]).getM(); +# double error = 1.04/sqrt(m); +# CardinalityCounter* newInst = new CardinalityCounter(error); +# int i = 0; +# while((*newInst).getM() != m) +# { +# i += 1; +# newInst = new CardinalityCounter(error/i); +# } +# (*newInst).merge(hll_counters[*s2]); +# if(hll_counters.count(*s1) < 1) +# { +# #hll_counters[*s1] = newInst; +# } +# else +# { +# delete hll_counters[*s1]; +# hll_counters[*s1] = newInst; +# } +# status = 1; +# } +# delete s1; +# delete s2; +# return new Val(status, TYPE_BOOL); +# %}} + diff --git a/src/bro.bif b/src/bro.bif index 42191d3b22..e8fbbfc169 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5911,7 +5911,7 @@ function hll_cardinality_add%(elem: any, index: any%): bool { CardinalityCounter* h = hll_counters[*s]; HashKey* key = hll_hash->ComputeHash(elem, 1); - a = (key->Hash()); + a = key->Hash(); h->addElement(a); status = 1; delete key; @@ -5949,6 +5949,10 @@ function hll_cardinality_merge_into%(index1: any, index2: any%): bool { i += 1; newInst = new CardinalityCounter(error/i); + if(i >= 5) + { + break; + } } hll_counters[*s1] = newInst; (*newInst).merge(hll_counters[*s2]); @@ -5985,7 +5989,8 @@ function hll_cardinality_destroy%(index: any%): bool if(hll_counters.count(*s) > 0) { - delete hll_counters[*s]; + hll_counters.erase(*s); + status = 1; } delete s; @@ -6009,17 +6014,17 @@ function hll_cardinality_estimate%(index: any%): double ##I'm really not sure about the notation of this function... -function hll_cardinality_keys%(%): bool +function hll_cardinality_keys%(%): string_set %{ -// TableVal* a = new TableVal(string_set); -// map::iterator it; + TableVal* a = new TableVal(string_set); + map::iterator it; + int i = 0; -// for(it = hll_counters.begin() ; it != hll_counters.end(); it++) -// { -// a->Assign((*it).first); -// } -// return a; - return new Val(1, TYPE_BOOL); + for(it = hll_counters.begin() ; it != hll_counters.end(); it++) + { + a->Assign(new Val(i++, TYPE_INT),new Val(&(*it).first, TYPE_STRING)); + } + return a; %} ## Stores the data structure at index2 into index1. Deletes the data structure at index1 @@ -6053,6 +6058,10 @@ function hll_cardinality_clone%(index1: any, index2: any%): bool { i += 1; newInst = new CardinalityCounter(error/i); + if(i >=5 ) + { + break; + } } (*newInst).merge(hll_counters[*s2]); if(hll_counters.count(*s1) < 1) From 3ffb4cab64d7940001761be738ed83238151f47a Mon Sep 17 00:00:00 2001 From: Soumya Basu Date: Thu, 30 Aug 2012 01:09:44 -0700 Subject: [PATCH 007/881] Everything works, and I just need to put the tests in the proper folder to get this functionality working. --- mytests.bro | 144 ++++++++++++--------------------------------- src/HyperLogLog.cc | 22 ++++++- src/HyperLogLog.h | 6 ++ src/bro.bif | 34 +++-------- 4 files changed, 70 insertions(+), 136 deletions(-) diff --git a/mytests.bro b/mytests.bro index 4de6f29dab..9392b205b0 100644 --- a/mytests.bro +++ b/mytests.bro @@ -83,65 +83,44 @@ event bro_init() print "This value should be around 13:"; print hll_cardinality_estimate("measurement1"); + + print "This value should be true:"; + print hll_cardinality_merge_into("measurement3", "measurement2"); + + print "This value should be false:"; + print hll_cardinality_merge_into("measurement4", "measurement6"); + + print "This value should be about 12:"; + print hll_cardinality_estimate("measurement3"); + + print "This value should be false:"; + print hll_cardinality_merge_into("measurement3", "measurement15"); + + print "This value should be about 12:"; + print hll_cardinality_estimate("measurement3"); + + print "This value should be true:"; + print hll_cardinality_merge_into("measurement2", "measurement1"); + + print "This value should be about 21:"; + print hll_cardinality_estimate("measurement2"); + + print "This value should be about 13:"; + print hll_cardinality_estimate("measurement1"); + + print "This value should be about 12:"; + print hll_cardinality_estimate("measurement3"); + + local keys = hll_cardinality_keys(); + for(key in keys) + { + print "The key is:"; + print key; + print "The value is:"; + print hll_cardinality_estimate(key); + } } -### The data structure at index1 will contain the combined count for the -## elements measured by index1 and index2. -## It returns true if it either cloned the value at index2 into index1 -## or if it merged the two data structures together. - -#function hll_cardinality_merge_into%(index1: any, index2: any%): bool -# %{ -# BroString* s1 = convert_index_to_string(index1); -# BroString* s2 = convert_index_to_string(index2); -# int status = 0; -# -# if(hll_counters.count(*s1) < 1) -# { -# if(hll_counters.count(*s2) < 1) -# { -# status = 0; -# } -# else -# { -# uint64_t m = (*hll_counters[*s2]).getM(); -# double error = 1.04/sqrt(m); -# CardinalityCounter* newInst = new CardinalityCounter(error); -# int i = 0; -# while((*newInst).getM() != m) -# { -# i += 1; -# newInst = new CardinalityCounter(error/i); -# } -# hll_counters[*s1] = newInst; -# (*newInst).merge(hll_counters[*s2]); -# status = 1; -# } -# } -# else -# { -# if(hll_counters.count(*s2) < 1) -# { -# status = 0; -# } -# else -# { -# if((*hll_counters[*s2]).getM() == (*hll_counters[*s1]).getM()) -# { -# status = 1; -## (*hll_counters[*s1]).merge(hll_counters[*s2]); -## } -# } -# } -# -# delete s1; -# delete s2; -# return new Val(status, TYPE_BOOL); -# -# %} - -##I'm really not sure about the notation of this function... -# #function hll_cardinality_keys%(%): bool # %{ #// TableVal* a = new TableVal(string_set); @@ -153,54 +132,3 @@ event bro_init() #// } #// return a; # return new Val(1, TYPE_BOOL); -# %} - -## Stores the data structure at index2 into index1. Deletes the data structure at index1 -## if there was any. Returns True if the data structure at index1 was changed in any way. - -#function hll_cardinality_clone%(index1: any, index2: any%): bool -# %{ -# BroString* s1 = convert_index_to_string(index1); -# BroString* s2 = convert_index_to_string(index2); -# int status = 0; -# -# if(hll_counters.count(*s2) < 1) -# { -# if(hll_counters.count(*s1) < 1) -## { -# status = 0; -# } -# else -# { -# delete hll_counters[*s1]; -# status = 1; -# } -# } -# else -# { -# uint64_t m = (*hll_counters[*s2]).getM(); -# double error = 1.04/sqrt(m); -# CardinalityCounter* newInst = new CardinalityCounter(error); -# int i = 0; -# while((*newInst).getM() != m) -# { -# i += 1; -# newInst = new CardinalityCounter(error/i); -# } -# (*newInst).merge(hll_counters[*s2]); -# if(hll_counters.count(*s1) < 1) -# { -# #hll_counters[*s1] = newInst; -# } -# else -# { -# delete hll_counters[*s1]; -# hll_counters[*s1] = newInst; -# } -# status = 1; -# } -# delete s1; -# delete s2; -# return new Val(status, TYPE_BOOL); -# %}} - diff --git a/src/HyperLogLog.cc b/src/HyperLogLog.cc index 22f522d1ab..22a06ee6c7 100644 --- a/src/HyperLogLog.cc +++ b/src/HyperLogLog.cc @@ -18,12 +18,32 @@ using namespace std; return answer; } + CardinalityCounter :: CardinalityCounter(uint64_t size){ + m = size; + buckets = new uint8_t[m]; + + if(m == 16) + alpha_m = 0.673; + else if(m == 32) + alpha_m = 0.697; + else if(m == 64) + alpha_m = 0.709; + else + alpha_m = 0.7213/(1+1.079/m); + + for(uint64_t i = 0; i < m; i++){ + buckets[i] = 0; + } + + V = m; + + } CardinalityCounter :: CardinalityCounter(double error_margin){ int b = optimalB(error_margin); m = (uint64_t) pow(2, b); buckets = new uint8_t[m]; - + if(m == 16) alpha_m = 0.673; else if(m == 32) diff --git a/src/HyperLogLog.h b/src/HyperLogLog.h index 3cbe4cfb03..ba9a46f1bd 100644 --- a/src/HyperLogLog.h +++ b/src/HyperLogLog.h @@ -53,6 +53,12 @@ class CardinalityCounter { uint8_t rank(uint64_t hash_modified); public: + /* + * This will be used when cloning. The error margin will be 1.04/sqrt(m) with approximately 68% + * probability. + */ + CardinalityCounter(uint64_t size); + /* * This will initialize the Cardinality counter.Based on the error_margin, the number of buckets * that need to be kept will be determined. Based on the max_size, the number of bits that will diff --git a/src/bro.bif b/src/bro.bif index e8fbbfc169..e75acfa653 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5942,18 +5942,7 @@ function hll_cardinality_merge_into%(index1: any, index2: any%): bool else { uint64_t m = (*hll_counters[*s2]).getM(); - double error = 1.04/sqrt(m); - CardinalityCounter* newInst = new CardinalityCounter(error); - int i = 0; - while((*newInst).getM() != m) - { - i += 1; - newInst = new CardinalityCounter(error/i); - if(i >= 5) - { - break; - } - } + CardinalityCounter* newInst = new CardinalityCounter(m); hll_counters[*s1] = newInst; (*newInst).merge(hll_counters[*s2]); status = 1; @@ -6022,7 +6011,8 @@ function hll_cardinality_keys%(%): string_set for(it = hll_counters.begin() ; it != hll_counters.end(); it++) { - a->Assign(new Val(i++, TYPE_INT),new Val(&(*it).first, TYPE_STRING)); + BroString* s = (BroString*) &(it->first); + a->Assign(new StringVal(s), 0); } return a; %} @@ -6050,20 +6040,10 @@ function hll_cardinality_clone%(index1: any, index2: any%): bool } else { - uint64_t m = (*hll_counters[*s2]).getM(); - double error = 1.04/sqrt(m); - CardinalityCounter* newInst = new CardinalityCounter(error); - int i = 0; - while((*newInst).getM() != m) - { - i += 1; - newInst = new CardinalityCounter(error/i); - if(i >=5 ) - { - break; - } - } - (*newInst).merge(hll_counters[*s2]); + uint64_t m = (*hll_counters[*s2]).getM(); + CardinalityCounter* newInst = new CardinalityCounter(m); + int i = 0; + (*newInst).merge(hll_counters[*s2]); if(hll_counters.count(*s1) < 1) { hll_counters[*s1] = newInst; From 5f5bc53b858848dba80d2b231910ec4e90197581 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 24 Oct 2012 11:13:02 -0700 Subject: [PATCH 008/881] New branch for documentation, with an initial skeleton. --- doc.old/INSTALL.rst | 1 + {doc => doc.old}/cluster.rst | 0 {doc => doc.old}/components/binpac/README.rst | 0 .../components/bro-aux/README.rst | 0 .../components/broccoli-python/README.rst | 0 .../components/broccoli-ruby/README.rst | 0 .../components/broccoli/README.rst | 0 .../components/broccoli/broccoli-manual.rst | 0 {doc => doc.old}/components/broctl/README.rst | 0 {doc => doc.old}/components/btest/README.rst | 0 .../components/capstats/README.rst | 0 .../components/pysubnettree/README.rst | 0 .../components/trace-summary/README.rst | 0 {doc => doc.old}/faq.rst | 0 {doc => doc.old}/geoip.rst | 0 doc.old/index.rst | 90 +++++++++++++++++++ {doc => doc.old}/input.rst | 0 {doc => doc.old}/logging-dataseries.rst | 0 {doc => doc.old}/logging-elasticsearch.rst | 0 {doc => doc.old}/logging.rst | 0 {doc => doc.old}/notice.rst | 0 {doc => doc.old}/quickstart.rst | 0 {doc => doc.old}/reporting-problems.rst | 0 {doc => doc.old}/signatures.rst | 0 {doc => doc.old}/upgrade.rst | 0 doc/INSTALL.rst | 1 - doc/LICENSE | 5 ++ doc/conf.py.in | 19 +++- doc/index.rst | 89 +++--------------- doc/reference/events.rst | 5 ++ doc/reference/frameworks.rst | 5 ++ doc/reference/index.rst | 13 +++ doc/reference/language.rst | 7 ++ doc/reference/subsystems.rst | 4 + doc/user-manual/index.rst | 12 +++ doc/user-manual/intro.rst | 4 + doc/user-manual/starting.rst | 4 + .../doc.sphinx.test/btest-doc.sphinx.test.rst | 13 +++ testing/btest/btest.cfg | 3 +- testing/btest/doc/sphinx/test.btest | 3 + 40 files changed, 199 insertions(+), 79 deletions(-) create mode 120000 doc.old/INSTALL.rst rename {doc => doc.old}/cluster.rst (100%) rename {doc => doc.old}/components/binpac/README.rst (100%) rename {doc => doc.old}/components/bro-aux/README.rst (100%) rename {doc => doc.old}/components/broccoli-python/README.rst (100%) rename {doc => doc.old}/components/broccoli-ruby/README.rst (100%) rename {doc => doc.old}/components/broccoli/README.rst (100%) rename {doc => doc.old}/components/broccoli/broccoli-manual.rst (100%) rename {doc => doc.old}/components/broctl/README.rst (100%) rename {doc => doc.old}/components/btest/README.rst (100%) rename {doc => doc.old}/components/capstats/README.rst (100%) rename {doc => doc.old}/components/pysubnettree/README.rst (100%) rename {doc => doc.old}/components/trace-summary/README.rst (100%) rename {doc => doc.old}/faq.rst (100%) rename {doc => doc.old}/geoip.rst (100%) create mode 100644 doc.old/index.rst rename {doc => doc.old}/input.rst (100%) rename {doc => doc.old}/logging-dataseries.rst (100%) rename {doc => doc.old}/logging-elasticsearch.rst (100%) rename {doc => doc.old}/logging.rst (100%) rename {doc => doc.old}/notice.rst (100%) rename {doc => doc.old}/quickstart.rst (100%) rename {doc => doc.old}/reporting-problems.rst (100%) rename {doc => doc.old}/signatures.rst (100%) rename {doc => doc.old}/upgrade.rst (100%) delete mode 120000 doc/INSTALL.rst create mode 100644 doc/LICENSE create mode 100644 doc/reference/events.rst create mode 100644 doc/reference/frameworks.rst create mode 100644 doc/reference/index.rst create mode 100644 doc/reference/language.rst create mode 100644 doc/reference/subsystems.rst create mode 100644 doc/user-manual/index.rst create mode 100644 doc/user-manual/intro.rst create mode 100644 doc/user-manual/starting.rst create mode 100644 testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst create mode 100644 testing/btest/doc/sphinx/test.btest diff --git a/doc.old/INSTALL.rst b/doc.old/INSTALL.rst new file mode 120000 index 0000000000..37675c714b --- /dev/null +++ b/doc.old/INSTALL.rst @@ -0,0 +1 @@ +../../INSTALL \ No newline at end of file diff --git a/doc/cluster.rst b/doc.old/cluster.rst similarity index 100% rename from doc/cluster.rst rename to doc.old/cluster.rst diff --git a/doc/components/binpac/README.rst b/doc.old/components/binpac/README.rst similarity index 100% rename from doc/components/binpac/README.rst rename to doc.old/components/binpac/README.rst diff --git a/doc/components/bro-aux/README.rst b/doc.old/components/bro-aux/README.rst similarity index 100% rename from doc/components/bro-aux/README.rst rename to doc.old/components/bro-aux/README.rst diff --git a/doc/components/broccoli-python/README.rst b/doc.old/components/broccoli-python/README.rst similarity index 100% rename from doc/components/broccoli-python/README.rst rename to doc.old/components/broccoli-python/README.rst diff --git a/doc/components/broccoli-ruby/README.rst b/doc.old/components/broccoli-ruby/README.rst similarity index 100% rename from doc/components/broccoli-ruby/README.rst rename to doc.old/components/broccoli-ruby/README.rst diff --git a/doc/components/broccoli/README.rst b/doc.old/components/broccoli/README.rst similarity index 100% rename from doc/components/broccoli/README.rst rename to doc.old/components/broccoli/README.rst diff --git a/doc/components/broccoli/broccoli-manual.rst b/doc.old/components/broccoli/broccoli-manual.rst similarity index 100% rename from doc/components/broccoli/broccoli-manual.rst rename to doc.old/components/broccoli/broccoli-manual.rst diff --git a/doc/components/broctl/README.rst b/doc.old/components/broctl/README.rst similarity index 100% rename from doc/components/broctl/README.rst rename to doc.old/components/broctl/README.rst diff --git a/doc/components/btest/README.rst b/doc.old/components/btest/README.rst similarity index 100% rename from doc/components/btest/README.rst rename to doc.old/components/btest/README.rst diff --git a/doc/components/capstats/README.rst b/doc.old/components/capstats/README.rst similarity index 100% rename from doc/components/capstats/README.rst rename to doc.old/components/capstats/README.rst diff --git a/doc/components/pysubnettree/README.rst b/doc.old/components/pysubnettree/README.rst similarity index 100% rename from doc/components/pysubnettree/README.rst rename to doc.old/components/pysubnettree/README.rst diff --git a/doc/components/trace-summary/README.rst b/doc.old/components/trace-summary/README.rst similarity index 100% rename from doc/components/trace-summary/README.rst rename to doc.old/components/trace-summary/README.rst diff --git a/doc/faq.rst b/doc.old/faq.rst similarity index 100% rename from doc/faq.rst rename to doc.old/faq.rst diff --git a/doc/geoip.rst b/doc.old/geoip.rst similarity index 100% rename from doc/geoip.rst rename to doc.old/geoip.rst diff --git a/doc.old/index.rst b/doc.old/index.rst new file mode 100644 index 0000000000..ed14be1dd2 --- /dev/null +++ b/doc.old/index.rst @@ -0,0 +1,90 @@ +.. Bro documentation master file + +================= +Bro Documentation +================= + +Guides +------ + +.. toctree:: + :maxdepth: 1 + + INSTALL + quickstart + upgrade + faq + reporting-problems + +Frameworks +---------- + +.. toctree:: + :maxdepth: 1 + + notice + logging + input + cluster + signatures + +How-Tos +------- + +.. toctree:: + :maxdepth: 1 + + geoip + +Script Reference +---------------- + +.. toctree:: + :maxdepth: 1 + + scripts/packages + scripts/index + scripts/builtins + scripts/bifs + +Other Bro Components +-------------------- + +The following are snapshots of documentation for components that come +with this version of Bro (|version|). Since they can also be used +independently, see the `download page +`_ for documentation of any +current, independent component releases. + +.. toctree:: + :maxdepth: 1 + + BinPAC - A protocol parser generator + Broccoli - The Bro Client Communication Library (README) + Broccoli - User Manual + Broccoli Python Bindings + Broccoli Ruby Bindings + BroControl - Interactive Bro management shell + Bro-Aux - Small auxiliary tools for Bro + BTest - A unit testing framework + Capstats - Command-line packet statistic tool + PySubnetTree - Python module for CIDR lookups + trace-summary - Script for generating break-downs of network traffic + +The `Broccoli API Reference `_ may also be of +interest. + +Other Indices and References +---------------------------- + +* :ref:`General Index ` +* `Notice Index `_ +* :ref:`search` + +Internal References +------------------- + +.. toctree:: + :maxdepth: 1 + + scripts/internal diff --git a/doc/input.rst b/doc.old/input.rst similarity index 100% rename from doc/input.rst rename to doc.old/input.rst diff --git a/doc/logging-dataseries.rst b/doc.old/logging-dataseries.rst similarity index 100% rename from doc/logging-dataseries.rst rename to doc.old/logging-dataseries.rst diff --git a/doc/logging-elasticsearch.rst b/doc.old/logging-elasticsearch.rst similarity index 100% rename from doc/logging-elasticsearch.rst rename to doc.old/logging-elasticsearch.rst diff --git a/doc/logging.rst b/doc.old/logging.rst similarity index 100% rename from doc/logging.rst rename to doc.old/logging.rst diff --git a/doc/notice.rst b/doc.old/notice.rst similarity index 100% rename from doc/notice.rst rename to doc.old/notice.rst diff --git a/doc/quickstart.rst b/doc.old/quickstart.rst similarity index 100% rename from doc/quickstart.rst rename to doc.old/quickstart.rst diff --git a/doc/reporting-problems.rst b/doc.old/reporting-problems.rst similarity index 100% rename from doc/reporting-problems.rst rename to doc.old/reporting-problems.rst diff --git a/doc/signatures.rst b/doc.old/signatures.rst similarity index 100% rename from doc/signatures.rst rename to doc.old/signatures.rst diff --git a/doc/upgrade.rst b/doc.old/upgrade.rst similarity index 100% rename from doc/upgrade.rst rename to doc.old/upgrade.rst diff --git a/doc/INSTALL.rst b/doc/INSTALL.rst deleted file mode 120000 index 99d491b4f8..0000000000 --- a/doc/INSTALL.rst +++ /dev/null @@ -1 +0,0 @@ -../INSTALL \ No newline at end of file diff --git a/doc/LICENSE b/doc/LICENSE new file mode 100644 index 0000000000..88a76c9ec7 --- /dev/null +++ b/doc/LICENSE @@ -0,0 +1,5 @@ +This work is licensed under the Creative Commons +Attribution-NonCommercial 3.0 Unported License. To view a copy of this +license, visit http://creativecommons.org/licenses/by-nc/3.0/ or send +a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain +View, California, 94041, USA. diff --git a/doc/conf.py.in b/doc/conf.py.in index 2e93e82502..e91b48d079 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -12,11 +12,28 @@ import sys, os +extensions = [] + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('sphinx-sources/ext')) +# ----- Begin of BTest configuration. ----- +btest = os.path.abspath("@CMAKE_SOURCE_DIR@/aux/btest") +brocut = os.path.abspath("@CMAKE_SOURCE_DIR@/aux/bro-aux/bro-cut") +bro = os.path.abspath("@CMAKE_SOURCE_DIR@/build/src") + +os.environ["PATH"] += (":%s:%s/sphinx:%s:%s" % (btest, btest, bro, brocut)) +sys.path.append(os.path.join(btest, "sphinx")) + +extensions += ["btest-sphinx"] + +btest_base="@CMAKE_SOURCE_DIR@/testing/btest" +btest_tests="doc/sphinx" +# ----- End of BTest configuration. ----- + + # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -24,7 +41,7 @@ sys.path.insert(0, os.path.abspath('sphinx-sources/ext')) # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc'] +extensions += ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static'] diff --git a/doc/index.rst b/doc/index.rst index ed14be1dd2..36a38ac0a8 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,90 +1,27 @@ + .. Bro documentation master file ================= Bro Documentation ================= -Guides ------- - .. toctree:: - :maxdepth: 1 + :maxdepth: 2 + :numbered: - INSTALL - quickstart - upgrade - faq - reporting-problems + user-manual/index + reference/index -Frameworks ----------- +Just Testing +============ -.. toctree:: - :maxdepth: 1 +.. code:: bro - notice - logging - input - cluster - signatures + print "Hey Bro!" -How-Tos -------- +.. btest:: test -.. toctree:: - :maxdepth: 1 + @TEST-COPY-FILE: ${TRACES}/wikipedia.trace + @TEST-EXEC: btest-rst-cmd bro -r wikipedia.trace + @TEST-EXEC: btest-rst-cmd "cat http.log | bro-cut ts id.orig_h | head -5" - geoip - -Script Reference ----------------- - -.. toctree:: - :maxdepth: 1 - - scripts/packages - scripts/index - scripts/builtins - scripts/bifs - -Other Bro Components --------------------- - -The following are snapshots of documentation for components that come -with this version of Bro (|version|). Since they can also be used -independently, see the `download page -`_ for documentation of any -current, independent component releases. - -.. toctree:: - :maxdepth: 1 - - BinPAC - A protocol parser generator - Broccoli - The Bro Client Communication Library (README) - Broccoli - User Manual - Broccoli Python Bindings - Broccoli Ruby Bindings - BroControl - Interactive Bro management shell - Bro-Aux - Small auxiliary tools for Bro - BTest - A unit testing framework - Capstats - Command-line packet statistic tool - PySubnetTree - Python module for CIDR lookups - trace-summary - Script for generating break-downs of network traffic - -The `Broccoli API Reference `_ may also be of -interest. - -Other Indices and References ----------------------------- - -* :ref:`General Index ` -* `Notice Index `_ -* :ref:`search` - -Internal References -------------------- - -.. toctree:: - :maxdepth: 1 - - scripts/internal diff --git a/doc/reference/events.rst b/doc/reference/events.rst new file mode 100644 index 0000000000..bcb3adae42 --- /dev/null +++ b/doc/reference/events.rst @@ -0,0 +1,5 @@ + +================ +Events (Missing) +================ + diff --git a/doc/reference/frameworks.rst b/doc/reference/frameworks.rst new file mode 100644 index 0000000000..20824b03bc --- /dev/null +++ b/doc/reference/frameworks.rst @@ -0,0 +1,5 @@ + +==================== +Frameworks (Missing) +==================== + diff --git a/doc/reference/index.rst b/doc/reference/index.rst new file mode 100644 index 0000000000..cba512cd1c --- /dev/null +++ b/doc/reference/index.rst @@ -0,0 +1,13 @@ + +========= +Reference +========= + +.. toctree:: + :maxdepth: 2 + :numbered: + + frameworks.rst + events.rst + language.rst + subsystems.rst diff --git a/doc/reference/language.rst b/doc/reference/language.rst new file mode 100644 index 0000000000..dd50997672 --- /dev/null +++ b/doc/reference/language.rst @@ -0,0 +1,7 @@ + +================== +Language (Missing) +================== + + + diff --git a/doc/reference/subsystems.rst b/doc/reference/subsystems.rst new file mode 100644 index 0000000000..9caafba8b3 --- /dev/null +++ b/doc/reference/subsystems.rst @@ -0,0 +1,4 @@ + +==================== +Subsystems (Missing) +==================== diff --git a/doc/user-manual/index.rst b/doc/user-manual/index.rst new file mode 100644 index 0000000000..971d3e386b --- /dev/null +++ b/doc/user-manual/index.rst @@ -0,0 +1,12 @@ + +=========== +User Manual +=========== + +.. toctree:: + :maxdepth: 2 + :numbered: + + intro.rst + starting.rst + diff --git a/doc/user-manual/intro.rst b/doc/user-manual/intro.rst new file mode 100644 index 0000000000..c7a210747d --- /dev/null +++ b/doc/user-manual/intro.rst @@ -0,0 +1,4 @@ + +====================== +Introduction (Missing) +====================== diff --git a/doc/user-manual/starting.rst b/doc/user-manual/starting.rst new file mode 100644 index 0000000000..f25746a533 --- /dev/null +++ b/doc/user-manual/starting.rst @@ -0,0 +1,4 @@ + +========================= +Getting Started (Missing) +========================= diff --git a/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst b/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst new file mode 100644 index 0000000000..6b59bf64a2 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst @@ -0,0 +1,13 @@ +.. code-block:: none + + # bro -r wikipedia.trace + +.. code-block:: none + + # cat http.log | bro-cut ts id.orig_h | head -5 + 1300475168.843894 141.142.220.118 + 1300475168.975800 141.142.220.118 + 1300475168.976327 141.142.220.118 + 1300475168.979160 141.142.220.118 + 1300475169.012666 141.142.220.118 + diff --git a/testing/btest/btest.cfg b/testing/btest/btest.cfg index d86b45d8a9..021121760a 100644 --- a/testing/btest/btest.cfg +++ b/testing/btest/btest.cfg @@ -4,6 +4,7 @@ TmpDir = %(testbase)s/.tmp BaselineDir = %(testbase)s/Baseline IgnoreDirs = .svn CVS .tmp IgnoreFiles = *.tmp *.swp #* *.trace .DS_Store +Finalizer = btest-diff-rst [environment] BROPATH=`bash -c %(testbase)s/../../build/bro-path-dev` @@ -11,7 +12,7 @@ BRO_SEED_FILE=%(testbase)s/random.seed TZ=UTC LC_ALL=C BTEST_PATH=%(testbase)s/../../aux/btest -PATH=%(testbase)s/../../build/src:%(testbase)s/../scripts:%(testbase)s/../../aux/btest:%(default_path)s +PATH=%(testbase)s/../../build/src:%(testbase)s/../scripts:%(testbase)s/../../aux/btest:%(testbase)s/../../aux/btest/sphinx:%(default_path)s TRACES=%(testbase)s/Traces SCRIPTS=%(testbase)s/../scripts DIST=%(testbase)s/../.. diff --git a/testing/btest/doc/sphinx/test.btest b/testing/btest/doc/sphinx/test.btest new file mode 100644 index 0000000000..f2f1bcff53 --- /dev/null +++ b/testing/btest/doc/sphinx/test.btest @@ -0,0 +1,3 @@ +@TEST-COPY-FILE: ${TRACES}/wikipedia.trace +@TEST-EXEC: btest-rst-cmd bro -r wikipedia.trace +@TEST-EXEC: btest-rst-cmd "cat http.log | bro-cut ts id.orig_h | head -5" From 54a0f3a5ae22c0b7cc76b5a74d60da0de42c865f Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 24 Oct 2012 17:04:44 -0500 Subject: [PATCH 009/881] Changed `make doc` target to re-use Sphinx cache. To do this, the document root and autogenerated bro script docs are rsync'd in to Sphinx's working directory instead of a plain recursive copy. There are still some index files that are auto generated on each build and will trigger Sphinx to re-build them since it thinks they changed, but overall the build is much faster this way. One limitation of this is that old files in the Sphinx work dir don't automatically get cleaned up (e.g. if you remove some static documentation from the /doc it will still be in build/doc/sphinx-sources). So a `make docclean` or at least `make broxygenclean` is needed at least in that case. (For now, rsync --delete isn't the right answer since the destination of the autogenerated stuff overlaps with the document root, the separate rsyncs end up clobbering each other.) --- doc/CMakeLists.txt | 12 +++++----- doc/bin/group_index_generator.py | 38 ++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index bdbb0e7b69..427d2b86b6 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -21,13 +21,13 @@ add_subdirectory(scripts) add_custom_target(broxygen # copy the template documentation to the build directory # to give as input for sphinx - COMMAND "${CMAKE_COMMAND}" -E copy_directory - ${DOC_SOURCE_DIR} + COMMAND rsync -r --copy-links --times + ${DOC_SOURCE_DIR}/ ${DOC_SOURCE_WORKDIR} # copy generated policy script documentation into the # working copy of the template documentation - COMMAND "${CMAKE_COMMAND}" -E copy_directory - ${RST_OUTPUT_DIR} + COMMAND rsync -r --copy-links --times + ${RST_OUTPUT_DIR}/ ${DOC_SOURCE_WORKDIR}/scripts # append to the master index of all policy scripts COMMAND cat ${MASTER_POLICY_INDEX} >> @@ -58,7 +58,7 @@ add_custom_target(broxygen # SOURCES just adds stuff to IDE projects as a convenience SOURCES ${DOC_SOURCES}) -# The "sphinxclean" target removes just the Sphinx input/output directories +# The "broxygenclean" target removes just the Sphinx input/output directories # from the build directory. add_custom_target(broxygenclean COMMAND "${CMAKE_COMMAND}" -E remove_directory @@ -67,7 +67,7 @@ add_custom_target(broxygenclean ${DOC_OUTPUT_DIR} VERBATIM) -add_dependencies(broxygen broxygenclean restdoc) +add_dependencies(broxygen restdoc) add_custom_target(doc) add_custom_target(docclean) diff --git a/doc/bin/group_index_generator.py b/doc/bin/group_index_generator.py index 720081e8b5..b41dcb379c 100755 --- a/doc/bin/group_index_generator.py +++ b/doc/bin/group_index_generator.py @@ -8,9 +8,11 @@ # 2nd argument is the directory containing ${group}_files lists of # scripts that belong to the group and ${group}_doc_names lists of # document names that can be supplied to a reST :doc: role -# 3rd argument is a directory in which write a ${group}.rst file (will -# append to existing file) that contains reST style references to -# script docs along with summary text contained in original script +# 3rd argument is a directory in which write a ${group}.rst file that contains +# reST style references to script docs along with summary text contained +# in original script. If ${group} ends with "index", then the file +# is always clobbered by this script, but for other unique group names, +# this script will append to existing files. import sys import os @@ -20,9 +22,28 @@ group_list = sys.argv[1] file_manifest_dir = sys.argv[2] output_dir = sys.argv[3] +def make_group_file_index(dir_name, group_name): + group_file = os.path.join(dir_name, group_name + ".rst") + + if not os.path.exists(group_file): + if not os.path.exists(os.path.dirname(group_file)): + os.makedirs(os.path.dirname(group_file)) + + if group_name.endswith("index"): + with open(group_file, 'w') as f_group_file: + f_group_file.write(":orphan:\n\n") + title = "Package Index: %s\n" % os.path.dirname(group_name) + f_group_file.write(title); + for n in range(len(title)): + f_group_file.write("=") + f_group_file.write("\n"); + + return group_file + with open(group_list, 'r') as f_group_list: for group in f_group_list.read().splitlines(): #print group + group_file = make_group_file_index(output_dir, group) file_manifest = os.path.join(file_manifest_dir, group + "_files") doc_manifest = os.path.join(file_manifest_dir, group + "_doc_names") src_files = [] @@ -44,17 +65,6 @@ with open(group_list, 'r') as f_group_list: if sum_pos != -1: summary_comments.append(line[(sum_pos+3):]) #print summary_comments - group_file = os.path.join(output_dir, group + ".rst") - if not os.path.exists(group_file): - if not os.path.exists(os.path.dirname(group_file)): - os.makedirs(os.path.dirname(group_file)) - with open(group_file, 'w') as f_group_file: - f_group_file.write(":orphan:\n\n") - title = "Package Index: %s\n" % os.path.dirname(group) - f_group_file.write(title); - for n in range(len(title)): - f_group_file.write("=") - f_group_file.write("\n"); with open(group_file, 'a') as f_group_file: f_group_file.write("\n:doc:`/scripts/%s`\n" % doc_names[i]) From bd9df5c5f943b5f3db47c9b2ed1417caf8513a34 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 1 Nov 2012 16:15:57 -0700 Subject: [PATCH 010/881] Moving submodules. --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 44a43e6245..d8537a474f 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 44a43e62452302277f88e8fac08d1f979dc53f98 +Subproject commit d8537a474fbab63ddea3e7137b40f76d994d7957 From 390d945d37d71c1a2b3aa30450bffab25b04d893 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sat, 3 Nov 2012 02:09:55 -0400 Subject: [PATCH 011/881] Initial commit of the scripting user manual. --- doc/user-manual/scripting.rst | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 doc/user-manual/scripting.rst diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst new file mode 100644 index 0000000000..e14382beaf --- /dev/null +++ b/doc/user-manual/scripting.rst @@ -0,0 +1,85 @@ + +========= +Scripting +========= + +.. toctree:: + :maxdepth: 2 + :numbered: + + Understanding Bro Scripts + Event Handlers + Data types + A complete script + Guidelines for writing scripts + +Understanding Bro Scripts +========================= + +Bro includes an event queue driven scripting language that provides the primary means for an organization to extend and customize Bro's functionality. An overwhelming amount of the output generated by Bro is, in fact, generated by bro scripts. It's almost easier to consider Bro to be an entity behind-the-scenes processing connections and generating events while Bro's scripting language is the medium through which we mere mortals can achieve communication. Bro scripts effectively notify Bro that should there be an event of a type we define, then let us have the information about the connection so we can perform some function on it. For example, the ssl.log file is generated by a bro script that walks the entire certificate chain and issues notifications if any of the steps along the cert chain are invalid. This entire process is setup by telling Bro that should it see a server or client issue an SSL HELLO message, we want to know about the information about that connection. + +It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script detect-MHR.bro is responsible for generating the appropriate DNS lookup and parsing the response. + + +.. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro + :language: bro + :linenos: + + +Visually, there are three distinct sections of the script. A base level with no identation followed by an indented and formatted section explaining custom the variables being set (export) and another indented and formatted section describing the instructions for a specific event (event log_http). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. + +.. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro + :language: bro + :linenos: + :lines: 7-11 + +Lines 7 and 8 of the script process the __load__.bro script in the respective directories being loaded. In a full production deployment of Bro it's likely that these files would already be loaded and their contents made available to the script, but including them explicitly ensures that Bro can be run in modes such as "bare" and still have scripts that reliably work. + +.. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro + :language: bro + :linenos: + :lines: 12-18 + +The export section redefines an enumerable constant that describes the type of notice we will generate with the logging framework. The notice type listed allows for the use of the NOTICE() function to generate notices of type Malware_Hash_Registry_Match as done in the next section. + +.. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro + :language: bro + :linenos: + :lines: 20-37 + +The workhorse of the script is contained in the event handler for log_http. The log_http event is defined as an event-hook in the base/protocols/http/main.bro script and allows scripts to handle connection as it is being passed to the logging framework. The event handler is passed an HTTP::Info data structure which will be referred to as "rec" in body of the event handler. + +An if statement is used to check for the existence of a datastructure named "md5" nested within the rec data structure. Bro uses the "$" as a deference operator and as such, and it is employed in this script to check if rec$md5 is present by including the "?" operator within the path. If the rec data structure includes a nested datastructure named "md5", the statement is processed as true and a local variable named "hash_domain" is provisioned and given a format string based on the contents of rec$md5. The script then provisions another local variable named "addrs" and fills it with the output of the lookup_hostname() function which will perform a DNS lookup on the arguments passed to it. + +DNS lookups against the Team Cymru Malware Hash Registry will return a '127.0.0.2' if the hash being queried is found in the hash registry. If the response includes 127.0.0.2, the script proceeds to build two new local variables to be used in the notice and then issues the NOTICE(). + +In approximately 15 lines of actual code, Bro provides an amazing utility that would be incredibly difficult to implement and deploy with other products. In truth, claiming that Bro does this in 15 lines is a misdirection; There is a truly massive number of things going on behind-the-scenes in Bro, but it is the inclusion of the scripting language that gives analysts access to those underlying layers in a succinct and well defined manner. + +Event Handlers +============== + +Bro's scripting language is event driven which is a gear change from the majority of scripting languages with which most users will have previous experience. Scripting in Bro depends on handling the events generated by Bro as it processes network traffic, altering the state of data structures through those events, and making decisions on the information provided. This approach to scripting can often cause confusion to users who come to Bro from a procedural or functional language, but once the initial shock wears off it becomes more clear with each exposure. Gaining familiarity with the specific events generated by Bro is a big step towards building a mindset for working with Bro scripts. + +Most, if not all, of Bro's events are defined in the built-in-function files or .bif files. Whether starting a script from scratch or reading and maintaining someone else's script, having the built-in-function files available is an excellent resource to have on hand. Before release version 2.0 the Bro developers put significant effort into organization and documentation of every event. This effort resulted in built-in-function files organized such that each entry contains a descriptive event name, the arguments passed to the event, and a concise explanation of the functions use. + +.. literalinclude:: ../../build/src/event.bif.bro + :language: bro + :linenos: + :lines: 4124-4149 + +Above is a segment of event.bif.bro showing the documentation for the event dns_request(). It's organized such that the documentation, commentary, and list of arguments preceed the actual event definition used by Bro. As Bro detects DNS requests being issued by an originator, it issues this event and any number of scripts then have access to the data Bro passes along with the event. In this example, Bro passes not only the message, the query, query type and query class for the DNS request, but also a then record used for the connection itself. + +The Connection Record Data Type +=============================== + +A majority of the events in Bro's event.bif.bro file are passed the connection record data type, in effect, making backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. + + + + +Not only are events defined in the built-in-functions in Bro, but as seen in the last section, users can define events as well. + +As events are handled, the script is given a chance to save or alter state. + + + From cd489913f4ce7842c65d14fff5242ac131602e96 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Thu, 8 Nov 2012 09:53:37 -0500 Subject: [PATCH 012/881] Additions, spelling corrections, prior to addition of custom scripts to be used in the User Manual. --- doc/user-manual/scripting.rst | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index e14382beaf..adc8498f89 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -16,17 +16,16 @@ Scripting Understanding Bro Scripts ========================= -Bro includes an event queue driven scripting language that provides the primary means for an organization to extend and customize Bro's functionality. An overwhelming amount of the output generated by Bro is, in fact, generated by bro scripts. It's almost easier to consider Bro to be an entity behind-the-scenes processing connections and generating events while Bro's scripting language is the medium through which we mere mortals can achieve communication. Bro scripts effectively notify Bro that should there be an event of a type we define, then let us have the information about the connection so we can perform some function on it. For example, the ssl.log file is generated by a bro script that walks the entire certificate chain and issues notifications if any of the steps along the cert chain are invalid. This entire process is setup by telling Bro that should it see a server or client issue an SSL HELLO message, we want to know about the information about that connection. +Bro includes an event queue driven scripting language that provides the primary means for an organization to extend and customize Bro's functionality. An overwhelming amount of the output generated by Bro is, in fact, generated by Bro scripts. It's almost easier to consider Bro to be an entity behind-the-scenes processing connections and generating events while Bro's scripting language is the medium through which we mere mortals can achieve communication. Bro scripts effectively notify Bro that should there be an event of a type we define, then let us have the information about the connection so we can perform some function on it. For example, the ssl.log file is generated by a Bro script that walks the entire certificate chain and issues notifications if any of the steps along the certificate chain are invalid. This entire process is setup by telling Bro that should it see a server or client issue an SSL HELLO message, we want to know about the information about that connection. -It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script detect-MHR.bro is responsible for generating the appropriate DNS lookup and parsing the response. +It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru Malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script detect-MHR.bro is responsible for generating the appropriate DNS lookup and parsing the response. .. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: - -Visually, there are three distinct sections of the script. A base level with no identation followed by an indented and formatted section explaining custom the variables being set (export) and another indented and formatted section describing the instructions for a specific event (event log_http). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. +Visually, there are three distinct sections of the script. A base level with no indentation followed by an indented and formatted section explaining custom the variables being set (export) and another indented and formatted section describing the instructions for a specific event (event log_http). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. .. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro :language: bro @@ -49,37 +48,41 @@ The export section redefines an enumerable constant that describes the type of n The workhorse of the script is contained in the event handler for log_http. The log_http event is defined as an event-hook in the base/protocols/http/main.bro script and allows scripts to handle connection as it is being passed to the logging framework. The event handler is passed an HTTP::Info data structure which will be referred to as "rec" in body of the event handler. -An if statement is used to check for the existence of a datastructure named "md5" nested within the rec data structure. Bro uses the "$" as a deference operator and as such, and it is employed in this script to check if rec$md5 is present by including the "?" operator within the path. If the rec data structure includes a nested datastructure named "md5", the statement is processed as true and a local variable named "hash_domain" is provisioned and given a format string based on the contents of rec$md5. The script then provisions another local variable named "addrs" and fills it with the output of the lookup_hostname() function which will perform a DNS lookup on the arguments passed to it. +An if statement is used to check for the existence of a data structure named "md5" nested within the rec data structure. Bro uses the "$" as a deference operator and as such, and it is employed in this script to check if rec$md5 is present by including the "?" operator within the path. If the rec data structure includes a nested data structure named "md5", the statement is processed as true and a local variable named "hash_domain" is provisioned and given a format string based on the contents of rec$md5. The script then provisions another local variable named "addrs" and fills it with the output of the lookup_hostname() function which will perform a DNS lookup on the arguments passed to it. DNS lookups against the Team Cymru Malware Hash Registry will return a '127.0.0.2' if the hash being queried is found in the hash registry. If the response includes 127.0.0.2, the script proceeds to build two new local variables to be used in the notice and then issues the NOTICE(). In approximately 15 lines of actual code, Bro provides an amazing utility that would be incredibly difficult to implement and deploy with other products. In truth, claiming that Bro does this in 15 lines is a misdirection; There is a truly massive number of things going on behind-the-scenes in Bro, but it is the inclusion of the scripting language that gives analysts access to those underlying layers in a succinct and well defined manner. -Event Handlers -============== +The Event Queue and Event Handlers +================================== -Bro's scripting language is event driven which is a gear change from the majority of scripting languages with which most users will have previous experience. Scripting in Bro depends on handling the events generated by Bro as it processes network traffic, altering the state of data structures through those events, and making decisions on the information provided. This approach to scripting can often cause confusion to users who come to Bro from a procedural or functional language, but once the initial shock wears off it becomes more clear with each exposure. Gaining familiarity with the specific events generated by Bro is a big step towards building a mindset for working with Bro scripts. +Bro's scripting language is event driven which is a gear change from the majority of scripting languages with which most users will have previous experience. Scripting in Bro depends on handling the events generated by Bro as it processes network traffic, altering the state of data structures through those events, and making decisions on the information provided. This approach to scripting can often cause confusion to users who come to Bro from a procedural or functional language, but once the initial shock wears off it becomes more clear with each exposure. -Most, if not all, of Bro's events are defined in the built-in-function files or .bif files. Whether starting a script from scratch or reading and maintaining someone else's script, having the built-in-function files available is an excellent resource to have on hand. Before release version 2.0 the Bro developers put significant effort into organization and documentation of every event. This effort resulted in built-in-function files organized such that each entry contains a descriptive event name, the arguments passed to the event, and a concise explanation of the functions use. +Bro's core acts to place events into an ordered "Event Queue", allowing event handlers to process them on a first-come-first-serve basis. In effect, this is Bro's core functionality as without the scripts written to perform discrete actions on events, there would be little to no usable output. As such, a basic understanding of the Event Queue, the Events being generated, and the way in which Event Handlers process those events is a basis for not only learning to write scripts for Bro but for understanding Bro itself. -.. literalinclude:: ../../build/src/event.bif.bro +Gaining familiarity with the specific events generated by Bro is a big step towards building a mind set for working with Bro scripts. The majority of events generated by Bro are defined in the built-in-function files or .bif files which also act as the basis for online event documentation. Whether starting a script from scratch or reading and maintaining someone else's script, having the built-in event definitions available is an excellent resource to have on hand. Before release version 2.0 the Bro developers put significant effort into organization and documentation of every event. This effort resulted in built-in-function files organized such that each entry contains a descriptive event name, the arguments passed to the event, and a concise explanation of the functions use. + +.. literalinclude:: ../../build/src/base/event.bif.bro :language: bro :linenos: :lines: 4124-4149 -Above is a segment of event.bif.bro showing the documentation for the event dns_request(). It's organized such that the documentation, commentary, and list of arguments preceed the actual event definition used by Bro. As Bro detects DNS requests being issued by an originator, it issues this event and any number of scripts then have access to the data Bro passes along with the event. In this example, Bro passes not only the message, the query, query type and query class for the DNS request, but also a then record used for the connection itself. +Above is a segment of event.bif.bro showing the documentation for the event dns_request(). It's organized such that the documentation, commentary, and list of arguments precede the actual event definition used by Bro. As Bro detects DNS requests being issued by an originator, it issues this event and any number of scripts then have access to the data Bro passes along with the event. In this example, Bro passes not only the message, the query, query type and query class for the DNS request, but also a then record used for the connection itself. The Connection Record Data Type =============================== -A majority of the events in Bro's event.bif.bro file are passed the connection record data type, in effect, making backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. +Of all the events defined in Bro's event.bif.bro file, an overwhelmingly large number of them are passed the connection record data type, in effect, making it the backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. Let's walk through the process of selecting an appropriate event, generating some output to standard out and dissecting the connection record so as to get an overview of it. We will cover data types in more detail later. - +While Bro is capable of packet level processing, its strengths lay in the context of a connection between an originator and a responder. As such, there are events defined for the primary parts of the connection life-cycle as you'll see from the small selection of connection-related events below. +.. literalinclude:: ../../build/src/base/event.bif.bro + :language: bro + :linenos: + :lines: 135-138,154,204-208,218,255-256,266,335-340,351 -Not only are events defined in the built-in-functions in Bro, but as seen in the last section, users can define events as well. - -As events are handled, the script is given a chance to save or alter state. +Of the events listed, the event that will give us the best insight into the connection record data type will be connection_state_remove(). As detailed in the in-line documentation, Bro generates this event just before it decides to remove this event from memory, effectively forgetting about it. From a3d010e9d83f9f4ded6d0c5926153f1f72faf90b Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 11 Nov 2012 23:27:14 -0500 Subject: [PATCH 013/881] Rewriting explanation of detect-MHR.bro to match recent changes to lookup_hostname_txt() --- doc/user-manual/scripting.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index adc8498f89..a8ec45e53d 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -18,39 +18,39 @@ Understanding Bro Scripts Bro includes an event queue driven scripting language that provides the primary means for an organization to extend and customize Bro's functionality. An overwhelming amount of the output generated by Bro is, in fact, generated by Bro scripts. It's almost easier to consider Bro to be an entity behind-the-scenes processing connections and generating events while Bro's scripting language is the medium through which we mere mortals can achieve communication. Bro scripts effectively notify Bro that should there be an event of a type we define, then let us have the information about the connection so we can perform some function on it. For example, the ssl.log file is generated by a Bro script that walks the entire certificate chain and issues notifications if any of the steps along the certificate chain are invalid. This entire process is setup by telling Bro that should it see a server or client issue an SSL HELLO message, we want to know about the information about that connection. -It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru Malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script detect-MHR.bro is responsible for generating the appropriate DNS lookup and parsing the response. +It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru Malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. Team Cymru also populates the TXT record of their DNS responses with both a "last seen" timestamp and a numerical "detection rate". The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script detect-MHR.bro is responsible for generating the appropriate DNS lookup and parsing the response. .. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: -Visually, there are three distinct sections of the script. A base level with no indentation followed by an indented and formatted section explaining custom the variables being set (export) and another indented and formatted section describing the instructions for a specific event (event log_http). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. +Visually, there are three distinct sections of the script. A base level with no indentation followed by an indented and formatted section explaining the custom variables being set (export) and another indented and formatted section describing the instructions for a specific event (event log_http). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. .. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: :lines: 7-11 -Lines 7 and 8 of the script process the __load__.bro script in the respective directories being loaded. In a full production deployment of Bro it's likely that these files would already be loaded and their contents made available to the script, but including them explicitly ensures that Bro can be run in modes such as "bare" and still have scripts that reliably work. +Lines 7 and 8 of the script process the __load__.bro script in the respective directories being loaded. In a full production deployment of Bro it's likely that these files would already be loaded and their contents made available to the script, but including them explicitly ensures that Bro can be run in modes such as "bare" and still have scripts that reliably work. Consider it a "best practice" to include appropriate @load statments when possible. .. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: - :lines: 12-18 + :lines: 12-24 The export section redefines an enumerable constant that describes the type of notice we will generate with the logging framework. The notice type listed allows for the use of the NOTICE() function to generate notices of type Malware_Hash_Registry_Match as done in the next section. .. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: - :lines: 20-37 + :lines: 26-44 -The workhorse of the script is contained in the event handler for log_http. The log_http event is defined as an event-hook in the base/protocols/http/main.bro script and allows scripts to handle connection as it is being passed to the logging framework. The event handler is passed an HTTP::Info data structure which will be referred to as "rec" in body of the event handler. +The workhorse of the script is contained in the event handler for log_http. The log_http event is defined as an event-hook in the base/protocols/http/main.bro script and allows scripts to handle a connection as it is being passed to the logging framework. The event handler is passed an HTTP::Info data structure which will be referred to as "rec" in body of the event handler. -An if statement is used to check for the existence of a data structure named "md5" nested within the rec data structure. Bro uses the "$" as a deference operator and as such, and it is employed in this script to check if rec$md5 is present by including the "?" operator within the path. If the rec data structure includes a nested data structure named "md5", the statement is processed as true and a local variable named "hash_domain" is provisioned and given a format string based on the contents of rec$md5. The script then provisions another local variable named "addrs" and fills it with the output of the lookup_hostname() function which will perform a DNS lookup on the arguments passed to it. +An if statement is used to check for the existence of a data structure named "md5" nested within the rec data structure. Bro uses the "$" as a deference operator and as such, and it is employed in this script to check if rec$md5 is present by including the "?" operator within the path. If the rec data structure includes a nested data structure named "md5", the statement is processed as true and a local variable named "hash_domain" is provisioned and given a format string based on the contents of rec$md5 to produce a valid DNS lookup. -DNS lookups against the Team Cymru Malware Hash Registry will return a '127.0.0.2' if the hash being queried is found in the hash registry. If the response includes 127.0.0.2, the script proceeds to build two new local variables to be used in the notice and then issues the NOTICE(). +The rest of the script is contained within a when() block. In short, a when block is used when Bro needs to perform asynchronous actions, such a DNS lookup, to ensure that performance isn't effected. The when() block performs a DNS TXT lookup and stores the result in the local variable MHR_result. Effectively, processing for this event continues and upon receipt of the values returned by lookup_hostname_txt(), the when block is executed. The when block splits the string returned into two seperate values and checks to ensure an expected format. If the format is invalid, the script assumes that the hash wasn't found in the respository and processing is concluded. If the format is as expected and the detection rate is above the threshold set by MHR_threshold, two new local variables are created and used in the notice issued by NOTICE(). In approximately 15 lines of actual code, Bro provides an amazing utility that would be incredibly difficult to implement and deploy with other products. In truth, claiming that Bro does this in 15 lines is a misdirection; There is a truly massive number of things going on behind-the-scenes in Bro, but it is the inclusion of the scripting language that gives analysts access to those underlying layers in a succinct and well defined manner. From 80cdfbcab406c52ae4548b12876037b52f0b0f5a Mon Sep 17 00:00:00 2001 From: Soumya Basu Date: Thu, 15 Nov 2012 13:04:48 -0800 Subject: [PATCH 014/881] Moved the testing file to the correct directory --- testing/btest/bifs/hll_cardinality.bro | 138 +++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 testing/btest/bifs/hll_cardinality.bro diff --git a/testing/btest/bifs/hll_cardinality.bro b/testing/btest/bifs/hll_cardinality.bro new file mode 100644 index 0000000000..093de134df --- /dev/null +++ b/testing/btest/bifs/hll_cardinality.bro @@ -0,0 +1,138 @@ +# +# @TEST-EXEC: bro %INPUT>out +# @TEST-EXEC: btest-diff out + +event bro_init() + { + local m1 = "measurement1"; + local m2 = "measurement2"; + + print "This value should be true:"; + print hll_cardinality_init(0.01, m1); + hll_cardinality_init(0.01, m2); + + print "This value should be false:"; + print hll_cardinality_init(0.02, "measurement1"); + + local add1 = "hey"; + local add2 = "hi"; + local add3 = 123; + + hll_cardinality_add(add1, m1); + hll_cardinality_add(add2, m1); + hll_cardinality_add(add3, m1); + hll_cardinality_add("a", m1); + hll_cardinality_add("b", m1); + hll_cardinality_add("c", m1); + hll_cardinality_add("d", m1); + hll_cardinality_add("e", m1); + hll_cardinality_add("f", m1); + hll_cardinality_add("g", m1); + hll_cardinality_add("h", m1); + hll_cardinality_add("i", m1); + + print "This value should be true:"; + print hll_cardinality_add("j", m1); + + print "This value should be false:"; + print hll_cardinality_add("asdf", "something"); + + + hll_cardinality_add(add1, m2); + hll_cardinality_add(add2, m2); + hll_cardinality_add(add3, m2); + hll_cardinality_add(1, m2); + hll_cardinality_add("b", m2); + hll_cardinality_add(2, m2); + hll_cardinality_add(3, m2); + hll_cardinality_add(4, m2); + hll_cardinality_add(5, m2); + hll_cardinality_add(6, m2); + hll_cardinality_add(7, m2); + hll_cardinality_add(8, m2); + + print "This value should be around 13:"; + print hll_cardinality_estimate("measurement1"); + + print "This value should be -1.0:"; + print hll_cardinality_estimate("m2"); + + hll_cardinality_init(0.02, "m2"); + + print "This value should be around 0:"; + print hll_cardinality_estimate("m2"); + + print "This value should be true:"; + print hll_cardinality_destroy("m2"); + + print "This value should be false:"; + print hll_cardinality_destroy("m2"); + + print "This value should be -1.0:"; + print hll_cardinality_estimate("m2"); + + print "This next thing should be false:"; + print hll_cardinality_clone("m3", "m2"); + + print "This next thing should be true:"; + print hll_cardinality_clone("measurement3", "measurement1"); + + print "This value should be around 13:"; + print hll_cardinality_estimate("measurement3"); + + hll_cardinality_destroy("measurement3"); + + print "This next thing should be equal to -1.0:"; + print hll_cardinality_estimate("measurement3"); + + print "This value should be around 13:"; + print hll_cardinality_estimate("measurement1"); + + print "This value should be true:"; + print hll_cardinality_merge_into("measurement3", "measurement2"); + + print "This value should be false:"; + print hll_cardinality_merge_into("measurement4", "measurement6"); + + print "This value should be about 12:"; + print hll_cardinality_estimate("measurement3"); + + print "This value should be false:"; + print hll_cardinality_merge_into("measurement3", "measurement15"); + + print "This value should be about 12:"; + print hll_cardinality_estimate("measurement3"); + + print "This value should be true:"; + print hll_cardinality_merge_into("measurement2", "measurement1"); + + print "This value should be about 21:"; + print hll_cardinality_estimate("measurement2"); + + print "This value should be about 13:"; + print hll_cardinality_estimate("measurement1"); + + print "This value should be about 12:"; + print hll_cardinality_estimate("measurement3"); + + local keys = hll_cardinality_keys(); + for(key in keys) + { + print "The key is:"; + print key; + print "The value is:"; + print hll_cardinality_estimate(key); + } + } + +#function hll_cardinality_keys%(%): bool +# %{ +#// TableVal* a = new TableVal(string_set); +#// map::iterator it; +# +#// for(it = hll_counters.begin() ; it != hll_counters.end(); it++) +#// { +#// a->Assign((*it).first); +#// } +#// return a; +# return new Val(1, TYPE_BOOL); From d1d7fe5d4d4c2c7086d638ceb11e0593c9db5278 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sat, 24 Nov 2012 14:16:50 -0500 Subject: [PATCH 015/881] Exploration of the connection record data type and corresponding btests. --- .../Baseline/doc.manual.connection_record_01/.stdout | 5 +++++ .../Baseline/doc.manual.connection_record_02/.stdout | 9 +++++++++ testing/btest/doc/manual/connection_record_01.bro | 9 +++++++++ testing/btest/doc/manual/connection_record_02.bro | 10 ++++++++++ 4 files changed, 33 insertions(+) create mode 100644 testing/btest/Baseline/doc.manual.connection_record_01/.stdout create mode 100644 testing/btest/Baseline/doc.manual.connection_record_02/.stdout create mode 100644 testing/btest/doc/manual/connection_record_01.bro create mode 100644 testing/btest/doc/manual/connection_record_02.bro diff --git a/testing/btest/Baseline/doc.manual.connection_record_01/.stdout b/testing/btest/Baseline/doc.manual.connection_record_01/.stdout new file mode 100644 index 0000000000..7f134460e3 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.connection_record_01/.stdout @@ -0,0 +1,5 @@ +[id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={ + +}, addl=, hot=0, history=ShADadFf, uid=UWkUyAuUGXf, tunnel=, conn=[ts=930613226.067666, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ + +}], extract_orig=F, extract_resp=F] diff --git a/testing/btest/Baseline/doc.manual.connection_record_02/.stdout b/testing/btest/Baseline/doc.manual.connection_record_02/.stdout new file mode 100644 index 0000000000..b048a2c924 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.connection_record_02/.stdout @@ -0,0 +1,9 @@ +[id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={ + +}, addl=, hot=0, history=ShADadFf, uid=UWkUyAuUGXf, tunnel=, conn=[ts=930613226.067666, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ + +}], extract_orig=F, extract_resp=F, dns=[ts=930613226.518174, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, trans_id=34798, query=, qclass=, qclass_name=, qtype=, qtype_name=, rcode=0, rcode_name=NOERROR, AA=F, TC=F, RD=F, RA=T, Z=0, answers=[4.3.2.1], TTLs=[8.0 hrs 42.0 mins 17.0 secs], rejected=F, ready=F, total_answers=0, total_replies=1], dns_state=[pending={ +[34798] = [ts=930613226.518174, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, trans_id=34798, query=, qclass=, qclass_name=, qtype=, qtype_name=, rcode=0, rcode_name=NOERROR, AA=F, TC=F, RD=F, RA=T, Z=0, answers=[4.3.2.1], TTLs=[8.0 hrs 42.0 mins 17.0 secs], rejected=F, ready=F, total_answers=0, total_replies=1] +}, finished_answers={ + +}]] diff --git a/testing/btest/doc/manual/connection_record_01.bro b/testing/btest/doc/manual/connection_record_01.bro new file mode 100644 index 0000000000..ffd2f82dcc --- /dev/null +++ b/testing/btest/doc/manual/connection_record_01.bro @@ -0,0 +1,9 @@ +# @TEST-EXEC: bro -b -r $TRACES/dns-session.trace %INPUT +# @TEST-EXEC: btest-diff .stdout + +@load base/protocols/conn + +event connection_state_remove(c: connection) + { + print c; + } \ No newline at end of file diff --git a/testing/btest/doc/manual/connection_record_02.bro b/testing/btest/doc/manual/connection_record_02.bro new file mode 100644 index 0000000000..480e42af0b --- /dev/null +++ b/testing/btest/doc/manual/connection_record_02.bro @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro -b -r $TRACES/dns-session.trace %INPUT +# @TEST-EXEC: btest-diff .stdout + +@load base/protocols/conn +@load base/protocols/dns + +event connection_state_remove(c: connection) + { + print c; + } \ No newline at end of file From d35268a41cd94aaa9d1bbdf2ba3ebe42b3a3ea36 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sat, 1 Dec 2012 02:22:52 -0500 Subject: [PATCH 016/881] Beginning exploration of network centric data types, starting with subnets. --- doc/user-manual/scripting.rst | 92 ++++++++++++++++--- .../doc.manual.data_type_subnets/.stdout | 4 + .../btest/doc/manual/data_type_subnets.bro | 22 +++++ 3 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.data_type_subnets/.stdout create mode 100644 testing/btest/doc/manual/data_type_subnets.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index a8ec45e53d..bd57d2f06f 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -8,10 +8,11 @@ Scripting :numbered: Understanding Bro Scripts - Event Handlers - Data types - A complete script - Guidelines for writing scripts + The Event Queue and Event Handlers + The Connection Record Datatype + Data Types + Variables and Scope + Branching and Iteration Understanding Bro Scripts ========================= @@ -21,27 +22,27 @@ Bro includes an event queue driven scripting language that provides the primary It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru Malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. Team Cymru also populates the TXT record of their DNS responses with both a "last seen" timestamp and a numerical "detection rate". The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script detect-MHR.bro is responsible for generating the appropriate DNS lookup and parsing the response. -.. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro +.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: Visually, there are three distinct sections of the script. A base level with no indentation followed by an indented and formatted section explaining the custom variables being set (export) and another indented and formatted section describing the instructions for a specific event (event log_http). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. -.. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro +.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: :lines: 7-11 Lines 7 and 8 of the script process the __load__.bro script in the respective directories being loaded. In a full production deployment of Bro it's likely that these files would already be loaded and their contents made available to the script, but including them explicitly ensures that Bro can be run in modes such as "bare" and still have scripts that reliably work. Consider it a "best practice" to include appropriate @load statments when possible. -.. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro +.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: :lines: 12-24 The export section redefines an enumerable constant that describes the type of notice we will generate with the logging framework. The notice type listed allows for the use of the NOTICE() function to generate notices of type Malware_Hash_Registry_Match as done in the next section. -.. literalinclude:: ../../scripts/policy/protocols/http/detect-MHR.bro +.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: :lines: 26-44 @@ -63,7 +64,7 @@ Bro's core acts to place events into an ordered "Event Queue", allowing event ha Gaining familiarity with the specific events generated by Bro is a big step towards building a mind set for working with Bro scripts. The majority of events generated by Bro are defined in the built-in-function files or .bif files which also act as the basis for online event documentation. Whether starting a script from scratch or reading and maintaining someone else's script, having the built-in event definitions available is an excellent resource to have on hand. Before release version 2.0 the Bro developers put significant effort into organization and documentation of every event. This effort resulted in built-in-function files organized such that each entry contains a descriptive event name, the arguments passed to the event, and a concise explanation of the functions use. -.. literalinclude:: ../../build/src/base/event.bif.bro +.. literalinclude:: ../../../../build/src/base/event.bif.bro :language: bro :linenos: :lines: 4124-4149 @@ -77,12 +78,81 @@ Of all the events defined in Bro's event.bif.bro file, an overwhelmingly large n While Bro is capable of packet level processing, its strengths lay in the context of a connection between an originator and a responder. As such, there are events defined for the primary parts of the connection life-cycle as you'll see from the small selection of connection-related events below. -.. literalinclude:: ../../build/src/base/event.bif.bro +.. literalinclude:: ../../../../build/src/base/event.bif.bro :language: bro :linenos: :lines: 135-138,154,204-208,218,255-256,266,335-340,351 -Of the events listed, the event that will give us the best insight into the connection record data type will be connection_state_remove(). As detailed in the in-line documentation, Bro generates this event just before it decides to remove this event from memory, effectively forgetting about it. +Of the events listed, the event that will give us the best insight into the connection record data type will be connection_state_remove(). As detailed in the in-line documentation, Bro generates this event just before it decides to remove this event from memory, effectively forgetting about it. Let's take a look at a simple script that will output the connection record for a single connection. +.. literalinclude:: ../../../../testing/btest/doc/manual/connection_record_01.bro + :language: bro + :linenos: + :lines: 4-9 +Again, we start with @load, this time importing the base/protocols/conn scripts which supply the tracking and logging of general information and state of connections. We handle the connection_state_remove() event and simply print the contents of the argument passed to it. For this example we're going to run Bro in "bare mode" which loads only the minimum number of scripts to retain operability and leaves the burden of loading required scripts to the script being run. This will give us a chance to see the contents of the connection record without it being overly populated. + +.. btest:: connection-record-01 + + @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_01.bro + +As you can see from the output, the connection record is something of a jumble when printed on its own. Regularly taking a peek at a populated connection record helps to understand the relationship between its fields as well as allowing an opportunity to build a frame of reference for accessing data in a script. + +Bro uses the dollar sign as it's field delimiter and a direct correlation exists between the output of the connection record and the proper format of a dereferenced variable in scripts. In the output of the script above, groups of information are collected between brackets, which would correspond to the $-delimiter in a Bro script. For example, the originating host is referenced by c$id$orig_h which breaks down to "orig_h which is a member of id which is a member of the data structure referred to as c that was passed into the event handler." Given that the responder port (c$id$resp_p) is 53/tcp, it's likely that Bro's base DNS scripts can further populate the connection record. Let's load the base/protocols/dns scripts and check the output of our script. + +.. literalinclude:: ../../../../testing/btest/doc/manual/connection_record_02.bro + :language: bro + :linenos: + :lines: 4-10 + +.. btest:: connection-record-02 + + @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_02.bro + +The addition of the base/protocols/dns scripts populates the dns=[] member of the connection record. While Bro is doing a massive amount of work in the background, it is in what is commonly called "script land" that details are being refined and decisions being made. Were we to continue running in "bare mode" we could slowly keep adding infrastructure through @load statements. For example, were we to load base/frameworks/logging, Bro would generate a conn.log and dns.log for us in the current working directory. Not only is it good practice to include appropriate load statements in your scripts, but it also helps to illuminate the various functionalities within Bro's scripting language. + +Data Types +========== + +The table below shows the common data types used in Bro, of which, the first four should seem familiar while the remaining six are less common in other languages. A basic understanding of the extra data types in Bro might save you a light night of reinventing the wheel. It should come as no surprise that a scripting language for a Network Security Monitoring platform has a fairly robust set of network-centric data types. While each of the network centric data types should be be familiar in the type of data they represent, seeing the data types in action can be a better starting point. + ++-----------+-------------------------------------+ +| Data Type | Description | ++===========+=====================================+ +| int | 64 bit signed integer | ++-----------+-------------------------------------+ +| count | 64 bit unsigned integer | ++-----------+-------------------------------------+ +| double | double precision floating precision | ++-----------+-------------------------------------+ +| bool | boolean (T/F) | ++-----------+-------------------------------------+ +| addr | ip address, ipv4 and ipv6 | ++-----------+-------------------------------------+ +| port | transport layer port | ++-----------+-------------------------------------+ +| subnet | CIDR subnet mask | ++-----------+-------------------------------------+ +| time | absolute epoch time | ++-----------+-------------------------------------+ +| interval | a time interval | ++-----------+-------------------------------------+ +| pattern | regular expression | ++-----------+-------------------------------------+ + +subnet +------ + +Bro has full support for CIDR notation subnets as a base data type. There is no need to manage the IP and the subnet mask as two seperate entities when you can provide the same information in CIDR notation in your scripts. The following example below uses a Bro script to determine if a series of IP addresses are within a set of subnets using a 20 bit subnet mask. We'll be using some structures we have not yet introduced, as well as some operationts, but we'll touch on them here before going into more detail with them later on. + +.. literalinclude:: ${TESTBASE}/doc/manual/data_type_subnets.bro + :language: bro + :linenos: + :lines: 4-19 + +Because this is a script that doesn't use any kind of network analysis, we can handle the event bro_init() which is always generated by Bro's core upon startup. On lines six and seven, two locally scoped vectors (vectors are like lists in Python or arrays in C) are created to hold our lists of subnets and IP addresses respectively. Then, using a set of nested for loops, we iterate over every subnet and every IP address and use an if statement to compare an IP address against a subnet using the in operator. The in operator returns true if the IP address falls within a given subnet. For example, 10.0.0.1 in 10.0.0.0/8 would return true while 192.168.2.1 in 192.168.1.0/24 would return false. When we run the script, we get the output listing the IP address and the subnet in which it belongs. + +.. btest:: data_type_subnets + + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_subnets.bro diff --git a/testing/btest/Baseline/doc.manual.data_type_subnets/.stdout b/testing/btest/Baseline/doc.manual.data_type_subnets/.stdout new file mode 100644 index 0000000000..facaaabe64 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_type_subnets/.stdout @@ -0,0 +1,4 @@ +172.16.4.56 belongs to subnet 172.16.0.0/20 +172.16.47.254 belongs to subnet 172.16.32.0/20 +172.16.22.45 belongs to subnet 172.16.16.0/20 +172.16.1.1 belongs to subnet 172.16.0.0/20 diff --git a/testing/btest/doc/manual/data_type_subnets.bro b/testing/btest/doc/manual/data_type_subnets.bro new file mode 100644 index 0000000000..b0d174069a --- /dev/null +++ b/testing/btest/doc/manual/data_type_subnets.bro @@ -0,0 +1,22 @@ +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local subnets = vector(172.16.0.0/20, 172.16.16.0/20, 172.16.32.0/20, 172.16.48.0/20); + local addresses = vector(172.16.4.56, 172.16.47.254, 172.16.22.45, 172.16.1.1); + for (a in addresses) + { + for (s in subnets) + { + if (addresses[a] in subnets[s]) + { + print fmt("%s belongs to subnet %s", addresses[a], subnets[s]); + } + } + } + + } + + + From 2dc2076b4405ab62d582241798d66cd6763b8a4d Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Tue, 4 Dec 2012 17:15:05 -0600 Subject: [PATCH 017/881] Improve description of built-in types Added more information on operators and literals. --- doc/scripts/builtins.rst | 215 +++++++++++++++++++++++++++++---------- 1 file changed, 161 insertions(+), 54 deletions(-) diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index d274de6b7b..507a4b96e3 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -1,5 +1,5 @@ -Builtin Types and Attributes -============================ +Built-in Types and Attributes +============================= Types ----- @@ -8,48 +8,79 @@ The Bro scripting language supports the following built-in types. .. bro:type:: void - An internal Bro type representing an absence of a type. Should - most often be seen as a possible function return type. + An internal Bro type representing the absence of a return type for a + function. .. bro:type:: bool Reflects a value with one of two meanings: true or false. The two ``bool`` constants are ``T`` and ``F``. + The ``bool`` type supports the following operators: equality/inequality + (``==``, ``!=``), logical and/or (``&&``, ``||``), logical + negation (``!``), and absolute value (where ``|T|`` is 1, and ``|F|`` is 0). + .. bro:type:: int - A numeric type representing a signed integer. An ``int`` constant + A numeric type representing a 64-bit signed integer. An ``int`` constant is a string of digits preceded by a ``+`` or ``-`` sign, e.g. - ``-42`` or ``+5``. When using type inferencing use care so that the + ``-42`` or ``+5`` (the "+" sign is optional but see note about type + inferencing below). An ``int`` constant can also be written in + hexadecimal notation (in which case "0x" must be between the sign and + the hex digits), e.g. ``-0xFF`` or ``+0xabc123``. + + The ``int`` type supports the following operators: arithmetic + operators (``+``, ``-``, ``*``, ``/``, ``%``), comparison operators + (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators + (``=``, ``+=``, ``-=``), pre-increment (``++``), pre-decrement + (``--``), and absolute value (e.g., ``|-3|`` is 3). + + When using type inferencing use care so that the intended type is inferred, e.g. ``local size_difference = 0`` will infer :bro:type:`count`, while ``local size_difference = +0`` will infer :bro:type:`int`. .. bro:type:: count - A numeric type representing an unsigned integer. A ``count`` - constant is a string of digits, e.g. ``1234`` or ``0``. + A numeric type representing a 64-bit unsigned integer. A ``count`` + constant is a string of digits, e.g. ``1234`` or ``0``. A ``count`` + can also be written in hexadecimal notation (in which case "0x" must + precede the hex digits), e.g. ``0xff`` or ``0xABC123``. + + The ``count`` type supports the same operators as the :bro:type:`int` + type. .. bro:type:: counter An alias to :bro:type:`count`. -.. TODO: is there anything special about this type? - .. bro:type:: double A numeric type representing a double-precision floating-point number. Floating-point constants are written as a string of digits with an optional decimal point, optional scale-factor in scientific notation, and optional ``+`` or ``-`` sign. Examples are ``-1234``, - ``-1234e0``, ``3.14159``, and ``.003e-23``. + ``-1234e0``, ``3.14159``, and ``.003E-23``. + + The ``double`` type supports the following operators: arithmetic + operators (``+``, ``-``, ``*``, ``/``), comparison operators + (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators + (``=``, ``+=``, ``-=``), and absolute value (e.g., ``|-3.14|`` is 3.14). + .. bro:type:: time A temporal type representing an absolute time. There is currently no way to specify a ``time`` constant, but one can use the - :bro:id:`current_time` or :bro:id:`network_time` built-in functions - to assign a value to a ``time``-typed variable. + :bro:id:`double_to_time`, :bro:id:`current_time`, or :bro:id:`network_time` + built-in functions to assign a value to a ``time``-typed variable. + + Time values support the comparison operators (``==``, ``!=``, ``<``, + ``<=``, ``>``, ``>=``). A ``time`` value can be subtracted from + another ``time`` value to produce an ``interval`` value. An ``interval`` + value can be added to, or subtracted from, a ``time`` value. The + absolute value of a ``time`` value is a ``double`` with the same + numeric value. .. bro:type:: interval @@ -61,16 +92,31 @@ The Bro scripting language supports the following built-in types. constant and time unit is optional. Appending the letter "s" to the time unit in order to pluralize it is also optional (to no semantic effect). Examples of ``interval`` constants are ``3.5 min`` and - ``3.5mins``. An ``interval`` can also be negated, for example ``- - 12 hr`` represents "twelve hours in the past". Intervals also - support addition, subtraction, multiplication, division, and - comparison operations. + ``3.5mins``. An ``interval`` can also be negated, for example + ``-12 hr`` represents "twelve hours in the past". + + Intervals support addition and subtraction. Intervals also support + division (in which case the result is a ``double`` value), the + comparison operators (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), + and the assignment operators (``=``, ``+=``, ``-=``). Also, an + interval can be multiplied or divided by an arithmetic type (``count``, + ``int``, or ``double``). The absolute value of an interval is a + ``double`` value equal to the number of seconds in the ``interval`` + (e.g., ``|-1 min|`` is 60). .. bro:type:: string A type used to hold character-string values which represent text. String constants are created by enclosing text in double quotes (") - and the backslash character (\\) introduces escape sequences. + and the backslash character (\\) introduces escape sequences (all of + the C-style escape sequences are supported). + + Strings support concatenation (``+``), and assignment (``=``, ``+=``). + Strings also support the comparison operators (``==``, ``!=``, ``<``, + ``<=``, ``>``, ``>=``). Substring searching can be performed using + the "in" or "!in" operators (e.g., "bar" in "foobar" yields true). + The number of characters in a string can be found by enclosing the + string within pipe characters (e.g., ``|"abc"|`` is 3). Note that Bro represents strings internally as a count and vector of bytes rather than a NUL-terminated byte string (although string @@ -127,9 +173,7 @@ The Bro scripting language supports the following built-in types. .. bro:type:: enum A type allowing the specification of a set of related values that - have no further structure. The only operations allowed on - enumerations are equality comparisons and they do not have - associated values or ordering. An example declaration: + have no further structure. An example declaration: .. code:: bro @@ -137,9 +181,9 @@ The Bro scripting language supports the following built-in types. The last comma after ``Blue`` is optional. -.. bro:type:: timer - -.. TODO: is this a type that's exposed to users? + The only operations allowed on enumerations are equality comparisons + (``==``, ``!=``) and assignment (``=``). + Enumerations do not have associated values or ordering. .. bro:type:: port @@ -149,10 +193,10 @@ The Bro scripting language supports the following built-in types. message code. A ``port`` constant is written as an unsigned integer followed by one of ``/tcp``, ``/udp``, ``/icmp``, or ``/unknown``. - Ports can be compared for equality and also for ordering. When - comparing order across transport-level protocols, ``unknown`` < - ``tcp`` < ``udp`` < ``icmp``, for example ``65535/tcp`` is smaller - than ``0/udp``. + Ports support the comparison operators (``==``, ``!=``, ``<``, ``<=``, + ``>``, ``>=``). When comparing order across transport-level protocols, + ``unknown`` < ``tcp`` < ``udp`` < ``icmp``, for example ``65535/tcp`` + is smaller than ``0/udp``. .. bro:type:: addr @@ -162,22 +206,29 @@ The Bro scripting language supports the following built-in types. ``A1.A2.A3.A4``, where Ai all lie between 0 and 255. IPv6 address constants are written as colon-separated hexadecimal form - as described by :rfc:`2373`, but additionally encased in square brackets. - The mixed notation with embedded IPv4 addresses as dotted-quads in the - lower 32 bits is also allowed. - Some examples: ``[2001:db8::1]``, ``[::ffff:192.168.1.100]``, or + as described by :rfc:`2373` (including the mixed notation with embedded + IPv4 addresses as dotted-quads in the lower 32 bits), but additionally + encased in square brackets. Some examples: ``[2001:db8::1]``, + ``[::ffff:192.168.1.100]``, or ``[aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222]``. + Note that IPv4-mapped IPv6 addresses (i.e., addresses with the first 80 + bits zero, the next 16 bits one, and the remaining 32 bits are the IPv4 + address) are treated internally as IPv4 addresses (for example, + ``[::ffff:192.168.1.100]`` is equal to ``192.168.1.100``). + Hostname constants can also be used, but since a hostname can - correspond to multiple IP addresses, the type of such variable is a + correspond to multiple IP addresses, the type of such a variable is a :bro:type:`set` of :bro:type:`addr` elements. For example: .. code:: bro local a = www.google.com; - Addresses can be compared for (in)equality using ``==`` and ``!=``. - They can also be masked with ``/`` to produce a :bro:type:`subnet`: + Addresses can be compared for equality (``==``, ``!=``), + and also for ordering (``<``, ``<=``, ``>``, ``>=``). The absolute value + of an address gives the size in bits (32 for IPv4, and 128 for IPv6). + Addresses can also be masked with ``/`` to produce a :bro:type:`subnet`: .. code:: bro @@ -186,7 +237,8 @@ The Bro scripting language supports the following built-in types. if ( a/16 == s ) print "true"; - And checked for inclusion within a :bro:type:`subnet` using ``in`` : + And checked for inclusion within a :bro:type:`subnet` using ``in`` + or ``!in``: .. code:: bro @@ -202,6 +254,10 @@ The Bro scripting language supports the following built-in types. slash (/) and then the network prefix size specified as a decimal number. For example, ``192.168.0.0/16`` or ``[fe80::]/64``. + Subnets can be compared for equality (``==``, ``!=``). An + :bro:type:`addr` can be checked for inclusion in a subnet using + the "in" or "!in" operators. + .. bro:type:: any Used to bypass strong typing. For example, a function can take an @@ -246,14 +302,14 @@ The Bro scripting language supports the following built-in types. [5] = "five", }; - Accessing table elements if provided by enclosing values within square - brackets (``[]``), for example: + Accessing table elements is provided by enclosing index values within + square brackets (``[]``), for example: .. code:: bro - t[13] = "thirteen"; + print t[11]; - And membership can be tested with ``in``: + And membership can be tested with ``in`` or ``!in``: .. code:: bro @@ -272,17 +328,23 @@ The Bro scripting language supports the following built-in types. for ( [a, p] in services ) ... + Add or overwrite individual table elements by assignment: + + .. code:: bro + + t[13] = "thirteen"; + Remove individual table elements with ``delete``: .. code:: bro delete t[13]; - Nothing happens if the element with value ``13`` isn't present in + Nothing happens if the element with index value ``13`` isn't present in the table. - Table size can be obtained by placing the table identifier between - vertical pipe (|) characters: + The number of elements in a table can be obtained by placing the table + identifier between vertical pipe characters: .. code:: bro @@ -308,27 +370,41 @@ The Bro scripting language supports the following built-in types. The types are explicitly shown in the example above, but they could have been left to type inference. - Set membership is tested with ``in``: + Set membership is tested with ``in`` or ``!in``: .. code:: bro if ( 21/tcp in s ) ... + Iterate over a set with a ``for`` loop: + + .. code:: bro + + local s: set[port]; + for ( p in s ) + ... + Elements are added with ``add``: .. code:: bro add s[22/tcp]; + Nothing happens if the element with value ``22/tcp`` was already present in + the set. + And removed with ``delete``: .. code:: bro delete s[21/tcp]; - Set size can be obtained by placing the set identifier between - vertical pipe (|) characters: + Nothing happens if the element with value ``21/tcp`` isn't present in + the set. + + The number of elements in a set can be obtained by placing the set + identifier between vertical pipe characters: .. code:: bro @@ -337,7 +413,8 @@ The Bro scripting language supports the following built-in types. .. bro:type:: vector A vector is like a :bro:type:`table`, except it's always indexed by a - :bro:type:`count`. A vector is declared like: + :bro:type:`count` (and vector indexing is always zero-based). A vector + is declared like: .. code:: bro @@ -349,21 +426,51 @@ The Bro scripting language supports the following built-in types. global v: vector of string = vector("one", "two", "three"); - Adding an element to a vector involves accessing/assigning it: + Accessing vector elements is provided by enclosing index values within + square brackets (``[]``), for example: .. code:: bro - v[3] = "four" + print v[2]; - Note how the vector indexing is 0-based. + Iterate over a vector with a ``for`` loop: - Vector size can be obtained by placing the vector identifier between - vertical pipe (|) characters: + .. code:: bro + + local v: vector of string; + for ( n in v ) + ... + + An element can be added to a vector by assigning the value (a value + that already exists at that index will be overwritten): + + .. code:: bro + + v[3] = "four"; + + The number of elements in a vector can be obtained by placing the vector + identifier between vertical pipe characters: .. code:: bro |v| + Vectors of integral types (``int`` or ``count``) support the pre-increment + (``++``) and pre-decrement operators (``--``), which will increment or + decrement each element in the vector. + + Vectors of arithmetic types (``int``, ``count``, or ``double``) can be + operands of the arithmetic operators (``+``, ``-``, ``*``, ``/``, ``%``), + but both operands must have the same number of elements (and the modulus + operator ``%`` cannot be used if either operand is a ``vector of double``). + The resulting vector contains the result of the operation applied to each + of the elements in the operand vectors. + + Vectors of bool can be operands of the logical "and" (``&&``) and logical + "or" (``||``) operators (both operands must have same number of elements). + The resulting vector of bool is the logical "and" (or logical "or") of + each element of the operand vectors. + .. bro:type:: record A ``record`` is a collection of values. Each value has a field name @@ -448,8 +555,8 @@ The Bro scripting language supports the following built-in types. Note that in the definition above, it's not necessary for us to have done the first (forward) declaration of ``greeting`` as a function - type, but when it is, the argument list and return type much match - exactly. + type, but when it is, the return type and argument list (including the + name of each argument) must match exactly. Function types don't need to have a name and can be assigned anonymously: From 8c73e83c5582b1960e2390a939b921e9c0c69ee1 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Wed, 5 Dec 2012 17:34:31 -0600 Subject: [PATCH 018/881] More updates to built-in types document --- doc/scripts/builtins.rst | 51 +++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index 9e14e72a0d..5418e84f72 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -4,6 +4,21 @@ Built-in Types and Attributes Types ----- +Every value in a Bro script has a type (see below for a list of all built-in +types). Although Bro variables have static types (meaning that their type +is fixed), their type is inferred from the value to which they are +initially assigned when the variable is declared without an explicit type +name. + +Automatic conversions happen when a binary operator has operands of +different types. Automatic conversions are limited to converting between +numeric types. The numeric types are ``int``, ``count``, and ``double`` +(``bool`` is not a numeric type). +When an automatic conversion occurs, values are promoted to the "highest" +type in the expression. In general, this promotion follows a simple +hierarchy: ``double`` is highest, ``int`` comes next, and ``count`` is +lowest. + The Bro scripting language supports the following built-in types. .. bro:type:: void @@ -48,7 +63,7 @@ The Bro scripting language supports the following built-in types. precede the hex digits), e.g. ``0xff`` or ``0xABC123``. The ``count`` type supports the same operators as the :bro:type:`int` - type. + type. A unary plus or minus applied to a ``count`` results in an ``int``. .. bro:type:: counter @@ -67,6 +82,10 @@ The Bro scripting language supports the following built-in types. (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators (``=``, ``+=``, ``-=``), and absolute value (e.g., ``|-3.14|`` is 3.14). + When using type inferencing use care so that the + intended type is inferred, e.g. ``local size_difference = 5`` will + infer :bro:type:`count`, while ``local size_difference = 5.0`` + will infer :bro:type:`double`. .. bro:type:: time @@ -78,9 +97,9 @@ The Bro scripting language supports the following built-in types. Time values support the comparison operators (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``). A ``time`` value can be subtracted from another ``time`` value to produce an ``interval`` value. An ``interval`` - value can be added to, or subtracted from, a ``time`` value. The - absolute value of a ``time`` value is a ``double`` with the same - numeric value. + value can be added to, or subtracted from, a ``time`` value to produce a + ``time`` value. The absolute value of a ``time`` value is a ``double`` + with the same numeric value. .. bro:type:: interval @@ -99,10 +118,10 @@ The Bro scripting language supports the following built-in types. division (in which case the result is a ``double`` value), the comparison operators (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), and the assignment operators (``=``, ``+=``, ``-=``). Also, an - interval can be multiplied or divided by an arithmetic type (``count``, - ``int``, or ``double``). The absolute value of an interval is a - ``double`` value equal to the number of seconds in the ``interval`` - (e.g., ``|-1 min|`` is 60). + ``interval`` can be multiplied or divided by an arithmetic type + (``count``, ``int``, or ``double``) to produce an ``interval`` value. + The absolute value of an ``interval`` is a ``double`` value equal to the + number of seconds in the ``interval`` (e.g., ``|-1 min|`` is 60). .. bro:type:: string @@ -198,6 +217,11 @@ The Bro scripting language supports the following built-in types. ``unknown`` < ``tcp`` < ``udp`` < ``icmp``, for example ``65535/tcp`` is smaller than ``0/udp``. + Note that you can obtain the transport-level protocol type of a ``port`` + with the :bro:id:`get_port_transport_proto` built-in function, and + the numeric value of a ``port`` with the :bro:id:`port_to_count` + built-in function. + .. bro:type:: addr A type representing an IP address. @@ -247,6 +271,9 @@ The Bro scripting language supports the following built-in types. if ( a in s ) print "true"; + Note that you can check if a given ``addr`` is IPv4 or IPv6 using + the :bro:id:`is_v4_addr` and :bro:id:`is_v6_addr` built-in functions. + .. bro:type:: subnet A type representing a block of IP addresses in CIDR notation. A @@ -511,9 +538,11 @@ The Bro scripting language supports the following built-in types. .. bro:type:: file - Bro supports writing to files, but not reading from them. For - example, declare, open, and write to a file and finally close it - like: + Bro supports writing to files, but not reading from them. Files + can be opened using either the :bro:id:`open` or :bro:id:`open_for_append` + built-in functions, and closed using the :bro:id:`close` built-in + function. For example, declare, open, and write to a file + and finally close it like: .. code:: bro From 1c0905914c2579673ef30780b67537a934da3e11 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 20 Dec 2012 15:25:29 -0600 Subject: [PATCH 019/881] Document undocumented attributes --- doc/scripts/builtins.rst | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index d5737c0036..fb9bf5a912 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -755,11 +755,18 @@ scripting language supports the following built-in attributes. .. bro:attr:: &add_func -.. TODO: needs to be documented. + Can be applied to an identifier with &redef to specify a function to + be called any time a "redef += ..." declaration is parsed. The + function takes two arguments of the same type as the identifier, the first + being the old value of the variable and the second being the new + value given after the "+=" operator in the "redef" declaration. The + return value of the function will be the actual new value of the + variable after the "redef" declaration is parsed. .. bro:attr:: &delete_func -.. TODO: needs to be documented. + Same as &add_func, except for "redef" declarations that use the "-=" + operator. .. bro:attr:: &expire_func @@ -836,5 +843,15 @@ scripting language supports the following built-in attributes. .. bro:attr:: &error_handler -.. TODO: needs documented + Internally set on the events that are associated with the reporter + framework: :bro:id:`reporter_info`, :bro:id:`reporter_warning`, and + :bro:id:`reporter_error`. It prevents any handlers of those events + from being able to generate reporter messages that go through any of + those events (i.e., it prevents an infinite event recursion). Instead, + such nested reporter messages are output to stderr. +.. bro:attr:: &type_column + + Used by the input framework. It can be used on columns of type + :bro:type:`port` and specifies the name of an additional column in + the input file which specifies the protocol of the port (tcp/udp/icmp). From b8c31458ff81e5202e3f90b0bdcd697afcdff978 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Thu, 3 Jan 2013 17:03:45 -0500 Subject: [PATCH 020/881] Local variables. Baselines and data_type_local.bro btest-able script. --- doc/user-manual/scripting.rst | 97 +++++++++++++++++-- .../doc.manual.connection_record_02/.stdout | 6 +- .../doc.manual.data_struct_vector/.stdout | 2 + .../doc.manual.data_type_const/.stdout | 4 + .../doc.manual.data_type_declaration/.stdout | 1 + .../doc.manual.data_type_local/.stdout | 1 + .../btest/doc/manual/data_struct_vector.bro | 10 ++ testing/btest/doc/manual/data_type_const.bro | 12 +++ .../doc/manual/data_type_declaration.bro | 14 +++ testing/btest/doc/manual/data_type_local.bro | 14 +++ 10 files changed, 150 insertions(+), 11 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.data_struct_vector/.stdout create mode 100644 testing/btest/Baseline/doc.manual.data_type_const/.stdout create mode 100644 testing/btest/Baseline/doc.manual.data_type_declaration/.stdout create mode 100644 testing/btest/Baseline/doc.manual.data_type_local/.stdout create mode 100644 testing/btest/doc/manual/data_struct_vector.bro create mode 100644 testing/btest/doc/manual/data_type_const.bro create mode 100644 testing/btest/doc/manual/data_type_declaration.bro create mode 100644 testing/btest/doc/manual/data_type_local.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index bd57d2f06f..4cda00bd0b 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -10,9 +10,13 @@ Scripting Understanding Bro Scripts The Event Queue and Event Handlers The Connection Record Datatype - Data Types - Variables and Scope - Branching and Iteration + Data Types and Data Structures + Scope + Global Variables + Constants + Local Variables + Data Structures + Understanding Bro Scripts ========================= @@ -111,10 +115,62 @@ Bro uses the dollar sign as it's field delimiter and a direct correlation exists The addition of the base/protocols/dns scripts populates the dns=[] member of the connection record. While Bro is doing a massive amount of work in the background, it is in what is commonly called "script land" that details are being refined and decisions being made. Were we to continue running in "bare mode" we could slowly keep adding infrastructure through @load statements. For example, were we to load base/frameworks/logging, Bro would generate a conn.log and dns.log for us in the current working directory. Not only is it good practice to include appropriate load statements in your scripts, but it also helps to illuminate the various functionalities within Bro's scripting language. -Data Types -========== +Data Types and Data Structures +============================== -The table below shows the common data types used in Bro, of which, the first four should seem familiar while the remaining six are less common in other languages. A basic understanding of the extra data types in Bro might save you a light night of reinventing the wheel. It should come as no surprise that a scripting language for a Network Security Monitoring platform has a fairly robust set of network-centric data types. While each of the network centric data types should be be familiar in the type of data they represent, seeing the data types in action can be a better starting point. +Scope +----- + +Before embarking on a exploration of Bro's native Data Types and Data Structures, it's important to have a good grasp of the different levels of scope available in Bro and the appropriate times to use them within a script. The declarations of variables in Bro come in two forms. Variables can be declared with or without a definition in the form "SCOPE name: TYPE" or "SCOPE name = EXPRESSION" respectively; each of which produce the same result if EXPRESSION evaluates to the same type as TYPE. The decision as to which type of declaration to use is likely to be dictated by personal preference and readability. + +.. literalinclude:: ../../../../testing/btest/doc/manual/data_type_declaration.bro + :language: bro + :linenos: + :lines: 4-14 + +Global Variables +~~~~~~~~~~~~~~~~ + +A global variable is used when the state of variable needs to be tracked, not surprisingly, globally. While there are some caveats, when a script declares a variable using the global scope, that script is granting access to that variable from other scripts. The declaration below, is a taken from the known-hosts.bro script and declares a variable called "known_hosts"" as a global set of unique ip addresses(line 32) within the "Known" namespace (line 8) and exports it (line 10) for use outside of the "Known" namespace. Were we to want to use the "known_hosts" variable we'd be able to access it through "Known::known_hosts". + +.. literalinclude:: ../scripts/policy/protocols/conn/known-hosts.bro + :language: bro + :linenos: + :lines: 8-10, 32, 37 + +The sample above also makes use of an export{} block. When the module keyword is used in a script, the variables declared are said to be in that module's "namespace". Where as a global variable can be accessed by its name alone when it is not declared within a module, a global variable declared within a module must be exported and then accessed via MODULE_NAME::VARIABLE_NAME. As in the example above, we would be able to access the "known_hosts" in a separate script variable via "Known::known_hosts" due to the fact that known_hosts was declared as a global variable within an export block under the "Known" namespace. + +Constants +~~~~~~~~~ + +The next level of scoping available in Bro are constants which are denoted by the "const" keyword. Unlike globals, constants can only be set or altered at parse time, afterwards (in runtime) the constants are unalterable. In most cases, constants are used in Bro scripts as containers for configuration options. The majority of constants defined are defined with the "&redef" attribute, making it such that the constant can be redefined. While the idea of a redefinable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the "&redef" attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added to the table through redef statements. The table is then printed in a bro_init() event. Were we to try to alter the table in an event handler, Bro would notify the user of an error and the script would fail. + +.. literalinclude:: ../../../../testing/btest/doc/manual/data_type_const.bro + :language: bro + :linenos: + :lines: 4-12 + +.. btest:: data_type_const.bro + + @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_type_const.bro + +Local Variables +~~~~~~~~~~~~~~~ + +Whereas globals and constants are widely available in scriptland through various means, when a variable is defined with a local scope, its availability is restricted to the body of the event or function in which it was declared. Local variables tend to be used for values that are only needed within a specific scope and once the processing of a script passes beyond that scope, the variable is deleted. It is possible for a function to return a locally scoped variable but in doing so, it is the value that is returned. Bro maintains a difference between variables and values. + +.. literalinclude:: ../../../../testing/btest/doc/manual/data_type_local.bro + :language: bro + :linenos: + :lines: 4-14 + + +Data Structures +--------------- + +It's difficult to talk about Bro's data types in a practical manner without first covering the data structures available in Bro. Some of the more interesting characteristics of data types are revealed when used inside of a data structure, but given that data structures are made up of data types, it devolved rather quickly into a "chicken-and-egg"" problem. As such, we'll introduce data types from bird's eye view before diving into data structures and from there a more complete exploration of data types. + +The table below shows the common data types used in Bro, of which, the first four should seem familiar if you have some scripting experience, while the remaining six are less common in other languages. It should come as no surprise that a scripting language for a Network Security Monitoring platform has a fairly robust set of network centric data types and taking note of them here may well save you a late night of reinventing the wheel. +-----------+-------------------------------------+ | Data Type | Description | @@ -140,17 +196,42 @@ The table below shows the common data types used in Bro, of which, the first fou | pattern | regular expression | +-----------+-------------------------------------+ +Data Structures +--------------- + +Vectors +~~~~~~~ + +Similar to arrays, vectors in Bro use contiguous storage for their contents and as such the contents can be accessed using a zero indexed numerical offset. Each element in a vector is indexed by a count, starting and zero and progressing up to the current length of the list. While members of a vector must all be of the same type, the vector itself can grow dynamically. The format for the declaration of a vector follows the pattern of other declarations, namely, SCOPE v: vector of T where v is the name of your vector of T is the data type of its members. For example, the following snippet shows an explicit and implicit declaration of a vector. + +.. literalinclude:: ../../../../testing/btest/doc/manual/data_struct_vector.bro + :language: bro + :linenos: + :lines: 6,7 + + + +Sets +~~~~ + +Tables +~~~~~~ + + While each of the network centric data types should be be familiar in the type of data they represent, seeing the data types in action can be a better starting point, to do so a basic understanding of Bro's data structures will be helpful and + + subnet ------ Bro has full support for CIDR notation subnets as a base data type. There is no need to manage the IP and the subnet mask as two seperate entities when you can provide the same information in CIDR notation in your scripts. The following example below uses a Bro script to determine if a series of IP addresses are within a set of subnets using a 20 bit subnet mask. We'll be using some structures we have not yet introduced, as well as some operationts, but we'll touch on them here before going into more detail with them later on. -.. literalinclude:: ${TESTBASE}/doc/manual/data_type_subnets.bro +.. literalinclude:: ../../../../testing/btest/doc/manual/data_type_subnets.bro :language: bro :linenos: :lines: 4-19 -Because this is a script that doesn't use any kind of network analysis, we can handle the event bro_init() which is always generated by Bro's core upon startup. On lines six and seven, two locally scoped vectors (vectors are like lists in Python or arrays in C) are created to hold our lists of subnets and IP addresses respectively. Then, using a set of nested for loops, we iterate over every subnet and every IP address and use an if statement to compare an IP address against a subnet using the in operator. The in operator returns true if the IP address falls within a given subnet. For example, 10.0.0.1 in 10.0.0.0/8 would return true while 192.168.2.1 in 192.168.1.0/24 would return false. When we run the script, we get the output listing the IP address and the subnet in which it belongs. +Because this is a script that doesn't use any kind of network analysis, we can handle the event bro_init() which is always generated by Bro's core upon startup. On lines six and seven, two locally scoped vectors are created to hold our lists of subnets and IP addresses respectively. Then, using a set of nested for loops, we iterate over every subnet and every IP address and use an if statement to compare an IP address against a subnet using the in operator. The in operator returns true if the IP address falls within a given subnet based on the longest prefix match calculation. For example, 10.0.0.1 in 10.0.0.0/8 would return true while 192.168.2.1 in 192.168.1.0/24 would return false. When we run the script, we get the output listing the IP address and the subnet in which it belongs. + .. btest:: data_type_subnets diff --git a/testing/btest/Baseline/doc.manual.connection_record_02/.stdout b/testing/btest/Baseline/doc.manual.connection_record_02/.stdout index b048a2c924..824dd03097 100644 --- a/testing/btest/Baseline/doc.manual.connection_record_02/.stdout +++ b/testing/btest/Baseline/doc.manual.connection_record_02/.stdout @@ -2,8 +2,8 @@ }, addl=, hot=0, history=ShADadFf, uid=UWkUyAuUGXf, tunnel=, conn=[ts=930613226.067666, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ -}], extract_orig=F, extract_resp=F, dns=[ts=930613226.518174, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, trans_id=34798, query=, qclass=, qclass_name=, qtype=, qtype_name=, rcode=0, rcode_name=NOERROR, AA=F, TC=F, RD=F, RA=T, Z=0, answers=[4.3.2.1], TTLs=[8.0 hrs 42.0 mins 17.0 secs], rejected=F, ready=F, total_answers=0, total_replies=1], dns_state=[pending={ -[34798] = [ts=930613226.518174, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, trans_id=34798, query=, qclass=, qclass_name=, qtype=, qtype_name=, rcode=0, rcode_name=NOERROR, AA=F, TC=F, RD=F, RA=T, Z=0, answers=[4.3.2.1], TTLs=[8.0 hrs 42.0 mins 17.0 secs], rejected=F, ready=F, total_answers=0, total_replies=1] -}, finished_answers={ +}], extract_orig=F, extract_resp=F, dns=, dns_state=[pending={ +}, finished_answers={ +34798 }]] diff --git a/testing/btest/Baseline/doc.manual.data_struct_vector/.stdout b/testing/btest/Baseline/doc.manual.data_struct_vector/.stdout new file mode 100644 index 0000000000..8348ce7198 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_struct_vector/.stdout @@ -0,0 +1,2 @@ +[1, 2, 3, 4] +[1, 2, 3, 4] diff --git a/testing/btest/Baseline/doc.manual.data_type_const/.stdout b/testing/btest/Baseline/doc.manual.data_type_const/.stdout new file mode 100644 index 0000000000..0e49670a83 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_type_const/.stdout @@ -0,0 +1,4 @@ +{ +[6666/tcp] = IRC, +[80/tcp] = WWW +} diff --git a/testing/btest/Baseline/doc.manual.data_type_declaration/.stdout b/testing/btest/Baseline/doc.manual.data_type_declaration/.stdout new file mode 100644 index 0000000000..a6f28b5e52 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_type_declaration/.stdout @@ -0,0 +1 @@ +A: 10, B: 10 diff --git a/testing/btest/Baseline/doc.manual.data_type_local/.stdout b/testing/btest/Baseline/doc.manual.data_type_local/.stdout new file mode 100644 index 0000000000..e150c0b19d --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_type_local/.stdout @@ -0,0 +1 @@ +i + 2 = 12 diff --git a/testing/btest/doc/manual/data_struct_vector.bro b/testing/btest/doc/manual/data_struct_vector.bro new file mode 100644 index 0000000000..99d0b4dc6d --- /dev/null +++ b/testing/btest/doc/manual/data_struct_vector.bro @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local v: vector of count = vector(1, 2, 3, 4); + local w = vector(1, 2, 3, 4); + print v; + print w; + } \ No newline at end of file diff --git a/testing/btest/doc/manual/data_type_const.bro b/testing/btest/doc/manual/data_type_const.bro new file mode 100644 index 0000000000..bdcc888945 --- /dev/null +++ b/testing/btest/doc/manual/data_type_const.bro @@ -0,0 +1,12 @@ +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff .stdout + +const port_list: table[port] of string &redef; + +redef port_list += { [6666/tcp] = "IRC"}; +redef port_list += { [80/tcp] = "WWW" }; + +event bro_init() + { + print port_list; + } \ No newline at end of file diff --git a/testing/btest/doc/manual/data_type_declaration.bro b/testing/btest/doc/manual/data_type_declaration.bro new file mode 100644 index 0000000000..ba82e0da20 --- /dev/null +++ b/testing/btest/doc/manual/data_type_declaration.bro @@ -0,0 +1,14 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local a: int; + a = 10; + local b = 10; + + if (a == b) + { + print fmt("A: %d, B: %d", a, b); + } + } \ No newline at end of file diff --git a/testing/btest/doc/manual/data_type_local.bro b/testing/btest/doc/manual/data_type_local.bro new file mode 100644 index 0000000000..e589f39e9f --- /dev/null +++ b/testing/btest/doc/manual/data_type_local.bro @@ -0,0 +1,14 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +function add_two(i: count): count + { + local added_two = i+2; + print fmt("i + 2 = %d", added_two); + return added_two; + } + +event bro_init() + { + local test = add_two(10); + } \ No newline at end of file From 5260e102904825f9cfe3a2e094a29bd59a828d7b Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sat, 5 Jan 2013 17:59:47 -0500 Subject: [PATCH 021/881] A short discussion of variables versus values in the section on Local Variables. --- doc/user-manual/scripting.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 4cda00bd0b..2b9332d8f9 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -157,7 +157,7 @@ The next level of scoping available in Bro are constants which are denoted by th Local Variables ~~~~~~~~~~~~~~~ -Whereas globals and constants are widely available in scriptland through various means, when a variable is defined with a local scope, its availability is restricted to the body of the event or function in which it was declared. Local variables tend to be used for values that are only needed within a specific scope and once the processing of a script passes beyond that scope, the variable is deleted. It is possible for a function to return a locally scoped variable but in doing so, it is the value that is returned. Bro maintains a difference between variables and values. +Whereas globals and constants are widely available in scriptland through various means, when a variable is defined with a local scope, its availability is restricted to the body of the event or function in which it was declared. Local variables tend to be used for values that are only needed within a specific scope and once the processing of a script passes beyond that scope and no longer used, the variable is deleted. While it is possible for a function to return a locally scoped variable, in doing so it retuns the value instead of the variable. Bro maintains a difference between variables an example of which is illustrated below. The script executes the event handler "bro_init()" which in turn calls the function "add_two(i: count)" with an argument of 10. Once Bro enters the add_two function, it provisions a locally scoped variable called "added_two" to hold the value of i+2, in this case, 12. The add_two function then prints the value of the added_two variable and returns its value to the bro_init() event handler. At this point, the variable "added_two" has fallen out of scope and no longer exists while the value 12 is still in use and stored in the locally scoped variable "test". When Bro finishes processing the bro_init function, the variable called "test" is no longer in scope and, since there exist no other references to the value "12", the value is also deleted. .. literalinclude:: ../../../../testing/btest/doc/manual/data_type_local.bro :language: bro @@ -220,10 +220,13 @@ Tables While each of the network centric data types should be be familiar in the type of data they represent, seeing the data types in action can be a better starting point, to do so a basic understanding of Bro's data structures will be helpful and -subnet ------- +Data Types Revisited +-------------------- -Bro has full support for CIDR notation subnets as a base data type. There is no need to manage the IP and the subnet mask as two seperate entities when you can provide the same information in CIDR notation in your scripts. The following example below uses a Bro script to determine if a series of IP addresses are within a set of subnets using a 20 bit subnet mask. We'll be using some structures we have not yet introduced, as well as some operationts, but we'll touch on them here before going into more detail with them later on. +subnet +~~~~~~ + +Bro has full support for CIDR notation subnets as a base data type. There is no need to manage the IP and the subnet mask as two seperate entities when you can provide the same information in CIDR notation in your scripts. The following example below uses a Bro script to determine if a series of IP addresses are within a set of subnets using a 20 bit subnet mask. .. literalinclude:: ../../../../testing/btest/doc/manual/data_type_subnets.bro :language: bro From 7d583b6b78ab908159cbef1363d3e31e73d1fda0 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 8 Jan 2013 14:47:39 -0500 Subject: [PATCH 022/881] Vector declarations and explanations, including btests --- doc/user-manual/scripting.rst | 15 +++++++++------ .../.stdout | 4 ++++ .../manual/data_struct_vector_declaration.bro | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.data_struct_vector_declaration/.stdout create mode 100644 testing/btest/doc/manual/data_struct_vector_declaration.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 2b9332d8f9..09d1a1ef8d 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -202,14 +202,20 @@ Data Structures Vectors ~~~~~~~ -Similar to arrays, vectors in Bro use contiguous storage for their contents and as such the contents can be accessed using a zero indexed numerical offset. Each element in a vector is indexed by a count, starting and zero and progressing up to the current length of the list. While members of a vector must all be of the same type, the vector itself can grow dynamically. The format for the declaration of a vector follows the pattern of other declarations, namely, SCOPE v: vector of T where v is the name of your vector of T is the data type of its members. For example, the following snippet shows an explicit and implicit declaration of a vector. +If you're coming to Bro with a programming background, you may or may not be familiar with the Vector data type depending on your language of choice. On the surface, vectors perform much of the same functionality as arrays, but in truth they are more like associate arrays with zero indexed unsigned integers as the indecies. As such any time you need to sequentially store data of the same type, in Bro you'll have to reach for a vector. Vectors are a collection of objects, all of which are of the same data type, to which elements can be dynamically added or removed. Since Vectors use contiguous storage for their elements, the contents of a vector can be accessed through a zero indexed numerical offset. -.. literalinclude:: ../../../../testing/btest/doc/manual/data_struct_vector.bro +The format for the declaration of a Vector follows the pattern of other declarations, namely, "SCOPE v: vector of T" where v is the name of your vector of T is the data type of its members. For example, the following snippet shows an explicit and implicit declaration of two locally scoped vectors. The script populates the first vector by inserting values at the end by placing the vector name between two vertical pipes to get the Vector's current length before printing the contents of both Vectors and their current lengths. + +.. literalinclude:: ../../../../testing/btest/doc/manual/data_struct_vector_declaration.bro :language: bro :linenos: :lines: 6,7 - +.. btest:: data_type_const.bro + + @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_declaration.bro + +In a lot of cases, storing elements in a vector is simply a precursor to then iterating over them. Sets ~~~~ @@ -217,9 +223,6 @@ Sets Tables ~~~~~~ - While each of the network centric data types should be be familiar in the type of data they represent, seeing the data types in action can be a better starting point, to do so a basic understanding of Bro's data structures will be helpful and - - Data Types Revisited -------------------- diff --git a/testing/btest/Baseline/doc.manual.data_struct_vector_declaration/.stdout b/testing/btest/Baseline/doc.manual.data_struct_vector_declaration/.stdout new file mode 100644 index 0000000000..48ce5d9c56 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_struct_vector_declaration/.stdout @@ -0,0 +1,4 @@ +contents of v1: [1, 2, 3, 4] +length of v1: 4 +contents of v1: [1, 2, 3, 4] +length of v2: 4 diff --git a/testing/btest/doc/manual/data_struct_vector_declaration.bro b/testing/btest/doc/manual/data_struct_vector_declaration.bro new file mode 100644 index 0000000000..06fe48aeec --- /dev/null +++ b/testing/btest/doc/manual/data_struct_vector_declaration.bro @@ -0,0 +1,16 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local v1: vector of count; + local v2 = vector(1, 2, 3, 4); + v1[|v1|] = 1; + v1[|v1|] = 2; + v1[|v1|] = 3; + v1[|v1|] = 4; + print fmt("contents of v1: %s", v1); + print fmt("length of v1: %d", |v1|); + print fmt("contents of v1: %s", v2); + print fmt("length of v2: %d", |v2|); + } \ No newline at end of file From c453c228cb98a502bf809968875118d57a7853aa Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 8 Jan 2013 15:31:56 -0500 Subject: [PATCH 023/881] Iteration over vectors. --- doc/user-manual/scripting.rst | 16 ++++++++++++---- .../doc.manual.data_struct_vector_iter/.stdout | 3 +++ .../btest/doc/manual/data_struct_vector_iter.bro | 12 ++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.data_struct_vector_iter/.stdout create mode 100644 testing/btest/doc/manual/data_struct_vector_iter.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 09d1a1ef8d..fcb812ce20 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -196,8 +196,6 @@ The table below shows the common data types used in Bro, of which, the first fou | pattern | regular expression | +-----------+-------------------------------------+ -Data Structures ---------------- Vectors ~~~~~~~ @@ -209,13 +207,23 @@ The format for the declaration of a Vector follows the pattern of other declarat .. literalinclude:: ../../../../testing/btest/doc/manual/data_struct_vector_declaration.bro :language: bro :linenos: - :lines: 6,7 + :lines: 4-16 .. btest:: data_type_const.bro @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_declaration.bro -In a lot of cases, storing elements in a vector is simply a precursor to then iterating over them. +In a lot of cases, storing elements in a vector is simply a precursor to then iterating over them. Iterating over a vector is easy with the for keyword. The sample below iterates over a vector of IP addresses and for each IP address, masks that address with 18 bits. + +.. literalinclude:: ../../../../testing/btest/doc/manual/data_struct_vector_iter.bro + :language: bro + :linenos: + :lines: 4-12 + +.. btest:: data_type_const.bro + + @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_iter.bro + Sets ~~~~ diff --git a/testing/btest/Baseline/doc.manual.data_struct_vector_iter/.stdout b/testing/btest/Baseline/doc.manual.data_struct_vector_iter/.stdout new file mode 100644 index 0000000000..0326e6580e --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_struct_vector_iter/.stdout @@ -0,0 +1,3 @@ +1.2.0.0/18 +2.3.0.0/18 +3.4.0.0/18 diff --git a/testing/btest/doc/manual/data_struct_vector_iter.bro b/testing/btest/doc/manual/data_struct_vector_iter.bro new file mode 100644 index 0000000000..96574eab1b --- /dev/null +++ b/testing/btest/doc/manual/data_struct_vector_iter.bro @@ -0,0 +1,12 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local addr_vector: vector of addr = vector( 1.2.3.4, 2.3.4.5, 3.4.5.6); + + for (i in addr_vector) + { + print mask_addr(addr_vector[i], 18); + } + } From 01090cf09fe8d78e43a130fbf48a4184c12ee44b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 9 Jan 2013 11:16:43 -0600 Subject: [PATCH 024/881] Teach sphinx a new ".. rootedliteralinclude::" directive. It's like ".. literalinclude::" except the argument is an absolute path which may contain environment variables to be be expanded when generating documents. --- doc/conf.py.in | 5 ++++- doc/ext/rootedliteralinclude.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 doc/ext/rootedliteralinclude.py diff --git a/doc/conf.py.in b/doc/conf.py.in index e91b48d079..8ca8d70a7a 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -41,7 +41,10 @@ btest_tests="doc/sphinx" # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions += ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc'] +extensions += ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc', + 'rootedliteralinclude'] + +os.environ["BRO_SRC_ROOT"] = "@CMAKE_SOURCE_DIR@" # Add any paths that contain templates here, relative to this directory. templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static'] diff --git a/doc/ext/rootedliteralinclude.py b/doc/ext/rootedliteralinclude.py new file mode 100644 index 0000000000..7b4aea5547 --- /dev/null +++ b/doc/ext/rootedliteralinclude.py @@ -0,0 +1,25 @@ +import os +from sphinx.directives.code import LiteralInclude + +def setup(app): + app.add_directive('rootedliteralinclude', RootedLiteralInclude) + +class RootedLiteralInclude(LiteralInclude): + """ + Like ``.. literalinclude::``, but the argument is an absolute path + which may contain environment variables which will be expanded when + generating documents. + """ + + def run(self): + document = self.state.document + if not document.settings.file_insertion_enabled: + return [document.reporter.warning('File insertion disabled', + line=self.lineno)] + env = document.settings.env + + expanded_arg = os.path.expandvars(self.arguments[0]) + sphinx_src_relation = os.path.relpath(expanded_arg, env.srcdir) + self.arguments[0] = os.path.join(os.sep, sphinx_src_relation) + + return super(RootedLiteralInclude, self).run() From f9359ad40d488098839e782ea99bd2b489ce19e6 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Wed, 9 Jan 2013 14:23:09 -0500 Subject: [PATCH 025/881] Moving to new rootedliteralinclude directive. --- doc/user-manual/scripting.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index fcb812ce20..f56843dd57 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -89,7 +89,7 @@ While Bro is capable of packet level processing, its strengths lay in the contex Of the events listed, the event that will give us the best insight into the connection record data type will be connection_state_remove(). As detailed in the in-line documentation, Bro generates this event just before it decides to remove this event from memory, effectively forgetting about it. Let's take a look at a simple script that will output the connection record for a single connection. -.. literalinclude:: ../../../../testing/btest/doc/manual/connection_record_01.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_01.bro :language: bro :linenos: :lines: 4-9 @@ -104,7 +104,7 @@ As you can see from the output, the connection record is something of a jumble w Bro uses the dollar sign as it's field delimiter and a direct correlation exists between the output of the connection record and the proper format of a dereferenced variable in scripts. In the output of the script above, groups of information are collected between brackets, which would correspond to the $-delimiter in a Bro script. For example, the originating host is referenced by c$id$orig_h which breaks down to "orig_h which is a member of id which is a member of the data structure referred to as c that was passed into the event handler." Given that the responder port (c$id$resp_p) is 53/tcp, it's likely that Bro's base DNS scripts can further populate the connection record. Let's load the base/protocols/dns scripts and check the output of our script. -.. literalinclude:: ../../../../testing/btest/doc/manual/connection_record_02.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_02.bro :language: bro :linenos: :lines: 4-10 @@ -123,7 +123,7 @@ Scope Before embarking on a exploration of Bro's native Data Types and Data Structures, it's important to have a good grasp of the different levels of scope available in Bro and the appropriate times to use them within a script. The declarations of variables in Bro come in two forms. Variables can be declared with or without a definition in the form "SCOPE name: TYPE" or "SCOPE name = EXPRESSION" respectively; each of which produce the same result if EXPRESSION evaluates to the same type as TYPE. The decision as to which type of declaration to use is likely to be dictated by personal preference and readability. -.. literalinclude:: ../../../../testing/btest/doc/manual/data_type_declaration.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_declaration.bro :language: bro :linenos: :lines: 4-14 @@ -145,7 +145,7 @@ Constants The next level of scoping available in Bro are constants which are denoted by the "const" keyword. Unlike globals, constants can only be set or altered at parse time, afterwards (in runtime) the constants are unalterable. In most cases, constants are used in Bro scripts as containers for configuration options. The majority of constants defined are defined with the "&redef" attribute, making it such that the constant can be redefined. While the idea of a redefinable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the "&redef" attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added to the table through redef statements. The table is then printed in a bro_init() event. Were we to try to alter the table in an event handler, Bro would notify the user of an error and the script would fail. -.. literalinclude:: ../../../../testing/btest/doc/manual/data_type_const.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const.bro :language: bro :linenos: :lines: 4-12 @@ -159,7 +159,7 @@ Local Variables Whereas globals and constants are widely available in scriptland through various means, when a variable is defined with a local scope, its availability is restricted to the body of the event or function in which it was declared. Local variables tend to be used for values that are only needed within a specific scope and once the processing of a script passes beyond that scope and no longer used, the variable is deleted. While it is possible for a function to return a locally scoped variable, in doing so it retuns the value instead of the variable. Bro maintains a difference between variables an example of which is illustrated below. The script executes the event handler "bro_init()" which in turn calls the function "add_two(i: count)" with an argument of 10. Once Bro enters the add_two function, it provisions a locally scoped variable called "added_two" to hold the value of i+2, in this case, 12. The add_two function then prints the value of the added_two variable and returns its value to the bro_init() event handler. At this point, the variable "added_two" has fallen out of scope and no longer exists while the value 12 is still in use and stored in the locally scoped variable "test". When Bro finishes processing the bro_init function, the variable called "test" is no longer in scope and, since there exist no other references to the value "12", the value is also deleted. -.. literalinclude:: ../../../../testing/btest/doc/manual/data_type_local.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_local.bro :language: bro :linenos: :lines: 4-14 @@ -204,7 +204,7 @@ If you're coming to Bro with a programming background, you may or may not be fam The format for the declaration of a Vector follows the pattern of other declarations, namely, "SCOPE v: vector of T" where v is the name of your vector of T is the data type of its members. For example, the following snippet shows an explicit and implicit declaration of two locally scoped vectors. The script populates the first vector by inserting values at the end by placing the vector name between two vertical pipes to get the Vector's current length before printing the contents of both Vectors and their current lengths. -.. literalinclude:: ../../../../testing/btest/doc/manual/data_struct_vector_declaration.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_vector_declaration.bro :language: bro :linenos: :lines: 4-16 @@ -213,9 +213,9 @@ The format for the declaration of a Vector follows the pattern of other declarat @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_declaration.bro -In a lot of cases, storing elements in a vector is simply a precursor to then iterating over them. Iterating over a vector is easy with the for keyword. The sample below iterates over a vector of IP addresses and for each IP address, masks that address with 18 bits. +In a lot of cases, storing elements in a vector is simply a precursor to then iterating over them. Iterating over a vector is easy with the for keyword. The sample below iterates over a vector of IP addresses and for each IP address, masks that address with 18 bits. The for keyword is used to generate a locally scoped variable called "i" which will hold the index of the current element in the vector. Using i as an index to addr_vector we can access the current item in the vector with addr_vector[i]. -.. literalinclude:: ../../../../testing/btest/doc/manual/data_struct_vector_iter.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_vector_iter.bro :language: bro :linenos: :lines: 4-12 From 52eae050d84983a8e3cf0eacd4c4c9d0b843d57f Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 20 Jan 2013 00:27:04 -0500 Subject: [PATCH 026/881] documentation of Sets. --- doc/user-manual/scripting.rst | 13 ++++++++++++ .../.stdout | 6 ++++++ .../manual/data_struct_set_declaration.bro | 21 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 testing/btest/Baseline/doc.manual.data_struct_set_declaration/.stdout create mode 100644 testing/btest/doc/manual/data_struct_set_declaration.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index f56843dd57..0bca035562 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -228,9 +228,22 @@ In a lot of cases, storing elements in a vector is simply a precursor to then it Sets ~~~~ +Sets, like Vectors, are containers which store elements in a specific order. Unlike Vectors though, all elements in a Set are unique, making them the perfect resource for collections where each element is naturally unique such as IP addresses, ports and subnets. Sets even share a good number of syntactic elements with Vectors such as assignments and constructors. Their declarations however, are different. Where as Vectors are declared with the use of the "of" keyword, Sets are declared using squared brackets. As such, a set of ports would be declared as "set[port]". Insertion and deletion of data into a set is performed by the add and delete keywords respectively while accessing data is again similar to Vectors and uses the squared brackets. The sample below shows the use of a Set to hold various SSL based protocols. First a local Set is declared named my_ports then in lines 8, 10 and 12, we use the add keyword to insert data for the SSH, HTTPS and IMAPS. In lines 15-18 an if statement is used to check whether the SMTPS port is currently in the my_ports set and if not, it is added. Finally, on line 20, the set is printed to stdout. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro + :language: bro + :linenos: + :lines: 4-21 + +.. btest:: connection-record-02 + + @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_set_declaration.bro + Tables ~~~~~~ + + Data Types Revisited -------------------- diff --git a/testing/btest/Baseline/doc.manual.data_struct_set_declaration/.stdout b/testing/btest/Baseline/doc.manual.data_struct_set_declaration/.stdout new file mode 100644 index 0000000000..f65e42a225 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_struct_set_declaration/.stdout @@ -0,0 +1,6 @@ +{ +993/tcp, +22/tcp, +587/tcp, +443/tcp +} diff --git a/testing/btest/doc/manual/data_struct_set_declaration.bro b/testing/btest/doc/manual/data_struct_set_declaration.bro new file mode 100644 index 0000000000..51aa4cad11 --- /dev/null +++ b/testing/btest/doc/manual/data_struct_set_declaration.bro @@ -0,0 +1,21 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local my_ports: set[port]; + # SSH + add my_ports[22/tcp]; + # HTTPS + add my_ports[443/tcp]; + # IMAPS + add my_ports[993/tcp]; + + # Check for SMTPS + if ( 587/tcp !in my_ports ) + { + add my_ports[587/tcp]; + } + + print my_ports; + } \ No newline at end of file From 61e95e8d4ed8b8910407a5f51d92fa560cb9fd5d Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 21 Jan 2013 00:19:29 -0500 Subject: [PATCH 027/881] Reorganize to introduce sets, then tables, then vectors. Rewrite of the section on sets. Start of discussion on tables. --- doc/user-manual/scripting.rst | 71 ++++++++++++++----- .../.stdout | 14 ++-- .../.stdout | 4 ++ .../manual/data_struct_set_declaration.bro | 23 ++++-- .../manual/data_struct_table_declaration.bro | 19 +++++ 5 files changed, 100 insertions(+), 31 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.data_struct_table_declaration/.stdout create mode 100644 testing/btest/doc/manual/data_struct_table_declaration.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 0bca035562..fe4061ec61 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -196,6 +196,59 @@ The table below shows the common data types used in Bro, of which, the first fou | pattern | regular expression | +-----------+-------------------------------------+ +Sets +~~~~ + +Sets in Bro are used to stored a unique elements of the same data type. In essence, you can think of them as "a unique set of integers" or "a unique set of ip addresses". While the declaration of a set may differ based on the data type being collected, the set will always contain unique elements and the elements in the set will always be of the same data type. Such requirements make the set data type perfect for information that is already naturally unique such as ports or ip addresses. The code snippet below shows both an explicit and implicit declaration of a locally scoped set. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro + :language: bro + :linenos: + :lines: 6,7 + +As you can see, sets are declared using the format "SCOPE var_name: set[TYPE]". Adding and removing elements in a set is achieved using the add and delete statements. Once you have elements inserted into the set, it's likely that you'll need to either iterate over that set or test for membership within the set, both of which are covered by the in operator. In the case of iterating over a set, combining the for statement and the in operator will allow you to sequentially process each element of the set as seen below. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro + :language: bro + :linenos: + :lines: 21-29 + +Here, the for statement loops over the contents of the set storing each element in the temporary variable "i". With each iteration of the for loop, the next element is chosen. Since sets are not an ordered data type, you cannot guarantee the order of the elements as the for loop processes. + +To test for membership in a set the in statment can be combined with an if statement to return a true or false value. If the exact element in the condition is already in the set, the condition returns true and the body executes. The in statement can also be negated by the ! operator to create the inverse of the condition. While line 16 of the code snippet below could be rewrite as "if (!( 587/tcp in ssl_ports ))" try to avoid using this construct; instead, negate the in operator itself. While the functionality is the same, using the latter is a more natural construct and will aid in the readability of your script. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro + :language: bro + :linenos: + :lines: 15-19 + +You can see the full script and its output below. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro + :language: bro + :linenos: + :lines: 4-21 + +.. btest:: connection-record-02 + + @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_set_declaration.bro + +Tables +~~~~~~ + +A table in Bro is a mapping of a key to a value or yield. While the values don't have to be unique, each key in the table must be unique to preserve a one-to-one mapping of keys to values. In the example below, we've compiled a table of SSL enable services and their common ports. The explicit declaration and constructor for the table on lines 6 and 7 lay out the data types of the keys (strings) and the data types of the yields (ports) and then fill in some sample key and yeild pairs. Line 8 shows how to use a table accessor to insert one key-yield pair into the table. When using the in operator on a table, you are effectively working with the keys of the table. In the case of an inf statement, the in operator will check for membership among the set of keys and return a true or false value. As seen on line 10, we are checking if "SMTPS" is not in the set of keys for the ssl_services table and if the condition holds true, we add the key-yield pair to the table. In the case of a for statement, as seen on line 15, we iterate over each key currently in the table. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_declaration.bro + :language: bro + :linenos: + :lines: 4-21 + +.. btest:: connection-record-02 + + @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_declaration.bro + +Simple examples aside, Tables can become extremely complex as the keys and values for the table become more intricate. The flexability gained with the use of Tables in Bro implies a cost in complexity for the person writing the scripts. + Vectors ~~~~~~~ @@ -225,24 +278,6 @@ In a lot of cases, storing elements in a vector is simply a precursor to then it @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_iter.bro -Sets -~~~~ - -Sets, like Vectors, are containers which store elements in a specific order. Unlike Vectors though, all elements in a Set are unique, making them the perfect resource for collections where each element is naturally unique such as IP addresses, ports and subnets. Sets even share a good number of syntactic elements with Vectors such as assignments and constructors. Their declarations however, are different. Where as Vectors are declared with the use of the "of" keyword, Sets are declared using squared brackets. As such, a set of ports would be declared as "set[port]". Insertion and deletion of data into a set is performed by the add and delete keywords respectively while accessing data is again similar to Vectors and uses the squared brackets. The sample below shows the use of a Set to hold various SSL based protocols. First a local Set is declared named my_ports then in lines 8, 10 and 12, we use the add keyword to insert data for the SSH, HTTPS and IMAPS. In lines 15-18 an if statement is used to check whether the SMTPS port is currently in the my_ports set and if not, it is added. Finally, on line 20, the set is printed to stdout. - -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro - :language: bro - :linenos: - :lines: 4-21 - -.. btest:: connection-record-02 - - @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_set_declaration.bro - -Tables -~~~~~~ - - Data Types Revisited -------------------- diff --git a/testing/btest/Baseline/doc.manual.data_struct_set_declaration/.stdout b/testing/btest/Baseline/doc.manual.data_struct_set_declaration/.stdout index f65e42a225..d1aa16c7d3 100644 --- a/testing/btest/Baseline/doc.manual.data_struct_set_declaration/.stdout +++ b/testing/btest/Baseline/doc.manual.data_struct_set_declaration/.stdout @@ -1,6 +1,8 @@ -{ -993/tcp, -22/tcp, -587/tcp, -443/tcp -} +SSL Port: 993/tcp +SSL Port: 22/tcp +SSL Port: 587/tcp +SSL Port: 443/tcp +Non-SSL Port: 143/tcp +Non-SSL Port: 25/tcp +Non-SSL Port: 80/tcp +Non-SSL Port: 23/tcp diff --git a/testing/btest/Baseline/doc.manual.data_struct_table_declaration/.stdout b/testing/btest/Baseline/doc.manual.data_struct_table_declaration/.stdout new file mode 100644 index 0000000000..19b1648904 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_struct_table_declaration/.stdout @@ -0,0 +1,4 @@ +Service Name: IMAPS - Common Port: 993/tcp +Service Name: HTTPS - Common Port: 443/tcp +Service Name: SSH - Common Port: 22/tcp +Service Name: SMTPS - Common Port: 587/tcp diff --git a/testing/btest/doc/manual/data_struct_set_declaration.bro b/testing/btest/doc/manual/data_struct_set_declaration.bro index 51aa4cad11..269cb3d328 100644 --- a/testing/btest/doc/manual/data_struct_set_declaration.bro +++ b/testing/btest/doc/manual/data_struct_set_declaration.bro @@ -3,19 +3,28 @@ event bro_init() { - local my_ports: set[port]; + local ssl_ports: set[port]; + local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp ); # SSH - add my_ports[22/tcp]; + add ssl_ports[22/tcp]; # HTTPS - add my_ports[443/tcp]; + add ssl_ports[443/tcp]; # IMAPS - add my_ports[993/tcp]; + add ssl_ports[993/tcp]; # Check for SMTPS - if ( 587/tcp !in my_ports ) + if ( 587/tcp !in ssl_ports ) { - add my_ports[587/tcp]; + add ssl_ports[587/tcp]; } - print my_ports; + for ( i in ssl_ports ) + { + print fmt("SSL Port: %s", i); + } + + for ( i in non_ssl_ports ) + { + print fmt("Non-SSL Port: %s", i); + } } \ No newline at end of file diff --git a/testing/btest/doc/manual/data_struct_table_declaration.bro b/testing/btest/doc/manual/data_struct_table_declaration.bro new file mode 100644 index 0000000000..36abd0db1b --- /dev/null +++ b/testing/btest/doc/manual/data_struct_table_declaration.bro @@ -0,0 +1,19 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local ssl_services: table[string] of port; + ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp); + ssl_services["IMAPS"] = 993/tcp; + + if ( "SMTPS" !in ssl_services ) + { + ssl_services["SMTPS"] = 587/tcp; + } + + for ( k in ssl_services ) + { + print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]); + } + } \ No newline at end of file From adfae5448fe5a583b448a754ccb697b8d3690668 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 22 Jan 2013 23:37:43 -0500 Subject: [PATCH 028/881] Tables with aggregate keys. --- doc/user-manual/scripting.rst | 20 ++++++++++++++----- .../.stdout | 4 ++++ .../doc/manual/data_struct_table_complex.bro | 17 ++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.data_struct_table_complex/.stdout create mode 100644 testing/btest/doc/manual/data_struct_table_complex.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index fe4061ec61..9357bfd1c2 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -229,7 +229,7 @@ You can see the full script and its output below. :linenos: :lines: 4-21 -.. btest:: connection-record-02 +.. btest:: data_struct_set_declaration @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_set_declaration.bro @@ -243,12 +243,22 @@ A table in Bro is a mapping of a key to a value or yield. While the values don' :linenos: :lines: 4-21 -.. btest:: connection-record-02 +.. btest:: data_struct_table_declaration @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_declaration.bro -Simple examples aside, Tables can become extremely complex as the keys and values for the table become more intricate. The flexability gained with the use of Tables in Bro implies a cost in complexity for the person writing the scripts. +Simple examples aside, tables can become extremely complex as the keys and values for the table become more intricate. Tables can have keys comprised of multiple data types, other data structures, and even of tables themselves. The flexibility gained with the use of complex tables in Bro implies a cost in complexity for the person writing the scripts but pays off in effectiveness given the power of Bro as a network security platform. +The script below shows a sample table of strings indexed by two strings, a count, and a final string. With multiple entities acting as an aggregate key, the order is the important as a change in order would result in a new key. Here, we're using the table to track the Director, Studio, year or release, and lead actor in a series of samurai flicks. It's important to note that in the case of the for statement, it's an all or nothing kind of iteration. We cannot iterate over, say, the directors; We have to iterate with the exact format as the keys themselves. In this case, we need squared brackets surrounding four temporary variables to act as a collection for our iteration. While this is a contrived example, we could easily have had keys containin ip addresses(addr), ports(port) and even a string calculated as the result of a reverse hostname lookup. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_complex.bro + :language: bro + :linenos: + :lines: 4-21 + +.. btest:: data_struct_table_complex + + @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_complex.bro Vectors ~~~~~~~ @@ -262,7 +272,7 @@ The format for the declaration of a Vector follows the pattern of other declarat :linenos: :lines: 4-16 -.. btest:: data_type_const.bro +.. btest:: data_struct_vector_declaration @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_declaration.bro @@ -273,7 +283,7 @@ In a lot of cases, storing elements in a vector is simply a precursor to then it :linenos: :lines: 4-12 -.. btest:: data_type_const.bro +.. btest:: data_struct_vector_iter @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_iter.bro diff --git a/testing/btest/Baseline/doc.manual.data_struct_table_complex/.stdout b/testing/btest/Baseline/doc.manual.data_struct_table_complex/.stdout new file mode 100644 index 0000000000..e22f36a244 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_struct_table_complex/.stdout @@ -0,0 +1,4 @@ +Kiru was released in 1968 by Toho studios, directed by Kihachi Okamoto and starring Tatsuya Nakadai +Goyokin was released in 1969 by Fuji studios, directed by Hideo Gosha and starring Tatsuya Nakadai +Harakiri was released in 1962 by Shochiku Eiga studios, directed by Masaki Kobayashi and starring Tatsuya Nakadai +Tasogare Seibei was released in 2002 by Eisei Gekijo studios, directed by Yoji Yamada and starring Hiroyuki Sanada diff --git a/testing/btest/doc/manual/data_struct_table_complex.bro b/testing/btest/doc/manual/data_struct_table_complex.bro new file mode 100644 index 0000000000..4ecd51aace --- /dev/null +++ b/testing/btest/doc/manual/data_struct_table_complex.bro @@ -0,0 +1,17 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local samurai_flicks: table[string, string, count, string] of string; + samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru"; + samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin"; + samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri"; + samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei"; + + for ( [d, s, y, a] in samurai_flicks ) + { + print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a); + } + } + From 2fd187f991b688510867219d404c72ad489472ad Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Wed, 6 Feb 2013 01:22:42 -0500 Subject: [PATCH 029/881] Start to integrate suggestions from Robin --- doc/user-manual/scripting.rst | 38 ++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 9357bfd1c2..d45b322add 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -23,7 +23,7 @@ Understanding Bro Scripts Bro includes an event queue driven scripting language that provides the primary means for an organization to extend and customize Bro's functionality. An overwhelming amount of the output generated by Bro is, in fact, generated by Bro scripts. It's almost easier to consider Bro to be an entity behind-the-scenes processing connections and generating events while Bro's scripting language is the medium through which we mere mortals can achieve communication. Bro scripts effectively notify Bro that should there be an event of a type we define, then let us have the information about the connection so we can perform some function on it. For example, the ssl.log file is generated by a Bro script that walks the entire certificate chain and issues notifications if any of the steps along the certificate chain are invalid. This entire process is setup by telling Bro that should it see a server or client issue an SSL HELLO message, we want to know about the information about that connection. -It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru Malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. Team Cymru also populates the TXT record of their DNS responses with both a "last seen" timestamp and a numerical "detection rate". The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script detect-MHR.bro is responsible for generating the appropriate DNS lookup and parsing the response. +It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru Malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. Team Cymru also populates the TXT record of their DNS responses with both a "last seen" timestamp and a numerical "detection rate". The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script ``detect-MHR.bro`` is responsible for generating the appropriate DNS lookup and parsing the response. .. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro @@ -37,14 +37,14 @@ Visually, there are three distinct sections of the script. A base level with no :linenos: :lines: 7-11 -Lines 7 and 8 of the script process the __load__.bro script in the respective directories being loaded. In a full production deployment of Bro it's likely that these files would already be loaded and their contents made available to the script, but including them explicitly ensures that Bro can be run in modes such as "bare" and still have scripts that reliably work. Consider it a "best practice" to include appropriate @load statments when possible. +Lines 7 and 8 of the script process the ``__load__.bro`` script in the respective directories being loaded. The ``@load`` directives are often considered good practice or even just good manners when writing Bro scripts that might be distributed. While it's unlikely that in a full production deployment of Bro these additional resources wouldn't already be loaded, it's not a bad habit to try to get into as you get more experienced with Bro scripting. If you're just starting out, this level of granularity might not be entirely necessary though. .. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: :lines: 12-24 -The export section redefines an enumerable constant that describes the type of notice we will generate with the logging framework. The notice type listed allows for the use of the NOTICE() function to generate notices of type Malware_Hash_Registry_Match as done in the next section. +The export section redefines an enumerable constant that describes the type of notice we will generate with the logging framework. Bro allows for redefinable constants, which at first, might seem counter-intuitive. We'll get more indepth with constants in a later chapter, for now, think of them as variables that can only be altered before Bro starts running. The notice type listed allows for the use of the NOTICE() function to generate notices of type Malware_Hash_Registry_Match as done in the next section. Notices allow Bro to generate some kind of extra notification beyond its default log types. Often times, this extra notification comes in the form of an email generated and sent to a pre-configured address. .. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro @@ -64,21 +64,21 @@ The Event Queue and Event Handlers Bro's scripting language is event driven which is a gear change from the majority of scripting languages with which most users will have previous experience. Scripting in Bro depends on handling the events generated by Bro as it processes network traffic, altering the state of data structures through those events, and making decisions on the information provided. This approach to scripting can often cause confusion to users who come to Bro from a procedural or functional language, but once the initial shock wears off it becomes more clear with each exposure. -Bro's core acts to place events into an ordered "Event Queue", allowing event handlers to process them on a first-come-first-serve basis. In effect, this is Bro's core functionality as without the scripts written to perform discrete actions on events, there would be little to no usable output. As such, a basic understanding of the Event Queue, the Events being generated, and the way in which Event Handlers process those events is a basis for not only learning to write scripts for Bro but for understanding Bro itself. +Bro's core acts to place events into an ordered "event queue", allowing event handlers to process them on a first-come-first-serve basis. In effect, this is Bro's core functionality as without the scripts written to perform discrete actions on events, there would be little to no usable output. As such, a basic understanding of the event queue, the events being generated, and the way in which event handlers process those events is a basis for not only learning to write scripts for Bro but for understanding Bro itself. -Gaining familiarity with the specific events generated by Bro is a big step towards building a mind set for working with Bro scripts. The majority of events generated by Bro are defined in the built-in-function files or .bif files which also act as the basis for online event documentation. Whether starting a script from scratch or reading and maintaining someone else's script, having the built-in event definitions available is an excellent resource to have on hand. Before release version 2.0 the Bro developers put significant effort into organization and documentation of every event. This effort resulted in built-in-function files organized such that each entry contains a descriptive event name, the arguments passed to the event, and a concise explanation of the functions use. +Gaining familiarity with the specific events generated by Bro is a big step towards building a mind set for working with Bro scripts. The majority of events generated by Bro are defined in the built-in-function files or .bif files which also act as the basis for online event documentation. These in-line comments are compiled into an online documentation system using Broxygen. Whether starting a script from scratch or reading and maintaining someone else's script, having the built-in event definitions available is an excellent resource to have on hand. For the 2.0 release the Bro developers put significant effort into organization and documentation of every event. This effort resulted in built-in-function files organized such that each entry contains a descriptive event name, the arguments passed to the event, and a concise explanation of the functions use. .. literalinclude:: ../../../../build/src/base/event.bif.bro :language: bro :linenos: :lines: 4124-4149 -Above is a segment of event.bif.bro showing the documentation for the event dns_request(). It's organized such that the documentation, commentary, and list of arguments precede the actual event definition used by Bro. As Bro detects DNS requests being issued by an originator, it issues this event and any number of scripts then have access to the data Bro passes along with the event. In this example, Bro passes not only the message, the query, query type and query class for the DNS request, but also a then record used for the connection itself. +Above is a segment of ``event.bif.bro`` showing the documentation for the event dns_request(). It's organized such that the documentation, commentary, and list of arguments precede the actual event definition used by Bro. As Bro detects DNS requests being issued by an originator, it issues this event and any number of scripts then have access to the data Bro passes along with the event. In this example, Bro passes not only the message, the query, query type and query class for the DNS request, but also a then record used for the connection itself. The Connection Record Data Type =============================== -Of all the events defined in Bro's event.bif.bro file, an overwhelmingly large number of them are passed the connection record data type, in effect, making it the backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. Let's walk through the process of selecting an appropriate event, generating some output to standard out and dissecting the connection record so as to get an overview of it. We will cover data types in more detail later. +Of all the events defined in Bro's ``event.bif.bro`` file, an overwhelmingly large number of them are passed the connection record data type, in effect, making it the backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. Let's walk through the process of selecting an appropriate event, generating some output to standard out and dissecting the connection record so as to get an overview of it. We will cover data types in more detail later. While Bro is capable of packet level processing, its strengths lay in the context of a connection between an originator and a responder. As such, there are events defined for the primary parts of the connection life-cycle as you'll see from the small selection of connection-related events below. @@ -94,7 +94,7 @@ Of the events listed, the event that will give us the best insight into the conn :linenos: :lines: 4-9 -Again, we start with @load, this time importing the base/protocols/conn scripts which supply the tracking and logging of general information and state of connections. We handle the connection_state_remove() event and simply print the contents of the argument passed to it. For this example we're going to run Bro in "bare mode" which loads only the minimum number of scripts to retain operability and leaves the burden of loading required scripts to the script being run. This will give us a chance to see the contents of the connection record without it being overly populated. +Again, we start with @load, this time importing the base/protocols/conn scripts which supply the tracking and logging of general information and state of connections. We handle the connection_state_remove() event and simply print the contents of the argument passed to it. For this example we're going to run Bro in "bare mode" which loads only the minimum number of scripts to retain operability and leaves the burden of loading required scripts to the script being run. While bare mode is a low level functionality incorporated into Bro, in this case, we're going to use it to demonstrate how different features of Bro add more and more layers of information about a connection. This will give us a chance to see the contents of the connection record without it being overly populated. .. btest:: connection-record-01 @@ -102,7 +102,9 @@ Again, we start with @load, this time importing the base/protocols/conn scripts As you can see from the output, the connection record is something of a jumble when printed on its own. Regularly taking a peek at a populated connection record helps to understand the relationship between its fields as well as allowing an opportunity to build a frame of reference for accessing data in a script. -Bro uses the dollar sign as it's field delimiter and a direct correlation exists between the output of the connection record and the proper format of a dereferenced variable in scripts. In the output of the script above, groups of information are collected between brackets, which would correspond to the $-delimiter in a Bro script. For example, the originating host is referenced by c$id$orig_h which breaks down to "orig_h which is a member of id which is a member of the data structure referred to as c that was passed into the event handler." Given that the responder port (c$id$resp_p) is 53/tcp, it's likely that Bro's base DNS scripts can further populate the connection record. Let's load the base/protocols/dns scripts and check the output of our script. +Bro makes extensive use of nested data structures to store state and information gleaned from the analysis of a connection as a complete unit. To break down this collection of information, you will have to make use of use Bro's field delimiter the "$". For example, the originating host is referenced by c$id$orig_h which if given a narritive relates to "``orig_h`` which is a member of ``id`` which is a member of the data structure referred to as ``c`` that was passed into the event handler." Given that the responder port (``c$id$resp_p``) is 53/tcp, it's likely that Bro's base DNS scripts can further populate the connection record. Let's load the ``base/protocols/dns`` scripts and check the output of our script. + +Bro uses the dollar sign as its field delimiter and a direct correlation exists between the output of the connection record and the proper format of a dereferenced variable in scripts. In the output of the script above, groups of information are collected between brackets, which would correspond to the $-delimiter in a Bro script. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_02.bro :language: bro @@ -113,7 +115,7 @@ Bro uses the dollar sign as it's field delimiter and a direct correlation exists @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_02.bro -The addition of the base/protocols/dns scripts populates the dns=[] member of the connection record. While Bro is doing a massive amount of work in the background, it is in what is commonly called "script land" that details are being refined and decisions being made. Were we to continue running in "bare mode" we could slowly keep adding infrastructure through @load statements. For example, were we to load base/frameworks/logging, Bro would generate a conn.log and dns.log for us in the current working directory. Not only is it good practice to include appropriate load statements in your scripts, but it also helps to illuminate the various functionalities within Bro's scripting language. +The addition of the ``base/protocols/dns`` scripts populates the dns=[] member of the connection record. While Bro is doing a massive amount of work in the background, it is in what is commonly called "script land" that details are being refined and decisions being made. Were we to continue running in "bare mode" we could slowly keep adding infrastructure through ``@load`` statements. For example, were we to ``@load base/frameworks/logging``, Bro would generate a conn.log and dns.log for us in the current working directory. As mentioned above, including the appropriate ``@load`` statements is not only good practice, but can also help to indicate which functionalities are being used in a script. Data Types and Data Structures ============================== @@ -131,7 +133,7 @@ Before embarking on a exploration of Bro's native Data Types and Data Structures Global Variables ~~~~~~~~~~~~~~~~ -A global variable is used when the state of variable needs to be tracked, not surprisingly, globally. While there are some caveats, when a script declares a variable using the global scope, that script is granting access to that variable from other scripts. The declaration below, is a taken from the known-hosts.bro script and declares a variable called "known_hosts"" as a global set of unique ip addresses(line 32) within the "Known" namespace (line 8) and exports it (line 10) for use outside of the "Known" namespace. Were we to want to use the "known_hosts" variable we'd be able to access it through "Known::known_hosts". +A global variable is used when the state of variable needs to be tracked, not surprisingly, globally. While there are some caveats, when a script declares a variable using the global scope, that script is granting access to that variable from other scripts. The declaration below, is a taken from the ``known-hosts.bro`` script and declares a variable called "known_hosts"" as a global set of unique ip addresses(line 32) within the "Known" namespace (line 8) and exports it (line 10) for use outside of the "Known" namespace. Were we to want to use the "known_hosts" variable we'd be able to access it through "Known::known_hosts". .. literalinclude:: ../scripts/policy/protocols/conn/known-hosts.bro :language: bro @@ -143,7 +145,7 @@ The sample above also makes use of an export{} block. When the module keyword i Constants ~~~~~~~~~ -The next level of scoping available in Bro are constants which are denoted by the "const" keyword. Unlike globals, constants can only be set or altered at parse time, afterwards (in runtime) the constants are unalterable. In most cases, constants are used in Bro scripts as containers for configuration options. The majority of constants defined are defined with the "&redef" attribute, making it such that the constant can be redefined. While the idea of a redefinable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the "&redef" attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added to the table through redef statements. The table is then printed in a bro_init() event. Were we to try to alter the table in an event handler, Bro would notify the user of an error and the script would fail. +Bro also makes use of constants which are denoted by the "const" keyword. Unlike globals, constants can only be set or altered at parse time, afterwards (in runtime) the constants are unalterable. In most cases, constants are used in Bro scripts as containers for configuration options. The majority of constants defined are defined with the "&redef" attribute, making it such that the constant can be redefined. While the idea of a redefinable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the "&redef" attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added to the table through redef statements. The table is then printed in a bro_init() event. Were we to try to alter the table in an event handler, Bro would notify the user of an error and the script would fail. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const.bro :language: bro @@ -170,7 +172,7 @@ Data Structures It's difficult to talk about Bro's data types in a practical manner without first covering the data structures available in Bro. Some of the more interesting characteristics of data types are revealed when used inside of a data structure, but given that data structures are made up of data types, it devolved rather quickly into a "chicken-and-egg"" problem. As such, we'll introduce data types from bird's eye view before diving into data structures and from there a more complete exploration of data types. -The table below shows the common data types used in Bro, of which, the first four should seem familiar if you have some scripting experience, while the remaining six are less common in other languages. It should come as no surprise that a scripting language for a Network Security Monitoring platform has a fairly robust set of network centric data types and taking note of them here may well save you a late night of reinventing the wheel. +The table below shows the atomic types used in Bro, of which, the first four should seem familiar if you have some scripting experience, while the remaining six are less common in other languages. It should come as no surprise that a scripting language for a Network Security Monitoring platform has a fairly robust set of network centric data types and taking note of them here may well save you a late night of reinventing the wheel. +-----------+-------------------------------------+ | Data Type | Description | @@ -215,7 +217,7 @@ As you can see, sets are declared using the format "SCOPE var_name: set[TYPE]". Here, the for statement loops over the contents of the set storing each element in the temporary variable "i". With each iteration of the for loop, the next element is chosen. Since sets are not an ordered data type, you cannot guarantee the order of the elements as the for loop processes. -To test for membership in a set the in statment can be combined with an if statement to return a true or false value. If the exact element in the condition is already in the set, the condition returns true and the body executes. The in statement can also be negated by the ! operator to create the inverse of the condition. While line 16 of the code snippet below could be rewrite as "if (!( 587/tcp in ssl_ports ))" try to avoid using this construct; instead, negate the in operator itself. While the functionality is the same, using the latter is a more natural construct and will aid in the readability of your script. +To test for membership in a set the in statment can be combined with an if statement to return a true or false value. If the exact element in the condition is already in the set, the condition returns true and the body executes. The in statement can also be negated by the ! operator to create the inverse of the condition. While line 16 of the code snippet below could be rewrite as "if (!( 587/tcp in ssl_ports ))" try to avoid using this construct; instead, negate the in operator itself. While the functionality is the same, using the "!in" is more efficient as well as a more natural construct which will aid in the readability of your script. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro :language: bro @@ -236,7 +238,7 @@ You can see the full script and its output below. Tables ~~~~~~ -A table in Bro is a mapping of a key to a value or yield. While the values don't have to be unique, each key in the table must be unique to preserve a one-to-one mapping of keys to values. In the example below, we've compiled a table of SSL enable services and their common ports. The explicit declaration and constructor for the table on lines 6 and 7 lay out the data types of the keys (strings) and the data types of the yields (ports) and then fill in some sample key and yeild pairs. Line 8 shows how to use a table accessor to insert one key-yield pair into the table. When using the in operator on a table, you are effectively working with the keys of the table. In the case of an inf statement, the in operator will check for membership among the set of keys and return a true or false value. As seen on line 10, we are checking if "SMTPS" is not in the set of keys for the ssl_services table and if the condition holds true, we add the key-yield pair to the table. In the case of a for statement, as seen on line 15, we iterate over each key currently in the table. +A table in Bro is a mapping of a key to a value or yield. While the values don't have to be unique, each key in the table must be unique to preserve a one-to-one mapping of keys to values. In the example below, we've compiled a table of SSL enable services and their common ports. The explicit declaration and constructor for the table on lines 3 and 4 lay out the data types of the keys (strings) and the data types of the yields (ports) and then fill in some sample key and yeild pairs. Line 5 shows how to use a table accessor to insert one key-yield pair into the table. When using the in operator on a table, you are effectively working with the keys of the table. In the case of an inf statement, the in operator will check for membership among the set of keys and return a true or false value. As seen on line 7, we are checking if "SMTPS" is not in the set of keys for the ssl_services table and if the condition holds true, we add the key-yield pair to the table. Line 12 shows the use of a for statement to iterate over each key currently in the table. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_declaration.bro :language: bro @@ -247,9 +249,9 @@ A table in Bro is a mapping of a key to a value or yield. While the values don' @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_declaration.bro -Simple examples aside, tables can become extremely complex as the keys and values for the table become more intricate. Tables can have keys comprised of multiple data types, other data structures, and even of tables themselves. The flexibility gained with the use of complex tables in Bro implies a cost in complexity for the person writing the scripts but pays off in effectiveness given the power of Bro as a network security platform. +Simple examples aside, tables can become extremely complex as the keys and values for the table become more intricate. Tables can have keys comprised of multiple data types and even a series of elements called a 'tuple'. The flexibility gained with the use of complex tables in Bro implies a cost in complexity for the person writing the scripts but pays off in effectiveness given the power of Bro as a network security platform. -The script below shows a sample table of strings indexed by two strings, a count, and a final string. With multiple entities acting as an aggregate key, the order is the important as a change in order would result in a new key. Here, we're using the table to track the Director, Studio, year or release, and lead actor in a series of samurai flicks. It's important to note that in the case of the for statement, it's an all or nothing kind of iteration. We cannot iterate over, say, the directors; We have to iterate with the exact format as the keys themselves. In this case, we need squared brackets surrounding four temporary variables to act as a collection for our iteration. While this is a contrived example, we could easily have had keys containin ip addresses(addr), ports(port) and even a string calculated as the result of a reverse hostname lookup. +The script below shows a sample table of strings indexed by two strings, a count, and a final string. With a tuple acting as an aggregate key, the order is the important as a change in order would result in a new key. Here, we're using the table to track the Director, Studio, year or release, and lead actor in a series of samurai flicks. It's important to note that in the case of the for statement, it's an all or nothing kind of iteration. We cannot iterate over, say, the directors; We have to iterate with the exact format as the keys themselves. In this case, we need squared brackets surrounding four temporary variables to act as a collection for our iteration. While this is a contrived example, we could easily have had keys containin ip addresses(addr), ports(port) and even a string calculated as the result of a reverse hostname lookup. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_complex.bro :language: bro @@ -263,7 +265,7 @@ The script below shows a sample table of strings indexed by two strings, a count Vectors ~~~~~~~ -If you're coming to Bro with a programming background, you may or may not be familiar with the Vector data type depending on your language of choice. On the surface, vectors perform much of the same functionality as arrays, but in truth they are more like associate arrays with zero indexed unsigned integers as the indecies. As such any time you need to sequentially store data of the same type, in Bro you'll have to reach for a vector. Vectors are a collection of objects, all of which are of the same data type, to which elements can be dynamically added or removed. Since Vectors use contiguous storage for their elements, the contents of a vector can be accessed through a zero indexed numerical offset. +If you're coming to Bro with a programming background, you may or may not be familiar with the Vector data type depending on your language of choice. On the surface, vectors perform much of the same functionality as arrays, but in truth they are more like associative arrays with zero indexed unsigned integers as the indecies. As such any time you need to sequentially store data of the same type, in Bro you'll have to reach for a vector. Vectors are a collection of objects, all of which are of the same data type, to which elements can be dynamically added or removed. Since Vectors use contiguous storage for their elements, the contents of a vector can be accessed through a zero indexed numerical offset. The format for the declaration of a Vector follows the pattern of other declarations, namely, "SCOPE v: vector of T" where v is the name of your vector of T is the data type of its members. For example, the following snippet shows an explicit and implicit declaration of two locally scoped vectors. The script populates the first vector by inserting values at the end by placing the vector name between two vertical pipes to get the Vector's current length before printing the contents of both Vectors and their current lengths. From 614f85259a8faae37c683dd8a14a409b6ac24f70 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Thu, 7 Feb 2013 22:36:17 -0500 Subject: [PATCH 030/881] Remove references to event.bif.bro --- doc/user-manual/scripting.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index d45b322add..3d3cf3e19f 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -73,12 +73,12 @@ Gaining familiarity with the specific events generated by Bro is a big step towa :linenos: :lines: 4124-4149 -Above is a segment of ``event.bif.bro`` showing the documentation for the event dns_request(). It's organized such that the documentation, commentary, and list of arguments precede the actual event definition used by Bro. As Bro detects DNS requests being issued by an originator, it issues this event and any number of scripts then have access to the data Bro passes along with the event. In this example, Bro passes not only the message, the query, query type and query class for the DNS request, but also a then record used for the connection itself. +Above is a segment of the documentation for the event dns_request(). It's organized such that the documentation, commentary, and list of arguments precede the actual event definition used by Bro. As Bro detects DNS requests being issued by an originator, it issues this event and any number of scripts then have access to the data Bro passes along with the event. In this example, Bro passes not only the message, the query, query type and query class for the DNS request, but also a then record used for the connection itself. The Connection Record Data Type =============================== -Of all the events defined in Bro's ``event.bif.bro`` file, an overwhelmingly large number of them are passed the connection record data type, in effect, making it the backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. Let's walk through the process of selecting an appropriate event, generating some output to standard out and dissecting the connection record so as to get an overview of it. We will cover data types in more detail later. +Of all the events defined by Bro, an overwhelmingly large number of them are passed the connection record data type, in effect, making it the backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. Let's walk through the process of selecting an appropriate event, generating some output to standard out and dissecting the connection record so as to get an overview of it. We will cover data types in more detail later. While Bro is capable of packet level processing, its strengths lay in the context of a connection between an originator and a responder. As such, there are events defined for the primary parts of the connection life-cycle as you'll see from the small selection of connection-related events below. From ed8267dd38c8e71de75287186a1c432c7cfd7ef5 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Thu, 7 Feb 2013 23:28:33 -0500 Subject: [PATCH 031/881] Added a more simple example to the section on Constants to re-inforce &redef. --- doc/user-manual/scripting.rst | 18 ++++++++++++++++-- .../doc.manual.data_type_const_simple/.stdout | 0 .../doc/manual/data_type_const_simple.bro | 7 +++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.data_type_const_simple/.stdout create mode 100644 testing/btest/doc/manual/data_type_const_simple.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 3d3cf3e19f..c78843c2df 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -115,7 +115,7 @@ Bro uses the dollar sign as its field delimiter and a direct correlation exists @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_02.bro -The addition of the ``base/protocols/dns`` scripts populates the dns=[] member of the connection record. While Bro is doing a massive amount of work in the background, it is in what is commonly called "script land" that details are being refined and decisions being made. Were we to continue running in "bare mode" we could slowly keep adding infrastructure through ``@load`` statements. For example, were we to ``@load base/frameworks/logging``, Bro would generate a conn.log and dns.log for us in the current working directory. As mentioned above, including the appropriate ``@load`` statements is not only good practice, but can also help to indicate which functionalities are being used in a script. +The addition of the ``base/protocols/dns`` scripts populates the dns=[] member of the connection record. While Bro is doing a massive amount of work in the background, it is in what is commonly called "script land" that details are being refined and decisions being made. Were we to continue running in "bare mode" we could slowly keep adding infrastructure through ``@load`` statements. For example, were we to ``@load base/frameworks/logging``, Bro would generate a conn.log and dns.log for us in the current working directory. As mentioned above, including the appropriate ``@load`` statements is not only good practice, but can also help to indicate which functionalities are being used in a script. Take a second to run the script with the ``-b`` flag and check the output when all of Bro's functionality is applied to the tracefile. Data Types and Data Structures ============================== @@ -145,7 +145,21 @@ The sample above also makes use of an export{} block. When the module keyword i Constants ~~~~~~~~~ -Bro also makes use of constants which are denoted by the "const" keyword. Unlike globals, constants can only be set or altered at parse time, afterwards (in runtime) the constants are unalterable. In most cases, constants are used in Bro scripts as containers for configuration options. The majority of constants defined are defined with the "&redef" attribute, making it such that the constant can be redefined. While the idea of a redefinable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the "&redef" attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added to the table through redef statements. The table is then printed in a bro_init() event. Were we to try to alter the table in an event handler, Bro would notify the user of an error and the script would fail. +Bro also makes use of constants which are denoted by the "const" keyword. Unlike globals, constants can only be set or altered at parse time if the &redef attribute has been used. Afterwards (in runtime) the constants are unalterable. In most cases, redefinable constants are used in Bro scripts as containers for configuration options. For example, the configuration option to log password decrypted from HTTP streams is stored in ``HTTP::default_capture_password`` as shown in the stripped down excerpt from ``http/main.bro`` below. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro + :language: bro + :linenos: + :lines: 8-10,19,20,74 + +Because the constant was declared with the ``&redef`` attribute, if we needed to turn this option on globally, we could do so by adding the following line to our ``site/local.bro`` file before firing up Bro. + + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const_simple.bro + :language: bro + :lines: 6 + +While the idea of a redefinable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the "&redef" attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added to the table through redef statements. The table is then printed in a bro_init() event. Were we to try to alter the table in an event handler, Bro would notify the user of an error and the script would fail. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const.bro :language: bro diff --git a/testing/btest/Baseline/doc.manual.data_type_const_simple/.stdout b/testing/btest/Baseline/doc.manual.data_type_const_simple/.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/doc/manual/data_type_const_simple.bro b/testing/btest/doc/manual/data_type_const_simple.bro new file mode 100644 index 0000000000..e32f740614 --- /dev/null +++ b/testing/btest/doc/manual/data_type_const_simple.bro @@ -0,0 +1,7 @@ +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff .stdout + +@load base/protocols/http + +redef HTTP::default_capture_password = T; + From 739134dc66dd158abef8893b0d34039353a814b8 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 12 Feb 2013 22:34:49 -0500 Subject: [PATCH 032/881] Include an extended explanation of the module and export{} considerations when using global variables. --- doc/user-manual/scripting.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index c78843c2df..64ef160448 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -133,7 +133,9 @@ Before embarking on a exploration of Bro's native Data Types and Data Structures Global Variables ~~~~~~~~~~~~~~~~ -A global variable is used when the state of variable needs to be tracked, not surprisingly, globally. While there are some caveats, when a script declares a variable using the global scope, that script is granting access to that variable from other scripts. The declaration below, is a taken from the ``known-hosts.bro`` script and declares a variable called "known_hosts"" as a global set of unique ip addresses(line 32) within the "Known" namespace (line 8) and exports it (line 10) for use outside of the "Known" namespace. Were we to want to use the "known_hosts" variable we'd be able to access it through "Known::known_hosts". +A global variable is used when the state of variable needs to be tracked, not surprisingly, globally. While there are some caveats, when a script declares a variable using the global scope, that script is granting access to that variable from other scripts. However, when a script uses the ``module`` keyword to give the script a namespace, more care must be given to the declaration of globals to ensure the intended result. When a global is declared in a script with a namespace there are two possible outcomes. First, the variable is available only within the context of the namespace. In this scenario, other scripts within the same namespace will have access to the varaible declared while scripts using a different namespace or no namespace altogether will not have access to the variable. Alternatively, if a global variable is declared within an ``export{}`` block that variable is available to any other script through the naming convention of ``MODULE::variable_name``. + +The declaration below, is a taken from the ``known-hosts.bro`` script and declares a variable called "known_hosts"" as a global set of unique ip addresses(line 32) within the "Known" namespace (line 8) and exports it (line 10) for use outside of the "Known" namespace. Were we to want to use the "known_hosts" variable we'd be able to access it through "Known::known_hosts". .. literalinclude:: ../scripts/policy/protocols/conn/known-hosts.bro :language: bro From b296f275148b75746d7bda3ca278c4b349424a15 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 12 Feb 2013 23:38:11 -0500 Subject: [PATCH 033/881] Start definition of address data type. --- doc/user-manual/scripting.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 64ef160448..c816e09eca 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -135,7 +135,7 @@ Global Variables A global variable is used when the state of variable needs to be tracked, not surprisingly, globally. While there are some caveats, when a script declares a variable using the global scope, that script is granting access to that variable from other scripts. However, when a script uses the ``module`` keyword to give the script a namespace, more care must be given to the declaration of globals to ensure the intended result. When a global is declared in a script with a namespace there are two possible outcomes. First, the variable is available only within the context of the namespace. In this scenario, other scripts within the same namespace will have access to the varaible declared while scripts using a different namespace or no namespace altogether will not have access to the variable. Alternatively, if a global variable is declared within an ``export{}`` block that variable is available to any other script through the naming convention of ``MODULE::variable_name``. -The declaration below, is a taken from the ``known-hosts.bro`` script and declares a variable called "known_hosts"" as a global set of unique ip addresses(line 32) within the "Known" namespace (line 8) and exports it (line 10) for use outside of the "Known" namespace. Were we to want to use the "known_hosts" variable we'd be able to access it through "Known::known_hosts". +The declaration below, is a taken from the ``known-hosts.bro`` script and declares a variable called "known_hosts"" as a global set of unique ip addresses(line 32) within the "Known" namespace (line 8) and exports it (line 10) for use outside of the "Known" namespace. Were we to want to use the "known_hosts" variable we'd be able to access it through ``Known::known_hosts``. .. literalinclude:: ../scripts/policy/protocols/conn/known-hosts.bro :language: bro @@ -306,10 +306,14 @@ In a lot of cases, storing elements in a vector is simply a precursor to then it @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_iter.bro - Data Types Revisited -------------------- +addr +~~~~ + +The addr, or address, data type manages to cover a surprisingly large amount of ground while remaining succinct. IPv4, IPv6 and even hostname constants are included in the addr data type. While IPv4 addresses use the default dotted quad formatting, IPv6 addresses use RFC 2373 defined notation with the addition of squared brackets wrapping the entire address. When you venture into hostname constants, Bro performs a little slight of hand for the benefit of the user; a hostname constant is, in fact, a set of addresses. Bro will issue a DNS request when it sees a hostname constant in use and return a set whose elements are the invidiual answers to the DNS request. + subnet ~~~~~~ From 6b3186780b5ff44cd29759e99acb0eeba7ef201d Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 17 Feb 2013 22:24:35 -0500 Subject: [PATCH 034/881] Added a quick explanation of the port data type. --- doc/user-manual/scripting.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index c816e09eca..47e6f3e06b 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -312,7 +312,14 @@ Data Types Revisited addr ~~~~ -The addr, or address, data type manages to cover a surprisingly large amount of ground while remaining succinct. IPv4, IPv6 and even hostname constants are included in the addr data type. While IPv4 addresses use the default dotted quad formatting, IPv6 addresses use RFC 2373 defined notation with the addition of squared brackets wrapping the entire address. When you venture into hostname constants, Bro performs a little slight of hand for the benefit of the user; a hostname constant is, in fact, a set of addresses. Bro will issue a DNS request when it sees a hostname constant in use and return a set whose elements are the invidiual answers to the DNS request. +The addr, or address, data type manages to cover a surprisingly large amount of ground while remaining succinct. IPv4, IPv6 and even hostname constants are included in the addr data type. While IPv4 addresses use the default dotted quad formatting, IPv6 addresses use RFC 2373 defined notation with the addition of squared brackets wrapping the entire address. When you venture into hostname constants, Bro performs a little slight of hand for the benefit of the user; a hostname constant is, in fact, a set of addresses. Bro will issue a DNS request when it sees a hostname constant in use and return a set whose elements are the answers to the DNS request. For example, if you were to use ``local google = www.google.com;`` you would end up with a locally scoped set of addr elements that represent the current set of round robin DNS entries for google. At first blush, this seems trivial, but it is yet another example of Bro making the life of the common Bro scripter a little easier through abstraction applied in a practical manner. + +port +~~~~ + +Transport layer port numbers in Bro are represented in the format of ``unsigned integer/protocol name`` e.g. ``22/tcp`` or ``53/udp``. Bro supports TCP( /tcp ), UDP( /udp ) , ICMP( /icmp ) and UNKNOWN( /unknown ) as protocol designations. While ICMP doesn't have an actual port, Bro supports the concept of ICMP "ports" by using the ICMP message type and ICMP message code as the source and destination port respectively. Ports can be compared for equality using the == or != operators and can even be compared for ordering. Bro gives the protocol designations the following "order": unknown < tcp < udp < icmp. + +Ports can be compared for equality and also for ordering. When comparing order across transport-level protocols, unknown < tcp < udp < icmp, for example 65535/tcp is smaller than 0/udp. subnet ~~~~~~ From 7e281015acb9338c60f6cb718ddcca2bb289c2f1 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 17 Feb 2013 23:23:03 -0500 Subject: [PATCH 035/881] Add documentation for the time data type. --- doc/user-manual/scripting.rst | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 47e6f3e06b..83c431a8d3 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -326,15 +326,32 @@ subnet Bro has full support for CIDR notation subnets as a base data type. There is no need to manage the IP and the subnet mask as two seperate entities when you can provide the same information in CIDR notation in your scripts. The following example below uses a Bro script to determine if a series of IP addresses are within a set of subnets using a 20 bit subnet mask. -.. literalinclude:: ../../../../testing/btest/doc/manual/data_type_subnets.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_subnets.bro :language: bro :linenos: :lines: 4-19 Because this is a script that doesn't use any kind of network analysis, we can handle the event bro_init() which is always generated by Bro's core upon startup. On lines six and seven, two locally scoped vectors are created to hold our lists of subnets and IP addresses respectively. Then, using a set of nested for loops, we iterate over every subnet and every IP address and use an if statement to compare an IP address against a subnet using the in operator. The in operator returns true if the IP address falls within a given subnet based on the longest prefix match calculation. For example, 10.0.0.1 in 10.0.0.0/8 would return true while 192.168.2.1 in 192.168.1.0/24 would return false. When we run the script, we get the output listing the IP address and the subnet in which it belongs. - .. btest:: data_type_subnets @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_subnets.bro +time +~~~~ + +While there is currently no supported way to add a time constant in Bro, two built-in functions exist to make use of the ``time`` data type. Both ``network_time()`` and ``current_time()`` return a ``time`` data type but they each return a time based on different criteria. The ``current_time()`` function returns what is called the wall-clock time as defined by the operating system. However, ``network_time()`` returns the timestamp of the last packet processed be it from a live data stream or saved packet capture. Both functions return the time in epoch seconds, meaning ``strftime`` must be used to turn the output into human readable output. The script below makes use of the ``connection_established`` event handler to generate text every time a SYN/ACK packet is seen responding to a SYN packet as part of a TCP handshake. The text generated, is in the format of a timestamp and an indication of who the originator and responder were. We use the ``strftime`` format string of ``%Y%M%d %H:%m:%S`` to produce a common date time formatted time stamp. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_time.bro + :language: bro + :linenos: + :lines: 4-7 + +When the script is executed we get an output showing the details of established connections. + +.. btest:: data_type_subnets + + @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_time.bro + + + From 11f9b83cd9b01d0d0ac0ceb10aa5744508a2312b Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 18 Feb 2013 00:16:59 -0500 Subject: [PATCH 036/881] Added documentation for the interval data type. --- doc/user-manual/scripting.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 83c431a8d3..e4a6ecf2d6 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -353,5 +353,27 @@ When the script is executed we get an output showing the details of established @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_time.bro +interval +~~~~~~~~ + +The interval data type is another area in Bro where rational application of abstraction made perfect sense. As a data type, the interval represents a relative time as denoted by a numeric constant followed by a unit of time. For example, ten seconds would be ``2.2sec`` and thirty-one days would be represented by ``31days``. Bro supports usec, msec, sec, min, hr, or day which represent microseconds, milliseconds, seconds, minutes, hours, and days respectively. In fact, the interval data type allows for a surprising amount of variation in its definitions. There can be a space between the numeric constant or they can crammed together like a temporal portmanteau. The time unit can be either singular or plural. All of this adds up to to the fact that both ``42hrs`` and ``42 hr`` are perfectly valid and logically equivalent in Bro. The point, however, is to increase the readability and thus maintainability of a script. Intervals can even be negated, allowing for ``- 10mins`` to represent "ten minutes ago". + +Intervals in Bro can have mathematical operations performed against them allowing the user to perform addition, subtraction, multiplication, division, and comparison operations. As well, Bro returns an interval when comparing two ``time`` values using the ``-`` operator. The script below amends the script started in the section above to include a time delta value printed along with the connection establishment report. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_interval.bro + :language: bro + :linenos: + :lines: 4-20 + +This time, when we execute the script we see an additional line in the output to display the time delta since the last fully established connection. + +.. btest:: data_type_subnets + + @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_interval.bro + + + + + From 1724784aad4806c4b206f67b8c2f612913652fba Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Wed, 20 Feb 2013 09:35:53 -0500 Subject: [PATCH 037/881] After extensive testing it has been revealed that 2.2 secons is not equal to 10 seconds. Scientific paper to follow. --- doc/user-manual/scripting.rst | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index e4a6ecf2d6..18cc4f961b 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -356,7 +356,7 @@ When the script is executed we get an output showing the details of established interval ~~~~~~~~ -The interval data type is another area in Bro where rational application of abstraction made perfect sense. As a data type, the interval represents a relative time as denoted by a numeric constant followed by a unit of time. For example, ten seconds would be ``2.2sec`` and thirty-one days would be represented by ``31days``. Bro supports usec, msec, sec, min, hr, or day which represent microseconds, milliseconds, seconds, minutes, hours, and days respectively. In fact, the interval data type allows for a surprising amount of variation in its definitions. There can be a space between the numeric constant or they can crammed together like a temporal portmanteau. The time unit can be either singular or plural. All of this adds up to to the fact that both ``42hrs`` and ``42 hr`` are perfectly valid and logically equivalent in Bro. The point, however, is to increase the readability and thus maintainability of a script. Intervals can even be negated, allowing for ``- 10mins`` to represent "ten minutes ago". +The interval data type is another area in Bro where rational application of abstraction made perfect sense. As a data type, the interval represents a relative time as denoted by a numeric constant followed by a unit of time. For example, 2.2 seconds would be ``2.2sec`` and thirty-one days would be represented by ``31days``. Bro supports usec, msec, sec, min, hr, or day which represent microseconds, milliseconds, seconds, minutes, hours, and days respectively. In fact, the interval data type allows for a surprising amount of variation in its definitions. There can be a space between the numeric constant or they can crammed together like a temporal portmanteau. The time unit can be either singular or plural. All of this adds up to to the fact that both ``42hrs`` and ``42 hr`` are perfectly valid and logically equivalent in Bro. The point, however, is to increase the readability and thus maintainability of a script. Intervals can even be negated, allowing for ``- 10mins`` to represent "ten minutes ago". Intervals in Bro can have mathematical operations performed against them allowing the user to perform addition, subtraction, multiplication, division, and comparison operations. As well, Bro returns an interval when comparing two ``time`` values using the ``-`` operator. The script below amends the script started in the section above to include a time delta value printed along with the connection establishment report. @@ -371,9 +371,3 @@ This time, when we execute the script we see an additional line in the output to @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_interval.bro - - - - - - From b53f701ffef85a2bf1726b43463a0738ae45b444 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 25 Feb 2013 01:12:07 -0500 Subject: [PATCH 038/881] Added documentation for the pattern data type as well as btests for time, interval, and pattern. --- doc/user-manual/scripting.rst | 24 +++++++++++++++++++ .../doc.manual.data_type_interval/.stdout | 15 ++++++++++++ .../doc.manual.data_type_pattern_01/.stdout | 3 +++ .../doc.manual.data_type_pattern_02/.stdout | 2 ++ .../doc.manual.data_type_time/.stdout | 8 +++++++ .../btest/doc/manual/data_type_interval.bro | 20 ++++++++++++++++ .../btest/doc/manual/data_type_pattern_01.bro | 14 +++++++++++ .../btest/doc/manual/data_type_pattern_02.bro | 14 +++++++++++ testing/btest/doc/manual/data_type_time.bro | 7 ++++++ 9 files changed, 107 insertions(+) create mode 100644 testing/btest/Baseline/doc.manual.data_type_interval/.stdout create mode 100644 testing/btest/Baseline/doc.manual.data_type_pattern_01/.stdout create mode 100644 testing/btest/Baseline/doc.manual.data_type_pattern_02/.stdout create mode 100644 testing/btest/Baseline/doc.manual.data_type_time/.stdout create mode 100644 testing/btest/doc/manual/data_type_interval.bro create mode 100644 testing/btest/doc/manual/data_type_pattern_01.bro create mode 100644 testing/btest/doc/manual/data_type_pattern_02.bro create mode 100644 testing/btest/doc/manual/data_type_time.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 18cc4f961b..086e0f9d49 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -371,3 +371,27 @@ This time, when we execute the script we see an additional line in the output to @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_interval.bro +Pattern +~~~~~~~ + +Bro has support for fast text searching operations using regular expressions and even goes so far as to declare a native data type for the patterns used in regular expressions. A pattern constant is created by enclosing text within the forward slash characters. Bro supports syntax very similar to the flex lexical analyzer syntax. The most common use of patterns in Bro you are likely to come across is embedded matching using the ``in`` operator. Embedded matching adheres to a strict format, requiring the regular expression or pattern constant to be on the left side of the ``in`` operator and the string against which it will be tested to be on the right. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_pattern_01.bro + :language: bro + :linenos: + :lines: 4-13 + +In the sample above, two local variables are declared to hold our sample sentence and regular expression. Our regular expression in this case will return true if the string contains either the word "quick" or the word "fox." The ``if`` statement on line six uses embedded matching and the ``in`` operator to check for the existence of the pattern within the string. If the statement resolves to true, split is called to break the string into separate pieces. Split takes a string and a pattern as its arguments and returns a table of strings indexed by a count. Each element of the table will be the segments before and after any matches against the pattern but excluding the actual matches. In this case, our pattern matches twice, and results in a table with three entries. Lines 11 through 13 print the contents of the table in order. + +.. btest:: data_type_subnets + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_01.bro + +Patterns can also be used to compare strings using equality and inequality operators through the ``==`` and ``!=`` operators respectively. When used in this manner however, the string must match entirely to resolve to true. For example, the script below uses two ternary conditional statements to illustrate the use of the ``==`` operators with patterns. On lines 5 and 8 the output is altered based on the result of the comparison between the pattern and the string. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_pattern_02.bro + :language: bro + :linenos: + :lines: 4-13 + +.. btest:: data_type_subnets + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_02.bro diff --git a/testing/btest/Baseline/doc.manual.data_type_interval/.stdout b/testing/btest/Baseline/doc.manual.data_type_interval/.stdout new file mode 100644 index 0000000000..1cd5999711 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_type_interval/.stdout @@ -0,0 +1,15 @@ +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118 +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 132.0 msecs 97.0 usecs +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 177.0 usecs +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 2.0 msecs 177.0 usecs +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 33.0 msecs 898.0 usecs +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 35.0 usecs +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 2.0 msecs 532.0 usecs +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2 + Time since last connection: 7.0 msecs 866.0 usecs diff --git a/testing/btest/Baseline/doc.manual.data_type_pattern_01/.stdout b/testing/btest/Baseline/doc.manual.data_type_pattern_01/.stdout new file mode 100644 index 0000000000..11358a776e --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_type_pattern_01/.stdout @@ -0,0 +1,3 @@ +The + brown fox jumped over the + dog. diff --git a/testing/btest/Baseline/doc.manual.data_type_pattern_02/.stdout b/testing/btest/Baseline/doc.manual.data_type_pattern_02/.stdout new file mode 100644 index 0000000000..808dc3d572 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_type_pattern_02/.stdout @@ -0,0 +1,2 @@ +equality and /^?(equal)$?/ are not equal +equality and /^?(equality)$?/ are equal diff --git a/testing/btest/Baseline/doc.manual.data_type_time/.stdout b/testing/btest/Baseline/doc.manual.data_type_time/.stdout new file mode 100644 index 0000000000..149cb40e2a --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_type_time/.stdout @@ -0,0 +1,8 @@ +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118^J +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J +2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2^J diff --git a/testing/btest/doc/manual/data_type_interval.bro b/testing/btest/doc/manual/data_type_interval.bro new file mode 100644 index 0000000000..869715b76c --- /dev/null +++ b/testing/btest/doc/manual/data_type_interval.bro @@ -0,0 +1,20 @@ +# @TEST-EXEC: bro -b -r $TRACES/wikipedia.trace %INPUT +# @TEST-EXEC: btest-diff .stdout + +# Store the time the previous connection was established. +global last_connection_time: time; + +# boolean value to indicate whether we have seen a previous connection. +global connection_seen: bool = F; + +event connection_established(c: connection) + { + local net_time: time = network_time(); + print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h); + if (connection_seen) + { + print fmt(" Time since last connection: %s", net_time - last_connection_time); + } + last_connection_time = net_time; + connection_seen = T; + } \ No newline at end of file diff --git a/testing/btest/doc/manual/data_type_pattern_01.bro b/testing/btest/doc/manual/data_type_pattern_01.bro new file mode 100644 index 0000000000..09b92773a3 --- /dev/null +++ b/testing/btest/doc/manual/data_type_pattern_01.bro @@ -0,0 +1,14 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local test_string = "The quick brown fox jumped over the lazy dog."; + local test_pattern = /quick|lazy/; + + if (test_pattern in test_string) + local results = split(test_string, test_pattern); + print results[1]; + print results[2]; + print results[3]; + } \ No newline at end of file diff --git a/testing/btest/doc/manual/data_type_pattern_02.bro b/testing/btest/doc/manual/data_type_pattern_02.bro new file mode 100644 index 0000000000..f4621cfb90 --- /dev/null +++ b/testing/btest/doc/manual/data_type_pattern_02.bro @@ -0,0 +1,14 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + local test_string = "equality"; + + local test_pattern = /equal/; + print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); + + test_pattern = /equality/; + print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); + } + diff --git a/testing/btest/doc/manual/data_type_time.bro b/testing/btest/doc/manual/data_type_time.bro new file mode 100644 index 0000000000..45bff4479e --- /dev/null +++ b/testing/btest/doc/manual/data_type_time.bro @@ -0,0 +1,7 @@ +# @TEST-EXEC: bro -b -r $TRACES/wikipedia.trace %INPUT +# @TEST-EXEC: btest-diff .stdout + +event connection_established(c: connection) + { + print fmt("%s: New connection established from %s to %s\n", strftime("%Y/%M/%d %H:%m:%S", network_time()), c$id$orig_h, c$id$resp_h); + } \ No newline at end of file From 78c81a59e0722517076692736263ac9ef9493713 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Fri, 1 Mar 2013 15:55:38 -0500 Subject: [PATCH 039/881] Started in on describing records. --- doc/user-manual/scripting.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 086e0f9d49..ae08e7adab 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -395,3 +395,31 @@ Patterns can also be used to compare strings using equality and inequality opera .. btest:: data_type_subnets @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_02.bro + + +Advanced Data Types +=================== + +Custom Data Types +~~~~~~~~~~~~~~~~~ + +With Bro's support for a wide array of data types and data structures an obvious extension of is to include the ability to create custom data types consisting of the atomic types and ddata structures. To accomplish this, Bro introduces the ``record`` type and the ``type`` keyword. Similar to how you would define a new data structure in C with the ``typedef`` and ``struct`` keywords, Bro allows you to cobble together new data types to suit the needs of your situation. + +When combined with the ``type`` keyword, ``record`` can generate a composite type. We have, in fact, already encountered a a complex example of the ``record`` data type in the earlier sections. The excerpt below shows the definition of the connection record data type as defined in the ``Conn`` module. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro + :language: bro + :linenos: + :lines: 10-12,16,17,19,21,23,25,28,31,35,37,56,62,68,90,93,97,100,104,108,109,114 + +While it might be surprising that Bro is tracking and passing around this much data for each connection, it shouldn't be too surprising, given our exploration of it earlier, that the connection record consists of a collection of atomic data types, simple data types and even another ``record``. Looking at the structure of the definition, a new collection of data types is being defined as a type called ``Info``. Since this type definition is within the confines of an export block, what is defined is, in fact, ``Conn::Info``. + +It's also common to see a ``type`` used to simply alias a data structure to a more descriptive name. The example below shows an example of this from Bro's own type definitions file. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/init-bare.bro + :language: bro + :linenos: + :lines: 12,19,26 + +The three lines above alias a type of data structure to a descriptive name. Functionally, the operations are the same, however, each of the types above are named such that their function is instantly identifiable. This is another place in Bro scripting where consideration can lead to better readability of your code and thus easier maintainability in the future. + From 5249a30c46f106bc804b7cbf2b34221e3c3c4bde Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 11 Mar 2013 00:19:23 -0400 Subject: [PATCH 040/881] Expanding on records, including two simple examples. --- doc/user-manual/scripting.rst | 24 ++++++++++ .../doc.manual.data_struct_record_01/.stdout | 6 +++ .../doc.manual.data_struct_record_02/.stdout | 7 +++ .../doc/manual/data_struct_record_01.bro | 25 ++++++++++ .../doc/manual/data_struct_record_02.bro | 47 +++++++++++++++++++ 5 files changed, 109 insertions(+) create mode 100644 testing/btest/Baseline/doc.manual.data_struct_record_01/.stdout create mode 100644 testing/btest/Baseline/doc.manual.data_struct_record_02/.stdout create mode 100644 testing/btest/doc/manual/data_struct_record_01.bro create mode 100644 testing/btest/doc/manual/data_struct_record_02.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index ae08e7adab..5ecc99b9c3 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -414,6 +414,30 @@ When combined with the ``type`` keyword, ``record`` can generate a composite typ While it might be surprising that Bro is tracking and passing around this much data for each connection, it shouldn't be too surprising, given our exploration of it earlier, that the connection record consists of a collection of atomic data types, simple data types and even another ``record``. Looking at the structure of the definition, a new collection of data types is being defined as a type called ``Info``. Since this type definition is within the confines of an export block, what is defined is, in fact, ``Conn::Info``. +The formatting for a declaration of a record type in Bro includes the descriptive name of the type being defined and the seperate entities that make up the record. The individual entites that make up the new record are not limited in type or number as long as the name for each entity is unique. + +.. rootliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_01.bro + :language: bro + :linenos: + :lines: 4-25 + +.. btest:: data_struct_record_01 + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_01.bro + +The sample above shows a simple type definition that includes a string, a set of ports, and a count to define a service type. Also included is a function to print each entity of a record in a formatted fashion and a bro_init event handler to show some functionality of working with records. The defintions of the dns and http services are both done inline using squared brackets before being passed to the ``print_service`` function. The ``print_service`` function makes use of the ``$`` dereference operator to access the entities within the newly defined Service record type. + +As you saw in the definition for the connection record, other records are even valid as entities within another record. We can extend the example above to include another record that contains a Service record. + +.. rootliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_02.bro + :language: bro + :linenos: + :lines: 4-25 + +.. btest:: data_struct_record_02 + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_02.bro + +The example above includes a second record type in which an entity is used as the data type for a set. Records can be reapeatedly nested within other records, their entities reachable through repeated chains of the ``$`` dereference operator. + It's also common to see a ``type`` used to simply alias a data structure to a more descriptive name. The example below shows an example of this from Bro's own type definitions file. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/init-bare.bro diff --git a/testing/btest/Baseline/doc.manual.data_struct_record_01/.stdout b/testing/btest/Baseline/doc.manual.data_struct_record_01/.stdout new file mode 100644 index 0000000000..4e628b9ae7 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_struct_record_01/.stdout @@ -0,0 +1,6 @@ +Service: dns(RFC1035) + port: 53/tcp + port: 53/udp +Service: http(RFC2616) + port: 80/tcp + port: 8080/tcp diff --git a/testing/btest/Baseline/doc.manual.data_struct_record_02/.stdout b/testing/btest/Baseline/doc.manual.data_struct_record_02/.stdout new file mode 100644 index 0000000000..0428764bea --- /dev/null +++ b/testing/btest/Baseline/doc.manual.data_struct_record_02/.stdout @@ -0,0 +1,7 @@ +System: morlock + Service: dns(RFC1035) + port: 53/tcp + port: 53/udp + Service: http(RFC2616) + port: 80/tcp + port: 8080/tcp diff --git a/testing/btest/doc/manual/data_struct_record_01.bro b/testing/btest/doc/manual/data_struct_record_01.bro new file mode 100644 index 0000000000..25eb0b02a0 --- /dev/null +++ b/testing/btest/doc/manual/data_struct_record_01.bro @@ -0,0 +1,25 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +type Service: record { + name: string; + ports: set[port]; + rfc: count; +}; + +function print_service(serv: Service): string + { + print fmt("Service: %s(RFC%d)",serv$name, serv$rfc); + for (p in serv$ports) + { + print fmt(" port: %s", p); + } + } + +event bro_init() + { + local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; + local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; + print_service(dns); + print_service(http); + } diff --git a/testing/btest/doc/manual/data_struct_record_02.bro b/testing/btest/doc/manual/data_struct_record_02.bro new file mode 100644 index 0000000000..e340bc5744 --- /dev/null +++ b/testing/btest/doc/manual/data_struct_record_02.bro @@ -0,0 +1,47 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +type Service: record { + name: string; + ports: set[port]; + rfc: count; + }; + +type System: record { + name: string; + services: set[Service]; + }; + + +function print_service(serv: Service): string + { + print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc); + for (p in serv$ports) + { + print fmt(" port: %s", p); + } + } + +function print_system(sys: System): string + { + print fmt("System: %s", sys$name); + for (s in sys$services) + { + print_service(s); + } + } + +event bro_init() + { + local server01: System; + server01$name = "morlock"; + add server01$services[[ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]]; + add server01$services[[ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]]; + print_system(server01); + + + # local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; + # local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; + # print_service(dns); + # print_service(http); + } From afdb80a334951c50b40563739e882e826c04fa35 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 12 Mar 2013 16:03:17 -0400 Subject: [PATCH 041/881] Include required blank line after btest directive to avoid python error. --- doc/user-manual/scripting.rst | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 5ecc99b9c3..4263de3204 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -349,9 +349,9 @@ While there is currently no supported way to add a time constant in Bro, two bui When the script is executed we get an output showing the details of established connections. -.. btest:: data_type_subnets +.. btest:: data_type_time - @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_time.bro + @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_time.bro interval ~~~~~~~~ @@ -367,9 +367,10 @@ Intervals in Bro can have mathematical operations performed against them allowin This time, when we execute the script we see an additional line in the output to display the time delta since the last fully established connection. -.. btest:: data_type_subnets +.. btest:: data_type_interval + + @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_interval.bro - @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_interval.bro Pattern ~~~~~~~ @@ -383,7 +384,8 @@ Bro has support for fast text searching operations using regular expressions and In the sample above, two local variables are declared to hold our sample sentence and regular expression. Our regular expression in this case will return true if the string contains either the word "quick" or the word "fox." The ``if`` statement on line six uses embedded matching and the ``in`` operator to check for the existence of the pattern within the string. If the statement resolves to true, split is called to break the string into separate pieces. Split takes a string and a pattern as its arguments and returns a table of strings indexed by a count. Each element of the table will be the segments before and after any matches against the pattern but excluding the actual matches. In this case, our pattern matches twice, and results in a table with three entries. Lines 11 through 13 print the contents of the table in order. -.. btest:: data_type_subnets +.. btest:: data_type_pattern + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_01.bro Patterns can also be used to compare strings using equality and inequality operators through the ``==`` and ``!=`` operators respectively. When used in this manner however, the string must match entirely to resolve to true. For example, the script below uses two ternary conditional statements to illustrate the use of the ``==`` operators with patterns. On lines 5 and 8 the output is altered based on the result of the comparison between the pattern and the string. @@ -393,15 +395,17 @@ Patterns can also be used to compare strings using equality and inequality opera :linenos: :lines: 4-13 -.. btest:: data_type_subnets +.. btest:: data_type_pattern_02 + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_02.bro + Advanced Data Types =================== Custom Data Types -~~~~~~~~~~~~~~~~~ +----------------- With Bro's support for a wide array of data types and data structures an obvious extension of is to include the ability to create custom data types consisting of the atomic types and ddata structures. To accomplish this, Bro introduces the ``record`` type and the ``type`` keyword. Similar to how you would define a new data structure in C with the ``typedef`` and ``struct`` keywords, Bro allows you to cobble together new data types to suit the needs of your situation. @@ -416,24 +420,26 @@ While it might be surprising that Bro is tracking and passing around this much d The formatting for a declaration of a record type in Bro includes the descriptive name of the type being defined and the seperate entities that make up the record. The individual entites that make up the new record are not limited in type or number as long as the name for each entity is unique. -.. rootliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_01.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_01.bro :language: bro :linenos: :lines: 4-25 .. btest:: data_struct_record_01 + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_01.bro The sample above shows a simple type definition that includes a string, a set of ports, and a count to define a service type. Also included is a function to print each entity of a record in a formatted fashion and a bro_init event handler to show some functionality of working with records. The defintions of the dns and http services are both done inline using squared brackets before being passed to the ``print_service`` function. The ``print_service`` function makes use of the ``$`` dereference operator to access the entities within the newly defined Service record type. As you saw in the definition for the connection record, other records are even valid as entities within another record. We can extend the example above to include another record that contains a Service record. -.. rootliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_02.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_02.bro :language: bro :linenos: :lines: 4-25 .. btest:: data_struct_record_02 + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_02.bro The example above includes a second record type in which an entity is used as the data type for a set. Records can be reapeatedly nested within other records, their entities reachable through repeated chains of the ``$`` dereference operator. @@ -446,4 +452,3 @@ It's also common to see a ``type`` used to simply alias a data structure to a mo :lines: 12,19,26 The three lines above alias a type of data structure to a descriptive name. Functionally, the operations are the same, however, each of the types above are named such that their function is instantly identifiable. This is another place in Bro scripting where consideration can lead to better readability of your code and thus easier maintainability in the future. - From 0f99956417425ef20e5592781e3b6335ea4f3f37 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 13 Mar 2013 14:36:27 -0400 Subject: [PATCH 042/881] Added Exec, Dir, and ActiveHTTP modules. --- scripts/base/init-default.bro | 3 + scripts/base/utils/active-http.bro | 120 +++++++++++++++++ scripts/base/utils/dir.bro | 51 +++++++ scripts/base/utils/exec.bro | 207 +++++++++++++++++++++++++++++ 4 files changed, 381 insertions(+) create mode 100644 scripts/base/utils/active-http.bro create mode 100644 scripts/base/utils/dir.bro create mode 100644 scripts/base/utils/exec.bro diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 8b36899f10..9b62c80014 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -5,9 +5,12 @@ ##! you actually want. @load base/utils/site +@load base/utils/active-http @load base/utils/addrs @load base/utils/conn-ids +@load base/utils/dir @load base/utils/directions-and-hosts +@load base/utils/exec @load base/utils/files @load base/utils/numbers @load base/utils/paths diff --git a/scripts/base/utils/active-http.bro b/scripts/base/utils/active-http.bro new file mode 100644 index 0000000000..5522cc108a --- /dev/null +++ b/scripts/base/utils/active-http.bro @@ -0,0 +1,120 @@ +##! A module for performing active HTTP requests and +##! getting the reply at runtime. + +@load ./exec + +module ActiveHTTP; + +export { + ## The default timeout for HTTP requests. + const default_max_time = 1min &redef; + + ## The default HTTP method/verb to use for requests. + const default_method = "GET" &redef; + + type Response: record { + ## Numeric response code from the server. + code: count; + ## String response messgae from the server. + msg: string; + ## Full body of the response. + body: string &optional; + ## All headers returned by the server. + headers: table[string] of string &optional; + }; + + type Request: record { + ## The URL being requested. + url: string; + ## The HTTP method/verb to use for the request. + method: string &default=default_method; + ## Data to send to the server in the client body. Keep in + ## mind that you will probably need to set the $method field + ## to "POST" or "PUT". + client_data: string &optional; + ## Arbitrary headers to pass to the server. Some headers + ## will be included by libCurl. + #custom_headers: table[string] of string &optional; + ## Timeout for the request. + max_time: interval &default=default_max_time; + ## Additional curl command line arguments. Be very careful + ## with this option since shell injection could take place + ## if careful handling of untrusted data is not applied. + addl_curl_args: string &optional; + }; + + ## Perform an HTTP request according to the :bro:type:`Request` record. + ## This is an asynchronous function and must be called within a "when" + ## statement. + ## + ## req: A record instance representing all options for an HTTP request. + ## + ## Returns: A record with the full response message. + global request: function(req: ActiveHTTP::Request): ActiveHTTP::Response; +} + +function request2curl(r: Request, bodyfile: string, headersfile: string): string + { + local cmd = fmt("curl -s -g -o \"%s\" -D \"%s\" -X \"%s\"", + str_shell_escape(bodyfile), + str_shell_escape(headersfile), + str_shell_escape(r$method)); + + cmd = fmt("%s -m %.0f", cmd, r$max_time); + + if ( r?$client_data ) + cmd = fmt("%s -d -", cmd); + + if ( r?$addl_curl_args ) + cmd = fmt("%s %s", cmd, r$addl_curl_args); + + cmd = fmt("%s \"%s\"", cmd, str_shell_escape(r$url)); + return cmd; + } + +function request(req: Request): ActiveHTTP::Response + { + local tmpfile = "/tmp/bro-activehttp-" + unique_id(""); + local bodyfile = fmt("%s_body", tmpfile); + local headersfile = fmt("%s_headers", tmpfile); + + local cmd = request2curl(req, bodyfile, headersfile); + local stdin_data = req?$client_data ? req$client_data : ""; + + local resp: Response; + resp$code = 0; + resp$msg = ""; + resp$body = ""; + resp$headers = table(); + return when ( local result = Exec::run([$cmd=cmd, $stdin=stdin_data, $read_files=set(bodyfile, headersfile)]) ) + { + # If there is no response line then nothing else will work either. + if ( ! (result?$files && headersfile in result$files) ) + Reporter::error(fmt("There was a failure when requesting \"%s\" with ActiveHTTP.", req$url)); + + local headers = result$files[headersfile]; + for ( i in headers ) + { + # The reply is the first line. + if ( i == 0 ) + { + local response_line = split_n(headers[0], /[[:blank:]]+/, F, 2); + if ( |response_line| != 3 ) + return resp; + + resp$code = to_count(response_line[2]); + resp$msg = response_line[3]; + resp$body = join_string_vec(result$files[bodyfile], ""); + } + else + { + local line = headers[i]; + local h = split1(line, /:/); + if ( |h| != 2 ) + next; + resp$headers[h[1]] = sub_bytes(h[2], 0, |h[2]|-1); + } + } + return resp; + } + } diff --git a/scripts/base/utils/dir.bro b/scripts/base/utils/dir.bro new file mode 100644 index 0000000000..2ed1c8e6e9 --- /dev/null +++ b/scripts/base/utils/dir.bro @@ -0,0 +1,51 @@ +@load base/utils/exec +@load base/frameworks/reporter +@load base/utils/paths + +module Dir; + +export { + ## Register a directory to monitor with a callback that is called + ## every time a previously unseen file is seen. If a file is deleted + ## and seen to be gone, the file is available for being seen again in + ## the future. + ## + ## dir: The directory to monitor for files. + ## + ## callback: Callback that gets executed with each file name + ## that is found. Filenames are provided with the full path. + global monitor: function(dir: string, callback: function(fname: string)); + + ## The interval this module checks for files in directories when using + ## the :bro:see:`Dir::monitor` function. + const polling_interval = 30sec &redef; +} + +event Dir::monitor_ev(dir: string, last_files: set[string], callback: function(fname: string)) + { + when ( local result = Exec::run([$cmd=fmt("ls \"%s\"", str_shell_escape(dir))]) ) + { + if ( result$exit_code != 0 ) + { + Reporter::warning("Requested monitoring of non-existent directory."); + return; + } + + local current_files: set[string] = set(); + local files = result$stdout; + for ( i in files ) + { + if ( files[i] !in last_files ) + callback(build_path_compressed(dir, files[i])); + add current_files[files[i]]; + } + schedule polling_interval { Dir::monitor_ev(dir, current_files, callback) }; + } + } + +function monitor(dir: string, callback: function(fname: string)) + { + event Dir::monitor_ev(dir, set(), callback); + } + + diff --git a/scripts/base/utils/exec.bro b/scripts/base/utils/exec.bro new file mode 100644 index 0000000000..fe353cf590 --- /dev/null +++ b/scripts/base/utils/exec.bro @@ -0,0 +1,207 @@ +##! A module for executing external command line programs. +##! This requires code that is still in topic branches and +##! definitely won't currently work on any released version of Bro. + +@load base/frameworks/input + +module Exec; + +export { + type Command: record { + ## The command line to execute. + ## Use care to avoid injection attacks! + cmd: string; + ## Provide standard in to the program as a + ## string. + stdin: string &default=""; + ## If additional files are required to be read + ## in as part of the output of the command they + ## can be defined here. + read_files: set[string] &optional; + }; + + type Result: record { + ## Exit code from the program. + exit_code: count &default=0; + ## Each line of standard out. + stdout: vector of string &optional; + ## Each line of standard error. + stderr: vector of string &optional; + ## If additional files were requested to be read in + ## the content of the files will be available here. + files: table[string] of string_vec &optional; + }; + + ## Function for running command line programs and getting + ## output. This is an asynchronous function which is meant + ## to be run with the `when` statement. + ## + ## cmd: The command to run. Use care to avoid injection attacks! + ## + ## returns: A record representing the full results from the + ## external program execution. + global run: function(cmd: Command): Result; +} + +redef record Command += { + # The prefix name for tracking temp files. + prefix_name: string &optional; +}; + +global results: table[string] of Result = table(); +global finished_commands: set[string]; +global tmp_files: set[string] = set(); + +type OneLine: record { line: string; }; + +event Exec::stdout_line(description: Input::EventDescription, tpe: Input::Event, s: string) + { + local name = sub(description$name, /_[^_]*$/, ""); + + local result = results[name]; + if ( ! results[name]?$stdout ) + result$stdout = vector(s); + else + result$stdout[|result$stdout|] = s; + } + +event Exec::stderr_line(description: Input::EventDescription, tpe: Input::Event, s: string) + { + local name = sub(description$name, /_[^_]*$/, ""); + + local result = results[name]; + if ( ! results[name]?$stderr ) + result$stderr = vector(s); + else + result$stderr[|result$stderr|] = s; + } + +event Exec::file_line(description: Input::EventDescription, tpe: Input::Event, s: string) + { + local parts = split1(description$name, /_/); + local name = parts[1]; + local track_file = parts[2]; + + local result = results[name]; + if ( ! result?$files ) + result$files = table(); + + if ( track_file !in result$files ) + result$files[track_file] = vector(s); + else + result$files[track_file][|result$files[track_file]|] = s; + } + +event Exec::cleanup_and_do_callback(name: string) + { + Input::remove(fmt("%s_stdout", name)); + system(fmt("rm %s_stdout", name)); + delete tmp_files[fmt("%s_stdout", name)]; + + Input::remove(fmt("%s_stderr", name)); + system(fmt("rm %s_stderr", name)); + delete tmp_files[fmt("%s_stderr", name)]; + + Input::remove(fmt("%s_done", name)); + system(fmt("rm %s_done", name)); + delete tmp_files[fmt("%s_done", name)]; + + # Indicate to the "when" async watcher that this command is done. + add finished_commands[name]; + } + +event Exec::run_done(description: Input::EventDescription, tpe: Input::Event, s: string) + { + local name = sub(description$name, /_[^_]*$/, ""); + + if ( /^exit_code:/ in s ) + results[name]$exit_code = to_count(split1(s, /:/)[2]); + else if ( s == "done" ) + # Wait one second to allow all threads to read all of their input + # and forward it. + schedule 1sec { Exec::cleanup_and_do_callback(name) }; + } + +event Exec::start_watching_files(cmd: Command) + { + Input::add_event([$source=fmt("%s_done", cmd$prefix_name), + $name=fmt("%s_done", cmd$prefix_name), + $reader=Input::READER_RAW, + $mode=Input::STREAM, + $want_record=F, + $fields=OneLine, + $ev=Exec::run_done]); + + Input::add_event([$source=fmt("%s_stdout", cmd$prefix_name), + $name=fmt("%s_stdout", cmd$prefix_name), + $reader=Input::READER_RAW, + $mode=Input::STREAM, + $want_record=F, + $fields=OneLine, + $ev=Exec::stdout_line]); + + Input::add_event([$source=fmt("%s_stderr", cmd$prefix_name), + $name=fmt("%s_stderr", cmd$prefix_name), + $reader=Input::READER_RAW, + $mode=Input::STREAM, + $want_record=F, + $fields=OneLine, + $ev=Exec::stderr_line]); + + if ( cmd?$read_files ) + { + for ( read_file in cmd$read_files ) + { + Input::add_event([$source=fmt("%s", read_file), + $name=fmt("%s_%s", cmd$prefix_name, read_file), + $reader=Input::READER_RAW, + $mode=Input::STREAM, + $want_record=F, + $fields=OneLine, + $ev=Exec::file_line]); + } + } + } + +function run(cmd: Command): Result + { + cmd$prefix_name = "/tmp/bro-exec-" + unique_id(""); + system(fmt("touch %s_done %s_stdout %s_stderr 2>/dev/null", cmd$prefix_name, cmd$prefix_name, cmd$prefix_name)); + add tmp_files[fmt("%s_done", cmd$prefix_name)]; + add tmp_files[fmt("%s_stdout", cmd$prefix_name)]; + add tmp_files[fmt("%s_stderr", cmd$prefix_name)]; + + if ( cmd?$read_files ) + { + for ( read_file in cmd$read_files ) + { + system(fmt("touch %s 2>/dev/null", read_file)); + add tmp_files[read_file]; + } + } + + piped_exec(fmt("%s 2>> %s_stderr 1>> %s_stdout; echo \"exit_code:${?}\" >> %s_done; echo \"done\" >> %s_done", + cmd$cmd, cmd$prefix_name, cmd$prefix_name, cmd$prefix_name, cmd$prefix_name), + cmd$stdin); + + results[cmd$prefix_name] = []; + + schedule 1msec { Exec::start_watching_files(cmd) }; + + return when ( cmd$prefix_name in finished_commands ) + { + delete finished_commands[cmd$prefix_name]; + local result = results[cmd$prefix_name]; + delete results[cmd$prefix_name]; + return result; + } + } + +event bro_done() + { + # We are punting here and just deleting any files that haven't been processed yet. + for ( fname in tmp_files ) + { + system(fmt("rm \"%s\"", str_shell_escape(fname))); + } + } \ No newline at end of file From daaeca5ef07436086eca69cceda200a5f3c05af7 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 18 Mar 2013 13:38:03 -0400 Subject: [PATCH 043/881] correct nomenclature for fields in a record. --- doc/user-manual/scripting.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 4263de3204..f090f22457 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -418,7 +418,7 @@ When combined with the ``type`` keyword, ``record`` can generate a composite typ While it might be surprising that Bro is tracking and passing around this much data for each connection, it shouldn't be too surprising, given our exploration of it earlier, that the connection record consists of a collection of atomic data types, simple data types and even another ``record``. Looking at the structure of the definition, a new collection of data types is being defined as a type called ``Info``. Since this type definition is within the confines of an export block, what is defined is, in fact, ``Conn::Info``. -The formatting for a declaration of a record type in Bro includes the descriptive name of the type being defined and the seperate entities that make up the record. The individual entites that make up the new record are not limited in type or number as long as the name for each entity is unique. +The formatting for a declaration of a record type in Bro includes the descriptive name of the type being defined and the seperate fields that make up the record. The individual fields that make up the new record are not limited in type or number as long as the name for each field is unique. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_01.bro :language: bro @@ -429,9 +429,9 @@ The formatting for a declaration of a record type in Bro includes the descriptiv @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_01.bro -The sample above shows a simple type definition that includes a string, a set of ports, and a count to define a service type. Also included is a function to print each entity of a record in a formatted fashion and a bro_init event handler to show some functionality of working with records. The defintions of the dns and http services are both done inline using squared brackets before being passed to the ``print_service`` function. The ``print_service`` function makes use of the ``$`` dereference operator to access the entities within the newly defined Service record type. +The sample above shows a simple type definition that includes a string, a set of ports, and a count to define a service type. Also included is a function to print each field of a record in a formatted fashion and a bro_init event handler to show some functionality of working with records. The defintions of the dns and http services are both done inline using squared brackets before being passed to the ``print_service`` function. The ``print_service`` function makes use of the ``$`` dereference operator to access the fields within the newly defined Service record type. -As you saw in the definition for the connection record, other records are even valid as entities within another record. We can extend the example above to include another record that contains a Service record. +As you saw in the definition for the connection record, other records are even valid as fields within another record. We can extend the example above to include another record that contains a Service record. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_02.bro :language: bro @@ -442,7 +442,7 @@ As you saw in the definition for the connection record, other records are even v @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_02.bro -The example above includes a second record type in which an entity is used as the data type for a set. Records can be reapeatedly nested within other records, their entities reachable through repeated chains of the ``$`` dereference operator. +The example above includes a second record type in which an field is used as the data type for a set. Records can be reapeatedly nested within other records, their fields reachable through repeated chains of the ``$`` dereference operator. It's also common to see a ``type`` used to simply alias a data structure to a more descriptive name. The example below shows an example of this from Bro's own type definitions file. From 19c401f8a61230d912c7cf1943a6aedd06ab5d3e Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 18 Mar 2013 21:46:19 -0400 Subject: [PATCH 044/881] Renamed Advanced Data Structures to simply Record Data Type. --- doc/user-manual/scripting.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index f090f22457..f898dfb584 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -401,11 +401,8 @@ Patterns can also be used to compare strings using equality and inequality opera -Advanced Data Types -=================== - -Custom Data Types ------------------ +Record Data Type +================ With Bro's support for a wide array of data types and data structures an obvious extension of is to include the ability to create custom data types consisting of the atomic types and ddata structures. To accomplish this, Bro introduces the ``record`` type and the ``type`` keyword. Similar to how you would define a new data structure in C with the ``typedef`` and ``struct`` keywords, Bro allows you to cobble together new data types to suit the needs of your situation. @@ -442,7 +439,7 @@ As you saw in the definition for the connection record, other records are even v @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_02.bro -The example above includes a second record type in which an field is used as the data type for a set. Records can be reapeatedly nested within other records, their fields reachable through repeated chains of the ``$`` dereference operator. +The example above includes a second record type in which a field is used as the data type for a set. Records can be reapeatedly nested within other records, their fields reachable through repeated chains of the ``$`` dereference operator. It's also common to see a ``type`` used to simply alias a data structure to a more descriptive name. The example below shows an example of this from Bro's own type definitions file. @@ -452,3 +449,4 @@ It's also common to see a ``type`` used to simply alias a data structure to a mo :lines: 12,19,26 The three lines above alias a type of data structure to a descriptive name. Functionally, the operations are the same, however, each of the types above are named such that their function is instantly identifiable. This is another place in Bro scripting where consideration can lead to better readability of your code and thus easier maintainability in the future. + From 940910768b8b7e381265ab7a9264024c96a47632 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 18 Mar 2013 23:23:43 -0400 Subject: [PATCH 045/881] Start on Logging Framework. --- doc/user-manual/scripting.rst | 22 +++++++++++++++ .../.stdout | 10 +++++++ .../manual/framework_logging_factorial_01.bro | 27 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 testing/btest/Baseline/doc.manual.framework_logging_factorial_01/.stdout create mode 100644 testing/btest/doc/manual/framework_logging_factorial_01.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index f898dfb584..8e7d06d493 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -450,3 +450,25 @@ It's also common to see a ``type`` used to simply alias a data structure to a mo The three lines above alias a type of data structure to a descriptive name. Functionally, the operations are the same, however, each of the types above are named such that their function is instantly identifiable. This is another place in Bro scripting where consideration can lead to better readability of your code and thus easier maintainability in the future. + +Logging Framework +================= + +Armed with a decent understanding of the data types and data structures in Bro, exploring the various frameworks available is a much more rewarding effort. The framework with which most users are likely to have the most interaction is the Logging Framework. Designed in such a way to so as to abstract much of the process of creating a file and appending ordered and organized data into it, the Logging Framework makes use of some potentially unfamiliar nomenclature. Specifically, Log streams, Filters and Writers are simply abstractions of the processes required to manage a high rate of incoming logs while maintaining full operability. If you've seen Bro employed in an environment with a large connection, you know that logs are produced incredibly quickly; the ability to process a large set of data and write it to disk is due to the design of the Logging Framework. + +Data is written to a Log stream based on decision making processes in Bro's scriptland. Log streams correspond to a single log as defined by the set of name value pairs that make up its fields. That data can then be filtered, modified, or redirected with Logging Filters which, by default, are set to log everything. Filters can be used to break log files into subsets or duplicate that information to another output. The final output of the data is defined by the writer. Bro's default writer is simple tab separated ASCII files but Bro also includes support for DataSeries and Elasticsearch outputs as well as additional writers currently in development. While these new terms and ideas may give the impression that the Logging Framework is difficult to work with, the actual learning curve is, in actuality, not very steep at all. The abstraction built into the Logging Framework makes it such that a vast majority of scripts needs not go past the basics. In effect, writting to a log file is as simple as defining the format of your data, letting Bro know that you wish to create a new log, and then calling the ``Log::write()`` method to output log records. + +The Logging Framework is an are in Bro where, the more you see it used and the more you use it yourself, the more second nature the boilerplate parts of the code will become. As such, let's work through a contrived example of simply logging the digits 1 through 10 and their corresponding factorials to the default ASCII log writer. It's always best to work through the problem once, simulating the desired output with ``print`` and ``fmt`` before attempting to dive into the Logging Framework. Below is a script that defines a factorial function to recursively calculate the factorial of a unsigned integer passed as an argument to the function. Using ``print`` and ``fmt`` we can ensure that Bro can perform these calculations correctly as well get an idea of the answers ourselves. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_01.bro + :language: bro + :linenos: + :lines: 4-25 + +.. btest:: framework_logging_factorial_01 + + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_01.bro + + + + diff --git a/testing/btest/Baseline/doc.manual.framework_logging_factorial_01/.stdout b/testing/btest/Baseline/doc.manual.framework_logging_factorial_01/.stdout new file mode 100644 index 0000000000..db47b283d0 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.framework_logging_factorial_01/.stdout @@ -0,0 +1,10 @@ +1 +2 +6 +24 +120 +720 +5040 +40320 +362880 +3628800 diff --git a/testing/btest/doc/manual/framework_logging_factorial_01.bro b/testing/btest/doc/manual/framework_logging_factorial_01.bro new file mode 100644 index 0000000000..961ee584bc --- /dev/null +++ b/testing/btest/doc/manual/framework_logging_factorial_01.bro @@ -0,0 +1,27 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +module Factor; + +function factorial(n: count): count + { + if ( n == 0 ) + { + return 1; + } + else + { + return ( n * factorial(n - 1) ); + } + } + +event bro_init() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + for ( n in numbers ) + { + print fmt("%d", factorial(numbers[n])); + } + } + + From 2e55399a85939df080e7f6942bff649212089108 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 18 Mar 2013 23:27:31 -0400 Subject: [PATCH 046/881] Correction of spelling mistakes. --- doc/user-manual/scripting.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 8e7d06d493..e4f699f2c1 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -456,9 +456,9 @@ Logging Framework Armed with a decent understanding of the data types and data structures in Bro, exploring the various frameworks available is a much more rewarding effort. The framework with which most users are likely to have the most interaction is the Logging Framework. Designed in such a way to so as to abstract much of the process of creating a file and appending ordered and organized data into it, the Logging Framework makes use of some potentially unfamiliar nomenclature. Specifically, Log streams, Filters and Writers are simply abstractions of the processes required to manage a high rate of incoming logs while maintaining full operability. If you've seen Bro employed in an environment with a large connection, you know that logs are produced incredibly quickly; the ability to process a large set of data and write it to disk is due to the design of the Logging Framework. -Data is written to a Log stream based on decision making processes in Bro's scriptland. Log streams correspond to a single log as defined by the set of name value pairs that make up its fields. That data can then be filtered, modified, or redirected with Logging Filters which, by default, are set to log everything. Filters can be used to break log files into subsets or duplicate that information to another output. The final output of the data is defined by the writer. Bro's default writer is simple tab separated ASCII files but Bro also includes support for DataSeries and Elasticsearch outputs as well as additional writers currently in development. While these new terms and ideas may give the impression that the Logging Framework is difficult to work with, the actual learning curve is, in actuality, not very steep at all. The abstraction built into the Logging Framework makes it such that a vast majority of scripts needs not go past the basics. In effect, writting to a log file is as simple as defining the format of your data, letting Bro know that you wish to create a new log, and then calling the ``Log::write()`` method to output log records. +Data is written to a Log stream based on decision making processes in Bro's scriptland. Log streams correspond to a single log as defined by the set of name value pairs that make up its fields. That data can then be filtered, modified, or redirected with Logging Filters which, by default, are set to log everything. Filters can be used to break log files into subsets or duplicate that information to another output. The final output of the data is defined by the writer. Bro's default writer is simple tab separated ASCII files but Bro also includes support for DataSeries and Elasticsearch outputs as well as additional writers currently in development. While these new terms and ideas may give the impression that the Logging Framework is difficult to work with, the actual learning curve is, in actuality, not very steep at all. The abstraction built into the Logging Framework makes it such that a vast majority of scripts needs not go past the basics. In effect, writing to a log file is as simple as defining the format of your data, letting Bro know that you wish to create a new log, and then calling the ``Log::write()`` method to output log records. -The Logging Framework is an are in Bro where, the more you see it used and the more you use it yourself, the more second nature the boilerplate parts of the code will become. As such, let's work through a contrived example of simply logging the digits 1 through 10 and their corresponding factorials to the default ASCII log writer. It's always best to work through the problem once, simulating the desired output with ``print`` and ``fmt`` before attempting to dive into the Logging Framework. Below is a script that defines a factorial function to recursively calculate the factorial of a unsigned integer passed as an argument to the function. Using ``print`` and ``fmt`` we can ensure that Bro can perform these calculations correctly as well get an idea of the answers ourselves. +The Logging Framework is an are in Bro where, the more you see it used and the more you use it yourself, the more second nature the boilerplate parts of the code will become. As such, let's work through a contrived example of simply logging the digits 1 through 10 and their corresponding factorial to the default ASCII log writer. It's always best to work through the problem once, simulating the desired output with ``print`` and ``fmt`` before attempting to dive into the Logging Framework. Below is a script that defines a factorial function to recursively calculate the factorial of a unsigned integer passed as an argument to the function. Using ``print`` and ``fmt`` we can ensure that Bro can perform these calculations correctly as well get an idea of the answers ourselves. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_01.bro :language: bro @@ -472,3 +472,5 @@ The Logging Framework is an are in Bro where, the more you see it used and the m + + From 9ae8487844528c553e49fa72f0c2ba93416030fd Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 18 Mar 2013 23:44:36 -0400 Subject: [PATCH 047/881] Logging Framework (contrived) example: Logging factorials. --- doc/user-manual/scripting.rst | 14 ++++++- .../factor.log | 19 +++++++++ .../manual/framework_logging_factorial_02.bro | 41 +++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.framework_logging_factorial_02/factor.log create mode 100644 testing/btest/doc/manual/framework_logging_factorial_02.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index e4f699f2c1..4ef00ab5ef 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -469,8 +469,18 @@ The Logging Framework is an are in Bro where, the more you see it used and the m @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_01.bro - - +The output of the script aligns with what we expect so now it's time to integrate the Logging Framework. As mentioned above we have to perform a few steps before we can issue the ``Log::write()`` method and produce a logfile. As we are working within a namespace and informing an outside entity of functionality internal to the namespace, we use an ``export{}`` block. First we need to inform Bro that we are going to be adding another Log stream by adding a value to the ``Log::ID`` enumerable. In line 3 of the script, we append the value ``LOG`` to the Log::ID enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs that make up the data of our logs and dictate its format. Lines 5 through 9 define a new datatype called an Info record (actually, ``Factor::Info``) with two fields, both unsigned integers. The next step is to create the logging stream with ``Log::create_stream()`` which takes a Log::ID and a record as its arguments. In this example, on line 28, we call the ``Log::create_stream()`` method and pass ``Factor::LOG`` and the ``Factor::Info`` record as arguments. From here on out, if we issue the ``Log::write()`` command with the correct Log::ID and a properly formatted ``Factor::Info`` record, a log entry will be generated. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_02.bro + :language: bro + :linenos: + :lines: 4-40 + +Running the script, instead of generating logging information to stdout, no output is created. Instead the output is all in factor.log, properly formatted and organized. + +.. btest:: framework_logging_factorial_02 + + @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_02.bro diff --git a/testing/btest/Baseline/doc.manual.framework_logging_factorial_02/factor.log b/testing/btest/Baseline/doc.manual.framework_logging_factorial_02/factor.log new file mode 100644 index 0000000000..c643116265 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.framework_logging_factorial_02/factor.log @@ -0,0 +1,19 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path factor +#open 2013-03-19-03-25-33 +#fields num factorial_num +#types count count +1 1 +2 2 +3 6 +4 24 +5 120 +6 720 +7 5040 +8 40320 +9 362880 +10 3628800 +#close 2013-03-19-03-25-33 diff --git a/testing/btest/doc/manual/framework_logging_factorial_02.bro b/testing/btest/doc/manual/framework_logging_factorial_02.bro new file mode 100644 index 0000000000..94246cb07c --- /dev/null +++ b/testing/btest/doc/manual/framework_logging_factorial_02.bro @@ -0,0 +1,41 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff factor.log + +module Factor; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + num: count &log; + factorial_num: count &log; + }; + } + +function factorial(n: count): count + { + if ( n == 0 ) + { + return 1; + } + else + { + return ( n * factorial(n - 1) ); + } + } + + +event bro_init() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + Log::create_stream(LOG, [$columns=Info]); + + for ( n in numbers ) + { + Log::write( Factor::LOG, [$num=numbers[n], + $factorial_num=factorial(numbers[n])]); + } + } + + From b4a92432e39d8155148d1a558e2e605a49445a5e Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 19 Mar 2013 23:28:48 -0400 Subject: [PATCH 048/881] Changes to framework_logging_factorial_02.bro to make the call to Log::create_stream() more distinct. --- doc/user-manual/scripting.rst | 5 +++-- .../doc/manual/framework_logging_factorial_02.bro | 11 +++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 4ef00ab5ef..7762915506 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -469,18 +469,19 @@ The Logging Framework is an are in Bro where, the more you see it used and the m @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_01.bro -The output of the script aligns with what we expect so now it's time to integrate the Logging Framework. As mentioned above we have to perform a few steps before we can issue the ``Log::write()`` method and produce a logfile. As we are working within a namespace and informing an outside entity of functionality internal to the namespace, we use an ``export{}`` block. First we need to inform Bro that we are going to be adding another Log stream by adding a value to the ``Log::ID`` enumerable. In line 3 of the script, we append the value ``LOG`` to the Log::ID enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs that make up the data of our logs and dictate its format. Lines 5 through 9 define a new datatype called an Info record (actually, ``Factor::Info``) with two fields, both unsigned integers. The next step is to create the logging stream with ``Log::create_stream()`` which takes a Log::ID and a record as its arguments. In this example, on line 28, we call the ``Log::create_stream()`` method and pass ``Factor::LOG`` and the ``Factor::Info`` record as arguments. From here on out, if we issue the ``Log::write()`` command with the correct Log::ID and a properly formatted ``Factor::Info`` record, a log entry will be generated. +The output of the script aligns with what we expect so now it's time to integrate the Logging Framework. As mentioned above we have to perform a few steps before we can issue the ``Log::write()`` method and produce a logfile. As we are working within a namespace and informing an outside entity of workings and data internal to the namespace, we use an ``export{}`` block. First we need to inform Bro that we are going to be adding another Log stream by adding a value to the ``Log::ID`` enumerable. In line 3 of the script, we append the value ``LOG`` to the Log::ID enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs that make up the data of our logs and dictate its format. Lines 5 through 9 define a new datatype called an Info record (actually, ``Factor::Info``) with two fields, both unsigned integers. The next step is to create the logging stream with ``Log::create_stream()`` which takes a Log::ID and a record as its arguments. In this example, on line 28, we call the ``Log::create_stream()`` method and pass ``Factor::LOG`` and the ``Factor::Info`` record as arguments. From here on out, if we issue the ``Log::write()`` command with the correct Log::ID and a properly formatted ``Factor::Info`` record, a log entry will be generated. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_02.bro :language: bro :linenos: :lines: 4-40 -Running the script, instead of generating logging information to stdout, no output is created. Instead the output is all in factor.log, properly formatted and organized. +Now, if we run the new version of the script, instead of generating logging information to stdout, no output is created. Instead the output is all in factor.log, properly formatted and organized. .. btest:: framework_logging_factorial_02 @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_02.bro +While the previous example is a simplistic one, it serves to demonstrate the small pieces of script that need to be in place in order to generate logs. For example, it's common to call ``Log::create_stream()`` in ``bro_init()`` and while in a live example, determinging when to call ``Log::write()`` would likely be done in an event handler, in this case we use ``bro_done()``. diff --git a/testing/btest/doc/manual/framework_logging_factorial_02.bro b/testing/btest/doc/manual/framework_logging_factorial_02.bro index 94246cb07c..2a6fb10d1a 100644 --- a/testing/btest/doc/manual/framework_logging_factorial_02.bro +++ b/testing/btest/doc/manual/framework_logging_factorial_02.bro @@ -24,18 +24,17 @@ function factorial(n: count): count } } - event bro_init() { - local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); - Log::create_stream(LOG, [$columns=Info]); - + } + +event bro_done() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); for ( n in numbers ) { Log::write( Factor::LOG, [$num=numbers[n], $factorial_num=factorial(numbers[n])]); } } - - From 65627209c1db39b6b3bc7539f2c14b81529fb33c Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 19 Mar 2013 23:40:29 -0400 Subject: [PATCH 049/881] Include a brief description of what &log does. --- doc/user-manual/scripting.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 7762915506..b1bb08d681 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -469,7 +469,7 @@ The Logging Framework is an are in Bro where, the more you see it used and the m @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_01.bro -The output of the script aligns with what we expect so now it's time to integrate the Logging Framework. As mentioned above we have to perform a few steps before we can issue the ``Log::write()`` method and produce a logfile. As we are working within a namespace and informing an outside entity of workings and data internal to the namespace, we use an ``export{}`` block. First we need to inform Bro that we are going to be adding another Log stream by adding a value to the ``Log::ID`` enumerable. In line 3 of the script, we append the value ``LOG`` to the Log::ID enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs that make up the data of our logs and dictate its format. Lines 5 through 9 define a new datatype called an Info record (actually, ``Factor::Info``) with two fields, both unsigned integers. The next step is to create the logging stream with ``Log::create_stream()`` which takes a Log::ID and a record as its arguments. In this example, on line 28, we call the ``Log::create_stream()`` method and pass ``Factor::LOG`` and the ``Factor::Info`` record as arguments. From here on out, if we issue the ``Log::write()`` command with the correct Log::ID and a properly formatted ``Factor::Info`` record, a log entry will be generated. +The output of the script aligns with what we expect so now it's time to integrate the Logging Framework. As mentioned above we have to perform a few steps before we can issue the ``Log::write()`` method and produce a logfile. As we are working within a namespace and informing an outside entity of workings and data internal to the namespace, we use an ``export{}`` block. First we need to inform Bro that we are going to be adding another Log stream by adding a value to the ``Log::ID`` enumerable. In line 3 of the script, we append the value ``LOG`` to the Log::ID enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs that make up the data of our logs and dictate its format. Lines 5 through 9 define a new datatype called an Info record (actually, ``Factor::Info``) with two fields, both unsigned integers. Each of the fields in the ``Factor::Log`` record type include the ``&log`` attribute, indicating that these fields should be passed to the Logging Framework when ``Log::write()`` is called. Were there to be any name value pairs without the ``&log`` attribute, those fields would simply be ignored during logging but remain available for the lifespan of the variable. The next step is to create the logging stream with ``Log::create_stream()`` which takes a Log::ID and a record as its arguments. In this example, on line 28, we call the ``Log::create_stream()`` method and pass ``Factor::LOG`` and the ``Factor::Info`` record as arguments. From here on out, if we issue the ``Log::write()`` command with the correct Log::ID and a properly formatted ``Factor::Info`` record, a log entry will be generated. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_02.bro :language: bro @@ -482,6 +482,4 @@ Now, if we run the new version of the script, instead of generating logging info @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_02.bro -While the previous example is a simplistic one, it serves to demonstrate the small pieces of script that need to be in place in order to generate logs. For example, it's common to call ``Log::create_stream()`` in ``bro_init()`` and while in a live example, determinging when to call ``Log::write()`` would likely be done in an event handler, in this case we use ``bro_done()``. - - +While the previous example is a simplistic one, it serves to demonstrate the small pieces of script that need to be in place in order to generate logs. For example, it's common to call ``Log::create_stream()`` in ``bro_init()`` and while in a live example, determining when to call ``Log::write()`` would likely be done in an event handler, in this case we use ``bro_done()``. From 44892cd78dfd66fb186d7f31ae090e3da546242a Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Wed, 20 Mar 2013 00:02:20 -0400 Subject: [PATCH 050/881] Split logging via Filters in the Logging Framework. --- doc/user-manual/scripting.rst | 14 +++++ .../factor-mod5.log | 15 +++++ .../factor-non5.log | 13 ++++ .../manual/framework_logging_factorial_03.bro | 60 +++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 testing/btest/Baseline/doc.manual.framework_logging_factorial_03/factor-mod5.log create mode 100644 testing/btest/Baseline/doc.manual.framework_logging_factorial_03/factor-non5.log create mode 100644 testing/btest/doc/manual/framework_logging_factorial_03.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index b1bb08d681..711773af99 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -483,3 +483,17 @@ Now, if we run the new version of the script, instead of generating logging info @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_02.bro While the previous example is a simplistic one, it serves to demonstrate the small pieces of script that need to be in place in order to generate logs. For example, it's common to call ``Log::create_stream()`` in ``bro_init()`` and while in a live example, determining when to call ``Log::write()`` would likely be done in an event handler, in this case we use ``bro_done()``. + +If you've already spent time with a deployment of Bro, you've likely had the opportunity to view, search through, or manipulate the logs produced by the Logging Framework. The log output from a default installation of Bro is substantial to say the least, however, there are times in which the way the Logging Framework by default isn't ideal for the situation. This can range from needing to log more or less data with each call to ``Log::write()`` or even the need to split log files based on arbitrary logic. In the later case, Filters come into play along with the Logging Framework. Filters grant a level of customization to Bro's scriptland, allowing the scripter to include or exclude fields in the log and even make alterations to the path of the file in which the logs are being placed. Each stream, when created, is given a default filter called, not surprisingly, ``default``. When using the ``default`` filter, every key value pair with the ``&log`` attribute is written to a single file. For the example we've been using, let's extend it so as to write any factorial which is a factor of 5 to an alternate file, while writing the remaining logs to factor.log. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_02.bro + :language: bro + :linenos: + :lines: 43-60 + +To dynamically alter the file in which a stream writes its logs a filter can specify function returns a string to be used as the filename for the current call to ``Log::write()``. The definition for this function has to take as its parameters a Log::ID called id, a string called path and the appropraite record type for the logs called "rec". You can see the definition of ``mod5`` used in this example on line one conforms to that requirement. The function simply returns "factor-mod5" if the factorial is divisible evenly by 5, otherwise, it retuns "factor-non5". In the additional ``bro_init()`` event handler, we define a locally scoped ``Log::Filter`` and assign it a record that defines the ``name`` and ``path_func`` fields. We then call ``Log::add_filter()`` to add the filter to the ``Factor::LOG`` Log::ID and call ``Log::remove_filter()`` to remove the ``default`` filter for Factor::LOG. Had we not removed the ``default`` filter, we'd have ended up with three log files: factor-mod5.log with all the factorials that are a factors of 5, factor-non5.log with the factorials that are not factors of 5, and factor.log which would have included all factorials. + + + + + diff --git a/testing/btest/Baseline/doc.manual.framework_logging_factorial_03/factor-mod5.log b/testing/btest/Baseline/doc.manual.framework_logging_factorial_03/factor-mod5.log new file mode 100644 index 0000000000..2a466484d6 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.framework_logging_factorial_03/factor-mod5.log @@ -0,0 +1,15 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path factor-mod5 +#open 2013-03-20-03-22-52 +#fields num factorial_num +#types count count +5 120 +6 720 +7 5040 +8 40320 +9 362880 +10 3628800 +#close 2013-03-20-03-22-52 diff --git a/testing/btest/Baseline/doc.manual.framework_logging_factorial_03/factor-non5.log b/testing/btest/Baseline/doc.manual.framework_logging_factorial_03/factor-non5.log new file mode 100644 index 0000000000..4430dcc8a4 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.framework_logging_factorial_03/factor-non5.log @@ -0,0 +1,13 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path factor-non5 +#open 2013-03-20-03-22-52 +#fields num factorial_num +#types count count +1 1 +2 2 +3 6 +4 24 +#close 2013-03-20-03-22-52 diff --git a/testing/btest/doc/manual/framework_logging_factorial_03.bro b/testing/btest/doc/manual/framework_logging_factorial_03.bro new file mode 100644 index 0000000000..967229bd94 --- /dev/null +++ b/testing/btest/doc/manual/framework_logging_factorial_03.bro @@ -0,0 +1,60 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff factor-mod5.log +# @TEST-EXEC: btest-diff factor-non5.log + +module Factor; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + num: count &log; + factorial_num: count &log; + }; + } + +function factorial(n: count): count + { + if ( n == 0 ) + { + return 1; + } + else + { + return ( n * factorial(n - 1) ); + } + } + +event bro_init() + { + Log::create_stream(LOG, [$columns=Info]); + } + +event bro_done() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + for ( n in numbers ) + { + Log::write( Factor::LOG, [$num=numbers[n], + $factorial_num=factorial(numbers[n])]); + } + } + +function mod5(id: Log::ID, path: string, rec: Factor::Info) : string + { + if ( rec$factorial_num % 5 == 0 ) + { + return "factor-mod5"; + } + else + { + return "factor-non5"; + } + } + +event bro_init() + { + local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; + Log::add_filter(Factor::LOG, filter); + Log::remove_filter(Factor::LOG, "default"); + } \ No newline at end of file From a699470145aefabb3657463e3c493c4b6a0e281d Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Wed, 20 Mar 2013 00:03:08 -0400 Subject: [PATCH 051/881] Spelling fixes. --- doc/user-manual/scripting.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index 711773af99..bd436fff08 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -491,7 +491,7 @@ If you've already spent time with a deployment of Bro, you've likely had the opp :linenos: :lines: 43-60 -To dynamically alter the file in which a stream writes its logs a filter can specify function returns a string to be used as the filename for the current call to ``Log::write()``. The definition for this function has to take as its parameters a Log::ID called id, a string called path and the appropraite record type for the logs called "rec". You can see the definition of ``mod5`` used in this example on line one conforms to that requirement. The function simply returns "factor-mod5" if the factorial is divisible evenly by 5, otherwise, it retuns "factor-non5". In the additional ``bro_init()`` event handler, we define a locally scoped ``Log::Filter`` and assign it a record that defines the ``name`` and ``path_func`` fields. We then call ``Log::add_filter()`` to add the filter to the ``Factor::LOG`` Log::ID and call ``Log::remove_filter()`` to remove the ``default`` filter for Factor::LOG. Had we not removed the ``default`` filter, we'd have ended up with three log files: factor-mod5.log with all the factorials that are a factors of 5, factor-non5.log with the factorials that are not factors of 5, and factor.log which would have included all factorials. +To dynamically alter the file in which a stream writes its logs a filter can specify function returns a string to be used as the filename for the current call to ``Log::write()``. The definition for this function has to take as its parameters a Log::ID called id, a string called path and the appropriate record type for the logs called "rec". You can see the definition of ``mod5`` used in this example on line one conforms to that requirement. The function simply returns "factor-mod5" if the factorial is divisible evenly by 5, otherwise, it returns "factor-non5". In the additional ``bro_init()`` event handler, we define a locally scoped ``Log::Filter`` and assign it a record that defines the ``name`` and ``path_func`` fields. We then call ``Log::add_filter()`` to add the filter to the ``Factor::LOG`` Log::ID and call ``Log::remove_filter()`` to remove the ``default`` filter for Factor::LOG. Had we not removed the ``default`` filter, we'd have ended up with three log files: factor-mod5.log with all the factorials that are a factors of 5, factor-non5.log with the factorials that are not factors of 5, and factor.log which would have included all factorials. From e755bf1b540f99a96e468889b87bb418813ff090 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 24 Mar 2013 21:58:28 -0400 Subject: [PATCH 052/881] Hooking into the Logging Framework. --- doc/user-manual/scripting.rst | 14 +++-- .../manual/framework_logging_factorial_04.bro | 62 +++++++++++++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 testing/btest/doc/manual/framework_logging_factorial_04.bro diff --git a/doc/user-manual/scripting.rst b/doc/user-manual/scripting.rst index bd436fff08..adc35b127e 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/user-manual/scripting.rst @@ -51,7 +51,7 @@ The export section redefines an enumerable constant that describes the type of n :linenos: :lines: 26-44 -The workhorse of the script is contained in the event handler for log_http. The log_http event is defined as an event-hook in the base/protocols/http/main.bro script and allows scripts to handle a connection as it is being passed to the logging framework. The event handler is passed an HTTP::Info data structure which will be referred to as "rec" in body of the event handler. +The workhorse of the script is contained in the event handler for ``log_http``. The ``log_http`` event is defined as an event-hook in the base/protocols/http/main.bro script and allows scripts to handle a connection as it is being passed to the logging framework. The event handler is passed an HTTP::Info data structure which will be referred to as "rec" in body of the event handler. An if statement is used to check for the existence of a data structure named "md5" nested within the rec data structure. Bro uses the "$" as a deference operator and as such, and it is employed in this script to check if rec$md5 is present by including the "?" operator within the path. If the rec data structure includes a nested data structure named "md5", the statement is processed as true and a local variable named "hash_domain" is provisioned and given a format string based on the contents of rec$md5 to produce a valid DNS lookup. @@ -484,16 +484,20 @@ Now, if we run the new version of the script, instead of generating logging info While the previous example is a simplistic one, it serves to demonstrate the small pieces of script that need to be in place in order to generate logs. For example, it's common to call ``Log::create_stream()`` in ``bro_init()`` and while in a live example, determining when to call ``Log::write()`` would likely be done in an event handler, in this case we use ``bro_done()``. -If you've already spent time with a deployment of Bro, you've likely had the opportunity to view, search through, or manipulate the logs produced by the Logging Framework. The log output from a default installation of Bro is substantial to say the least, however, there are times in which the way the Logging Framework by default isn't ideal for the situation. This can range from needing to log more or less data with each call to ``Log::write()`` or even the need to split log files based on arbitrary logic. In the later case, Filters come into play along with the Logging Framework. Filters grant a level of customization to Bro's scriptland, allowing the scripter to include or exclude fields in the log and even make alterations to the path of the file in which the logs are being placed. Each stream, when created, is given a default filter called, not surprisingly, ``default``. When using the ``default`` filter, every key value pair with the ``&log`` attribute is written to a single file. For the example we've been using, let's extend it so as to write any factorial which is a factor of 5 to an alternate file, while writing the remaining logs to factor.log. +If you've already spent time with a deployment of Bro, you've likely had the opportunity to view, search through, or manipulate the logs produced by the Logging Framework. The log output from a default installation of Bro is substantial to say the least, however, there are times in which the way the Logging Framework by default isn't ideal for the situation. This can range from needing to log more or less data with each call to ``Log::write()`` or even the need to split log files based on arbitrary logic. In the later case, Filters come into play along with the Logging Framework. Filters grant a level of customization to Bro's scriptland, allowing the script writer to include or exclude fields in the log and even make alterations to the path of the file in which the logs are being placed. Each stream, when created, is given a default filter called, not surprisingly, ``default``. When using the ``default`` filter, every key value pair with the ``&log`` attribute is written to a single file. For the example we've been using, let's extend it so as to write any factorial which is a factor of 5 to an alternate file, while writing the remaining logs to factor.log. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_02.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_03.bro :language: bro :linenos: :lines: 43-60 To dynamically alter the file in which a stream writes its logs a filter can specify function returns a string to be used as the filename for the current call to ``Log::write()``. The definition for this function has to take as its parameters a Log::ID called id, a string called path and the appropriate record type for the logs called "rec". You can see the definition of ``mod5`` used in this example on line one conforms to that requirement. The function simply returns "factor-mod5" if the factorial is divisible evenly by 5, otherwise, it returns "factor-non5". In the additional ``bro_init()`` event handler, we define a locally scoped ``Log::Filter`` and assign it a record that defines the ``name`` and ``path_func`` fields. We then call ``Log::add_filter()`` to add the filter to the ``Factor::LOG`` Log::ID and call ``Log::remove_filter()`` to remove the ``default`` filter for Factor::LOG. Had we not removed the ``default`` filter, we'd have ended up with three log files: factor-mod5.log with all the factorials that are a factors of 5, factor-non5.log with the factorials that are not factors of 5, and factor.log which would have included all factorials. +The ability of Bro to generate easily customizable and extensible logs which remain easily parsable is a big part of the reason Bro has gained a large measure of respect. In fact, it's difficult at times to think of something that Bro doesn't log and as such, it is often advantageous for analysts and systems architects to instead hook into the logging framework to be able to perform custom actions based upon the data being sent to the Logging Frame. To that end, every default log stream in Bro generates a custom event that can be handled by anyone wishing to act upon the data being sent to the stream. By convention these events are usually in the format ``log_x`` where x is the name of the logging stream; as such the event raised for every log sent to the Logging Framework by the HTTP parser would be ``log_http``. In fact, we've already seen a script handle the ``log_http`` event when we broke down how the ``detect-MHR.bro`` script worked. In that example, as each log entry was sent to the logging framework, post-processing was taking place in the ``log_http`` event. Instead of using an external script to parse the ``http.log`` file and do post-processing for the entry, post-processing can be done in real time in Bro. +Telling Bro to raise an event in your own Logging stream is as simple as exporting that event name and then adding that event in the call to ``Log::create_stream``. Going back to our simple example of logging the factorial of an integer, we add ``log_factor`` to the ``export`` block and define the value to be passed to it, in this case the ``Factor::Info`` record. We then list the ``log_factor`` function as the ``$ev`` field in the call to ``Log::create_stream`` - - +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_04.bro + :language: bro + :linenos: + :lines: 4-62 diff --git a/testing/btest/doc/manual/framework_logging_factorial_04.bro b/testing/btest/doc/manual/framework_logging_factorial_04.bro new file mode 100644 index 0000000000..e3b50af829 --- /dev/null +++ b/testing/btest/doc/manual/framework_logging_factorial_04.bro @@ -0,0 +1,62 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff factor-mod5.log +# @TEST-EXEC: btest-diff factor-non5.log + +module Factor; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + num: count &log; + factorial_num: count &log; + }; + + global log_factor: event(rec: Info); + } + +function factorial(n: count): count + { + if ( n == 0 ) + { + return 1; + } + else + { + return ( n * factorial(n - 1) ); + } + } + +event bro_init() + { + Log::create_stream(LOG, [$columns=Info, $ev=log_factorial]); + } + +event bro_done() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + for ( n in numbers ) + { + Log::write( Factor::LOG, [$num=numbers[n], + $factorial_num=factorial(numbers[n])]); + } + } + +function mod5(id: Log::ID, path: string, rec: Factor::Info) : string + { + if ( rec$factorial_num % 5 == 0 ) + { + return "factor-mod5"; + } + else + { + return "factor-non5"; + } + } + +event bro_init() + { + local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; + Log::add_filter(Factor::LOG, filter); + Log::remove_filter(Factor::LOG, "default"); + } \ No newline at end of file From a4998f37801c166dda28c8aea8f73802ad604c31 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 24 Mar 2013 22:01:08 -0400 Subject: [PATCH 053/881] Typo fix and baselines for hooking the log framework. --- .../factor-mod5.log | 15 +++++++++++++++ .../factor-non5.log | 13 +++++++++++++ .../doc/manual/framework_logging_factorial_04.bro | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 testing/btest/Baseline/doc.manual.framework_logging_factorial_04/factor-mod5.log create mode 100644 testing/btest/Baseline/doc.manual.framework_logging_factorial_04/factor-non5.log diff --git a/testing/btest/Baseline/doc.manual.framework_logging_factorial_04/factor-mod5.log b/testing/btest/Baseline/doc.manual.framework_logging_factorial_04/factor-mod5.log new file mode 100644 index 0000000000..6b50ca55e7 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.framework_logging_factorial_04/factor-mod5.log @@ -0,0 +1,15 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path factor-mod5 +#open 2013-03-25-02-00-12 +#fields num factorial_num +#types count count +5 120 +6 720 +7 5040 +8 40320 +9 362880 +10 3628800 +#close 2013-03-25-02-00-12 diff --git a/testing/btest/Baseline/doc.manual.framework_logging_factorial_04/factor-non5.log b/testing/btest/Baseline/doc.manual.framework_logging_factorial_04/factor-non5.log new file mode 100644 index 0000000000..d272ba48a9 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.framework_logging_factorial_04/factor-non5.log @@ -0,0 +1,13 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path factor-non5 +#open 2013-03-25-02-00-12 +#fields num factorial_num +#types count count +1 1 +2 2 +3 6 +4 24 +#close 2013-03-25-02-00-12 diff --git a/testing/btest/doc/manual/framework_logging_factorial_04.bro b/testing/btest/doc/manual/framework_logging_factorial_04.bro index e3b50af829..49aef83ffc 100644 --- a/testing/btest/doc/manual/framework_logging_factorial_04.bro +++ b/testing/btest/doc/manual/framework_logging_factorial_04.bro @@ -29,7 +29,7 @@ function factorial(n: count): count event bro_init() { - Log::create_stream(LOG, [$columns=Info, $ev=log_factorial]); + Log::create_stream(LOG, [$columns=Info, $ev=log_factor]); } event bro_done() From 12e4dd806653febfa7591e0e9dd8a10c1c343a90 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 27 Mar 2013 13:47:02 -0700 Subject: [PATCH 054/881] Moving the quickstart guide back in. --- doc/user-manual/index.rst | 3 +- doc/user-manual/quickstart.rst | 422 +++++++++++++++++++++++++++++++++ doc/user-manual/starting.rst | 4 - 3 files changed, 424 insertions(+), 5 deletions(-) create mode 100644 doc/user-manual/quickstart.rst delete mode 100644 doc/user-manual/starting.rst diff --git a/doc/user-manual/index.rst b/doc/user-manual/index.rst index 971d3e386b..ad3e516a78 100644 --- a/doc/user-manual/index.rst +++ b/doc/user-manual/index.rst @@ -8,5 +8,6 @@ User Manual :numbered: intro.rst - starting.rst + quickstart.rst + scripting.rst diff --git a/doc/user-manual/quickstart.rst b/doc/user-manual/quickstart.rst new file mode 100644 index 0000000000..9f64e36d89 --- /dev/null +++ b/doc/user-manual/quickstart.rst @@ -0,0 +1,422 @@ + +================= +Quick Start Guide +================= + +.. rst-class:: opening + + The short story for getting Bro up and running in a simple configuration + for analysis of either live traffic from a network interface or a packet + capture trace file. + +.. contents:: + +Installation +============ + +Bro works on most modern, Unix-based systems and requires no custom +hardware. It can be downloaded in either pre-built binary package or +source code forms. See :doc:`Installing Bro ` for instructions +on how to install Bro. + +.. note:: Below, ``$PREFIX`` is used to reference the Bro installation + root directory. + +Using BroControl +================ + +BroControl is an interactive shell for easily operating/managing Bro +installations on a single system or even across multiple systems in a +traffic-monitoring cluster. + +A Minimal Starting Configuration +-------------------------------- + +These are the basic configuration changes to make for a minimal BroControl installation +that will manage a single Bro instance on the ``localhost``: + +1) In ``$PREFIX/etc/node.cfg``, set the right interface to monitor. +2) In ``$PREFIX/etc/networks.cfg``, comment out the default settings and add + the networks that Bro will consider local to the monitored environment. +3) In ``$PREFIX/etc/broctl.cfg``, change the ``MailTo`` email address to a + desired recipient and the ``LogRotationInterval`` to a desired log + archival frequency. + +Now start the BroControl shell like: + +.. console:: + + broctl + +Since this is the first-time use of the shell, perform an initial installation +of the BroControl configuration: + +.. console:: + + [BroControl] > install + +Then start up a Bro instance: + +.. console:: + + [BroControl] > start + +If there are errors while trying to start the Bro instance, you can +can view the details with the ``diag`` command. If started successfully, +the Bro instance will begin analyzing traffic according to a default +policy and output the results in ``$PREFIX/logs``. + +.. note:: The user starting BroControl needs permission to capture + network traffic. If you are not root, you may need to grant further + privileges to the account you're using; see the :doc:`FAQ `. + Also, if it looks like Bro is not seeing any traffic, check out + the FAQ entry on checksum offloading. + +You can leave it running for now, but to stop this Bro instance you would do: + +.. console:: + + [BroControl] > stop + +We also recommend to insert the following entry into `crontab`:: + + 0-59/5 * * * * $PREFIX/bin/broctl cron + +This will perform a number of regular housekeeping tasks, including +verifying that the process is still running (and restarting if not in +case of any abnormal termination). + +Browsing Log Files +------------------ + +By default, logs are written out in human-readable (ASCII) format and +data is organized into columns (tab-delimited). Logs that are part of +the current rotation interval are accumulated in +``$PREFIX/logs/current/`` (if Bro is not running, the directory will +be empty). For example, the ``http.log`` contains the results of Bro +HTTP protocol analysis. Here are the first few columns of +``http.log``:: + + # ts uid orig_h orig_p resp_h resp_p + 1311627961.8 HSH4uV8KVJg 192.168.1.100 52303 192.150.187.43 80 + +Logs that deal with analysis of a network protocol will often start like this: +a timestamp, a unique connection identifier (UID), and a connection 4-tuple +(originator host/port and responder host/port). The UID can be used to +identify all logged activity (possibly across multiple log files) associated +with a given connection 4-tuple over its lifetime. + +The remaining columns of protocol-specific logs then detail the +protocol-dependent activity that's occurring. E.g. ``http.log``'s next few +columns (shortened for brevity) show a request to the root of Bro website:: + + # method host uri referrer user_agent + GET bro.org / - <...>Chrome/12.0.742.122<...> + +Some logs are worth explicit mention: + + ``weird.log`` + Contains unusual/exceptional activity that can indicate + malformed connections, traffic that doesn't conform to a particular + protocol, malfunctioning/misconfigured hardware, or even an attacker + attempting to avoid/confuse a sensor. Without context, it's hard to + judge whether this category of activity is interesting and so that is + left up to the user to configure. + + ``notice.log`` + Identifies specific activity that Bro recognizes as + potentially interesting, odd, or bad. In Bro-speak, such + activity is called a "notice". + + +By default, ``BroControl`` regularly takes all the logs from +``$PREFIX/logs/current`` and archives/compresses them to a directory +named by date, e.g. ``$PREFIX/logs/2011-10-06``. The frequency at +which this is done can be configured via the ``LogRotationInterval`` +option in ``$PREFIX/etc/broctl.cfg``. + +Deployment Customization +------------------------ + +The goal of most Bro *deployments* may be to send email alarms when a network +event requires human intervention/investigation, but sometimes that conflicts +with Bro's goal as a *distribution* to remain policy and site neutral -- the +events on one network may be less noteworthy than the same events on another. +As a result, deploying Bro can be an iterative process of +updating its policy to take different actions for events that are noticed, and +using its scripting language to programmatically extend traffic analysis +in a precise way. + +One of the first steps to take in customizing Bro might be to get familiar +with the notices it can generate by default and either tone down or escalate +the action that's taken when specific ones occur. + +Let's say that we've been looking at the ``notice.log`` for a bit and see two +changes we want to make: + +1) ``SSL::Invalid_Server_Cert`` (found in the ``note`` column) is one type of + notice that means an SSL connection was established and the server's + certificate couldn't be validated using Bro's default trust roots, but + we want to ignore it. +2) ``SSH::Login`` is a notice type that is triggered when an SSH connection + attempt looks like it may have been successful, and we want email when + that happens, but only for certain servers. + +So we've defined *what* we want to do, but need to know *where* to do it. +The answer is to use a script written in the Bro programming language, so +let's do a quick intro to Bro scripting. + +Bro Scripts +~~~~~~~~~~~ + +Bro ships with many pre-written scripts that are highly customizable +to support traffic analysis for your specific environment. By +default, these will be installed into ``$PREFIX/share/bro`` and can be +identified by the use of a ``.bro`` file name extension. These files +should **never** be edited directly as changes will be lost when +upgrading to newer versions of Bro. The exception to this rule is the +directory ``$PREFIX/share/bro/site`` where local site-specific files +can be put without fear of being clobbered later. The other main +script directories under ``$PREFIX/share/bro`` are ``base`` and +``policy``. By default, Bro automatically loads all scripts under +``base`` (unless the ``-b`` command line option is supplied), which +deal either with collecting basic/useful state about network +activities or providing frameworks/utilities that extend Bro's +functionality without any performance cost. Scripts under the +``policy`` directory may be more situational or costly, and so users +must explicitly choose if they want to load them. + +The main entry point for the default analysis configuration of a standalone +Bro instance managed by BroControl is the ``$PREFIX/share/bro/site/local.bro`` +script. So we'll be adding to that in the following sections, but first +we have to figure out what to add. + +Redefining Script Option Variables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Many simple customizations just require you to redefine a variable +from a standard Bro script with your own value, using Bro's ``redef`` +operator. + +The typical way a standard Bro script advertises tweak-able options to users +is by defining variables with the ``&redef`` attribute and ``const`` qualifier. +A redefineable constant might seem strange, but what that really means is that +the variable's value may not change at run-time, but whose initial value can be +modified via the ``redef`` operator at parse-time. + +So let's continue on our path to modify the behavior for the two SSL +and SSH notices. Looking at :doc:`scripts/base/frameworks/notice/main`, +we see that it advertises: + +.. code:: bro + + module Notice; + + export { + ... + ## Ignored notice types. + const ignored_types: set[Notice::Type] = {} &redef; + } + +That's exactly what we want to do for the SSL notice. So add to ``local.bro``: + +.. code:: bro + + redef Notice::ignored_types += { SSL::Invalid_Server_Cert }; + +.. note:: The ``Notice`` namespace scoping is necessary here because the + variable was declared and exported inside the ``Notice`` module, but is + being referenced from outside of it. Variables declared and exported + inside a module do not have to be scoped if referring to them while still + inside the module. + +Then go into the BroControl shell to check whether the configuration change +is valid before installing it and then restarting the Bro instance: + +.. console:: + + [BroControl] > check + bro is ok. + [BroControl] > install + removing old policies in /usr/local/bro/spool/policy/site ... done. + removing old policies in /usr/local/bro/spool/policy/auto ... done. + creating policy directories ... done. + installing site policies ... done. + generating standalone-layout.bro ... done. + generating local-networks.bro ... done. + generating broctl-config.bro ... done. + updating nodes ... done. + [BroControl] > restart + stopping bro ... + starting bro ... + +Now that the SSL notice is ignored, let's look at how to send an email on +the SSH notice. The notice framework has a similar option called +``emailed_types``, but that can't differentiate between SSH servers and we +only want email for logins to certain ones. Then we come to the ``PolicyItem`` +record and ``policy`` set and realize that those are actually what get used +to implement the simple functionality of ``ignored_types`` and +``emailed_types``, but it's extensible such that the condition and action taken +on notices can be user-defined. + +In ``local.bro``, let's add a new ``PolicyItem`` record to the ``policy`` set +that only takes the email action for SSH logins to a defined set of servers: + +.. code:: bro + + const watched_servers: set[addr] = { + 192.168.1.100, + 192.168.1.101, + 192.168.1.102, + } &redef; + + redef Notice::policy += { + [$action = Notice::ACTION_EMAIL, + $pred(n: Notice::Info) = + { + return n$note == SSH::Login && n$id$resp_h in watched_servers; + } + ] + }; + +You'll just have to trust the syntax for now, but what we've done is +first declare our own variable to hold a set of watched addresses, +``watched_servers``; then added a record to the policy that will generate +an email on the condition that the predicate function evaluates to true, which +is whenever the notice type is an SSH login and the responding host stored +inside the ``Info`` record's connection field is in the set of watched servers. + +.. note:: record field member access is done with the '$' character + instead of a '.' as might be expected from other languages, in + order to avoid ambiguity with the builtin address type's use of '.' + in IPv4 dotted decimal representations. + +Remember, to finalize that configuration change perform the ``check``, +``install``, ``restart`` commands in that order inside the BroControl shell. + +Next Steps +---------- + +By this point, we've learned how to set up the most basic Bro instance and +tweak the most basic options. Here's some suggestions on what to explore next: + +* We only looked at how to change options declared in the notice framework, + there's many more options to look at in other script packages. +* Look at the scripts in ``$PREFIX/share/bro/policy`` for further ones + you may want to load. +* Reading the code of scripts that ship with Bro is also a great way to gain + understanding of the language and how you can start writing your own custom + analysis. +* Review the :doc:`FAQ `. +* Continue reading below for another mini-tutorial on using Bro as a standalone + command-line utility. + +Bro, the Command-Line Utility +============================= + +If you prefer not to use BroControl (e.g. don't need its automation and +management features), here's how to directly control Bro for your analysis +activities. + +Monitoring Live Traffic +----------------------- + +Analyzing live traffic from an interface is simple: + +.. console:: + + bro -i en0 + +``en0`` can be replaced by the interface of your choice and for the list of +scripts, you can just use "all" for now to perform all the default analysis +that's available. + +Bro will output log files into the working directory. + +.. note:: The :doc:`FAQ ` entries about + capturing as an unprivileged user and checksum offloading are particularly + relevant at this point. + +To use the site-specific ``local.bro`` script, just add it to the +command-line: + +.. console:: + + bro -i en0 local + +This will cause Bro to print a warning about lacking the +``Site::local_nets`` variable being configured. You can supply this +information at the command line like this (supply your "local" subnets +in place of the example subnets): + +.. console:: + + bro -r mypackets.trace local "Site::local_nets += { 1.2.3.0/24, 5.6.7.0/24 }" + + +Reading Packet Capture (pcap) Files +----------------------------------- + +Capturing packets from an interface and writing them to a file can be done +like this: + +.. console:: + + sudo tcpdump -i en0 -s 0 -w mypackets.trace + +Where ``en0`` can be replaced by the correct interface for your system as +shown by e.g. ``ifconfig``. (The ``-s 0`` argument tells it to capture +whole packets; in cases where it's not supported use ``-s 65535`` instead). + +After a while of capturing traffic, kill the ``tcpdump`` (with ctrl-c), +and tell Bro to perform all the default analysis on the capture which primarily includes : + +.. console:: + + bro -r mypackets.trace + +Bro will output log files into the working directory. + +If you are interested in more detection, you can again load the ``local`` +script that we include as a suggested configuration: + +.. console:: + + bro -r mypackets.trace local + + +Telling Bro Which Scripts to Load +--------------------------------- + +A command-line invocation of Bro typically looks like: + +.. console:: + + bro + +Where the last arguments are the specific policy scripts that this Bro +instance will load. These arguments don't have to include the ``.bro`` +file extension, and if the corresponding script resides under the default +installation path, ``$PREFIX/share/bro``, then it requires no path +qualification. Further, a directory of scripts can be specified as +an argument to be loaded as a "package" if it contains a ``__load__.bro`` +script that defines the scripts that are part of the package. + +This example does all of the base analysis (primarily protocol +logging) and adds SSL certificate validation. + +.. console:: + + bro -r mypackets.trace protocols/ssl/validate-certs + +You might notice that a script you load from the command line uses the +``@load`` directive in the Bro language to declare dependence on other scripts. +This directive is similar to the ``#include`` of C/C++, except the semantics +are "load this script if it hasn't already been loaded". + +.. note:: If one wants Bro to be able to load scripts that live outside the + default directories in Bro's installation root, the ``BROPATH`` environment + variable will need to be extended to include all the directories that need + to be searched for scripts. See the default search path by doing + ``bro --help``. + diff --git a/doc/user-manual/starting.rst b/doc/user-manual/starting.rst deleted file mode 100644 index f25746a533..0000000000 --- a/doc/user-manual/starting.rst +++ /dev/null @@ -1,4 +0,0 @@ - -========================= -Getting Started (Missing) -========================= From b5cdf13469335b0d4b49b6a2503b995e351d9155 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 2 Apr 2013 00:35:37 +0200 Subject: [PATCH 055/881] and re-add a function that I apparently deleted accidentally --- src/bro.bif | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bro.bif b/src/bro.bif index 70e5568c6b..13e0d6e407 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5651,6 +5651,15 @@ function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr %%{ #include "HyperLogLog.h" static map hll_counters; + +BroString* convert_index_to_string(Val* index) + { + ODesc d; + index->Describe(&d); + BroString* s = new BroString(1, d.TakeBytes(), d.Len()); + s->SetUseFreeToDelete(1); + return s; + } %%} ## Initializes the hash for the HyperLogLog cardinality counting algorithm. From 25bf563e1c8e4a6243b26f2a0d74cec19d35402a Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 1 Apr 2013 17:30:12 -0700 Subject: [PATCH 056/881] Restructuring the main documentation index. I'm merging in the remaining pieces from the former doc directory and restructuring things into sub-directories. --- doc/CMakeLists.txt | 2 +- doc/cluster/index.rst | 86 + doc/components/binpac/README.rst | 68 + doc/components/bro-aux/README.rst | 70 + doc/components/broccoli-python/README.rst | 231 ++ doc/components/broccoli-ruby/README.rst | 67 + doc/components/broccoli/README.rst | 141 ++ doc/components/broccoli/broccoli-manual.rst | 1355 ++++++++++++ doc/components/broctl/README.rst | 1913 +++++++++++++++++ doc/components/btest/README.rst | 843 ++++++++ doc/components/capstats/README.rst | 107 + doc/components/index.rst | 28 + doc/components/pysubnettree/README.rst | 98 + doc/components/trace-summary/README.rst | 154 ++ doc/frameworks/index.rst | 16 + doc/frameworks/input.rst | 408 ++++ doc/{ => frameworks}/intel.rst | 6 +- doc/frameworks/logging-dataseries.rst | 186 ++ doc/frameworks/logging-elasticsearch.rst | 89 + doc/frameworks/logging.rst | 387 ++++ doc/frameworks/notice.rst | 357 +++ doc/frameworks/signatures.rst | 394 ++++ doc/index.rst | 55 +- doc/indices/index.rst | 7 + doc/intro/index.rst | 13 + .../language.rst => intro/overview.rst} | 4 +- doc/{user-manual => intro}/quickstart.rst | 0 doc/intro/reporting-problems.rst | 194 ++ doc/intro/upgrade.rst | 308 +++ doc/misc/geoip.rst | 102 + doc/misc/index.rst | 9 + doc/reference/events.rst | 5 - doc/reference/frameworks.rst | 5 - doc/reference/index.rst | 13 - doc/reference/subsystems.rst | 4 - .../scripting.rst => scripting/index.rst} | 6 +- doc/scripts/index.rst | 17 +- doc/scripts/scripts.rst | 8 + doc/user-manual/index.rst | 13 - doc/user-manual/intro.rst | 4 - doc/using/index.rst | 6 + 41 files changed, 7679 insertions(+), 100 deletions(-) create mode 100644 doc/cluster/index.rst create mode 100644 doc/components/binpac/README.rst create mode 100644 doc/components/bro-aux/README.rst create mode 100644 doc/components/broccoli-python/README.rst create mode 100644 doc/components/broccoli-ruby/README.rst create mode 100644 doc/components/broccoli/README.rst create mode 100644 doc/components/broccoli/broccoli-manual.rst create mode 100644 doc/components/broctl/README.rst create mode 100644 doc/components/btest/README.rst create mode 100644 doc/components/capstats/README.rst create mode 100644 doc/components/index.rst create mode 100644 doc/components/pysubnettree/README.rst create mode 100644 doc/components/trace-summary/README.rst create mode 100644 doc/frameworks/index.rst create mode 100644 doc/frameworks/input.rst rename doc/{ => frameworks}/intel.rst (98%) create mode 100644 doc/frameworks/logging-dataseries.rst create mode 100644 doc/frameworks/logging-elasticsearch.rst create mode 100644 doc/frameworks/logging.rst create mode 100644 doc/frameworks/notice.rst create mode 100644 doc/frameworks/signatures.rst create mode 100644 doc/indices/index.rst create mode 100644 doc/intro/index.rst rename doc/{reference/language.rst => intro/overview.rst} (65%) rename doc/{user-manual => intro}/quickstart.rst (100%) create mode 100644 doc/intro/reporting-problems.rst create mode 100644 doc/intro/upgrade.rst create mode 100644 doc/misc/geoip.rst create mode 100644 doc/misc/index.rst delete mode 100644 doc/reference/events.rst delete mode 100644 doc/reference/frameworks.rst delete mode 100644 doc/reference/index.rst delete mode 100644 doc/reference/subsystems.rst rename doc/{user-manual/scripting.rst => scripting/index.rst} (99%) create mode 100644 doc/scripts/scripts.rst delete mode 100644 doc/user-manual/index.rst delete mode 100644 doc/user-manual/intro.rst create mode 100644 doc/using/index.rst diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 427d2b86b6..373b4643ba 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -31,7 +31,7 @@ add_custom_target(broxygen ${DOC_SOURCE_WORKDIR}/scripts # append to the master index of all policy scripts COMMAND cat ${MASTER_POLICY_INDEX} >> - ${DOC_SOURCE_WORKDIR}/scripts/index.rst + ${DOC_SOURCE_WORKDIR}/scripts/scripts.rst # append to the master index of all policy packages COMMAND cat ${MASTER_PACKAGE_INDEX} >> ${DOC_SOURCE_WORKDIR}/scripts/packages.rst diff --git a/doc/cluster/index.rst b/doc/cluster/index.rst new file mode 100644 index 0000000000..6de70d38cc --- /dev/null +++ b/doc/cluster/index.rst @@ -0,0 +1,86 @@ + +======================== +Setting up a Bro Cluster +======================== + +Intro +------ + +Bro is not multithreaded, so once the limitations of a single processor core are reached, the only option currently is to spread the workload across many cores or even many physical computers. The cluster deployment scenario for Bro is the current solution to build these larger systems. The accompanying tools and scripts provide the structure to easily manage many Bro processes examining packets and doing correlation activities but acting as a singular, cohesive entity. + +Architecture +--------------- + +The figure below illustrates the main components of a Bro cluster. + +.. image:: /images/deployment.png + +Tap +*** +This is a mechanism that splits the packet stream in order to make a copy +available for inspection. Examples include the monitoring port on a switch and +an optical splitter for fiber networks. + +Frontend +******** +This is a discrete hardware device or on-host technique that will split your traffic into many streams or flows. The Bro binary does not do this job. There are numerous ways to accomplish this task, some of which are described below in `Frontend Options`_. + +Manager +******* +This is a Bro process which has two primary jobs. It receives log messages and notices from the rest of the nodes in the cluster using the Bro communications protocol. The result is that you will end up with single logs for each log instead of many discrete logs that you have to later combine in some manner with post processing. The manager also takes the opportunity to de-duplicate notices and it has the ability to do so since it’s acting as the choke point for notices and how notices might be processed into actions such as emailing, paging, or blocking. + +The manager process is started first by BroControl and it only opens it’s designated port and waits for connections, it doesn’t initiate any connections to the rest of the cluster. Once the workers are started and connect to the manager, logs and notices will start arriving to the manager process from the workers. + +Proxy +***** +This is a Bro process which manages synchronized state. Variables can be synchronized across connected Bro processes automatically in Bro and proxies will help the workers by alleviating the need for all of the workers to connect directly to each other. + +Examples of synchronized state from the scripts that ship with Bro are things such as the full list of “known” hosts and services which are hosts or services which have been detected as performing full TCP handshakes or an analyzed protocol has been found on the connection. If worker A detects host 1.2.3.4 as an active host, it would be beneficial for worker B to know that as well so worker A shares that information as an insertion to a set which travels to the cluster’s proxy and the proxy then sends that same set insertion to worker B. The result is that worker A and worker B have shared knowledge about host and services that are active on the network being monitored. + +The proxy model extends to having multiple proxies as well if necessary for performance reasons, it only adds one additional step for the Bro processes. Each proxy connects to another proxy in a ring and the workers are shared between them as evenly as possible. When a proxy receives some new bit of state, it will share that with it’s proxy which is then shared around the ring of proxies and down to all of the workers. From a practical standpoint, there are no rules of thumb established yet for the number of proxies necessary for the number of workers they are serving. Best is to start with a single proxy and add more if communication performance problems are found. + +Bro processes acting as proxies don’t tend to be extremely intense to CPU or memory and users frequently run proxy processes on the same physical host as the manager. + +Worker +****** +This is the Bro process that sniffs network traffic and does protocol analysis on the reassembled traffic streams. Most of the work of an active cluster takes place on the workers and as such, the workers typically represent the bulk of the Bro processes that are running in a cluster. The fastest memory and CPU core speed you can afford is best here since all of the protocol parsing and most analysis will take place here. There are no particular requirements for the disks in workers since almost all logging is done remotely to the manager and very little is normally written to disk. + +The rule of thumb we have followed recently is to allocate approximately 1 core for every 80Mbps of traffic that is being analyzed, however this estimate could be extremely traffic mix specific. It has generally worked for mixed traffic with many users and servers. For example, if your traffic peaks around 2Gbps (combined) and you want to handle traffic at peak load, you may want to have 26 cores available (2048 / 80 == 25.6). If the 80Mbps estimate works for your traffic, this could be handled by 3 physical hosts dedicated to being workers with each one containing dual 6-core processors. + +Once a flow based load balancer is put into place this model is extremely easy to scale as well so it’s recommended that you guess at the amount of hardware you will need to fully analyze your traffic. If it turns out that you need more, it’s relatively easy to increase the size of the cluster in most cases. + +Frontend Options +---------------- + +There are many options for setting up a frontend flow distributor and in many cases it may even be beneficial to do multiple stages of flow distribution on the network and on the host. + +Discrete hardware flow balancers +******************************** + +cPacket +^^^^^^^ + +If you are monitoring one or more 10G physical interfaces, the recommended solution is to use either a cFlow or cVu device from cPacket because they are currently being used very successfully at a number of sites. These devices will perform layer-2 load balancing by rewriting the destination ethernet MAC address to cause each packet associated with a particular flow to have the same destination MAC. The packets can then be passed directly to a monitoring host where each worker has a BPF filter to limit its visibility to only that stream of flows or onward to a commodity switch to split the traffic out to multiple 1G interfaces for the workers. This can ultimately greatly reduce costs since workers can use relatively inexpensive 1G interfaces. + +OpenFlow Switches +^^^^^^^^^^^^^^^^^ + +We are currently exploring the use of OpenFlow based switches to do flow based load balancing directly on the switch which can greatly reduce frontend costs for many users. This document will be updated when we have more information. + +On host flow balancing +********************** + +PF_RING +^^^^^^^ + +The PF_RING software for Linux has a “clustering” feature which will do flow based load balancing across a number of processes that are sniffing the same interface. This will allow you to easily take advantage of multiple cores in a single physical host because Bro’s main event loop is single threaded and can’t natively utilize all of the cores. More information about Bro with PF_RING can be found here: (someone want to write a quick Bro/PF_RING tutorial to link to here? document installing kernel module, libpcap wrapper, building Bro with the --with-pcap configure option) + +Netmap +^^^^^^ + +FreeBSD has an in-progress project named Netmap which will enable flow based load balancing as well. When it becomes viable for real world use, this document will be updated. + +Click! Software Router +^^^^^^^^^^^^^^^^^^^^^^ + +Click! can be used for flow based load balancing with a simple configuration. (link to an example for the config). This solution is not recommended on Linux due to Bro’s PF_RING support and only as a last resort on other operating systems since it causes a lot of overhead due to context switching back and forth between kernel and userland several times per packet. diff --git a/doc/components/binpac/README.rst b/doc/components/binpac/README.rst new file mode 100644 index 0000000000..683b5455f4 --- /dev/null +++ b/doc/components/binpac/README.rst @@ -0,0 +1,68 @@ +.. -*- mode: rst-mode -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 0.34-3 + +====== +BinPAC +====== + +.. rst-class:: opening + + BinPAC is a high level language for describing protocol parsers and + generates C++ code. It is currently maintained and distributed with the + Bro Network Security Monitor distribution, however, the generated parsers + may be used with other programs besides Bro. + +Download +-------- + +You can find the latest BinPAC release for download at +http://www.bro.org/download. + +BinPAC's git repository is located at `git://git.bro.org/binpac.git +`__. You can browse the repository +`here `__. + +This document describes BinPAC |version|. See the ``CHANGES`` +file for version history. + +Prerequisites +------------- + +BinPAC relies on the following libraries and tools, which need to be +installed before you begin: + + * Flex (Fast Lexical Analyzer) + Flex is already installed on most systems, so with luck you can + skip having to install it yourself. + + * Bison (GNU Parser Generator) + Bison is also already installed on many system. + + * CMake 2.6.3 or greater + CMake is a cross-platform, open-source build system, typically + not installed by default. See http://www.cmake.org for more + information regarding CMake and the installation steps below for + how to use it to build this distribution. CMake generates native + Makefiles that depend on GNU Make by default + +Installation +------------ + +To build and install into ``/usr/local``:: + + ./configure + cd build + make + make install + +This will perform an out-of-source build into the build directory using +the default build options and then install the binpac binary into +``/usr/local/bin``. + +You can specify a different installation directory with:: + + ./configure --prefix= + +Run ``./configure --help`` for more options. diff --git a/doc/components/bro-aux/README.rst b/doc/components/bro-aux/README.rst new file mode 100644 index 0000000000..822afea358 --- /dev/null +++ b/doc/components/bro-aux/README.rst @@ -0,0 +1,70 @@ +.. -*- mode: rst; -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 0.26-5 + +====================== +Bro Auxiliary Programs +====================== + +.. contents:: + +:Version: |version| + +Handy auxiliary programs related to the use of the Bro Network Security +Monitor (http://www.bro.org). + +Note that some files that were formerly distributed with Bro as part +of the aux/ tree are now maintained separately. See the +http://www.bro.org/download for their download locations. + +adtrace +======= + +Makefile and source for the adtrace utility. This program is used +in conjunction with the localnetMAC.pl perl script to compute the +network address that compose the internal and extern nets that bro +is monitoring. This program when run by itself just reads a pcap +(tcpdump) file and writes out the src MAC, dst MAC, src IP, dst +IP for each packet seen in the file. This output is processed by +the localnetMAC.pl script during 'make install'. + + +devel-tools +=========== + +A set of scripts used commonly for Bro development. + +extract-conn-by-uid: + Extracts a connection from a trace file based + on its UID found in Bro's conn.log + +gen-mozilla-ca-list.rb + Generates list of Mozilla SSL root certificates in + a format readable by Bro. + +update-changes + A script to maintain the CHANGES and VERSION files. + +git-show-fastpath + Show commits to the fastpath branch not yet merged into master. + +cpu-bench-with-trace + Run a number of Bro benchmarks on a trace file. + + +nftools +======= + +Utilities for dealing with Bro's custom file format for storing +NetFlow records. nfcollector reads NetFlow data from a socket and +writes it in Bro's format. ftwire2bro reads NetFlow "wire" format +(e.g., as generated by a 'flow-export' directive) and writes it in +Bro's format. + +rst +=== + +Makefile and source for the rst utility. "rst" can be invoked by +a Bro script to terminate an established TCP connection by forging +RST tear-down packets. See terminate_connection() in conn.bro. diff --git a/doc/components/broccoli-python/README.rst b/doc/components/broccoli-python/README.rst new file mode 100644 index 0000000000..b2203a906a --- /dev/null +++ b/doc/components/broccoli-python/README.rst @@ -0,0 +1,231 @@ +.. -*- mode: rst-mode -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 0.54 + +============================ +Python Bindings for Broccoli +============================ + +.. rst-class:: opening + + This Python module provides bindings for Broccoli, Bro's client + communication library. In general, the bindings provide the same + functionality as Broccoli's C API. + +.. contents:: + + +Download +-------- + +You can find the latest Broccoli-Python release for download at +http://www.bro.org/download. + +Broccoli-Python's git repository is located at `git://git.bro.org/broccoli-python.git +`__. You can browse the repository +`here `__. + +This document describes Broccoli-Python |version|. See the ``CHANGES`` +file for version history. + + +Installation +------------ + +Installation of the Python module is pretty straight-forward. After +Broccoli itself has been installed, it follows the standard installation +process for Python modules:: + + python setup.py install + +Try the following to test the installation. If you do not see any +error message, everything should be fine:: + + python -c "import broccoli" + +Usage +----- + +The following examples demonstrate how to send and receive Bro +events in Python. + +The main challenge when using Broccoli from Python is dealing with +the data types of Bro event parameters as there is no one-to-one +mapping between Bro's types and Python's types. The Python modules +automatically maps between those types which both systems provide +(such as strings) and provides a set of wrapper classes for Bro +types which do not have a direct Python equivalent (such as IP +addresses). + +Connecting to Bro +~~~~~~~~~~~~~~~~~ + +The following code sets up a connection from Python to a remote Bro +instance (or another Broccoli) and provides a connection handle for +further communication:: + + from broccoli import * + bc = Connection("127.0.0.1:47758") + +An ``IOError`` will be raised if the connection cannot be established. + +Sending Events +~~~~~~~~~~~~~~ + +Once you have a connection handle ``bc`` set up as shown above, you can +start sending events:: + + bc.send("foo", 5, "attack!") + +This sends an event called ``foo`` with two parameters, ``5`` and +``attack!``. Broccoli operates asynchronously, i.e., events scheduled +with ``send()`` are not always sent out immediately but might be +queued for later transmission. To ensure that all events get out +(and incoming events are processed, see below), you need to call +``bc.processInput()`` regularly. + +Data Types +~~~~~~~~~~ + +In the example above, the types of the event parameters are +automatically derived from the corresponding Python types: the first +parameter (``5``) has the Bro type ``int`` and the second one +(``attack!``) has Bro type ``string``. + +For types which do not have a Python equivalent, the ``broccoli`` +module provides wrapper classes which have the same names as the +corresponding Bro types. For example, to send an event called ``bar`` +with one ``addr`` argument and one ``count`` argument, you can write:: + + bc.send("bar", addr("192.168.1.1"), count(42)) + +The following table summarizes the available atomic types and their +usage. + +======== =========== =========================== +Bro Type Python Type Example +======== =========== =========================== +addr ``addr("192.168.1.1")`` +bool bool ``True`` +count ``count(42)`` +double float ``3.14`` +enum Type currently not supported +int int ``5`` +interval ``interval(60)`` +net Type currently not supported +port ``port("80/tcp")`` +string string ``"attack!"`` +subnet ``subnet("192.168.1.0/24")`` +time ``time(1111111111.0)`` +======== =========== =========================== + +The ``broccoli`` module also supports sending Bro records as event +parameters. To send a record, you first define a record type. For +example, a Bro record type:: + + type my_record: record { + a: int; + b: addr; + c: subnet; + }; + +turns into Python as:: + + my_record = record_type("a", "b", "c") + +As the example shows, Python only needs to know the attribute names +but not their types. The types are derived automatically in the same +way as discussed above for atomic event parameters. + +Now you can instantiate a record instance of the newly defined type +and send it out:: + + rec = record(my_record) + rec.a = 5 + rec.b = addr("192.168.1.1") + rec.c = subnet("192.168.1.0/24") + bc.send("my_event", rec) + +.. note:: The Python module does not support nested records at this time. + +Receiving Events +~~~~~~~~~~~~~~~~ + +To receive events, you define a callback function having the same +name as the event and mark it with the ``event`` decorator:: + + @event + def foo(arg1, arg2): + print arg1, arg2 + +Once you start calling ``bc.processInput()`` regularly (see above), +each received ``foo`` event will trigger the callback function. + +By default, the event's arguments are always passed in with built-in +Python types. For Bro types which do not have a direct Python +equivalent (see table above), a substitute built-in type is used +which corresponds to the type the wrapper class' constructor expects +(see the examples in the table). For example, Bro type ``addr`` is +passed in as a string and Bro type ``time`` is passed in as a float. + +Alternatively, you can define a _typed_ prototype for the event. If you +do so, arguments will first be type-checked and then passed to the +call-back with the specified type (which means instances of the +wrapper classes for non-Python types). Example:: + + @event(count, addr) + def bar(arg1, arg2): + print arg1, arg2 + +Here, ``arg1`` will be an instance of the ``count`` wrapper class and +``arg2`` will be an instance of the ``addr`` wrapper class. + +Protoyping works similarly with built-in Python types:: + + @event(int, string): + def foo(arg1, arg2): + print arg1, arg2 + +In general, the prototype specifies the types in which the callback +wants to receive the arguments. This actually provides support for +simple type casts as some types support conversion to into something +different. If for instance the event source sends an event with a +single port argument, ``@event(port)`` will pass the port as an +instance of the ``port`` wrapper class; ``@event(string)`` will pass it +as a string (e.g., ``"80/tcp"``); and ``@event(int)`` will pass it as an +integer without protocol information (e.g., just ``80``). If an +argument cannot be converted into the specified type, a ``TypeError`` +will be raised. + +To receive an event with a record parameter, the record type first +needs to be defined, as described above. Then the type can be used +with the ``@event`` decorator in the same way as atomic types:: + + my_record = record_type("a", "b", "c") + @event(my_record) + def my_event(rec): + print rec.a, rec.b, rec.c + +Helper Functions +---------------- + +The ``broccoli`` module provides one helper function: ``current_time()`` +returns the current time as a float which, if necessary, can be +wrapped into a ``time`` parameter (i.e., ``time(current_time()``) + +Examples +-------- + +There are some example scripts in the ``tests/`` subdirectory of the +``broccoli-python`` repository +`here `_: + + - ``broping.py`` is a (simplified) Python version of Broccoli's test program + ``broping``. Start Bro with ``broping.bro``. + + - ``broping-record.py`` is a Python version of Broccoli's ``broping`` + for records. Start Bro with ``broping-record.bro``. + + - ``test.py`` is a very ugly but comprehensive regression test and part of + the communication test-suite. Start Bro with ``test.bro``. diff --git a/doc/components/broccoli-ruby/README.rst b/doc/components/broccoli-ruby/README.rst new file mode 100644 index 0000000000..647a568cd8 --- /dev/null +++ b/doc/components/broccoli-ruby/README.rst @@ -0,0 +1,67 @@ +.. -*- mode: rst-mode -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 1.54 + +=============================================== +Ruby Bindings for Broccoli +=============================================== + +.. rst-class:: opening + + This is the broccoli-ruby extension for Ruby which provides access + to the Broccoli API. Broccoli is a library for + communicating with the Bro Intrusion Detection System. + + +Download +======== + +You can find the latest Broccoli-Ruby release for download at +http://www.bro.org/download. + +Broccoli-Ruby's git repository is located at `git://git.bro.org/broccoli-ruby.git +`__. You can browse the repository +`here `__. + +This document describes Broccoli-Ruby |version|. See the ``CHANGES`` +file for version history. + + +Installation +============ + +To install the extension: + +1. Make sure that the ``broccoli-config`` binary is in your path. + (``export PATH=/usr/local/bro/bin:$PATH``) + +2. Run ``sudo ruby setup.rb``. + +To install the extension as a gem (suggested): + +1. Install `rubygems `_. + +2. Make sure that the ``broccoli-config`` binary is in your path. + (``export PATH=/usr/local/bro/bin:$PATH``) + +3. Run, ``sudo gem install rbroccoli``. + +Usage +===== + +There aren't really any useful docs yet. Your best bet currently is +to read through the examples. + +One thing I should mention however is that I haven't done any optimization +yet. You may find that if you write code that is going to be sending or +receiving extremely large numbers of events, that it won't run fast enough and +will begin to fall behind the Bro server. The dns_requests.rb example is +a good performance test if your Bro server is sitting on a network with many +dns lookups. + +Contact +======= + +If you have a question/comment/patch, see the Bro `contact page +`_. diff --git a/doc/components/broccoli/README.rst b/doc/components/broccoli/README.rst new file mode 100644 index 0000000000..4860324292 --- /dev/null +++ b/doc/components/broccoli/README.rst @@ -0,0 +1,141 @@ +.. -*- mode: rst-mode -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 1.92-9 + +=============================================== +Broccoli: The Bro Client Communications Library +=============================================== + +.. rst-class:: opening + + Broccoli is the "Bro client communications library". It allows you + to create client sensors for the Bro intrusion detection system. + Broccoli can speak a good subset of the Bro communication protocol, + in particular, it can receive Bro IDs, send and receive Bro events, + and send and receive event requests to/from peering Bros. You can + currently create and receive values of pure types like integers, + counters, timestamps, IP addresses, port numbers, booleans, and + strings. + + +Download +-------- + +You can find the latest Broccoli release for download at +http://www.bro.org/download. + +Broccoli's git repository is located at +`git://git.bro.org/broccoli `_. You +can browse the repository `here `_. + +This document describes Broccoli |version|. See the ``CHANGES`` +file for version history. + + +Installation +------------ + +The Broccoli library has been tested on Linux, the BSDs, and Solaris. +A Windows build has not currently been tried but is part of our future +plans. If you succeed in building Broccoli on other platforms, let us +know! + + +Prerequisites +------------- + +Broccoli relies on the following libraries and tools, which need to be +installed before you begin: + + Flex (Fast Lexical Analyzer) + Flex is already installed on most systems, so with luck you + can skip having to install it yourself. + + Bison (GNU Parser Generator) + This comes with many systems, but if you get errors compiling + parse.y, you will need to install it. + + OpenSSL headers and libraries + For encrypted communication. These are likely installed, + though some platforms may require installation of a 'devel' + package for the headers. + + CMake 2.6.3 or greater + CMake is a cross-platform, open-source build system, typically + not installed by default. See http://www.cmake.org for more + information regarding CMake and the installation steps below + for how to use it to build this distribution. CMake generates + native Makefiles that depend on GNU Make by default. + +Broccoli can also make use of some optional libraries if they are found at +installation time: + +Libpcap headers and libraries + Network traffic capture library + + +Installation +------------ + +To build and install into ``/usr/local``:: + + ./configure + make + make install + +This will perform an out-of-source build into the build directory using the +default build options and then install libraries into ``/usr/local/lib``. + +You can specify a different installation directory with:: + + ./configure --prefix= + +Or control the python bindings install destination more precisely with:: + + ./configure --python-install-dir= + +Run ``./configure --help`` for more options. + + +Further notable configure options: + + ``--enable-debug`` + This one enables lots of debugging output. Be sure to disable + this when using the library in a production environment! The + output could easily end up in undersired places when the stdout + of the program you've instrumented is used in other ways. + + ``--with-configfile=FILE`` + Broccoli can read key/value pairs from a config file. By default + it is located in the etc directory of the installation root + (exception: when using ``--prefix=/usr``, ``/etc`` is used + instead of /usr/etc). The default config file name is + broccoli.conf. Using ``--with-configfile``, you can override the + location and name of the config file. + +To use the library in other programs & configure scripts, use the +``broccoli-config`` script. It gives you the necessary configuration flags +and linker flags for your system, see ``--cflags`` and ``--libs``. + +The API is contained in broccoli.h and pretty well documented. A few +usage examples can be found in the test directory, in particular, the +``broping`` tool can be used to test event transmission and reception. Have +a look at the policy file ``broping.bro`` for the events that need to be +defined at the peering Bro. Try ``broping -h`` for a look at the available +options. + +Broccoli knows two kinds of version numbers: the release version number +(as in "broccoli-x.y.tar.gz", or as shipped with Bro) and the shared +library API version number (as in libbroccoli.so.3.0.0). The former +relates to changes in the tree, the latter to compatibility changes in +the API. + +Comments, feedback and patches are appreciated; please check the `Bro +website `_. + +Documentation +------------- + +Please see the `Broccoli User Manual <./broccoli-manual.html>`_ and +the `Broccoli API Reference <../../broccoli-api/index.html>`_. diff --git a/doc/components/broccoli/broccoli-manual.rst b/doc/components/broccoli/broccoli-manual.rst new file mode 100644 index 0000000000..4d3c8ec79f --- /dev/null +++ b/doc/components/broccoli/broccoli-manual.rst @@ -0,0 +1,1355 @@ +=============================================== +Broccoli: The Bro Client Communications Library +=============================================== + +This page documents Broccoli, the Bro client communications library. +It allows you to create client sensors for the Bro intrusion detection +system. Broccoli can speak a good subset of the Bro communication +protocol, in particular, it can receive Bro IDs, send and receive Bro +events, and send and receive event requests to/from peering Bros. + +.. contents:: + +Introduction +############ + +What is Broccoli? +================= + +Broccoli is the BRO Client COmmunications LIbrary. It allows you to +write applications that speak the communication protocol of the `Bro +intrusion detection system `_. + +Broccoli is free software under terms of the BSD license as given in the +COPYING file distributed with its source code. + +In this document, we assume that you are familiar with the basic +concepts of Bro, so please first review the documentation/publications +available from the Bro website if necessary. + +Feedback, patches and bug reports are all welcome, please see +http://www.bro.org/community for instructions on how to participate +in the Bro community. + +Why do I care? +============== + +Having a single IDS on your network is good, but things become a lot +more interesting when you can communicate information among multiple +vantage points in your network. Bro agents can communicate with other +Bro agents, sending and receiving events and other state information. In +the Bro context this is particularly interesting because it means that +you can build sophisticated policy-controlled distributed event +management systems. + +Broccoli enters the picture when it comes to integrating components that +are not Bro agents themselves. Broccoli lets you create applications +that can speak the Bro communication protocol. You can compose, send, +request, and receive events. You can register your own event handlers. +You can talk to other Broccoli applications or Bro agents -- Bro agents +cannot tell whether they are talking to another Bro or a Broccoli +application. Broccoli allows you to integrate applications of your +choosing into a distributed policy-controlled event management system. +Broccoli is intended to be portable: it should build on Linux, the BSDs, +Solaris, and Windows (in the `MinGW `_ +environment). + +Unlike other distributed IDSs, Bro does not assume a strict +sensor-manager hierarchy in the information flow. Instead, Bro agents +can request delivery of arbitrary *events* from other instances. When +an event is triggered in a Bro agent, it checks whether any connected +agents have requested notification of this event, and sends a *copy* of +the event, including the *event arguments*. Recall that in Bro, an +event handler is essentially a function defined in the Bro language, +and an event materializes through invocation of an event handler. Each +remote agent can define its own event handlers. + +Broccoli applications will typically do one or more of the following: + +- *Configuration/Management Tasks:* the Broccoli application + is used to configure remotely running Bros without the need for a + restart. + +- *Interfacing with other Systems:* the Broccoli application + is used to convert Bro events to other alert/notice formats, or into + syslogd entries. + +- *Host-based Sensor Feeds into Bro:* the Broccoli + application reports events based on host-based activity generated in + kernel space or user space applications. + +Installing Broccoli +################### + +The installation process will hopefully be painless: Broccoli is +installed from source using the usual ``./configure && make && +make install`` routine after extraction of the tarball. + +Some relevant configuration options to pass to configure are: + +- ``--prefix=``: sets the installation root to DIR. + The default is to install below ``/usr/local``. + +- ``--enable-debug``: enables debugging output. + Please refer to the `Configuring Debugging Output`_ section for + details on configuring and using debugging output. + +- ``--with-configfile=``: use FILE as location of configuration + file. See the section on `Configuration Files`_ for more on this. + +- ``--with-openssl=``: use the OpenSSL installation below DIR. + +After installation, you'll find the library in shared and static +versions in ``/lib``, the header file for compilation in +``/include``. + +Using Broccoli +############## + +Obtaining information about your build using ``broccoli-config`` +================================================================ + +Similarly to many other software packages, the Broccoli distribution +provides a script that you can use to obtain details about your Broccoli +setup. The script currently provides the following flags: + +- ``--build`` prints the name of the machine the build was + made on, when, and whether debugging support was enabled or not. + +- ``--prefix`` prints the directory in the filesystem + below which Broccoli was installed. + +- ``--version`` prints the version of the distribution + you have installed. + +- ``--libs`` prints the flags to pass to the + linker in order to link in the Broccoli library. + +- ``--cflags`` prints the flags to pass to the + compiler in order to properly include Broccoli's header file. + +- ``--config`` prints the location of the system-wide + config file your installation will use. + +The ``--cflags`` and ``--libs`` flags are the suggested way of obtaining +the necessary information for integrating Broccoli into your build +environment. It is generally recommended to use ``broccoli-config`` for +this purpose, rather than, say, develop new **autoconf** tests. If you +use the **autoconf/automake** tools, we recommend something along the +following lines for your ``configure`` script:: + + dnl ################################################## + dnl # Check for Broccoli + dnl ################################################## + AC_ARG_WITH(broccoli-config, + AC_HELP_STRING(\[--with-broccoli-config=FILE], \[Use given broccoli-config]), + [ brocfg="$withval" ], + [ AC_PATH_GENERIC(broccoli,, + brocfg="broccoli-config", + AC_MSG_ERROR(Cannot find Broccoli: Is broccoli-config in path? Use more fertilizer?)) ]) + + broccoli_libs=`$brocfg --libs` + broccoli_cflags=`$brocfg --cflags` + AC_SUBST(broccoli_libs) + AC_SUBST(broccoli_cflags)`` + +You can then use the compiler/linker flags in your Makefile.in/ams by +substituting in the values accordingly, which might look as follows:: + + CFLAGS = -W -Wall -g -DFOOBAR @broccoli_cflags@ + LDFLAGS = -L/usr/lib/foobar @broccoli_libs@ + +Suggestions for instrumenting applications +========================================== + +Often you will want to make existing applications Bro-aware, that is, +*instrument* them so that they can send and receive Bro events at +appropriate moments in the execution flow. This will involve modifying +an existing code tree, so care needs to be taken to avoid unwanted side +effects. By protecting the instrumented code with ``#ifdef``/``#endif`` +statements you can still build the original application, using the +instrumented source tree. The ``broccoli-config`` script helps you in +doing so because it already adds ``-DBROCCOLI`` to the compiler flags +reported when run with the ``--cflags`` option: + +.. console:: + + > broccoli-config --cflags + -I/usr/local/include -I/usr/local/include -DBROCCOLI + +So simply surround all inserted code with a preprocessor check for +``BROCCOLI`` and you will be able to build the original application as +soon as ``BROCCOLI`` is not defined. + +The Broccoli API +================ + +Time for some code. In the code snippets below we will introduce variables +whenever context requires them and not necessarily when C requires them. +The library does not require calling a global initialization function. +In order to make the API known, include ``broccoli.h``: + +.. code:: c + + #ifdef BROCCOLI + #include + #endif + +.. note:: + *Broccoli's memory management philosophy:* + + Broccoli generally does not release objects you allocate. + The approach taken is "you clean up what you allocate." + +Initialization +-------------- + +Broccoli requires global initialization before most of its other +functions can be used. Generally, the way to initialize Broccoli is as +follows: + +.. code:: c + + bro_init(NULL); + +The argument to ``bro_init()`` provides optional initialization context, +and may be kept ``NULL`` for normal use. If required, you may allocate a +``BroCtx`` structure locally, initialize it using ``bro_ctx_init()``, +fill in additional values as required and subsequently pass it to +``bro_init()``: + +.. code:: c + + BroCtx ctx; + bro_ctx_init(&ctx); + /* Make adjustments to the context structure as required...*/ + bro_init(&ctx); + +.. note:: The ``BroCtx`` structure currently contains a set of five + different callback function pointers. These are *required* for + thread-safe operation of OpenSSL (Broccoli itself is thread-safe). + If you intend to use Broccoli in a multithreaded environment, you + need to implement functions and register them via the ``BroCtx`` + structure. The O'Reilly book "Network Security with OpenSSL" by + Viega et al. shows how to implement these callbacks. + +.. warning:: You *must* call ``bro_init()`` at the start of your + application. Undefined behavior may result if you don't. + +Data types in Broccoli +---------------------- + +Broccoli declares a number of data types in ``broccoli.h`` that you +should know about. The more complex ones are kept opaque, while you do +get access to the fields in the simpler ones. The full list is as +follows: + +- Simple signed and unsigned types: int, uint, uint16, uint32, uint64 + and uchar. + +- Connection handles: BroConn, kept opaque. + +- Bro events: BroEvent, kept opaque. + +- Buffer objects: BroBuf, kept opaque. See also `Using Dynamic + Buffers`_. + +- Ports: BroPort for network ports, defined as follows: + + .. code:: c + + typedef struct bro_port { + uint16 port_num; /* port number in host byte order */ + int port_proto; /* IPPROTO_xxx */ + } BroPort; + +- Records: BroRecord, kept opaque. See also `Handling Records`_. + +- Strings (character and binary): BroString, defined as follows: + + .. code:: c + + typedef struct bro_string { + int str_len; + char str_val; + } BroString; + +- BroStrings are mostly kept transparent for convenience; please have a + look at the `Broccoli API Reference`_. + +- Tables: BroTable, kept opaque. See also `Handling Tables`_. + +- Sets: BroSet, kept opaque. See also `Handling Sets`_. + +- IP Address: BroAddr, defined as follows: + + .. code:: c + + typedef struct bro_addr { + uint32 addr[4]; /* IP address in network byte order */ + int size; /* Number of 4-byte words occupied in addr */ + } BroAddr; + + Both IPv4 and IPv6 addresses are supported, with the former occupying + only the first 4 bytes of the ``addr`` array. + +- Subnets: BroSubnet, defined as follows: + + .. code:: c + + typedef struct bro_subnet { + BroAddr sn_net; /* IP address in network byte order */ + uint32 sn_width; /* Length of prefix to consider. */ + } BroSubnet; + +Managing Connections +-------------------- + +You can use Broccoli to establish a connection to a remote Bro, or to +create a Broccoli-enabled server application that other Bros will +connect to (this means that in principle, you can also use Broccoli +purely as middleware and have multiple Broccoli applications communicate +directly). + +In order to establish a connection to a remote Bro, you first obtain a +connection handle. You then use this connection handle to request +events, connect to the remote Bro, send events, etc. Connection handles +are pointers to ``BroConn`` structures, which are kept opaque. Use +``bro_conn_new()`` or ``bro_conn_new_str()`` to obtain a handle, +depending on what parameters are more convenient for you: the former +accepts the IP address and port number as separate numerical arguments, +the latter uses a single string to encode both, in "hostname:port" +format. + +To write a Broccoli-enabled server, you first need to implement the +usual ``socket()`` / ``bind()`` / ``listen()`` / ``accept()`` routine. +Once you have obtained a file descriptor for the new connection from +``accept()``, you pass it to the third function that returns a +``BroConn`` handle, ``bro_conn_new_socket()``. The rest of the +connection handling then proceeds as in the client scenario. + +All three calls accept additional flags for fine-tuning connection +behaviour. These flags are: + +- ``BRO_CFLAG_NONE``: no functionality. Use when no flags are desired. + +- ``BRO_CFLAG_RECONNECT``: + When using this option, Broccoli will attempt to reconnect to the peer + transparently after losing connectivity. Essentially whenever you try to + read from or write to the peer and its connection has broke down, a full + reconnect including complete handshaking is attempted. You can check + whether the connection to a peer is alive at any time using + ``bro_conn_alive()``. + +- ``BRO_CFLAG_ALWAYS_QUEUE``: + When using this option, Broccoli will queue any events you send for + later transmission when a connection is currently down. Without using + this flag, any events you attempt to send while a connection is down + get dropped on the floor. Note that Broccoli maintains a maximum queue + size per connection so if you attempt to send lots of events while the + connection is down, the oldest events may start to get dropped + nonetheless. Again, you can check whether the connection is currently + okay by using ``bro_conn_alive()``. + +- ``BRO_CFLAG_DONTCACHE``: + When using this option, Broccoli will ask the peer not to use caching + on the objects it sends to us. This is the default, and the flag need + not normally be used. It is kept to maintain backward compatibility. + +- ``BRO_CFLAG_CACHE``: + When using this option, Broccoli will ask the peer to use caching on + the objects it sends to us. Caching is normally disabled. + +- ``BRO_CFLAG_YIELD``: + When using this option, ``bro_conn_process_input()`` processes at most + one event at a time and then returns. + +By obtaining a connection handle, you do not also establish a connection +right away. This is done using ``bro_conn_connect()``. The main reason +for this is to allow you to subscribe to events (using +``bro_event_registry_add()``, see `Receiving Events`_) before +establishing the connection. Upon returning from ``bro_conn_connect()`` +you are guaranteed to receive all instances of the event types you have +requested, while later on during the connection some time may elapse +between the issuing of a request for events and the processing of that +request at the remote end. Connections are established via TCP, +optionally using SSL encryption. See "`Configuring Encrypted +Communication`_", for more information on setting up encryption. The +port numbers Bro agents and Broccoli applications listen on can vary +from peer to peer. + +Finally, ``bro_conn_delete()`` terminates a connection and releases all +resources associated with it. You can create as many connections as you +like, to one or more peers. You can obtain the file descriptor of a +connection using ``bro_conn_get_fd()``: + +.. code:: c + + char host_str = "bro.yourorganization.com"; + int port = 1234; + struct hostent *host; + BroConn *bc; + + if (! (host = gethostbyname(host_str)) || ! + (host->h_addr_list[0])) + { + /* Error handling -- could not resolve host */ + } + + /* In this example, we obtain a connection handle, then register + event handlers, and finally connect to the remote Bro. */ + /* First obtain a connection handle: */ + if (! (bc = bro_conn_new((struct in_addr*) host->h_addr_list[0], + htons(port), BRO_CFLAG_NONE))) + { + /* Error handling - could not get connection handle */ + } + + /* Register event handlers: */ + bro_event_registry_add(bc, "foo", bro_foo_handler, NULL); + /* ... */ + + /* Now connect to the peer: */ + if (! bro_conn_connect(bc)) + { + /* Error handling - could not connect to remote Bro. */ + } + + /* Send and receive events ... */ + + /* Disconnect from Bro and clean up connection */ + bro_conn_delete(bc); + +Or simply use the string-based version: + +.. code:: c + + char host_str = "bro.yourcompany.com:1234"; + BroConn bc; + + /* In this example we don't request any events from the peer, + but we ask it not to use the serialization cache. */ + /* Again, first obtain a connection handle: */ + if (! (bc = bro_conn_new_str(host_str, BRO_CFLAG_DONTCACHE))) + { + /* Error handling - could not get connection handle */ + } + + /* Now connect to the peer: */ + if (! bro_conn_connect(bc)) + { + /* Error handling - could not connect to remote Bro. */ + } + + /* ... */ + +Connection Classes +------------------ + +When you want to establish connections from multiple Broccoli +applications with different purposes, the peer needs a means to +understand what kind of application each connection belongs to. The real +meaning of "kind of application" here is "sets of event types to +request", because depending on the class of an application, the peer +will likely want to receive different types of events. + +Broccoli lets you set the class of a connection using +``bro_conn_set_class()``. When using this feature, you need to call that +function before issuing a ``bro_conn_connect()`` since the class of a +connection is determined at connection startup: + +.. code:: c + + if (! (bc = bro_conn_new_str(host_str, BRO_CFLAG_DONTCACHE))) + { + /* Error handling - could not get connection handle */ + } + + /* Set class of this connection: */ + bro_conn_set_class(bc, "syslog"); + + if (! bro_conn_connect(bc)) + { + /* Error handling - could not connect to remote Bro. */ + } + +If your peer is a Bro node, you need to match the chosen connection +class in the remote Bro's ``Communication::nodes`` configuration. See +`Configuring event reception in Bro scripts`_, for how to do +this. Finally, in order to obtain the class of a connection as +indicated by the remote side, use ``bro_conn_get_peer_class()``. + +Composing and sending events +---------------------------- + +In order to send an event to the remote Bro agent, you first create an +empty event structure with the name of the event, then add parameters to +pass to the event handler at the remote agent, and then send off the +event. + +.. note: + *Bro peers ignore unrequested events.* + + You need to make sure that the remote Bro agent is interested in + receiving the events you send. This interest is expressed in policy + configuration. We'll explain this in more detail in `Configuring + event reception in Bro scripts`_, and for now assume that our + remote peer is configured to receive the events we send. + +Let's assume we want to request a report of all connections a remote Bro +currently keeps state for that match a given destination port and host +name and that have amassed more than a certain number of bytes. The +idea is to send an event to the remote Bro that contains the query, +identifiable through a request ID, and have the remote Bro answer us +with ``remote_conn`` events containing the information we asked for. The +definition of our requesting event could look as follows in the Bro +policy: + +.. code:: bro + + event report_conns(req_id: int, dest_host: string, + dest_port: port, min_size: count); + +First, create a new event: + +.. code:: c + + BroEvent *ev; + + if (! (ev = bro_event_new("report_conns"))) + { + /* Error handling - could not allocate new event. */ + } + +Now we need to add parameters to the event. The sequence and types must +match the event handler declaration -- check the Bro policy to make sure +they match. The function to use for adding parameter values is +``bro_event_add_val()``. All values are passed as *pointer arguments* +and are copied internally, so the object you're pointing to stays +unmodified at all times. You clean up what you allocate. In order to +indicate the type of the value passed into the function, you need to +pass a numerical type identifier along as well. Table-1_ lists the +value types that Broccoli supports along with the type identifier and +data structures to point to. + +.. _Table-1: + +Types, type tags, and data structures for event parameters in Broccoli +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +============================== ===================== ==================== +Type Type tag Data type pointed to +============================== ===================== ==================== +Boolean ``BRO_TYPE_BOOL`` ``int`` +Integer value ``BRO_TYPE_INT`` ``uint64`` +Counter (nonnegative integers) ``BRO_TYPE_COUNT`` ``uint64`` +Enums (enumerated values) ``BRO_TYPE_ENUM`` ``uint64`` (see also description of ``bro_event_add_val()``'s ``type_name`` argument) +Floating-point number ``BRO_TYPE_DOUBLE`` ``double`` +Timestamp ``BRO_TYPE_TIME`` ``double`` (see also ``bro_util_timeval_to_double()`` and ``bro_util_current_time()``) +Time interval ``BRO_TYPE_INTERVAL`` ``double`` +Strings (text and binary) ``BRO_TYPE_STRING`` ``BroString`` (see also family of ``bro_string_xxx()`` functions) +Network ports ``BRO_TYPE_PORT`` ``BroPort``, with the port number in host byte order +IPv4/IPv6 address ``BRO_TYPE_IPADDR`` ``BroAddr``, with the ``addr`` member in network byte order and ``size`` member indicating the address family and number of 4-byte words of ``addr`` that are occupied (1 for IPv4 and 4 for IPv6) +IPv4/IPv6 subnet ``BRO_TYPE_SUBNET`` ``BroSubnet``, with the ``sn_net`` member in network byte order +Record ``BRO_TYPE_RECORD`` ``BroRecord`` (see also the family of ``bro_record_xxx()`` functions and their explanation below) +Table ``BRO_TYPE_TABLE`` ``BroTable`` (see also the family of ``bro_table_xxx()`` functions and their explanation below) +Set ``BRO_TYPE_SET`` ``BroSet`` (see also the family of ``bro_set_xxx()`` functions and their explanation below) +============================== ===================== ==================== + +Knowing these, we can now compose a ``request_connections`` event: + +.. code:: c + + BroString dest_host; + BroPort dest_port; + uint32 min_size; + int req_id = 0; + + bro_event_add_val(ev, BRO_TYPE_INT, NULL, &req_id); + req_id++; + + bro_string_set(&dest_host, "desthost.destdomain.com"); + bro_event_add_val(ev, BRO_TYPE_STRING, NULL, &dest_host); + bro_string_cleanup(&dest_host); + + dest_port.dst_port = 80; + dest_port.dst_proto = IPPROTO_TCP; + bro_event_add_val(ev, BRO_TYPE_PORT, NULL, &dest_port); + + min_size = 1000; bro_event_add_val(ev, BRO_TYPE_COUNT, NULL, &min_size); + +The third argument to ``bro_event_add_val()`` lets you specify a +specialization of the types listed in Table-1_. This is generally not +necessary except for one situation: when using ``BRO_TYPE_ENUM``. You +currently cannot define a Bro-level enum type in Broccoli, and thus when +sending an enum value, you have to specify the type of the enum along +with the value. For example, in order to add an instance of enum +``transport_type`` defined in Bro's ``bro.init``, you would use: + +.. code:: c + + int transport_proto = 2; + /* ... */ + bro_event_add_val(ev, BRO_TYPE_ENUM, "transport_proto", &transport_proto); + +to get the equivalent of "udp" on the remote side. The same system is +used to point out type names when calling ``bro_event_set_val()``, +``bro_record_add_val()``, ``bro_record_set_nth_val()``, and +``bro_record_set_named_val()``. + +All that's left to do now is to send off the event. For this, use +``bro_event_send()`` and pass it the connection handle and the event. +The function returns ``TRUE`` when the event could be sent right away or +if it was queued for later delivery. ``FALSE`` is returned on error. If +the event gets queued, this does not indicate an error -- likely the +connection was just not ready to send the event at this point. Whenever +you call ``bro_event_send()``, Broccoli attempts to send as much of an +existing event queue as possible. Again, the event is copied internally +to make it easier for you to send the same event repeatedly. You clean +up what you allocate: + +.. code:: c + + bro_event_send(bc, ev); + bro_event_free(ev); + +Two other functions may be useful to you: ``bro_event_queue_length()`` +tells you how many events are currently queued, and +``bro_event_queue_flush()`` attempts to flush the current event queue +and returns the number of events that do remain in the queue after the +flush. + +.. note:: you do not normally need to call this function, queue + flushing is attempted every time you send an event. + +Receiving Events +---------------- + +Receiving events is a little more work because you need to + +1. tell Broccoli what to do when requested events arrive, + +#. let the remote Bro agent know that you would like to receive those + events, + +#. find a spot in the code path suitable for extracting and processing + arriving events. + +Each of these steps is explained in the following sections. + +Implementing event callbacks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When Broccoli receives an event, it tries to dispatch the event to +callbacks registered for that event type. The place where callbacks get +registered is called the callback registry. Any callbacks registered for +the arriving event's name are invoked with the parameters shipped with +the event. There are two styles of argument passing to the event +callbacks. Which one is better suited depends on your application. + +Expanded Argument Passing +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Each event argument is passed via a pointer to the callback. This makes +best sense when you know the type of the event and of its arguments, +because it provides you immediate access to arguments as when using a +normal C function. + +In order to register a callback with expanded argument passing, use +``bro_event_registry_add()`` and pass it the connection handle, the name +of the event for which you register the callback, the callback itself +that matches the signature of the ``BroEventFunc`` type, and any user +data (or ``NULL``) you want to see passed to the callback on each +invocation. The callback's type is defined rather generically as +follows: + +.. code:: c + + typedef void (*BroEventFunc) (BroConn *bc, void *user_data, ...); + +It requires a connection handle as its first argument and a pointer to +user-provided callback data as the second argument. Broccoli will pass +the connection handle of the connection on which the event arrived +through to the callback. ``BroEventFunc``'s are variadic, because each +callback you provide is directly invoked with pointers to the parameters +of the event, in a format directly usable in C. All you need to know is +what type to point to in order to receive the parameters in the right +layout. Refer to Table-1_ again for a summary of those types. Record +types are more involved and are addressed in more detail in `Handling +Records`_. + +.. note:: Note that *all* parameters are passed to the + callback as pointers, even elementary types such as ``int`` that + would normally be passed directly. Also note that Broccoli manages + the lifecycle of event parameters and therefore you do *not* have + to clean them up inside the event handler. + +Continuing our example, we will want to process the connection reports +that contain the responses to our ``report_conns`` event. Let's assume +those look as follows: + +.. code:: bro + + event remote_conn(req_id: int, conn: connection); + +The reply events contain the request ID so we can associate requests +with replies, and a connection record (defined in ``bro.init`` in Bro). +(It'd be nicer to report all replies in a single event but we'll +ignore that for now.) For this event, our callback would look like +this: + +.. code:: c + + void remote_conn_cb(BroConn *bc, void *user_data, int *req_id, + BroRecord *conn); + +Once more, you clean up what you allocate, and since you never allocated +the space these arguments point to, you also don't clean them up. +Finally, we register the callback using ``bro_event_registry_add()``: + +.. code:: c + + bro_event_registry_add(bc, "remote_conn", remote_conn_cb, NULL); + +In this case we have no additional data to be passed into the callback, +so we use ``NULL`` for the last argument. If you have multiple events +you are interested in, register each one in this fashion. + +Compact Argument Passing +^^^^^^^^^^^^^^^^^^^^^^^^ + +This is designed for situations when you have to determine how to handle +different types of events at runtime, for example when writing language +bindings or when implementing generic event handlers for multiple event +types. The callback is passed a connection handle and the user data as +above but is only passed one additional pointer, to a BroEvMeta +structure. This structure contains all metadata about the event, +including its name, timestamp (in UTC) of creation, number of arguments, +the arguments' types (via type tags as listed in Table-1_), and the +arguments themselves. + +In order to register a callback with compact argument passing, use +``bro_event_registry_add_compact()`` and pass it similar arguments as +you'd use with ``bro_event_registry_add()``. The callback's type is +defined as follows: + +.. code:: c + + typedef void (*BroCompactEventFunc) (BroConn *bc, void *user_data, + BroEvMeta *meta); + + +.. note:: As before, Broccoli manages the lifecycle of event parameters. + You do not have to clean up the BroEvMeta structure or any of its + contents. + +Below is sample code for extracting the arguments from the BroEvMeta +structure, using our running example. This is still written with the +assumption that we know the types of the arguments, but note that this +is not a requirement for this style of callback: + +.. code:: c + + void remote_conn_cb(BroConn *bc, void *user_data, + BroEvMeta *meta) { + int *req_id; BroRecord *rec; + + /* For demonstration, print out the event's name: */ + + printf("Handling a %s event.\n", meta->ev_name); + + /* Sanity-check the number of arguments: */ + + if (meta->ev_numargs != 2) + { /* error */ } + + /* Sanity-check the argument types: */ + + if (meta->ev_args[0].arg_type != BRO_TYPE_INT) + { /* error */ } + + if (meta->ev_args[1].arg_type != BRO_TYPE_RECORD) + { /* error */ } + + req_id = (int *) meta->ev_args[0].arg_data; + rec = (BroRecord *) meta->ev_args[1].arg_data; + + /* ... */ + } + +Finally, register the callback using +``bro_event_registry_add_compact()``: + +.. code:: c + + bro_event_registry_add_compact(bc, "remote_conn", remote_conn_cb, NULL); + +Requesting event delivery +~~~~~~~~~~~~~~~~~~~~~~~~~ + +At this point, Broccoli knows what to do with the requested events upon +arrival. What's left to do is to let the remote Bro know that you would +like to receive the events for which you registered. If you haven't yet +called ``bro_conn_connect()``, then there is nothing to do, since that +function will request the registered events anyway. Once connected, you +can still request events. To do so, call +``bro_event_registry_request()``: + +.. code:: c + + bro_event_registry_request(bc); + +This mechanism also implies that no unrequested events will be delivered +to us (and if that happened for whatever reason, the event would simply +be dropped on the floor). + +.. note:: At the moment you cannot unrequest events, nor can you request + events based on predicates on the values of the events' arguments. + +Reading events from the connection handle +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +At this point the remote Bro will start sending you the requested events +once they are triggered. What is left to do is to read the arriving +events from the connection and trigger dispatching them to the +registered callbacks. + +If you are writing a new Bro-enabled application, this is easy, and you +can choose among two approaches: polling explicitly via Broccoli's API, +or using ``select()`` on the file handle associated with a BroConn. The +former case is particularly straightforward; all you need to do is call +``bro_conn_process_input()``, which will go off and check if any events +have arrived and if so, dispatch them accordingly. This function does +not block -- if no events have arrived, then the call will return +immediately. For more fine-grained control over your I/O handling, you +will probably want to use ``bro_conn_get_fd()`` to obtain the file +descriptor of your connection and then incorporate that in your standard +``FD_SET``/``select()`` code. Once you have determined that data in fact +are ready to be read from the obtained file descriptor, you can then try +another ``bro_conn_process_input()`` this time knowing that it'll find +something to dispatch. + +As a side note, if you don't process arriving events frequently enough, +then TCP's flow control will start to slow down the sender until +eventually events will queue up and be dropped at the sending end. + +Handling Records +---------------- + +Broccoli supports record structures, i.e., types that pack a set of +values together, placing each value into its own field. In Broccoli, the +way you handle records is somewhat similar to events: after creating an +empty record (of opaque type ``BroRecord``), you can iteratively add +fields and values to it. The main difference is that you must specify a +field name with the value; each value in a record can be identified both +by position (a numerical index starting from zero), and by field name. +You can retrieve vals in a record by field index or field name. You can +also reassign values. There is no explicit, IDL-style definition of +record types. You define the type of a record implicitly by the sequence +of field names and the sequence of the types of the values you put into +the record. + +Note that all fields in a record must be assigned before it can be +shipped. + +The API for record composition consists of ``bro_record_new()``, +``bro_record_free()``, ``bro_record_add_val()``, +``bro_record_set_nth_val()``, and ``bro_record_set_named_val()``. + +On records that use field names, the names of individual fields can be +extracted using ``bro_record_get_nth_name()``. Extracting values from a +record is done using ``bro_record_get_nth_val()`` and +``bro_record_get_named_val()``. The former allows numerical indexing of +the fields in the record, the latter provides name-based lookups. Both +need to be passed the record you want to extract a value from, the index +or name of the field, and either a pointer to an int holding a +BRO_TYPE_xxx value (see again Table-1_ for a summary of those types) or +``NULL``. The pointer, if not ``NULL``, serves two purposes: type +checking and type retrieval. Type checking is performed if the value of +the int upon calling the functions is not BRO_TYPE_UNKNOWN. The type tag +of the requested record field then has to match the type tag stored in +the int, otherwise ``NULL`` is returned. If the int stores +BRO_TYPE_UNKNOWN upon calling, no type-checking is performed. In *both* +cases, the *actual* type of the requested record field is returned in +the int pointed to upon return from the function. Since you have no +guarantees of the type of the value upon return if you pass ``NULL`` as +the int pointer, this is a bad idea and either BRO_TYPE_UNKNOWN or +another type value should always be used. + +For example, you could extract the value of the record field "label", +which we assume should be a string, in the following ways: + +.. code:: c + + BroRecord *rec = /* obtained somehow */ + BroString *string; + int type; + + /* --- Example 1 --- */ + + type = BRO_TYPE_STRING; + /* Use type-checking, will not accept other types */ + + if (! (string = bro_record_get_named_val(rec, "label", &type))) + { + /* Error handling, either there's no field of that value or + the value is not of BRO_TYPE_STRING. The actual type is now + stored in "type". */ + } + + /* --- Example 2 --- */ + + type = BRO_TYPE_UNKNOWN; + /* No type checking, just report the existent type */ + + if (! (string = bro_record_get_named_val(rec, "label", &type))) + { + /* Error handling, no field of that name exists. */ + } + + printf("The type of the value in field 'label' is %i\n", type); + + /* --- Example 3 --- */ + + if (! (string = bro_record_get_named_val(rec, "label", NULL))) + { + /* Error handling, no field of that name exists. */ + } + + /* We now have a value, but we can't really be sure of its type */ + +Record fields can be records, for example in the case of Bro's standard +connection record type. In this case, in order to get to a nested +record, you use ``BRO_TYPE_RECORD``: + +.. code:: c + + void remote_conn_cb(BroConn *bc, int *req_id, BroRecord *conn) + { + BroRecord *conn_id; + int type = BRO_TYPE_RECORD; + if ( ! (conn_id = bro_record_get_named_val(conn, "id", &type))) + { + /* Error handling */ + } + } + +Handling Tables +--------------- + +Broccoli supports Bro-style tables, i.e., associative containers that +map instances of a key type to an instance of a value type. A given key +can only ever point to a single value. The key type can be *composite*, +i.e., it may consist of an ordered sequence of different types, or it +can be *direct*, i.e., consisting of a single type (such as an integer, +a string, or a record). + +The API for table manipulation consists of ``bro_table_new()`` +``bro_table_free()``, ``bro_table_insert()``, ``bro_table_find()``, +``bro_table_get_size()``, ``bro_table_get_types()``, and +``bro_table_foreach()``. + +Tables are handled similarly to records in that typing is determined +dynamically by the initial key/value pair inserted. The resulting types +can be obtained via ``bro_table_get_types()``. Should the types not +have been determined yet, ``BRO_TYPE_UNKNOWN`` will result. Also, as +with records, values inserted into the table are copied internally, and +the ones passed to the insertion functions remain unaffected. + +In contrast to records, table entries can be iterated. By passing a +function of signature ``BroTableCallback()`` and a pointer to data of +your choosing, ``bro_table_foreach()`` will invoke the given function +for each key/value pair stored in the table. Return ``TRUE`` to keep +the iteration going, or ``FALSE`` to stop it. + +.. note:: + The main thing to know about Broccoli's tables is how to use + composite key types. To avoid additional API calls, you may treat + composite key types exactly as records, though you do not need to use + field names when assigning elements to individual fields. So in order + to insert a key/value pair, you create a record with the needed items + assigned to its slots, and use this record as the key object. In + order to differentiate composite index types from direct ones + consisting of a single record, use ``BRO_TYPE_LIST`` as the type of + the record, as opposed to ``BRO_TYPE_RECORD``. Broccoli will then + know to interpret the record as an ordered sequence of items making + up a composite element, not a regular record. + +``brotable.c`` in the ``test/`` subdirectory of the Broccoli tree +contains an extensive example of using tables with composite as well as +direct indexing types. + +Handling Sets +------------- + +Sets are essentially tables with void value types. The API for set +manipulation consists of ``bro_set_new()``, ``bro_set_free()``, +``bro_set_insert()``, ``bro_set_find()``, ``bro_set_get_size()``, +``bro_set_get_type()``, and ``bro_set_foreach()``. + +Associating data with connections +--------------------------------- + +You will often find that you would like to connect data with a +``BroConn``. Broccoli provides an API that lets you associate data items +with a connection handle through a string-based key-value registry. The +functions of interest are ``bro_conn_data_set()``, +``bro_conn_data_get()``, and ``bro_conn_data_del()``. You need to +provide a string identifier for a data item and can then use that string +to register, look up, and remove the associated data item. Note that +there is currently no mechanism to trigger a destructor function for +registered data items when the Bro connection is terminated. You +therefore need to make sure that all data items that you do not have +pointers to via some other means are properly released before calling +``bro_disconnect()``. + +Configuration Files +------------------- + +Imagine you have instrumented the mother of all server applications. +Building it takes forever, and every now and then you need to change +some of the parameters that your Broccoli code uses, such as the host +names of the Bro agents to talk to. To allow you to do this quickly, +Broccoli comes with support for configuration files. All you need to do +is change the settings in the file and restart the application (we're +considering adding support for volatile configuration items that are +read from the file every time they are requested). + +A configuration is read from a single configuration file. This file can +be read from different locations. Broccoli searches in this order +for the config file: + +- The location specified by the ``BROCCOLI_CONFIG_FILE`` environment + variable. + +- A per-user configuration file stored in ``~/.broccoli.conf``. + +- The system-wide configuration file. You can obtain the location + of this config file by running ``broccoli-config --config``. + +.. note:: ``BROCCOLI_CONFIG_FILE`` or ``~/.broccoli.conf`` will only be + used if it is a regular file, not executable, and neither group nor + others have any permissions on the file. That is, the file's + permissions must look like ``-rw-------`` *or* ``-r--------``. + +In the configuration file, a ``#`` anywhere starts a comment that runs to +the end of the line. Configuration items are specified as key-value +pairs:: + + # This is the Broccoli system-wide configuration file. + # + # Entries are of the form , where the + # identifier is a sequence of letters, and value can be a string + # (including whitespace), and floating point or integer numbers. + # Comments start with a "#" and go to the end of the line. For + # boolean values, you may also use "yes", "on", "true", "no", + # "off", or "false". Strings may contain whitespace, but need + # to be surrounded by double quotes '"'. + # + # Examples: + # + Foo/PeerName mybro.securesite.com + Foo/PortNum 123 + Bar/SomeFloat 1.23443543 + Bar/SomeLongStr "Hello World" + +You can also have multiple sections in your configuration. Your +application can select a section as the current one, and queries for +configuration settings will then only be answered with values specified +in that section. A section is started by putting its name (no whitespace +please) between square brackets. Configuration items positioned before +the first section title are in the default domain and will be used by +default:: + + # This section contains all settings for myapp. + [ myapp ] + +You can name identifiers any way you like, but to keep things organized +it is recommended to keep a namespace hierarchy similar to the file +system. In the code, you can query configuration items using +``bro_conf_get_str()``, ``bro_conf_get_int()``, and +``bro_conf_get_dbl()``. You can switch between sections using +``bro_conf_set_domain()``. + +Using Dynamic Buffers +--------------------- + +Broccoli provides an API for dynamically allocatable, growable, +shrinkable, and consumable buffers with ``BroBuf``. You may or may not +find this useful -- Broccoli mainly provides this feature in +``broccoli.h`` because these buffers are used internally anyway and +because they are a typical case of something that people implement +themselves over and over again, for example to collect a set of data +before sending it through a file descriptor, etc. + +The buffers work as follows. The structure implementing a buffer is +called ``BroBuf``, and is initialized to a default size when +created via ``bro_buf_new()`` and released using ``bro_buf_free()``. +Each ``BroBuf`` has a content pointer that points to an arbitrary +location between the start of the buffer and the first byte after the +last byte currently used in the buffer (see ``buf_off`` in the +illustration below). The content pointer can seek to arbitrary +locations, and data can be copied from and into the buffer, adjusting +the content pointer accordingly. You can repeatedly append data to the end +of the buffer's used contents using ``bro_buf_append()``. +:: + + <---------------- allocated buffer space ------------> + <======== used buffer space ========> ^ + ^ ^ ^ | + | | | | + buf buf_ptr buf_off buf_len + +Have a look at the following functions for the details: +``bro_buf_new()``, ``bro_buf_free()``, ``bro_buf_append()``, +``bro_buf_consume()``, ``bro_buf_reset()``, ``bro_buf_get()``, +``bro_buf_get_end()``, ``bro_buf_get_size()``, +``bro_buf_get_used_size()``, ``bro_buf_ptr_get()``, +``bro_buf_ptr_tell()``, ``bro_buf_ptr_seek()``, ``bro_buf_ptr_check()``, +and ``bro_buf_ptr_read()``. + +Configuring Encrypted Communication +=================================== + +Encrypted communication between Bro peers takes place over an SSL +connection in which both endpoints of the connection are authenticated. +This requires at least some PKI in the form of a certificate authority +(CA) which you use to issue and sign certificates for your Bro peers. To +facilitate the SSL setup, each peer requires three documents: a +certificate signed by the CA and containing the public key, the +corresponding private key, and a copy of the CA's certificate. + +The OpenSSL command line tool ``openssl`` can be used to create all +files necessary, but its unstructured arguments and poor documentation +make it a pain to use and waste lots of people a lot of time [#]_. +For an alternative tool to create SSL certificates for secure Bro/Broccoli +communication, see the ``create-cert`` tool available at +ftp://ee.lbl.gov/create-cert.tar.gz. + +In order to enable encrypted communication for your Broccoli +application, you need to put the CA certificate and the peer certificate +in the ``/broccoli/ca_cert`` and ``/broccoli/host_cert`` keys, +respectively, in the configuration file. Optionally, you can store the +private key in a separate file specified by ``/broccoli/host_key``. To +quickly enable/disable a certificate configuration, the +``/broccoli/use_ssl`` key can be used. + +.. note:: + *This is where you configure whether to use encrypted or unencrypted + connections.* + + If the ``/broccoli/use_ssl`` key is present and set to one of "yes", + "true", "on", or 1, then SSL will be used and an incorrect or missing + certificate configuration will cause connection attempts to fail. If + the key's value is one of "no", "false", "off", or 0, then in no case + will SSL be used and connections will always be cleartext. + + If the ``/broccoli/use_ssl`` key is *not* present, then SSL will be + used if a certificate configuration is found, and invalid + certificates will cause the connection to fail. If no certificates + are configured, cleartext connections will be used. + + In no case does an SSL-enabled setup ever fall back to a cleartext + one. + +:: + + /broccoli/use_ssl yes + /broccoli/ca_cert /ca_cert.pem + /broccoli/host_cert /bro_cert.pem + /broccoli/host_key /bro_cert.key + +In a Bro policy, you need to load the ``frameworks/communication/listen.bro`` +script and redef ``Communication::listen_ssl=T``, +``ssl_ca_certificate``, and ``ssl_private_key``, defined in ``bro.init``: + +.. code:: bro + + @load frameworks/communication/listen + + redef Communication::listen_ssl=T; + redef ssl_ca_certificate = "/ca_cert.pem"; + redef ssl_private_key = "/bro.pem"; + +By default, you will be prompted for the passphrase for the private key +matching the public key in your agent's certificate. Depending on your +application's user interface and deployment, this may be inappropriate. +You can store the passphrase in the config file as well, using the +following identifier:: + + /broccoli/host_pass foobar + +.. warning:: *Make sure that access to your configuration is restricted.* + + If you provide the passphrase this way, it is obviously essential to + have restrictive permissions on the configuration file. Broccoli + partially enforces this. Please refer to the section on + `Configuration Files`_ for details. + +Configuring event reception in Bro scripts +========================================== + +Before a remote Bro will accept your connection and your events, it +needs to have its policy configured accordingly: + +1. Load ``frameworks/communication/listen``, and redef the boolean variable + ``Communication::listen_ssl`` depending on whether you want to have + encrypted or cleartext communication. Obviously, encrypting the event + exchange is recommended and cleartext should only be used for early + experimental setups. See below for details on how to set up encrypted + communication via SSL. + +#. You need to find a port to use for the Bros and Broccoli applications + that will listen for connections. Every such agent can use a + different port, though default ports are provided in the Bro + policies. To change the port the Bro agent will be listening on from + its default, redefine the ``Communication::listen_port``. Have a + look at these policies as well as + ``base/frameworks/communication/main.bro`` for the default values. + Here is the policy for the unencrypted case: + + .. code:: bro + + @load frameworks/communication/listen + redef Communication::listen_port = 12345/tcp; + + .. + + Including the settings for the cryptographic files introduced in the + previous section, here is the encrypted one: + + .. code:: bro + + @load frameworks/communication/listen + redef Communication::listen_ssl = T; + redef Communication::listen_port = 12345/tcp; + redef ssl_ca_certificate = "/ca_cert.pem"; + redef ssl_private_key = "/bro.pem"; + + .. + +#. The policy controlling which peers a Bro agent will communicate with + and how this communication will happen are defined in the + ``Communication::nodes`` table defined in + ``base/frameworks/communication/main.bro``. This table contains + entries of type ``Node``, whose members mostly provide default values + so you do not need to define everything. You need to come up with a + tag for the connection under which it can be found in the table (a + creative one would be "broccoli"), the IP address of the peer, the + pattern of names of the events the Bro will accept from you, whether + you want Bro to connect to your machine on startup or not, if so, a + port to connect to (default is ``Communication::default_port`` also defined in + ``base/frameworks/communication/main.bro``), a retry timeout, + whether to use SSL, and the class of a connection as set on the + Broccoli side via ``bro_conn_set_class()``. + + An example could look as follows: + + .. code:: bro + + redef Communication::nodes += { + ["broping"] = [$host = 127.0.0.1, $class="broping", + $events = /ping/, $connect=F, $ssl=F] + }; + + .. + + This example is taken from ``broping.bro``, the policy the remote Bro + must run when you want to use the ``broping`` tool explained in the + section on `test programs`_ below. It will allow an agent on the + local host to connect and send "ping" events. Our Bro will not + attempt to connect, and incoming connections will be expected in + cleartext. + +Configuring Debugging Output +============================ + +If your Broccoli installation was configured with ``--enable-debug``, +Broccoli will report two kinds of debugging information: + +1. function call traces and +#. individual debugging messages. + +Both are enabled by default, but can be adjusted in two ways. + +- In the configuration file: in the appropriate section of the + configuration file, you can set the keys ``/broccoli/debug_messages`` + and ``/broccoli/debug_calltrace`` to ``on``/``off`` to enable/disable + the corresponding output. + +- In code: you can set the variables + ``bro_debug_calltrace`` and ``bro_debug_messages`` to 1/0 at any time + to enable/disable the corresponding output. + +By default, debugging output is inactive (even with debug support +compiled in). You need to enable it explicitly either in your code by +assigning 1 to ``bro_debug_calltrace`` and ``bro_debug_messages`` or by +enabling it in the configuration file. + +Test programs +============= + +The Broccoli distribution comes with a few small test programs, located +in the ``test/`` directory of the tree. The most notable one is +``broping`` [#]_, a mini-version of ping. It sends "ping" events to a +remote Bro agent, expecting "pong" events in return. It operates in two +flavours: one uses atomic types for sending information across, and the +other one uses records. The Bro agent you want to ping needs to run +either the ``broping.bro`` or ``broping-record.bro`` policies. You can +find these in the ``test/`` directory of the source tree, and in +``/share/broccoli`` in the installed version. ``broping.bro`` is +shown below. By default, pinging a Bro on the same machine is +configured. If you want your Bro to be pinged from another machine, you +need to update the ``Communication::nodes`` variable accordingly: + +.. code:: bro + + @load frameworks/communication/listen; + + global ping_log = open_log_file("ping"); + + redef Communication::nodes += { + ["broping"] = [$host = 127.0.0.1, $events = /ping/, + $connect=F, $retry = 60 secs, $ssl=F] + }; + + event ping(src_time: time, seq: count) { + event pong(src_time, current_time(), seq); + } + + event pong(src_time: time, dst_time: time, seq: count) { + print ping_log, + fmt("ping received, seq %d, %f at src, %f at dest, one-way: %f", + seq, src_time, dst_time, dst_time-src_time); + } + +``broping`` sends ping events to Bro. Bro accepts those because they are +configured accordingly in the nodes table. As shown in the +policy, ping events trigger pong events, and ``broccoli`` requests +delivery of all pong events back to it. When running ``broping``, +you'll see something like this: + +.. console:: + + > ./test/broping + pong event from 127.0.0.1: seq=1, time=0.004700/1.010303 s + pong event from 127.0.0.1: seq=2, time=0.053777/1.010266 s + pong event from 127.0.0.1: seq=3, time=0.006435/1.010284 s + pong event from 127.0.0.1: seq=4, time=0.020278/1.010319 s + pong event from 127.0.0.1: seq=5, time=0.004563/1.010187 s + pong event from 127.0.0.1: seq=6, time=0.005685/1.010393 s + +Notes +===== + +.. [#] In other documents and books on OpenSSL you will find this + expressed more politely, using terms such as "daunting to the + uninitiated", "challenging", "complex", "intimidating". + +.. [#] Pronunciation is said to be somewhere on the continuum between + "brooping" and "burping". + +Broccoli API Reference +###################### + +The `API documentation <../../broccoli-api/index.html>`_ +describes Broccoli's public C interface. diff --git a/doc/components/broctl/README.rst b/doc/components/broctl/README.rst new file mode 100644 index 0000000000..1fd728c7cf --- /dev/null +++ b/doc/components/broctl/README.rst @@ -0,0 +1,1913 @@ +.. Autogenerated. Do not edit. + +.. -*- mode: rst-mode -*- +.. +.. Note: This file includes further autogenerated ones. +.. +.. Version number is filled in automatically. +.. |version| replace:: 1.1-3 + +========== +BroControl +========== + +.. rst-class:: opening + + This document summarizes installation and use of *BroControl*, + Bro's interactive shell for operating Bro installations. *BroControl* + has two modes of operation: a *stand-alone* mode for + managing a traditional, single-system Bro setup; and a *cluster* + mode for maintaining a multi-system setup of coordinated Bro + instances load-balancing the work across a set of independent + machines. Below, we describe the installation process separately + for the two modes. Once installed, the operation is pretty similar + for both types; just keep in mind that if this document refers to + "nodes" and you're in a stand-alone setup, there is only a + single one and no worker/proxies. + +.. contents:: + +Download +-------- + +You can find the latest BroControl release for download at +http://www.bro.org/download. + +BroControl's git repository is located at +`git://git.bro.org/broctl `_. You +can browse the repository `here `_. + +This document describes BroControl |version|. See the ``CHANGES`` +file for version history. + +Prerequisites +------------- + +Running *BroControl* requires the following prerequisites: + + - A Unix system. FreeBSD, Linux, and MacOS are supported and + should work out of the box. Other Unix systems will quite likely + require some tweaking. Note that in a cluster setup, all systems + must be running exactly the *same* operating system. + + - A version of *Python* >= 2.6. + + - A *bash* (note in particular, that on FreeBSD, *bash* is not + installed by default). + +Installation +------------ + +Stand-alone Bro +~~~~~~~~~~~~~~~ + +For installing a stand-alone Bro setup, just follow the +Bro :doc:`Quick Start Guide<../../quickstart>`. + +Bro Cluster +~~~~~~~~~~~ + +A *Bro Cluster* is a set of systems jointly analyzing the traffic of +a network link in a coordinated fashion. *BroControl* is able to +operate such a setup from a central manager system pretty much +transparently, hiding much of the complexity of the multi-machine +installation. + +A cluster consists of four types of components: + + Frontends. + One or more frontends: Frontends load-balance the traffic + across a set of worker machines. + + Worker nodes. + Workers are doing the actual analysis, with each seeing a + slice of the overall traffic as split by the frontend(s). + + One or more proxies. + Proxies relay the communication between worker nodes. + + One manager. + The manager provides the cluster's user-interface for + controlling and logging. During operation, the user only + interacts with the manager; this is where *BroControl* is + running. + +For more information about the cluster architecture, including options +for the frontend, see the :doc:`Bro Cluster<../../cluster>` documentation. + +This document focuses on the installation of manager, +workers, and the proxies. If not otherwise +stated, in the following we use the terms "manager", "worker", and +"proxy" to refer to Bro instances, not to physical machines; rather, +we use the term "node" to refer to physical machines. There may be +multiple Bro instances running on the same node. For example, it's +possible to run a proxy on the same node as the manager is operating +on. + +In the following, as an example setup, we will assume that our +cluster consists of four nodes (not counting the frontend). The host +names of the systems will be ``host1``, ``host2``, ``host3``, and +``host4``. We will configure the cluster so that ``host1`` runs the +manager and the (only) proxy, and ``host{2,3,4}`` are each running +one worker. This is a typical setup, which will work well for many +sites. + +When installing a cluster, in addition to the prerequisites +mentioned above, you need to + + - have the same user account set up on all nodes. On the worker + nodes, this user must have access to target network interface in + promiscuous mode. ``ssh`` access from the manager node to this + user account must be setup on all machines, and must work + without asking for a password/passphrase. + + - have some storage available on all nodes under the same path, + which we will call the cluster's *prefix* path. In the + following, we will use ``/usr/local/bro`` as an example. The Bro + user must be able to either create this directory or, where it + already exists, must have write permission inside this directory + on all nodes. + + - have ``ssh`` and ``rsync`` installed. + + +With all prerequisites in place, perform the following steps to +install a Bro cluster (as the Bro user) if you install from the Bro source +code (which includes BroControl): + +- Configure and compile the Bro distribution using the cluster's + prefix path as ``--prefix``:: + + > cd /path/to/bro/source/distribution + > ./configure --prefix=/usr/local/bro && make && make install + +- Add ``/bin`` to your ``PATH``. + +- Create a cluster configuration file. There is an example provided, + which you can edit according to the instructions in the file:: + + > cd /usr/local/bro + > vi etc/broctl.cfg + +- Create a node configuration file to define where manager, workers, + and proxies are to run. There is again an example, which defines + the example scenario described above and can be edited as needed:: + + > cd /usr/local/bro + > vi etc/node.cfg + +- Create a network configuration file that lists all of the networks + which the cluster should consider as local to the monitored + environment. Once again, the installation installs a template for + editing:: + + > cd /usr/local/bro + > vi etc/networks.cfg + +- Install workers and proxies using *BroControl*:: + + > broctl install + + This installation process uses ``ssh`` and ``rdist`` to copy the + configuration over to the remote machines so, as described above, + you need to ensure that logging in via SSH works before the install will + succeed. + +- Some tasks need to be run on a regular basis. On the manager node, + insert a line like this into the crontab of the user running the + cluster:: + + 0-59/5 * * * * /bin/broctl cron + +- Finally, you can start the cluster:: + + > broctl start + +Getting Started +--------------- + +*BroControl* is an interactive interface to the cluster which allows +you to, e.g., start/stop the monitoring or update its configuration. +It is started with the ``broctl`` script and then expects commands +on its command-line (alternatively, ``broctl`` can also be started +with a single command directly on the shell's command line):: + + > broctl + Welcome to BroControl x.y + + Type "help" for help. + + [BroControl] > + +As the message says, type help_ to see a list of +all commands. We will now briefly summarize the most important +commands. A full reference follows `Command Reference`_. + +Once ``broctl.cfg`` and ``node.cfg`` are set up as described above, +the monitoring can be started with the start_ command. In the cluster +setup, this will successively start manager, proxies, and workers. The +status_ command should then show all nodes as operating. To stop the +monitoring, issue the stop_ command. exit_ leaves the shell. + +On the manager system (and on the stand-alone system), you find the +current set of (aggregated) logs in ``logs/current`` (which is a +symlink to the corresponding spool directory). The proxies and workers +log into ``spool/proxy/`` and ``spool//``, respectively. +The manager/stand-alone logs are archived in ``logs/``, by default +once a day. Log files of workers and proxies are discarded at the +same rotation interval. + +Whenever the *BroControl* configuration is modified in any way +(including changes to configuration files and site-specific policy +scripts), install_ installs the new version. *No changes will take +effect until* install_ *is run*. Before you run install_, check_ can be +used to check for any potential errors in the new configuration, e.g., +typos in scripts. If check_ does not report any problems, doing +install_ will pretty likely not break anything. + +Note that generally configuration changes only take effect after a +restart of the affected nodes. The restart_ command triggers this. +Some changes however can be put into effect on-the-fly without +restarting any of the nodes by using the update_ command (again only +after doing install_ first). Such dynamic updates generally work with +all changes done which only modify const variables declared as +*redefinable* (i.e., with Bro's *&redef* attribute). + +Generally, site-specific tuning needs to be done with local policy +scripts, as in any Bro setup. This is described in +`Site-specific Customization`_. + +*BroControl* provides various options to control the behavior of +the setup. These options can be set by editing ``broctl.cfg``. +The config_ command gives a list of all options +with their current values. A list of the most important options also +follows `Option Reference`_. + +Site-specific Customization +--------------------------- + +You'll most likely want to adapt the Bro policy to the local +environment and much of the more specific tuning requires writing +local policy files. + +During the initial install, sample local policy scripts (which you can edit) +are installed in ``share/bro/site``. In the stand-alone setup, a single +file called ``local.bro`` gets loaded automatically. In the cluster +setup, the same ``local.bro`` gets loaded, followed by one of three +other files: ``local-manager.bro``, ``local-worker.bro``, and +``local-proxy.bro`` are loaded by the manager, workers, and proxy, +respectively. + +In the cluster setup, the main exception to putting everything into +``local.bro`` is notice filtering, which should be done only on the +manager. + +The next scripts that are loaded are the ones that are automatically +generated by BroControl. These scripts are created from the +``networks.cfg`` and ``broctl.cfg`` files. + +The last scripts loaded are any node-specific scripts specified with the +option ``aux_scripts`` in ``node.cfg``. This option can be used to +load additional scripts to individual nodes only. For example, one could +add a script ``experimental.bro`` to a single worker for trying out new +experimental code. + +The scripts_ command shows precisely which policy scripts get loaded (and +in what order) by a node; that can be very helpful. + +If you want to change which local policy scripts are loaded by the nodes, +you can set SitePolicyStandalone_ for all Bro instances, +SitePolicyManager_ for the manager, and SitePolicyWorker_ for the +workers. To change the directory where local policy scripts are +located, set the option SitePolicyPath_ to a different path. These +options can be changed in the ``broctl.cfg`` file. + +Command Reference +----------------- + +The following summary lists all commands supported by *BroControl*. +All commands may be either entered interactively or specified on the +shell's command line. If not specified otherwise, commands taking +*[]* as arguments apply their action either to the given set of +nodes, or to all nodes if none is given. + +[?1034h.. Automatically generated. Do not edit. + + +.. _attachgdb: + +*attachgdb* *[]* + Primarily for debugging, the command attaches a *gdb* to the main Bro + process on the given nodes. + + +.. _capstats: + +*capstats* *[] []* + Determines the current load on the network interfaces monitored by + each of the given worker nodes. The load is measured over the + specified interval (in seconds), or by default over 10 seconds. This + command uses the `capstats tool + `_, + which is installed along with ``broctl``. + + (Note: When using a CFlow and the CFlow command line utility is + installed as well, the ``capstats`` command can also query the device + for port statistics. *TODO*: document how to set this up.) + + +.. _check: + +*check* *[]* + Verifies a modified configuration in terms of syntactical correctness + (most importantly correct syntax in policy scripts). This command + should be executed for each configuration change *before* + install_ is used to put the change into place. Note + that ``check`` is the only command which operates correctly without a + former install_ command; ``check`` uses the policy + files as found in SitePolicyPath_ to make + sure they compile correctly. If they do, install_ + will then copy them over to an internal place from where the nodes + will read them at the next start_. This approach + ensures that new errors in a policy script will not affect currently + running nodes, even when one or more of them needs to be restarted. + + +.. _cleanup: + +*cleanup* *[--all] []* + Clears the nodes' spool directories (if they are not running + currently). This implies that their persistent state is flushed. Nodes + that were crashed are reset into *stopped* state. If ``--all`` is + specified, this command also removes the content of the node's + TmpDir_, in particular deleteing any data + potentially saved there for reference from previous crashes. + Generally, if you want to reset the installation back into a clean + state, you can first stop_ all nodes, then execute + ``cleanup --all``, and finally start_ all nodes + again. + + +.. _config: + +*config* + Prints all configuration options with their current values. + + +.. _cron: + +*cron* *[enable|disable|?] | [--no-watch]* + This command has two modes of operation. Without arguments (or just + ``--no-watch``), it performs a set of maintenance tasks, including + the logging of various statistical information, expiring old log + files, checking for dead hosts, and restarting nodes which terminated + unexpectedly. The latter can be suppressed with the ``--no-watch`` + option if no auto-restart is desired. This mode is intended to be + executed regularly via *cron*, as described in the installation + instructions. While not intended for interactive use, no harm will be + caused by executing the command manually: all the maintenance tasks + will then just be performed one more time. + + The second mode is for interactive usage and determines if the regular + tasks are indeed performed when ``broctl cron`` is executed. In other + words, even with ``broctl cron`` in your crontab, you can still + temporarily disable its execution by running ``cron disable``, and + then later reenable with ``cron enable``. This can be helpful while + working, e.g., on the BroControl configuration and ``cron`` would + interfere with that. ``cron ?`` can be used to query the current state. + + +.. _df: + +*df* *[]* + Reports the amount of disk space available on the nodes. Shows only + paths relevant to the broctl installation. + + +.. _diag: + +*diag* *[]* + If a node has terminated unexpectedly, this command prints a (somewhat + cryptic) summary of its final state including excerpts of any + stdout/stderr output, resource usage, and also a stack backtrace if a + core dump is found. The same information is sent out via mail when a + node is found to have crashed (the "crash report"). While the + information is mainly intended for debugging, it can also help to find + misconfigurations (which are usually, but not always, caught by the + check_ command). + + +.. _exec: + +*exec* ** + Executes the given Unix shell command line on all nodes configured to + run at least one Bro instance. This is handy to quickly perform an + action across all systems. + + +.. _exit: + +*exit* + Terminates the shell. + + +.. _help: + +*help* + Prints a brief summary of all commands understood by the shell. + + +.. _install: + +*install* + Reinstalls the given nodes, including all configuration files and + local policy scripts. This command must be executed after *all* + changes to any part of the broctl configuration, otherwise the + modifications will not take effect. Usually all nodes should be + reinstalled at the same time, as any inconsistencies between them will + lead to strange effects. Before executing ``install``, it is recommended + to verify the configuration with check_. + + +.. _netstats: + +*netstats* *[]* + Queries each of the nodes for their current counts of captured and + dropped packets. + + +.. _nodes: + +*nodes* + Prints a list of all configured nodes. + + +.. _peerstatus: + +*peerstatus* *[]* + Primarily for debugging, ``peerstatus`` reports statistics about the + network connections cluster nodes are using to communicate with other + nodes. + + +.. _print: + +*print* * []* + Reports the *current* live value of the given Bro script ID on all of + the specified nodes (which obviously must be running). This can for + example be useful to (1) check that policy scripts are working as + expected, or (2) confirm that configuration changes have in fact been + applied. Note that IDs defined inside a Bro namespace must be + prefixed with ``::`` (e.g., ``print SSH::did*ssh*version`` to + print the corresponding table from ``ssh.bro``.) + + +.. _process: + +*process* * [options] [-- ]* + Runs Bro offline on a given trace file using the same configuration as + when running live. It does, however, use the potentially + not-yet-installed policy files in SitePolicyPath_ and disables log + rotation. Additional Bro command line flags and scripts can + be given (each argument after a ``--`` argument is interpreted as + a script). + + Upon completion, the command prints a path where the log files can be + found. Subsequent runs of this command may delete these logs. + + In cluster mode, Bro is run with *both* manager and worker scripts + loaded into a single instance. While that doesn't fully reproduce the + live setup, it is often sufficient for debugging analysis scripts. + + +.. _quit: + +*quit* + Terminates the shell. + + +.. _restart: + +*restart* *[--clean] []* + Restarts the given nodes, or all nodes if none are specified. The + effect is the same as first executing stop_ followed + by a start_, giving the same nodes in both cases. + This command is most useful to activate any changes made to Bro policy + scripts (after running install_ first). Note that a + subset of policy changes can also be installed on the fly via the + update_, without requiring a restart. + + If ``--clean`` is given, the installation is reset into a clean state + before restarting. More precisely, a ``restart --clean`` turns into + the command sequence stop_, cleanup_ --all, check_, install_, and + start_. + + +.. _scripts: + +*scripts* *[-c] []* + Primarily for debugging Bro configurations, the ``scripts`` + command lists all the Bro scripts loaded by each of the nodes in the + order they will be parsed by the node at startup. + If ``-c`` is given, the command operates as check_ does: it reads + the policy files from their *original* location, not the copies + installed by install_. The latter option is useful to check a + not yet installed configuration. + + +.. _start: + +*start* *[]* + Starts the given nodes, or all nodes if none are specified. Nodes + already running are left untouched. + + +.. _status: + +*status* *[]* + Prints the current status of the given nodes. + + +.. _stop: + +*stop* *[]* + Stops the given nodes, or all nodes if none are specified. Nodes not + running are left untouched. + + +.. _top: + +*top* *[]* + For each of the nodes, prints the status of the two Bro + processes (parent process and child process) in a *top*-like + format, including CPU usage and memory consumption. If + executed interactively, the display is updated frequently + until key ``q`` is pressed. If invoked non-interactively, the + status is printed only once. + + +.. _update: + +*update* *[]* + After a change to Bro policy scripts, this command updates the Bro + processes on the given nodes *while they are running* (i.e., without + requiring a restart_). However, such dynamic + updates work only for a *subset* of Bro's full configuration. The + following changes can be applied on the fly: The value of all + const variables defined with the ``&redef`` attribute can be changed. + More extensive script changes are not possible during runtime and + always require a restart; if you change more than just the values of + ``&redef``-able consts and still issue ``update``, the results are + undefined and can lead to crashes. Also note that before running + ``update``, you still need to do an install_ (preferably after + check_), as otherwise ``update`` will not see the changes and it will + resend the old configuration. + + +Option Reference +---------------- + +This section summarizes the options that can be set in ``broctl.cfg`` +for customizing the behavior of *BroControl*. Usually, one only needs +to change the "user options", which are listed first. The "internal +options" are, as the name suggests, primarily used internally and set +automatically. They are documented here only for reference. + +.. Automatically generated. Do not edit. + +User Options +~~~~~~~~~~~~ +.. _BroArgs: + +*BroArgs* (string, default _empty_) + Additional arguments to pass to Bro on the command-line. + +.. _CFlowAddress: + +*CFlowAddress* (string, default _empty_) + If a cFlow load-balancer is used, the address of the device (format: :). + +.. _CFlowPassword: + +*CFlowPassword* (string, default _empty_) + If a cFlow load-balancer is used, the password for accessing its configuration interface. + +.. _CFlowUser: + +*CFlowUser* (string, default _empty_) + If a cFlow load-balancer is used, the user name for accessing its configuration interface. + +.. _CommTimeout: + +*CommTimeout* (int, default 10) + The number of seconds to wait before assuming Broccoli communication events have timed out. + +.. _CompressCmd: + +*CompressCmd* (string, default "gzip -9") + If archived logs will be compressed, the command to use for that. The specified command must compress its standard input to standard output. + +.. _CompressExtension: + +*CompressExtension* (string, default "gz") + If archived logs will be compressed, the file extension to use on compressed log files. When specifying a file extension, don't include the period character (e.g., specify 'gz' instead of '.gz'). + +.. _CompressLogs: + +*CompressLogs* (bool, default 1) + True to compress archived log files. + +.. _CronCmd: + +*CronCmd* (string, default _empty_) + A custom command to run everytime the cron command has finished. + +.. _Debug: + +*Debug* (bool, default 0) + Enable extensive debugging output in spool/debug.log. + +.. _HaveNFS: + +*HaveNFS* (bool, default 0) + True if shared files are mounted across all nodes via NFS (see FAQ). + +.. _IPv6Comm: + +*IPv6Comm* (bool, default 1) + Enable IPv6 communication between cluster nodes (and also between them and BroControl) + +.. _LogDir: + +*LogDir* (string, default "$\{BroBase}/logs") + Directory for archived log files. + +.. _LogExpireInterval: + +*LogExpireInterval* (int, default 0) + Number of days log files are kept (zero means disabled). + +.. _LogRotationInterval: + +*LogRotationInterval* (int, default 3600) + The frequency of log rotation in seconds for the manager/standalone node. + +.. _MailAlarmsTo: + +*MailAlarmsTo* (string, default "$\{MailTo}") + Destination address for alarm summary mails. Default is to use the same address as MailTo. + +.. _MailFrom: + +*MailFrom* (string, default "Big Brother ") + Originator address for broctl-generated mails. + +.. _MailReplyTo: + +*MailReplyTo* (string, default _empty_) + Reply-to address for broctl-generated mails. + +.. _MailSubjectPrefix: + +*MailSubjectPrefix* (string, default "[Bro]") + General Subject prefix for mails. + +.. _MailTo: + +*MailTo* (string, default "") + Destination address for non-alarm mails. + +.. _MakeArchiveName: + +*MakeArchiveName* (string, default "$\{BroBase}/share/broctl/scripts/make-archive-name") + Script to generate filenames for archived log files. + +.. _MemLimit: + +*MemLimit* (string, default "unlimited") + Maximum amount of memory for Bro processes to use (in KB, or the string 'unlimited'). + +.. _MinDiskSpace: + +*MinDiskSpace* (int, default 5) + Percentage of minimum disk space available before warning is mailed. + +.. _PFRINGClusterID: + +*PFRINGClusterID* (int, default @PF_RING_CLUSTER_ID@) + If PF_RING flow-based load balancing is desired, this is where the PF_RING cluster id is defined. The default value is configuration-dependent and determined automatically by CMake at configure-time based upon whether PF_RING's enhanced libpcap is available. Bro must be linked with PF_RING's libpcap wrapper for this option to work. + +.. _Prefixes: + +*Prefixes* (string, default "local") + Additional script prefixes for Bro, separated by colons. Use this instead of @prefix. + +.. _SaveTraces: + +*SaveTraces* (bool, default 0) + True to let backends capture short-term traces via '-w'. These are not archived but might be helpful for debugging. + +.. _SendMail: + +*SendMail* (string, default "@SENDMAIL@") + Location of the sendmail binary. Make this string blank to prevent email from being sent. The default value is configuration-dependent and determined automatically by CMake at configure-time. + +.. _SitePluginPath: + +*SitePluginPath* (string, default _empty_) + Directories to search for custom plugins, separated by colons. + +.. _SitePolicyManager: + +*SitePolicyManager* (string, default "local-manager.bro") + Space-separated list of local policy files for manager. + +.. _SitePolicyPath: + +*SitePolicyPath* (string, default "$\{PolicyDir}/site") + Directories to search for local policy files, separated by colons. + +.. _SitePolicyStandalone: + +*SitePolicyStandalone* (string, default "local.bro") + Space-separated list of local policy files for all Bro instances. + +.. _SitePolicyWorker: + +*SitePolicyWorker* (string, default "local-worker.bro") + Space-separated list of local policy files for workers. + +.. _StopTimeout: + +*StopTimeout* (int, default 60) + The number of seconds to wait before sending a SIGKILL to a node which was previously issued the 'stop' command but did not terminate gracefully. + +.. _TimeFmt: + +*TimeFmt* (string, default "%d %b %H:%M:%S") + Format string to print date/time specifications (see 'man strftime'). + +.. _TimeMachineHost: + +*TimeMachineHost* (string, default _empty_) + If the manager should connect to a Time Machine, the address of the host it is running on. + +.. _TimeMachinePort: + +*TimeMachinePort* (string, default "47757/tcp") + If the manager should connect to a Time Machine, the port it is running on (in Bro syntax, e.g., 47757/tcp). + +.. _ZoneID: + +*ZoneID* (string, default _empty_) + If the host running BroControl is managing a cluster comprised of nodes with non-global IPv6 addresses, this option indicates what RFC 4007 zone_id to append to node addresses when communicating with them. + + +Internal Options +~~~~~~~~~~~~~~~~ + +.. _BinDir: + +*BinDir* (string, default "$\{BroBase}/bin") + Directory for executable files. + +.. _BroBase: + +*BroBase* (string, default _empty_) + Base path of broctl installation on all nodes. + +.. _CapstatsPath: + +*CapstatsPath* (string, default "$\{bindir}/capstats") + Path to capstats binary; empty if not available. + +.. _CfgDir: + +*CfgDir* (string, default "$\{BroBase}/etc") + Directory for configuration files. + +.. _DebugLog: + +*DebugLog* (string, default "$\{SpoolDir}/debug.log") + Log file for debugging information. + +.. _HelperDir: + +*HelperDir* (string, default "$\{BroBase}/share/broctl/scripts/helpers") + Directory for broctl helper scripts. + +.. _LibDir: + +*LibDir* (string, default "$\{BroBase}/lib") + Directory for library files. + +.. _LibDirInternal: + +*LibDirInternal* (string, default "$\{BroBase}/lib/broctl") + Directory for broctl-specific library files. + +.. _LocalNetsCfg: + +*LocalNetsCfg* (string, default "$\{CfgDir}/networks.cfg") + File defining the local networks. + +.. _LockFile: + +*LockFile* (string, default "$\{SpoolDir}/lock") + Lock file preventing concurrent shell operations. + +.. _NodeCfg: + +*NodeCfg* (string, default "$\{CfgDir}/node.cfg") + Node configuration file. + +.. _OS: + +*OS* (string, default _empty_) + Name of operating system as reported by uname. + +.. _PluginDir: + +*PluginDir* (string, default "$\{LibDirInternal}/plugins") + Directory where standard plugins are located. + +.. _PolicyDir: + +*PolicyDir* (string, default "$\{BroBase}/share/bro") + Directory for standard policy files. + +.. _PolicyDirSiteInstall: + +*PolicyDirSiteInstall* (string, default "$\{SpoolDir}/installed-scripts-do-not-touch/site") + Directory where the shell copies local policy scripts when installing. + +.. _PolicyDirSiteInstallAuto: + +*PolicyDirSiteInstallAuto* (string, default "$\{SpoolDir}/installed-scripts-do-not-touch/auto") + Directory where the shell copies auto-generated local policy scripts when installing. + +.. _PostProcDir: + +*PostProcDir* (string, default "$\{BroBase}/share/broctl/scripts/postprocessors") + Directory for log postprocessors. + +.. _ScriptsDir: + +*ScriptsDir* (string, default "$\{BroBase}/share/broctl/scripts") + Directory for executable scripts shipping as part of broctl. + +.. _SpoolDir: + +*SpoolDir* (string, default "$\{BroBase}/spool") + Directory for run-time data. + +.. _StandAlone: + +*StandAlone* (bool, default 0) + True if running in stand-alone mode (see elsewhere). + +.. _StateFile: + +*StateFile* (string, default "$\{SpoolDir}/broctl.dat") + File storing the current broctl state. + +.. _StaticDir: + +*StaticDir* (string, default "$\{BroBase}/share/broctl") + Directory for static, arch-independent files. + +.. _StatsDir: + +*StatsDir* (string, default "$\{LogDir}/stats") + Directory where statistics are kept. + +.. _StatsLog: + +*StatsLog* (string, default "$\{SpoolDir}/stats.log") + Log file for statistics. + +.. _Time: + +*Time* (string, default _empty_) + Path to time binary. + +.. _TmpDir: + +*TmpDir* (string, default "$\{SpoolDir}/tmp") + Directory for temporary data. + +.. _TmpExecDir: + +*TmpExecDir* (string, default "$\{SpoolDir}/tmp") + Directory where binaries are copied before execution. + +.. _TraceSummary: + +*TraceSummary* (string, default "$\{bindir}/trace-summary") + Path to trace-summary script (empty if not available). Make this string blank to disable the connection summary emails. + +.. _Version: + +*Version* (string, default _empty_) + Version of the broctl. + + +Writing Plugins +--------------- + +BroControl provides a plugin interface to extend its functionality. A +plugin is written in Python and can do any, or all, of the following: + + * Perform actions before or after any of the standard BroControl + commands is executed. When running before the actual command, it + can filter which nodes to operate or stop the execution + altogether. When running after the command, it gets access to + the commands success on a per-node basis (where applicable). + + * Add custom commands to BroControl. + + * Add custom options to BroControl defined in ``broctl.cfg``. + + * Add custom keys to nodes defined in ``node.cfg``. + +A plugin is written by deriving a new class from BroControl class +`Plugin`_. The Python script with the new plugin is then copied into a +plugin directory searched by BroControl at startup. By default, +BroControl searches ``/lib/broctl/plugins``; further may be +configured by setting the PluginDir_ option. Note that any plugin +script must end in ``*.py`` to be found. BroControl comes with some +example plugins that can be used as a starting point; see +the ``/lib/broctl/plugins`` directory. + +In the following, we document the API that is available to plugins. A +plugin must be derived from the `Plugin`_ class, and can use its +methods as well as those of the `Node`_ class. + +.. _Plugin: + +Class ``Plugin`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class **Plugin** + The class ``Plugin`` is the base class for all BroControl plugins. + + The class has a number of methods for plugins to override, and every + plugin must at least override ``name()`` and ``pluginVersion()``. + + For each BroControl command ``foo``, there are two methods, + ``cmd_foo_pre`` and ``cmd_foo_post``, that are called just before the + command is executed and just after it has finished, respectively. The + arguments these methods receive correspond to their command-line + parameters, and are further documented below. + + The ``cmd__pre`` methods have the ability to prevent the command's + execution, either completely or partially for those commands that take + nodes as parameters. In the latter case, the method receives a list of + nodes that the command is to be run on, and it can filter that list and + returns modified version of nodes to actually use. The standard case would + be returning simply the unmodified ``nodes`` parameter. To completely + block the command's execution, return an empty list. To just not execute + the command for a subset, remove the affected ones. For commands that do + not receive nodes as arguments, the return value is interpreted as boolean + indicating whether command execution should proceed (True) or not (False). + + The ``cmd__post`` methods likewise receive the commands arguments as + their parameter, as documented below. For commands taking nodes, the list + corresponds to those nodes for which the command was actually executed + (i.e., after any ``cmd__pre`` filtering). Each node is given as a + tuple ``(node, bool)`` with *node* being the actual `Node`_, and the boolean + indicating whether the command was successful for it. + + Note that if a plugin prevents a command from executing either completely or + partially, it should report its reason via the ``message*()`` or + ``error()`` methods. + + If multiple plugins hook into the same command, all their + ``cmd__{pre,post}`` are executed in undefined order. The command is + executed on the intersection of all ``cmd__pre`` results. + + Finally, note that the ``restart`` command doesn't have its own method as + it's just a combination of other commands and thus their callbacks are + run. + + .. _Plugin.debug: + + **debug** (self, msg) + + Logs a debug message in BroControl's debug log if enabled. + + .. _Plugin.error: + + **error** (self, msg) + + Reports an error to the user. + + .. _Plugin.execute: + + **execute** (self, node, cmd) + + Executes a command on the host for the given *node* of type + `Node`_. Returns a tuple ``(success, output)`` in which ``success`` is + True if the command ran successfully and ``output`` is the combined + stdout/stderr output. + + .. _Plugin.executeParallel: + + **executeParallel** (self, cmds) + + Executes a set of commands in parallel on multiple hosts. ``cmds`` + is a list of tuples ``(node, cmd)``, in which the *node* is a `Node`_ + instance and *cmd* is a string with the command to execute for it. The + method returns a list of tuples ``(node, success, output)``, in which + ``success`` is True if the command ran successfully and ``output`` is + the combined stdout/stderr output for the corresponding ``node``. + + .. _Plugin.getGlobalOption: + + **getGlobalOption** (self, name) + + Returns the value of the global BroControl option or state + attribute *name*. If the user has not set the options, its default + value is returned. See the output of ``broctl config`` for a complete + list. + + .. _Plugin.getOption: + + **getOption** (self, name) + + Returns the value of one of the plugin's options, *name*. The + returned value will always be a string. + + An option has a default value (see *options()*), which can be + overridden by a user in ``broctl.cfg``. An option's value cannot be + changed by the plugin. + + .. _Plugin.getState: + + **getState** (self, name) + + Returns the current value of one of the plugin's state variables, + *name*. The returned value will always be a string. If it has not yet + been set, an empty string will be returned. + + Different from options, state variables can be set by the plugin and + are persistent across restarts. They are not visible to the user. + + Note that a plugin cannot query any global BroControl state variables. + + .. _Plugin.hosts: + + **hosts** (self, nodes) + + Returns a list of all hosts running at least one node from the list + of Nodes_ objects in *nodes*, or configured in if *nodes* is empty. + + .. _Plugin.message: + + **message** (self, msg) + + Reports a message to the user. + + .. _Plugin.nodes: + + **nodes** (self) + + Returns a list of all configured `Node`_ objects. + + .. _Plugin.parseNodes: + + **parseNodes** (self, names) + + Returns `Node`_ objects for a string of space-separated node names. + If a name does not correspond to a known node, an error message is + printed and the node is skipped from the returned list. If no names + are known, an empty list is returned. + + .. _Plugin.setState: + + **setState** (self, name, value) + + Sets one of the plugin's state variables, *name*, to *value*. + *value* must be a string. The change is permanent and will be recorded + to disk. + + Note that a plugin cannot change any global BroControl state + variables. + + .. _Plugin.broProcessDied: + + **broProcessDied** (self, node) + + Called when BroControl finds the Bro process for Node_ *node* + to have terminated unexpectedly. This method will be called just + before BroControl prepares the node's "crash report" and before it + cleans up the node's spool directory. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_attachgdb_post: + + **cmd_attachgdb_post** (self, nodes) + + Called just after the ``attachgdb`` command has finished. Arguments + are as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_attachgdb_pre: + + **cmd_attachgdb_pre** (self, nodes) + + Called just before the ``attachgdb`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_capstats_post: + + **cmd_capstats_post** (self, nodes, interval) + + Called just after the ``capstats`` command has finished. Arguments + are as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_capstats_pre: + + **cmd_capstats_pre** (self, nodes, interval) + + Called just before the ``capstats`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. *integer* is an integer with the measurement interval in + seconds. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_check_post: + + **cmd_check_post** (self, results) + + Called just after the ``check`` command has finished. It receives + the list of 2-tuples ``(node, bool)`` indicating the nodes the command + was executed for, along with their success status. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_check_pre: + + **cmd_check_pre** (self, nodes) + + Called just before the ``check`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_cleanup_post: + + **cmd_cleanup_post** (self, nodes, all) + + Called just after the ``cleanup`` command has finished. Arguments + are as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_cleanup_pre: + + **cmd_cleanup_pre** (self, nodes, all) + + Called just before the ``cleanup`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. *all* is boolean indicating whether the ``--all`` + argument has been given. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_config_post: + + **cmd_config_post** (self) + + Called just after the ``config`` command has finished. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_config_pre: + + **cmd_config_pre** (self) + + Called just before the ``config`` command is run. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_cron_post: + + **cmd_cron_post** (self, arg, watch) + + Called just after the ``cron`` command has finished. Arguments are + as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_cron_pre: + + **cmd_cron_pre** (self, arg, watch) + + Called just before the ``cron`` command is run. *arg* is None if + the cron is executed without arguments. Otherwise, it is one of the + strings: ``enable``, ``disable``, ``?``. *watch* is a boolean + indicating whether ``cron`` should restart abnormally terminated Bro + processes; it's only valid if arg is empty. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_custom: + + **cmd_custom** (self, cmd, args) + + Called when command defined by the ``commands`` method is executed. + ``cmd`` is the command (with the plugin's prefix), and ``args`` is a + single *string* with all arguments. + + If the arguments are actually node names, ``parseNodes`` can + be used to get the `Node`_ objects. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_df_post: + + **cmd_df_post** (self, nodes) + + Called just after the ``df`` command has finished. Arguments are as + with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_df_pre: + + **cmd_df_pre** (self, nodes) + + Called just before the ``df`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_diag_post: + + **cmd_diag_post** (self, nodes) + + Called just after the ``diag`` command has finished. Arguments are + as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_diag_pre: + + **cmd_diag_pre** (self, nodes) + + Called just before the ``diag`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_exec_post: + + **cmd_exec_post** (self, cmdline) + + Called just after the ``exec`` command has finished. Arguments are + as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_exec_pre: + + **cmd_exec_pre** (self, cmdline) + + Called just before the ``exec`` command is run. *cmdline* is a + string with the command line to execute. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_install_post: + + **cmd_install_post** (self) + + Called just after the ``install`` command has finished. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_install_pre: + + **cmd_install_pre** (self) + + Called just before the ``install`` command is run. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_netstats_post: + + **cmd_netstats_post** (self, nodes) + + Called just after the ``netstats`` command has finished. Arguments + are as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_netstats_pre: + + **cmd_netstats_pre** (self, nodes) + + Called just before the ``netstats`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_nodes_post: + + **cmd_nodes_post** (self) + + Called just after the ``nodes`` command has finished. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_nodes_pre: + + **cmd_nodes_pre** (self) + + Called just before the ``nodes`` command is run. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_peerstatus_post: + + **cmd_peerstatus_post** (self, nodes) + + Called just after the ``peerstatus`` command has finished. + Arguments are as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_peerstatus_pre: + + **cmd_peerstatus_pre** (self, nodes) + + Called just before the ``peerstatus`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_print_post: + + **cmd_print_post** (self, nodes, id) + + Called just after the ``print`` command has finished. Arguments are + as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_print_pre: + + **cmd_print_pre** (self, nodes, id) + + Called just before the ``print`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. *id* is a string with the name of the ID to be printed. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_process_post: + + **cmd_process_post** (self, trace, options, scripts, success) + + Called just after the ``process`` command has finished. Arguments + are as with the ``pre`` method, plus an additional boolean *success* + indicating whether Bro terminated normally. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_process_pre: + + **cmd_process_pre** (self, trace, options, scripts) + + Called just before the ``process`` command is run. It receives the + *trace* to read from as a string, a list of additional Bro *options*, + and a list of additional Bro scripts. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_restart_post: + + **cmd_restart_post** (self, results) + + Called just after the ``restart`` command has finished. It receives + the list of 2-tuples ``(node, bool)`` indicating the nodes the command + was executed for, along with their success status. The remaining + arguments are as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_restart_pre: + + **cmd_restart_pre** (self, nodes, clean) + + Called just before the ``restart`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. *clean* is boolean indicating whether the ``--clean`` + argument has been given. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_scripts_post: + + **cmd_scripts_post** (self, nodes, full_path, check) + + Called just after the ``scripts`` command has finished. Arguments + are as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_scripts_pre: + + **cmd_scripts_pre** (self, nodes, full_path, check) + + Called just before the ``scripts`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. ``full_path`` and ``check`` are boolean indicating + whether the ``-p`` and ``-c`` options were given, respectively. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_start_post: + + **cmd_start_post** (self, results) + + Called just after the ``start`` command has finished. It receives + the list of 2-tuples ``(node, bool)`` indicating the nodes the command + was executed for, along with their success status. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_start_pre: + + **cmd_start_pre** (self, nodes) + + Called just before the ``start`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_status_post: + + **cmd_status_post** (self, nodes) + + Called just after the ``status`` command has finished. Arguments + are as with the ``pre`` method. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_status_pre: + + **cmd_status_pre** (self, nodes) + + Called just before the ``status`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_stop_post: + + **cmd_stop_post** (self, results) + + Called just after the ``stop`` command has finished. It receives + the list of 2-tuples ``(node, bool)`` indicating the nodes the command + was executed for, along with their success status. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_stop_pre: + + **cmd_stop_pre** (self, nodes) + + Called just before the ``stop`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_top_post: + + **cmd_top_post** (self, nodes) + + Called just after the ``top`` command has finished. Arguments are + as with the ``pre`` method. Note that when ``top`` is run + interactively to auto-refresh continuously, this method will be called + once after each update. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_top_pre: + + **cmd_top_pre** (self, nodes) + + Called just before the ``top`` command is run. It receives the list + of nodes, and returns the list of nodes that should proceed with the + command. Note that when ``top`` is run interactively to auto-refresh + continuously, this method will be called once before each update. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_update_post: + + **cmd_update_post** (self, results) + + Called just after the ``update`` command has finished. It receives + the list of 2-tuples ``(node, bool)`` indicating the nodes the command + was executed for, along with their success status. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.cmd_update_pre: + + **cmd_update_pre** (self, nodes) + + Called just before the ``update`` command is run. It receives the + list of nodes, and returns the list of nodes that should proceed with + the command. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.commands: + + **commands** (self) + + Returns a set of custom commands provided by the + plugin. + + The return value is a list of 3-tuples each having the following + elements: + + ``command`` + A string with the command's name. Note that the command name + exposed to the user will be prefixed with the plugin's prefix + as returned by *name()* (e.g., ``myplugin.mycommand``). + + ``arguments`` + A string describing the command's arguments in a textual form + suitable for use in the ``help`` command summary (e.g., + ``[]`` for command taking an optional list of nodes). + Empty if no arguments are expected. + + ``description`` + A string with a description of the command's semantics. + + + This method can be overridden by derived classes. The implementation + must not call the parent class' implementation. The default + implementation returns an empty list. + + .. _Plugin.done: + + **done** (self) + + Called once just before BroControl terminates. This method can do + any cleanup the plugin may require. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.hostStatusChanged: + + **hostStatusChanged** (self, host, status) + + Called when BroControl's ``cron`` command finds the availability of + a cluster system to have changed. Initially, all systems are assumed + to be up and running. Once BroControl notices that a system isn't + responding (defined as either it doesn't ping at all, or does not + accept SSH sessions), it calls this method, passing in a string with + the name of the *host* and a boolean *status* set to False. Once the + host becomes available again, the method will be called again for the + same host with *status* now set to True. + + Note that BroControl's ``cron`` tracks a host's availability across + execution, so if the next time it's run the host is still down, this + method will not be called again. + + This method can be overridden by derived classes. The default + implementation does nothing. + + .. _Plugin.init: + + **init** (self) + + Called once just before BroControl starts executing any commands. + This method can do any initialization that the plugin may require. + + Note that when this method executes, BroControl guarantees that all + internals are fully set up (e.g., user-defined options are available). + This may not be the case when the class ``__init__`` method runs. + + Returns a boolean, indicating whether the plugin should be used. If it + returns ``False``, the plugin will be removed and no other methods + called. + + This method can be overridden by derived classes. The default + implementation always returns True. + + .. _Plugin.name: + + **name** (self) + + Returns a string with a descriptive *name* for the plugin (e.g., + ``"TestPlugin"``). The name must not contain any whitespace. + + This method must be overridden by derived classes. The implementation + must not call the parent class' implementation. + + .. _Plugin.nodeKeys: + + **nodeKeys** (self) + + Returns a list of custom keys for ``node.cfg``. The value for a + key will be available from the `Node`_ object as attribute + ``_`` (e.g., ``node.test_mykw``). If not set, the + attribute will be set to None. + + This method can be overridden by derived classes. The implementation + must not call the parent class' implementation. The default + implementation returns an empty list. + + .. _Plugin.options: + + **options** (self) + + Returns a set of local configuration options provided by the + plugin. + + The return value is a list of 4-tuples each having the following + elements: + + ``name`` + A string with name of the option (e.g., ``Path``). Option + names are case-insensitive. Note that the option name exposed + to the user will be prefixed with your plugin's prefix as + returned by *name()* (e.g., ``myplugin.Path``). + + ``type`` + A string with type of the option, which must be one of + ``"bool"``, ``"string"``, or ``"int"``. + + ``default`` + A string with the option's default value. Note that this must + always be a string, even for non-string types. For booleans, + use ``"0"`` for False and ``"1"`` for True. For integers, give + the value as a string ``"42"``. + + ``description`` + A string with a description of the option semantics. + + This method can be overridden by derived classes. The implementation + must not call the parent class' implementation. The default + implementation returns an empty list. + + .. _Plugin.pluginVersion: + + **pluginVersion** (self) + + Returns an integer with a version number for the plugin. Plugins + should increase their version number with any significant change. + + This method must be overridden by derived classes. The implementation + must not call the parent class' implementation. + + .. _Plugin.prefix: + + **prefix** (self) + + Returns a string with a prefix for the plugin's options and + commands names (e.g., "myplugin"). + + This method can be overridden by derived classes. The implementation + must not call the parent class' implementation. The default + implementation returns a lower-cased version of *name()*. + +.. _Node: + +Class ``Node`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class **Node** + Class representing one node of the BroControl maintained setup. In + standalone mode, there's always exactly one node of type ``standalone``. In + a cluster setup, there is exactly one of type ``manager``, one or + more of type ``proxy``, and zero or more of type ``worker``. + + In addition to the methods described above, a ``Node`` object has a number + of keys with values that are set via ``node.cfg`` and can be accessed + directly via corresponding Python attributes (e.g., ``node.name``): + + ``name`` (string) + The name of the node, which corresponds to the ``[]`` + section in ``node.cfg``. + + ``type`` (string) + The type of the node, which will be one of ``standalone``, + ``manager``, ``proxy``, and ``worker``. + + ``host`` (string) + The hostname of the system the node is running on. + + ``interface`` (string) + The network interface for Bro to use; empty if not set. + + ``lb_procs`` (integer) + The number of clustered Bro workers you'd like to start up. + + ``lb_method`` (string) + The load balancing method to distribute packets to all of the + processes (must be one of: ``pf_ring``, ``myricom``, or + ``interfaces``). + + ``lb_interfaces`` (string) + If the load balancing method is ``interfaces``, then this is + a comma-separated list of network interface names to use. + + ``aux_scripts`` (string) + Any node-specific Bro script configured for this node. + + ``zone_id`` (string) + If BroControl is managing a cluster comprised of nodes + using non-global IPv6 addresses, then this configures the + RFC 4007 ``zone_id`` string that the node associates with + the common zone that all cluster nodes are a part of. This + identifier may differ between nodes. + + Any attribute that is not defined in ``node.cfg`` will be empty. + + In addition, plugins can override `Plugin.nodeKeys`_ to define their own + node keys, which can then be likewise set in ``node.cfg``. The key names + will be prepended with the plugin's `Plugin.prefix`_ (e.g., for the plugin + ``test``, the node key ``foo`` is set by adding ``test.foo=value`` to + ``node.cfg``). + + .. _Node.cwd: + + **cwd** (self) + + Returns a string with the node's working directory. + + .. _Node.describe: + + **describe** (self) + + Returns an extended string representation of the node including all + its keys with values. + + .. _Node.getPID: + + **getPID** (self) + + Returns the process ID of the node's Bro process if running, and + None otherwise. + + .. _Node.getPort: + + **getPort** (self) + + Returns an integer with the port that this node's communication + system is listening on for incoming connections, or -1 if no such port + has been set yet. + + .. _Node.hasCrashed: + + **hasCrashed** (self) + + Returns True if the node's Bro process has exited abnormally. + + +Miscellaneous +------------- + +Mails +~~~~~ + +*BroControl* sends four types of mails to the address given in +``MailTo``: + +1. When logs are rotated (per default once a day), a list of all + alarms during the last rotation interval is sent. This can be + disabled by setting ``MailAlarms=0``. + +2. When the ``cron`` command notices that a node has crashed, it + restarts it and sends a notification. It may also send a more + detailed crash report containing information about the crash. + +3. NOTICES with a notice action ``EMAIL``. + +4. If `trace-summary `_ + is installed, a traffic summary is sent each rotation interval. + +Performance Analysis +~~~~~~~~~~~~~~~~~~~~ + +*TODO*: ``broctl cron`` logs a number of statistics, which can be +analyzed/plotted for understanding the clusters run-time behavior. + +Questions and Answers +--------------------- + +*Can I use an NFS-mounted partition as the cluster's base directory to avoid the ``rsync``'ing?* + Yes. BroBase_ can be on an NFS partition. + Configure and install the shell as usual with + ``--prefix=``. Then add ``HaveNFS=1`` and + ``SpoolDir=`` to ``broctl.cfg``, where ```` is a + path on the local disks of the nodes; ```` will be used for + all non-shared data (make sure that the parent directory exists + and is writable on all nodes!). Then run ``make install`` again. + Finally, you can remove ``/spool`` (or link it to ). + In addition, you might want to keep the log files locally on the nodes + as well by setting LogDir_ to a non-NFS directory. (Only + the manager's logs will be kept permanently, the logs of + workers/proxies are discarded upon rotation.) + +*When I'm using the stand-alone mode, do I still need to have ``ssh`` and ``rsync`` installed and configured?* + No. In stand-alone mode all operations are performed directly on the local + file system. + +*What do I need to do when something in the Bro distribution changes?* + After pulling from the main Bro git repository, just re-run ``make + install`` inside your build directory. It will reinstall all the + files from the distribution that are not up-to-date. Then do + ``broctl install`` to make sure everything gets pushed out. + +*Can I change the naming scheme that BroControl uses for archived log files?* + Yes, set MakeArchiveName_ to a + script that outputs the desired destination file name for an + archived log file. The default script for that task is + ``/share/broctl/scripts/make-archive-name``, which you + can use as a template for creating your own version. See + the beginning of that script for instructions. + +*Can BroControl manage a cluster of nodes over non-global IPv6 scope (e.g. link-local)?* + Yes, set ``ZoneID`` in ``broctl.cfg`` to the zone identifier + that the BroControl node uses to identify the scope zone + (the ``ifconfig`` command output is usually helpful, if it doesn't + show the zone identifier appended to the address with a '%' + character, then it may just be the interface name). Then in + ``node.cfg``, add a ``zone_id`` key to each node section + representing that particular node's zone identifier and set + the ``host`` key to the IPv6 address assigned to the node within + the scope zone. Most nodes probably have the same ``zone_id``, but + may not if their interface configuration differs. See RFC 4007 for + more information on IPv6 scoped addresses and zones. diff --git a/doc/components/btest/README.rst b/doc/components/btest/README.rst new file mode 100644 index 0000000000..03a859e735 --- /dev/null +++ b/doc/components/btest/README.rst @@ -0,0 +1,843 @@ +.. -*- mode: rst-mode -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 0.4-14 + +============================================ +BTest - A Simple Driver for Basic Unit Tests +============================================ + +.. rst-class:: opening + + The ``btest`` is a simple framework for writing unit tests. Freely + borrowing some ideas from other packages, it's main objective is to + provide an easy-to-use, straightforward driver for a suite of + shell-based tests. Each test consists of a set of command lines that + will be executed, and success is determined based on their exit + codes. ``btest`` comes with some additional tools that can be used + within such tests to compare output against a previously established + baseline. + +.. contents:: + +Download +======== + +You can find the latest BTest release for download at +http://www.bro.org/download. + +BTest's git repository is located at `git://git.bro.org/btest.git +`__. You can browse the repository +`here `__. + +This document describes BTest |version|. See the ``CHANGES`` +file for version history. + + +Installation +============ + +Installation is simple and standard:: + + tar xzvf btest-*.tar.gz + cd btest-* + python setup.py install + +This will install a few scripts: ``btest`` is the main driver program, +and there are a number of further helper scripts that we discuss below +(including ``btest-diff``, which is a tool for comparing output to a +previously established baseline). + +Writing a Simple Test +===================== + +In the most simple case, ``btest`` simply executes a set of command +lines, each of which must be prefixed with ``@TEST-EXEC:`` +:: + + > cat examples/t1 + @TEST-EXEC: echo "Foo" | grep -q Foo + @TEST-EXEC: test -d . + > btest examples/t1 + examples.t1 ... ok + +The test passes as both command lines return success. If one of them +didn't, that would be reported:: + + > cat examples/t2 + @TEST-EXEC: echo "Foo" | grep -q Foo + @TEST-EXEC: test -d DOESNOTEXIST + > btest examples/t2 + examples.t2 ... failed + +Usually you will just run all tests found in a directory:: + + > btest examples + examples.t1 ... ok + examples.t2 ... failed + 1 test failed + +Why do we need the ``@TEST-EXEC:`` prefixes? Because the file +containing the test can simultaneously act as *its input*. Let's +say we want to verify a shell script:: + + > cat examples/t3.sh + # @TEST-EXEC: sh %INPUT + ls /etc | grep -q passwd + > btest examples/t3.sh + examples.t3 ... ok + +Here, ``btest`` is executing (something similar to) ``sh +examples/t3.sh``, and then checks the return value as usual. The +example also shows that the ``@TEST-EXEC`` prefix can appear +anywhere, in particular inside the comment section of another +language. + +Now, let's say we want to check the output of a program, making sure +that it matches what we expect. For that, we first add a command +line to the test that produces the output we want to check, and then +run ``btest-diff`` to make sure it matches a previously recorded +baseline. ``btest-diff`` is itself just a script that returns +success if the output is as expected, and failure otherwise. In the +following example, we use an awk script as a fancy way to print all +file names starting with a dot in the user's home directory. We +write that list into a file called ``dots`` and then check whether +its content matches what we know from last time:: + + > cat examples/t4.awk + # @TEST-EXEC: ls -a $HOME | awk -f %INPUT >dots + # @TEST-EXEC: btest-diff dots + /^\.+/ { print $1 } + +Note that each test gets its own little sandbox directory when run, +so by creating a file like ``dots``, you aren't cluttering up +anything. + +The first time we run this test, we need to record a baseline:: + + > btest -U examples/t4.awk + +Now, ``btest-diff`` has remembered what the ``dots`` file should +look like:: + + > btest examples/t4.awk + examples.t4 ... ok + > touch ~/.NEWDOTFILE + > btest examples/t4.awk + examples.t4 ... failed + 1 test failed + +If we want to see what exactly the unexpected change is that was +introduced to ``dots``, there's a *diff* mode for that:: + + > btest -d examples/t4.awk + examples.t4 ... failed + % 'btest-diff dots' failed unexpectedly (exit code 1) + % cat .diag + == File =============================== + [... current dots file ...] + == Diff =============================== + --- /Users/robin/work/binpacpp/btest/Baseline/examples.t4/dots + 2010-10-28 20:11:11.000000000 -0700 + +++ dots 2010-10-28 20:12:30.000000000 -0700 + @@ -4,6 +4,7 @@ + .CFUserTextEncoding + .DS_Store + .MacOSX + +.NEWDOTFILE + .Rhistory + .Trash + .Xauthority + ======================================= + + % cat .stderr + [... if any of the commands had printed something to stderr, that would follow here ...] + +Once we delete the new file, we are fine again:: + + > rm ~/.NEWDOTFILE + > btest -d examples/t4.awk + examples.t4 ... ok + +That's already the main functionality that the ``btest`` package +provides. In the following, we describe a number of further options +extending/modifying this basic approach. + +Reference +========= + +Command Line Usage +------------------ + +``btest`` must be started with a list of tests and/or directories +given on the command line. In the latter case, the default is to +recursively scan the directories and assume all files found to be +tests to perform. It is however possible to exclude certain files by +specifying a suitable `configuration file`_. + +``btest`` returns exit code 0 if all tests have successfully passed, +and 1 otherwise. + +``btest`` accepts the following options: + + -a ALTERNATIVE, --alternative=ALTERNATIVE + Activates an alternative_ configuration defined in the + configuration file. This option can be given multiple times to + run tests with several alternatives. If ``ALTERNATIVE`` is ``-`` + that refers to running with the standard setup, which can be used + to run tests both with and without alterantives by giving both. + + -b, --brief + Does not output *anything* for tests which pass. If all tests + pass, there will not be any output at all. + + -c CONFIG, --config=CONFIG + Specifies an alternative `configuration file`_ to use. If not + specified, the default is to use a file called ``btest.cfg`` + if found in the current directory. + + -d, --diagnostics + Reports diagnostics for all failed tests. The diagnostics + include the command line that failed, its output to standard + error, and potential additional information recorded by the + command line for diagnostic purposes (see `@TEST-EXEC`_ + below). In the case of ``btest-diff``, the latter is the + ``diff`` between baseline and actual output. + + -D, --diagnostics-all + Reports diagnostics for all tests, including those which pass. + + -f DIAGFILE, --file-diagnostics=DIAGFILE + Writes diagnostics for all failed tests into the given file. + If the file already exists, it will be overwritten. + + -g GROUPS, --group=GROUPS + Runs only tests assigned to the given test groups, see + `@TEST-GROUP`_. Multiple groups can be given as a + comma-separated list. Specifying ``-`` as a group name selects + all tests that do not belong to any group. + + -j [THREADS], --jobs[=THREADS] + Runs up to the given number of tests in parallel. If no number + is given, BTest substitutes the number of available CPU cores + as reported by the OS. + + By default, BTest assumes that all tests can be executed + concurrently without further constraints. One can however + ensure serialization of subsets by assigning them to the same + serialization set, see `@TEST-SERIALIZE`_. + + -q, --quiet + Suppress information output other than about failed tests. + If all tests pass, there will not be any output at all. + + -r, --rerun + Runs only tests that failed last time. After each execution + (except when updating baselines), BTest generates a state file + that records the tests that have failed. Using this option on + the next run then reads that file back in and limits execution + to those tests found in there. + + -t, --tmp-keep + Does not delete any temporary files created for running the + tests (including their outputs). By default, the temporary + files for a test will be located in ``.tmp//``, where + ```` is the relative path of the test file with all slashes + replaced with dots and the file extension removed (e.g., the files + for ``example/t3.sh`` will be in ``.tmp/example.t3``). + + -U, --update-baseline + Records a new baseline for all ``btest-diff`` commands found + in any of the specified tests. To do this, all tests are run + as normal except that when ``btest-diff`` is executed, it + does not compute a diff but instead considers the given file + to be authoritative and records it as the version to compare + with in future runs. + + -u, --update-interactive + Each time a ``btest-diff`` command fails in any tests that are + run, btest will stop and ask whether or not the user wants to + record a new baseline. + + -v, --verbose + Shows all test command lines as they are executed. + + -w, --wait + Interactively waits for ```` after showing diagnostics + for a test. + + -x FILE, --xml=FILE + Records test results in JUnit XML format to the given file. + If the file exists already, it is overwritten. + +.. _configuration file: + +Configuration +------------- + +Specifics of ``btest``'s execution can be tuned with a configuration +file, which by default is ``btest.cfg`` if that's found in the +current directory. It can alternatively be specified with the +``--config`` command line option. The configuration file is +"INI-style", and an example comes with the distribution, see +``btest.cfg.example``. A configuration file has one main section, +``btest``, that defines most options; as well as an optional section +for defining `environment variables`_ and further optional sections +for defining alternatives_. + +Note that all paths specified in the configuration file are relative +to ``btest``'s *base directory*. The base directory is either the +one where the configuration file is located if such is given/found, +or the current working directory if not. When setting values for +configuration options, the absolute path to the base directory is +available by using the macro ``%(testbase)s`` (the weird syntax is +due to Python's ``ConfigParser`` module). + +Furthermore, all values can use standard "backtick-syntax" to +include the output of external commands (e.g., xyz=`\echo test\`). +Note that the backtick expansion is performed after any ``%(..)`` +have already been replaced (including within the backticks). + +Options +~~~~~~~ + +The following options can be set in the ``btest`` section of the +configuration file: + +``TestDirs`` + A space-separated list of directories to search for tests. If + defined, one doesn't need to specify any tests on the command + line. + +``TmpDir`` + A directory where to create temporary files when running tests. + By default, this is set to ``%(testbase)s/.tmp``. + +``BaselineDir`` + A directory where to store the baseline files for ``btest-diff``. + By default, this is set to ``%(testbase)s/Baseline``. + +``IgnoreDirs`` + A space-separated list of relative directory names to ignore + when scanning test directories recursively. Default is empty. + +``IgnoreFiles`` + A space-separated list of filename globs matching files to + ignore when scanning given test directories recursively. + Default is empty. + +``StateFile`` + The name of the state file to record the names of failing tests. Default is + ``.btest.failed.dat``. + +``Finalizer`` + An executable that will be executed each time any test has + successfully run. It runs in the same directory as the test itself + and receives the name of the test as its parameter. The return + value indicates whether the test should indeed be considered + successful. By default, there's no finalizer set. + +.. _environment variables: + +Environment Variables +~~~~~~~~~~~~~~~~~~~~~ + +A special section ``environment`` defines environment variables that +will be propagated to all tests:: + + [environment] + CFLAGS=-O3 + PATH=%(testbase)s/bin:%(default_path)s + +Note how ``PATH`` can be adjusted to include local scripts: the +example above prefixes it with a local ``bin/`` directory inside the +base directory, using the predefined ``default_path`` macro to refer +to the ``PATH`` as it is set by default. + +Furthermore, by setting ``PATH`` to include the ``btest`` +distribution directory, one could skip the installation of the +``btest`` package. + +.. _alternative: + +Alternatives +~~~~~~~~~~~~ + +BTest can run a set of tests with different settings than it would +normally use by specifying an *alternative* configuration. Currently, +three things can be adjusted: + + - Further environment variables can be set that will then be + available to all the commands that a test executes. + + - *Filters* can modify an input file before a test uses it. + + - *Substitutions* can modify command lines executed as part of a + test. + +We discuss the three separately in the following. All of them are +defined by adding sections ``[-]`` where ```` +corresponds to the type of adjustment being made and ```` is the +name of the alternative. Once at least one section is defined for a +name, that alternative can be enabled by BTest's ``--alternative`` +flag. + +Environment Variables +^^^^^^^^^^^^^^^^^^^^^ + +An alternative can add further environment variables by defining an +``[environment-]`` section: + + [environment-myalternative] + CFLAGS=-O3 + +Running ``btest`` with ``--alternative=myalternative`` will now make +the ``CFLAGS`` environment variable available to all commands +executed. + +.. _filters: + +Filters +^^^^^^^ + +Filters are a transparent way to adapt the input to a specific test +command before it is executed. A filter is defined by adding a section +``[filter-]`` to the configuration file. This section must have +exactly one entry, and the name of that entry is interpreted as the +name of a command whose input is to be filtered. The value of that +entry is the name of a filter script that will be run with two +arguments representing input and output files, respectively. Example:: + + [filter-myalternative] + cat=%(testbase)s/bin/filter-cat + +Once the filter is activated by running ``btest`` with +``--alternative=myalternative``, every time a ``@TEST-EXEC: cat +%INPUT`` is found, ``btest`` will first execute (something similar to) +``%(testbase)s/bin/filter-cat %INPUT out.tmp``, and then subsequently +``cat out.tmp`` (i.e., the original command but with the filtered +output). In the simplest case, the filter could be a no-op in the +form ``cp $1 $2``. + +.. note:: + There are a few limitations to the filter concept currently: + + * Filters are *always* fed with ``%INPUT`` as their first + argument. We should add a way to filter other files as well. + + * Filtered commands are only recognized if they are directly + starting the command line. For example, ``@TEST-EXEC: ls | cat + >outout`` would not trigger the example filter above. + + * Filters are only executed for ``@TEST-EXEC``, not for + ``@TEST-EXEC-FAIL``. + +.. _substitution: + +Substitutions +^^^^^^^^^^^^^^ + +Substitutions are similar to filters, yet they do not adapt the input +but the command line being executed. A substitution is defined by +adding a section ``[substitution-]`` to the configuration file. +For each entry in this section, the entry's name specifies the +command that is to be replaced with something else given as its value. +Example:: + + [substitution-myalternative] + gcc=gcc -O2 + +Once the substitution is activated by running ``btest`` with +``--alternative=myalternative``, every time a ``@TEST-EXEC`` executes +``gcc``, that is replaced with ``gcc -O2``. The replacement is simple +string substitution so it works not only with commands but anything +found on the command line; it however only replaces full words, not +subparts of words. + +Writing Tests +------------- + +``btest`` scans a test file for lines containing keywords that +trigger certain functionality. Currently, the following keywords are +supported: + +.. _@TEST-EXEC: + +``@TEST-EXEC: `` + Executes the given command line and aborts the test if it + returns an error code other than zero. The ```` is + passed to the shell and thus can be a pipeline, use redirection, + and any environment variables specified in ```` will be + expanded, etc. + + When running a test, the current working directory for all + command lines will be set to a temporary sandbox (and will be + deleted later). + + There are two macros that can be used in ````: + ``%INPUT`` will be replaced with the full pathname of the file defining + the test; and ``%DIR`` will be replaced with the directory where + the test file is located. The latter can be used to reference + further files also located there. + + In addition to environment variables defined in the + configuration file, there are further ones that are passed into + the commands: + + ``TEST_DIAGNOSTICS`` + A file where further diagnostic information can be saved + in case a command fails. ``--diagnostics`` will show + this file. (This is also where ``btest-diff`` stores its + diff.) + + ``TEST_MODE`` + This is normally set to ``TEST``, but will be ``UPDATE`` + if ``btest`` is run with ``--update-baseline``, or + ``UPDATE_INTERACTIVE`` if run with ``--update-interactive``. + + ``TEST_BASELINE`` + The name of a directory where the command can save permanent + information across ``btest`` runs. (This is where + ``btest-diff`` stores its baseline in ``UPDATE`` mode.) + + ``TEST_NAME`` + The name of the currently executing test. + + ``TEST_VERBOSE`` + The path of a file where the test can record further + information about its execution that will be included with + btest's ``--verbose`` output. This is for further tracking + the execution of commands and should generally generate + output that follows a line-based structure. + + .. note:: + + If a command returns the special exit code 100, the test is + considered failed, however subsequent test commands are still + run. ``btest-diff`` uses this special exit code to indicate that + no baseline has yet been established. + + If a command returns the special exit code 200, the test is + considered failed and all further test executions are aborted. + + +``@TEST-EXEC-FAIL: `` + Like ``@TEST-EXEC``, except that this expects the command to + *fail*, i.e., the test is aborted when the return code is zero. + +``@TEST-REQUIRES: `` + Defines a condition that must be met for the test to be executed. + The given command line will be run before any of the actual test + commands, and it must return success for the test to continue. If + it does not return success, the rest of the test will be skipped + but doing so will not be considered a failure of the test. This allows to + write conditional tests that may not always make sense to run, depending + on whether external constraints are satisfied or not (say, whether + a particular library is available). Multiple requirements may be + specified and then all must be met for the test to continue. + +``@TEST-ALTERNATIVE: `` Runs this test only for the given + alternative (see alternative_). If ```` is + ``default``, the test executes when BTest runs with no alternative + given (which however is the default anyways). + +``@TEST-NOT-ALTERNATIVE: `` Ignores this test for the + given alternative (see alternative_). If ```` is + ``default``, the test is ignored if BTest runs with no alternative + given. + +``@TEST-COPY-FILE: `` + Copy the given file into the test's directory before the test is + run. If ```` is a relative path, it's interpreted relative + to the BTest's base directory. Environment variables in ```` + will be replaced if enclosed in ``${..}``. This command can be + given multiple times. + +``@TEST-START-NEXT`` + This is a short-cut for defining multiple test inputs in the + same file, all executing with the same command lines. When + ``@TEST-START-NEXT`` is encountered, the test file is initially + considered to end at that point, and all ``@TEST-EXEC-*`` are + run with an ``%INPUT`` truncated accordingly. Afterwards, a + *new* ``%INPUT`` is created with everything *following* the + ``@TEST-START-NEXT`` marker, and the *same* commands are run + again (further ``@TEST-EXEC-*`` will be ignored). The effect is + that a single file can actually define two tests, and the + ``btest`` output will enumerate them:: + + > cat examples/t5.sh + # @TEST-EXEC: cat %INPUT | wc -c >output + # @TEST-EXEC: btest-diff output + + This is the first test input in this file. + + # @TEST-START-NEXT + + ... and the second. + + > ./btest -D examples/t5.sh + examples.t5 ... ok + % cat .diag + == File =============================== + 119 + [...] + + examples.t5-2 ... ok + % cat .diag + == File =============================== + 22 + [...] + + Multiple ``@TEST-START-NEXT`` can be used to create more than + two tests per file. + +``@TEST-START-FILE `` + This is used to include an additional input file for a test + right inside the test file. All lines following the keyword will + be written into the given file (and removed from the test's + `%INPUT`) until a terminating ``@TEST-END-FILE`` is found. + Example:: + + > cat examples/t6.sh + # @TEST-EXEC: awk -f %INPUT output + # @TEST-EXEC: btest-diff output + + { lines += 1; } + END { print lines; } + + @TEST-START-FILE foo.dat + 1 + 2 + 3 + @TEST-END-FILE + + > btest -D examples/t6.sh + examples.t6 ... ok + % cat .diag + == File =============================== + 3 + + Multiple such files can be defined within a single test. + + Note that this is only one way to use further input files. + Another is to store a file in the same directory as the test + itself, making sure it's ignored via ``IgnoreFiles``, and then + refer to it via ``%DIR/``. + +.. _@TEST-GROUP: + +``@TEST-GROUP: `` + Assigns the test to a group of name ````. By using option + ``-g`` one can limit execution to all tests that belong to a given + group (or a set of groups). + +.. _@TEST-SERIALIZE: + +``@TEST-SERIALIZE: `` + When using option ``-j`` to parallelize execution, all tests that + specify the same serialization set are guaranteed to run + sequentially. ```` is an arbitrary user-chosen string. + + +Canonifying Diffs +================= + +``btest-diff`` has the capability to filter its input through an +additional script before it compares the current version with the +baseline. This can be useful if certain elements in an output are +*expected* to change (e.g., timestamps). The filter can then +remove/replace these with something consistent. To enable such +canonification, set the environment variable +``TEST_DIFF_CANONIFIER`` to a script reading the original version +from stdin and writing the canonified version to stdout. Note that +both baseline and current output are passed through the filter +before their differences are computed. + +Running Processes in the Background +=================================== + +Sometimes processes need to be spawned in the background for a test, +in particular if multiple processes need to cooperate in some fashion. +``btest`` comes with two helper scripts to make life easier in such a +situation: + +``btest-bg-run `` + This is a script that runs ```` in the background, i.e., + it's like using ``cmdline &`` in a shell script. Test execution + continues immediately with the next command. Note that the spawned + command is *not* run in the current directory, but instead in a + newly created sub-directory called ````. This allows + spawning multiple instances of the same process without needing to + worry about conflicting outputs. If you want to access a command's + output later, like with ``btest-diff``, use ``/foo.log`` to + access it. + +``btest-bg-wait [-k] `` + This script waits for all processes previously spawned via + ``btest-bg-run`` to finish. If any of them exits with a non-zero + return code, ``btest-bg-wait`` does so as well, indicating a + failed test. ```` is mandatory and gives the maximum + number of seconds to wait for any of the processes to terminate. + If any process hasn't done so when the timeout expires, it will be + killed and the test is considered to be failed as long as ``-k`` + is not given. If ``-k`` is given, pending processes are still + killed but the test continues normally, i.e., non-termination is + not considered a failure in this case. This script also collects + the processes' stdout and stderr outputs for diagnostics output. + +Integration with Sphinx +======================= + +``btest`` comes with a new directive for the documentation framework +`Sphinx `_. The directive allows to write a +test directly inside a Sphinx document, and then to include output +from the test's command into the generated documentation. The same +tests can also run externally and will catch if any changes to the +included content occur. The following walks through setting this up. + +Configuration +------------- + +First, you need to tell Sphinx a base directory for the ``btest`` +configuration as well as a directory in there where to store tests +it extracts from the Sphinx documentation. Typically, you'd just +create a new subdirectory ``tests`` in the Sphinx project for the +``btest`` setup and then store the tests in there in, e.g., +``doc/``:: + + cd + mkdir tests + mkdir tests/doc + +Then add the following to your Sphinx ``conf.py``:: + + extensions += ["btest-sphinx"] + btest_base="tests" # Relative to Sphinx-root. + btest_tests="doc" # Relative to btest_base. + +Next, a finalizer to ``btest.cfg``:: + + [btest] + ... + Finalizer=btest-diff-rst + +Finally, create a ``btest.cfg`` in ``tests/`` as usual and add +``doc/`` to the ``TestDirs`` option. + +Including a Test into a Sphinx Document +--------------------------------------- + +The ``btest`` extension provides a new directive to include a test +inside a Sphinx document:: + + + .. btest:: + + + +Here, ```` is a custom name for the test; it will be +stored in ``btest_tests`` under that name. ```` is just +a standard test as you would normally put into one of the +``TestDirs``. Example:: + + + .. btest:: just-a-test + + @TEST-EXEC: expr 2 + 2 + +When you now run Sphinx, it will (1) store the test content into +``tests/doc/just-a-test`` (assuming the above path layout), and (2) +execute the test by running ``btest`` on it. You can then run +``btest`` manually in ``tests/`` as well and it will execute the test +just as it would in a standard setup. If a test fails when Sphinx runs +it, there will be a corresponding error and include the diagnostic output +into the document. + +By default, nothing else will be included into the generated +documentation, i.e., the above test will just turn into an empty text +block. However, ``btest`` comes with a set of scripts that you can use +to specify content to be included. As a simple example, +``btest-rst-cmd `` will execute a command and (if it +succeeds) include both the command line and the standard output into +the documentation. Example:: + + .. btest:: another-test + + @TEST-EXEC: btest-rst-cmd echo Hello, world! + +When running Sphinx, this will render as: + +.. code:: + + # echo Hello, world! + Hello world! + + +When running ``btest`` manually in ``tests/``, the ``Finalizer`` we +added to ``btest.cfg`` (see above) compares the generated reST code +with a previously established baseline, just like ``btest-diff`` does +with files. To establish the initial baseline, run ``btest -u``, like +you would with ``btest-diff``. + +Scripts +------- + +The following Sphinx support scripts come with ``btest``: + +``btest-rst-cmd [options] `` + + By default, this executes ```` and includes both the + command line itself and its standard output into the generated + documentation. See above for an example. + + This script provides the following options: + + -c ALTERNATIVE_CMDLINE + Show ``ALTERNATIVE_CMDLINE`` in the generated + documentation instead of the one actually executed. (It + still runs the ```` given outside the option.) + + -d + Do not actually execute ````; just format it for + the generated documentation and include no further output. + + -f FILTER_CMD + Pipe the command line's output through ``FILTER_CMD`` + before including. If ``-r`` is given, it filters the + file's content instead of stdout. + + -o + Do not include the executed command into the generated + documentation, just its output. + + -r FILE + Insert ``FILE`` into output instead of stdout. + + +``btest-rst-include `` + + Includes ```` inside a code block. + +``btest-rst-pipe `` + + Executes ````, includes its standard output inside a code + block. Note that this script does not include the command line + itself into the code block, just the output. + +.. note:: + + All these scripts can be run directly from the command line to show + the reST code they generate. + +.. note:: + + ``btest-rst-cmd`` can do everything the other scripts provide if + you give it the right options. In fact, the other scripts are + provided just for convenience and leverage ``btest-rst-cmd`` + internally. + +License +======= + +btest is open-source under a BSD licence. + diff --git a/doc/components/capstats/README.rst b/doc/components/capstats/README.rst new file mode 100644 index 0000000000..1ddc07c51c --- /dev/null +++ b/doc/components/capstats/README.rst @@ -0,0 +1,107 @@ +.. -*- mode: rst-mode -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 0.18 + +=============================================== +capstats - A tool to get some NIC statistics. +=============================================== + +.. rst-class:: opening + + capstats is a small tool to collect statistics on the + current load of a network interface, using either `libpcap + `_ or the native interface for `Endace's + `_. It reports statistics per time interval + and/or for the tool's total run-time. + +Download +-------- + +You can find the latest capstats release for download at +http://www.bro.org/download. + +Capstats's git repository is located at `git://git.bro.org/capstats.git +`__. You can browse the repository +`here `__. + +This document describes capstats |version|. See the ``CHANGES`` +file for version history. + + +Output +------ + +Here's an example output with output in one-second intervals until +``CTRL-C`` is hit: + +.. console:: + + >capstats -i nve0 -I 1 + 1186620936.890567 pkts=12747 kpps=12.6 kbytes=10807 mbps=87.5 nic_pkts=12822 nic_drops=0 u=960 t=11705 i=58 o=24 nonip=0 + 1186620937.901490 pkts=13558 kpps=13.4 kbytes=11329 mbps=91.8 nic_pkts=13613 nic_drops=0 u=1795 t=24339 i=119 o=52 nonip=0 + 1186620938.912399 pkts=14771 kpps=14.6 kbytes=13659 mbps=110.7 nic_pkts=14781 nic_drops=0 u=2626 t=38154 i=185 o=111 nonip=0 + 1186620939.012446 pkts=1332 kpps=13.3 kbytes=1129 mbps=92.6 nic_pkts=1367 nic_drops=0 u=2715 t=39387 i=194 o=112 nonip=0 + === Total + 1186620939.012483 pkts=42408 kpps=13.5 kbytes=36925 mbps=96.5 nic_pkts=1 nic_drops=0 u=2715 t=39387 i=194 o=112 nonip=0 + +Each line starts with a timestamp and the other fields are: + + :pkts: + Absolute number of packets seen by ``capstats`` during interval. + + :kpps: + Number of packets per second. + + :kbytes: + Absolute number of KBytes during interval. + + :mbps: + Mbits/sec. + + :nic_pkts: + Number of packets as reported by ``libpcap``'s ``pcap_stats()`` (may not match _pkts_) + + :nic_drops: + Number of packet drops as reported by ``libpcap``'s ``pcap_stats()``. + + :u: + Number of UDP packets. + + :t: + Number of TCP packets. + + :i: + Number of ICMP packets. + + :nonip: + Number of non-IP packets. + +Options +------- + +A list of all options:: + + capstats [Options] -i interface + + -i| --interface Listen on interface + -d| --dag Use native DAG API + -f| --filter BPF filter + -I| --interval Stats logging interval + -l| --syslog Use syslog rather than print to stderr + -n| --number Stop after outputting intervals + -N| --select Use select() for live pcap (for testing only) + -p| --payload Verifies that packets' payloads consist + entirely of bytes of the given value. + -q| --quiet Suppress output, exit code indicates >= count + packets received. + -S| --size Verify packets to have given + -s| --snaplen Use pcap snaplen + -v| --version Print version and exit + -w| --write Write packets to file + +Installation +------------ + +``capstats`` has been tested on Linux, FreeBSD, and MacOS. Please see +the ``INSTALL`` file for installation instructions. diff --git a/doc/components/index.rst b/doc/components/index.rst new file mode 100644 index 0000000000..8ffbdea1f7 --- /dev/null +++ b/doc/components/index.rst @@ -0,0 +1,28 @@ + +===================== +Additional Components +===================== + +The following are snapshots of documentation for components that come +with this version of Bro (|version|). Since they can also be used +independently, see the `download page +`_ for documentation of any +current, independent component releases. + +.. toctree:: + :maxdepth: 1 + + BinPAC - A protocol parser generator + Broccoli - The Bro Client Communication Library (README) + Broccoli - User Manual + Broccoli Python Bindings + Broccoli Ruby Bindings + BroControl - Interactive Bro management shell + Bro-Aux - Small auxiliary tools for Bro + BTest - A unit testing framework + Capstats - Command-line packet statistic tool + PySubnetTree - Python module for CIDR lookups + trace-summary - Script for generating break-downs of network traffic + +The `Broccoli API Reference `_ may also be of +interest. diff --git a/doc/components/pysubnettree/README.rst b/doc/components/pysubnettree/README.rst new file mode 100644 index 0000000000..be97eef9e3 --- /dev/null +++ b/doc/components/pysubnettree/README.rst @@ -0,0 +1,98 @@ +.. -*- mode: rst-mode -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 0.19-9 + +=============================================== +PySubnetTree - A Python Module for CIDR Lookups +=============================================== + +.. rst-class:: opening + + The PySubnetTree package provides a Python data structure + ``SubnetTree`` which maps subnets given in `CIDR + `_ notation (incl. + corresponding IPv6 versions) to Python objects. Lookups are + performed by longest-prefix matching. + + +Download +-------- + +You can find the latest PySubnetTree release for download at +http://www.bro.org/download. + +PySubnetTree's git repository is located at `git://git.bro.org/pysubnettree.git +`__. You can browse the repository +`here `__. + +This document describes PySubnetTree |version|. See the ``CHANGES`` +file for version history. + + +Example +------- + +A simple example which associates CIDR prefixes with strings:: + + >>> import SubnetTree + >>> t = SubnetTree.SubnetTree() + >>> t["10.1.0.0/16"] = "Network 1" + >>> t["10.1.42.0/24"] = "Network 1, Subnet 42" + >>> t["10.2.0.0/16"] = "Network 2" + >>> print t["10.1.42.1"] + Network 1, Subnet 42 + >>> print t["10.1.43.1"] + Network 1 + >>> print "10.1.42.1" in t + True + >>> print "10.1.43.1" in t + True + >>> print "10.20.1.1" in t + False + >>> print t["10.20.1.1"] + Traceback (most recent call last): + File "", line 1, in + File "SubnetTree.py", line 67, in __getitem__ + def __getitem__(*args): return _SubnetTree.SubnetTree___getitem__(*args) + KeyError: '10.20.1.1' + +By default, CIDR prefixes and IP addresses are given as strings. +Alternatively, a ``SubnetTree`` object can be switched into *binary +mode*, in which single addresses are passed in the form of packed +binary strings as, e.g., returned by `socket.inet_aton +`_:: + + + >>> t.get_binary_lookup_mode() + False + >>> t.set_binary_lookup_mode(True) + >>> t.binary_lookup_mode() + True + >>> import socket + >>> print t[socket.inet_aton("10.1.42.1")] + Network 1, Subnet 42 + +A SubnetTree also provides methods ``insert(prefix,object=None)`` for insertion +of prefixes (``object`` can be skipped to use the tree like a set), and +``remove(prefix)`` for removing entries (``remove`` performs an _exact_ match +rather than longest-prefix). + +Internally, the CIDR prefixes of a ``SubnetTree`` are managed by a +Patricia tree data structure and lookups are therefore efficient +even with a large number of prefixes. + +PySubnetTree comes with a BSD license. + + +Prerequisites +------------- + +This package requires Python 2.4 or newer. + +Installation +------------ + +Installation is pretty simple:: + + > python setup.py install diff --git a/doc/components/trace-summary/README.rst b/doc/components/trace-summary/README.rst new file mode 100644 index 0000000000..a47381fc37 --- /dev/null +++ b/doc/components/trace-summary/README.rst @@ -0,0 +1,154 @@ +.. -*- mode: rst-mode -*- +.. +.. Version number is filled in automatically. +.. |version| replace:: 0.8 + +==================================================== +trace-summary - Generating network traffic summaries +==================================================== + +.. rst-class:: opening + + ``trace-summary`` is a Python script that generates break-downs of + network traffic, including lists of the top hosts, protocols, + ports, etc. Optionally, it can generate output separately for + incoming vs. outgoing traffic, per subnet, and per time-interval. + +Download +-------- + +You can find the latest trace-summary release for download at +http://www.bro.org/download. + +trace-summary's git repository is located at `git://git.bro.org/trace-summary.git +`__. You can browse the repository +`here `__. + +This document describes trace-summary |version|. See the ``CHANGES`` +file for version history. + + +Overview +-------- + +The ``trace-summary`` script reads both packet traces in `libpcap +`_ format and connection logs produced by the +`Bro `_ network intrusion detection system +(for the latter, it supports both 1.x and 2.x output formats). + +Here are two example outputs in the most basic form (note that IP +addresses are 'anonymized'). The first is from a packet trace and the +second from a Bro connection log:: + + + >== Total === 2005-01-06-14-23-33 - 2005-01-06-15-23-43 + - Bytes 918.3m - Payload 846.3m - Pkts 1.8m - Frags 0.9% - MBit/s 1.9 - + Ports | Sources | Destinations | Protocols | + 80 33.8% | 131.243.89.214 8.5% | 131.243.89.214 7.7% | 6 76.0% | + 22 16.7% | 128.3.2.102 6.2% | 128.3.2.102 5.4% | 17 23.3% | + 11001 12.4% | 204.116.120.26 4.8% | 131.243.89.4 4.8% | 1 0.5% | + 2049 10.7% | 128.3.161.32 3.6% | 131.243.88.227 3.6% | | + 1023 10.6% | 131.243.89.4 3.5% | 204.116.120.26 3.4% | | + 993 8.2% | 128.3.164.194 2.7% | 131.243.89.64 3.1% | | + 1049 8.1% | 128.3.164.15 2.4% | 128.3.164.229 2.9% | | + 524 6.6% | 128.55.82.146 2.4% | 131.243.89.155 2.5% | | + 33305 4.5% | 131.243.88.227 2.3% | 128.3.161.32 2.3% | | + 1085 3.7% | 131.243.89.155 2.3% | 128.55.82.146 2.1% | | + + + >== Total === 2005-01-06-14-23-33 - 2005-01-06-15-23-42 + - Connections 43.4k - Payload 398.4m - + Ports | Sources | Destinations | Services | Protocols | States | + 80 21.7% | 207.240.215.71 3.0% | 239.255.255.253 8.0% | other 51.0% | 17 55.8% | S0 46.2% | + 427 13.0% | 131.243.91.71 2.2% | 131.243.91.255 4.0% | http 21.7% | 6 36.4% | SF 30.1% | + 443 3.8% | 128.3.161.76 1.7% | 131.243.89.138 2.1% | i-echo 7.3% | 1 7.7% | OTH 7.8% | + 138 3.7% | 131.243.90.138 1.6% | 255.255.255.255 1.7% | https 3.8% | | RSTO 5.8% | + 515 2.4% | 131.243.88.159 1.6% | 128.3.97.204 1.5% | nb-dgm 3.7% | | SHR 4.4% | + 11001 2.3% | 131.243.88.202 1.4% | 131.243.88.107 1.1% | printer 2.4% | | REJ 3.0% | + 53 1.9% | 131.243.89.250 1.4% | 117.72.94.10 1.1% | dns 1.9% | | S1 1.0% | + 161 1.6% | 131.243.89.80 1.3% | 131.243.88.64 1.1% | snmp 1.6% | | RSTR 0.9% | + 137 1.4% | 131.243.90.52 1.3% | 131.243.88.159 1.1% | nb-ns 1.4% | | SH 0.3% | + 2222 1.1% | 128.3.161.252 1.2% | 131.243.91.92 1.1% | ntp 1.0% | | RSTRH 0.2% | + + +Prerequisites +------------- + +* This script requires Python 2.4 or newer. + +* The `pysubnettree + `_ Python + module. + +* Eddie Kohler's `ipsumdump `_ + if using ``trace-summary`` with packet traces (versus Bro connection logs) + +Installation +------------ + +Simply copy the script into some directory which is in your ``PATH``. + +Usage +----- + +The general usage is:: + + trace-summary [options] [input-file] + +Per default, it assumes the ``input-file`` to be a ``libpcap`` trace +file. If it is a Bro connection log, use ``-c``. If ``input-file`` is +not given, the script reads from stdin. It writes its output to +stdout. + +Options +~~~~~~~ + +The most important options are summarized +below. Run ``trace-summary --help`` to see the full list including +some more esoteric ones. + +:-c: + Input is a Bro connection log instead of a ``libpcap`` trace + file. + +:-b: + Counts all percentages in bytes rather than number of + packets/connections. + +:-E : + Gives a file which contains a list of networks to ignore for the + analysis. The file must contain one network per line, where each + network is of the CIDR form ``a.b.c.d/mask`` (including the + corresponding syntax for IPv6 prefixes, e.g., ``1:2:3:4::/64``). + Empty lines and lines starting with a "#" are ignored. + +:-i : + Creates totals for each time interval of the given length + (default is seconds; add "``m``" for minutes and "``h``" for + hours). Use ``-v`` if you also want to see the breakdowns for + each interval. + +:-l : + Generates separate summaries for incoming and outgoing traffic. + ```` is a file which contains a list of networks to be + considered local. Format as for ``-E``. + +:-n : + Show top n entries in each break-down. Default is 10. + +:-r: + Resolves hostnames in the output. + +:-s : + Gives the sample factor if the input has been sampled. + +:-S : + Sample input with the given factor; less accurate but faster and + saves memory. + +:-m: + Does skip memory-expensive statistics. + +:-v: + Generates full break-downs for each time interval. Requires + ``-i``. diff --git a/doc/frameworks/index.rst b/doc/frameworks/index.rst new file mode 100644 index 0000000000..63e87a6732 --- /dev/null +++ b/doc/frameworks/index.rst @@ -0,0 +1,16 @@ + +========== +Frameworks +========== + +.. toctree:: + :maxdepth: 1 + + notice + logging + input + intel + cluster + signatures + geoip + diff --git a/doc/frameworks/input.rst b/doc/frameworks/input.rst new file mode 100644 index 0000000000..aca5091972 --- /dev/null +++ b/doc/frameworks/input.rst @@ -0,0 +1,408 @@ + +=============== +Input Framework +=============== + +.. rst-class:: opening + + Bro now features a flexible input framework that allows users + to import data into Bro. Data is either read into Bro tables or + converted to events which can then be handled by scripts. + This document gives an overview of how to use the input framework + with some examples. For more complex scenarios it is + worthwhile to take a look at the unit tests in + ``testing/btest/scripts/base/frameworks/input/``. + +.. contents:: + +Reading Data into Tables +======================== + +Probably the most interesting use-case of the input framework is to +read data into a Bro table. + +By default, the input framework reads the data in the same format +as it is written by the logging framework in Bro - a tab-separated +ASCII file. + +We will show the ways to read files into Bro with a simple example. +For this example we assume that we want to import data from a blacklist +that contains server IP addresses as well as the timestamp and the reason +for the block. + +An example input file could look like this: + +:: + + #fields ip timestamp reason + 192.168.17.1 1333252748 Malware host + 192.168.27.2 1330235733 Botnet server + 192.168.250.3 1333145108 Virus detected + +To read a file into a Bro table, two record types have to be defined. +One contains the types and names of the columns that should constitute the +table keys and the second contains the types and names of the columns that +should constitute the table values. + +In our case, we want to be able to lookup IPs. Hence, our key record +only contains the server IP. All other elements should be stored as +the table content. + +The two records are defined as: + +.. code:: bro + + type Idx: record { + ip: addr; + }; + + type Val: record { + timestamp: time; + reason: string; + }; + +Note that the names of the fields in the record definitions have to correspond +to the column names listed in the '#fields' line of the log file, in this +case 'ip', 'timestamp', and 'reason'. + +The log file is read into the table with a simple call of the ``add_table`` +function: + +.. code:: bro + + global blacklist: table[addr] of Val = table(); + + Input::add_table([$source="blacklist.file", $name="blacklist", $idx=Idx, $val=Val, $destination=blacklist]); + Input::remove("blacklist"); + +With these three lines we first create an empty table that should contain the +blacklist data and then instruct the input framework to open an input stream +named ``blacklist`` to read the data into the table. The third line removes the +input stream again, because we do not need it any more after the data has been +read. + +Because some data files can - potentially - be rather big, the input framework +works asynchronously. A new thread is created for each new input stream. +This thread opens the input data file, converts the data into a Bro format and +sends it back to the main Bro thread. + +Because of this, the data is not immediately accessible. Depending on the +size of the data source it might take from a few milliseconds up to a few +seconds until all data is present in the table. Please note that this means +that when Bro is running without an input source or on very short captured +files, it might terminate before the data is present in the system (because +Bro already handled all packets before the import thread finished). + +Subsequent calls to an input source are queued until the previous action has +been completed. Because of this, it is, for example, possible to call +``add_table`` and ``remove`` in two subsequent lines: the ``remove`` action +will remain queued until the first read has been completed. + +Once the input framework finishes reading from a data source, it fires +the ``end_of_data`` event. Once this event has been received all data +from the input file is available in the table. + +.. code:: bro + + event Input::end_of_data(name: string, source: string) { + # now all data is in the table + print blacklist; + } + +The table can also already be used while the data is still being read - it +just might not contain all lines in the input file when the event has not +yet fired. After it has been populated it can be used like any other Bro +table and blacklist entries can easily be tested: + +.. code:: bro + + if ( 192.168.18.12 in blacklist ) + # take action + + +Re-reading and streaming data +----------------------------- + +For many data sources, like for many blacklists, the source data is continually +changing. For these cases, the Bro input framework supports several ways to +deal with changing data files. + +The first, very basic method is an explicit refresh of an input stream. When +an input stream is open, the function ``force_update`` can be called. This +will trigger a complete refresh of the table; any changed elements from the +file will be updated. After the update is finished the ``end_of_data`` +event will be raised. + +In our example the call would look like: + +.. code:: bro + + Input::force_update("blacklist"); + +The input framework also supports two automatic refresh modes. The first mode +continually checks if a file has been changed. If the file has been changed, it +is re-read and the data in the Bro table is updated to reflect the current +state. Each time a change has been detected and all the new data has been +read into the table, the ``end_of_data`` event is raised. + +The second mode is a streaming mode. This mode assumes that the source data +file is an append-only file to which new data is continually appended. Bro +continually checks for new data at the end of the file and will add the new +data to the table. If newer lines in the file have the same index as previous +lines, they will overwrite the values in the output table. Because of the +nature of streaming reads (data is continually added to the table), +the ``end_of_data`` event is never raised when using streaming reads. + +The reading mode can be selected by setting the ``mode`` option of the +add_table call. Valid values are ``MANUAL`` (the default), ``REREAD`` +and ``STREAM``. + +Hence, when adding ``$mode=Input::REREAD`` to the previous example, the +blacklist table will always reflect the state of the blacklist input file. + +.. code:: bro + + Input::add_table([$source="blacklist.file", $name="blacklist", $idx=Idx, $val=Val, $destination=blacklist, $mode=Input::REREAD]); + +Receiving change events +----------------------- + +When re-reading files, it might be interesting to know exactly which lines in +the source files have changed. + +For this reason, the input framework can raise an event each time when a data +item is added to, removed from or changed in a table. + +The event definition looks like this: + +.. code:: bro + + event entry(description: Input::TableDescription, tpe: Input::Event, left: Idx, right: Val) { + # act on values + } + +The event has to be specified in ``$ev`` in the ``add_table`` call: + +.. code:: bro + + Input::add_table([$source="blacklist.file", $name="blacklist", $idx=Idx, $val=Val, $destination=blacklist, $mode=Input::REREAD, $ev=entry]); + +The ``description`` field of the event contains the arguments that were +originally supplied to the add_table call. Hence, the name of the stream can, +for example, be accessed with ``description$name``. ``tpe`` is an enum +containing the type of the change that occurred. + +If a line that was not previously present in the table has been added, +then ``tpe`` will contain ``Input::EVENT_NEW``. In this case ``left`` contains +the index of the added table entry and ``right`` contains the values of the +added entry. + +If a table entry that already was present is altered during the re-reading or +streaming read of a file, ``tpe`` will contain ``Input::EVENT_CHANGED``. In +this case ``left`` contains the index of the changed table entry and ``right`` +contains the values of the entry before the change. The reason for this is +that the table already has been updated when the event is raised. The current +value in the table can be ascertained by looking up the current table value. +Hence it is possible to compare the new and the old values of the table. + +If a table element is removed because it was no longer present during a +re-read, then ``tpe`` will contain ``Input::REMOVED``. In this case ``left`` +contains the index and ``right`` the values of the removed element. + + +Filtering data during import +---------------------------- + +The input framework also allows a user to filter the data during the import. +To this end, predicate functions are used. A predicate function is called +before a new element is added/changed/removed from a table. The predicate +can either accept or veto the change by returning true for an accepted +change and false for a rejected change. Furthermore, it can alter the data +before it is written to the table. + +The following example filter will reject to add entries to the table when +they were generated over a month ago. It will accept all changes and all +removals of values that are already present in the table. + +.. code:: bro + + Input::add_table([$source="blacklist.file", $name="blacklist", $idx=Idx, $val=Val, $destination=blacklist, $mode=Input::REREAD, + $pred(typ: Input::Event, left: Idx, right: Val) = { + if ( typ != Input::EVENT_NEW ) { + return T; + } + return ( ( current_time() - right$timestamp ) < (30 day) ); + }]); + +To change elements while they are being imported, the predicate function can +manipulate ``left`` and ``right``. Note that predicate functions are called +before the change is committed to the table. Hence, when a table element is +changed (``tpe`` is ``INPUT::EVENT_CHANGED``), ``left`` and ``right`` +contain the new values, but the destination (``blacklist`` in our example) +still contains the old values. This allows predicate functions to examine +the changes between the old and the new version before deciding if they +should be allowed. + +Different readers +----------------- + +The input framework supports different kinds of readers for different kinds +of source data files. At the moment, the default reader reads ASCII files +formatted in the Bro log file format (tab-separated values). At the moment, +Bro comes with two other readers. The ``RAW`` reader reads a file that is +split by a specified record separator (usually newline). The contents are +returned line-by-line as strings; it can, for example, be used to read +configuration files and the like and is probably +only useful in the event mode and not for reading data to tables. + +Another included reader is the ``BENCHMARK`` reader, which is being used +to optimize the speed of the input framework. It can generate arbitrary +amounts of semi-random data in all Bro data types supported by the input +framework. + +In the future, the input framework will get support for new data sources +like, for example, different databases. + +Add_table options +----------------- + +This section lists all possible options that can be used for the add_table +function and gives a short explanation of their use. Most of the options +already have been discussed in the previous sections. + +The possible fields that can be set for a table stream are: + + ``source`` + A mandatory string identifying the source of the data. + For the ASCII reader this is the filename. + + ``name`` + A mandatory name for the filter that can later be used + to manipulate it further. + + ``idx`` + Record type that defines the index of the table. + + ``val`` + Record type that defines the values of the table. + + ``reader`` + The reader used for this stream. Default is ``READER_ASCII``. + + ``mode`` + The mode in which the stream is opened. Possible values are + ``MANUAL``, ``REREAD`` and ``STREAM``. Default is ``MANUAL``. + ``MANUAL`` means that the file is not updated after it has + been read. Changes to the file will not be reflected in the + data Bro knows. ``REREAD`` means that the whole file is read + again each time a change is found. This should be used for + files that are mapped to a table where individual lines can + change. ``STREAM`` means that the data from the file is + streamed. Events / table entries will be generated as new + data is appended to the file. + + ``destination`` + The destination table. + + ``ev`` + Optional event that is raised, when values are added to, + changed in, or deleted from the table. Events are passed an + Input::Event description as the first argument, the index + record as the second argument and the values as the third + argument. + + ``pred`` + Optional predicate, that can prevent entries from being added + to the table and events from being sent. + + ``want_record`` + Boolean value, that defines if the event wants to receive the + fields inside of a single record value, or individually + (default). This can be used if ``val`` is a record + containing only one type. In this case, if ``want_record`` is + set to false, the table will contain elements of the type + contained in ``val``. + +Reading Data to Events +====================== + +The second supported mode of the input framework is reading data to Bro +events instead of reading them to a table using event streams. + +Event streams work very similarly to table streams that were already +discussed in much detail. To read the blacklist of the previous example +into an event stream, the following Bro code could be used: + +.. code:: bro + + type Val: record { + ip: addr; + timestamp: time; + reason: string; + }; + + event blacklistentry(description: Input::EventDescription, tpe: Input::Event, ip: addr, timestamp: time, reason: string) { + # work with event data + } + + event bro_init() { + Input::add_event([$source="blacklist.file", $name="blacklist", $fields=Val, $ev=blacklistentry]); + } + + +The main difference in the declaration of the event stream is, that an event +stream needs no separate index and value declarations -- instead, all source +data types are provided in a single record definition. + +Apart from this, event streams work exactly the same as table streams and +support most of the options that are also supported for table streams. + +The options that can be set when creating an event stream with +``add_event`` are: + + ``source`` + A mandatory string identifying the source of the data. + For the ASCII reader this is the filename. + + ``name`` + A mandatory name for the stream that can later be used + to remove it. + + ``fields`` + Name of a record type containing the fields, which should be + retrieved from the input stream. + + ``ev`` + The event which is fired, after a line has been read from the + input source. The first argument that is passed to the event + is an Input::Event structure, followed by the data, either + inside of a record (if ``want_record is set``) or as + individual fields. The Input::Event structure can contain + information, if the received line is ``NEW``, has been + ``CHANGED`` or ``DELETED``. Since the ASCII reader cannot + track this information for event filters, the value is + always ``NEW`` at the moment. + + ``mode`` + The mode in which the stream is opened. Possible values are + ``MANUAL``, ``REREAD`` and ``STREAM``. Default is ``MANUAL``. + ``MANUAL`` means that the file is not updated after it has + been read. Changes to the file will not be reflected in the + data Bro knows. ``REREAD`` means that the whole file is read + again each time a change is found. This should be used for + files that are mapped to a table where individual lines can + change. ``STREAM`` means that the data from the file is + streamed. Events / table entries will be generated as new + data is appended to the file. + + ``reader`` + The reader used for this stream. Default is ``READER_ASCII``. + + ``want_record`` + Boolean value, that defines if the event wants to receive the + fields inside of a single record value, or individually + (default). If this is set to true, the event will receive a + single record of the type provided in ``fields``. + + + diff --git a/doc/intel.rst b/doc/frameworks/intel.rst similarity index 98% rename from doc/intel.rst rename to doc/frameworks/intel.rst index 390313461a..a8107905a9 100644 --- a/doc/intel.rst +++ b/doc/frameworks/intel.rst @@ -1,5 +1,7 @@ -Intel Framework -=============== + +====================== +Intelligence Framework +====================== Intro ----- diff --git a/doc/frameworks/logging-dataseries.rst b/doc/frameworks/logging-dataseries.rst new file mode 100644 index 0000000000..139a13f813 --- /dev/null +++ b/doc/frameworks/logging-dataseries.rst @@ -0,0 +1,186 @@ + +============================= +Binary Output with DataSeries +============================= + +.. rst-class:: opening + + Bro's default ASCII log format is not exactly the most efficient + way for storing and searching large volumes of data. An an + alternative, Bro comes with experimental support for `DataSeries + `_ + output, an efficient binary format for recording structured bulk + data. DataSeries is developed and maintained at HP Labs. + +.. contents:: + +Installing DataSeries +--------------------- + +To use DataSeries, its libraries must be available at compile-time, +along with the supporting *Lintel* package. Generally, both are +distributed on `HP Labs' web site +`_. Currently, however, you need +to use recent development versions for both packages, which you can +download from github like this:: + + git clone http://github.com/dataseries/Lintel + git clone http://github.com/dataseries/DataSeries + +To build and install the two into ````, do:: + + ( cd Lintel && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX= .. && make && make install ) + ( cd DataSeries && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX= .. && make && make install ) + +Please refer to the packages' documentation for more information about +the installation process. In particular, there's more information on +required and optional `dependencies for Lintel +`_ +and `dependencies for DataSeries +`_. +For users on RedHat-style systems, you'll need the following:: + + yum install libxml2-devel boost-devel + +Compiling Bro with DataSeries Support +------------------------------------- + +Once you have installed DataSeries, Bro's ``configure`` should pick it +up automatically as long as it finds it in a standard system location. +Alternatively, you can specify the DataSeries installation prefix +manually with ``--with-dataseries=``. Keep an eye on +``configure``'s summary output, if it looks like the following, Bro +found DataSeries and will compile in the support:: + + # ./configure --with-dataseries=/usr/local + [...] + ====================| Bro Build Summary |===================== + [...] + DataSeries: true + [...] + ================================================================ + +Activating DataSeries +--------------------- + +The direct way to use DataSeries is to switch *all* log files over to +the binary format. To do that, just add ``redef +Log::default_writer=Log::WRITER_DATASERIES;`` to your ``local.bro``. +For testing, you can also just pass that on the command line:: + + bro -r trace.pcap Log::default_writer=Log::WRITER_DATASERIES + +With that, Bro will now write all its output into DataSeries files +``*.ds``. You can inspect these using DataSeries's set of command line +tools, which its installation process installs into ``/bin``. +For example, to convert a file back into an ASCII representation:: + + $ ds2txt conn.log + [... We skip a bunch of metadata here ...] + ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes + 1300475167.096535 CRCC5OdDlXe 141.142.220.202 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 73 0 0 + 1300475167.097012 o7XBsfvo3U1 fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0.000000 0 0 S0 F 0 D 1 199 0 0 + 1300475167.099816 pXPi1kPMgxb 141.142.220.50 5353 224.0.0.251 5353 udp 0.000000 0 0 S0 F 0 D 1 179 0 0 + 1300475168.853899 R7sOc16woCj 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF F 0 Dd 1 66 1 117 + 1300475168.854378 Z6dfHVmt0X7 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF F 0 Dd 1 80 1 127 + 1300475168.854837 k6T92WxgNAh 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF F 0 Dd 1 66 1 211 + [...] + +(``--skip-all`` suppresses the metadata.) + +Note that the ASCII conversion is *not* equivalent to Bro's default +output format. + +You can also switch only individual files over to DataSeries by adding +code like this to your ``local.bro``: + +.. code:: bro + + event bro_init() + { + local f = Log::get_filter(Conn::LOG, "default"); # Get default filter for connection log. + f$writer = Log::WRITER_DATASERIES; # Change writer type. + Log::add_filter(Conn::LOG, f); # Replace filter with adapted version. + } + +Bro's DataSeries writer comes with a few tuning options, see +:doc:`scripts/base/frameworks/logging/writers/dataseries`. + +Working with DataSeries +======================= + +Here are a few examples of using DataSeries command line tools to work +with the output files. + +* Printing CSV:: + + $ ds2txt --csv conn.log + ts,uid,id.orig_h,id.orig_p,id.resp_h,id.resp_p,proto,service,duration,orig_bytes,resp_bytes,conn_state,local_orig,missed_bytes,history,orig_pkts,orig_ip_bytes,resp_pkts,resp_ip_bytes + 1258790493.773208,ZTtgbHvf4s3,192.168.1.104,137,192.168.1.255,137,udp,dns,3.748891,350,0,S0,F,0,D,7,546,0,0 + 1258790451.402091,pOY6Rw7lhUd,192.168.1.106,138,192.168.1.255,138,udp,,0.000000,0,0,S0,F,0,D,1,229,0,0 + 1258790493.787448,pn5IiEslca9,192.168.1.104,138,192.168.1.255,138,udp,,2.243339,348,0,S0,F,0,D,2,404,0,0 + 1258790615.268111,D9slyIu3hFj,192.168.1.106,137,192.168.1.255,137,udp,dns,3.764626,350,0,S0,F,0,D,7,546,0,0 + [...] + + Add ``--separator=X`` to set a different separator. + +* Extracting a subset of columns:: + + $ ds2txt --select '*' ts,id.resp_h,id.resp_p --skip-all conn.log + 1258790493.773208 192.168.1.255 137 + 1258790451.402091 192.168.1.255 138 + 1258790493.787448 192.168.1.255 138 + 1258790615.268111 192.168.1.255 137 + 1258790615.289842 192.168.1.255 138 + [...] + +* Filtering rows:: + + $ ds2txt --where '*' 'duration > 5 && id.resp_p > 1024' --skip-all conn.ds + 1258790631.532888 V8mV5WLITu5 192.168.1.105 55890 239.255.255.250 1900 udp 15.004568 798 0 S0 F 0 D 6 966 0 0 + 1258792413.439596 tMcWVWQptvd 192.168.1.105 55890 239.255.255.250 1900 udp 15.004581 798 0 S0 F 0 D 6 966 0 0 + 1258794195.346127 cQwQMRdBrKa 192.168.1.105 55890 239.255.255.250 1900 udp 15.005071 798 0 S0 F 0 D 6 966 0 0 + 1258795977.253200 i8TEjhWd2W8 192.168.1.105 55890 239.255.255.250 1900 udp 15.004824 798 0 S0 F 0 D 6 966 0 0 + 1258797759.160217 MsLsBA8Ia49 192.168.1.105 55890 239.255.255.250 1900 udp 15.005078 798 0 S0 F 0 D 6 966 0 0 + 1258799541.068452 TsOxRWJRGwf 192.168.1.105 55890 239.255.255.250 1900 udp 15.004082 798 0 S0 F 0 D 6 966 0 0 + [...] + +* Calculate some statistics: + + Mean/stddev/min/max over a column:: + + $ dsstatgroupby '*' basic duration from conn.ds + # Begin DSStatGroupByModule + # processed 2159 rows, where clause eliminated 0 rows + # count(*), mean(duration), stddev, min, max + 2159, 42.7938, 1858.34, 0, 86370 + [...] + + Quantiles of total connection volume:: + + $ dsstatgroupby '*' quantile 'orig_bytes + resp_bytes' from conn.ds + [...] + 2159 data points, mean 24616 +- 343295 [0,1.26615e+07] + quantiles about every 216 data points: + 10%: 0, 124, 317, 348, 350, 350, 601, 798, 1469 + tails: 90%: 1469, 95%: 7302, 99%: 242629, 99.5%: 1226262 + [...] + +The ``man`` pages for these tools show further options, and their +``-h`` option gives some more information (either can be a bit cryptic +unfortunately though). + +Deficiencies +------------ + +Due to limitations of the DataSeries format, one cannot inspect its +files before they have been fully written. In other words, when using +DataSeries, it's currently not possible to inspect the live log +files inside the spool directory before they are rotated to their +final location. It seems that this could be fixed with some effort, +and we will work with DataSeries development team on that if the +format gains traction among Bro users. + +Likewise, we're considering writing custom command line tools for +interacting with DataSeries files, making that a bit more convenient +than what the standard utilities provide. diff --git a/doc/frameworks/logging-elasticsearch.rst b/doc/frameworks/logging-elasticsearch.rst new file mode 100644 index 0000000000..7571c68219 --- /dev/null +++ b/doc/frameworks/logging-elasticsearch.rst @@ -0,0 +1,89 @@ + +========================================= +Indexed Logging Output with ElasticSearch +========================================= + +.. rst-class:: opening + + Bro's default ASCII log format is not exactly the most efficient + way for searching large volumes of data. ElasticSearch + is a new data storage technology for dealing with tons of data. + It's also a search engine built on top of Apache's Lucene + project. It scales very well, both for distributed indexing and + distributed searching. + +.. contents:: + +Warning +------- + +This writer plugin is still in testing and is not yet recommended for +production use! The approach to how logs are handled in the plugin is "fire +and forget" at this time, there is no error handling if the server fails to +respond successfully to the insertion request. + +Installing ElasticSearch +------------------------ + +Download the latest version from: . +Once extracted, start ElasticSearch with:: + +# ./bin/elasticsearch + +For more detailed information, refer to the ElasticSearch installation +documentation: http://www.elasticsearch.org/guide/reference/setup/installation.html + +Compiling Bro with ElasticSearch Support +---------------------------------------- + +First, ensure that you have libcurl installed the run configure.:: + + # ./configure + [...] + ====================| Bro Build Summary |===================== + [...] + cURL: true + [...] + ElasticSearch: true + [...] + ================================================================ + +Activating ElasticSearch +------------------------ + +The easiest way to enable ElasticSearch output is to load the tuning/logs-to- +elasticsearch.bro script. If you are using BroControl, the following line in +local.bro will enable it. + +.. console:: + + @load tuning/logs-to-elasticsearch + +With that, Bro will now write most of its logs into ElasticSearch in addition +to maintaining the Ascii logs like it would do by default. That script has +some tunable options for choosing which logs to send to ElasticSearch, refer +to the autogenerated script documentation for those options. + +There is an interface being written specifically to integrate with the data +that Bro outputs into ElasticSearch named Brownian. It can be found here:: + + https://github.com/grigorescu/Brownian + +Tuning +------ + +A common problem encountered with ElasticSearch is too many files being held +open. The ElasticSearch website has some suggestions on how to increase the +open file limit. + + - http://www.elasticsearch.org/tutorials/2011/04/06/too-many-open-files.html + +TODO +---- + +Lots. + +- Perform multicast discovery for server. +- Better error detection. +- Better defaults (don't index loaded-plugins, for instance). +- diff --git a/doc/frameworks/logging.rst b/doc/frameworks/logging.rst new file mode 100644 index 0000000000..06935647d3 --- /dev/null +++ b/doc/frameworks/logging.rst @@ -0,0 +1,387 @@ + +================= +Logging Framework +================= + +.. rst-class:: opening + + Bro comes with a flexible key-value based logging interface that + allows fine-grained control of what gets logged and how it is + logged. This document describes how logging can be customized and + extended. + +.. contents:: + +Terminology +=========== + +Bro's logging interface is built around three main abstractions: + + Log streams + A stream corresponds to a single log. It defines the set of + fields that a log consists of with their names and fields. + Examples are the ``conn`` for recording connection summaries, + and the ``http`` stream for recording HTTP activity. + + Filters + Each stream has a set of filters attached to it that determine + what information gets written out. By default, each stream has + one default filter that just logs everything directly to disk + with an automatically generated file name. However, further + filters can be added to record only a subset, split a stream + into different outputs, or to even duplicate the log to + multiple outputs. If all filters are removed from a stream, + all output is disabled. + + Writers + A writer defines the actual output format for the information + being logged. At the moment, Bro comes with only one type of + writer, which produces tab separated ASCII files. In the + future we will add further writers, like for binary output and + direct logging into a database. + +Basics +====== + +The data fields that a stream records are defined by a record type +specified when it is created. Let's look at the script generating Bro's +connection summaries as an example, +:doc:`scripts/base/protocols/conn/main`. It defines a record +:bro:type:`Conn::Info` that lists all the fields that go into +``conn.log``, each marked with a ``&log`` attribute indicating that it +is part of the information written out. To write a log record, the +script then passes an instance of :bro:type:`Conn::Info` to the logging +framework's :bro:id:`Log::write` function. + +By default, each stream automatically gets a filter named ``default`` +that generates the normal output by recording all record fields into a +single output file. + +In the following, we summarize ways in which the logging can be +customized. We continue using the connection summaries as our example +to work with. + +Filtering +--------- + +To create a new output file for an existing stream, you can add a +new filter. A filter can, e.g., restrict the set of fields being +logged: + +.. code:: bro + + event bro_init() + { + # Add a new filter to the Conn::LOG stream that logs only + # timestamp and originator address. + local filter: Log::Filter = [$name="orig-only", $path="origs", $include=set("ts", "id.orig_h")]; + Log::add_filter(Conn::LOG, filter); + } + +Note the fields that are set for the filter: + + ``name`` + A mandatory name for the filter that can later be used + to manipulate it further. + + ``path`` + The filename for the output file, without any extension (which + may be automatically added by the writer). Default path values + are generated by taking the stream's ID and munging it slightly. + :bro:enum:`Conn::LOG` is converted into ``conn``, + :bro:enum:`PacketFilter::LOG` is converted into + ``packet_filter``, and :bro:enum:`Notice::POLICY_LOG` is + converted into ``notice_policy``. + + ``include`` + A set limiting the fields to the ones given. The names + correspond to those in the :bro:type:`Conn::Info` record, with + sub-records unrolled by concatenating fields (separated with + dots). + +Using the code above, you will now get a new log file ``origs.log`` +that looks like this:: + + #separator \x09 + #path origs + #fields ts id.orig_h + #types time addr + 1128727430.350788 141.42.64.125 + 1128727435.450898 141.42.64.125 + +If you want to make this the only log file for the stream, you can +remove the default filter (which, conveniently, has the name +``default``): + +.. code:: bro + + event bro_init() + { + # Remove the filter called "default". + Log::remove_filter(Conn::LOG, "default"); + } + +An alternate approach to "turning off" a log is to completely disable +the stream: + +.. code:: bro + + event bro_init() + { + Log::disable_stream(Conn::LOG); + } + +If you want to skip only some fields but keep the rest, there is a +corresponding ``exclude`` filter attribute that you can use instead of +``include`` to list only the ones you are not interested in. + +A filter can also determine output paths *dynamically* based on the +record being logged. That allows, e.g., to record local and remote +connections into separate files. To do this, you define a function +that returns the desired path: + +.. code:: bro + + function split_log(id: Log::ID, path: string, rec: Conn::Info) : string + { + # Return "conn-local" if originator is a local IP, otherwise "conn-remote". + local lr = Site::is_local_addr(rec$id$orig_h) ? "local" : "remote"; + return fmt("%s-%s", path, lr); + } + + event bro_init() + { + local filter: Log::Filter = [$name="conn-split", $path_func=split_log, $include=set("ts", "id.orig_h")]; + Log::add_filter(Conn::LOG, filter); + } + +Running this will now produce two files, ``local.log`` and +``remote.log``, with the corresponding entries. One could extend this +further for example to log information by subnets or even by IP +address. Be careful, however, as it is easy to create many files very +quickly ... + +.. sidebar:: A More Generic Path Function + + The ``split_log`` method has one draw-back: it can be used + only with the :bro:enum:`Conn::LOG` stream as the record type is hardcoded + into its argument list. However, Bro allows to do a more generic + variant: + + .. code:: bro + + function split_log(id: Log::ID, path: string, rec: record { id: conn_id; } ) : string + { + return Site::is_local_addr(rec$id$orig_h) ? "local" : "remote"; + } + + This function can be used with all log streams that have records + containing an ``id: conn_id`` field. + +While so far we have seen how to customize the columns being logged, +you can also control which records are written out by providing a +predicate that will be called for each log record: + +.. code:: bro + + function http_only(rec: Conn::Info) : bool + { + # Record only connections with successfully analyzed HTTP traffic + return rec$service == "http"; + } + + event bro_init() + { + local filter: Log::Filter = [$name="http-only", $path="conn-http", $pred=http_only]; + Log::add_filter(Conn::LOG, filter); + } + +This will result in a log file ``conn-http.log`` that contains only +traffic detected and analyzed as HTTP traffic. + +Extending +--------- + +You can add further fields to a log stream by extending the record +type that defines its content. Let's say we want to add a boolean +field ``is_private`` to :bro:type:`Conn::Info` that indicates whether the +originator IP address is part of the :rfc:`1918` space: + +.. code:: bro + + # Add a field to the connection log record. + redef record Conn::Info += { + ## Indicate if the originator of the connection is part of the + ## "private" address space defined in RFC1918. + is_private: bool &default=F &log; + }; + + +Now we need to set the field. A connection's summary is generated at +the time its state is removed from memory. We can add another handler +at that time that sets our field correctly: + +.. code:: bro + + event connection_state_remove(c: connection) + { + if ( c$id$orig_h in Site::private_address_space ) + c$conn$is_private = T; + } + +Now ``conn.log`` will show a new field ``is_private`` of type +``bool``. + +Notes: + +- For extending logs this way, one needs a bit of knowledge about how + the script that creates the log stream is organizing its state + keeping. Most of the standard Bro scripts attach their log state to + the :bro:type:`connection` record where it can then be accessed, just + as the ``c$conn`` above. For example, the HTTP analysis adds a field + ``http`` of type :bro:type:`HTTP::Info` to the :bro:type:`connection` + record. See the script reference for more information. + +- When extending records as shown above, the new fields must always be + declared either with a ``&default`` value or as ``&optional``. + Furthermore, you need to add the ``&log`` attribute or otherwise the + field won't appear in the output. + +Hooking into the Logging +------------------------ + +Sometimes it is helpful to do additional analysis of the information +being logged. For these cases, a stream can specify an event that will +be generated every time a log record is written to it. All of Bro's +default log streams define such an event. For example, the connection +log stream raises the event :bro:id:`Conn::log_conn`. You +could use that for example for flagging when a connection to a +specific destination exceeds a certain duration: + +.. code:: bro + + redef enum Notice::Type += { + ## Indicates that a connection remained established longer + ## than 5 minutes. + Long_Conn_Found + }; + + event Conn::log_conn(rec: Conn::Info) + { + if ( rec$duration > 5mins ) + NOTICE([$note=Long_Conn_Found, + $msg=fmt("unusually long conn to %s", rec$id$resp_h), + $id=rec$id]); + } + +Often, these events can be an alternative to post-processing Bro logs +externally with Perl scripts. Much of what such an external script +would do later offline, one may instead do directly inside of Bro in +real-time. + +Rotation +-------- + +By default, no log rotation occurs, but it's globally controllable for all +filters by redefining the :bro:id:`Log::default_rotation_interval` option: + +.. code:: bro + + redef Log::default_rotation_interval = 1 hr; + +Or specifically for certain :bro:type:`Log::Filter` instances by setting +their ``interv`` field. Here's an example of changing just the +:bro:enum:`Conn::LOG` stream's default filter rotation. + +.. code:: bro + + event bro_init() + { + local f = Log::get_filter(Conn::LOG, "default"); + f$interv = 1 min; + Log::remove_filter(Conn::LOG, "default"); + Log::add_filter(Conn::LOG, f); + } + +ASCII Writer Configuration +-------------------------- + +The ASCII writer has a number of options for customizing the format of +its output, see :doc:`scripts/base/frameworks/logging/writers/ascii`. + +Adding Streams +============== + +It's easy to create a new log stream for custom scripts. Here's an +example for the ``Foo`` module: + +.. code:: bro + + module Foo; + + export { + # Create an ID for our new stream. By convention, this is + # called "LOG". + redef enum Log::ID += { LOG }; + + # Define the fields. By convention, the type is called "Info". + type Info: record { + ts: time &log; + id: conn_id &log; + }; + + # Define a hook event. By convention, this is called + # "log_". + global log_foo: event(rec: Info); + + } + + # This event should be handled at a higher priority so that when + # users modify your stream later and they do it at priority 0, + # their code runs after this. + event bro_init() &priority=5 + { + # Create the stream. This also adds a default filter automatically. + Log::create_stream(Foo::LOG, [$columns=Info, $ev=log_foo]); + } + +You can also add the state to the :bro:type:`connection` record to make +it easily accessible across event handlers: + +.. code:: bro + + redef record connection += { + foo: Info &optional; + } + +Now you can use the :bro:id:`Log::write` method to output log records and +save the logged ``Foo::Info`` record into the connection record: + +.. code:: bro + + event connection_established(c: connection) + { + local rec: Foo::Info = [$ts=network_time(), $id=c$id]; + c$foo = rec; + Log::write(Foo::LOG, rec); + } + +See the existing scripts for how to work with such a new connection +field. A simple example is :doc:`scripts/base/protocols/syslog/main`. + +When you are developing scripts that add data to the :bro:type:`connection` +record, care must be given to when and how long data is stored. +Normally data saved to the connection record will remain there for the +duration of the connection and from a practical perspective it's not +uncommon to need to delete that data before the end of the connection. + +Other Writers +------------- + +Bro supports the following output formats other than ASCII: + +.. toctree:: + :maxdepth: 1 + + logging-dataseries + logging-elasticsearch diff --git a/doc/frameworks/notice.rst b/doc/frameworks/notice.rst new file mode 100644 index 0000000000..dd0be42f02 --- /dev/null +++ b/doc/frameworks/notice.rst @@ -0,0 +1,357 @@ + +================ +Notice Framework +================ + +.. rst-class:: opening + + One of the easiest ways to customize Bro is writing a local notice + policy. Bro can detect a large number of potentially interesting + situations, and the notice policy hook which of them the user wants to be + acted upon in some manner. In particular, the notice policy can specify + actions to be taken, such as sending an email or compiling regular + alarm emails. This page gives an introduction into writing such a notice + policy. + +.. contents:: + +Overview +-------- + +Let's start with a little bit of background on Bro's philosophy on reporting +things. Bro ships with a large number of policy scripts which perform a wide +variety of analyses. Most of these scripts monitor for activity which might be +of interest for the user. However, none of these scripts determines the +importance of what it finds itself. Instead, the scripts only flag situations +as *potentially* interesting, leaving it to the local configuration to define +which of them are in fact actionable. This decoupling of detection and +reporting allows Bro to address the different needs that sites have. +Definitions of what constitutes an attack or even a compromise differ quite a +bit between environments, and activity deemed malicious at one site might be +fully acceptable at another. + +Whenever one of Bro's analysis scripts sees something potentially +interesting it flags the situation by calling the :bro:see:`NOTICE` +function and giving it a single :bro:see:`Notice::Info` record. A Notice +has a :bro:see:`Notice::Type`, which reflects the kind of activity that +has been seen, and it is usually also augmented with further context +about the situation. + +More information about raising notices can be found in the `Raising Notices`_ +section. + +Once a notice is raised, it can have any number of actions applied to it by +writing :bro:see:`Notice::policy` hooks which is described in the `Notice Policy`_ +section below. Such actions can be to send a mail to the configured +address(es) or to simply ignore the notice. Currently, the following actions +are defined: + +.. list-table:: + :widths: 20 80 + :header-rows: 1 + + * - Action + - Description + + * - Notice::ACTION_LOG + - Write the notice to the :bro:see:`Notice::LOG` logging stream. + + * - Notice::ACTION_ALARM + - Log into the :bro:see:`Notice::ALARM_LOG` stream which will rotate + hourly and email the contents to the email address or addresses + defined in the :bro:see:`Notice::mail_dest` variable. + + * - Notice::ACTION_EMAIL + - Send the notice in an email to the email address or addresses given in + the :bro:see:`Notice::mail_dest` variable. + + * - Notice::ACTION_PAGE + - Send an email to the email address or addresses given in the + :bro:see:`Notice::mail_page_dest` variable. + +How these notice actions are applied to notices is discussed in the +`Notice Policy`_ and `Notice Policy Shortcuts`_ sections. + +Processing Notices +------------------ + +Notice Policy +************* + +The hook :bro:see:`Notice::policy` provides the mechanism for applying +actions and generally modifying the notice before it's sent onward to +the action plugins. Hooks can be thought of as multi-bodied functions +and using them looks very similar to handling events. The difference +is that they don't go through the event queue like events. Users should +directly make modifications to the :bro:see:`Notice::Info` record +given as the argument to the hook. + +Here's a simple example which tells Bro to send an email for all notices of +type :bro:see:`SSH::Login` if the server is 10.0.0.1: + +.. code:: bro + + hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSH::Login && n$id$resp_h == 10.0.0.1 ) + add n$actions[Notice::ACTION_EMAIL]; + } + +.. note:: + + Keep in mind that the semantics of the SSH::Login notice are + such that it is only raised when Bro heuristically detects a successful + login. No apparently failed logins will raise this notice. + +Hooks can also have priorities applied to order their execution like events +with a default priority of 0. Greater values are executed first. Setting +a hook body to run before default hook bodies might look like this: + +.. code:: bro + + hook Notice::policy(n: Notice::Info) &priority=5 + { + if ( n$note == SSH::Login && n$id$resp_h == 10.0.0.1 ) + add n$actions[Notice::ACTION_EMAIL]; + } + +Hooks can also abort later hook bodies with the ``break`` keyword. This +is primarily useful if one wants to completely preempt processing by +lower priority :bro:see:`Notice::policy` hooks. + +Notice Policy Shortcuts +*********************** + +Although the notice framework provides a great deal of flexibility and +configurability there are many times that the full expressiveness isn't needed +and actually becomes a hindrance to achieving results. The framework provides +a default :bro:see:`Notice::policy` hook body as a way of giving users the +shortcuts to easily apply many common actions to notices. + +These are implemented as sets and tables indexed with a +:bro:see:`Notice::Type` enum value. The following table shows and describes +all of the variables available for shortcut configuration of the notice +framework. + +.. list-table:: + :widths: 32 40 + :header-rows: 1 + + * - Variable name + - Description + + * - :bro:see:`Notice::ignored_types` + - Adding a :bro:see:`Notice::Type` to this set results in the notice + being ignored. It won't have any other action applied to it, not even + :bro:see:`Notice::ACTION_LOG`. + + * - :bro:see:`Notice::emailed_types` + - Adding a :bro:see:`Notice::Type` to this set results in + :bro:see:`Notice::ACTION_EMAIL` being applied to the notices of + that type. + + * - :bro:see:`Notice::alarmed_types` + - Adding a :bro:see:`Notice::Type` to this set results in + :bro:see:`Notice::ACTION_ALARM` being applied to the notices of + that type. + + * - :bro:see:`Notice::not_suppressed_types` + - Adding a :bro:see:`Notice::Type` to this set results in that notice + no longer undergoing the normal notice suppression that would + take place. Be careful when using this in production it could + result in a dramatic increase in the number of notices being + processed. + + * - :bro:see:`Notice::type_suppression_intervals` + - This is a table indexed on :bro:see:`Notice::Type` and yielding an + interval. It can be used as an easy way to extend the default + suppression interval for an entire :bro:see:`Notice::Type` + without having to create a whole :bro:see:`Notice::policy` entry + and setting the ``$suppress_for`` field. + +Raising Notices +--------------- + +A script should raise a notice for any occurrence that a user may want +to be notified about or take action on. For example, whenever the base +SSH analysis scripts sees an SSH session where it is heuristically +guessed to be a successful login, it raises a Notice of the type +:bro:see:`SSH::Login`. The code in the base SSH analysis script looks +like this: + +.. code:: bro + + NOTICE([$note=SSH::Login, + $msg="Heuristically detected successful SSH login.", + $conn=c]); + +:bro:see:`NOTICE` is a normal function in the global namespace which +wraps a function within the ``Notice`` namespace. It takes a single +argument of the :bro:see:`Notice::Info` record type. The most common +fields used when raising notices are described in the following table: + +.. list-table:: + :widths: 32 40 + :header-rows: 1 + + * - Field name + - Description + + * - ``$note`` + - This field is required and is an enum value which represents the + notice type. + + * - ``$msg`` + - This is a human readable message which is meant to provide more + information about this particular instance of the notice type. + + * - ``$sub`` + - This is a sub-message meant for human readability but will + frequently also be used to contain data meant to be matched with the + ``Notice::policy``. + + * - ``$conn`` + - If a connection record is available when the notice is being raised + and the notice represents some attribute of the connection, then the + connection record can be given here. Other fields such as ``$id`` and + ``$src`` will automatically be populated from this value. + + * - ``$id`` + - If a conn_id record is available when the notice is being raised and + the notice represents some attribute of the connection, then the + connection can be given here. Other fields such as ``$src`` will + automatically be populated from this value. + + * - ``$src`` + - If the notice represents an attribute of a single host then it's + possible that only this field should be filled out to represent the + host that is being "noticed". + + * - ``$n`` + - This normally represents a number if the notice has to do with some + number. It's most frequently used for numeric tests in the + ``Notice::policy`` for making policy decisions. + + * - ``$identifier`` + - This represents a unique identifier for this notice. This field is + described in more detail in the `Automated Suppression`_ section. + + * - ``$suppress_for`` + - This field can be set if there is a natural suppression interval for + the notice that may be different than the default value. The + value set to this field can also be modified by a user's + :bro:see:`Notice::policy` so the value is not set permanently + and unchangeably. + +When writing Bro scripts which raise notices, some thought should be given to +what the notice represents and what data should be provided to give a consumer +of the notice the best information about the notice. If the notice is +representative of many connections and is an attribute of a host (e.g. a +scanning host) it probably makes most sense to fill out the ``$src`` field and +not give a connection or conn_id. If a notice is representative of a +connection attribute (e.g. an apparent SSH login) then it makes sense to fill +out either ``$conn`` or ``$id`` based on the data that is available when the +notice is raised. Using care when inserting data into a notice will make later +analysis easier when only the data to fully represent the occurrence that +raised the notice is available. If complete connection information is +available when an SSL server certificate is expiring, the logs will be very +confusing because the connection that the certificate was detected on is a +side topic to the fact that an expired certificate was detected. It's possible +in many cases that two or more separate notices may need to be generated. As +an example, one could be for the detection of the expired SSL certificate and +another could be for if the client decided to go ahead with the connection +neglecting the expired certificate. + +Automated Suppression +--------------------- + +The notice framework supports suppression for notices if the author of the +script that is generating the notice has indicated to the notice framework how +to identify notices that are intrinsically the same. Identification of these +"intrinsically duplicate" notices is implemented with an optional field in +:bro:see:`Notice::Info` records named ``$identifier`` which is a simple string. +If the ``$identifier`` and ``$type`` fields are the same for two notices, the +notice framework actually considers them to be the same thing and can use that +information to suppress duplicates for a configurable period of time. + +.. note:: + + If the ``$identifier`` is left out of a notice, no notice suppression + takes place due to the framework's inability to identify duplicates. This + could be completely legitimate usage if no notices could ever be + considered to be duplicates. + +The ``$identifier`` field is typically comprised of several pieces of +data related to the notice that when combined represent a unique +instance of that notice. Here is an example of the script +:doc:`scripts/policy/protocols/ssl/validate-certs` raising a notice +for session negotiations where the certificate or certificate chain did +not validate successfully against the available certificate authority +certificates. + +.. code:: bro + + NOTICE([$note=SSL::Invalid_Server_Cert, + $msg=fmt("SSL certificate validation failed with (%s)", c$ssl$validation_status), + $sub=c$ssl$subject, + $conn=c, + $identifier=cat(c$id$resp_h,c$id$resp_p,c$ssl$validation_status,c$ssl$cert_hash)]); + +In the above example you can see that the ``$identifier`` field contains a +string that is built from the responder IP address and port, the validation +status message, and the MD5 sum of the server certificate. Those fields in +particular are chosen because different SSL certificates could be seen on any +port of a host, certificates could fail validation for different reasons, and +multiple server certificates could be used on that combination of IP address +and port with the ``server_name`` SSL extension (explaining the addition of +the MD5 sum of the certificate). The result is that if a certificate fails +validation and all four pieces of data match (IP address, port, validation +status, and certificate hash) that particular notice won't be raised again for +the default suppression period. + +Setting the ``$identifier`` field is left to those raising notices because +it's assumed that the script author who is raising the notice understands the +full problem set and edge cases of the notice which may not be readily +apparent to users. If users don't want the suppression to take place or simply +want a different interval, they can set a notice's suppression +interval to ``0secs`` or delete the value from the ``$identifier`` field in +a :bro:see:`Notice::policy` hook. + + +Extending Notice Framework +-------------------------- + +There are a couple of mechanism currently for extending the notice framework +and adding new capability. + +Extending Notice Emails +*********************** + +If there is extra information that you would like to add to emails, that is +possible to add by writing :bro:see:`Notice::policy` hooks. + +There is a field in the :bro:see:`Notice::Info` record named +``$email_body_sections`` which will be included verbatim when email is being +sent. An example of including some information from an HTTP request is +included below. + +.. code:: bro + + hook Notice::policy(n: Notice::Info) + { + if ( n?$conn && n$conn?$http && n$conn$http?$host ) + n$email_body_sections[|email_body_sections|] = fmt("HTTP host header: %s", n$conn$http$host); + } + + +Cluster Considerations +---------------------- + +As a user/developer of Bro, the main cluster concern with the notice framework +is understanding what runs where. When a notice is generated on a worker, the +worker checks to see if the notice shoudl be suppressed based on information +locally maintained in the worker process. If it's not being +suppressed, the worker forwards the notice directly to the manager and does no more +local processing. The manager then runs the :bro:see:`Notice::policy` hook and +executes all of the actions determined to be run. + diff --git a/doc/frameworks/signatures.rst b/doc/frameworks/signatures.rst new file mode 100644 index 0000000000..915133e178 --- /dev/null +++ b/doc/frameworks/signatures.rst @@ -0,0 +1,394 @@ + +=================== +Signature Framework +=================== + +.. rst-class:: opening + + Bro relies primarily on its extensive scripting language for + defining and analyzing detection policies. In addition, however, + Bro also provides an independent *signature language* for doing + low-level, Snort-style pattern matching. While signatures are + *not* Bro's preferred detection tool, they sometimes come in handy + and are closer to what many people are familiar with from using + other NIDS. This page gives a brief overview on Bro's signatures + and covers some of their technical subtleties. + +.. contents:: + :depth: 2 + +Basics +====== + +Let's look at an example signature first: + +.. code:: bro-sig + + signature my-first-sig { + ip-proto == tcp + dst-port == 80 + payload /.*root/ + event "Found root!" + } + + +This signature asks Bro to match the regular expression ``.*root`` on +all TCP connections going to port 80. When the signature triggers, Bro +will raise an event :bro:id:`signature_match` of the form: + +.. code:: bro + + event signature_match(state: signature_state, msg: string, data: string) + +Here, ``state`` contains more information on the connection that +triggered the match, ``msg`` is the string specified by the +signature's event statement (``Found root!``), and data is the last +piece of payload which triggered the pattern match. + +To turn such :bro:id:`signature_match` events into actual alarms, you can +load Bro's :doc:`/scripts/base/frameworks/signatures/main` script. +This script contains a default event handler that raises +:bro:enum:`Signatures::Sensitive_Signature` :doc:`Notices ` +(as well as others; see the beginning of the script). + +As signatures are independent of Bro's policy scripts, they are put into +their own file(s). There are three ways to specify which files contain +signatures: By using the ``-s`` flag when you invoke Bro, or by +extending the Bro variable :bro:id:`signature_files` using the ``+=`` +operator, or by using the ``@load-sigs`` directive inside a Bro script. +If a signature file is given without a full path, it is searched for +along the normal ``BROPATH``. Additionally, the ``@load-sigs`` +directive can be used to load signature files in a path relative to the +Bro script in which it's placed, e.g. ``@load-sigs ./mysigs.sig`` will +expect that signature file in the same directory as the Bro script. The +default extension of the file name is ``.sig``, and Bro appends that +automatically when necessary. + +Signature language +================== + +Let's look at the format of a signature more closely. Each individual +signature has the format ``signature { }``. ```` +is a unique label for the signature. There are two types of +attributes: *conditions* and *actions*. The conditions define when the +signature matches, while the actions declare what to do in the case of +a match. Conditions can be further divided into four types: *header*, +*content*, *dependency*, and *context*. We discuss these all in more +detail in the following. + +Conditions +---------- + +Header Conditions +~~~~~~~~~~~~~~~~~ + +Header conditions limit the applicability of the signature to a subset +of traffic that contains matching packet headers. This type of matching +is performed only for the first packet of a connection. + +There are pre-defined header conditions for some of the most used +header fields. All of them generally have the format `` +``, where ```` names the header field; ``cmp`` is +one of ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``; and +```` is a list of comma-separated values to compare +against. The following keywords are defined: + +``src-ip``/``dst-ip `` + Source and destination address, respectively. Addresses can be given + as IPv4 or IPv6 addresses or CIDR masks. For IPv6 addresses/masks + the colon-hexadecimal representation of the address must be enclosed + in square brackets (e.g. ``[fe80::1]`` or ``[fe80::0]/16``). + +``src-port``/``dst-port `` + Source and destination port, respectively. + +``ip-proto tcp|udp|icmp|icmp6|ip|ip6`` + IPv4 header's Protocol field or the Next Header field of the final + IPv6 header (i.e. either Next Header field in the fixed IPv6 header + if no extension headers are present or that field from the last + extension header in the chain). Note that the IP-in-IP forms of + tunneling are automatically decapsulated by default and signatures + apply to only the inner-most packet, so specifying ``ip`` or ``ip6`` + is a no-op. + +For lists of multiple values, they are sequentially compared against +the corresponding header field. If at least one of the comparisons +evaluates to true, the whole header condition matches (exception: with +``!=``, the header condition only matches if all values differ). + +In addition to these pre-defined header keywords, a general header +condition can be defined either as + +.. code:: bro-sig + + header [:] [& ] + +This compares the value found at the given position of the packet header +with a list of values. ``offset`` defines the position of the value +within the header of the protocol defined by ``proto`` (which can be +``ip``, ``ip6``, ``tcp``, ``udp``, ``icmp`` or ``icmp6``). ``size`` is +either 1, 2, or 4 and specifies the value to have a size of this many +bytes. If the optional ``& `` is given, the packet's value is +first masked with the integer before it is compared to the value-list. +``cmp`` is one of ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``. +``value-list`` is a list of comma-separated integers similar to those +described above. The integers within the list may be followed by an +additional ``/ mask`` where ``mask`` is a value from 0 to 32. This +corresponds to the CIDR notation for netmasks and is translated into a +corresponding bitmask applied to the packet's value prior to the +comparison (similar to the optional ``& integer``). IPv6 address values +are not allowed in the value-list, though you can still inspect any 1, +2, or 4 byte section of an IPv6 header using this keyword. + +Putting it all together, this is an example condition that is +equivalent to ``dst-ip == 1.2.3.4/16, 5.6.7.8/24``: + +.. code:: bro-sig + + header ip[16:4] == 1.2.3.4/16, 5.6.7.8/24 + +Note that the analogous example for IPv6 isn't currently possible since +4 bytes is the max width of a value that can be compared. + +Content Conditions +~~~~~~~~~~~~~~~~~~ + +Content conditions are defined by regular expressions. We +differentiate two kinds of content conditions: first, the expression +may be declared with the ``payload`` statement, in which case it is +matched against the raw payload of a connection (for reassembled TCP +streams) or of each packet (for ICMP, UDP, and non-reassembled TCP). +Second, it may be prefixed with an analyzer-specific label, in which +case the expression is matched against the data as extracted by the +corresponding analyzer. + +A ``payload`` condition has the form: + +.. code:: bro-sig + + payload // + +Currently, the following analyzer-specific content conditions are +defined (note that the corresponding analyzer has to be activated by +loading its policy script): + +``http-request //`` + The regular expression is matched against decoded URIs of HTTP + requests. Obsolete alias: ``http``. + +``http-request-header //`` + The regular expression is matched against client-side HTTP headers. + +``http-request-body //`` + The regular expression is matched against client-side bodys of + HTTP requests. + +``http-reply-header //`` + The regular expression is matched against server-side HTTP headers. + +``http-reply-body //`` + The regular expression is matched against server-side bodys of + HTTP replys. + +``ftp //`` + The regular expression is matched against the command line input + of FTP sessions. + +``finger //`` + The regular expression is matched against finger requests. + +For example, ``http-request /.*(etc/(passwd|shadow)/`` matches any URI +containing either ``etc/passwd`` or ``etc/shadow``. To filter on request +types, e.g. ``GET``, use ``payload /GET /``. + +Note that HTTP pipelining (that is, multiple HTTP transactions in a +single TCP connection) has some side effects on signature matches. If +multiple conditions are specified within a single signature, this +signature matches if all conditions are met by any HTTP transaction +(not necessarily always the same!) in a pipelined connection. + +Dependency Conditions +~~~~~~~~~~~~~~~~~~~~~ + +To define dependencies between signatures, there are two conditions: + + +``requires-signature [!] `` + Defines the current signature to match only if the signature given + by ``id`` matches for the same connection. Using ``!`` negates the + condition: The current signature only matches if ``id`` does not + match for the same connection (using this defers the match + decision until the connection terminates). + +``requires-reverse-signature [!] `` + Similar to ``requires-signature``, but ``id`` has to match for the + opposite direction of the same connection, compared to the current + signature. This allows to model the notion of requests and + replies. + +Context Conditions +~~~~~~~~~~~~~~~~~~ + +Context conditions pass the match decision on to other components of +Bro. They are only evaluated if all other conditions have already +matched. The following context conditions are defined: + +``eval `` + The given policy function is called and has to return a boolean + confirming the match. If false is returned, no signature match is + going to be triggered. The function has to be of type ``function + cond(state: signature_state, data: string): bool``. Here, + ``data`` may contain the most recent content chunk available at + the time the signature was matched. If no such chunk is available, + ``data`` will be the empty string. See :bro:type:`signature_state` + for its definition. + +``payload-size `` + Compares the integer to the size of the payload of a packet. For + reassembled TCP streams, the integer is compared to the size of + the first in-order payload chunk. Note that the latter is not very + well defined. + +``same-ip`` + Evaluates to true if the source address of the IP packets equals + its destination address. + +``tcp-state `` + Imposes restrictions on the current TCP state of the connection. + ``state-list`` is a comma-separated list of the keywords + ``established`` (the three-way handshake has already been + performed), ``originator`` (the current data is send by the + originator of the connection), and ``responder`` (the current data + is send by the responder of the connection). + + +Actions +------- + +Actions define what to do if a signature matches. Currently, there are +two actions defined: + +``event `` + Raises a :bro:id:`signature_match` event. The event handler has the + following type: + + .. code:: bro + + event signature_match(state: signature_state, msg: string, data: string) + + The given string is passed in as ``msg``, and data is the current + part of the payload that has eventually lead to the signature + match (this may be empty for signatures without content + conditions). + +``enable `` + Enables the protocol analyzer ```` for the matching + connection (``"http"``, ``"ftp"``, etc.). This is used by Bro's + dynamic protocol detection to activate analyzers on the fly. + +Things to keep in mind when writing signatures +============================================== + +* Each signature is reported at most once for every connection, + further matches of the same signature are ignored. + +* The content conditions perform pattern matching on elements + extracted from an application protocol dialogue. For example, ``http + /.*passwd/`` scans URLs requested within HTTP sessions. The thing to + keep in mind here is that these conditions only perform any matching + when the corresponding application analyzer is actually *active* for + a connection. Note that by default, analyzers are not enabled if the + corresponding Bro script has not been loaded. A good way to + double-check whether an analyzer "sees" a connection is checking its + log file for corresponding entries. If you cannot find the + connection in the analyzer's log, very likely the signature engine + has also not seen any application data. + +* As the name indicates, the ``payload`` keyword matches on packet + *payload* only. You cannot use it to match on packet headers; use + the header conditions for that. + +* For TCP connections, header conditions are only evaluated for the + *first packet from each endpoint*. If a header condition does not + match the initial packets, the signature will not trigger. Bro + optimizes for the most common application here, which is header + conditions selecting the connections to be examined more closely + with payload statements. + +* For UDP and ICMP flows, the payload matching is done on a per-packet + basis; i.e., any content crossing packet boundaries will not be + found. For TCP connections, the matching semantics depend on whether + Bro is *reassembling* the connection (i.e., putting all of a + connection's packets in sequence). By default, Bro is reassembling + the first 1K of every TCP connection, which means that within this + window, matches will be found without regards to packet order or + boundaries (i.e., *stream-wise matching*). + +* For performance reasons, by default Bro *stops matching* on a + connection after seeing 1K of payload; see the section on options + below for how to change this behaviour. The default was chosen with + Bro's main user of signatures in mind: dynamic protocol detection + works well even when examining just connection heads. + +* Regular expressions are implicitly anchored, i.e., they work as if + prefixed with the ``^`` operator. For reassembled TCP connections, + they are anchored at the first byte of the payload *stream*. For all + other connections, they are anchored at the first payload byte of + each packet. To match at arbitrary positions, you can prefix the + regular expression with ``.*``, as done in the examples above. + +* To match on non-ASCII characters, Bro's regular expressions support + the ``\x`` operator. CRs/LFs are not treated specially by the + signature engine and can be matched with ``\r`` and ``\n``, + respectively. Generally, Bro follows `flex's regular expression + syntax + `_. + See the DPD signatures in ``base/frameworks/dpd/dpd.sig`` for some examples + of fairly complex payload patterns. + +* The data argument of the :bro:id:`signature_match` handler might not carry + the full text matched by the regular expression. Bro performs the + matching incrementally as packets come in; when the signature + eventually fires, it can only pass on the most recent chunk of data. + + +Options +======= + +The following options control details of Bro's matching process: + +``dpd_reassemble_first_packets: bool`` (default: ``T``) + If true, Bro reassembles the beginning of every TCP connection (of + up to ``dpd_buffer_size`` bytes, see below), to facilitate + reliable matching across packet boundaries. If false, only + connections are reassembled for which an application-layer + analyzer gets activated (e.g., by Bro's dynamic protocol + detection). + +``dpd_match_only_beginning : bool`` (default: ``T``) + If true, Bro performs packet matching only within the initial + payload window of ``dpd_buffer_size``. If false, it keeps matching + on subsequent payload as well. + +``dpd_buffer_size: count`` (default: ``1024``) + Defines the buffer size for the two preceding options. In + addition, this value determines the amount of bytes Bro buffers + for each connection in order to activate application analyzers + even after parts of the payload have already passed through. This + is needed by the dynamic protocol detection capability to defer + the decision which analyzers to use. + + +So, how about using Snort signatures with Bro? +============================================== + +There was once a script, ``snort2bro``, that converted Snort +signatures automatically into Bro's signature syntax. However, in our +experience this didn't turn out to be a very useful thing to do +because by simply using Snort signatures, one can't benefit from the +additional capabilities that Bro provides; the approaches of the two +systems are just too different. We therefore stopped maintaining the +``snort2bro`` script, and there are now many newer Snort options which +it doesn't support. The script is now no longer part of the Bro +distribution. + diff --git a/doc/index.rst b/doc/index.rst index e966661115..32c01a6e7d 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -5,50 +5,15 @@ Bro Documentation ================= -Guides ------- - .. toctree:: - :maxdepth: 1 - - INSTALL - upgrade - quickstart - faq - reporting-problems - -xFrameworks ----------- - -.. toctree:: - :maxdepth: 1 - - notice - logging - input - cluster - signatures - -How-Tos -------- - -.. toctree:: - :maxdepth: 2 - :numbered: - - user-manual/index - reference/index - -Just Testing -============ - -.. code:: bro - - print "Hey Bro!" - -.. btest:: test - - @TEST-COPY-FILE: ${TRACES}/wikipedia.trace - @TEST-EXEC: btest-rst-cmd bro -r wikipedia.trace - @TEST-EXEC: btest-rst-cmd "cat http.log | bro-cut ts id.orig_h | head -5" + :maxdepth: 2 + intro/index.rst + using/index.rst + scripting/index.rst + frameworks/index.rst + cluster/index.rst + scripts/index.rst + misc/index.rst + components/index.rst + indices/index.rst diff --git a/doc/indices/index.rst b/doc/indices/index.rst new file mode 100644 index 0000000000..1d0411c7c0 --- /dev/null +++ b/doc/indices/index.rst @@ -0,0 +1,7 @@ + +======= +Indices +======= + +* :ref:`General Index ` +* :ref:`search` diff --git a/doc/intro/index.rst b/doc/intro/index.rst new file mode 100644 index 0000000000..58a5a03bd0 --- /dev/null +++ b/doc/intro/index.rst @@ -0,0 +1,13 @@ + +============ +Introduction +============ + +.. toctree:: + :maxdepth: 2 + + overview + quickstart + upgrade + reporting-problems + diff --git a/doc/reference/language.rst b/doc/intro/overview.rst similarity index 65% rename from doc/reference/language.rst rename to doc/intro/overview.rst index dd50997672..acb9c970d5 100644 --- a/doc/reference/language.rst +++ b/doc/intro/overview.rst @@ -1,7 +1,5 @@ ================== -Language (Missing) +Overview (Missing) ================== - - diff --git a/doc/user-manual/quickstart.rst b/doc/intro/quickstart.rst similarity index 100% rename from doc/user-manual/quickstart.rst rename to doc/intro/quickstart.rst diff --git a/doc/intro/reporting-problems.rst b/doc/intro/reporting-problems.rst new file mode 100644 index 0000000000..903df76257 --- /dev/null +++ b/doc/intro/reporting-problems.rst @@ -0,0 +1,194 @@ + +Reporting Problems +================== + +.. rst-class:: opening + + Here we summarize some steps to follow when you see Bro doing + something it shouldn't. To provide help, it is often crucial for + us to have a way of reliably reproducing the effect you're seeing. + Unfortunately, reproducing problems can be rather tricky with Bro + because more often than not, they occur only in either very rare + situations or only after Bro has been running for some time. In + particular, getting a small trace showing a specific effect can be + a real problem. In the following, we'll summarize some strategies + to this end. + +Reporting Problems +------------------ + +Generally, when you encounter a problem with Bro, the best thing to do +is opening a new ticket in `Bro's issue tracker +`__ and include information on how to +reproduce the issue. Ideally, your ticket should come with the +following: + +* The Bro version you're using (if working directly from the git + repository, the branch and revision number.) + +* The output you're seeing along with a description of what you'd expect + Bro to do instead. + +* A *small* trace in `libpcap format `__ + demonstrating the effect (assuming the problem doesn't happen right + at startup already). + +* The exact command-line you're using to run Bro with that trace. If + you can, please try to run the Bro binary directly from the command + line rather than using BroControl. + +* Any non-standard scripts you're using (but please only those really + necessary; just a small code snippet triggering the problem would + be perfect). + +* If you encounter a crash, information from the core dump, such as + the stack backtrace, can be very helpful. See below for more on + this. + + +How Do I Get a Trace File? +-------------------------- + +As Bro is usually running live, coming up with a small trace file that +reproduces a problem can turn out to be quite a challenge. Often it +works best to start with a large trace that triggers the problem, +and then successively thin it out as much as possible. + +To get to the initial large trace, here are a few things you can try: + +* Capture a trace with `tcpdump `__, either + on the same interface Bro is running on, or on another host where + you can generate traffic of the kind likely triggering the problem + (e.g., if you're seeing problems with the HTTP analyzer, record some + of your Web browsing on your desktop.) When using tcpdump, don't + forget to record *complete* packets (``tcpdump -s 0 ...``). You can + reduce the amount of traffic captured by using a suitable BPF filter + (e.g., for HTTP only, try ``port 80``). + +* Bro's command-line option ``-w `` records all packets it + processes into the given file. You can then later run Bro + offline on this trace and it will process the packets in the same + way as it did live. This is particularly helpful with problems that + only occur after Bro has already been running for some time. For + example, sometimes a crash may be triggered by a particular kind of + traffic only occurring rarely. Running Bro live with ``-w`` and + then, after the crash, offline on the recorded trace might, with a + little bit of luck, reproduce the problem reliably. However, be + careful with ``-w``: it can result in huge trace files, quickly + filling up your disk. (One way to mitigate the space issues is to + periodically delete the trace file by configuring + ``rotate-logs.bro`` accordingly. BroControl does that for you if you + set its ``SaveTraces`` option.) + +* Finally, you can try running Bro on a publically available trace + file, such as `anonymized FTP traffic `__, `headers-only enterprise traffic + `__, or + `Defcon traffic `__. Some of these + particularly stress certain components of Bro (e.g., the Defcon + traces contain tons of scans). + +Once you have a trace that demonstrates the effect, you will often +notice that it's pretty big, in particular if recorded from the link +you're monitoring. Therefore, the next step is to shrink its size as +much as possible. Here are a few things you can try to this end: + +* Very often, a single connection is able to demonstrate the problem. + If you can identify which one it is (e.g., from one of Bro's + ``*.log`` files) you can extract the connection's packets from the + trace using tcpdump by filtering for the corresponding 4-tuple of + addresses and ports: + + .. console:: + + > tcpdump -r large.trace -w small.trace host and port and host and port + +* If you can't reduce the problem to a connection, try to identify + either a host pair or a single host triggering it, and filter down + the trace accordingly. + +* You can try to extract a smaller time slice from the trace using + `TCPslice `__. For example, to + extract the first 100 seconds from the trace: + + .. console:: + + # Test comment + > tcpslice +100 out + +Alternatively, tcpdump extracts the first ``n`` packets with its +option ``-c ``. + + +Getting More Information After a Crash +-------------------------------------- + +If Bro crashes, a *core dump* can be very helpful to nail down the +problem. Examining a core is not for the faint of heart but can reveal +extremely useful information. + +First, you should configure Bro with the option ``--enable-debug`` and +recompile; this will disable all compiler optimizations and thus make +the core dump more useful (don't expect great performance with this +version though; compiling Bro without optimization has a noticeable +impact on its CPU usage.). Then enable core dumps if you haven't +already (e.g., ``ulimit -c unlimited`` if you're using bash). + +Once Bro has crashed, start gdb with the Bro binary and the file +containing the core dump. (Alternatively, you can also run Bro +directly inside gdb instead of working from a core file.) The first +helpful information to include with your tracker ticket is a stack +backtrace, which you get with gdb's ``bt`` command: + +.. console:: + + > gdb bro core + [...] + > bt + + +If the crash occurs inside Bro's script interpreter, the next thing to +do is identifying the line of script code processed just before the +abnormal termination. Look for methods in the stack backtrace which +belong to any of the script interpreter's classes. Roughly speaking, +these are all classes with names ending in ``Expr``, ``Stmt``, or +``Val``. Then climb up the stack with ``up`` until you reach the first +of these methods. The object to which ``this`` is pointing will have a +``Location`` object, which in turn contains the file name and line +number of the corresponding piece of script code. Continuing the +example from above, here's how to get that information: + +.. console:: + + [in gdb] + > up + > ... + > up + > print this->location->filename + > print this->location->first_line + + +If the crash occurs while processing input packets but you cannot +directly tell which connection is responsible (and thus not extract +its packets from the trace as suggested above), try getting the +4-tuple of the connection currently being processed from the core dump +by again examining the stack backtrace, this time looking for methods +belonging to the ``Connection`` class. That class has members +``orig_addr``/``resp_addr`` and ``orig_port``/``resp_port`` storing +(pointers to) the IP addresses and ports respectively: + +.. console:: + + [in gdb] + > up + > ... + > up + > printf "%08x:%04x %08x:%04x\n", *this->orig_addr, this->orig_port, *this->resp_addr, this->resp_port + + +Note that these values are stored in `network byte order +`__ +so you will need to flip the bytes around if you are on a low-endian +machine (which is why the above example prints them in hex). For +example, if an IP address prints as ``0100007f`` , that's 127.0.0.1 . + diff --git a/doc/intro/upgrade.rst b/doc/intro/upgrade.rst new file mode 100644 index 0000000000..539757537d --- /dev/null +++ b/doc/intro/upgrade.rst @@ -0,0 +1,308 @@ + +========================================== +Upgrading From the Previous Version of Bro +========================================== + +.. rst-class:: opening + + This guide details specific differences between Bro versions + that may be important for users to know as they work on updating + their Bro deployment/configuration to the later version. + +.. contents:: + + +Upgrading From Bro 2.0 to 2.1 +============================= + +In Bro 2.1, IPv6 is enabled by default. Therefore, when building Bro from +source, the "--enable-brov6" configure option has been removed because it +is no longer relevant. + +Other configure changes include renaming the "--enable-perftools" option +to "--enable-perftools-debug" to indicate that the option is only relevant +for debugging the heap. One other change involves what happens when +tcmalloc (part of Google perftools) is found at configure time. On Linux, +it will automatically be linked with Bro, but on other platforms you +need to use the "--enable-perftools" option to enable linking to tcmalloc. + +There are a couple of changes to the Bro scripting language to better +support IPv6. First, IPv6 literals appearing in a Bro script must now be +enclosed in square brackets (for example, ``[fe80::db15]``). For subnet +literals, the slash "/" appears after the closing square bracket (for +example, ``[fe80:1234::]/32``). Second, when an IP address variable or IP +address literal is enclosed in pipes (for example, ``|[fe80::db15]|``) the +result is now the size of the address in bits (32 for IPv4 and 128 for IPv6). + +In the Bro scripting language, "match" and "using" are no longer reserved +keywords. + +Some built-in functions have been removed: "addr_to_count" (use +"addr_to_counts" instead), "bro_has_ipv6" (this is no longer relevant +because Bro now always supports IPv6), "active_connection" (use +"connection_exists" instead), and "connection_record" (use "lookup_connection" +instead). + +The "NFS3::mode2string" built-in function has been renamed to "file_mode". + +Some built-in functions have been changed: "exit" (now takes the exit code +as a parameter), "to_port" (now takes a string as parameter instead +of a count and transport protocol, but "count_to_port" is still available), +"connect" (now takes an additional string parameter specifying the zone of +a non-global IPv6 address), and "listen" (now takes three additional +parameters to enable listening on IPv6 addresses). + +Some Bro script variables have been renamed: "LogAscii::header_prefix" +has been renamed to "LogAscii::meta_prefix", "LogAscii::include_header" +has been renamed to "LogAscii::include_meta". + +Some Bro script variables have been removed: "tunnel_port", +"parse_udp_tunnels", "use_connection_compressor", "cc_handle_resets", +"cc_handle_only_syns", and "cc_instantiate_on_data". + +A couple events have changed: the "icmp_redirect" event now includes +the target and destination addresses and any Neighbor Discovery options +in the message, and the last parameter of the "dns_AAAA_reply" event has +been removed because it was unused. + +The format of the ASCII log files has changed very slightly. Two new lines +are automatically added, one to record the time when the log was opened, +and the other to record the time when the log was closed. + +In BroControl, the option (in broctl.cfg) "CFlowAddr" was renamed +to "CFlowAddress". + + +Upgrading From Bro 1.5 to 2.0 +============================= + +As the version number jump suggests, Bro 2.0 is a major upgrade and +lots of things have changed. Most importantly, we have rewritten +almost all of Bro's default scripts from scratch, using quite +different structure now and focusing more on operational deployment. +The result is a system that works much better "out of the box", even +without much initial site-specific configuration. The down-side is +that 1.x configurations will need to be adapted to work with the new +version. The two rules of thumb are: + + (1) If you have written your own Bro scripts + that do not depend on any of the standard scripts formerly + found in ``policy/``, they will most likely just keep working + (although you might want to adapt them to use some of the new + features, like the new logging framework; see below). + + (2) If you have custom code that depends on specifics of 1.x + default scripts (including most configuration tuning), that is + unlikely to work with 2.x. We recommend to start by using just + the new scripts first, and then port over any customizations + incrementally as necessary (they may be much easier to do now, + or even unnecessary). Send mail to the Bro user mailing list + if you need help. + +Below we summarize changes from 1.x to 2.x in more detail. This list +isn't complete, see the :download:`CHANGES ` file in the +distribution for the full story. + +Default Scripts +=============== + +Organization +------------ + +In versions before 2.0, Bro scripts were all maintained in a flat +directory called ``policy/`` in the source tree. This directory is now +renamed to ``scripts/`` and contains major subdirectories ``base/``, +``policy/``, and ``site/``, each of which may also be subdivided +further. + +The contents of the new ``scripts/`` directory, like the old/flat +``policy/`` still gets installed under the ``share/bro`` +subdirectory of the installation prefix path just like previous +versions. For example, if Bro was compiled like ``./configure +--prefix=/usr/local/bro && make && make install``, then the script +hierarchy can be found in ``/usr/local/bro/share/bro``. + +The main +subdirectories of that hierarchy are as follows: + +- ``base/`` contains all scripts that are loaded by Bro by default + (unless the ``-b`` command line option is used to run Bro in a + minimal configuration). Note that is a major conceptual change: + rather than not loading anything by default, Bro now uses an + extensive set of default scripts out of the box. + + The scripts under this directory generally either accumulate/log + useful state/protocol information for monitored traffic, configure a + default/recommended mode of operation, or provide extra Bro + scripting-layer functionality that has no significant performance cost. + +- ``policy/`` contains all scripts that a user will need to explicitly + tell Bro to load. These are scripts that implement + functionality/analysis that not all users may want to use and may have + more significant performance costs. For a new installation, you + should go through these and see what appears useful to load. + +- ``site/`` remains a directory that can be used to store locally + developed scripts. It now comes with some preinstalled example + scripts that contain recommended default configurations going beyond + the ``base/`` setup. E.g. ``local.bro`` loads extra scripts from + ``policy/`` and does extra tuning. These files can be customized in + place without being overwritten by upgrades/reinstalls, unlike + scripts in other directories. + +With version 2.0, the default ``BROPATH`` is set to automatically +search for scripts in ``policy/``, ``site/`` and their parent +directory, but **not** ``base/``. Generally, everything under +``base/`` is loaded automatically, but for users of the ``-b`` option, +it's important to know that loading a script in that directory +requires the extra ``base/`` path qualification. For example, the +following two scripts: + +* ``$PREFIX/share/bro/base/protocols/ssl/main.bro`` +* ``$PREFIX/share/bro/policy/protocols/ssl/validate-certs.bro`` + +are referenced from another Bro script like: + +.. code:: bro + + @load base/protocols/ssl/main + @load protocols/ssl/validate-certs + +Notice how ``policy/`` can be omitted as a convenience in the second +case. ``@load`` can now also use relative path, e.g., ``@load +../main``. + + +Logging Framework +----------------- + +- The logs generated by scripts that ship with Bro are entirely redone + to use a standardized, machine parsable format via the new logging + framework. Generally, the log content has been restructured towards + making it more directly useful to operations. Also, several + analyzers have been significantly extended and thus now log more + information. Take a look at ``ssl.log``. + + * A particular format change that may be useful to note is that the + ``conn.log`` ``service`` field is derived from DPD instead of + well-known ports (while that was already possible in 1.5, it was + not the default). + + * Also, ``conn.log`` now reports raw number of packets/bytes per + endpoint. + +- The new logging framework makes it possible to extend, customize, + and filter logs very easily. See the :doc:`logging framework ` + for more information on usage. + +- A common pattern found in the new scripts is to store logging stream + records for protocols inside the ``connection`` records so that + state can be collected until enough is seen to log a coherent unit + of information regarding the activity of that connection. This + state is now frequently seen/accessible in event handlers, for + example, like ``c$`` where ```` is replaced by + the name of the protocol. This field is added to the ``connection`` + record by ``redef``'ing it in a + ``base/protocols//main.bro`` script. + +- The logging code has been rewritten internally, with script-level + interface and output backend now clearly separated. While ASCII + logging is still the default, we will add further output types in + the future (binary format, direct database logging). + + +Notice Framework +---------------- + +The way users interact with "notices" has changed significantly in +order to make it easier to define a site policy and more extensible +for adding customized actions. See the :doc:`notice framework `. + + +New Default Settings +-------------------- + +- Dynamic Protocol Detection (DPD) is now enabled/loaded by default. + +- The default packet filter now examines all packets instead of + dynamically building a filter based on which protocol analysis scripts + are loaded. See ``PacketFilter::all_packets`` for how to revert to old + behavior. + +API Changes +----------- + +- The ``@prefixes`` directive works differently now. + Any added prefixes are now searched for and loaded *after* all input + files have been parsed. After all input files are parsed, Bro + searches ``BROPATH`` for prefixed, flattened versions of all of the + parsed input files. For example, if ``lcl`` is in ``@prefixes``, and + ``site.bro`` is loaded, then a file named ``lcl.site.bro`` that's in + ``BROPATH`` would end up being automatically loaded as well. Packages + work similarly, e.g. loading ``protocols/http`` means a file named + ``lcl.protocols.http.bro`` in ``BROPATH`` gets loaded automatically. + +- The ``make_addr`` BIF now returns a ``subnet`` versus an ``addr`` + + +Variable Naming +--------------- + +- ``Module`` is more widely used for namespacing. E.g. the new + ``site.bro`` exports the ``local_nets`` identifier (among other + things) into the ``Site`` module. + +- Identifiers may have been renamed to conform to new `scripting + conventions + `_ + + +BroControl +========== + +BroControl looks pretty much similar to the version coming with Bro 1.x, +but has been cleaned up and streamlined significantly internally. + +BroControl has a new ``process`` command to process a trace on disk +offline using a similar configuration to what BroControl installs for +live analysis. + +BroControl now has an extensive plugin interface for adding new +commands and options. Note that this is still considered experimental. + +We have removed the ``analysis`` command, and BroControl currently +does not send daily alarm summaries anymore (this may be restored +later). + +Removed Functionality +===================== + +We have remove a bunch of functionality that was rarely used and/or +had not been maintained for a while already: + + - The ``net`` script data type. + - The ``alarm`` statement; use the notice framework instead. + - Trace rewriting. + - DFA state expiration in regexp engine. + - Active mapping. + - Native DAG support (may come back eventually) + - ClamAV support. + - The connection compressor is now disabled by default, and will + be removed in the future. + +Development Infrastructure +========================== + +Bro development has moved from using SVN to Git for revision control. +Users that want to use the latest Bro development snapshot by checking it out +from the source repositories should see the `development process +`_. Note that all the various +sub-components now reside in their own repositories. However, the +top-level Bro repository includes them as git submodules so it's easy +to check them all out simultaneously. + +Bro now uses `CMake `_ for its build system so +that is a new required dependency when building from source. + +Bro now comes with a growing suite of regression tests in +``testing/``. diff --git a/doc/misc/geoip.rst b/doc/misc/geoip.rst new file mode 100644 index 0000000000..bd9ae0c08d --- /dev/null +++ b/doc/misc/geoip.rst @@ -0,0 +1,102 @@ + +=========== +GeoLocation +=========== + +.. rst-class:: opening + + During the process of creating policy scripts the need may arise + to find the geographic location for an IP address. Bro has support + for the `GeoIP library `__ at the + policy script level beginning with release 1.3 to account for this + need. + +.. contents:: + +GeoIPLite Database Installation +------------------------------------ + +A country database for GeoIPLite is included when you do the C API +install, but for Bro, we are using the city database which includes +cities and regions in addition to countries. + +`Download `__ the geolitecity +binary database and follow the directions to install it. + +FreeBSD Quick Install +--------------------- + +.. console:: + + pkg_add -r GeoIP + wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz + gunzip GeoLiteCity.dat.gz + mv GeoLiteCity.dat /usr/local/share/GeoIP/GeoIPCity.dat + + # Set your environment correctly before running Bro's configure script + export CFLAGS=-I/usr/local/include + export LDFLAGS=-L/usr/local/lib + + +CentOS Quick Install +-------------------- + +.. console:: + + yum install GeoIP-devel + + wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz + gunzip GeoLiteCity.dat.gz + mkdir -p /var/lib/GeoIP/ + mv GeoLiteCity.dat /var/lib/GeoIP/GeoIPCity.dat + + # Set your environment correctly before running Bro's configure script + export CFLAGS=-I/usr/local/include + export LDFLAGS=-L/usr/local/lib + + +Usage +----- + +There is a single built in function that provides the GeoIP +functionality: + +.. code:: bro + + function lookup_location(a:addr): geo_location + +There is also the ``geo_location`` data structure that is returned +from the ``lookup_location`` function: + +.. code:: bro + + type geo_location: record { + country_code: string; + region: string; + city: string; + latitude: double; + longitude: double; + }; + + +Example +------- + +To write a line in a log file for every ftp connection from hosts in +Ohio, this is now very easy: + +.. code:: bro + + global ftp_location_log: file = open_log_file("ftp-location"); + + event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) + { + local client = c$id$orig_h; + local loc = lookup_location(client); + if (loc$region == "OH" && loc$country_code == "US") + { + print ftp_location_log, fmt("FTP Connection from:%s (%s,%s,%s)", client, loc$city, loc$region, loc$country_code); + } + } + + diff --git a/doc/misc/index.rst b/doc/misc/index.rst new file mode 100644 index 0000000000..edf82e8fd2 --- /dev/null +++ b/doc/misc/index.rst @@ -0,0 +1,9 @@ + +==================== +Miscellaneous Topics +==================== + +.. toctree:: + :maxdepth: 2 + + geoip diff --git a/doc/reference/events.rst b/doc/reference/events.rst deleted file mode 100644 index bcb3adae42..0000000000 --- a/doc/reference/events.rst +++ /dev/null @@ -1,5 +0,0 @@ - -================ -Events (Missing) -================ - diff --git a/doc/reference/frameworks.rst b/doc/reference/frameworks.rst deleted file mode 100644 index 20824b03bc..0000000000 --- a/doc/reference/frameworks.rst +++ /dev/null @@ -1,5 +0,0 @@ - -==================== -Frameworks (Missing) -==================== - diff --git a/doc/reference/index.rst b/doc/reference/index.rst deleted file mode 100644 index cba512cd1c..0000000000 --- a/doc/reference/index.rst +++ /dev/null @@ -1,13 +0,0 @@ - -========= -Reference -========= - -.. toctree:: - :maxdepth: 2 - :numbered: - - frameworks.rst - events.rst - language.rst - subsystems.rst diff --git a/doc/reference/subsystems.rst b/doc/reference/subsystems.rst deleted file mode 100644 index 9caafba8b3..0000000000 --- a/doc/reference/subsystems.rst +++ /dev/null @@ -1,4 +0,0 @@ - -==================== -Subsystems (Missing) -==================== diff --git a/doc/user-manual/scripting.rst b/doc/scripting/index.rst similarity index 99% rename from doc/user-manual/scripting.rst rename to doc/scripting/index.rst index adc35b127e..9ef8e8f8f3 100644 --- a/doc/user-manual/scripting.rst +++ b/doc/scripting/index.rst @@ -1,7 +1,7 @@ -========= -Scripting -========= +=================== +Writing Bro Scripts +=================== .. toctree:: :maxdepth: 2 diff --git a/doc/scripts/index.rst b/doc/scripts/index.rst index bf0fa25f10..d8fe2e57b1 100644 --- a/doc/scripts/index.rst +++ b/doc/scripts/index.rst @@ -1,8 +1,21 @@ .. This is a stub doc to which broxygen appends during the build process -Index of All Individual Bro Scripts -=================================== +================ +Script Reference +================ .. toctree:: :maxdepth: 1 + builtins + bifs + scripts + packages + internal + +Indices +======= + + * `Notice Index `_ + + diff --git a/doc/scripts/scripts.rst b/doc/scripts/scripts.rst new file mode 100644 index 0000000000..d454063002 --- /dev/null +++ b/doc/scripts/scripts.rst @@ -0,0 +1,8 @@ +.. This is a stub doc to which broxygen appends during the build process + +======================== +Index of All Bro Scripts +======================== + +.. toctree:: + :maxdepth: 1 diff --git a/doc/user-manual/index.rst b/doc/user-manual/index.rst deleted file mode 100644 index ad3e516a78..0000000000 --- a/doc/user-manual/index.rst +++ /dev/null @@ -1,13 +0,0 @@ - -=========== -User Manual -=========== - -.. toctree:: - :maxdepth: 2 - :numbered: - - intro.rst - quickstart.rst - scripting.rst - diff --git a/doc/user-manual/intro.rst b/doc/user-manual/intro.rst deleted file mode 100644 index c7a210747d..0000000000 --- a/doc/user-manual/intro.rst +++ /dev/null @@ -1,4 +0,0 @@ - -====================== -Introduction (Missing) -====================== diff --git a/doc/using/index.rst b/doc/using/index.rst new file mode 100644 index 0000000000..ab7834d904 --- /dev/null +++ b/doc/using/index.rst @@ -0,0 +1,6 @@ + +=================== +Using Bro (Missing) +=================== + +TODO. From fd51db1c89e024227a46e9770499ea9eceb87fb1 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 2 Apr 2013 11:24:03 +0200 Subject: [PATCH 057/881] purely aesthetical - make whitespacing fit bro coding style. Second step will be to change the bifs a bit... --- src/HyperLogLog.cc | 242 +++++++++++++++++++++++---------------------- src/HyperLogLog.h | 2 + 2 files changed, 128 insertions(+), 116 deletions(-) diff --git a/src/HyperLogLog.cc b/src/HyperLogLog.cc index 22a06ee6c7..436d754b4d 100644 --- a/src/HyperLogLog.cc +++ b/src/HyperLogLog.cc @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include #include #include "HyperLogLog.h" @@ -5,129 +7,137 @@ using namespace std; - int CardinalityCounter::optimalB(double error){ - double initial_estimate = 2*(log(1.04)-log(error))/log(2); - int answer = (int) floor(initial_estimate); - double k; +int CardinalityCounter::optimalB(double error) + { + double initial_estimate = 2*(log(1.04)-log(error))/log(2); + int answer = (int) floor(initial_estimate); + double k; - do{ - answer++; - k = pow(2, (answer - initial_estimate)/2); - }while(erf(k/sqrt(2)) < conf); + do + { + answer++; + k = pow(2, (answer - initial_estimate)/2); + } + while (erf(k/sqrt(2)) < conf); - return answer; - } + return answer; + } - CardinalityCounter :: CardinalityCounter(uint64_t size){ - m = size; - buckets = new uint8_t[m]; +CardinalityCounter::CardinalityCounter(uint64_t size) + { + m = size; + buckets = new uint8_t[m]; - if(m == 16) - alpha_m = 0.673; - else if(m == 32) - alpha_m = 0.697; - else if(m == 64) - alpha_m = 0.709; - else - alpha_m = 0.7213/(1+1.079/m); + if(m == 16) + alpha_m = 0.673; + else if(m == 32) + alpha_m = 0.697; + else if(m == 64) + alpha_m = 0.709; + else + alpha_m = 0.7213/(1+1.079/m); - for(uint64_t i = 0; i < m; i++){ - buckets[i] = 0; - } - - V = m; - - } - - CardinalityCounter :: CardinalityCounter(double error_margin){ - int b = optimalB(error_margin); - m = (uint64_t) pow(2, b); - buckets = new uint8_t[m]; - - if(m == 16) - alpha_m = 0.673; - else if(m == 32) - alpha_m = 0.697; - else if(m == 64) - alpha_m = 0.709; - else - alpha_m = 0.7213/(1+1.079/m); - - for(uint64_t i = 0; i < m; i++){ - buckets[i] = 0; - } - - V = m; - } - - CardinalityCounter :: ~CardinalityCounter(){ - delete [] buckets; - delete &m; - delete &V; - delete &alpha_m; - } - - uint8_t CardinalityCounter :: rank(uint64_t hash_modified){ - uint8_t answer = 0; - hash_modified = (uint64_t)(hash_modified/m); - hash_modified *= 2; - do{ - hash_modified = (uint64_t) (hash_modified/2); - answer++; - }while(hash_modified%2 == 0); - return answer; - } - - - - void CardinalityCounter::addElement(uint64_t hash){ - uint64_t index = hash % m; - hash = hash-index; - - if(buckets[index] == 0) - V--; - uint8_t temp = rank(hash); - if(temp > buckets[index]){ - buckets[index] = temp; - } - } + for (uint64_t i = 0; i < m; i++) + buckets[i] = 0; - double CardinalityCounter::size(){ - double answer = 0; - for(int i = 0; i < m; i++){ - answer += pow(2, -(int)buckets[i]); - } - answer = 1/answer; - answer = alpha_m*m*m*answer; + V = m; + } + +CardinalityCounter :: CardinalityCounter(double error_margin) + { + int b = optimalB(error_margin); + m = (uint64_t) pow(2, b); + buckets = new uint8_t[m]; - if(answer <= 5*(double)(m/2)){ - return m*log((double) m/V); - } - else if(answer <= pow(2,64)/30){ - return answer; - } - else{ - return -pow(2,64)*log(1-answer/pow(2,64)); - } - } + if(m == 16) + alpha_m = 0.673; + else if(m == 32) + alpha_m = 0.697; + else if(m == 64) + alpha_m = 0.709; + else + alpha_m = 0.7213/(1+1.079/m); - void CardinalityCounter::merge(CardinalityCounter* c){ - uint8_t* temp = (*c).getBuckets(); - V = 0; - for(int i = 0; i < m; i++){ - if(temp[i] > buckets[i]){ - buckets[i] = temp[i]; - } - if(buckets[i] == 0){ - V += 1; - } - } - } + for (uint64_t i = 0; i < m; i++) + buckets[i] = 0; - uint8_t* CardinalityCounter::getBuckets(){ - return buckets; - } + V = m; +} - uint64_t CardinalityCounter::getM(){ - return m; - } +CardinalityCounter::~CardinalityCounter() + { + delete [] buckets; + delete &m; + delete &V; + delete &alpha_m; + } + +uint8_t CardinalityCounter::rank(uint64_t hash_modified) + { + uint8_t answer = 0; + hash_modified = (uint64_t)(hash_modified/m); + hash_modified *= 2; + do + { + hash_modified = (uint64_t) (hash_modified/2); + answer++; + } + while (hash_modified%2 == 0); + + return answer; + } + +void CardinalityCounter::addElement(uint64_t hash) + { + uint64_t index = hash % m; + hash = hash-index; + + if(buckets[index] == 0) + V--; + + uint8_t temp = rank(hash); + + if (temp > buckets[index]) + buckets[index] = temp; +} + +double CardinalityCounter::size() + { + double answer = 0; + for (int i = 0; i < m; i++) + answer += pow(2, -(int)buckets[i]); + + answer = 1/answer; + answer = alpha_m*m*m*answer; + + if (answer <= 5*(double)(m/2)) + return m*log((double) m/V); + else if(answer <= pow(2,64)/30) + return answer; + else + return -pow(2,64)*log(1-answer/pow(2,64)); +} + +void CardinalityCounter::merge(CardinalityCounter* c) + { + uint8_t* temp = (*c).getBuckets(); + V = 0; + for (int i = 0; i < m; i++) + { + if (temp[i] > buckets[i]) + buckets[i] = temp[i]; + + if (buckets[i] == 0) + V += 1; + } + } + +uint8_t* CardinalityCounter::getBuckets() + { + return buckets; + } + +uint64_t CardinalityCounter::getM() + { + return m; + } diff --git a/src/HyperLogLog.h b/src/HyperLogLog.h index ba9a46f1bd..81c19067a1 100644 --- a/src/HyperLogLog.h +++ b/src/HyperLogLog.h @@ -1,3 +1,5 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include /* From 53d6f3aae70a770c977dcbf97d98b9ed4d267058 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Sun, 7 Apr 2013 23:05:14 +0200 Subject: [PATCH 058/881] rework cardinality interface to use opaque. I like it better... --- src/OpaqueVal.cc | 22 +++ src/OpaqueVal.h | 18 +++ src/bro.bif | 207 ++++++++----------------- testing/btest/bifs/hll_cardinality.bro | 145 ++++++----------- 4 files changed, 147 insertions(+), 245 deletions(-) diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 51f975edf8..604ce2938e 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -2,6 +2,28 @@ #include "Reporter.h" #include "Serializer.h" + +CardinalityVal::CardinalityVal() + { + valid = false; + } + +CardinalityVal::~CardinalityVal() + { + if ( valid && c ) + delete c; + } + +bool CardinalityVal::Init(CardinalityCounter* arg_c) + { + if ( valid ) + return false; + + valid = true; + c = arg_c; + return valid; + } + bool HashVal::IsValid() const { return valid; diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index 0428e50bdb..01f86529c7 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -7,6 +7,24 @@ #include "Val.h" #include "digest.h" +class CardinalityCounter; + +class CardinalityVal: public OpaqueVal { +public: + CardinalityVal(); + ~CardinalityVal(); + bool Init(CardinalityCounter*); + bool IsValid() const { return valid; }; + CardinalityCounter* Get() { return c; }; + +private: + bool valid; + CardinalityCounter* c; + +// DECLARE_SERIAL(CardinalityVal); Fixme? +}; + + class HashVal : public OpaqueVal { public: virtual bool IsValid() const; diff --git a/src/bro.bif b/src/bro.bif index 13e0d6e407..6e39ee16b0 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5650,44 +5650,36 @@ function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr %%{ #include "HyperLogLog.h" -static map hll_counters; - -BroString* convert_index_to_string(Val* index) - { - ODesc d; - index->Describe(&d); - BroString* s = new BroString(1, d.TakeBytes(), d.Len()); - s->SetUseFreeToDelete(1); - return s; - } %%} ## Initializes the hash for the HyperLogLog cardinality counting algorithm. ## It returns true if it was successful in creating a structure and false ## if it wasn't. -function hll_cardinality_init%(err: double,index: any%): bool +function hll_cardinality_init%(err: double%): opaque of cardinality %{ - BroString* s = convert_index_to_string(index); - int status = 0; + CardinalityCounter* c = new CardinalityCounter(err); + CardinalityVal* cv = new CardinalityVal(); - if ( hll_counters.count(*s) < 1 ) - { - hll_counters[*s] = new CardinalityCounter(err); - status = 1; - } + if ( !c ) + reporter->Error("Failed initialize Cardinality counter"); + else + cv->Init(c); - delete s; - return new Val(status, TYPE_BOOL); + return cv; %} ## Adds an element to the HyperLogLog data structure located at index. ##elem->Type() to get the type of elem. -function hll_cardinality_add%(elem: any, index: any%): bool +function hll_cardinality_add%(handle: opaque of cardinality, elem: any%): bool %{ - BroString* s = convert_index_to_string(index); + if ( !((CardinalityVal*) handle)->IsValid() ) { + reporter->Error("Need valid handle"); + return new Val(0, TYPE_BOOL); + } + int status = 0; uint64_t a = 123456; @@ -5696,19 +5688,13 @@ function hll_cardinality_add%(elem: any, index: any%): bool CompositeHash* hll_hash = new CompositeHash(tl); Unref(tl); - if( hll_counters.count(*s) > 0 ) - { - CardinalityCounter* h = hll_counters[*s]; - HashKey* key = hll_hash->ComputeHash(elem, 1); - a = key->Hash(); - h->addElement(a); - status = 1; - delete key; - } + CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); + HashKey* key = hll_hash->ComputeHash(elem, 1); + a = key->Hash(); + h->addElement(a); delete hll_hash; - delete s; - return new Val(status, TYPE_BOOL); + return new Val(1, TYPE_BOOL); %} ## The data structure at index1 will contain the combined count for the @@ -5716,135 +5702,68 @@ function hll_cardinality_add%(elem: any, index: any%): bool ## It returns true if it either cloned the value at index2 into index1 ## or if it merged the two data structures together. -function hll_cardinality_merge_into%(index1: any, index2: any%): bool +function hll_cardinality_merge_into%(handle1: opaque of cardinality, handle2: opaque of cardinality%): bool %{ - BroString* s1 = convert_index_to_string(index1); - BroString* s2 = convert_index_to_string(index2); - int status = 0; + CardinalityVal* v1 = (CardinalityVal*) handle1; + CardinalityVal* v2 = (CardinalityVal*) handle2; - if(hll_counters.count(*s1) < 1) - { - if(hll_counters.count(*s2) < 1) - { - status = 0; - } - else - { - uint64_t m = (*hll_counters[*s2]).getM(); - CardinalityCounter* newInst = new CardinalityCounter(m); - hll_counters[*s1] = newInst; - (*newInst).merge(hll_counters[*s2]); - status = 1; - } - } - else - { - if(hll_counters.count(*s2) < 1) - { - status = 0; - } - else - { - if((*hll_counters[*s2]).getM() == (*hll_counters[*s1]).getM()) - { - status = 1; - (*hll_counters[*s1]).merge(hll_counters[*s2]); - } - } - } + if ( !v1->IsValid() || !v2->IsValid() ) { + reporter->Error("need valid handles"); + return new Val(0, TYPE_BOOL); + } - delete s1; - delete s2; - return new Val(status, TYPE_BOOL); + CardinalityCounter* h1 = v1->Get(); + CardinalityCounter* h2 = v2->Get(); + h1->merge(h2); + + return new Val(1, TYPE_BOOL); %} ## Returns true if it destroyed something. False if it didn't. -function hll_cardinality_destroy%(index: any%): bool - %{ - BroString* s = convert_index_to_string(index); - int status = 0; - - if(hll_counters.count(*s) > 0) - { - hll_counters.erase(*s); - status = 1; - } - - delete s; - return new Val(status, TYPE_BOOL); - %} +#function hll_cardinality_destroy%(handle: opaque of cardinality%): bool +# %{ +# if ( !((CardinalityVal*) handle)->IsValid() ) { +# reporter->Error("Need valid handle"); +# return new Val(0, TYPE_BOOL); +# } +# CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); +# delete h; +# h = 0; +# return new Val(1, TYPE_BOOL); +# %} ## Returns the cardinality estimate. Returns -1.0 if there is nothing in that index. -function hll_cardinality_estimate%(index: any%): double +function hll_cardinality_estimate%(handle: opaque of cardinality%): double %{ - BroString* s = convert_index_to_string(index); - double estimate = -1.0; + if ( !((CardinalityVal*) handle)->IsValid() ) { + reporter->Error("Need valid handle"); + return new Val(0, TYPE_BOOL); + } + CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); - if(hll_counters.count(*s) > 0) - { - estimate = (*hll_counters[*s]).size(); - } + double estimate = h->size(); - delete s; return new Val(estimate, TYPE_DOUBLE); %} -##I'm really not sure about the notation of this function... - -function hll_cardinality_keys%(%): string_set - %{ - TableVal* a = new TableVal(string_set); - map::iterator it; - int i = 0; - - for(it = hll_counters.begin() ; it != hll_counters.end(); it++) - { - BroString* s = (BroString*) &(it->first); - a->Assign(new StringVal(s), 0); - } - return a; - %} - ## Stores the data structure at index2 into index1. Deletes the data structure at index1 ## if there was any. Returns True if the data structure at index1 was changed in any way. -function hll_cardinality_clone%(index1: any, index2: any%): bool +function hll_cardinality_clone%(handle: opaque of cardinality%): opaque of cardinality %{ - BroString* s1 = convert_index_to_string(index1); - BroString* s2 = convert_index_to_string(index2); - int status = 0; + if ( !((CardinalityVal*) handle)->IsValid() ) { + reporter->Error("Need valid handle"); + return new Val(0, TYPE_BOOL); + } + CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); - if(hll_counters.count(*s2) < 1) - { - if(hll_counters.count(*s1) < 1) - { - status = 0; - } - else - { - delete hll_counters[*s1]; - status = 1; - } - } - else - { - uint64_t m = (*hll_counters[*s2]).getM(); - CardinalityCounter* newInst = new CardinalityCounter(m); - int i = 0; - (*newInst).merge(hll_counters[*s2]); - if(hll_counters.count(*s1) < 1) - { - hll_counters[*s1] = newInst; - } - else - { - delete hll_counters[*s1]; - hll_counters[*s1] = newInst; - } - status = 1; - } - delete s1; - delete s2; - return new Val(status, TYPE_BOOL); + + uint64_t m = h->getM(); + CardinalityCounter* h2 = new CardinalityCounter(m); + int i = 0; + h2->merge(h); + CardinalityVal* cv = new CardinalityVal(); + cv->Init(h2); + return cv; %} diff --git a/testing/btest/bifs/hll_cardinality.bro b/testing/btest/bifs/hll_cardinality.bro index 093de134df..774e8f6e28 100644 --- a/testing/btest/bifs/hll_cardinality.bro +++ b/testing/btest/bifs/hll_cardinality.bro @@ -4,135 +4,78 @@ event bro_init() { - local m1 = "measurement1"; - local m2 = "measurement2"; - - print "This value should be true:"; - print hll_cardinality_init(0.01, m1); - hll_cardinality_init(0.01, m2); - - print "This value should be false:"; - print hll_cardinality_init(0.02, "measurement1"); + local c1 = hll_cardinality_init(0.01); + local c2 = hll_cardinality_init(0.01); local add1 = "hey"; local add2 = "hi"; local add3 = 123; - hll_cardinality_add(add1, m1); - hll_cardinality_add(add2, m1); - hll_cardinality_add(add3, m1); - hll_cardinality_add("a", m1); - hll_cardinality_add("b", m1); - hll_cardinality_add("c", m1); - hll_cardinality_add("d", m1); - hll_cardinality_add("e", m1); - hll_cardinality_add("f", m1); - hll_cardinality_add("g", m1); - hll_cardinality_add("h", m1); - hll_cardinality_add("i", m1); + hll_cardinality_add(c1, add1); + hll_cardinality_add(c1, add2); + hll_cardinality_add(c1, add3); + hll_cardinality_add(c1, "a"); + hll_cardinality_add(c1, "b"); + hll_cardinality_add(c1, "c"); + hll_cardinality_add(c1, "d"); + hll_cardinality_add(c1, "e"); + hll_cardinality_add(c1, "f"); + hll_cardinality_add(c1, "g"); + hll_cardinality_add(c1, "h"); + hll_cardinality_add(c1, "i"); + hll_cardinality_add(c1, "j"); - print "This value should be true:"; - print hll_cardinality_add("j", m1); - - print "This value should be false:"; - print hll_cardinality_add("asdf", "something"); - - - hll_cardinality_add(add1, m2); - hll_cardinality_add(add2, m2); - hll_cardinality_add(add3, m2); - hll_cardinality_add(1, m2); - hll_cardinality_add("b", m2); - hll_cardinality_add(2, m2); - hll_cardinality_add(3, m2); - hll_cardinality_add(4, m2); - hll_cardinality_add(5, m2); - hll_cardinality_add(6, m2); - hll_cardinality_add(7, m2); - hll_cardinality_add(8, m2); + hll_cardinality_add(c2, add1); + hll_cardinality_add(c2, add2); + hll_cardinality_add(c2, add3); + hll_cardinality_add(c2, 1); + hll_cardinality_add(c2, "b"); + hll_cardinality_add(c2, 2); + hll_cardinality_add(c2, 3); + hll_cardinality_add(c2, 4); + hll_cardinality_add(c2, 5); + hll_cardinality_add(c2, 6); + hll_cardinality_add(c2, 7); + hll_cardinality_add(c2, 8); print "This value should be around 13:"; - print hll_cardinality_estimate("measurement1"); + print hll_cardinality_estimate(c1); - print "This value should be -1.0:"; - print hll_cardinality_estimate("m2"); + print "This value should be about 12:"; + print hll_cardinality_estimate(c2); - hll_cardinality_init(0.02, "m2"); + local m2 = hll_cardinality_init(0.02); print "This value should be around 0:"; - print hll_cardinality_estimate("m2"); + print hll_cardinality_estimate(m2); - print "This value should be true:"; - print hll_cardinality_destroy("m2"); - - print "This value should be false:"; - print hll_cardinality_destroy("m2"); - - print "This value should be -1.0:"; - print hll_cardinality_estimate("m2"); - - print "This next thing should be false:"; - print hll_cardinality_clone("m3", "m2"); - - print "This next thing should be true:"; - print hll_cardinality_clone("measurement3", "measurement1"); + local c3 = hll_cardinality_clone(c1); print "This value should be around 13:"; - print hll_cardinality_estimate("measurement3"); + print hll_cardinality_estimate(c3); - hll_cardinality_destroy("measurement3"); - - print "This next thing should be equal to -1.0:"; - print hll_cardinality_estimate("measurement3"); - - print "This value should be around 13:"; - print hll_cardinality_estimate("measurement1"); + c3 = hll_cardinality_init(0.01); + print "This value should be 0:"; + print hll_cardinality_estimate(c3); print "This value should be true:"; - print hll_cardinality_merge_into("measurement3", "measurement2"); - - print "This value should be false:"; - print hll_cardinality_merge_into("measurement4", "measurement6"); + print hll_cardinality_merge_into(c3, c2); print "This value should be about 12:"; - print hll_cardinality_estimate("measurement3"); - - print "This value should be false:"; - print hll_cardinality_merge_into("measurement3", "measurement15"); - - print "This value should be about 12:"; - print hll_cardinality_estimate("measurement3"); + print hll_cardinality_estimate(c2); + print hll_cardinality_estimate(c3); print "This value should be true:"; - print hll_cardinality_merge_into("measurement2", "measurement1"); + print hll_cardinality_merge_into(c2, c1); print "This value should be about 21:"; - print hll_cardinality_estimate("measurement2"); + print hll_cardinality_estimate(c2); print "This value should be about 13:"; - print hll_cardinality_estimate("measurement1"); + print hll_cardinality_estimate(c1); print "This value should be about 12:"; - print hll_cardinality_estimate("measurement3"); + print hll_cardinality_estimate(c3); - local keys = hll_cardinality_keys(); - for(key in keys) - { - print "The key is:"; - print key; - print "The value is:"; - print hll_cardinality_estimate(key); - } } -#function hll_cardinality_keys%(%): bool -# %{ -#// TableVal* a = new TableVal(string_set); -#// map::iterator it; -# -#// for(it = hll_counters.begin() ; it != hll_counters.end(); it++) -#// { -#// a->Assign((*it).first); -#// } -#// return a; -# return new Val(1, TYPE_BOOL); From 7f5e2b130172c3c6350fbbc188d57d5e44bfd3ad Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 8 Apr 2013 09:44:24 +0200 Subject: [PATCH 059/881] and test results. are those stable accross platforms? Or do we have to do some kind of rounding? --- .../btest/Baseline/bifs.hll_cardinality/out | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 testing/btest/Baseline/bifs.hll_cardinality/out diff --git a/testing/btest/Baseline/bifs.hll_cardinality/out b/testing/btest/Baseline/bifs.hll_cardinality/out new file mode 100644 index 0000000000..8d20248cc3 --- /dev/null +++ b/testing/btest/Baseline/bifs.hll_cardinality/out @@ -0,0 +1,23 @@ +This value should be around 13: +13.00129 +This value should be about 12: +12.001099 +This value should be around 0: +0.0 +This value should be around 13: +13.00129 +This value should be 0: +0.0 +This value should be true: +T +This value should be about 12: +12.001099 +12.001099 +This value should be true: +T +This value should be about 21: +21.003365 +This value should be about 13: +13.00129 +This value should be about 12: +12.001099 From 7eee2f0d17d7b51dcd893a0cacb87474112a4fb3 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 8 Apr 2013 10:00:34 +0200 Subject: [PATCH 060/881] measurement framework with hll unique --- scripts/base/frameworks/measurement/plugins/__load__.bro | 3 ++- .../scripts.base.frameworks.measurement.basic/.stdout | 6 +++--- testing/btest/scripts/base/frameworks/measurement/basic.bro | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/base/frameworks/measurement/plugins/__load__.bro b/scripts/base/frameworks/measurement/plugins/__load__.bro index 0d4c2ed302..0a51a081a9 100644 --- a/scripts/base/frameworks/measurement/plugins/__load__.bro +++ b/scripts/base/frameworks/measurement/plugins/__load__.bro @@ -5,4 +5,5 @@ @load ./std-dev @load ./sum @load ./unique -@load ./variance \ No newline at end of file +@load ./variance +@load ./hll_unique diff --git a/testing/btest/Baseline/scripts.base.frameworks.measurement.basic/.stdout b/testing/btest/Baseline/scripts.base.frameworks.measurement.basic/.stdout index 208b6103b7..5f1c5ab5e4 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.measurement.basic/.stdout +++ b/testing/btest/Baseline/scripts.base.frameworks.measurement.basic/.stdout @@ -1,3 +1,3 @@ -Host: 6.5.4.3 - num:1 - sum:2.0 - var:0.0 - avg:2.0 - max:2.0 - min:2.0 - std_dev:0.0 - unique:1 -Host: 1.2.3.4 - num:5 - sum:221.0 - var:1144.2 - avg:44.2 - max:94.0 - min:5.0 - std_dev:33.8 - unique:4 -Host: 7.2.1.5 - num:1 - sum:1.0 - var:0.0 - avg:1.0 - max:1.0 - min:1.0 - std_dev:0.0 - unique:1 +Host: 6.5.4.3 - num:1 - sum:2.0 - var:0.0 - avg:2.0 - max:2.0 - min:2.0 - std_dev:0.0 - unique:1 - hllunique:1.0 +Host: 1.2.3.4 - num:5 - sum:221.0 - var:1144.2 - avg:44.2 - max:94.0 - min:5.0 - std_dev:33.8 - unique:4 - hllunique:4.0 +Host: 7.2.1.5 - num:1 - sum:1.0 - var:0.0 - avg:1.0 - max:1.0 - min:1.0 - std_dev:0.0 - unique:1 - hllunique:1.0 diff --git a/testing/btest/scripts/base/frameworks/measurement/basic.bro b/testing/btest/scripts/base/frameworks/measurement/basic.bro index e9dd21e0ef..4706a7c9b1 100644 --- a/testing/btest/scripts/base/frameworks/measurement/basic.bro +++ b/testing/btest/scripts/base/frameworks/measurement/basic.bro @@ -10,7 +10,8 @@ event bro_init() &priority=5 Measurement::MAX, Measurement::MIN, Measurement::STD_DEV, - Measurement::UNIQUE)]; + Measurement::UNIQUE, + Measurement::HLLUNIQUE)]; Measurement::create([$epoch=3secs, $reducers=set(r1), $epoch_finished(data: Measurement::ResultTable) = @@ -18,7 +19,7 @@ event bro_init() &priority=5 for ( key in data ) { local r = data[key]["test.metric"]; - print fmt("Host: %s - num:%d - sum:%.1f - var:%.1f - avg:%.1f - max:%.1f - min:%.1f - std_dev:%.1f - unique:%d", key$host, r$num, r$sum, r$variance, r$average, r$max, r$min, r$std_dev, r$unique); + print fmt("Host: %s - num:%d - sum:%.1f - var:%.1f - avg:%.1f - max:%.1f - min:%.1f - std_dev:%.1f - unique:%d - hllunique:%.1f", key$host, r$num, r$sum, r$variance, r$average, r$max, r$min, r$std_dev, r$unique, hll_cardinality_estimate(r$hllunique)); } } ]); From ac0e211c6cb02e1160fc7153d5e25111acdb4ebd Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 8 Apr 2013 10:01:55 +0200 Subject: [PATCH 061/881] do away with old file. --- mytests.bro | 134 ---------------------------------------------------- 1 file changed, 134 deletions(-) delete mode 100644 mytests.bro diff --git a/mytests.bro b/mytests.bro deleted file mode 100644 index 9392b205b0..0000000000 --- a/mytests.bro +++ /dev/null @@ -1,134 +0,0 @@ -event bro_init() - { - local m1 = "measurement1"; - local m2 = "measurement2"; - - print "This value should be true:"; - print hll_cardinality_init(0.01, m1); - hll_cardinality_init(0.01, m2); - - print "This value should be false:"; - print hll_cardinality_init(0.02, "measurement1"); - - local add1 = "hey"; - local add2 = "hi"; - local add3 = 123; - - hll_cardinality_add(add1, m1); - hll_cardinality_add(add2, m1); - hll_cardinality_add(add3, m1); - hll_cardinality_add("a", m1); - hll_cardinality_add("b", m1); - hll_cardinality_add("c", m1); - hll_cardinality_add("d", m1); - hll_cardinality_add("e", m1); - hll_cardinality_add("f", m1); - hll_cardinality_add("g", m1); - hll_cardinality_add("h", m1); - hll_cardinality_add("i", m1); - - print "This value should be true:"; - print hll_cardinality_add("j", m1); - - print "This value should be false:"; - print hll_cardinality_add("asdf", "something"); - - - hll_cardinality_add(add1, m2); - hll_cardinality_add(add2, m2); - hll_cardinality_add(add3, m2); - hll_cardinality_add(1, m2); - hll_cardinality_add("b", m2); - hll_cardinality_add(2, m2); - hll_cardinality_add(3, m2); - hll_cardinality_add(4, m2); - hll_cardinality_add(5, m2); - hll_cardinality_add(6, m2); - hll_cardinality_add(7, m2); - hll_cardinality_add(8, m2); - - print "This value should be around 13:"; - print hll_cardinality_estimate("measurement1"); - - print "This value should be -1.0:"; - print hll_cardinality_estimate("m2"); - - hll_cardinality_init(0.02, "m2"); - - print "This value should be around 0:"; - print hll_cardinality_estimate("m2"); - - print "This value should be true:"; - print hll_cardinality_destroy("m2"); - - print "This value should be false:"; - print hll_cardinality_destroy("m2"); - - print "This value should be -1.0:"; - print hll_cardinality_estimate("m2"); - - print "This next thing should be false:"; - print hll_cardinality_clone("m3", "m2"); - - print "This next thing should be true:"; - print hll_cardinality_clone("measurement3", "measurement1"); - - print "This value should be around 13:"; - print hll_cardinality_estimate("measurement3"); - - hll_cardinality_destroy("measurement3"); - - print "This next thing should be equal to -1.0:"; - print hll_cardinality_estimate("measurement3"); - - print "This value should be around 13:"; - print hll_cardinality_estimate("measurement1"); - - print "This value should be true:"; - print hll_cardinality_merge_into("measurement3", "measurement2"); - - print "This value should be false:"; - print hll_cardinality_merge_into("measurement4", "measurement6"); - - print "This value should be about 12:"; - print hll_cardinality_estimate("measurement3"); - - print "This value should be false:"; - print hll_cardinality_merge_into("measurement3", "measurement15"); - - print "This value should be about 12:"; - print hll_cardinality_estimate("measurement3"); - - print "This value should be true:"; - print hll_cardinality_merge_into("measurement2", "measurement1"); - - print "This value should be about 21:"; - print hll_cardinality_estimate("measurement2"); - - print "This value should be about 13:"; - print hll_cardinality_estimate("measurement1"); - - print "This value should be about 12:"; - print hll_cardinality_estimate("measurement3"); - - local keys = hll_cardinality_keys(); - for(key in keys) - { - print "The key is:"; - print key; - print "The value is:"; - print hll_cardinality_estimate(key); - } - } - -#function hll_cardinality_keys%(%): bool -# %{ -#// TableVal* a = new TableVal(string_set); -#// map::iterator it; -# -#// for(it = hll_counters.begin() ; it != hll_counters.end(); it++) -#// { -#// a->Assign((*it).first); -#// } -#// return a; -# return new Val(1, TYPE_BOOL); From bcd610fd50252b2095639e0d5821af1088e36325 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 8 Apr 2013 10:55:00 +0200 Subject: [PATCH 062/881] Forgot a file. Again. Like always. Basically. --- .../measurement/plugins/hll_unique.bro | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 scripts/base/frameworks/measurement/plugins/hll_unique.bro diff --git a/scripts/base/frameworks/measurement/plugins/hll_unique.bro b/scripts/base/frameworks/measurement/plugins/hll_unique.bro new file mode 100644 index 0000000000..0e95e6fcdd --- /dev/null +++ b/scripts/base/frameworks/measurement/plugins/hll_unique.bro @@ -0,0 +1,39 @@ + +module Measurement; + +export { + redef enum Calculation += { + ## Calculate the number of unique values. + HLLUNIQUE + }; + + redef record ResultVal += { + ## If cardinality is being tracked, the number of unique + ## items is tracked here. + hllunique: opaque of cardinality &default=hll_cardinality_init(0.01); + }; +} + +hook init_resultval_hook(r: Reducer, rv: ResultVal) + { + if ( HLLUNIQUE in r$apply && ! rv?$hllunique ) + rv$hllunique = hll_cardinality_init(0.01); + } + + +hook add_to_reducer_hook(r: Reducer, val: double, data: DataPoint, rv: ResultVal) + { + if ( HLLUNIQUE in r$apply ) + { + hll_cardinality_add(rv$hllunique, data); + } + } + +hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) + { + local rhll = hll_cardinality_init(0.01); + hll_cardinality_merge_into(rhll, rv1$hllunique); + hll_cardinality_merge_into(rhll, rv2$hllunique); + + result$hllunique = rhll; + } From f10ed9e29a6abf56e8110e2cc400f8e796e4c07a Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 10 Apr 2013 10:45:45 -0400 Subject: [PATCH 063/881] change plugin after feedback of seth --- .../measurement/plugins/hll_unique.bro | 25 +++++++++++++------ .../base/frameworks/measurement/basic.bro | 2 +- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/scripts/base/frameworks/measurement/plugins/hll_unique.bro b/scripts/base/frameworks/measurement/plugins/hll_unique.bro index 0e95e6fcdd..ccdb872606 100644 --- a/scripts/base/frameworks/measurement/plugins/hll_unique.bro +++ b/scripts/base/frameworks/measurement/plugins/hll_unique.bro @@ -10,14 +10,23 @@ export { redef record ResultVal += { ## If cardinality is being tracked, the number of unique ## items is tracked here. - hllunique: opaque of cardinality &default=hll_cardinality_init(0.01); + hllunique: count &default=0; }; } +redef record ResultVal += { + # Internal use only. This is not meant to be publically available + # because probabilistic data structures have to be examined using + # specialized bifs. + card: opaque of cardinality &default=hll_cardinality_init(0.01); +}; + + hook init_resultval_hook(r: Reducer, rv: ResultVal) { - if ( HLLUNIQUE in r$apply && ! rv?$hllunique ) - rv$hllunique = hll_cardinality_init(0.01); + if ( HLLUNIQUE in r$apply && ! rv?$card ) + rv$card = hll_cardinality_init(0.01); + rv$hllunique = 0; } @@ -25,15 +34,17 @@ hook add_to_reducer_hook(r: Reducer, val: double, data: DataPoint, rv: ResultVal { if ( HLLUNIQUE in r$apply ) { - hll_cardinality_add(rv$hllunique, data); + hll_cardinality_add(rv$card, data); + rv$hllunique = double_to_count(hll_cardinality_estimate(rv$card)); } } hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { local rhll = hll_cardinality_init(0.01); - hll_cardinality_merge_into(rhll, rv1$hllunique); - hll_cardinality_merge_into(rhll, rv2$hllunique); + hll_cardinality_merge_into(rhll, rv1$card); + hll_cardinality_merge_into(rhll, rv2$card); - result$hllunique = rhll; + result$card = rhll; + result$hllunique = double_to_count(hll_cardinality_estimate(rhll)); } diff --git a/testing/btest/scripts/base/frameworks/measurement/basic.bro b/testing/btest/scripts/base/frameworks/measurement/basic.bro index 4706a7c9b1..701b79fbb3 100644 --- a/testing/btest/scripts/base/frameworks/measurement/basic.bro +++ b/testing/btest/scripts/base/frameworks/measurement/basic.bro @@ -19,7 +19,7 @@ event bro_init() &priority=5 for ( key in data ) { local r = data[key]["test.metric"]; - print fmt("Host: %s - num:%d - sum:%.1f - var:%.1f - avg:%.1f - max:%.1f - min:%.1f - std_dev:%.1f - unique:%d - hllunique:%.1f", key$host, r$num, r$sum, r$variance, r$average, r$max, r$min, r$std_dev, r$unique, hll_cardinality_estimate(r$hllunique)); + print fmt("Host: %s - num:%d - sum:%.1f - var:%.1f - avg:%.1f - max:%.1f - min:%.1f - std_dev:%.1f - unique:%d - hllunique:%d", key$host, r$num, r$sum, r$variance, r$average, r$max, r$min, r$std_dev, r$unique, r$hllunique); } } ]); From a37ffab0ea6a2780469be2e6001709748f1034e7 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 10 Apr 2013 13:15:31 -0400 Subject: [PATCH 064/881] serialization compiles. Not entirely sure if it works too... --- src/HyperLogLog.h | 3 +++ src/OpaqueVal.cc | 46 +++++++++++++++++++++++++++++++++++++- src/OpaqueVal.h | 6 ++--- src/SerialTypes.h | 1 + src/SerializationFormat.cc | 30 +++++++++++++++++++++++++ src/SerializationFormat.h | 6 +++++ src/Serializer.h | 1 + 7 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/HyperLogLog.h b/src/HyperLogLog.h index 81c19067a1..34a2afd9b7 100644 --- a/src/HyperLogLog.h +++ b/src/HyperLogLog.h @@ -10,7 +10,10 @@ */ #define conf .95 +class CardinalityVal; + class CardinalityCounter { + friend class CardinalityVal; private: /* diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 604ce2938e..d1d97c1f8c 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -1,9 +1,10 @@ #include "OpaqueVal.h" #include "Reporter.h" #include "Serializer.h" +#include "HyperLogLog.h" -CardinalityVal::CardinalityVal() +CardinalityVal::CardinalityVal() : OpaqueVal(new OpaqueType("cardinality")) { valid = false; } @@ -14,6 +15,49 @@ CardinalityVal::~CardinalityVal() delete c; } +IMPLEMENT_SERIAL(CardinalityVal, SER_CARDINALITY_VAL); + +bool CardinalityVal::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_CARDINALITY_VAL, OpaqueVal); + + if ( ! IsValid() ) + return true; + + assert(c); + + bool valid = true; + + valid &= SERIALIZE(c->m); + for ( int i = 0; i < c->m; i++ ) + { + valid &= SERIALIZE(c->buckets[i]); + } + + return valid; + } + +bool CardinalityVal::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(OpaqueVal); + + if ( ! IsValid() ) + return true; + + uint64_t m; + bool valid = UNSERIALIZE(&m); + + c = new CardinalityCounter(m); + uint8_t* buckets = c->buckets; + for ( int i = 0; i < m; i++ ) + { + uint8_t* currbucket = buckets + i; + valid &= UNSERIALIZE( currbucket ); + } + + return valid; + } + bool CardinalityVal::Init(CardinalityCounter* arg_c) { if ( valid ) diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index 01f86529c7..1bdd842cad 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -11,17 +11,17 @@ class CardinalityCounter; class CardinalityVal: public OpaqueVal { public: - CardinalityVal(); - ~CardinalityVal(); bool Init(CardinalityCounter*); bool IsValid() const { return valid; }; CardinalityCounter* Get() { return c; }; + CardinalityVal(); + ~CardinalityVal(); private: bool valid; CardinalityCounter* c; -// DECLARE_SERIAL(CardinalityVal); Fixme? + DECLARE_SERIAL(CardinalityVal); }; diff --git a/src/SerialTypes.h b/src/SerialTypes.h index 723badab1e..56a1c5e8dd 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -104,6 +104,7 @@ SERIAL_VAL(MD5_VAL, 16) SERIAL_VAL(SHA1_VAL, 17) SERIAL_VAL(SHA256_VAL, 18) SERIAL_VAL(ENTROPY_VAL, 19) +SERIAL_VAL(CARDINALITY_VAL, 20) #define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR) SERIAL_EXPR(EXPR, 1) diff --git a/src/SerializationFormat.cc b/src/SerializationFormat.cc index 10dd4f29ea..271163d5db 100644 --- a/src/SerializationFormat.cc +++ b/src/SerializationFormat.cc @@ -107,6 +107,16 @@ bool BinarySerializationFormat::Read(int* v, const char* tag) return true; } +bool BinarySerializationFormat::Read(uint8* v, const char* tag) + { + if ( ! ReadData(v, sizeof(*v)) ) + return false; + + *v = ntohs(*v); + DBG_LOG(DBG_SERIAL, "Read uint8 %hu [%s]", *v, tag); + return true; + } + bool BinarySerializationFormat::Read(uint16* v, const char* tag) { if ( ! ReadData(v, sizeof(*v)) ) @@ -301,6 +311,13 @@ bool BinarySerializationFormat::Write(char v, const char* tag) return WriteData(&v, 1); } +bool BinarySerializationFormat::Write(uint8 v, const char* tag) + { + DBG_LOG(DBG_SERIAL, "Write uint8 %hu [%s]", v, tag); + v = htons(v); + return WriteData(&v, sizeof(v)); + } + bool BinarySerializationFormat::Write(uint16 v, const char* tag) { DBG_LOG(DBG_SERIAL, "Write uint16 %hu [%s]", v, tag); @@ -447,6 +464,12 @@ bool XMLSerializationFormat::Read(int* v, const char* tag) return false; } +bool XMLSerializationFormat::Read(uint8* v, const char* tag) + { + reporter->InternalError("no reading of xml"); + return false; + } + bool XMLSerializationFormat::Read(uint16* v, const char* tag) { reporter->InternalError("no reading of xml"); @@ -530,6 +553,13 @@ bool XMLSerializationFormat::Write(char v, const char* tag) return WriteElem(tag, "char", &v, 1); } +bool XMLSerializationFormat::Write(uint8 v, const char* tag) + { + const char* tmp = fmt("%" PRIu8, v); + return WriteElem(tag, "uint8", tmp, strlen(tmp)); + } + + bool XMLSerializationFormat::Write(uint16 v, const char* tag) { const char* tmp = fmt("%" PRIu16, v); diff --git a/src/SerializationFormat.h b/src/SerializationFormat.h index f270b61bae..05cf56d961 100644 --- a/src/SerializationFormat.h +++ b/src/SerializationFormat.h @@ -23,6 +23,7 @@ public: virtual void EndRead(); virtual bool Read(int* v, const char* tag) = 0; + virtual bool Read(uint8* v, const char* tag) = 0; virtual bool Read(uint16* v, const char* tag) = 0; virtual bool Read(uint32* v, const char* tag) = 0; virtual bool Read(int64* v, const char* tag) = 0; @@ -47,6 +48,7 @@ public: virtual uint32 EndWrite(char** data); // passes ownership virtual bool Write(int v, const char* tag) = 0; + virtual bool Write(uint8 v, const char* tag) = 0; virtual bool Write(uint16 v, const char* tag) = 0; virtual bool Write(uint32 v, const char* tag) = 0; virtual bool Write(int64 v, const char* tag) = 0; @@ -92,6 +94,7 @@ public: virtual ~BinarySerializationFormat(); virtual bool Read(int* v, const char* tag); + virtual bool Read(uint8* v, const char* tag); virtual bool Read(uint16* v, const char* tag); virtual bool Read(uint32* v, const char* tag); virtual bool Read(int64* v, const char* tag); @@ -106,6 +109,7 @@ public: virtual bool Read(struct in_addr* addr, const char* tag); virtual bool Read(struct in6_addr* addr, const char* tag); virtual bool Write(int v, const char* tag); + virtual bool Write(uint8 v, const char* tag); virtual bool Write(uint16 v, const char* tag); virtual bool Write(uint32 v, const char* tag); virtual bool Write(int64 v, const char* tag); @@ -132,6 +136,7 @@ public: // We don't write anything if tag is nil. virtual bool Write(int v, const char* tag); + virtual bool Write(uint8 v, const char* tag); virtual bool Write(uint16 v, const char* tag); virtual bool Write(uint32 v, const char* tag); virtual bool Write(int64 v, const char* tag); @@ -152,6 +157,7 @@ public: // Not implemented. virtual bool Read(int* v, const char* tag); + virtual bool Read(uint8* v, const char* tag); virtual bool Read(uint16* v, const char* tag); virtual bool Read(uint32* v, const char* tag); virtual bool Read(int64* v, const char* tag); diff --git a/src/Serializer.h b/src/Serializer.h index 72e0723880..719d4dc527 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -54,6 +54,7 @@ public: DECLARE_WRITE(type) DECLARE_IO(int) + DECLARE_IO(uint8) DECLARE_IO(uint16) DECLARE_IO(uint32) DECLARE_IO(int64) From 240d667e30568128422da75fc37a83c703635555 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 10 Apr 2013 13:45:21 -0400 Subject: [PATCH 065/881] ok, this bug was hard to find. hyperloglog.h was missing guards and randomly deleting memory at addresses equal to variable contents. I am not entirely sure why that did not crash before... --- src/HyperLogLog.cc | 5 +---- src/HyperLogLog.h | 11 ++++++++--- src/OpaqueVal.cc | 9 ++++++--- src/OpaqueVal.h | 4 ++-- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/HyperLogLog.cc b/src/HyperLogLog.cc index 436d754b4d..58cbd72e70 100644 --- a/src/HyperLogLog.cc +++ b/src/HyperLogLog.cc @@ -18,7 +18,7 @@ int CardinalityCounter::optimalB(double error) answer++; k = pow(2, (answer - initial_estimate)/2); } - while (erf(k/sqrt(2)) < conf); + while (erf(k/sqrt(2)) < HLL_CONF); return answer; } @@ -67,9 +67,6 @@ CardinalityCounter :: CardinalityCounter(double error_margin) CardinalityCounter::~CardinalityCounter() { delete [] buckets; - delete &m; - delete &V; - delete &alpha_m; } uint8_t CardinalityCounter::rank(uint64_t hash_modified) diff --git a/src/HyperLogLog.h b/src/HyperLogLog.h index 34a2afd9b7..68b7f0ecfc 100644 --- a/src/HyperLogLog.h +++ b/src/HyperLogLog.h @@ -1,16 +1,19 @@ // See the file "COPYING" in the main distribution directory for copyright. +#ifndef hyperloglog_h +#define hyperloglog_h + #include +#include /* * "conf" is how confident the estimate given by the counter is. * - * In other words, if the cardinality is estimated to be 100 with 2% error margin and conf is + * In other words, if the cardinality is estimated to be 100 with 2% error margin and HLL_CONFis * 0.95, then we are 95% sure that the actual cardinality is between 98 and 102. */ -#define conf .95 +#define HLL_CONF .95 -class CardinalityVal; class CardinalityCounter { friend class CardinalityVal; @@ -114,3 +117,5 @@ class CardinalityCounter { */ uint64_t getM(); }; + +#endif diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index d1d97c1f8c..4e8b0744f9 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -11,14 +11,16 @@ CardinalityVal::CardinalityVal() : OpaqueVal(new OpaqueType("cardinality")) CardinalityVal::~CardinalityVal() { - if ( valid && c ) + if ( valid && c != 0 ) delete c; + c = 0; + valid = false; } - IMPLEMENT_SERIAL(CardinalityVal, SER_CARDINALITY_VAL); bool CardinalityVal::DoSerialize(SerialInfo* info) const { + printf("Serializing\n"); DO_SERIALIZE(SER_CARDINALITY_VAL, OpaqueVal); if ( ! IsValid() ) @@ -39,6 +41,7 @@ bool CardinalityVal::DoSerialize(SerialInfo* info) const bool CardinalityVal::DoUnserialize(UnserialInfo* info) { + printf("Unserializing\n"); DO_UNSERIALIZE(OpaqueVal); if ( ! IsValid() ) @@ -56,7 +59,7 @@ bool CardinalityVal::DoUnserialize(UnserialInfo* info) } return valid; - } + } bool CardinalityVal::Init(CardinalityCounter* arg_c) { diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index 1bdd842cad..dd70eaf96b 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -11,11 +11,11 @@ class CardinalityCounter; class CardinalityVal: public OpaqueVal { public: + CardinalityVal(); + ~CardinalityVal(); bool Init(CardinalityCounter*); bool IsValid() const { return valid; }; CardinalityCounter* Get() { return c; }; - CardinalityVal(); - ~CardinalityVal(); private: bool valid; From 5291bb29f2c50732d620a1b98aac7c4d4f983588 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 10 Apr 2013 16:05:24 -0400 Subject: [PATCH 066/881] and also serialize the other things we need --- src/OpaqueVal.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 4e8b0744f9..90230c37fe 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -31,6 +31,8 @@ bool CardinalityVal::DoSerialize(SerialInfo* info) const bool valid = true; valid &= SERIALIZE(c->m); + valid &= SERIALIZE(c->V); + valid &= SERIALIZE(c->alpha_m); for ( int i = 0; i < c->m; i++ ) { valid &= SERIALIZE(c->buckets[i]); @@ -51,6 +53,9 @@ bool CardinalityVal::DoUnserialize(UnserialInfo* info) bool valid = UNSERIALIZE(&m); c = new CardinalityCounter(m); + valid &= UNSERIALIZE(&c->V); + valid &= UNSERIALIZE(&c->alpha_m); + uint8_t* buckets = c->buckets; for ( int i = 0; i < m; i++ ) { From d7d33db8ec82d12b03f58ef9db04ed59086ccff8 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 15 Apr 2013 23:26:04 -0400 Subject: [PATCH 067/881] Initial commit to include the Notice Framework in the User Manual. --- doc/scripting/index.rst | 47 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 9ef8e8f8f3..6661a20f43 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -501,3 +501,50 @@ Telling Bro to raise an event in your own Logging stream is as simple as exporti :language: bro :linenos: :lines: 4-62 + + +Notice Framework +================ + +While Bro's Logging Framework provides an easy and systematic way to generate logs, there still exists a need to indicate when a specific behavior has been detected and a method to allow that detection to come to someone's attention. To that end, the Notice Framework is in place to allow script writers a codified means through which they can raise a notice and a system through which an operator can opt-in to receive the notice. Bro holds to the philosophy that it is up to the individual operator to indicate the behaviors in which they are interested and as such Bro ships with a large number of policy scripts which detect behavior that may be of interest but it does not presume to guess as to which behaviors are "action-able". In effect, Bro works to separate the act of detection and the responsibility of reporting. With the Notice Framework it's simple to raise a notice for any behavior that is detected. + +To raise a notice in Bro, you only need to indicate to Bro that you are provide a specific ``Notice::Type`` by exporting it and then make a call to ``NOTICE()`` supplying it with an appropriate ``Notice::Info`` record. Often times the call to ``NOTICE()`` includes just the ``Notice::Type``, and a concise message. There are however, significantly more options available when raising notices as seen in the table below. The only field in the table below whose attributes make it a required field is the ``note`` field. Still, good manners are always important and including a concise message in ``$msg`` and, where necessary, the contents of the connection record in ``$conn`` along with the ``Notice::Type`` tend to comprise the minimum of information required for an notice to be considered useful. If the ``$conn`` variable is supplied the Notice Framework will auto-populate the ``$id`` and ``$src`` fields as well. Other fields that are commonly included, ``$identifier`` and ``$suppress_for`` are built around the automated suppression feature of the Notice Framework which we will cover shortly. + ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ +| Field | Type | Attributes | Use | +|=====================+==================================================================+================+========================================+ +| ts | time | &log &optional | The time of the notice | +| uid | string | &log &optional | A unique connection ID | +| id | conn_id | &log &optional | A 4-tuple to identify endpoints | +| conn | connection | &optional | Shorthand for the uid and id | +| iconn | icmp_conn | &optional | Shorthand for the uid and id | +| proto | transport_proto | &log &optional | Transport protocol | +| note | Notice::Type | &log | The Notice::Type of the notice | +| msg | string | &log &optional | Human readable message | +| sub | string | &log &optional | Human readable message | +| src | addr | &log &optional | Source address if no conn_id | +| dst | addr | &log &optional | Destination addr if no conn_id | +| p | port | &log &optional | Port if no conn_id | +| n | count | &log &optional | Count or status code | +| src_peer | event_peer | &log &optional | Peer that raised the notice | +| peer_descr | string | &log &optional | Text description of the src_peer | +| actions | set[Notice::Action] | &log &optional | Actions applied to the notice | +| policy_items | set[count] | &log &optional | Policy items that have been applied | +| email_body_sections | vector | &optinal | Body of the email for email notices. | +| email_delay_tokens | set[string] | &optional | Delay functionality for email notices. | +| identifier | string | &optional | A unique string identifier | +| suppress_for | interval | &log &optional | Length of time to suppress a notice. | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ + +One of the default policy scripts raises a notice when an SSH login has been heuristically detected and the originating hostname is one that would raise suspicion. Effectively, the script attempts to define a list of hosts from which you would never want to see SSH traffic originating, dns servers, mail servers, etc. To accomplish this, the script adhere's to the seperation of detection and reporting by detecting a behavior and raising a notice. Whether or not that notice is acted upon is decided by the local Notice Policy, but the script attempts to supply as much information as possible while staying concise. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssh/interesting-hostnames.bro + :language: bro + :linenos: + :lines: 1-46 + +While much of the script relates to the actual detection, the parts specific to the Notice Framework are actually quite interesting in themselves. On line 12 the script's ``export`` block adds the value ``SSH::Interesting_Hostname_Login`` to the enumerable constant ``Notice::Type`` to indicate to the Bro core that a new type of notice is being defined. The script then calls ``NOTICE()`` and defines the ``$note``, ``$msg``, ``$sub`` and ``$conn`` fields. Line 39 also includes a ternary if statement that modifies the ``$msg`` text depending on whether the host is a local address and whether it is the client or the server. This use of ``fmt()`` and a ternary operators is a concise way to lend readability to the notices that are generated without the need for branching ``if`` statements that each raise a specific notice. + + + + From 70c020e412e02e9b177863766340e3eb72f6cf3f Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 16 Apr 2013 05:16:32 -0700 Subject: [PATCH 068/881] well, with this commit synchronizing the data structure should work.. ...if we had consistent hashing. --- src/OpaqueVal.cc | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 90230c37fe..6d56f3ae71 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -20,47 +20,48 @@ IMPLEMENT_SERIAL(CardinalityVal, SER_CARDINALITY_VAL); bool CardinalityVal::DoSerialize(SerialInfo* info) const { - printf("Serializing\n"); DO_SERIALIZE(SER_CARDINALITY_VAL, OpaqueVal); + bool serialvalid = true; + serialvalid &= SERIALIZE(&valid); + if ( ! IsValid() ) - return true; + return serialvalid; assert(c); - bool valid = true; - - valid &= SERIALIZE(c->m); - valid &= SERIALIZE(c->V); - valid &= SERIALIZE(c->alpha_m); + serialvalid &= SERIALIZE(c->m); + serialvalid &= SERIALIZE(c->V); + serialvalid &= SERIALIZE(c->alpha_m); for ( int i = 0; i < c->m; i++ ) { - valid &= SERIALIZE(c->buckets[i]); + serialvalid &= SERIALIZE(c->buckets[i]); } - return valid; + return serialvalid; } bool CardinalityVal::DoUnserialize(UnserialInfo* info) { - printf("Unserializing\n"); DO_UNSERIALIZE(OpaqueVal); + bool serialvalid = UNSERIALIZE(&valid); + if ( ! IsValid() ) - return true; + return serialvalid; uint64_t m; - bool valid = UNSERIALIZE(&m); + serialvalid &= UNSERIALIZE(&m); c = new CardinalityCounter(m); - valid &= UNSERIALIZE(&c->V); - valid &= UNSERIALIZE(&c->alpha_m); + serialvalid &= UNSERIALIZE(&c->V); + serialvalid &= UNSERIALIZE(&c->alpha_m); uint8_t* buckets = c->buckets; for ( int i = 0; i < m; i++ ) { uint8_t* currbucket = buckets + i; - valid &= UNSERIALIZE( currbucket ); + serialvalid &= UNSERIALIZE( currbucket ); } return valid; From 8340af55d1ac15a659488f117c2e1a8691542457 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Fri, 19 Apr 2013 09:52:45 -0700 Subject: [PATCH 069/881] persistence really works. It took me way too long to find this - I got the uint8 serialize/deserialize wrong :/ --- src/HyperLogLog.cc | 6 +-- src/OpaqueVal.cc | 5 +-- src/SerializationFormat.cc | 2 - .../btest/Baseline/bifs.hll_persistence/out | 6 +++ testing/btest/bifs/hll_persistence.bro | 40 +++++++++++++++++++ 5 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 testing/btest/Baseline/bifs.hll_persistence/out create mode 100644 testing/btest/bifs/hll_persistence.bro diff --git a/src/HyperLogLog.cc b/src/HyperLogLog.cc index 58cbd72e70..a399f5a495 100644 --- a/src/HyperLogLog.cc +++ b/src/HyperLogLog.cc @@ -43,7 +43,7 @@ CardinalityCounter::CardinalityCounter(uint64_t size) V = m; } -CardinalityCounter :: CardinalityCounter(double error_margin) +CardinalityCounter::CardinalityCounter(double error_margin) { int b = optimalB(error_margin); m = (uint64_t) pow(2, b); @@ -101,9 +101,9 @@ void CardinalityCounter::addElement(uint64_t hash) double CardinalityCounter::size() { double answer = 0; - for (int i = 0; i < m; i++) + for (int i = 0; i < m; i++) answer += pow(2, -(int)buckets[i]); - + answer = 1/answer; answer = alpha_m*m*m*answer; diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 6d56f3ae71..b712f728f7 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -34,9 +34,7 @@ bool CardinalityVal::DoSerialize(SerialInfo* info) const serialvalid &= SERIALIZE(c->V); serialvalid &= SERIALIZE(c->alpha_m); for ( int i = 0; i < c->m; i++ ) - { - serialvalid &= SERIALIZE(c->buckets[i]); - } + serialvalid &= SERIALIZE( c->buckets[i] ); return serialvalid; } @@ -63,7 +61,6 @@ bool CardinalityVal::DoUnserialize(UnserialInfo* info) uint8_t* currbucket = buckets + i; serialvalid &= UNSERIALIZE( currbucket ); } - return valid; } diff --git a/src/SerializationFormat.cc b/src/SerializationFormat.cc index 271163d5db..a005a103cf 100644 --- a/src/SerializationFormat.cc +++ b/src/SerializationFormat.cc @@ -112,7 +112,6 @@ bool BinarySerializationFormat::Read(uint8* v, const char* tag) if ( ! ReadData(v, sizeof(*v)) ) return false; - *v = ntohs(*v); DBG_LOG(DBG_SERIAL, "Read uint8 %hu [%s]", *v, tag); return true; } @@ -314,7 +313,6 @@ bool BinarySerializationFormat::Write(char v, const char* tag) bool BinarySerializationFormat::Write(uint8 v, const char* tag) { DBG_LOG(DBG_SERIAL, "Write uint8 %hu [%s]", v, tag); - v = htons(v); return WriteData(&v, sizeof(v)); } diff --git a/testing/btest/Baseline/bifs.hll_persistence/out b/testing/btest/Baseline/bifs.hll_persistence/out new file mode 100644 index 0000000000..f5bb99d960 --- /dev/null +++ b/testing/btest/Baseline/bifs.hll_persistence/out @@ -0,0 +1,6 @@ +1 +10.000763 +2 +10.000763 +3 +11.000923 diff --git a/testing/btest/bifs/hll_persistence.bro b/testing/btest/bifs/hll_persistence.bro new file mode 100644 index 0000000000..a966ef9343 --- /dev/null +++ b/testing/btest/bifs/hll_persistence.bro @@ -0,0 +1,40 @@ +# @TEST-EXEC: bro -b %INPUT runnumber=1 >out +# @TEST-EXEC: bro -b %INPUT runnumber=2 >>out +# @TEST-EXEC: bro -b %INPUT runnumber=3 >>out +# @TEST-EXEC: btest-diff out + +global runnumber: count &redef; # differentiate first and second run + +global card: opaque of cardinality &persistent; + +event bro_init() + { + print runnumber; + + if ( runnumber == 1 ) + { + card = hll_cardinality_init(0.01); + + hll_cardinality_add(card, "a"); + hll_cardinality_add(card, "b"); + hll_cardinality_add(card, "c"); + hll_cardinality_add(card, "d"); + hll_cardinality_add(card, "e"); + hll_cardinality_add(card, "f"); + hll_cardinality_add(card, "g"); + hll_cardinality_add(card, "h"); + hll_cardinality_add(card, "i"); + hll_cardinality_add(card, "j"); + } + + print hll_cardinality_estimate(card); + + if ( runnumber == 2 ) + { + hll_cardinality_add(card, "a"); + hll_cardinality_add(card, "b"); + hll_cardinality_add(card, "c"); + hll_cardinality_add(card, "aa"); + } + } + From 6e532e89608fc188e00d266a41a90ba6fdc9b668 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Fri, 19 Apr 2013 09:58:57 -0700 Subject: [PATCH 070/881] update cluster test to also use hll --- .../manager-1..stdout | 8 ++++---- .../scripts/base/frameworks/sumstats/basic-cluster.bro | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/testing/btest/Baseline/scripts.base.frameworks.sumstats.basic-cluster/manager-1..stdout b/testing/btest/Baseline/scripts.base.frameworks.sumstats.basic-cluster/manager-1..stdout index ea8904d2e6..ab25d52947 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.sumstats.basic-cluster/manager-1..stdout +++ b/testing/btest/Baseline/scripts.base.frameworks.sumstats.basic-cluster/manager-1..stdout @@ -1,4 +1,4 @@ -Host: 6.5.4.3 - num:2 - sum:6.0 - avg:3.0 - max:5.0 - min:1.0 - var:8.0 - std_dev:2.8 - unique:2 -Host: 10.10.10.10 - num:1 - sum:5.0 - avg:5.0 - max:5.0 - min:5.0 - var:0.0 - std_dev:0.0 - unique:1 -Host: 1.2.3.4 - num:9 - sum:437.0 - avg:48.6 - max:95.0 - min:3.0 - var:758.8 - std_dev:27.5 - unique:8 -Host: 7.2.1.5 - num:2 - sum:145.0 - avg:72.5 - max:91.0 - min:54.0 - var:684.5 - std_dev:26.2 - unique:2 +Host: 6.5.4.3 - num:2 - sum:6.0 - avg:3.0 - max:5.0 - min:1.0 - var:8.0 - std_dev:2.8 - unique:2 - hllunique:2 +Host: 10.10.10.10 - num:1 - sum:5.0 - avg:5.0 - max:5.0 - min:5.0 - var:0.0 - std_dev:0.0 - unique:1 - hllunique:1 +Host: 1.2.3.4 - num:9 - sum:437.0 - avg:48.6 - max:95.0 - min:3.0 - var:758.8 - std_dev:27.5 - unique:8 - hllunique:8 +Host: 7.2.1.5 - num:2 - sum:145.0 - avg:72.5 - max:91.0 - min:54.0 - var:684.5 - std_dev:26.2 - unique:2 - hllunique:2 diff --git a/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro b/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro index 1b7903ca1a..080697a824 100644 --- a/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro +++ b/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro @@ -22,7 +22,7 @@ global n = 0; event bro_init() &priority=5 { - local r1: SumStats::Reducer = [$stream="test", $apply=set(SumStats::SUM, SumStats::MIN, SumStats::MAX, SumStats::AVERAGE, SumStats::STD_DEV, SumStats::VARIANCE, SumStats::UNIQUE)]; + local r1: SumStats::Reducer = [$stream="test", $apply=set(SumStats::SUM, SumStats::MIN, SumStats::MAX, SumStats::AVERAGE, SumStats::STD_DEV, SumStats::VARIANCE, SumStats::UNIQUE, SumStats::HLLUNIQUE)]; SumStats::create([$epoch=5secs, $reducers=set(r1), $epoch_finished(rt: SumStats::ResultTable) = @@ -30,7 +30,7 @@ event bro_init() &priority=5 for ( key in rt ) { local r = rt[key]["test"]; - print fmt("Host: %s - num:%d - sum:%.1f - avg:%.1f - max:%.1f - min:%.1f - var:%.1f - std_dev:%.1f - unique:%d", key$host, r$num, r$sum, r$average, r$max, r$min, r$variance, r$std_dev, r$unique); + print fmt("Host: %s - num:%d - sum:%.1f - avg:%.1f - max:%.1f - min:%.1f - var:%.1f - std_dev:%.1f - unique:%d - hllunique:%d", key$host, r$num, r$sum, r$average, r$max, r$min, r$variance, r$std_dev, r$unique, r$hllunique); } terminate(); From c21c18ea45d24a20f48c42b0d828c184d1f66ebd Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 22 Apr 2013 01:10:29 -0700 Subject: [PATCH 071/881] implement topk. This is _completely_ untested. It compiles. It will probably do nothing else (well, besides crashing Bro). --- src/CMakeLists.txt | 1 + src/Topk.cc | 224 +++++++++++++++++++++++++++++++++++++++++++++ src/Topk.h | 56 ++++++++++++ 3 files changed, 281 insertions(+) create mode 100644 src/Topk.cc create mode 100644 src/Topk.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 83a018ccde..bc2512af68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -408,6 +408,7 @@ set(bro_SRCS Telnet.cc Teredo.cc Timer.cc + Topk.cc Traverse.cc Trigger.cc TunnelEncapsulation.cc diff --git a/src/Topk.cc b/src/Topk.cc new file mode 100644 index 0000000000..ef7d7bfbd8 --- /dev/null +++ b/src/Topk.cc @@ -0,0 +1,224 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Topk.h" +#include "CompHash.h" +#include "Reporter.h" + +namespace Topk { + +static void topk_element_hash_delete_func(void* val) + { + Element* e = (Element*) val; + delete e; + } + +Element::~Element() + { + if ( value ) + Unref(value); + value=0; + } + +HashKey* Topk::GetHash(Val* v) + { + TypeList* tl = new TypeList(v->Type()); + tl->Append(v->Type()); + CompositeHash* topk_hash = new CompositeHash(tl); + Unref(tl); + + HashKey* key = topk_hash->ComputeHash(v, 1); + assert(key); + return key; + } + +Topk::Topk(uint64 arg_size) + { + elementDict = new PDict(Element); + elementDict->SetDeleteFunc(topk_element_hash_delete_func); + size = arg_size; + type = 0; + } + +Topk::~Topk() + { + elementDict->Clear(); + delete elementDict; + + // now all elements are already gone - delete the buckets + std::list::iterator bi = buckets.begin(); + while ( bi != buckets.end() ) + { + delete *bi; + bi++; + } + + if ( type ) + Unref(type); + type = 0; + } + +VectorVal* Topk::getTopK(int k) // returns vector + { + if ( numElements == 0 ) + { + reporter->Error("Cannot return topk of empty"); + return 0; + } + + TypeList* vector_index = new TypeList(type); + vector_index->Append(type); + VectorType* v = new VectorType(vector_index); + VectorVal* t = new VectorVal(v); + + // this does no estimation if the results is correct! + // in any case - just to make this future-proof (and I am lazy) - this can return more than k. + + int read = 0; + std::list::iterator it = buckets.end(); + while (read < k ) + { + std::list::iterator eit = (*it)->elements.begin(); + while (eit != (*it)->elements.end() ) + { + t->Assign(read, (*eit)->value->Ref()); + read++; + } + + if ( it == buckets.begin() ) + break; + } + + + Unref(v); + return t; + } + +void Topk::Encountered(Val* encountered) + { + // ok, let's see if we already know this one. + + // check type compatibility + if ( numElements == 0 ) + type = encountered->Type()->Ref(); + else + if ( !same_type(type, encountered->Type()) ) + { + reporter->Error("Trying to add element to topk with differing type from other elements"); + return; + } + + + // Step 1 - get the hash. + HashKey* key = GetHash(encountered); + Element* e = (Element*) elementDict->Lookup(key); + + if ( e == 0 ) + { + e = new Element(); + e->epsilon = 0; + e->value = encountered->Ref(); // or no ref? + + + // well, we do not know this one yet... + if ( numElements < size ) + { + // brilliant. just add it at position 1 + if ( buckets.size() == 0 || (*buckets.begin())->count > 1 ) + { + Bucket* b = new Bucket(); + b->count = 1; + std::list::iterator pos = buckets.insert(buckets.begin(), b); + b->bucketPos = pos; + b->elements.insert(b->elements.end(), e); + e->parent = b; + } + else + { + Bucket* b = *buckets.begin(); + assert(b->count == 1); + b->elements.insert(b->elements.end(), e); + e->parent = b; + } + + elementDict->Insert(key, e); + numElements++; + delete key; + return; // done. it is at pos 1. + } + else + { + // replace element with min-value + Bucket* b = *buckets.begin(); // bucket with smallest elements + // evict oldest element with least hits. + assert(b->elements.size() > 0); + HashKey* deleteKey = GetHash((*(b->elements.begin()))->value); + b->elements.erase(b->elements.begin()); + Element* deleteElement = (Element*) elementDict->RemoveEntry(deleteKey); + assert(deleteElement); // there has to have been a minimal element... + delete deleteElement; + delete deleteKey; + // and add the new one to the end + e->epsilon = b->count; + b->elements.insert(b->elements.end(), e); + elementDict->Insert(key, e); + // fallthrough, increment operation has to run! + } + + } + + // ok, we now have an element in e + delete key; + IncrementCounter(e); // well, this certainly was anticlimatic. + + } + +void Topk::IncrementCounter(Element* e) + { + Bucket* currBucket = e->parent; + uint64 currcount = currBucket->count; + + // well, let's test if there is a bucket for currcount++ + std::list::iterator bucketIter = currBucket->bucketPos; + + Bucket* nextBucket = 0; + + bucketIter++; + + if ( bucketIter != buckets.end() ) + { + if ( (*bucketIter)->count == currcount+1 ) + nextBucket = *bucketIter; + } + + if ( nextBucket == 0 ) + { + // the bucket for the value that we want does not exist. + // create it... + + Bucket* b = new Bucket(); + b->count = currcount+1; + + std::list::iterator nextBucketPos = buckets.insert(bucketIter, b); + b->bucketPos = nextBucketPos; // and give it the iterator we know now. + + nextBucket = b; + } + + // ok, now we have the new bucket in nextBucket. Shift the element over... + currBucket->elements.remove(e); + nextBucket->elements.insert(nextBucket->elements.end(), e); + + e->parent = nextBucket; + + // if currBucket is empty, we have to delete it now + if ( currBucket->elements.size() == 0 ) + { + buckets.remove(currBucket); + delete currBucket; + currBucket = 0; + } + + + } + +}; diff --git a/src/Topk.h b/src/Topk.h new file mode 100644 index 0000000000..b38e1e8ab3 --- /dev/null +++ b/src/Topk.h @@ -0,0 +1,56 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef topk_h +#define topk_h + +#include +#include "Val.h" +#include "CompHash.h" + +// This class implements the top-k algorithm. Or - to be more precise - my interpretation of it. + +namespace Topk { + +struct Element; + +struct Bucket { + uint64 count; + std::list elements; + std::list::iterator bucketPos; // iterators only get invalidated for removed elements. This one points to us - so it is invalid when we are no longer there. Cute, isn't it? +}; + +struct Element { + uint64 epsilon; + Val* value; + Bucket* parent; + + ~Element(); +}; + + +declare(PDict, Element); + +class Topk { + +public: + Topk(uint64 size); + ~Topk(); + void Encountered(Val* value); // we saw something + VectorVal* getTopK(int k); // returns vector + +private: + void IncrementCounter(Element* e); + HashKey* GetHash(Val*); // this probably should go somewhere else. + + BroType* type; + std::list buckets; + PDict(Element)* elementDict; + uint64 size; // how many elements are we tracking? + uint64 numElements; // how many elements do we have at the moment + + +}; + +}; + +#endif From ce7ad003f251e8c76be3d07190907157cd9a87c1 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 22 Apr 2013 02:40:42 -0700 Subject: [PATCH 072/881] well, a test that works.. Note: merging top-k data structures is not yet possible (and is actually quite awkward/expensive). I will have to think about how to do that for a bit... --- src/Topk.cc | 23 +++++++---- src/Topk.h | 9 ++-- src/bro.bif | 27 ++++++++++++ testing/btest/Baseline/bifs.topk/out | 7 ++++ testing/btest/bifs/topk.bro | 61 ++++++++++++++++++++++++++++ 5 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 testing/btest/Baseline/bifs.topk/out create mode 100644 testing/btest/bifs/topk.bro diff --git a/src/Topk.cc b/src/Topk.cc index ef7d7bfbd8..8f4d63ed78 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -19,7 +19,7 @@ Element::~Element() value=0; } -HashKey* Topk::GetHash(Val* v) +HashKey* TopkVal::GetHash(Val* v) { TypeList* tl = new TypeList(v->Type()); tl->Append(v->Type()); @@ -31,15 +31,16 @@ HashKey* Topk::GetHash(Val* v) return key; } -Topk::Topk(uint64 arg_size) +TopkVal::TopkVal(uint64 arg_size) : OpaqueVal(new OpaqueType("topk")) { elementDict = new PDict(Element); elementDict->SetDeleteFunc(topk_element_hash_delete_func); size = arg_size; type = 0; + numElements = 0; } -Topk::~Topk() +TopkVal::~TopkVal() { elementDict->Clear(); delete elementDict; @@ -57,7 +58,7 @@ Topk::~Topk() type = 0; } -VectorVal* Topk::getTopK(int k) // returns vector +VectorVal* TopkVal::getTopK(int k) // returns vector { if ( numElements == 0 ) { @@ -75,17 +76,23 @@ VectorVal* Topk::getTopK(int k) // returns vector int read = 0; std::list::iterator it = buckets.end(); + it--; while (read < k ) { + //printf("Bucket %llu\n", (*it)->count); std::list::iterator eit = (*it)->elements.begin(); while (eit != (*it)->elements.end() ) { + //printf("Size: %ld\n", (*it)->elements.size()); t->Assign(read, (*eit)->value->Ref()); read++; + eit++; } if ( it == buckets.begin() ) break; + + it--; } @@ -93,13 +100,14 @@ VectorVal* Topk::getTopK(int k) // returns vector return t; } -void Topk::Encountered(Val* encountered) +void TopkVal::Encountered(Val* encountered) { // ok, let's see if we already know this one. + //printf("NumElements: %d\n", numElements); // check type compatibility if ( numElements == 0 ) - type = encountered->Type()->Ref(); + type = encountered->Type()->Ref()->Ref(); else if ( !same_type(type, encountered->Type()) ) { @@ -161,6 +169,7 @@ void Topk::Encountered(Val* encountered) e->epsilon = b->count; b->elements.insert(b->elements.end(), e); elementDict->Insert(key, e); + e->parent = b; // fallthrough, increment operation has to run! } @@ -172,7 +181,7 @@ void Topk::Encountered(Val* encountered) } -void Topk::IncrementCounter(Element* e) +void TopkVal::IncrementCounter(Element* e) { Bucket* currBucket = e->parent; uint64 currcount = currBucket->count; diff --git a/src/Topk.h b/src/Topk.h index b38e1e8ab3..7c983ebdfc 100644 --- a/src/Topk.h +++ b/src/Topk.h @@ -6,6 +6,7 @@ #include #include "Val.h" #include "CompHash.h" +#include "OpaqueVal.h" // This class implements the top-k algorithm. Or - to be more precise - my interpretation of it. @@ -30,11 +31,11 @@ struct Element { declare(PDict, Element); -class Topk { +class TopkVal : public OpaqueVal { public: - Topk(uint64 size); - ~Topk(); + TopkVal(uint64 size); + ~TopkVal(); void Encountered(Val* value); // we saw something VectorVal* getTopK(int k); // returns vector @@ -47,8 +48,6 @@ private: PDict(Element)* elementDict; uint64 size; // how many elements are we tracking? uint64 numElements; // how many elements do we have at the moment - - }; }; diff --git a/src/bro.bif b/src/bro.bif index ac54da0e75..695337bcf1 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5642,3 +5642,30 @@ function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr } %} + + +%%{ +#include "Topk.h" +%%} + +function topk_init%(size: count%): opaque of topk + %{ + Topk::TopkVal* v = new Topk::TopkVal(size); + return v; + %} + +function topk_add%(handle: opaque of topk, value: any%): any + %{ + assert(handle); + Topk::TopkVal* h = (Topk::TopkVal*) handle; + h->Encountered(value); + + return 0; + %} + +function topk_get_top%(handle: opaque of topk, k: count%): any + %{ + assert(handle); + Topk::TopkVal* h = (Topk::TopkVal*) handle; + return h->getTopK(k); + %} diff --git a/testing/btest/Baseline/bifs.topk/out b/testing/btest/Baseline/bifs.topk/out new file mode 100644 index 0000000000..94aa5bd572 --- /dev/null +++ b/testing/btest/Baseline/bifs.topk/out @@ -0,0 +1,7 @@ +[b, c] +[d, c] +[d, e] +[f, e] +[f, e] +[g, e] +[c, e, d] diff --git a/testing/btest/bifs/topk.bro b/testing/btest/bifs/topk.bro new file mode 100644 index 0000000000..af1f38c773 --- /dev/null +++ b/testing/btest/bifs/topk.bro @@ -0,0 +1,61 @@ +# @TEST-EXEC: bro -b %INPUT > out +# @TEST-EXEC: btest-diff out + +event bro_init() + { + local k1 = topk_init(2); + + # first - peculiarity check... + topk_add(k1, "a"); + topk_add(k1, "b"); + topk_add(k1, "b"); + topk_add(k1, "c"); + + local s = topk_get_top(k1, 5); + print s; + + topk_add(k1, "d"); + s = topk_get_top(k1, 5); + print s; + + topk_add(k1, "e"); + s = topk_get_top(k1, 5); + print s; + + topk_add(k1, "f"); + s = topk_get_top(k1, 5); + print s; + + topk_add(k1, "e"); + s = topk_get_top(k1, 5); + print s; + + topk_add(k1, "g"); + s = topk_get_top(k1, 5); + print s; + + k1 = topk_init(100); + topk_add(k1, "a"); + topk_add(k1, "b"); + topk_add(k1, "b"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "f"); + s = topk_get_top(k1, 3); + print s; + + +} From 2832939026aeea51bae0fb87c809d601a46a76cd Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Mon, 22 Apr 2013 11:03:20 -0400 Subject: [PATCH 073/881] Include btest-rst-include directives for logging framework examples. --- doc/scripting/index.rst | 50 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 6661a20f43..893a6f7f3d 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -3,21 +3,6 @@ Writing Bro Scripts =================== -.. toctree:: - :maxdepth: 2 - :numbered: - - Understanding Bro Scripts - The Event Queue and Event Handlers - The Connection Record Datatype - Data Types and Data Structures - Scope - Global Variables - Constants - Local Variables - Data Structures - - Understanding Bro Scripts ========================= @@ -479,8 +464,8 @@ The output of the script aligns with what we expect so now it's time to integrat Now, if we run the new version of the script, instead of generating logging information to stdout, no output is created. Instead the output is all in factor.log, properly formatted and organized. .. btest:: framework_logging_factorial_02 - - @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_02.bro + + @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_02/factor.log While the previous example is a simplistic one, it serves to demonstrate the small pieces of script that need to be in place in order to generate logs. For example, it's common to call ``Log::create_stream()`` in ``bro_init()`` and while in a live example, determining when to call ``Log::write()`` would likely be done in an event handler, in this case we use ``bro_done()``. @@ -493,6 +478,11 @@ If you've already spent time with a deployment of Bro, you've likely had the opp To dynamically alter the file in which a stream writes its logs a filter can specify function returns a string to be used as the filename for the current call to ``Log::write()``. The definition for this function has to take as its parameters a Log::ID called id, a string called path and the appropriate record type for the logs called "rec". You can see the definition of ``mod5`` used in this example on line one conforms to that requirement. The function simply returns "factor-mod5" if the factorial is divisible evenly by 5, otherwise, it returns "factor-non5". In the additional ``bro_init()`` event handler, we define a locally scoped ``Log::Filter`` and assign it a record that defines the ``name`` and ``path_func`` fields. We then call ``Log::add_filter()`` to add the filter to the ``Factor::LOG`` Log::ID and call ``Log::remove_filter()`` to remove the ``default`` filter for Factor::LOG. Had we not removed the ``default`` filter, we'd have ended up with three log files: factor-mod5.log with all the factorials that are a factors of 5, factor-non5.log with the factorials that are not factors of 5, and factor.log which would have included all factorials. +.. btest:: framework_logging_factorial_02 + + @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_03/factor-mod5.log + @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_03/factor-non5.log + The ability of Bro to generate easily customizable and extensible logs which remain easily parsable is a big part of the reason Bro has gained a large measure of respect. In fact, it's difficult at times to think of something that Bro doesn't log and as such, it is often advantageous for analysts and systems architects to instead hook into the logging framework to be able to perform custom actions based upon the data being sent to the Logging Frame. To that end, every default log stream in Bro generates a custom event that can be handled by anyone wishing to act upon the data being sent to the stream. By convention these events are usually in the format ``log_x`` where x is the name of the logging stream; as such the event raised for every log sent to the Logging Framework by the HTTP parser would be ``log_http``. In fact, we've already seen a script handle the ``log_http`` event when we broke down how the ``detect-MHR.bro`` script worked. In that example, as each log entry was sent to the logging framework, post-processing was taking place in the ``log_http`` event. Instead of using an external script to parse the ``http.log`` file and do post-processing for the entry, post-processing can be done in real time in Bro. Telling Bro to raise an event in your own Logging stream is as simple as exporting that event name and then adding that event in the call to ``Log::create_stream``. Going back to our simple example of logging the factorial of an integer, we add ``log_factor`` to the ``export`` block and define the value to be passed to it, in this case the ``Factor::Info`` record. We then list the ``log_factor`` function as the ``$ev`` field in the call to ``Log::create_stream`` @@ -512,27 +502,47 @@ To raise a notice in Bro, you only need to indicate to Bro that you are provide +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | Field | Type | Attributes | Use | -|=====================+==================================================================+================+========================================+ ++=====================+==================================================================+================+========================================+ | ts | time | &log &optional | The time of the notice | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | uid | string | &log &optional | A unique connection ID | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | id | conn_id | &log &optional | A 4-tuple to identify endpoints | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | conn | connection | &optional | Shorthand for the uid and id | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | iconn | icmp_conn | &optional | Shorthand for the uid and id | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | proto | transport_proto | &log &optional | Transport protocol | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | note | Notice::Type | &log | The Notice::Type of the notice | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | msg | string | &log &optional | Human readable message | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | sub | string | &log &optional | Human readable message | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | src | addr | &log &optional | Source address if no conn_id | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | dst | addr | &log &optional | Destination addr if no conn_id | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | p | port | &log &optional | Port if no conn_id | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | n | count | &log &optional | Count or status code | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | src_peer | event_peer | &log &optional | Peer that raised the notice | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | peer_descr | string | &log &optional | Text description of the src_peer | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | actions | set[Notice::Action] | &log &optional | Actions applied to the notice | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | policy_items | set[count] | &log &optional | Policy items that have been applied | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | email_body_sections | vector | &optinal | Body of the email for email notices. | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | email_delay_tokens | set[string] | &optional | Delay functionality for email notices. | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | identifier | string | &optional | A unique string identifier | ++---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | suppress_for | interval | &log &optional | Length of time to suppress a notice. | +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ @@ -545,6 +555,6 @@ One of the default policy scripts raises a notice when an SSH login has been heu While much of the script relates to the actual detection, the parts specific to the Notice Framework are actually quite interesting in themselves. On line 12 the script's ``export`` block adds the value ``SSH::Interesting_Hostname_Login`` to the enumerable constant ``Notice::Type`` to indicate to the Bro core that a new type of notice is being defined. The script then calls ``NOTICE()`` and defines the ``$note``, ``$msg``, ``$sub`` and ``$conn`` fields. Line 39 also includes a ternary if statement that modifies the ``$msg`` text depending on whether the host is a local address and whether it is the client or the server. This use of ``fmt()`` and a ternary operators is a concise way to lend readability to the notices that are generated without the need for branching ``if`` statements that each raise a specific notice. +The opt-in system for notices is managed through writing ``Notice::policy`` hooks. A ``Notice::policy`` hook takes as its argument a ``Notice::Info`` which will hold the same information your script provided in its call to ``NOTICE()``. With access to the ``Notice::Info`` record for a specific notice you can include predicates in your hook to alter the Policy for handling notices on your system. The simplest kind of ``Notice::policy`` hooks simply check the value of ``$note`` in the ``Notice::Info`` record being passed into the hook and performing an action based on the answer. The hook below adds the ``Notice::ACTION_EMAIL`` action for the SSH::Interesting_Hostname_Login notice raised in the interesting-hostnames.bro script. - - +Much like event handlers, it's possible to have multiple Notice::policy hooks for the same Notice. From 035b668f7398cd4b803c9ecc455ce58203de666b Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 22 Apr 2013 21:52:21 -0400 Subject: [PATCH 074/881] Updates to use new input framework mechanism to execute command line programs. --- scripts/base/utils/exec.bro | 160 ++++++++++++++---------------------- 1 file changed, 60 insertions(+), 100 deletions(-) diff --git a/scripts/base/utils/exec.bro b/scripts/base/utils/exec.bro index fe353cf590..45cd8cb287 100644 --- a/scripts/base/utils/exec.bro +++ b/scripts/base/utils/exec.bro @@ -23,6 +23,8 @@ export { type Result: record { ## Exit code from the program. exit_code: count &default=0; + ## True if the command was terminated with a signal. + signal_exit: bool &default=F; ## Each line of standard out. stdout: vector of string &optional; ## Each line of standard error. @@ -41,39 +43,45 @@ export { ## returns: A record representing the full results from the ## external program execution. global run: function(cmd: Command): Result; + + ## The system directory for temp files. + const tmp_dir = "/tmp" &redef; } redef record Command += { - # The prefix name for tracking temp files. - prefix_name: string &optional; + # The unique id for tracking executors. + uid: string &optional; }; global results: table[string] of Result = table(); global finished_commands: set[string]; -global tmp_files: set[string] = set(); +global currently_tracked_files: set[string] = set(); +type OneLine: record { + s: string; + is_stderr: bool; +}; -type OneLine: record { line: string; }; +type FileLine: record { + s: string; +}; -event Exec::stdout_line(description: Input::EventDescription, tpe: Input::Event, s: string) +event Exec::line(description: Input::EventDescription, tpe: Input::Event, s: string, is_stderr: bool) { - local name = sub(description$name, /_[^_]*$/, ""); - - local result = results[name]; - if ( ! results[name]?$stdout ) - result$stdout = vector(s); + local result = results[description$name]; + if ( is_stderr ) + { + if ( ! result?$stderr ) + result$stderr = vector(s); + else + result$stderr[|result$stderr|] = s; + } else - result$stdout[|result$stdout|] = s; - } - -event Exec::stderr_line(description: Input::EventDescription, tpe: Input::Event, s: string) - { - local name = sub(description$name, /_[^_]*$/, ""); - - local result = results[name]; - if ( ! results[name]?$stderr ) - result$stderr = vector(s); - else - result$stderr[|result$stderr|] = s; + { + if ( ! result?$stdout ) + result$stdout = vector(s); + else + result$stdout[|result$stdout|] = s; + } } event Exec::file_line(description: Input::EventDescription, tpe: Input::Event, s: string) @@ -92,107 +100,59 @@ event Exec::file_line(description: Input::EventDescription, tpe: Input::Event, s result$files[track_file][|result$files[track_file]|] = s; } -event Exec::cleanup_and_do_callback(name: string) +event InputRaw::process_finished(name: string, source:string, exit_code:count, signal_exit:bool) { - Input::remove(fmt("%s_stdout", name)); - system(fmt("rm %s_stdout", name)); - delete tmp_files[fmt("%s_stdout", name)]; - - Input::remove(fmt("%s_stderr", name)); - system(fmt("rm %s_stderr", name)); - delete tmp_files[fmt("%s_stderr", name)]; - - Input::remove(fmt("%s_done", name)); - system(fmt("rm %s_done", name)); - delete tmp_files[fmt("%s_done", name)]; + results[name]$exit_code = exit_code; + results[name]$signal_exit = signal_exit; + Input::remove(name); # Indicate to the "when" async watcher that this command is done. add finished_commands[name]; } -event Exec::run_done(description: Input::EventDescription, tpe: Input::Event, s: string) +event Exec::start_watching_file(uid: string, read_file: string) { - local name = sub(description$name, /_[^_]*$/, ""); - - if ( /^exit_code:/ in s ) - results[name]$exit_code = to_count(split1(s, /:/)[2]); - else if ( s == "done" ) - # Wait one second to allow all threads to read all of their input - # and forward it. - schedule 1sec { Exec::cleanup_and_do_callback(name) }; - } - -event Exec::start_watching_files(cmd: Command) - { - Input::add_event([$source=fmt("%s_done", cmd$prefix_name), - $name=fmt("%s_done", cmd$prefix_name), + Input::add_event([$source=fmt("%s", read_file), + $name=fmt("%s_%s", uid, read_file), $reader=Input::READER_RAW, $mode=Input::STREAM, $want_record=F, - $fields=OneLine, - $ev=Exec::run_done]); - - Input::add_event([$source=fmt("%s_stdout", cmd$prefix_name), - $name=fmt("%s_stdout", cmd$prefix_name), - $reader=Input::READER_RAW, - $mode=Input::STREAM, - $want_record=F, - $fields=OneLine, - $ev=Exec::stdout_line]); - - Input::add_event([$source=fmt("%s_stderr", cmd$prefix_name), - $name=fmt("%s_stderr", cmd$prefix_name), - $reader=Input::READER_RAW, - $mode=Input::STREAM, - $want_record=F, - $fields=OneLine, - $ev=Exec::stderr_line]); - - if ( cmd?$read_files ) - { - for ( read_file in cmd$read_files ) - { - Input::add_event([$source=fmt("%s", read_file), - $name=fmt("%s_%s", cmd$prefix_name, read_file), - $reader=Input::READER_RAW, - $mode=Input::STREAM, - $want_record=F, - $fields=OneLine, - $ev=Exec::file_line]); - } - } + $fields=FileLine, + $ev=Exec::file_line]); } function run(cmd: Command): Result { - cmd$prefix_name = "/tmp/bro-exec-" + unique_id(""); - system(fmt("touch %s_done %s_stdout %s_stderr 2>/dev/null", cmd$prefix_name, cmd$prefix_name, cmd$prefix_name)); - add tmp_files[fmt("%s_done", cmd$prefix_name)]; - add tmp_files[fmt("%s_stdout", cmd$prefix_name)]; - add tmp_files[fmt("%s_stderr", cmd$prefix_name)]; + cmd$uid = unique_id(""); + results[cmd$uid] = []; if ( cmd?$read_files ) { for ( read_file in cmd$read_files ) { - system(fmt("touch %s 2>/dev/null", read_file)); - add tmp_files[read_file]; + add currently_tracked_files[read_file]; + system(fmt("touch \"%s\" 2>/dev/null", str_shell_escape(read_file))); + schedule 1msec { Exec::start_watching_file(cmd$uid, read_file) }; } } - piped_exec(fmt("%s 2>> %s_stderr 1>> %s_stdout; echo \"exit_code:${?}\" >> %s_done; echo \"done\" >> %s_done", - cmd$cmd, cmd$prefix_name, cmd$prefix_name, cmd$prefix_name, cmd$prefix_name), - cmd$stdin); + local config_strings: table[string] of string = { + ["stdin"] = cmd$stdin, + ["read_stderr"] = "1", + }; + Input::add_event([$name=cmd$uid, + $source=fmt("%s |", cmd$cmd), + $reader=Input::READER_RAW, + $fields=Exec::OneLine, + $ev=Exec::line, + $want_record=F, + $config=config_strings]); - results[cmd$prefix_name] = []; - - schedule 1msec { Exec::start_watching_files(cmd) }; - - return when ( cmd$prefix_name in finished_commands ) + return when ( cmd$uid in finished_commands ) { - delete finished_commands[cmd$prefix_name]; - local result = results[cmd$prefix_name]; - delete results[cmd$prefix_name]; + delete finished_commands[cmd$uid]; + local result = results[cmd$uid]; + delete results[cmd$uid]; return result; } } @@ -200,7 +160,7 @@ function run(cmd: Command): Result event bro_done() { # We are punting here and just deleting any files that haven't been processed yet. - for ( fname in tmp_files ) + for ( fname in currently_tracked_files ) { system(fmt("rm \"%s\"", str_shell_escape(fname))); } From 08348b2bc29f0d4661fbe61be355716a3ee51a25 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 22 Apr 2013 21:53:00 -0400 Subject: [PATCH 075/881] Update to make Dir::monitor watch inodes instead of file names. --- scripts/base/utils/dir.bro | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/base/utils/dir.bro b/scripts/base/utils/dir.bro index 2ed1c8e6e9..b154fe000e 100644 --- a/scripts/base/utils/dir.bro +++ b/scripts/base/utils/dir.bro @@ -23,11 +23,11 @@ export { event Dir::monitor_ev(dir: string, last_files: set[string], callback: function(fname: string)) { - when ( local result = Exec::run([$cmd=fmt("ls \"%s\"", str_shell_escape(dir))]) ) + when ( local result = Exec::run([$cmd=fmt("ls -i \"%s/\"", str_shell_escape(dir))]) ) { if ( result$exit_code != 0 ) { - Reporter::warning("Requested monitoring of non-existent directory."); + Reporter::warning(fmt("Requested monitoring of non-existent directory (%s).", dir)); return; } @@ -35,9 +35,10 @@ event Dir::monitor_ev(dir: string, last_files: set[string], callback: function(f local files = result$stdout; for ( i in files ) { - if ( files[i] !in last_files ) - callback(build_path_compressed(dir, files[i])); - add current_files[files[i]]; + local parts = split1(files[i], / /); + if ( parts[1] !in last_files ) + callback(build_path_compressed(dir, parts[2])); + add current_files[parts[1]]; } schedule polling_interval { Dir::monitor_ev(dir, current_files, callback) }; } From 59405af80452319c40bce658f56a93d0d36cef0f Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 23 Apr 2013 17:02:42 -0400 Subject: [PATCH 076/881] Notice::policy hooks and tests. Include explanation of various Notice::policy hook actions. Add two btest scripts. framework_notice_hook_01.bro shows adding an action to the n$action set while framework_notice_suppression.bro shows how to add a custom n$suppress_for value for a notice through a policy hook. While both scripts include an @load directive, it is left out in RST document so as to avoid confusion. --- doc/scripting/index.rst | 39 ++++++++++++++++++- .../.stdout | 0 .../.stdout | 0 .../doc/manual/framework_notice_hook_01.bro | 12 ++++++ .../framework_notice_hook_suppression_01.bro | 12 ++++++ 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.framework_notice_hook_01/.stdout create mode 100644 testing/btest/Baseline/doc.manual.framework_notice_hook_suppression_01/.stdout create mode 100644 testing/btest/doc/manual/framework_notice_hook_01.bro create mode 100644 testing/btest/doc/manual/framework_notice_hook_suppression_01.bro diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 893a6f7f3d..c7fcc93ea9 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -555,6 +555,41 @@ One of the default policy scripts raises a notice when an SSH login has been heu While much of the script relates to the actual detection, the parts specific to the Notice Framework are actually quite interesting in themselves. On line 12 the script's ``export`` block adds the value ``SSH::Interesting_Hostname_Login`` to the enumerable constant ``Notice::Type`` to indicate to the Bro core that a new type of notice is being defined. The script then calls ``NOTICE()`` and defines the ``$note``, ``$msg``, ``$sub`` and ``$conn`` fields. Line 39 also includes a ternary if statement that modifies the ``$msg`` text depending on whether the host is a local address and whether it is the client or the server. This use of ``fmt()`` and a ternary operators is a concise way to lend readability to the notices that are generated without the need for branching ``if`` statements that each raise a specific notice. -The opt-in system for notices is managed through writing ``Notice::policy`` hooks. A ``Notice::policy`` hook takes as its argument a ``Notice::Info`` which will hold the same information your script provided in its call to ``NOTICE()``. With access to the ``Notice::Info`` record for a specific notice you can include predicates in your hook to alter the Policy for handling notices on your system. The simplest kind of ``Notice::policy`` hooks simply check the value of ``$note`` in the ``Notice::Info`` record being passed into the hook and performing an action based on the answer. The hook below adds the ``Notice::ACTION_EMAIL`` action for the SSH::Interesting_Hostname_Login notice raised in the interesting-hostnames.bro script. +The opt-in system for notices is managed through writing ``Notice::policy`` hooks. A ``Notice::policy`` hook takes as its argument a ``Notice::Info`` record which will hold the same information your script provided in its call to ``NOTICE()``. With access to the ``Notice::Info`` record for a specific notice you can include logic such as in statements in the body of your hook to alter the Policy for handling notices on your system. Notice hooks are akin to functions and event handlers and share the same structure; You can even think of hooks as multi-bodied functions. You define the hook and Bro will take care of passing in the ``Notice::Info`` record. The simplest kind of ``Notice::policy`` hooks simply check the value of ``$note`` in the ``Notice::Info`` record being passed into the hook and performing an action based on the answer. The hook below adds the ``Notice::ACTION_EMAIL`` action for the SSH::Interesting_Hostname_Login notice raised in the interesting-hostnames.bro script. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_hook_01.bro + :language: bro + :linenos: + :lines: 6-12 + +In the example above we've added ``Notice::ACTION_EMAIL`` to the ``n$actions`` set. This set, defined in the Notice Framework scripts, can only have entries from the Notice::Action type which is itself an enumerable that defines the values shown in the table below along with their corresponding meanings. The ``Notice::ACTION_LOG`` action writes the notice to the ``Notice::LOG`` logging stream which, in the default configuration, will write each notice to the notice.log file and take no further action. The ``Notice::ACTION_EMAIL`` action will send an email to the address or addresses defined in the ``Notice::mail_dest`` variable with the particulars of the notice as the body of the email. The last action, ``Notice::ACTION_ALARM`` sends the notice to the ``Notice::ALARM_LOG`` logging stream which is then rotated hourly and its contents emailed in readable ASCII to the addresses in ``Notice::mail_dest``. + ++--------------+-----------------------------------------------------+ +| ACTION_NONE | Take no action | ++--------------+-----------------------------------------------------+ +| ACTION_LOG | Send the notice to the Notice::LOG logging stream. | ++--------------+-----------------------------------------------------+ +| ACTION_EMAIL | Send an email with the notice in the body. | ++--------------+-----------------------------------------------------+ +| ACTION_ALARM | Send the notice to the Notice::Alarm_LOG stream. | ++--------------+-----------------------------------------------------+ + +While actions like the ``Notice::ACTION_EMAIL`` action have appeal for quick alerts and response, a caveat of its use is to make sure the notices configured with this action also have a suppression. A suppression is a means through which notices can be ignored after they are initially raised if the author of the script has set an identifier. An identifier is a unique string of information collected from the connection relative to the behavior that has been observed by Bro. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssl/expiring-certs.bro + :language: bro + :linenos: + :lines: 59-62 + +In the ``expiring-certs.bro`` script which identifies when SSL certificates are set to expire and raises notices when it crosses a pre-defined threshold, the call to ``NOTICE()`` above also sets the ``$identfier`` entry by concatenating the responder ip, port, and the hash of the certificate. The selection of responder ip, port and certificate hash fits perfectly into an appropriate identifier as it creates a unique identifier with which the suppression can be matched. Were we to take out any of the entities used for the identifier, for example the certificate hash, we could be setting our suppression too broadly, causing an analyst to miss a notice that should have been raised. Depending on the available data for the identifier, it can be useful to set the ``$suppress_for`` variable as well. The ``expiring-certs.bro`` script sets ``$suppress_for`` to ``1day``, telling the Notice Framework to suppress the notice for 24 hours after the first notice is raised. Once that time limit has passed, another notice can be raised which will again set the ``1day`` suppression time. Suppressing for a specific amount of time has benefits beyond simply not filling up an analyst's email inbox; keeping the notice alerts timely and succinct helps avoid a case where an analyst might see the notice and, due to over exposure, ignore it. + +The ``$suppress_for`` variable can also be altered in a ``Notice::policy`` hook, allowing a deployment to better suit the environment in which it is be run. Using the example of ``expiring-certs.bro``, we can write a ``Notice::policy`` hook for ``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for`` variable to a shorter time. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_suppression_01.bro + :language: bro + :linenos: + :lines: 6-12 + + + -Much like event handlers, it's possible to have multiple Notice::policy hooks for the same Notice. diff --git a/testing/btest/Baseline/doc.manual.framework_notice_hook_01/.stdout b/testing/btest/Baseline/doc.manual.framework_notice_hook_01/.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/Baseline/doc.manual.framework_notice_hook_suppression_01/.stdout b/testing/btest/Baseline/doc.manual.framework_notice_hook_suppression_01/.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/doc/manual/framework_notice_hook_01.bro b/testing/btest/doc/manual/framework_notice_hook_01.bro new file mode 100644 index 0000000000..3ec0bbff02 --- /dev/null +++ b/testing/btest/doc/manual/framework_notice_hook_01.bro @@ -0,0 +1,12 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +@load policy/protocols/ssh/interesting-hostnames.bro + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSH::Interesting_Hostname_Login ) + { + add n$actions[Notice::ACTION_EMAIL]; + } + } \ No newline at end of file diff --git a/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro b/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro new file mode 100644 index 0000000000..3d948f65b5 --- /dev/null +++ b/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro @@ -0,0 +1,12 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +@load policy/protocols/ssl/expiring-certs.bro + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSL::Certificate_Expires_Soon ) + { + n$suppress_for = 12hrs; + } + } From de5769a88fd123cf6f34f978cf67ec5ee494de15 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 23 Apr 2013 15:19:01 -0700 Subject: [PATCH 077/881] topk for sumstats --- .../frameworks/sumstats/plugins/__load__.bro | 3 +- .../base/frameworks/sumstats/plugins/topk.bro | 24 ++++++++++ src/Topk.cc | 33 ++++++++++++- src/Topk.h | 4 +- src/bro.bif | 15 ++++++ testing/btest/Baseline/bifs.topk/.stderr | 6 +++ testing/btest/Baseline/bifs.topk/out | 30 ++++++++++++ .../.stdout | 8 ++++ testing/btest/bifs/topk.bro | 31 ++++++++++++ .../scripts/base/frameworks/sumstats/topk.bro | 48 +++++++++++++++++++ 10 files changed, 198 insertions(+), 4 deletions(-) create mode 100644 scripts/base/frameworks/sumstats/plugins/topk.bro create mode 100644 testing/btest/Baseline/bifs.topk/.stderr create mode 100644 testing/btest/Baseline/scripts.base.frameworks.sumstats.topk/.stdout create mode 100644 testing/btest/scripts/base/frameworks/sumstats/topk.bro diff --git a/scripts/base/frameworks/sumstats/plugins/__load__.bro b/scripts/base/frameworks/sumstats/plugins/__load__.bro index 0d4c2ed302..35191a4776 100644 --- a/scripts/base/frameworks/sumstats/plugins/__load__.bro +++ b/scripts/base/frameworks/sumstats/plugins/__load__.bro @@ -4,5 +4,6 @@ @load ./sample @load ./std-dev @load ./sum +@load ./topk @load ./unique -@load ./variance \ No newline at end of file +@load ./variance diff --git a/scripts/base/frameworks/sumstats/plugins/topk.bro b/scripts/base/frameworks/sumstats/plugins/topk.bro new file mode 100644 index 0000000000..f64e9fb18d --- /dev/null +++ b/scripts/base/frameworks/sumstats/plugins/topk.bro @@ -0,0 +1,24 @@ +@load base/frameworks/sumstats + +module SumStats; + +export { + redef enum Calculation += { + TOPK + }; + + redef record ResultVal += { + topk: opaque of topk &default=topk_init(500); + }; + +} + +hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) + { + if ( TOPK in r$apply ) + { + topk_add(rv$topk, obs); + } + } + + diff --git a/src/Topk.cc b/src/Topk.cc index 8f4d63ed78..d5866b4f41 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -19,7 +19,7 @@ Element::~Element() value=0; } -HashKey* TopkVal::GetHash(Val* v) +HashKey* TopkVal::GetHash(Val* v) const { TypeList* tl = new TypeList(v->Type()); tl->Append(v->Type()); @@ -58,7 +58,8 @@ TopkVal::~TopkVal() type = 0; } -VectorVal* TopkVal::getTopK(int k) // returns vector + +VectorVal* TopkVal::getTopK(int k) // returns vector { if ( numElements == 0 ) { @@ -100,6 +101,34 @@ VectorVal* TopkVal::getTopK(int k) // returns vector return t; } +uint64_t TopkVal::getCount(Val* value) const + { + HashKey* key = GetHash(value); + Element* e = (Element*) elementDict->Lookup(key); + + if ( e == 0 ) + { + reporter->Error("getCount for element that is not in top-k"); + return 0; + } + + return e->parent->count; + } + +uint64_t TopkVal::getEpsilon(Val* value) const + { + HashKey* key = GetHash(value); + Element* e = (Element*) elementDict->Lookup(key); + + if ( e == 0 ) + { + reporter->Error("getEpsilon for element that is not in top-k"); + return 0; + } + + return e->epsilon; + } + void TopkVal::Encountered(Val* encountered) { // ok, let's see if we already know this one. diff --git a/src/Topk.h b/src/Topk.h index 7c983ebdfc..e4c6aa5aea 100644 --- a/src/Topk.h +++ b/src/Topk.h @@ -38,10 +38,12 @@ public: ~TopkVal(); void Encountered(Val* value); // we saw something VectorVal* getTopK(int k); // returns vector + uint64_t getCount(Val* value) const; + uint64_t getEpsilon(Val* value) const; private: void IncrementCounter(Element* e); - HashKey* GetHash(Val*); // this probably should go somewhere else. + HashKey* GetHash(Val*) const; // this probably should go somewhere else. BroType* type; std::list buckets; diff --git a/src/bro.bif b/src/bro.bif index 695337bcf1..e8e78c7872 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5669,3 +5669,18 @@ function topk_get_top%(handle: opaque of topk, k: count%): any Topk::TopkVal* h = (Topk::TopkVal*) handle; return h->getTopK(k); %} + +function topk_count%(handle: opaque of topk, value: any%): count + %{ + assert(handle); + Topk::TopkVal* h = (Topk::TopkVal*) handle; + return new Val(h->getCount(value), TYPE_COUNT); + %} + +function topk_epsilon%(handle: opaque of topk, value: any%): count + %{ + assert(handle); + Topk::TopkVal* h = (Topk::TopkVal*) handle; + return new Val(h->getEpsilon(value), TYPE_COUNT); + %} + diff --git a/testing/btest/Baseline/bifs.topk/.stderr b/testing/btest/Baseline/bifs.topk/.stderr new file mode 100644 index 0000000000..f57e35ca51 --- /dev/null +++ b/testing/btest/Baseline/bifs.topk/.stderr @@ -0,0 +1,6 @@ +error: getCount for element that is not in top-k +error: getEpsilon for element that is not in top-k +error: getCount for element that is not in top-k +error: getEpsilon for element that is not in top-k +error: getCount for element that is not in top-k +error: getEpsilon for element that is not in top-k diff --git a/testing/btest/Baseline/bifs.topk/out b/testing/btest/Baseline/bifs.topk/out index 94aa5bd572..2116a30a12 100644 --- a/testing/btest/Baseline/bifs.topk/out +++ b/testing/btest/Baseline/bifs.topk/out @@ -1,7 +1,37 @@ [b, c] +0 +0 +2 +0 +2 +1 [d, c] +0 +0 +2 +1 +3 +2 [d, e] +3 +2 +3 +2 [f, e] +4 +3 +3 +2 [f, e] +4 +3 +4 +2 [g, e] +0 +0 +4 +2 +5 +4 [c, e, d] diff --git a/testing/btest/Baseline/scripts.base.frameworks.sumstats.topk/.stdout b/testing/btest/Baseline/scripts.base.frameworks.sumstats.topk/.stdout new file mode 100644 index 0000000000..c85316eecc --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.sumstats.topk/.stdout @@ -0,0 +1,8 @@ +Top entries for key counter +Num: 1, count: 99, epsilon: 0 +Num: 2, count: 98, epsilon: 0 +Num: 3, count: 97, epsilon: 0 +Num: 4, count: 96, epsilon: 0 +Num: 5, count: 95, epsilon: 0 +Top entries for key two +Num: 1, count: 2, epsilon: 0 diff --git a/testing/btest/bifs/topk.bro b/testing/btest/bifs/topk.bro index af1f38c773..9d936ce2f4 100644 --- a/testing/btest/bifs/topk.bro +++ b/testing/btest/bifs/topk.bro @@ -1,5 +1,6 @@ # @TEST-EXEC: bro -b %INPUT > out # @TEST-EXEC: btest-diff out +# @TEST-EXEC: btest-diff .stderr event bro_init() { @@ -13,26 +14,56 @@ event bro_init() local s = topk_get_top(k1, 5); print s; + print topk_count(k1, "a"); + print topk_epsilon(k1, "a"); + print topk_count(k1, "b"); + print topk_epsilon(k1, "b"); + print topk_count(k1, "c"); + print topk_epsilon(k1, "c"); topk_add(k1, "d"); s = topk_get_top(k1, 5); print s; + print topk_count(k1, "b"); + print topk_epsilon(k1, "b"); + print topk_count(k1, "c"); + print topk_epsilon(k1, "c"); + print topk_count(k1, "d"); + print topk_epsilon(k1, "d"); topk_add(k1, "e"); s = topk_get_top(k1, 5); print s; + print topk_count(k1, "d"); + print topk_epsilon(k1, "d"); + print topk_count(k1, "e"); + print topk_epsilon(k1, "e"); topk_add(k1, "f"); s = topk_get_top(k1, 5); print s; + print topk_count(k1, "f"); + print topk_epsilon(k1, "f"); + print topk_count(k1, "e"); + print topk_epsilon(k1, "e"); topk_add(k1, "e"); s = topk_get_top(k1, 5); print s; + print topk_count(k1, "f"); + print topk_epsilon(k1, "f"); + print topk_count(k1, "e"); + print topk_epsilon(k1, "e"); topk_add(k1, "g"); s = topk_get_top(k1, 5); print s; + print topk_count(k1, "f"); + print topk_epsilon(k1, "f"); + print topk_count(k1, "e"); + print topk_epsilon(k1, "e"); + print topk_count(k1, "g"); + print topk_epsilon(k1, "g"); k1 = topk_init(100); topk_add(k1, "a"); diff --git a/testing/btest/scripts/base/frameworks/sumstats/topk.bro b/testing/btest/scripts/base/frameworks/sumstats/topk.bro new file mode 100644 index 0000000000..22a5af1bc7 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/sumstats/topk.bro @@ -0,0 +1,48 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +event bro_init() &priority=5 + { + local r1: SumStats::Reducer = [$stream="test.metric", + $apply=set(SumStats::TOPK)]; + SumStats::create([$epoch=3secs, + $reducers=set(r1), + $epoch_finished(data: SumStats::ResultTable) = + { + for ( key in data ) + { + local r = data[key]["test.metric"]; + + local s: vector of SumStats::Observation; + s = topk_get_top(r$topk, 5); + + print fmt("Top entries for key %s", key$str); + for ( element in s ) + { + print fmt("Num: %d, count: %d, epsilon: %d", s[element]$num, topk_count(r$topk, s[element]), topk_epsilon(r$topk, s[element])); + } + + } + } + ]); + + + const loop_v: vector of count = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100}; + + local a: count; + a = 0; + + for ( i in loop_v ) + { + a = a + 1; + for ( j in loop_v ) + { + if ( i < j ) + SumStats::observe("test.metric", [$str="counter"], [$num=a]); + } + } + + + SumStats::observe("test.metric", [$str="two"], [$num=1]); + SumStats::observe("test.metric", [$str="two"], [$num=1]); + } From a426c7612270b5cc40143cc14b4e3c42c6499617 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 23 Apr 2013 18:23:34 -0700 Subject: [PATCH 078/881] make the get function const --- src/Topk.cc | 4 ++-- src/Topk.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Topk.cc b/src/Topk.cc index d5866b4f41..b89fa2e96f 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -59,7 +59,7 @@ TopkVal::~TopkVal() } -VectorVal* TopkVal::getTopK(int k) // returns vector +VectorVal* TopkVal::getTopK(int k) const // returns vector { if ( numElements == 0 ) { @@ -76,7 +76,7 @@ VectorVal* TopkVal::getTopK(int k) // returns vector // in any case - just to make this future-proof (and I am lazy) - this can return more than k. int read = 0; - std::list::iterator it = buckets.end(); + std::list::const_iterator it = buckets.end(); it--; while (read < k ) { diff --git a/src/Topk.h b/src/Topk.h index e4c6aa5aea..f486948c5c 100644 --- a/src/Topk.h +++ b/src/Topk.h @@ -37,7 +37,7 @@ public: TopkVal(uint64 size); ~TopkVal(); void Encountered(Val* value); // we saw something - VectorVal* getTopK(int k); // returns vector + VectorVal* getTopK(int k) const; // returns vector uint64_t getCount(Val* value) const; uint64_t getEpsilon(Val* value) const; From 6f863d2259a5d388068f4ad70571ab62dcaa9cd4 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 23 Apr 2013 23:24:02 -0700 Subject: [PATCH 079/881] add serialization for topk --- src/SerialTypes.h | 1 + src/Topk.cc | 108 ++++++++++++++++++ src/Topk.h | 5 + .../btest/Baseline/bifs.topk_persistence/out | 21 ++++ testing/btest/bifs/topk_persistence.bro | 74 ++++++++++++ 5 files changed, 209 insertions(+) create mode 100644 testing/btest/Baseline/bifs.topk_persistence/out create mode 100644 testing/btest/bifs/topk_persistence.bro diff --git a/src/SerialTypes.h b/src/SerialTypes.h index 723badab1e..f07392eff4 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -104,6 +104,7 @@ SERIAL_VAL(MD5_VAL, 16) SERIAL_VAL(SHA1_VAL, 17) SERIAL_VAL(SHA256_VAL, 18) SERIAL_VAL(ENTROPY_VAL, 19) +SERIAL_VAL(TOPK_VAL, 20) #define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR) SERIAL_EXPR(EXPR, 1) diff --git a/src/Topk.cc b/src/Topk.cc index b89fa2e96f..a31f49adf4 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -3,9 +3,13 @@ #include "Topk.h" #include "CompHash.h" #include "Reporter.h" +#include "Serializer.h" + namespace Topk { +IMPLEMENT_SERIAL(TopkVal, SER_TOPK_VAL); + static void topk_element_hash_delete_func(void* val) { Element* e = (Element*) val; @@ -40,6 +44,15 @@ TopkVal::TopkVal(uint64 arg_size) : OpaqueVal(new OpaqueType("topk")) numElements = 0; } +TopkVal::TopkVal() : OpaqueVal(new OpaqueType("topk")) + { + elementDict = new PDict(Element); + elementDict->SetDeleteFunc(topk_element_hash_delete_func); + size = 0; + type = 0; + numElements = 0; + } + TopkVal::~TopkVal() { elementDict->Clear(); @@ -59,6 +72,101 @@ TopkVal::~TopkVal() } +bool TopkVal::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_TOPK_VAL, OpaqueVal); + + bool v = true; + + v &= SERIALIZE(size); + v &= SERIALIZE(numElements); + bool type_present = (type != 0); + v &= SERIALIZE(type_present); + if ( type_present ) + v &= type->Serialize(info); + else + assert(numElements == 0); + + int i = 0; + std::list::const_iterator it = buckets.begin(); + while ( it != buckets.end() ) + { + Bucket* b = *it; + uint32_t elements_count = b->elements.size(); + v &= SERIALIZE(elements_count); + v &= SERIALIZE(b->count); + std::list::const_iterator eit = b->elements.begin(); + while ( eit != b->elements.end() ) + { + Element* element = *eit; + v &= SERIALIZE(element->epsilon); + v &= element->value->Serialize(info); + + eit++; + i++; + } + + it++; + } + + assert(i == numElements); + + return v; + } + +bool TopkVal::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(OpaqueVal); + + bool v = true; + + v &= UNSERIALIZE(&size); + v &= UNSERIALIZE(&numElements); + bool type_present = false; + v &= UNSERIALIZE(&type_present); + if ( type_present ) + { + type = BroType::Unserialize(info); + assert(type); + } + else + assert(numElements == 0); + + int i = 0; + while ( i < numElements ) + { + Bucket* b = new Bucket(); + uint32_t elements_count; + v &= UNSERIALIZE(&elements_count); + v &= UNSERIALIZE(&b->count); + b->bucketPos = buckets.insert(buckets.end(), b); + + for ( int j = 0; j < elements_count; j++ ) + { + Element* e = new Element(); + v &= UNSERIALIZE(&e->epsilon); + e->value = Val::Unserialize(info, type); + e->parent = b; + + b->elements.insert(b->elements.end(), e); + + HashKey* key = GetHash(e->value); + assert ( elementDict->Lookup(key) == 0 ); + + elementDict->Insert(key, e); + delete key; + + + i++; + } + } + + assert(i == numElements); + + return v; + } + + VectorVal* TopkVal::getTopK(int k) const // returns vector { if ( numElements == 0 ) diff --git a/src/Topk.h b/src/Topk.h index f486948c5c..0e38319380 100644 --- a/src/Topk.h +++ b/src/Topk.h @@ -41,6 +41,9 @@ public: uint64_t getCount(Val* value) const; uint64_t getEpsilon(Val* value) const; +protected: + TopkVal(); // for deserialize + private: void IncrementCounter(Element* e); HashKey* GetHash(Val*) const; // this probably should go somewhere else. @@ -50,6 +53,8 @@ private: PDict(Element)* elementDict; uint64 size; // how many elements are we tracking? uint64 numElements; // how many elements do we have at the moment + + DECLARE_SERIAL(TopkVal); }; }; diff --git a/testing/btest/Baseline/bifs.topk_persistence/out b/testing/btest/Baseline/bifs.topk_persistence/out new file mode 100644 index 0000000000..ef3d0cef30 --- /dev/null +++ b/testing/btest/Baseline/bifs.topk_persistence/out @@ -0,0 +1,21 @@ +1 +2 +6 +4 +5 +1 +[c, e, d] +1 +2 +6 +4 +5 +1 +[c, e, d] +2 +4 +12 +8 +10 +2 +[c, e, d] diff --git a/testing/btest/bifs/topk_persistence.bro b/testing/btest/bifs/topk_persistence.bro new file mode 100644 index 0000000000..4d599c2780 --- /dev/null +++ b/testing/btest/bifs/topk_persistence.bro @@ -0,0 +1,74 @@ +# @TEST-EXEC: bro -b %INPUT runnumber=1 >out +# @TEST-EXEC: bro -b %INPUT runnumber=2 >>out +# @TEST-EXEC: bro -b %INPUT runnumber=3 >>out +# @TEST-EXEC: btest-diff out + +global runnumber: count &redef; # differentiate runs + +global k1: opaque of topk &persistent; +global k2: opaque of topk &persistent; + +event bro_init() + { + + k2 = topk_init(20); + + if ( runnumber == 1 ) + { + k1 = topk_init(100); + + topk_add(k1, "a"); + topk_add(k1, "b"); + topk_add(k1, "b"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "f"); + } + + local s = topk_get_top(k1, 3); + print topk_count(k1, "a"); + print topk_count(k1, "b"); + print topk_count(k1, "c"); + print topk_count(k1, "d"); + print topk_count(k1, "e"); + print topk_count(k1, "f"); + + if ( runnumber == 2 ) + { + topk_add(k1, "a"); + topk_add(k1, "b"); + topk_add(k1, "b"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "c"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "d"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "e"); + topk_add(k1, "f"); + } + + print s; + + } From 2f48008c423019c05a209939f00d8c52d29eb1ee Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 24 Apr 2013 06:17:51 -0700 Subject: [PATCH 080/881] implement merging for top-k. I am not (entirely) sure that this is mathematically correct, but I am (more and more) getting the feeling that it... might be. In any case - this was the last step and now it should work in cluster settings. --- .../base/frameworks/sumstats/plugins/topk.bro | 7 ++ src/Topk.cc | 106 ++++++++++++++++-- src/Topk.h | 3 +- src/bro.bif | 13 +++ testing/btest/Baseline/bifs.topk/.stderr | 4 + testing/btest/Baseline/bifs.topk/out | 20 ++++ testing/btest/bifs/topk.bro | 28 +++++ 7 files changed, 173 insertions(+), 8 deletions(-) diff --git a/scripts/base/frameworks/sumstats/plugins/topk.bro b/scripts/base/frameworks/sumstats/plugins/topk.bro index f64e9fb18d..6107a252ae 100644 --- a/scripts/base/frameworks/sumstats/plugins/topk.bro +++ b/scripts/base/frameworks/sumstats/plugins/topk.bro @@ -22,3 +22,10 @@ hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) } +hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) + { + result$topk = topk_init(500); + + topk_merge(result$topk, rv1$topk); + topk_merge(result$topk, rv2$topk); + } diff --git a/src/Topk.cc b/src/Topk.cc index a31f49adf4..8ad2113235 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -71,6 +71,97 @@ TopkVal::~TopkVal() type = 0; } +void TopkVal::Merge(const TopkVal* value) + { + + if ( type == 0 ) + { + assert(numElements == 0); + type = value->type->Ref(); + } + else + if ( !same_type(type, value->type) ) + { + reporter->Error("Tried to merge top-k elements of differing types. Aborted"); + return; + } + + std::list::const_iterator it = value->buckets.begin(); + while ( it != value->buckets.end() ) + { + Bucket* b = *it; + uint64_t currcount = b->count; + std::list::const_iterator eit = b->elements.begin(); + + while ( eit != b->elements.end() ) + { + Element* e = *eit; + // lookup if we already know this one... + HashKey* key = GetHash(e->value); + Element* olde = (Element*) elementDict->Lookup(key); + + if ( olde == 0 ) + { + olde = new Element(); + olde->epsilon=0; + olde->value = e->value->Ref(); + // insert at bucket position 0 + if ( buckets.size() > 0 ) + { + assert (buckets.front()-> count > 0 ); + } + + Bucket* newbucket = new Bucket(); + newbucket->count = 0; + newbucket->bucketPos = buckets.insert(buckets.begin(), newbucket); + + olde->parent = newbucket; + newbucket->elements.insert(newbucket->elements.end(), olde); + + elementDict->Insert(key, olde); + numElements++; + + } + + // now that we are sure that the old element is present - increment epsilon + olde->epsilon += e->epsilon; + // and increment position... + IncrementCounter(olde, currcount); + delete key; + + eit++; + } + + it++; + } + + // now we have added everything. And our top-k table could be too big. + // prune everything... + + assert(size > 0); + while ( numElements > size ) + { + assert(buckets.size() > 0 ); + Bucket* b = buckets.front(); + assert(b->elements.size() > 0); + + Element* e = b->elements.front(); + HashKey* key = GetHash(e->value); + elementDict->RemoveEntry(key); + delete e; + + b->elements.pop_front(); + + if ( b->elements.size() == 0 ) + { + delete b; + buckets.pop_front(); + } + + numElements--; + } + + } bool TopkVal::DoSerialize(SerialInfo* info) const { @@ -318,7 +409,8 @@ void TopkVal::Encountered(Val* encountered) } -void TopkVal::IncrementCounter(Element* e) +// increment by count +void TopkVal::IncrementCounter(Element* e, unsigned int count) { Bucket* currBucket = e->parent; uint64 currcount = currBucket->count; @@ -330,11 +422,11 @@ void TopkVal::IncrementCounter(Element* e) bucketIter++; - if ( bucketIter != buckets.end() ) - { - if ( (*bucketIter)->count == currcount+1 ) - nextBucket = *bucketIter; - } + while ( bucketIter != buckets.end() && (*bucketIter)->count < currcount+count ) + bucketIter++; + + if ( bucketIter != buckets.end() && (*bucketIter)->count == currcount+count ) + nextBucket = *bucketIter; if ( nextBucket == 0 ) { @@ -342,7 +434,7 @@ void TopkVal::IncrementCounter(Element* e) // create it... Bucket* b = new Bucket(); - b->count = currcount+1; + b->count = currcount+count; std::list::iterator nextBucketPos = buckets.insert(bucketIter, b); b->bucketPos = nextBucketPos; // and give it the iterator we know now. diff --git a/src/Topk.h b/src/Topk.h index 0e38319380..30e87f7a99 100644 --- a/src/Topk.h +++ b/src/Topk.h @@ -40,12 +40,13 @@ public: VectorVal* getTopK(int k) const; // returns vector uint64_t getCount(Val* value) const; uint64_t getEpsilon(Val* value) const; + void Merge(const TopkVal* value); protected: TopkVal(); // for deserialize private: - void IncrementCounter(Element* e); + void IncrementCounter(Element* e, unsigned int count = 1); HashKey* GetHash(Val*) const; // this probably should go somewhere else. BroType* type; diff --git a/src/bro.bif b/src/bro.bif index e8e78c7872..b6f101c025 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5684,3 +5684,16 @@ function topk_epsilon%(handle: opaque of topk, value: any%): count return new Val(h->getEpsilon(value), TYPE_COUNT); %} +function topk_merge%(handle1: opaque of topk, handle2: opaque of topk%): any + %{ + assert(handle1); + assert(handle2); + + Topk::TopkVal* h1 = (Topk::TopkVal*) handle1; + Topk::TopkVal* h2 = (Topk::TopkVal*) handle2; + + h1->Merge(h2); + + return 0; + %} + diff --git a/testing/btest/Baseline/bifs.topk/.stderr b/testing/btest/Baseline/bifs.topk/.stderr index f57e35ca51..f2bd316fd8 100644 --- a/testing/btest/Baseline/bifs.topk/.stderr +++ b/testing/btest/Baseline/bifs.topk/.stderr @@ -4,3 +4,7 @@ error: getCount for element that is not in top-k error: getEpsilon for element that is not in top-k error: getCount for element that is not in top-k error: getEpsilon for element that is not in top-k +error: getCount for element that is not in top-k +error: getEpsilon for element that is not in top-k +error: getCount for element that is not in top-k +error: getEpsilon for element that is not in top-k diff --git a/testing/btest/Baseline/bifs.topk/out b/testing/btest/Baseline/bifs.topk/out index 2116a30a12..8db55eeca8 100644 --- a/testing/btest/Baseline/bifs.topk/out +++ b/testing/btest/Baseline/bifs.topk/out @@ -35,3 +35,23 @@ 5 4 [c, e, d] +6 +0 +5 +0 +4 +0 +[c, e] +6 +0 +5 +0 +0 +0 +[c, e] +12 +0 +10 +0 +0 +0 diff --git a/testing/btest/bifs/topk.bro b/testing/btest/bifs/topk.bro index 9d936ce2f4..92a68999cc 100644 --- a/testing/btest/bifs/topk.bro +++ b/testing/btest/bifs/topk.bro @@ -87,6 +87,34 @@ event bro_init() topk_add(k1, "f"); s = topk_get_top(k1, 3); print s; + print topk_count(k1, "c"); + print topk_epsilon(k1, "c"); + print topk_count(k1, "e"); + print topk_epsilon(k1, "d"); + print topk_count(k1, "d"); + print topk_epsilon(k1, "d"); + local k3 = topk_init(2); + topk_merge(k3, k1); + + s = topk_get_top(k3, 3); + print s; + print topk_count(k3, "c"); + print topk_epsilon(k3, "c"); + print topk_count(k3, "e"); + print topk_epsilon(k3, "e"); + print topk_count(k3, "d"); + print topk_epsilon(k3, "d"); + + topk_merge(k3, k1); + + s = topk_get_top(k3, 3); + print s; + print topk_count(k3, "c"); + print topk_epsilon(k3, "c"); + print topk_count(k3, "e"); + print topk_epsilon(k3, "e"); + print topk_count(k3, "d"); + print topk_epsilon(k3, "d"); } From c0890f2a0f1448dc81f4b3e6b3e54a45a6e5a08b Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 24 Apr 2013 15:01:06 -0700 Subject: [PATCH 081/881] make size of topk-list configureable when using sumstats --- scripts/base/frameworks/sumstats/plugins/topk.bro | 15 +++++++++++++-- src/Topk.h | 1 + src/bro.bif | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/scripts/base/frameworks/sumstats/plugins/topk.bro b/scripts/base/frameworks/sumstats/plugins/topk.bro index 6107a252ae..a830b1c5ec 100644 --- a/scripts/base/frameworks/sumstats/plugins/topk.bro +++ b/scripts/base/frameworks/sumstats/plugins/topk.bro @@ -3,16 +3,27 @@ module SumStats; export { + redef record Reducer += { + ## number of elements to keep in the top-k list + topk_size: count &default=500; + }; + redef enum Calculation += { TOPK }; redef record ResultVal += { - topk: opaque of topk &default=topk_init(500); + topk: opaque of topk &optional; }; } +hook init_resultval_hook(r: Reducer, rv: ResultVal) + { + if ( TOPK in r$apply && ! rv?$topk ) + rv$topk = topk_init(r$topk_size); + } + hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) { if ( TOPK in r$apply ) @@ -24,7 +35,7 @@ hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { - result$topk = topk_init(500); + result$topk = topk_init(topk_size(rv1$topk)); topk_merge(result$topk, rv1$topk); topk_merge(result$topk, rv2$topk); diff --git a/src/Topk.h b/src/Topk.h index 30e87f7a99..51a2d75251 100644 --- a/src/Topk.h +++ b/src/Topk.h @@ -40,6 +40,7 @@ public: VectorVal* getTopK(int k) const; // returns vector uint64_t getCount(Val* value) const; uint64_t getEpsilon(Val* value) const; + uint64_t getSize() const { return size; } void Merge(const TopkVal* value); protected: diff --git a/src/bro.bif b/src/bro.bif index b6f101c025..4d0db54c8c 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5684,6 +5684,13 @@ function topk_epsilon%(handle: opaque of topk, value: any%): count return new Val(h->getEpsilon(value), TYPE_COUNT); %} +function topk_size%(handle: opaque of topk%): count + %{ + assert(handle); + Topk::TopkVal* h = (Topk::TopkVal*) handle; + return new Val(h->getSize(), TYPE_COUNT); + %} + function topk_merge%(handle1: opaque of topk, handle2: opaque of topk%): any %{ assert(handle1); From 12cbf20ce07a8cd8a9eb6fd866d2c83855eda865 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 24 Apr 2013 15:30:24 -0700 Subject: [PATCH 082/881] add topk cluster test --- .../manager-1..stdout | 9 ++ .../base/frameworks/sumstats/topk-cluster.bro | 110 ++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 testing/btest/Baseline/scripts.base.frameworks.sumstats.topk-cluster/manager-1..stdout create mode 100644 testing/btest/scripts/base/frameworks/sumstats/topk-cluster.bro diff --git a/testing/btest/Baseline/scripts.base.frameworks.sumstats.topk-cluster/manager-1..stdout b/testing/btest/Baseline/scripts.base.frameworks.sumstats.topk-cluster/manager-1..stdout new file mode 100644 index 0000000000..2d076eeac7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.sumstats.topk-cluster/manager-1..stdout @@ -0,0 +1,9 @@ +Top entries for key counter +Num: 995, count: 100, epsilon: 0 +Num: 1, count: 99, epsilon: 0 +Num: 2, count: 98, epsilon: 0 +Num: 3, count: 97, epsilon: 0 +Num: 4, count: 96, epsilon: 0 +Top entries for key two +Num: 2, count: 4, epsilon: 0 +Num: 1, count: 3, epsilon: 0 diff --git a/testing/btest/scripts/base/frameworks/sumstats/topk-cluster.bro b/testing/btest/scripts/base/frameworks/sumstats/topk-cluster.bro new file mode 100644 index 0000000000..0ade38e86c --- /dev/null +++ b/testing/btest/scripts/base/frameworks/sumstats/topk-cluster.bro @@ -0,0 +1,110 @@ +# @TEST-SERIALIZE: comm +# +# @TEST-EXEC: btest-bg-run manager-1 BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro %INPUT +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT +# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT +# @TEST-EXEC: btest-bg-wait 15 + +# @TEST-EXEC: btest-diff manager-1/.stdout +# +@TEST-START-FILE cluster-layout.bro +redef Cluster::nodes = { + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1", "worker-2")], + ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37760/tcp, $manager="manager-1", $interface="eth0"], + ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37761/tcp, $manager="manager-1", $interface="eth1"], +}; +@TEST-END-FILE + +redef Log::default_rotation_interval = 0secs; + + +event bro_init() &priority=5 + { + local r1: SumStats::Reducer = [$stream="test.metric", + $apply=set(SumStats::TOPK)]; + SumStats::create([$epoch=5secs, + $reducers=set(r1), + $epoch_finished(data: SumStats::ResultTable) = + { + for ( key in data ) + { + local r = data[key]["test.metric"]; + + local s: vector of SumStats::Observation; + s = topk_get_top(r$topk, 5); + + print fmt("Top entries for key %s", key$str); + for ( element in s ) + { + print fmt("Num: %d, count: %d, epsilon: %d", s[element]$num, topk_count(r$topk, s[element]), topk_epsilon(r$topk, s[element])); + } + + terminate(); + } + } + ]); + + + } + +event remote_connection_closed(p: event_peer) + { + terminate(); + } + +global ready_for_data: event(); +redef Cluster::manager2worker_events += /^ready_for_data$/; + +event ready_for_data() + { + const loop_v: vector of count = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100}; + + + if ( Cluster::node == "worker-1" ) + { + + local a: count; + a = 0; + + for ( i in loop_v ) + { + a = a + 1; + for ( j in loop_v ) + { + if ( i < j ) + SumStats::observe("test.metric", [$str="counter"], [$num=a]); + } + } + + + SumStats::observe("test.metric", [$str="two"], [$num=1]); + SumStats::observe("test.metric", [$str="two"], [$num=1]); + } + if ( Cluster::node == "worker-2" ) + { + SumStats::observe("test.metric", [$str="two"], [$num=2]); + SumStats::observe("test.metric", [$str="two"], [$num=2]); + SumStats::observe("test.metric", [$str="two"], [$num=2]); + SumStats::observe("test.metric", [$str="two"], [$num=2]); + SumStats::observe("test.metric", [$str="two"], [$num=1]); + + for ( i in loop_v ) + { + SumStats::observe("test.metric", [$str="counter"], [$num=995]); + } + } + } + +@if ( Cluster::local_node_type() == Cluster::MANAGER ) + +global peer_count = 0; +event remote_connection_handshake_done(p: event_peer) &priority=-5 + { + ++peer_count; + if ( peer_count == 2 ) + event ready_for_data(); + } + +@endif + From f2967f485b0f27365421523842121b1a44c1721c Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 24 Apr 2013 16:03:40 -0700 Subject: [PATCH 083/881] add persistence test not using predetermined random seeds. This is failing at the moment. --- .../btest/bifs/hll_persistence_twoseeds.bro | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 testing/btest/bifs/hll_persistence_twoseeds.bro diff --git a/testing/btest/bifs/hll_persistence_twoseeds.bro b/testing/btest/bifs/hll_persistence_twoseeds.bro new file mode 100644 index 0000000000..4d828dafc9 --- /dev/null +++ b/testing/btest/bifs/hll_persistence_twoseeds.bro @@ -0,0 +1,40 @@ +# @TEST-EXEC: BRO_SEED_FILE="" bro -b %INPUT runnumber=1 >out +# @TEST-EXEC: BRO_SEED_FILE="" bro -b %INPUT runnumber=2 >>out +# @TEST-EXEC: BRO_SEED_FILE="" bro -b %INPUT runnumber=3 >>out +# @TEST-EXEC: btest-diff out + +global runnumber: count &redef; # differentiate first and second run + +global card: opaque of cardinality &persistent; + +event bro_init() + { + print runnumber; + + if ( runnumber == 1 ) + { + card = hll_cardinality_init(0.01); + + hll_cardinality_add(card, "a"); + hll_cardinality_add(card, "b"); + hll_cardinality_add(card, "c"); + hll_cardinality_add(card, "d"); + hll_cardinality_add(card, "e"); + hll_cardinality_add(card, "f"); + hll_cardinality_add(card, "g"); + hll_cardinality_add(card, "h"); + hll_cardinality_add(card, "i"); + hll_cardinality_add(card, "j"); + } + + print hll_cardinality_estimate(card); + + if ( runnumber == 2 ) + { + hll_cardinality_add(card, "a"); + hll_cardinality_add(card, "b"); + hll_cardinality_add(card, "c"); + hll_cardinality_add(card, "aa"); + } + } + From 5608caf79afd850f5bc610acfca7bd69b982ad88 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 25 Apr 2013 14:20:13 -0700 Subject: [PATCH 084/881] make error rate configureable --- .../frameworks/sumstats/plugins/hll_unique.bro | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/scripts/base/frameworks/sumstats/plugins/hll_unique.bro b/scripts/base/frameworks/sumstats/plugins/hll_unique.bro index 47ded2ca60..41889532f3 100644 --- a/scripts/base/frameworks/sumstats/plugins/hll_unique.bro +++ b/scripts/base/frameworks/sumstats/plugins/hll_unique.bro @@ -3,6 +3,11 @@ module SumStats; export { + redef record Reducer += { + ## The threshold when we switch to hll + hll_error_margin: double &default=0.01; + }; + redef enum Calculation += { ## Calculate the number of unique values. HLLUNIQUE @@ -19,14 +24,18 @@ redef record ResultVal += { # Internal use only. This is not meant to be publically available # because probabilistic data structures have to be examined using # specialized bifs. - card: opaque of cardinality &default=hll_cardinality_init(0.01); + card: opaque of cardinality &optional; + + # we need this in the compose hook. + hll_error_margin: double &optional; }; hook init_resultval_hook(r: Reducer, rv: ResultVal) { if ( HLLUNIQUE in r$apply && ! rv?$card ) - rv$card = hll_cardinality_init(0.01); + rv$card = hll_cardinality_init(r$hll_error_margin); + rv$hll_error_margin = r$hll_error_margin; rv$hllunique = 0; } @@ -42,7 +51,7 @@ hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { - local rhll = hll_cardinality_init(0.01); + local rhll = hll_cardinality_init(rv1$hll_error_margin); hll_cardinality_merge_into(rhll, rv1$card); hll_cardinality_merge_into(rhll, rv2$card); From fd2e0503068117d406a87b9a6d7d843b59289f59 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Fri, 26 Apr 2013 11:34:07 -0700 Subject: [PATCH 085/881] fix warnings --- src/Topk.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Topk.cc b/src/Topk.cc index 8ad2113235..26f14c4fcb 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -178,7 +178,7 @@ bool TopkVal::DoSerialize(SerialInfo* info) const else assert(numElements == 0); - int i = 0; + uint64_t i = 0; std::list::const_iterator it = buckets.begin(); while ( it != buckets.end() ) { @@ -223,7 +223,7 @@ bool TopkVal::DoUnserialize(UnserialInfo* info) else assert(numElements == 0); - int i = 0; + uint64_t i = 0; while ( i < numElements ) { Bucket* b = new Bucket(); @@ -232,7 +232,7 @@ bool TopkVal::DoUnserialize(UnserialInfo* info) v &= UNSERIALIZE(&b->count); b->bucketPos = buckets.insert(buckets.end(), b); - for ( int j = 0; j < elements_count; j++ ) + for ( uint64_t j = 0; j < elements_count; j++ ) { Element* e = new Element(); v &= UNSERIALIZE(&e->epsilon); From 1accee41edb48f7ed162f879bdf593f505d84b5b Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Fri, 26 Apr 2013 14:06:38 -0700 Subject: [PATCH 086/881] fix memory leaks --- src/Topk.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Topk.cc b/src/Topk.cc index 26f14c4fcb..116a4d3de4 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -26,12 +26,13 @@ Element::~Element() HashKey* TopkVal::GetHash(Val* v) const { TypeList* tl = new TypeList(v->Type()); - tl->Append(v->Type()); + tl->Append(v->Type()->Ref()); CompositeHash* topk_hash = new CompositeHash(tl); Unref(tl); HashKey* key = topk_hash->ComputeHash(v, 1); assert(key); + delete topk_hash; return key; } @@ -311,6 +312,7 @@ uint64_t TopkVal::getCount(Val* value) const return 0; } + delete key; return e->parent->count; } @@ -325,6 +327,7 @@ uint64_t TopkVal::getEpsilon(Val* value) const return 0; } + delete key; return e->epsilon; } From cb3e05edd486f73f0a0a8a00aded4e4341eadd77 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 28 Apr 2013 15:48:44 -0400 Subject: [PATCH 087/881] Include Notice Policy shortcuts in the Scripting User Manual. Include two tests and baselines for the RST output. --- doc/scripting/index.rst | 30 +++++++++++++++++++ .../.stdout | 0 .../.stdout | 0 .../manual/framework_notice_shortcuts_01.bro | 11 +++++++ .../manual/framework_notice_shortcuts_02.bro | 10 +++++++ 5 files changed, 51 insertions(+) create mode 100644 testing/btest/Baseline/doc.manual.framework_notice_shortcuts_01/.stdout create mode 100644 testing/btest/Baseline/doc.manual.framework_notice_shortcuts_02/.stdout create mode 100644 testing/btest/doc/manual/framework_notice_shortcuts_01.bro create mode 100644 testing/btest/doc/manual/framework_notice_shortcuts_02.bro diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index c7fcc93ea9..84004e5ab6 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -590,6 +590,36 @@ The ``$suppress_for`` variable can also be altered in a ``Notice::policy`` hook, :linenos: :lines: 6-12 +While ``Notice::policy`` hooks allow you to build custom predicate-based policies for a deployment, there are bound to be times where you don't require the full expressiveness that a hook allows. In short, there will be notice policy considerations where a broad decision can be made based on the ``Notice::Type`` alone. To facilitate these types of decisions, the Notice Framework supports Notice Policy shortcuts. These shortcuts are implemented through the means of a group of data structures that map specific, pre-defined details and actions to the effective name of a notice. Primarily implemented as a set or table of enumerables of ``Notice::Type``, Notice Policy shortcuts can be placed as a single directive in your ``local.bro`` file as a conscise readable configuration. As these variables are all constants, it bears mentioning that these variables are all set at parsetime before Bro is fully up and running and not set dynamically. + ++------------------------------------+-----------------------------------------------------+-------------------------------------+ +| Name | Description | Data Type | ++====================================+=====================================================+=====================================+ +| Notice::ignored_types | Ignore the Notice::Type entirely | set[Notice::Type] | ++------------------------------------+-----------------------------------------------------+-------------------------------------+ +| Notice::emailed_types | Set Notice::ACTION_EMAIL to this Notice::Type | set[Notice::Type] | ++------------------------------------+-----------------------------------------------------+-------------------------------------+ +| Notice::alarmed_types | Set Notice::ACTION_ALARM to this Notice::Type | set[Notice::Type] | ++------------------------------------+-----------------------------------------------------+-------------------------------------+ +| Notice::not_suppressed_types | Remove suppression from this Notice::Type | set[Notice::Type] | ++------------------------------------+-----------------------------------------------------+-------------------------------------+ +| Notice::type_suppression_intervals | Alter the $suppress_for value for this Notice::Type | table[Notice::Type] of interval | ++------------------------------------+-----------------------------------------------------+-------------------------------------+ +The table above details the five Notice Policy shortcuts, their meaning and the data type used to implement them. With the exception of ``Notice::type_suppression_intervals`` a ``set`` data type is employed to hold the ``Notice::Type`` of the notice upon which a shortcut should applied. The first three shortcuts are fairly self explanatory, applying an action to the ``Notice::Type`` elements in the set, while the latter two shortcuts alter details of the suppression being applied to the Notice. The shortcut ``Notice::not_suppressed_types`` can be used to remove the configured suppression from a notice while ``Notice::type_suppression_intervals`` can be used to alter the suppression interval defined by $suppress_for in the call to ``NOTICE()``. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_shortcuts_01.bro + :language: bro + :linenos: + :lines: 7-10 + +The Notice Policy shortcut above adds the ``Notice::Types`` of SSH::Interesting_Hostname_Login and SSH::Login to the Notice::emailed_types set while the shortcut below alters the length of time for which those notices will be suppressed. + +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_shortcuts_02.bro + :language: bro + :linenos: + :lines: 7-10 + + diff --git a/testing/btest/Baseline/doc.manual.framework_notice_shortcuts_01/.stdout b/testing/btest/Baseline/doc.manual.framework_notice_shortcuts_01/.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/Baseline/doc.manual.framework_notice_shortcuts_02/.stdout b/testing/btest/Baseline/doc.manual.framework_notice_shortcuts_02/.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/doc/manual/framework_notice_shortcuts_01.bro b/testing/btest/doc/manual/framework_notice_shortcuts_01.bro new file mode 100644 index 0000000000..d1d2f19312 --- /dev/null +++ b/testing/btest/doc/manual/framework_notice_shortcuts_01.bro @@ -0,0 +1,11 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +@load policy/protocols/ssh/interesting-hostnames.bro +@load base/protocols/ssh/ + +redef Notice::emailed_types += { + SSH::Interesting_Hostname_Login, + SSH::Login +}; + diff --git a/testing/btest/doc/manual/framework_notice_shortcuts_02.bro b/testing/btest/doc/manual/framework_notice_shortcuts_02.bro new file mode 100644 index 0000000000..5d05fdc775 --- /dev/null +++ b/testing/btest/doc/manual/framework_notice_shortcuts_02.bro @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +@load policy/protocols/ssh/interesting-hostnames.bro +@load base/protocols/ssh/ + +redef Notice::type_suppression_intervals += { + [SSH::Interesting_Hostname_Login] = 1day, + [SSH::Login] = 12hrs, +}; From 4f9869fe5c28b657aecc3d59e77244ffc199b999 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 28 Apr 2013 15:50:03 -0400 Subject: [PATCH 088/881] Spelling corrections. --- doc/scripting/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 84004e5ab6..93af02d53e 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -581,7 +581,7 @@ While actions like the ``Notice::ACTION_EMAIL`` action have appeal for quick ale :linenos: :lines: 59-62 -In the ``expiring-certs.bro`` script which identifies when SSL certificates are set to expire and raises notices when it crosses a pre-defined threshold, the call to ``NOTICE()`` above also sets the ``$identfier`` entry by concatenating the responder ip, port, and the hash of the certificate. The selection of responder ip, port and certificate hash fits perfectly into an appropriate identifier as it creates a unique identifier with which the suppression can be matched. Were we to take out any of the entities used for the identifier, for example the certificate hash, we could be setting our suppression too broadly, causing an analyst to miss a notice that should have been raised. Depending on the available data for the identifier, it can be useful to set the ``$suppress_for`` variable as well. The ``expiring-certs.bro`` script sets ``$suppress_for`` to ``1day``, telling the Notice Framework to suppress the notice for 24 hours after the first notice is raised. Once that time limit has passed, another notice can be raised which will again set the ``1day`` suppression time. Suppressing for a specific amount of time has benefits beyond simply not filling up an analyst's email inbox; keeping the notice alerts timely and succinct helps avoid a case where an analyst might see the notice and, due to over exposure, ignore it. +In the ``expiring-certs.bro`` script which identifies when SSL certificates are set to expire and raises notices when it crosses a pre-defined threshold, the call to ``NOTICE()`` above also sets the ``$identifier`` entry by concatenating the responder ip, port, and the hash of the certificate. The selection of responder ip, port and certificate hash fits perfectly into an appropriate identifier as it creates a unique identifier with which the suppression can be matched. Were we to take out any of the entities used for the identifier, for example the certificate hash, we could be setting our suppression too broadly, causing an analyst to miss a notice that should have been raised. Depending on the available data for the identifier, it can be useful to set the ``$suppress_for`` variable as well. The ``expiring-certs.bro`` script sets ``$suppress_for`` to ``1day``, telling the Notice Framework to suppress the notice for 24 hours after the first notice is raised. Once that time limit has passed, another notice can be raised which will again set the ``1day`` suppression time. Suppressing for a specific amount of time has benefits beyond simply not filling up an analyst's email inbox; keeping the notice alerts timely and succinct helps avoid a case where an analyst might see the notice and, due to over exposure, ignore it. The ``$suppress_for`` variable can also be altered in a ``Notice::policy`` hook, allowing a deployment to better suit the environment in which it is be run. Using the example of ``expiring-certs.bro``, we can write a ``Notice::policy`` hook for ``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for`` variable to a shorter time. @@ -590,7 +590,7 @@ The ``$suppress_for`` variable can also be altered in a ``Notice::policy`` hook, :linenos: :lines: 6-12 -While ``Notice::policy`` hooks allow you to build custom predicate-based policies for a deployment, there are bound to be times where you don't require the full expressiveness that a hook allows. In short, there will be notice policy considerations where a broad decision can be made based on the ``Notice::Type`` alone. To facilitate these types of decisions, the Notice Framework supports Notice Policy shortcuts. These shortcuts are implemented through the means of a group of data structures that map specific, pre-defined details and actions to the effective name of a notice. Primarily implemented as a set or table of enumerables of ``Notice::Type``, Notice Policy shortcuts can be placed as a single directive in your ``local.bro`` file as a conscise readable configuration. As these variables are all constants, it bears mentioning that these variables are all set at parsetime before Bro is fully up and running and not set dynamically. +While ``Notice::policy`` hooks allow you to build custom predicate-based policies for a deployment, there are bound to be times where you don't require the full expressiveness that a hook allows. In short, there will be notice policy considerations where a broad decision can be made based on the ``Notice::Type`` alone. To facilitate these types of decisions, the Notice Framework supports Notice Policy shortcuts. These shortcuts are implemented through the means of a group of data structures that map specific, pre-defined details and actions to the effective name of a notice. Primarily implemented as a set or table of enumerables of ``Notice::Type``, Notice Policy shortcuts can be placed as a single directive in your ``local.bro`` file as a concise readable configuration. As these variables are all constants, it bears mentioning that these variables are all set at parsetime before Bro is fully up and running and not set dynamically. +------------------------------------+-----------------------------------------------------+-------------------------------------+ | Name | Description | Data Type | From 07ecd31bbdcb85db52a206cb24ced7ea9b32c9f7 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Sun, 28 Apr 2013 21:21:22 -0700 Subject: [PATCH 089/881] in cluster settings, the resultvals can apparently been uninitialized in some special cases --- .../base/frameworks/sumstats/plugins/topk.bro | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/scripts/base/frameworks/sumstats/plugins/topk.bro b/scripts/base/frameworks/sumstats/plugins/topk.bro index a830b1c5ec..ed6074b081 100644 --- a/scripts/base/frameworks/sumstats/plugins/topk.bro +++ b/scripts/base/frameworks/sumstats/plugins/topk.bro @@ -35,8 +35,18 @@ hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { - result$topk = topk_init(topk_size(rv1$topk)); + if ( rv1?$topk ) + { + result$topk = topk_init(topk_size(rv1$topk)); - topk_merge(result$topk, rv1$topk); - topk_merge(result$topk, rv2$topk); + topk_merge(result$topk, rv1$topk); + if ( rv2?$topk ) + topk_merge(result$topk, rv2$topk); + } + else if ( rv2?$topk ) + { + result$topk = topk_init(topk_size(rv2$topk)); + topk_merge(result$topk, rv2$topk); + } + } From 160da6f1a6c246532705ac8a0f5ab49eee51c00e Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Sun, 28 Apr 2013 21:55:06 -0700 Subject: [PATCH 090/881] add sum function that can be used to get the number of total observed elements. Add methods to merge with and without pruning (before only merge method was with pruning, which invalidates the number of total observed elements) --- src/Topk.cc | 60 +++++++++++++++++------- src/Topk.h | 32 ++++++++++++- src/bro.bif | 54 +++++++++++++++++++++ testing/btest/Baseline/bifs.topk/.stderr | 1 + testing/btest/Baseline/bifs.topk/out | 24 ++++++++++ testing/btest/bifs/topk.bro | 38 ++++++++++++++- 6 files changed, 187 insertions(+), 22 deletions(-) diff --git a/src/Topk.cc b/src/Topk.cc index 116a4d3de4..2527ecc4bc 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -43,6 +43,7 @@ TopkVal::TopkVal(uint64 arg_size) : OpaqueVal(new OpaqueType("topk")) size = arg_size; type = 0; numElements = 0; + pruned = false; } TopkVal::TopkVal() : OpaqueVal(new OpaqueType("topk")) @@ -72,7 +73,7 @@ TopkVal::~TopkVal() type = 0; } -void TopkVal::Merge(const TopkVal* value) +void TopkVal::Merge(const TopkVal* value, bool doPrune) { if ( type == 0 ) @@ -140,26 +141,31 @@ void TopkVal::Merge(const TopkVal* value) // prune everything... assert(size > 0); - while ( numElements > size ) + + if ( doPrune ) { - assert(buckets.size() > 0 ); - Bucket* b = buckets.front(); - assert(b->elements.size() > 0); - - Element* e = b->elements.front(); - HashKey* key = GetHash(e->value); - elementDict->RemoveEntry(key); - delete e; - - b->elements.pop_front(); - - if ( b->elements.size() == 0 ) + while ( numElements > size ) { - delete b; - buckets.pop_front(); - } + pruned = true; + assert(buckets.size() > 0 ); + Bucket* b = buckets.front(); + assert(b->elements.size() > 0); - numElements--; + Element* e = b->elements.front(); + HashKey* key = GetHash(e->value); + elementDict->RemoveEntry(key); + delete e; + + b->elements.pop_front(); + + if ( b->elements.size() == 0 ) + { + delete b; + buckets.pop_front(); + } + + numElements--; + } } } @@ -330,6 +336,24 @@ uint64_t TopkVal::getEpsilon(Val* value) const delete key; return e->epsilon; } + +uint64_t TopkVal::getSum() const + { + uint64_t sum = 0; + + std::list::const_iterator it = buckets.begin(); + while ( it != buckets.end() ) + { + sum += (*it)->elements.size() * (*it)->count; + + it++; + } + + if ( pruned ) + reporter->Warning("TopkVal::getSum() was used on a pruned data structure. Result values do not represent total element count"); + + return sum; + } void TopkVal::Encountered(Val* encountered) { diff --git a/src/Topk.h b/src/Topk.h index 51a2d75251..608b810ddb 100644 --- a/src/Topk.h +++ b/src/Topk.h @@ -34,14 +34,41 @@ declare(PDict, Element); class TopkVal : public OpaqueVal { public: + // Initialize a TopkVal. Size specifies how many total elements are tracked TopkVal(uint64 size); ~TopkVal(); - void Encountered(Val* value); // we saw something + + // Call this, when a new value is encountered. Note that on the first call, + // the Bro-Type of the value types that are counted is set. All following calls + // to encountered have to specify the same type + void Encountered(Val* value); + + // Return the first k elements of the result vector. At the moment, this does + // not check if it is in the right order or if we can prove that these are + // the correct top-k. Use count and epsilon for this. VectorVal* getTopK(int k) const; // returns vector + + // Get the current count tracked in the top-k data structure for a certain val. + // Returns 0 if the val is unknown (and logs the error to reporter) uint64_t getCount(Val* value) const; + + // Get the current epsilon tracked in the top-k data structure for a certain val. + // Returns 0 if the val is unknown (and logs the error to reporter) uint64_t getEpsilon(Val* value) const; + + // Get the size set in the constructor uint64_t getSize() const { return size; } - void Merge(const TopkVal* value); + + // Get the sum of all counts of all tracked elements. This is equal to the number + // of total observations up to this moment, if no elements were pruned from the data + // structure. + uint64_t getSum() const; + + // Merge another top-k data structure in this one. + // doPrune specifies if the total count of elements is limited to size after + // merging. + // Please note, that pruning will invalidate the results of getSum. + void Merge(const TopkVal* value, bool doPrune=false); protected: TopkVal(); // for deserialize @@ -55,6 +82,7 @@ private: PDict(Element)* elementDict; uint64 size; // how many elements are we tracking? uint64 numElements; // how many elements do we have at the moment + bool pruned; // was this data structure pruned? DECLARE_SERIAL(TopkVal); }; diff --git a/src/bro.bif b/src/bro.bif index 195e4c2bde..4c46b23241 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -5739,12 +5739,18 @@ function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr #include "Topk.h" %%} +## Creates a top-k data structure which tracks size elements. +## +## Returns: Opaque pointer to the data structure. function topk_init%(size: count%): opaque of topk %{ Topk::TopkVal* v = new Topk::TopkVal(size); return v; %} +## Add a new observed object to the data structure. The first +## added object sets the type of data tracked by the top-k data +## structure. All following values have to be of the same type function topk_add%(handle: opaque of topk, value: any%): any %{ assert(handle); @@ -5754,6 +5760,9 @@ function topk_add%(handle: opaque of topk, value: any%): any return 0; %} +## Get the first k elements of the top-k data structure +## +## Returns: vector of the first k elements function topk_get_top%(handle: opaque of topk, k: count%): any %{ assert(handle); @@ -5761,6 +5770,11 @@ function topk_get_top%(handle: opaque of topk, k: count%): any return h->getTopK(k); %} +## Get an overestimated count of how often value has been encountered. +## value has to be part of the currently tracked elements, otherwise +## 0 will be returned and an error message will be added to reporter. +## +## Returns: Overestimated number for how often the element has been encountered function topk_count%(handle: opaque of topk, value: any%): count %{ assert(handle); @@ -5768,6 +5782,10 @@ function topk_count%(handle: opaque of topk, value: any%): count return new Val(h->getCount(value), TYPE_COUNT); %} +## Get a the maximal overestimation for count. Same restrictiosn as for topk_count +## apply. +## +## Returns: Number which represents the maximal overesimation for the count of this element. function topk_epsilon%(handle: opaque of topk, value: any%): count %{ assert(handle); @@ -5775,6 +5793,11 @@ function topk_epsilon%(handle: opaque of topk, value: any%): count return new Val(h->getEpsilon(value), TYPE_COUNT); %} +## Get the number of elements this data structure is supposed to track (given on init). +## Note that the actual number of elements in the data structure can be lower or higher +## than this. (higher due to non-pruned merges) +## +## Returns: size given during initialization function topk_size%(handle: opaque of topk%): count %{ assert(handle); @@ -5782,6 +5805,20 @@ function topk_size%(handle: opaque of topk%): count return new Val(h->getSize(), TYPE_COUNT); %} +## Get the sum of all counts of all elements in the data structure. Is equal to the number +## of all inserted objects if the data structure never has been pruned. Do not use after +## calling topk_merge_prune (will throw a warning message if used afterwards) +## +## Returns: sum of all counts +function topk_sum%(handle: opaque of topk%): count + %{ + assert(handle); + Topk::TopkVal* h = (Topk::TopkVal*) handle; + return new Val(h->getSum(), TYPE_COUNT); + %} + +## Merge the second topk data structure into the first. Does not remove any elements, the +## resulting data structure can be bigger than the maximum size given on initialization. function topk_merge%(handle1: opaque of topk, handle2: opaque of topk%): any %{ assert(handle1); @@ -5795,3 +5832,20 @@ function topk_merge%(handle1: opaque of topk, handle2: opaque of topk%): any return 0; %} +## Merge the second topk data structure into the first and prunes the final data structure +## back to the size given on initialization. Use with care and only when being aware of the +## restrictions this imposed. Do not call topk_size or topk_add afterwards, results will +## probably not be what you expect. +function topk_merge_prune%(handle1: opaque of topk, handle2: opaque of topk%): any + %{ + assert(handle1); + assert(handle2); + + Topk::TopkVal* h1 = (Topk::TopkVal*) handle1; + Topk::TopkVal* h2 = (Topk::TopkVal*) handle2; + + h1->Merge(h2, true); + + return 0; + %} + diff --git a/testing/btest/Baseline/bifs.topk/.stderr b/testing/btest/Baseline/bifs.topk/.stderr index f2bd316fd8..80626107aa 100644 --- a/testing/btest/Baseline/bifs.topk/.stderr +++ b/testing/btest/Baseline/bifs.topk/.stderr @@ -6,5 +6,6 @@ error: getCount for element that is not in top-k error: getEpsilon for element that is not in top-k error: getCount for element that is not in top-k error: getEpsilon for element that is not in top-k +warning: TopkVal::getSum() was used on a pruned data structure. Result values do not represent total element count error: getCount for element that is not in top-k error: getEpsilon for element that is not in top-k diff --git a/testing/btest/Baseline/bifs.topk/out b/testing/btest/Baseline/bifs.topk/out index 8db55eeca8..1ce5c4b850 100644 --- a/testing/btest/Baseline/bifs.topk/out +++ b/testing/btest/Baseline/bifs.topk/out @@ -1,4 +1,5 @@ [b, c] +4 0 0 2 @@ -6,6 +7,7 @@ 2 1 [d, c] +5 0 0 2 @@ -13,21 +15,25 @@ 3 2 [d, e] +6 3 2 3 2 [f, e] +7 4 3 3 2 [f, e] +8 4 3 4 2 [g, e] +9 0 0 4 @@ -35,6 +41,7 @@ 5 4 [c, e, d] +19 6 0 5 @@ -49,9 +56,26 @@ 0 0 [c, e] +22 12 0 10 0 0 0 +[c, e] +19 +6 +0 +5 +0 +4 +0 +[c, e, d] +38 +12 +0 +10 +0 +8 +0 diff --git a/testing/btest/bifs/topk.bro b/testing/btest/bifs/topk.bro index 92a68999cc..02d13c4195 100644 --- a/testing/btest/bifs/topk.bro +++ b/testing/btest/bifs/topk.bro @@ -14,6 +14,7 @@ event bro_init() local s = topk_get_top(k1, 5); print s; + print topk_sum(k1); print topk_count(k1, "a"); print topk_epsilon(k1, "a"); print topk_count(k1, "b"); @@ -24,6 +25,7 @@ event bro_init() topk_add(k1, "d"); s = topk_get_top(k1, 5); print s; + print topk_sum(k1); print topk_count(k1, "b"); print topk_epsilon(k1, "b"); print topk_count(k1, "c"); @@ -34,6 +36,7 @@ event bro_init() topk_add(k1, "e"); s = topk_get_top(k1, 5); print s; + print topk_sum(k1); print topk_count(k1, "d"); print topk_epsilon(k1, "d"); print topk_count(k1, "e"); @@ -42,6 +45,7 @@ event bro_init() topk_add(k1, "f"); s = topk_get_top(k1, 5); print s; + print topk_sum(k1); print topk_count(k1, "f"); print topk_epsilon(k1, "f"); print topk_count(k1, "e"); @@ -50,6 +54,7 @@ event bro_init() topk_add(k1, "e"); s = topk_get_top(k1, 5); print s; + print topk_sum(k1); print topk_count(k1, "f"); print topk_epsilon(k1, "f"); print topk_count(k1, "e"); @@ -58,6 +63,7 @@ event bro_init() topk_add(k1, "g"); s = topk_get_top(k1, 5); print s; + print topk_sum(k1); print topk_count(k1, "f"); print topk_epsilon(k1, "f"); print topk_count(k1, "e"); @@ -87,6 +93,7 @@ event bro_init() topk_add(k1, "f"); s = topk_get_top(k1, 3); print s; + print topk_sum(k1); print topk_count(k1, "c"); print topk_epsilon(k1, "c"); print topk_count(k1, "e"); @@ -95,7 +102,7 @@ event bro_init() print topk_epsilon(k1, "d"); local k3 = topk_init(2); - topk_merge(k3, k1); + topk_merge_prune(k3, k1); s = topk_get_top(k3, 3); print s; @@ -106,10 +113,11 @@ event bro_init() print topk_count(k3, "d"); print topk_epsilon(k3, "d"); - topk_merge(k3, k1); + topk_merge_prune(k3, k1); s = topk_get_top(k3, 3); print s; + print topk_sum(k3); # this gives a warning and a wrong result. print topk_count(k3, "c"); print topk_epsilon(k3, "c"); print topk_count(k3, "e"); @@ -117,4 +125,30 @@ event bro_init() print topk_count(k3, "d"); print topk_epsilon(k3, "d"); + k3 = topk_init(2); + topk_merge(k3, k1); + print s; + print topk_sum(k3); + print topk_count(k3, "c"); + print topk_epsilon(k3, "c"); + print topk_count(k3, "e"); + print topk_epsilon(k3, "e"); + print topk_count(k3, "d"); + print topk_epsilon(k3, "d"); + + topk_merge(k3, k1); + + s = topk_get_top(k3, 3); + print s; + print topk_sum(k3); + print topk_count(k3, "c"); + print topk_epsilon(k3, "c"); + print topk_count(k3, "e"); + print topk_epsilon(k3, "e"); + print topk_count(k3, "d"); + print topk_epsilon(k3, "d"); + + + + } From c6e69ddc05cc6cdcaa8006e0d2fb2535a885f30b Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 1 May 2013 17:06:45 -0700 Subject: [PATCH 091/881] potentially found wrong Ref. --- src/Topk.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Topk.cc b/src/Topk.cc index 2527ecc4bc..9c0a04607d 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -274,7 +274,7 @@ VectorVal* TopkVal::getTopK(int k) const // returns vector } TypeList* vector_index = new TypeList(type); - vector_index->Append(type); + vector_index->Append(type->Ref()); VectorType* v = new VectorType(vector_index); VectorVal* t = new VectorVal(v); @@ -362,7 +362,7 @@ void TopkVal::Encountered(Val* encountered) //printf("NumElements: %d\n", numElements); // check type compatibility if ( numElements == 0 ) - type = encountered->Type()->Ref()->Ref(); + type = encountered->Type()->Ref(); else if ( !same_type(type, encountered->Type()) ) { From 1cf506071df6498a87b495472f5d9236f79e165e Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 1 May 2013 18:12:20 -0700 Subject: [PATCH 092/881] make it compile on case-sensitive file systems and fix warnings --- src/HyperLogLog.cc | 4 ++-- src/HyperLogLog.h | 2 +- src/OpaqueVal.cc | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/HyperLogLog.cc b/src/HyperLogLog.cc index a399f5a495..6dacab33a2 100644 --- a/src/HyperLogLog.cc +++ b/src/HyperLogLog.cc @@ -101,7 +101,7 @@ void CardinalityCounter::addElement(uint64_t hash) double CardinalityCounter::size() { double answer = 0; - for (int i = 0; i < m; i++) + for (unsigned int i = 0; i < m; i++) answer += pow(2, -(int)buckets[i]); answer = 1/answer; @@ -119,7 +119,7 @@ void CardinalityCounter::merge(CardinalityCounter* c) { uint8_t* temp = (*c).getBuckets(); V = 0; - for (int i = 0; i < m; i++) + for (unsigned int i = 0; i < m; i++) { if (temp[i] > buckets[i]) buckets[i] = temp[i]; diff --git a/src/HyperLogLog.h b/src/HyperLogLog.h index 68b7f0ecfc..f07167502a 100644 --- a/src/HyperLogLog.h +++ b/src/HyperLogLog.h @@ -4,7 +4,7 @@ #define hyperloglog_h #include -#include +#include /* * "conf" is how confident the estimate given by the counter is. diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index b712f728f7..54c771b366 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -33,7 +33,7 @@ bool CardinalityVal::DoSerialize(SerialInfo* info) const serialvalid &= SERIALIZE(c->m); serialvalid &= SERIALIZE(c->V); serialvalid &= SERIALIZE(c->alpha_m); - for ( int i = 0; i < c->m; i++ ) + for ( unsigned int i = 0; i < c->m; i++ ) serialvalid &= SERIALIZE( c->buckets[i] ); return serialvalid; @@ -56,7 +56,7 @@ bool CardinalityVal::DoUnserialize(UnserialInfo* info) serialvalid &= UNSERIALIZE(&c->alpha_m); uint8_t* buckets = c->buckets; - for ( int i = 0; i < m; i++ ) + for ( unsigned int i = 0; i < m; i++ ) { uint8_t* currbucket = buckets + i; serialvalid &= UNSERIALIZE( currbucket ); From 075bfc5b3ded8b2f223805eaa48c4d04451868a8 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 2 May 2013 12:09:35 -0700 Subject: [PATCH 093/881] synchronize pruned attribute --- src/Topk.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Topk.cc b/src/Topk.cc index 9c0a04607d..2b84b389b0 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -178,6 +178,7 @@ bool TopkVal::DoSerialize(SerialInfo* info) const v &= SERIALIZE(size); v &= SERIALIZE(numElements); + v &= SERIALIZE(pruned); bool type_present = (type != 0); v &= SERIALIZE(type_present); if ( type_present ) @@ -220,6 +221,7 @@ bool TopkVal::DoUnserialize(UnserialInfo* info) v &= UNSERIALIZE(&size); v &= UNSERIALIZE(&numElements); + v &= UNSERIALIZE(&pruned); bool type_present = false; v &= UNSERIALIZE(&type_present); if ( type_present ) From f6e99fce11e7e10b50607cfaea82a801e690585b Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Fri, 3 May 2013 23:03:31 -0700 Subject: [PATCH 094/881] fix opaqueval-related memleak. --- src/NetVar.cc | 2 ++ src/NetVar.h | 1 + src/OpaqueVal.cc | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/NetVar.cc b/src/NetVar.cc index 012e4a85bc..3ee899634a 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -243,6 +243,7 @@ OpaqueType* md5_type; OpaqueType* sha1_type; OpaqueType* sha256_type; OpaqueType* entropy_type; +OpaqueType* cardinality_type; #include "const.bif.netvar_def" #include "types.bif.netvar_def" @@ -308,6 +309,7 @@ void init_general_global_var() sha1_type = new OpaqueType("sha1"); sha256_type = new OpaqueType("sha256"); entropy_type = new OpaqueType("entropy"); + cardinality_type = new OpaqueType("cardinality"); } void init_net_var() diff --git a/src/NetVar.h b/src/NetVar.h index d7590b20e7..2239bbb560 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -248,6 +248,7 @@ extern OpaqueType* md5_type; extern OpaqueType* sha1_type; extern OpaqueType* sha256_type; extern OpaqueType* entropy_type; +extern OpaqueType* cardinality_type; // Initializes globals that don't pertain to network/event analysis. extern void init_general_global_var(); diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 39eab973b7..0515ae2989 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -5,7 +5,7 @@ #include "HyperLogLog.h" -CardinalityVal::CardinalityVal() : OpaqueVal(new OpaqueType("cardinality")) +CardinalityVal::CardinalityVal() : OpaqueVal(cardinality_type) { valid = false; } From cf6e768ad641988320a3379b5ead701ea09a0ff1 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Fri, 3 May 2013 23:08:26 -0700 Subject: [PATCH 095/881] fix opaqueval-related memleak --- src/NetVar.cc | 2 ++ src/NetVar.h | 1 + src/Topk.cc | 5 +++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/NetVar.cc b/src/NetVar.cc index 012e4a85bc..1a2e604e90 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -243,6 +243,7 @@ OpaqueType* md5_type; OpaqueType* sha1_type; OpaqueType* sha256_type; OpaqueType* entropy_type; +OpaqueType* topk_type; #include "const.bif.netvar_def" #include "types.bif.netvar_def" @@ -308,6 +309,7 @@ void init_general_global_var() sha1_type = new OpaqueType("sha1"); sha256_type = new OpaqueType("sha256"); entropy_type = new OpaqueType("entropy"); + topk_type = new OpaqueType("topk"); } void init_net_var() diff --git a/src/NetVar.h b/src/NetVar.h index d7590b20e7..37ed3c7c85 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -248,6 +248,7 @@ extern OpaqueType* md5_type; extern OpaqueType* sha1_type; extern OpaqueType* sha256_type; extern OpaqueType* entropy_type; +extern OpaqueType* topk_type; // Initializes globals that don't pertain to network/event analysis. extern void init_general_global_var(); diff --git a/src/Topk.cc b/src/Topk.cc index 2b84b389b0..10374f3087 100644 --- a/src/Topk.cc +++ b/src/Topk.cc @@ -4,6 +4,7 @@ #include "CompHash.h" #include "Reporter.h" #include "Serializer.h" +#include "NetVar.h" namespace Topk { @@ -36,7 +37,7 @@ HashKey* TopkVal::GetHash(Val* v) const return key; } -TopkVal::TopkVal(uint64 arg_size) : OpaqueVal(new OpaqueType("topk")) +TopkVal::TopkVal(uint64 arg_size) : OpaqueVal(topk_type) { elementDict = new PDict(Element); elementDict->SetDeleteFunc(topk_element_hash_delete_func); @@ -46,7 +47,7 @@ TopkVal::TopkVal(uint64 arg_size) : OpaqueVal(new OpaqueType("topk")) pruned = false; } -TopkVal::TopkVal() : OpaqueVal(new OpaqueType("topk")) +TopkVal::TopkVal() : OpaqueVal(topk_type) { elementDict = new PDict(Element); elementDict->SetDeleteFunc(topk_element_hash_delete_func); From 8ba9250cf47df4a6cc4fc259aab6e2938affb8e4 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 5 May 2013 00:01:12 -0400 Subject: [PATCH 096/881] Initial start for "Using Bro". --- doc/using/index.rst | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/doc/using/index.rst b/doc/using/index.rst index ab7834d904..cbb7db4436 100644 --- a/doc/using/index.rst +++ b/doc/using/index.rst @@ -1,6 +1,25 @@ -=================== -Using Bro (Missing) -=================== +========= +Using Bro +========= + +Once Bro has been deployed in an environment and monitoring live traffic, it will, in its default configuration, begin to produce human-readable ASCII logs. Each log file, produced by Bro's Logging Framework, is populated with organized, connection-oriented data. As the logfiles are simple ASCII data, working with the data contained in them can be done from a command line terminal once you have been familiarized with the types of data you can find in each log file. + +---------------------- +Structure of Log Files +---------------------- + +The log files produced by Bro adhere to a structure as defined by the scripts that produced through which they were produced. However, as each log file has been produced using the Logging Framework, there are similiarites shared by each log file. Without breaking into the scripting aspect of Bro, a bird's eye view of how the log files are produced would progress as follows. The script's author defines the kinds of data, such as the originating IP address or the duration of a connection, which will be used as fields in the log file. The author then decides what behavior should generate a logfile entry, these behaviors can range from a connection having been completed or an HTTP GET method being issued by an orignator. Once these behaviors have been observed, the data is passed to the Logging Framework which, in turn, adds an entry to the appropriate log file. While the fields of the log entries can be modified by the user, the Logging Framework makes use of a header entry in each logfile to ensure that it remains self-describing. This header entry can be see by running the unix utility ``head`` and outputting the first eight lines of the file. + +.. btest:: framework_logging_factorial_02 + + @TEST-EXEC: btest-rst-cmd head -8 ${TESTBASE}/Baseline/core.pppoe/conn.log + +The sample above shows the header for a ``conn.log`` file which gives a detailed account of each connection as seen by Bro. As you can see, header includes information such as what separators are being used for various types of data, what an empty field looks like and what an unset field looks like. In this example, the default TAB separator is being used as the delimiter between fiends (\x09 is the tab character in hex). It also lists the comma as the separator for set data, the string "(empty)" as the indicator for an empty field and the '-' character as the indicator for a field that hasn't been set. The timestampe for when the file was created is included under "#open". The header then goes on to detail the fields being listed in the file and the datatypes of those fields in #fields and #types respectively. These two entries are often the two most significant points of interest as they detail not only the field name but the data type used. + +------------- +Using bro-cut +------------- + +With an understanding of the structure of logfiles, we can start looking at using tools such as ``bro-cut`` to retrieve information from log files. -TODO. From 4a7de4a6165c77888cbe1bd9a6e30b153a8a7ad3 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Sun, 5 May 2013 15:24:30 -0400 Subject: [PATCH 097/881] Corrected a mis-typed RST include. --- doc/scripting/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 93af02d53e..02cd97e3b1 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -585,7 +585,7 @@ In the ``expiring-certs.bro`` script which identifies when SSL certificates are The ``$suppress_for`` variable can also be altered in a ``Notice::policy`` hook, allowing a deployment to better suit the environment in which it is be run. Using the example of ``expiring-certs.bro``, we can write a ``Notice::policy`` hook for ``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for`` variable to a shorter time. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_suppression_01.bro +.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro :language: bro :linenos: :lines: 6-12 From a93a6535e7bf85af8bffd68f494a6eae53911837 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 7 May 2013 05:56:45 -0400 Subject: [PATCH 098/881] Using redirection with bro-cut. Include initial btests for this document. --- doc/using/index.rst | 51 +++++++++++++++++-- .../doc.manual.using_bro_sandbox_01/.stdout | 0 .../doc.manual.using_bro_sandbox_01/conn.log | 43 ++++++++++++++++ .../doc.manual.using_bro_sandbox_01/http.log | 23 +++++++++ testing/btest/doc/manual/using_bro_sandbox_01 | 4 ++ 5 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.using_bro_sandbox_01/.stdout create mode 100644 testing/btest/Baseline/doc.manual.using_bro_sandbox_01/conn.log create mode 100644 testing/btest/Baseline/doc.manual.using_bro_sandbox_01/http.log create mode 100644 testing/btest/doc/manual/using_bro_sandbox_01 diff --git a/doc/using/index.rst b/doc/using/index.rst index cbb7db4436..cc48e478b8 100644 --- a/doc/using/index.rst +++ b/doc/using/index.rst @@ -3,7 +3,7 @@ Using Bro ========= -Once Bro has been deployed in an environment and monitoring live traffic, it will, in its default configuration, begin to produce human-readable ASCII logs. Each log file, produced by Bro's Logging Framework, is populated with organized, connection-oriented data. As the logfiles are simple ASCII data, working with the data contained in them can be done from a command line terminal once you have been familiarized with the types of data you can find in each log file. +Once Bro has been deployed in an environment and monitoring live traffic, it will, in its default configuration, begin to produce human-readable ASCII logs. Each log file, produced by Bro's Logging Framework, is populated with organized, connection-oriented data. As the logfiles are simple ASCII data, working with the data contained in them can be done from a command line terminal once you have been familiarized with the types of data that can be found in each log file. ---------------------- Structure of Log Files @@ -11,15 +11,58 @@ Structure of Log Files The log files produced by Bro adhere to a structure as defined by the scripts that produced through which they were produced. However, as each log file has been produced using the Logging Framework, there are similiarites shared by each log file. Without breaking into the scripting aspect of Bro, a bird's eye view of how the log files are produced would progress as follows. The script's author defines the kinds of data, such as the originating IP address or the duration of a connection, which will be used as fields in the log file. The author then decides what behavior should generate a logfile entry, these behaviors can range from a connection having been completed or an HTTP GET method being issued by an orignator. Once these behaviors have been observed, the data is passed to the Logging Framework which, in turn, adds an entry to the appropriate log file. While the fields of the log entries can be modified by the user, the Logging Framework makes use of a header entry in each logfile to ensure that it remains self-describing. This header entry can be see by running the unix utility ``head`` and outputting the first eight lines of the file. -.. btest:: framework_logging_factorial_02 +.. btest:: using_bro_cmd_line_01 @TEST-EXEC: btest-rst-cmd head -8 ${TESTBASE}/Baseline/core.pppoe/conn.log -The sample above shows the header for a ``conn.log`` file which gives a detailed account of each connection as seen by Bro. As you can see, header includes information such as what separators are being used for various types of data, what an empty field looks like and what an unset field looks like. In this example, the default TAB separator is being used as the delimiter between fiends (\x09 is the tab character in hex). It also lists the comma as the separator for set data, the string "(empty)" as the indicator for an empty field and the '-' character as the indicator for a field that hasn't been set. The timestampe for when the file was created is included under "#open". The header then goes on to detail the fields being listed in the file and the datatypes of those fields in #fields and #types respectively. These two entries are often the two most significant points of interest as they detail not only the field name but the data type used. +The sample above shows the header for a ``conn.log`` file which gives a detailed account of each connection as seen by Bro. As you can see, header includes information such as what separators are being used for various types of data, what an empty field looks like and what an unset field looks like. In this example, the default TAB separator is being used as the delimiter between fiends (\x09 is the tab character in hex). It also lists the comma as the separator for set data, the string "(empty)" as the indicator for an empty field and the '-' character as the indicator for a field that hasn't been set. The timestampe for when the file was created is included under "#open". The header then goes on to detail the fields being listed in the file and the datatypes of those fields in #fields and #types respectively. These two entries are often the two most significant points of interest as they detail not only the field name but the data type used. Navigating through the different log files produced by Bro, often requires the use of different elements of the unix tool chain such as ``sed``, ``awk``, or ``grep`` and having the field definitions readily available will save the user some mental legwork. The field names are also a key resource for using the ``bro-cut`` utility included with Bro. ------------- Using bro-cut ------------- -With an understanding of the structure of logfiles, we can start looking at using tools such as ``bro-cut`` to retrieve information from log files. +The ``bro-cut`` utility can be used in place of other tools to build terminal commands that remain flexible and accurate independent of possible changes that can be made to the log file itself. It accomplishes this by parsing the header in each file and allowing the user to refer to the specific columnar data available. In contrast tools like ``awk`` require the user to refer to fields referenced by their position. For example, the two commands listed below produce the same output given a default configuration of Bro. + +.. btest:: using_bro_bro_cut_01 + + @TEST-EXEC: btest-rst-cmd awk \'{print \$3, \$4, \$5, \$6, \$9}\' ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/conn.log + +.. btest:: using_bro_bro_cut_02 + + @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/conn.log | btest-rst-cmd bro-cut id.orig_h id.orig_p id.resp_h duration + + +While the output is similar, the advantages to using bro-cut over awk lay in that, while awk is flexible and powerful, ``bro-cut`` was specifically designed to work with log files. Firstly, the ``bro-cut`` output includes only the logfile entries, while the ``awk`` output includes the header parts of the logfile, which would require the user to use a secondary utility to suppress those lones. Secondly, since ``bro-cut`` uses the field descriptors to identify and extract data, it allows for flexibilty independent of the format and contents of the logfile. It's not uncommon for a Bro configuration to add extra fields to various logfiles as required by the environment. In this case, the fields in the ``awk`` command would have to be altered to compensate for the new position whereas the ``bro-cut`` output would not change. + +As you may have noticed, the command for ``bro-cut`` uses the output redirection through the ``cat`` command and ``|`` operator. Whereas tools like ``awk`` allow you to indicate the log file as a command line option, bro-cut only takes input through redirection such as ``\`` and ``<``. There are a couple of ways to direct log file data into ``bro-cut``, each dependent upon the type of log file you're processing. A caveat of its use, however, is that the 8 lines of header data must be present. In its default setup, Bro will rotate log files on an hourly basis, moving the current log file into a directory with format ``YYYY-MM-DD`` and gzip compressing the file with a file format that includes the log file type and time range of the file. In the case of processing a compressed log file you simply adjust your command line tools to use the complementary z* versions of commands such as cat (``zcat``), ``grep`` (``zgrep``), and ``head`` (``zhead``). + +....................... +Working with timestamps +....................... + +The ``bro-cut`` accepts the flag ``-d`` to convert the epoch time values in the log files to human-readable format. The following command includes the human readable time stamp, the unique identifier and the HTTP host and HTTP uri as parsed from the ``http.log`` file. + +.. btest:: using_bro_bro_cut_time_01 + + @TEST-EXEC: btest-rst-cmd bro-cut -d ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log + +Often times logfiles from multiple sources are stored in UTC time to allow easy correlation. Converting the timestamp from a logfile to UTC can be accomplished with the ``-u`` command. + +.. btest:: using_bro_bro_cut_time_02 + + @TEST-EXEC: btest-rst-cmd bro-cut -u ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log + +The default time format when using the ``-d`` or ``-u`` is the ``strftime`` format string %Y-%m-%dT%H:%M:%S%z which results in a string with year, month, day of month, followed by hour, minutes, seconds and the timezone offset. The default ``strftime`` can be altered by using the ``-D`` and ``-U`` flags. For example, to format the timestamp in the US-typical "Middle Endian" you could use a format string of: %d-%m-%YT%H:%M:%S%z + +.. btest:: using_bro_bro_cut_time_03 + + @TEST-EXEC: btest-rst-cmd bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log + +---------------------- +Working with Log Files +---------------------- + +As Bro runs, it deposits its logfiles in + + diff --git a/testing/btest/Baseline/doc.manual.using_bro_sandbox_01/.stdout b/testing/btest/Baseline/doc.manual.using_bro_sandbox_01/.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/Baseline/doc.manual.using_bro_sandbox_01/conn.log b/testing/btest/Baseline/doc.manual.using_bro_sandbox_01/conn.log new file mode 100644 index 0000000000..7fe6aa385c --- /dev/null +++ b/testing/btest/Baseline/doc.manual.using_bro_sandbox_01/conn.log @@ -0,0 +1,43 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2013-05-05-20-51-24 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1300475167.096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 73 0 0 (empty) +1300475167.097012 arKYeMETxOg fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp - - - - S0 - 0 D 1 199 0 0 (empty) +1300475167.099816 k6kgXLOoSKl 141.142.220.50 5353 224.0.0.251 5353 udp - - - - S0 - 0 D 1 179 0 0 (empty) +1300475168.853899 TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF - 0 Dd 1 66 1 117 (empty) +1300475168.854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF - 0 Dd 1 80 1 127 (empty) +1300475168.854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF - 0 Dd 1 66 1 211 (empty) +1300475168.857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF - 0 Dd 1 66 1 117 (empty) +1300475168.858306 qSsw6ESzHV4 141.142.220.118 59816 141.142.2.2 53 udp dns 0.000343 52 99 SF - 0 Dd 1 80 1 127 (empty) +1300475168.858713 iE6yhOq3SF 141.142.220.118 59714 141.142.2.2 53 udp dns 0.000375 38 183 SF - 0 Dd 1 66 1 211 (empty) +1300475168.891644 qCaWGmzFtM5 141.142.220.118 58206 141.142.2.2 53 udp dns 0.000339 38 89 SF - 0 Dd 1 66 1 117 (empty) +1300475168.892037 70MGiRM1Qf4 141.142.220.118 38911 141.142.2.2 53 udp dns 0.000335 52 99 SF - 0 Dd 1 80 1 127 (empty) +1300475168.892414 h5DsfNtYzi1 141.142.220.118 59746 141.142.2.2 53 udp dns 0.000421 38 183 SF - 0 Dd 1 66 1 211 (empty) +1300475168.893988 c4Zw9TmAE05 141.142.220.118 45000 141.142.2.2 53 udp dns 0.000384 38 89 SF - 0 Dd 1 66 1 117 (empty) +1300475168.894422 EAr0uf4mhq 141.142.220.118 48479 141.142.2.2 53 udp dns 0.000317 52 99 SF - 0 Dd 1 80 1 127 (empty) +1300475168.894787 GvmoxJFXdTa 141.142.220.118 48128 141.142.2.2 53 udp dns 0.000423 38 183 SF - 0 Dd 1 66 1 211 (empty) +1300475168.901749 slFea8xwSmb 141.142.220.118 56056 141.142.2.2 53 udp dns 0.000402 36 131 SF - 0 Dd 1 64 1 159 (empty) +1300475168.902195 UfGkYA2HI2g 141.142.220.118 55092 141.142.2.2 53 udp dns 0.000374 36 198 SF - 0 Dd 1 64 1 226 (empty) +1300475169.899438 BWaU4aSuwkc 141.142.220.44 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 85 0 0 (empty) +1300475170.862384 10XodEwRycf 141.142.220.226 137 141.142.220.255 137 udp dns 2.613017 350 0 S0 - 0 D 7 546 0 0 (empty) +1300475171.675372 zno26fFZkrh fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 0.100096 66 0 S0 - 0 D 2 162 0 0 (empty) +1300475171.677081 v5rgkJBig5l 141.142.220.226 55131 224.0.0.252 5355 udp dns 0.100021 66 0 S0 - 0 D 2 122 0 0 (empty) +1300475173.116749 eWZCH7OONC1 fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 0.099801 66 0 S0 - 0 D 2 162 0 0 (empty) +1300475173.117362 0Pwk3ntf8O3 141.142.220.226 55671 224.0.0.252 5355 udp dns 0.099849 66 0 S0 - 0 D 2 122 0 0 (empty) +1300475173.153679 0HKorjr8Zp7 141.142.220.238 56641 141.142.220.255 137 udp dns - - - S0 - 0 D 1 78 0 0 (empty) +1300475168.859163 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 tcp http 0.215893 1130 734 S1 - 0 ShADad 6 1450 4 950 (empty) +1300475168.652003 nQcgTWjvg4c 141.142.220.118 35634 208.80.152.2 80 tcp - 0.061329 463 350 OTH - 0 DdA 2 567 1 402 (empty) +1300475168.895267 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 tcp http 0.227284 1178 734 S1 - 0 ShADad 6 1498 4 950 (empty) +1300475168.902635 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 tcp http 0.120041 534 412 S1 - 0 ShADad 4 750 3 576 (empty) +1300475168.892936 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 tcp http 0.229603 1148 734 S1 - 0 ShADad 6 1468 4 950 (empty) +1300475168.855305 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 tcp http 0.218501 1171 733 S1 - 0 ShADad 6 1491 4 949 (empty) +1300475168.892913 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 tcp http 0.220961 1137 733 S1 - 0 ShADad 6 1457 4 949 (empty) +1300475169.780331 2cx26uAvUPl 141.142.220.235 6705 173.192.163.128 80 tcp - - - - OTH - 0 h 0 0 1 48 (empty) +1300475168.724007 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 tcp http 0.119905 525 232 S1 - 0 ShADad 4 741 3 396 (empty) +1300475168.855330 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 tcp http 0.219720 1125 734 S1 - 0 ShADad 6 1445 4 950 (empty) +#close 2013-05-05-20-51-24 diff --git a/testing/btest/Baseline/doc.manual.using_bro_sandbox_01/http.log b/testing/btest/Baseline/doc.manual.using_bro_sandbox_01/http.log new file mode 100644 index 0000000000..617c1f0e6e --- /dev/null +++ b/testing/btest/Baseline/doc.manual.using_bro_sandbox_01/http.log @@ -0,0 +1,23 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#open 2013-05-05-21-12-40 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1300475168.784020 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 1 GET bits.wikimedia.org /skins-1.5/monobook/main.css http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.916018 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.916183 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.918358 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.952307 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.952296 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/4/4a/Wiktionary-logo-en-35px.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.954820 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikiquote-logo.svg/35px-Wikiquote-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.962687 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 1 GET meta.wikimedia.org /images/wikimedia-button.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.975934 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.976436 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/d/df/Wikispecies-logo.svg/35px-Wikispecies-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475168.979264 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4c/Wikisource-logo.svg/35px-Wikisource-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475169.014619 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475169.014593 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +1300475169.014927 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - +#close 2013-05-05-21-12-40 diff --git a/testing/btest/doc/manual/using_bro_sandbox_01 b/testing/btest/doc/manual/using_bro_sandbox_01 new file mode 100644 index 0000000000..4130ea8ceb --- /dev/null +++ b/testing/btest/doc/manual/using_bro_sandbox_01 @@ -0,0 +1,4 @@ +# @TEST-EXEC: bro -r ${TRACES}/wikipedia.trace +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff http.log + From 5734d7fe259cf130997e421fcc749efbc5e6672a Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 7 May 2013 06:01:04 -0400 Subject: [PATCH 099/881] A truly embarassing number of spelling corrections. --- doc/using/index.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/using/index.rst b/doc/using/index.rst index cc48e478b8..a6d42ed211 100644 --- a/doc/using/index.rst +++ b/doc/using/index.rst @@ -3,19 +3,19 @@ Using Bro ========= -Once Bro has been deployed in an environment and monitoring live traffic, it will, in its default configuration, begin to produce human-readable ASCII logs. Each log file, produced by Bro's Logging Framework, is populated with organized, connection-oriented data. As the logfiles are simple ASCII data, working with the data contained in them can be done from a command line terminal once you have been familiarized with the types of data that can be found in each log file. +Once Bro has been deployed in an environment and monitoring live traffic, it will, in its default configuration, begin to produce human-readable ASCII logs. Each log file, produced by Bro's Logging Framework, is populated with organized, connection-oriented data. As the log files are simple ASCII data, working with the data contained in them can be done from a command line terminal once you have been familiarized with the types of data that can be found in each log file. ---------------------- Structure of Log Files ---------------------- -The log files produced by Bro adhere to a structure as defined by the scripts that produced through which they were produced. However, as each log file has been produced using the Logging Framework, there are similiarites shared by each log file. Without breaking into the scripting aspect of Bro, a bird's eye view of how the log files are produced would progress as follows. The script's author defines the kinds of data, such as the originating IP address or the duration of a connection, which will be used as fields in the log file. The author then decides what behavior should generate a logfile entry, these behaviors can range from a connection having been completed or an HTTP GET method being issued by an orignator. Once these behaviors have been observed, the data is passed to the Logging Framework which, in turn, adds an entry to the appropriate log file. While the fields of the log entries can be modified by the user, the Logging Framework makes use of a header entry in each logfile to ensure that it remains self-describing. This header entry can be see by running the unix utility ``head`` and outputting the first eight lines of the file. +The log files produced by Bro adhere to a structure as defined by the scripts that produced through which they were produced. However, as each log file has been produced using the Logging Framework, there are similarities shared by each log file. Without breaking into the scripting aspect of Bro, a bird's eye view of how the log files are produced would progress as follows. The script's author defines the kinds of data, such as the originating IP address or the duration of a connection, which will be used as fields in the log file. The author then decides what behavior should generate a log file entry, these behaviors can range from a connection having been completed or an HTTP GET method being issued by an originator. Once these behaviors have been observed, the data is passed to the Logging Framework which, in turn, adds an entry to the appropriate log file. While the fields of the log entries can be modified by the user, the Logging Framework makes use of a header entry in each log file to ensure that it remains self-describing. This header entry can be see by running the unix utility ``head`` and outputting the first eight lines of the file. .. btest:: using_bro_cmd_line_01 @TEST-EXEC: btest-rst-cmd head -8 ${TESTBASE}/Baseline/core.pppoe/conn.log -The sample above shows the header for a ``conn.log`` file which gives a detailed account of each connection as seen by Bro. As you can see, header includes information such as what separators are being used for various types of data, what an empty field looks like and what an unset field looks like. In this example, the default TAB separator is being used as the delimiter between fiends (\x09 is the tab character in hex). It also lists the comma as the separator for set data, the string "(empty)" as the indicator for an empty field and the '-' character as the indicator for a field that hasn't been set. The timestampe for when the file was created is included under "#open". The header then goes on to detail the fields being listed in the file and the datatypes of those fields in #fields and #types respectively. These two entries are often the two most significant points of interest as they detail not only the field name but the data type used. Navigating through the different log files produced by Bro, often requires the use of different elements of the unix tool chain such as ``sed``, ``awk``, or ``grep`` and having the field definitions readily available will save the user some mental legwork. The field names are also a key resource for using the ``bro-cut`` utility included with Bro. +The sample above shows the header for a ``conn.log`` file which gives a detailed account of each connection as seen by Bro. As you can see, header includes information such as what separators are being used for various types of data, what an empty field looks like and what an unset field looks like. In this example, the default TAB separator is being used as the delimiter between fiends (\x09 is the tab character in hex). It also lists the comma as the separator for set data, the string "(empty)" as the indicator for an empty field and the '-' character as the indicator for a field that hasn't been set. The timestamp for when the file was created is included under "#open". The header then goes on to detail the fields being listed in the file and the data types of those fields in #fields and #types respectively. These two entries are often the two most significant points of interest as they detail not only the field name but the data type used. Navigating through the different log files produced by Bro, often requires the use of different elements of the unix tool chain such as ``sed``, ``awk``, or ``grep`` and having the field definitions readily available will save the user some mental leg work. The field names are also a key resource for using the ``bro-cut`` utility included with Bro. ------------- Using bro-cut @@ -32,9 +32,9 @@ The ``bro-cut`` utility can be used in place of other tools to build terminal co @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/conn.log | btest-rst-cmd bro-cut id.orig_h id.orig_p id.resp_h duration -While the output is similar, the advantages to using bro-cut over awk lay in that, while awk is flexible and powerful, ``bro-cut`` was specifically designed to work with log files. Firstly, the ``bro-cut`` output includes only the logfile entries, while the ``awk`` output includes the header parts of the logfile, which would require the user to use a secondary utility to suppress those lones. Secondly, since ``bro-cut`` uses the field descriptors to identify and extract data, it allows for flexibilty independent of the format and contents of the logfile. It's not uncommon for a Bro configuration to add extra fields to various logfiles as required by the environment. In this case, the fields in the ``awk`` command would have to be altered to compensate for the new position whereas the ``bro-cut`` output would not change. +While the output is similar, the advantages to using bro-cut over awk lay in that, while awk is flexible and powerful, ``bro-cut`` was specifically designed to work with log files. Firstly, the ``bro-cut`` output includes only the log file entries, while the ``awk`` output includes the header parts of the log file, which would require the user to use a secondary utility to suppress those lines. Secondly, since ``bro-cut`` uses the field descriptors to identify and extract data, it allows for flexibility independent of the format and contents of the log file. It's not uncommon for a Bro configuration to add extra fields to various log files as required by the environment. In this case, the fields in the ``awk`` command would have to be altered to compensate for the new position whereas the ``bro-cut`` output would not change. -As you may have noticed, the command for ``bro-cut`` uses the output redirection through the ``cat`` command and ``|`` operator. Whereas tools like ``awk`` allow you to indicate the log file as a command line option, bro-cut only takes input through redirection such as ``\`` and ``<``. There are a couple of ways to direct log file data into ``bro-cut``, each dependent upon the type of log file you're processing. A caveat of its use, however, is that the 8 lines of header data must be present. In its default setup, Bro will rotate log files on an hourly basis, moving the current log file into a directory with format ``YYYY-MM-DD`` and gzip compressing the file with a file format that includes the log file type and time range of the file. In the case of processing a compressed log file you simply adjust your command line tools to use the complementary z* versions of commands such as cat (``zcat``), ``grep`` (``zgrep``), and ``head`` (``zhead``). +As you may have noticed, the command for ``bro-cut`` uses the output redirection through the ``cat`` command and ``|`` operator. Whereas tools like ``awk`` allow you to indicate the log file as a command line option, bro-cut only takes input through redirection such as ``|`` and ``<``. There are a couple of ways to direct log file data into ``bro-cut``, each dependent upon the type of log file you're processing. A caveat of its use, however, is that the 8 lines of header data must be present. In its default setup, Bro will rotate log files on an hourly basis, moving the current log file into a directory with format ``YYYY-MM-DD`` and gzip compressing the file with a file format that includes the log file type and time range of the file. In the case of processing a compressed log file you simply adjust your command line tools to use the complementary z* versions of commands such as cat (``zcat``), ``grep`` (``zgrep``), and ``head`` (``zhead``). ....................... Working with timestamps @@ -46,7 +46,7 @@ The ``bro-cut`` accepts the flag ``-d`` to convert the epoch time values in the @TEST-EXEC: btest-rst-cmd bro-cut -d ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log -Often times logfiles from multiple sources are stored in UTC time to allow easy correlation. Converting the timestamp from a logfile to UTC can be accomplished with the ``-u`` command. +Often times log files from multiple sources are stored in UTC time to allow easy correlation. Converting the timestamp from a log file to UTC can be accomplished with the ``-u`` command. .. btest:: using_bro_bro_cut_time_02 @@ -62,7 +62,7 @@ The default time format when using the ``-d`` or ``-u`` is the ``strftime`` form Working with Log Files ---------------------- -As Bro runs, it deposits its logfiles in +As Bro runs, it deposits its log files in From 4aa51e760845a04097e9375b80ca97a464eb720a Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Tue, 7 May 2013 13:33:38 -0400 Subject: [PATCH 100/881] Basic cross-referencing UIDs between files, btests, and baselines. Also includes appropriate btest-rst-cmd directives with titles. --- doc/using/index.rst | 21 ++++++++++---- .../doc.manual.using_bro_sandbox_02/conn.log | 15 ++++++++++ .../doc.manual.using_bro_sandbox_02/http.log | 26 ++++++++++++++++++ .../btest/Traces/workshop_2011_browse.trace | Bin 0 -> 19909 bytes testing/btest/doc/manual/using_bro_sandbox_02 | 4 +++ 5 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 testing/btest/Baseline/doc.manual.using_bro_sandbox_02/conn.log create mode 100644 testing/btest/Baseline/doc.manual.using_bro_sandbox_02/http.log create mode 100644 testing/btest/Traces/workshop_2011_browse.trace create mode 100644 testing/btest/doc/manual/using_bro_sandbox_02 diff --git a/doc/using/index.rst b/doc/using/index.rst index a6d42ed211..fc979dd30a 100644 --- a/doc/using/index.rst +++ b/doc/using/index.rst @@ -29,7 +29,7 @@ The ``bro-cut`` utility can be used in place of other tools to build terminal co .. btest:: using_bro_bro_cut_02 - @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/conn.log | btest-rst-cmd bro-cut id.orig_h id.orig_p id.resp_h duration + @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/conn.log | btest-rst-cmd -c "cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration " bro-cut id.orig_h id.orig_p id.resp_h duration While the output is similar, the advantages to using bro-cut over awk lay in that, while awk is flexible and powerful, ``bro-cut`` was specifically designed to work with log files. Firstly, the ``bro-cut`` output includes only the log file entries, while the ``awk`` output includes the header parts of the log file, which would require the user to use a secondary utility to suppress those lines. Secondly, since ``bro-cut`` uses the field descriptors to identify and extract data, it allows for flexibility independent of the format and contents of the log file. It's not uncommon for a Bro configuration to add extra fields to various log files as required by the environment. In this case, the fields in the ``awk`` command would have to be altered to compensate for the new position whereas the ``bro-cut`` output would not change. @@ -44,25 +44,36 @@ The ``bro-cut`` accepts the flag ``-d`` to convert the epoch time values in the .. btest:: using_bro_bro_cut_time_01 - @TEST-EXEC: btest-rst-cmd bro-cut -d ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log + @TEST-EXEC: btest-rst-cmd -c "bro-cut -d ts uid host uri < http.log" bro-cut -d ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log Often times log files from multiple sources are stored in UTC time to allow easy correlation. Converting the timestamp from a log file to UTC can be accomplished with the ``-u`` command. .. btest:: using_bro_bro_cut_time_02 - @TEST-EXEC: btest-rst-cmd bro-cut -u ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log + @TEST-EXEC: btest-rst-cmd -c "bro-cut -u ts uid host uri < http.log" bro-cut -u ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log The default time format when using the ``-d`` or ``-u`` is the ``strftime`` format string %Y-%m-%dT%H:%M:%S%z which results in a string with year, month, day of month, followed by hour, minutes, seconds and the timezone offset. The default ``strftime`` can be altered by using the ``-D`` and ``-U`` flags. For example, to format the timestamp in the US-typical "Middle Endian" you could use a format string of: %d-%m-%YT%H:%M:%S%z .. btest:: using_bro_bro_cut_time_03 - @TEST-EXEC: btest-rst-cmd bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log + @TEST-EXEC: btest-rst-cmd -c "bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log" bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log ---------------------- Working with Log Files ---------------------- -As Bro runs, it deposits its log files in +While Bro can do signature based analysis, its primary focus is on behavioral detection which alters the practice of log review from "reactionary review" to a process a little more akin to a hunting trip. A common progression of review includes correlating a session across multiple log files. As a connection is processed by Bro, a unique identifier is assigned to each session. This unique identifier is almost always included in any log file entry specific to that connection and can be used to cross-reference log files. +A simple example would be to cross-reference a UID seen in a ``conn.log`` file. Here, we're looking for the connection with the largest number of bytes from the responder by redirecting the output for ``cat conn.log`` into bro-cut to extract the UID and the resp_bytes, then sorting that output by the resp_bytes field. +.. btest:: using_bro_practical_02 + @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_02/conn.log | bro-cut uid resp_bytes | btest-rst-cmd -c "cat conn.log | bro-cut uid resp_bytes | btest-rst-cmd sort -nrk2" sort -nrk2 + +With the UID of the largest response, it can be crossreferenced with the UIDs in the ``http.log`` file. + +.. btest:: using_bro_practical_03 + + @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_02/http.log | bro-cut uid id.resp_h method status_code host uri | btest-rst-cmd -c "cat http.log | bro-cut uid id.resp_h method status_code host uri | grep j4u32Pc5bif" grep j4u32Pc5bif + +As you can see there are multiple HTTP GET requests within the session that Bro identified and logged. Given that HTTP is a stream protocol, it can have multiple GET/POST/etc requests in a stream and Bro is able to extract and track that information for you, giving you an in-depth and structured view into HTTP traffic on your network. diff --git a/testing/btest/Baseline/doc.manual.using_bro_sandbox_02/conn.log b/testing/btest/Baseline/doc.manual.using_bro_sandbox_02/conn.log new file mode 100644 index 0000000000..1227e60ad3 --- /dev/null +++ b/testing/btest/Baseline/doc.manual.using_bro_sandbox_02/conn.log @@ -0,0 +1,15 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#open 2013-05-07-14-38-27 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string bool count string count count count count table[string] +1320329757.771503 j4u32Pc5bif 10.0.2.15 49286 192.150.187.43 80 tcp http 15.161537 2899 1127 S2 - 0 ShADadF 20 3719 19 1891 (empty) +1320329757.771262 nQcgTWjvg4c 10.0.2.15 49285 192.150.187.43 80 tcp http 15.161772 889 377 S2 - 0 ShADadF 8 1229 8 701 (empty) +1320329757.761327 arKYeMETxOg 10.0.2.15 49283 192.150.187.43 80 tcp http 15.168898 459 189 S2 - 0 ShADadF 5 679 4 353 (empty) +1320329757.458867 UWkUyAuUGXf 10.0.2.15 49282 192.150.187.43 80 tcp http 15.471378 1824 751 S2 - 0 ShADadF 12 2324 13 1275 (empty) +1320329757.761638 k6kgXLOoSKl 10.0.2.15 49284 192.150.187.43 80 tcp http 15.168613 898 376 S2 - 0 ShADadF 8 1238 8 700 (empty) +1320329757.771755 TEfuqmmG4bh 10.0.2.15 49287 192.150.187.43 80 tcp http 15.161267 900 376 S2 - 0 ShADadF 8 1240 8 700 (empty) +#close 2013-05-07-14-38-27 diff --git a/testing/btest/Baseline/doc.manual.using_bro_sandbox_02/http.log b/testing/btest/Baseline/doc.manual.using_bro_sandbox_02/http.log new file mode 100644 index 0000000000..031a9ce2ce --- /dev/null +++ b/testing/btest/Baseline/doc.manual.using_bro_sandbox_02/http.log @@ -0,0 +1,26 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#open 2013-05-07-14-38-27 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1320329757.460004 UWkUyAuUGXf 10.0.2.15 49282 192.150.187.43 80 1 GET bro-ids.org / - Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.772457 UWkUyAuUGXf 10.0.2.15 49282 192.150.187.43 80 2 GET bro-ids.org /css/pygments.css http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.874406 UWkUyAuUGXf 10.0.2.15 49282 192.150.187.43 80 3 GET bro-ids.org /js/jquery.zrssfeed.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.775110 k6kgXLOoSKl 10.0.2.15 49284 192.150.187.43 80 1 GET bro-ids.org /css/960.css http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.776072 TEfuqmmG4bh 10.0.2.15 49287 192.150.187.43 80 1 GET bro-ids.org /js/jquery.cycle.all.min.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.776421 nQcgTWjvg4c 10.0.2.15 49285 192.150.187.43 80 1 GET bro-ids.org /js/jquery.tweet.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.776240 j4u32Pc5bif 10.0.2.15 49286 192.150.187.43 80 1 GET bro-ids.org /js/jquery.fancybox-1.3.4.pack.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.775251 arKYeMETxOg 10.0.2.15 49283 192.150.187.43 80 1 GET bro-ids.org /css/bro-ids.css http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.975651 UWkUyAuUGXf 10.0.2.15 49282 192.150.187.43 80 4 GET bro-ids.org /js/jquery.tableofcontents.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.979943 k6kgXLOoSKl 10.0.2.15 49284 192.150.187.43 80 2 GET bro-ids.org /js/superfish.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.985656 TEfuqmmG4bh 10.0.2.15 49287 192.150.187.43 80 2 GET bro-ids.org /js/hoverIntent.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.989904 nQcgTWjvg4c 10.0.2.15 49285 192.150.187.43 80 2 GET bro-ids.org /js/general.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329757.991315 j4u32Pc5bif 10.0.2.15 49286 192.150.187.43 80 2 GET bro-ids.org /js/jquery.collapse.js http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329758.172397 j4u32Pc5bif 10.0.2.15 49286 192.150.187.43 80 3 GET bro-ids.org /css/print.css http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329759.998388 j4u32Pc5bif 10.0.2.15 49286 192.150.187.43 80 4 GET bro-ids.org /documentation/index.html http://bro-ids.org/ Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329760.146412 j4u32Pc5bif 10.0.2.15 49286 192.150.187.43 80 5 GET bro-ids.org /js/breadcrumbs.js http://bro-ids.org/documentation/index.html Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +1320329762.971726 j4u32Pc5bif 10.0.2.15 49286 192.150.187.43 80 6 GET bro-ids.org /documentation/reporting-problems.html http://bro-ids.org/documentation/index.html Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2 0 0 304 Not Modified - - - (empty) - - - - - - +#close 2013-05-07-14-38-27 diff --git a/testing/btest/Traces/workshop_2011_browse.trace b/testing/btest/Traces/workshop_2011_browse.trace new file mode 100644 index 0000000000000000000000000000000000000000..74d2f9c21f60eec207455470b38c775487aa52e2 GIT binary patch literal 19909 zcmeHP3v^V~xjr+A$Q>FI=&eR8cnT;ZW*%oACvzrHpb#aEu~P|BD_SRK&LjiLOqiL( z5X@S)i1J!$Sv;;Sw^qGyZ?A~A*oQ$)Lm<-f5cMj^sG#Lh=*2cfN^2jG`~Ul7&g^-d zy_UvUa#v=py%w1TU%vf6zWwii@6B7gpMT28<#WkTUmwRA;D>QfKYx3SyOR4l{29j` z)!bOOaU?f+#rjDjxpI!1+I3_GH)BNaSQBR~+_~|kn|Chbd-fiLw(ueX?CkrGQ~E9 z{K=C9vXqDANFWrh_42i?p~jMc60G;fm6BLMuG9X`ZT@g=lfPE+@=Dk;Z*GYa&H$NJ z=a0q|U{x{q8y1hpEm?$;rg+feA%Cy5ME#}C0#ilMa(g7KSgQPSxz5W^aJvLosc3PQ z);KJ#8hgO0*yVualI;`7->m{_!H^QL%ngNQ`1RFwO(neD$=@Dn<{frH;01@*DR~`E z{?@AM0#ktrLv-5+Mu?iFpOO&0Eh9vY2D7-)SJc-hJ_6B5K8Ur{YT|m~CmdPfenR>= zVzob(6RWtd&+;>lONJHiw7YXNZ+hgA!?qPji>>4gQvCg56$VDzEl~&zTND z1FQlAFmm)=lA{yTvrF6vIojbXn%e%CYt$S)Y%}Sr#uVun#3i?8n6ZPn1k7muCC3$* z&?m^~7+^6Ny+;^L$ib+SFuGbr>G|O(hC)tvAWCe9hVmfiD_OoTf*epG6R)Q!JhD6i@xa0G4b-MvFGmj4m)4 zO?M)r*a3}^>XAmkBaFUYsWSRyH_Q4*`Vb{?RzrD+^Hq$n{3vPtZ(o~c{rm9yq+kF0 z6&7-vjL7bl8uG)OkFQ*rmqa!<>LYL6!$LMUA@b^G4S5CUbDux@r6h6(hzzw_--q8P zIfwR+Vy%rw5xM714VlydBzrr3#Z%iCezAXTlw&bl6 zLkTKT6xO>tQCNwg576Z_*g4DVh&>gwf`+D#`{nBM@k?(F}^wL*kju z29S{_k7LnS$df;qGc9~?oNZ*n|ar>%1Bxb$L>SAIjy|zD-GjB-)47;BzdM?MeU& zYqw%g%0Z1gAb-MA+3lv~VD4M2^OgfgD4HXK46Jy+#Hlcs5JF0s?MlNv+`}0(wOhZ;9A+G1sABYmssT`a=l{p*VkJcLSgH|AycG`=E!)p+GK6Y6YEY5(_oeZx5_k2!4 zNL+x521iy%oK6@pB#wMl3kkZ;f{^$(S5`>G?^l%ga1ab`5I8LkM~(8C1;N+^Q)4=b z#?Xa3Zf=b3^T&>&#w?1`8nc&;wUb~?r#1n&Eiv+ytKLAY_im)I-hG$JtBYWLmBPXe zg|T9U?K_C|#bY$qq3QxwLvj~lwJ)QvQdDqvM5yGdqFP0yy?tp>Aq0%oSLiq6dD_eXP( zUSwn)75ql(&Xt+{Sdf`>zjAqICL9!LCk1vr^J8D3^Mld)rkoE5gykNa!tl}J#IgyW{Xy^et&3$8iE2vD=MhXkmU5uk2^ zx$G?Fx-G4Vw(Hzz)++of#A zENFv+8f0|(JUABg0!Nl+oY+A25!cPii2?^EFF@Is>{-N`8kJ};6ssGq2nMkt5L_}(u`pQ>kYE~hWg$x?;Jyv0L@R}r+K)hZ z|7-0KPzkWVPNN93=_)XQeomTOFeg{9(6Whi0FNDoO&L)MOP`vPV@4LTDvSNZC5{X; zc93lynDL%}r&XdDuo#S%5JnH@U_?~Ha#3aEF%@#>K_PHtsl+LBE26CYbxsseiCadd zRH7~dmpdv*Ju$2kgQ^pyf<>~uo@0wXBR(g6~b&Wxb!bf5p=2dEQuaB`x4Fioah z&D4ok5v%=v3M@ev0%OnsJAfG9yM~2kBOU8AlY-a{EmtqeLEY?B6s-DaR7IJzS?UD!+!w z2<~D5BMZd{9os>Aalq){e40@eU@>e|OKkMG#wcYY!svZlU+*AI*Tpo+iUZV{Y8SF%bR@NvVR!2jn#z;R^tdQM4i zU_`brrXn(RngtQrJ!c3=jo{KdTUPt97r_Mji8S4fDG=MIr2x4)aG(qh^++PkhO1>L zHj~FOQrj&34;nHpwNY$3D@F*{;4(S}N@VqeSabP8?qf(u99c>EzioBM$azR(M5i_+ zum<^9DIQzE76ZjZy{D%qQh}Zx7sv17PVpWP=eMGVY@05YjSJCW$9I$Wfa49@Qbu^Oz2S-3g>f zm|}!o4s|C4j2?p<*Oz08q&q}s^GFtj#gcSP1HR72qOYyY%H8_q(MvFrR?jz7I z99gT#N$EY}ky?sTYDEG@dyWqUkLa!91tzpW$0e2>+d^nZ_eRZ*q&8c#PCUJp*zs}b z&Lc_#Ja_~kGO{YXb8QO|CG+A}KMI`MyYK9;@W^w9Xeb;XzP`NHZ>YLFGn78O*EK&*e*sKiU*_5tk@Q@jo}Q1~EuMbXg$M3y?@-f|H|Og+WQqh2 zBfuf!(~bD7i#P;~xEInhRV+>hEC!=`!f0I%Mj~P4i&@j`IQ$xd|UXsc&pU;egU&#fP>-@*UJb-V6_kM^kng&ZL}@-`}q^ zf*>jOPkMRTlYAzDVf2OR%pE113PE5SGXh)WD<4~cO7oW1rQiW;(h6pEb_ucC>8G%u zTFQ668(tnuLF z5UhA9!z1U2N3f#OYCOdHF<>zmMF^wsrHce%^buhstBgJ@GjgLqYH(yqjp1TjBceE8 z%!yK5G3N-h1d}%hYNCoiAV-@TYGVH%J5PFIdf7a>gqts=mQqE#oIaq26b9H!(^-Xz z7m5%F*1n8j{fMtzE1-P5ak#%uA%TDYfjmZ`;)UWEu*!2{LE!I)3yPn5w>^mRAyN$~ zUGt+U*TD1{xw@F->Z9pdwpI{NZ`c;shu@JL@*(bP-Wvdo>jLbZ^Ym_Ss`qlnqRjt`msT`(+J< z?)ZSRX~|st)dhP zEW0E|AWGt64TbIp0?KP$D#|P-N?S9cxKsag0_ld4s0sPTfRDbXqHG5g-HRG#?=B8d z+NV)bgNM+a@T77o=JCJ4^+WZ8HhzVTwVPmNJcQ`(g>#+{5z7kIYYJ;W8%uo%QAY8C z6Pk`zIHI@#u|l(HtS6>2=lBZY<)yITaAA8Zbk{c_Rvns$d~lA>u(8Mm@OJtFIP}H0 nEQP-CwTM*&eeo35PuN($BE0C=4zP=RE(96-EyOzLNn-sU+snk@ literal 0 HcmV?d00001 diff --git a/testing/btest/doc/manual/using_bro_sandbox_02 b/testing/btest/doc/manual/using_bro_sandbox_02 new file mode 100644 index 0000000000..5a21b59800 --- /dev/null +++ b/testing/btest/doc/manual/using_bro_sandbox_02 @@ -0,0 +1,4 @@ +# @TEST-EXEC: bro -r ${TRACES}/workshop_2011_browse.trace +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff http.log + From bec965b66f7df28f023ff34600ed26a4f1735c20 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 21 May 2013 15:52:59 -0400 Subject: [PATCH 101/881] Large update for the SumStats framework. - On-demand access to sumstats results through "return from" functions named SumStats::request and Sumstats::request_key. Both functions are tested in standalone and clustered modes. - $name field has returned to SumStats which simplifies cluster code and makes the on-demand access stuff possible. - Clustered results can only be collected for 1 minute from their time of creation now instead of time of last read. - Thresholds use doubles instead of counts everywhere now. - Calculation dependency resolution occurs at start up time now instead of doing it at observation time which provide a minor cpu performance improvement. A new plugin registration mechanism was created to support this change. - AppStats now has a minimal doc string and is broken into hook-based plugins. - AppStats and traceroute detection added to local.bro --- scripts/base/frameworks/sumstats/cluster.bro | 200 +++++++++------ scripts/base/frameworks/sumstats/main.bro | 241 +++++++++++++----- .../base/frameworks/sumstats/non-cluster.bro | 29 ++- .../frameworks/sumstats/plugins/average.bro | 9 +- .../base/frameworks/sumstats/plugins/max.bro | 8 +- .../base/frameworks/sumstats/plugins/min.bro | 9 +- .../frameworks/sumstats/plugins/sample.bro | 13 +- .../frameworks/sumstats/plugins/std-dev.bro | 15 +- .../base/frameworks/sumstats/plugins/sum.bro | 30 ++- .../frameworks/sumstats/plugins/unique.bro | 8 +- .../frameworks/sumstats/plugins/variance.bro | 10 +- scripts/policy/misc/app-stats/__load__.bro | 2 + .../{app-metrics.bro => app-stats/main.bro} | 48 +--- .../misc/app-stats/plugins/__load__.bro | 6 + .../misc/app-stats/plugins/facebook.bro | 12 + .../policy/misc/app-stats/plugins/gmail.bro | 12 + .../policy/misc/app-stats/plugins/google.bro | 12 + .../policy/misc/app-stats/plugins/netflix.bro | 12 + .../policy/misc/app-stats/plugins/pandora.bro | 12 + .../policy/misc/app-stats/plugins/youtube.bro | 12 + .../policy/misc/detect-traceroute/main.bro | 9 +- scripts/policy/misc/scan.bro | 18 +- .../protocols/ftp/detect-bruteforcing.bro | 7 +- scripts/policy/protocols/http/detect-sqli.bro | 12 +- .../protocols/ssh/detect-bruteforcing.bro | 7 +- scripts/site/local.bro | 7 + .../manager-1..stdout | 7 + .../.stdout | 5 + .../frameworks/sumstats/basic-cluster.bro | 3 +- .../base/frameworks/sumstats/basic.bro | 21 +- .../sumstats/cluster-intermediate-update.bro | 7 +- .../frameworks/sumstats/on-demand-cluster.bro | 93 +++++++ .../base/frameworks/sumstats/on-demand.bro | 45 ++++ .../base/frameworks/sumstats/thresholding.bro | 23 +- 34 files changed, 687 insertions(+), 277 deletions(-) create mode 100644 scripts/policy/misc/app-stats/__load__.bro rename scripts/policy/misc/{app-metrics.bro => app-stats/main.bro} (58%) create mode 100644 scripts/policy/misc/app-stats/plugins/__load__.bro create mode 100644 scripts/policy/misc/app-stats/plugins/facebook.bro create mode 100644 scripts/policy/misc/app-stats/plugins/gmail.bro create mode 100644 scripts/policy/misc/app-stats/plugins/google.bro create mode 100644 scripts/policy/misc/app-stats/plugins/netflix.bro create mode 100644 scripts/policy/misc/app-stats/plugins/pandora.bro create mode 100644 scripts/policy/misc/app-stats/plugins/youtube.bro create mode 100644 testing/btest/Baseline/scripts.base.frameworks.sumstats.on-demand-cluster/manager-1..stdout create mode 100644 testing/btest/Baseline/scripts.base.frameworks.sumstats.on-demand/.stdout create mode 100644 testing/btest/scripts/base/frameworks/sumstats/on-demand-cluster.bro create mode 100644 testing/btest/scripts/base/frameworks/sumstats/on-demand.bro diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index 9ee63a674e..23e20ae9c0 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -27,39 +27,34 @@ export { ## performed. In practice this should hopefully have a minimal effect. const max_outstanding_global_views = 10 &redef; - ## Intermediate updates can cause overload situations on very large clusters. This - ## option may help reduce load and correct intermittent problems. The goal for this - ## option is also meant to be temporary. - const enable_intermediate_updates = T &redef; - ## Event sent by the manager in a cluster to initiate the collection of values for ## a sumstat. - global cluster_ss_request: event(uid: string, ssid: string); + global cluster_ss_request: event(uid: string, ss_name: string, cleanup: bool); ## Event sent by nodes that are collecting sumstats after receiving a request for ## the sumstat from the manager. - global cluster_ss_response: event(uid: string, ssid: string, data: ResultTable, done: bool); + global cluster_ss_response: event(uid: string, ss_name: string, data: ResultTable, done: bool); ## This event is sent by the manager in a cluster to initiate the collection of ## a single key value from a sumstat. It's typically used to get intermediate ## updates before the break interval triggers to speed detection of a value ## crossing a threshold. - global cluster_key_request: event(uid: string, ssid: string, key: Key); + global cluster_key_request: event(uid: string, ss_name: string, key: Key, cleanup: bool); ## This event is sent by nodes in response to a ## :bro:id:`SumStats::cluster_key_request` event. - global cluster_key_response: event(uid: string, ssid: string, key: Key, result: Result); + global cluster_key_response: event(uid: string, ss_name: string, key: Key, result: Result, cleanup: bool); ## This is sent by workers to indicate that they crossed the percent ## of the current threshold by the percentage defined globally in ## :bro:id:`SumStats::cluster_request_global_view_percent` - global cluster_key_intermediate_response: event(ssid: string, key: SumStats::Key); + global cluster_key_intermediate_response: event(ss_name: string, key: SumStats::Key); ## This event is scheduled internally on workers to send result chunks. - global send_data: event(uid: string, ssid: string, data: ResultTable); + global send_data: event(uid: string, ss_name: string, data: ResultTable, cleanup: bool); ## This event is generated when a threshold is crossed. - global cluster_threshold_crossed: event(ssid: string, key: SumStats::Key, thold: Thresholding); + global cluster_threshold_crossed: event(ss_name: string, key: SumStats::Key, thold: Thresholding); } # Add events to the cluster framework to make this work. @@ -74,44 +69,38 @@ redef Cluster::worker2manager_events += /SumStats::cluster_(ss_response|key_resp # an intermediate result has been received. global recent_global_view_keys: table[string, Key] of count &create_expire=1min &default=0; -event bro_init() &priority=-100 - { - # The manager is the only host allowed to track these. - stats_store = table(); - reducer_store = table(); - } - # This is done on all non-manager node types in the event that a sumstat is # being collected somewhere other than a worker. function data_added(ss: SumStat, key: Key, result: Result) { # If an intermediate update for this value was sent recently, don't send # it again. - if ( [ss$id, key] in recent_global_view_keys ) + if ( [ss$name, key] in recent_global_view_keys ) return; # If val is 5 and global view % is 0.1 (10%), pct_val will be 50. If that # crosses the full threshold then it's a candidate to send as an # intermediate update. - if ( enable_intermediate_updates && - check_thresholds(ss, key, result, cluster_request_global_view_percent) ) + if ( check_thresholds(ss, key, result, cluster_request_global_view_percent) ) { # kick off intermediate update - event SumStats::cluster_key_intermediate_response(ss$id, key); - ++recent_global_view_keys[ss$id, key]; + event SumStats::cluster_key_intermediate_response(ss$name, key); + ++recent_global_view_keys[ss$name, key]; } } -event SumStats::send_data(uid: string, ssid: string, data: ResultTable) +event SumStats::send_data(uid: string, ss_name: string, data: ResultTable, cleanup: bool) { #print fmt("WORKER %s: sending data for uid %s...", Cluster::node, uid); local local_data: ResultTable = table(); + local incoming_data: ResultTable = cleanup ? data : copy(data); + local num_added = 0; - for ( key in data ) + for ( key in incoming_data ) { - local_data[key] = data[key]; - delete data[key]; + local_data[key] = incoming_data[key]; + delete incoming_data[key]; # Only send cluster_send_in_groups_of at a time. Queue another # event to send the next group. @@ -121,56 +110,56 @@ event SumStats::send_data(uid: string, ssid: string, data: ResultTable) local done = F; # If data is empty, this sumstat is done. - if ( |data| == 0 ) + if ( |incoming_data| == 0 ) done = T; - event SumStats::cluster_ss_response(uid, ssid, local_data, done); + event SumStats::cluster_ss_response(uid, ss_name, local_data, done); if ( ! done ) - schedule 0.01 sec { SumStats::send_data(uid, ssid, data) }; + schedule 0.01 sec { SumStats::send_data(uid, ss_name, incoming_data, T) }; } -event SumStats::cluster_ss_request(uid: string, ssid: string) +event SumStats::cluster_ss_request(uid: string, ss_name: string, cleanup: bool) { #print fmt("WORKER %s: received the cluster_ss_request event for %s.", Cluster::node, id); # Initiate sending all of the data for the requested stats. - if ( ssid in result_store ) - event SumStats::send_data(uid, ssid, result_store[ssid]); + if ( ss_name in result_store ) + event SumStats::send_data(uid, ss_name, result_store[ss_name], cleanup); else - event SumStats::send_data(uid, ssid, table()); + event SumStats::send_data(uid, ss_name, table(), cleanup); # Lookup the actual sumstats and reset it, the reference to the data # currently stored will be maintained internally by the send_data event. - if ( ssid in stats_store ) - reset(stats_store[ssid]); + if ( ss_name in stats_store && cleanup ) + reset(stats_store[ss_name]); } -event SumStats::cluster_key_request(uid: string, ssid: string, key: Key) +event SumStats::cluster_key_request(uid: string, ss_name: string, key: Key, cleanup: bool) { - if ( ssid in result_store && key in result_store[ssid] ) + if ( ss_name in result_store && key in result_store[ss_name] ) { #print fmt("WORKER %s: received the cluster_key_request event for %s=%s.", Cluster::node, key2str(key), data); - event SumStats::cluster_key_response(uid, ssid, key, result_store[ssid][key]); + event SumStats::cluster_key_response(uid, ss_name, key, result_store[ss_name][key], cleanup); } else { # We need to send an empty response if we don't have the data so that the manager # can know that it heard back from all of the workers. - event SumStats::cluster_key_response(uid, ssid, key, table()); + event SumStats::cluster_key_response(uid, ss_name, key, table(), cleanup); } } -event SumStats::cluster_threshold_crossed(ssid: string, key: SumStats::Key, thold: Thresholding) +event SumStats::cluster_threshold_crossed(ss_name: string, key: SumStats::Key, thold: Thresholding) { - if ( ssid !in threshold_tracker ) - threshold_tracker[ssid] = table(); + if ( ss_name !in threshold_tracker ) + threshold_tracker[ss_name] = table(); - threshold_tracker[ssid][key] = thold; + threshold_tracker[ss_name][key] = thold; } -event SumStats::thresholds_reset(ssid: string) +event SumStats::thresholds_reset(ss_name: string) { - threshold_tracker[ssid] = table(); + threshold_tracker[ss_name] = table(); } @endif @@ -181,7 +170,7 @@ event SumStats::thresholds_reset(ssid: string) # This variable is maintained by manager nodes as they collect and aggregate # results. # Index on a uid. -global stats_results: table[string] of ResultTable &read_expire=1min; +global stats_results: table[string] of ResultTable &create_expire=1min &default=table(); # This variable is maintained by manager nodes to track how many "dones" they # collected per collection unique id. Once the number of results for a uid @@ -189,18 +178,18 @@ global stats_results: table[string] of ResultTable &read_expire=1min; # result is written out and deleted from here. # Indexed on a uid. # TODO: add an &expire_func in case not all results are received. -global done_with: table[string] of count &read_expire=1min &default=0; +global done_with: table[string] of count &create_expire=1min &default=0; # This variable is maintained by managers to track intermediate responses as # they are getting a global view for a certain key. # Indexed on a uid. -global key_requests: table[string] of Result &read_expire=1min; +global key_requests: table[string] of Result &create_expire=1min; # This variable is maintained by managers to prevent overwhelming communication due # to too many intermediate updates. Each sumstat is tracked separately so that # one won't overwhelm and degrade other quieter sumstats. # Indexed on a sumstat id. -global outstanding_global_views: table[string] of count &default=0; +global outstanding_global_views: table[string] of count &create_expire=1min &default=0; const zero_time = double_to_time(0.0); # Managers handle logging. @@ -216,7 +205,7 @@ event SumStats::finish_epoch(ss: SumStat) stats_results[uid] = table(); # Request data from peers. - event SumStats::cluster_ss_request(uid, ss$id); + event SumStats::cluster_ss_request(uid, ss$name, T); } # Schedule the next finish_epoch event. @@ -230,20 +219,20 @@ function data_added(ss: SumStat, key: Key, result: Result) if ( check_thresholds(ss, key, result, 1.0) ) { threshold_crossed(ss, key, result); - event SumStats::cluster_threshold_crossed(ss$id, key, threshold_tracker[ss$id][key]); + event SumStats::cluster_threshold_crossed(ss$name, key, threshold_tracker[ss$name][key]); } } -event SumStats::cluster_key_response(uid: string, ssid: string, key: Key, result: Result) +event SumStats::cluster_key_response(uid: string, ss_name: string, key: Key, result: Result, cleanup: bool) { #print fmt("%0.6f MANAGER: receiving key data from %s - %s=%s", network_time(), get_event_peer()$descr, key2str(key), result); # We only want to try and do a value merge if there are actually measured datapoints # in the Result. - if ( uid in key_requests ) - key_requests[uid] = compose_results(key_requests[uid], result); - else + if ( uid !in key_requests || |key_requests[uid]| == 0 ) key_requests[uid] = result; + else + key_requests[uid] = compose_results(key_requests[uid], result); # Mark that a worker is done. ++done_with[uid]; @@ -251,30 +240,39 @@ event SumStats::cluster_key_response(uid: string, ssid: string, key: Key, result #print fmt("worker_count:%d :: done_with:%d", Cluster::worker_count, done_with[uid]); if ( Cluster::worker_count == done_with[uid] ) { - local ss = stats_store[ssid]; + local ss = stats_store[ss_name]; local ir = key_requests[uid]; if ( check_thresholds(ss, key, ir, 1.0) ) { threshold_crossed(ss, key, ir); - event SumStats::cluster_threshold_crossed(ss$id, key, threshold_tracker[ss$id][key]); + event SumStats::cluster_threshold_crossed(ss$name, key, threshold_tracker[ss$name][key]); } - delete done_with[uid]; - delete key_requests[uid]; - # Check that there is an outstanding view before subtracting. - if ( outstanding_global_views[ssid] > 0 ) - --outstanding_global_views[ssid]; + if ( cleanup ) + { + # We only want to delete the data if this is a non dynamic + # request because the dynamic requests use when statements + # and the data needs to remain available. + delete key_requests[uid]; + delete done_with[uid]; + + # Check that there is an outstanding view before subtracting. + # Global views only apply to non-dynamic requests. Dynamic + # requests must be serviced. + if ( outstanding_global_views[ss_name] > 0 ) + --outstanding_global_views[ss_name]; + } } } # Managers handle intermediate updates here. -event SumStats::cluster_key_intermediate_response(ssid: string, key: Key) +event SumStats::cluster_key_intermediate_response(ss_name: string, key: Key) { #print fmt("MANAGER: receiving intermediate key data from %s", get_event_peer()$descr); #print fmt("MANAGER: requesting key data for %s", key2str(key)); - if ( ssid in outstanding_global_views && - |outstanding_global_views[ssid]| > max_outstanding_global_views ) + if ( ss_name in outstanding_global_views && + |outstanding_global_views[ss_name]| > max_outstanding_global_views ) { # Don't do this intermediate update. Perhaps at some point in the future # we will queue and randomly select from these ignored intermediate @@ -282,13 +280,14 @@ event SumStats::cluster_key_intermediate_response(ssid: string, key: Key) return; } - ++outstanding_global_views[ssid]; + ++outstanding_global_views[ss_name]; local uid = unique_id(""); - event SumStats::cluster_key_request(uid, ssid, key); + done_with[uid] = 0; + event SumStats::cluster_key_request(uid, ss_name, key, T); } -event SumStats::cluster_ss_response(uid: string, ssid: string, data: ResultTable, done: bool) +event SumStats::cluster_ss_response(uid: string, ss_name: string, data: ResultTable, done: bool) { #print fmt("MANAGER: receiving results from %s", get_event_peer()$descr); @@ -297,7 +296,7 @@ event SumStats::cluster_ss_response(uid: string, ssid: string, data: ResultTable ++done_with[uid]; local local_data = stats_results[uid]; - local ss = stats_store[ssid]; + local ss = stats_store[ss_name]; for ( key in data ) { @@ -314,13 +313,14 @@ event SumStats::cluster_ss_response(uid: string, ssid: string, data: ResultTable if ( check_thresholds(ss, key, local_data[key], 1.0) ) { threshold_crossed(ss, key, local_data[key]); - event SumStats::cluster_threshold_crossed(ss$id, key, threshold_tracker[ss$id][key]); + event SumStats::cluster_threshold_crossed(ss$name, key, threshold_tracker[ss$name][key]); } } } # If the data has been collected from all peers, we are done and ready to finish. - if ( Cluster::worker_count == done_with[uid] ) + if ( Cluster::worker_count == done_with[uid] && + /^dyn-/ !in uid ) { if ( ss?$epoch_finished ) ss$epoch_finished(local_data); @@ -328,14 +328,60 @@ event SumStats::cluster_ss_response(uid: string, ssid: string, data: ResultTable # Clean up delete stats_results[uid]; delete done_with[uid]; - # Not sure I need to reset the sumstat on the manager. reset(ss); } } -event remote_connection_handshake_done(p: event_peer) &priority=5 +function request(ss_name: string): ResultTable { - send_id(p, "SumStats::stats_store"); - send_id(p, "SumStats::reducer_store"); + # This only needs to be implemented this way for cluster compatibility. + local uid = unique_id("dyn-"); + stats_results[uid] = table(); + done_with[uid] = 0; + event SumStats::cluster_ss_request(uid, ss_name, F); + + return when ( uid in done_with && Cluster::worker_count == done_with[uid] ) + { + if ( uid in stats_results ) + { + local ss_result = stats_results[uid]; + # Clean up + delete stats_results[uid]; + delete done_with[uid]; + reset(stats_store[ss_name]); + return ss_result; + } + else + return table(); + } + timeout 1.1min + { + Reporter::warning(fmt("Dynamic SumStat request for %s took longer than 1 minute and was automatically cancelled.", ss_name)); + return table(); + } } + +function request_key(ss_name: string, key: Key): Result + { + local uid = unique_id("dyn-"); + done_with[uid] = 0; + key_requests[uid] = table(); + + event SumStats::cluster_key_request(uid, ss_name, key, F); + return when ( uid in done_with && Cluster::worker_count == done_with[uid] ) + { + local result = key_requests[uid]; + # Clean up + delete key_requests[uid]; + delete done_with[uid]; + + return result; + } + timeout 1.1min + { + Reporter::warning(fmt("Dynamic SumStat key request for %s (%s) took longer than 1 minute and was automatically cancelled.", ss_name, key)); + return table(); + } + } + @endif diff --git a/scripts/base/frameworks/sumstats/main.bro b/scripts/base/frameworks/sumstats/main.bro index 6864966766..b1e5761483 100644 --- a/scripts/base/frameworks/sumstats/main.bro +++ b/scripts/base/frameworks/sumstats/main.bro @@ -87,6 +87,10 @@ export { ## is no assurance provided as to where the callbacks ## will be executed on clusters. type SumStat: record { + ## An arbitrary name for the sumstat so that it can + ## be referred to later. + name: string; + ## The interval at which this filter should be "broken" ## and the '$epoch_finished' callback called. The ## results are also reset at this time so any threshold @@ -102,22 +106,22 @@ export { ## :bro:see:`Result` structure which will be used ## for thresholding. ## This is required if a $threshold value is given. - threshold_val: function(key: SumStats::Key, result: SumStats::Result): count &optional; + threshold_val: function(key: SumStats::Key, result: SumStats::Result): double &optional; ## The threshold value for calling the ## $threshold_crossed callback. - threshold: count &optional; + threshold: double &optional; ## A series of thresholds for calling the ## $threshold_crossed callback. - threshold_series: vector of count &optional; + threshold_series: vector of double &optional; ## A callback that is called when a threshold is crossed. threshold_crossed: function(key: SumStats::Key, result: SumStats::Result) &optional; ## A callback with the full collection of Results for ## this SumStat. - epoch_finished: function(rt: SumStats::ResultTable) &optional; + epoch_finished: function(rt: SumStats::ResultTable) &optional; }; ## Create a summary statistic. @@ -134,19 +138,37 @@ export { ## obs: The data point to send into the stream. global observe: function(id: string, key: SumStats::Key, obs: SumStats::Observation); - ## This record is primarily used for internal threshold tracking. - type Thresholding: record { - # Internal use only. Indicates if a simple threshold was already crossed. - is_threshold_crossed: bool &default=F; + ## Dynamically request a sumstat. This function should be + ## used sparingly and not as a replacement for the callbacks + ## from the :bro:see:`SumStat` record. The function is only + ## available for use within "when" statements as an asynchronous + ## function. + ## + ## ss_name: SumState name. + ## + ## Returns: The result table for the requested sumstat. + global request: function(ss_name: string): ResultTable; - # Internal use only. Current key for threshold series. - threshold_series_index: count &default=0; - }; + ## Dynamically request a sumstat key. This function should be + ## used sparingly and not as a replacement for the callbacks + ## from the :bro:see:`SumStat` record. The function is only + ## available for use within "when" statements as an asynchronous + ## function. + ## + ## ss_name: SumStat name. + ## + ## key: The SumStat key being requested. + ## + ## Returns: The result for the requested sumstat key. + global request_key: function(ss_name: string, key: Key): Result; + + ## This record is primarily used for internal threshold tracking. + type Thresholding: record {}; ## This event is generated when thresholds are reset for a SumStat. ## - ## ssid: SumStats ID that thresholds were reset for. - global thresholds_reset: event(ssid: string); + ## name: SumStats name that thresholds were reset for. + global thresholds_reset: event(name: string); ## Helper function to represent a :bro:type:`SumStats::Key` value as ## a simple string. @@ -157,19 +179,43 @@ export { global key2str: function(key: SumStats::Key): string; } +# The function prototype for plugins to do calculations. +type ObserveFunc: function(r: Reducer, val: double, data: Observation, rv: ResultVal); + redef record Reducer += { - # Internal use only. Provides a reference back to the related SumStats by it's ID. - sid: string &optional; + # Internal use only. Provides a reference back to the related SumStats by its name. + ssname: string &optional; + + calc_funcs: vector of Calculation &optional; }; +redef record Thresholding += { + # Internal use only. Indicates if a simple threshold was already crossed. + is_threshold_crossed: bool &default=F; + + # Internal use only. Current key for threshold series. + threshold_series_index: count &default=0; +}; + + # Internal use only. For tracking thresholds per sumstat and key. global threshold_tracker: table[string] of table[Key] of Thresholding &optional; redef record SumStat += { + # Internal use only. + ssname: string &optional; + # Internal use only (mostly for cluster coherency). id: string &optional; }; +# Prototype the hook point for plugins to initialize any result values. +global init_resultval_hook: hook(r: Reducer, rv: ResultVal); + +# Prototype the hook point for plugins to merge Results. +global compose_resultvals_hook: hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal); + + # Store of sumstats indexed on the sumstat id. global stats_store: table[string] of SumStat = table(); @@ -182,20 +228,20 @@ global result_store: table[string] of ResultTable = table(); # Store of threshold information. global thresholds_store: table[string, Key] of bool = table(); +# Store the calculations. +global calc_store: table[Calculation] of ObserveFunc = table(); + +# Store the dependencies for Calculations. +global calc_deps: table[Calculation] of vector of Calculation = table(); + +# Hook for registering observation calculation plugins. +global register_observe_plugins: hook(); + # This is called whenever key values are updated and the new val is given as the # `val` argument. It's only prototyped here because cluster and non-cluster have # separate implementations. global data_added: function(ss: SumStat, key: Key, result: Result); -# Prototype the hook point for plugins to do calculations. -global observe_hook: hook(r: Reducer, val: double, data: Observation, rv: ResultVal); - -# Prototype the hook point for plugins to initialize any result values. -global init_resultval_hook: hook(r: Reducer, rv: ResultVal); - -# Prototype the hook point for plugins to merge Results. -global compose_resultvals_hook: hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal); - # Event that is used to "finish" measurements and adapt the measurement # framework for clustered or non-clustered usage. global finish_epoch: event(ss: SumStat); @@ -210,6 +256,24 @@ function key2str(key: Key): string return fmt("sumstats_key(%s)", out); } +function register_observe_plugin(calc: Calculation, func: ObserveFunc) + { + calc_store[calc] = func; + } + +function add_observe_plugin_dependency(calc: Calculation, depends_on: Calculation) + { + if ( calc !in calc_deps ) + calc_deps[calc] = vector(); + calc_deps[calc][|calc_deps[calc]|] = depends_on; + } + +event bro_init() &priority=100000 + { + # Call all of the plugin registration hooks + hook register_observe_plugins(); + } + function init_resultval(r: Reducer): ResultVal { local rv: ResultVal = [$begin=network_time(), $end=network_time()]; @@ -234,25 +298,17 @@ function compose_results(r1: Result, r2: Result): Result { local result: Result = table(); - if ( |r1| > |r2| ) + for ( id in r1 ) { - for ( data_id in r1 ) - { - if ( data_id in r2 ) - result[data_id] = compose_resultvals(r1[data_id], r2[data_id]); - else - result[data_id] = r1[data_id]; - } + result[id] = r1[id]; } - else + + for ( id in r2 ) { - for ( data_id in r2 ) - { - if ( data_id in r1 ) - result[data_id] = compose_resultvals(r1[data_id], r2[data_id]); - else - result[data_id] = r2[data_id]; - } + if ( id in r1 ) + result[id] = compose_resultvals(r1[id], r2[id]); + else + result[id] = r2[id]; } return result; @@ -261,18 +317,42 @@ function compose_results(r1: Result, r2: Result): Result function reset(ss: SumStat) { - if ( ss$id in result_store ) - delete result_store[ss$id]; + if ( ss$name in result_store ) + delete result_store[ss$name]; - result_store[ss$id] = table(); + result_store[ss$name] = table(); if ( ss?$threshold || ss?$threshold_series ) { - threshold_tracker[ss$id] = table(); - event SumStats::thresholds_reset(ss$id); + threshold_tracker[ss$name] = table(); + event SumStats::thresholds_reset(ss$name); } } +# This could potentially recurse forever, but plugin authors +# should be making sure they aren't causing reflexive dependencies. +function add_calc_deps(calcs: vector of Calculation, c: Calculation) + { + #print fmt("Checking for deps for %s", c); + for ( i in calc_deps[c] ) + { + local skip_calc=F; + for ( j in calcs ) + { + if ( calcs[j] == calc_deps[c][i] ) + skip_calc=T; + } + if ( ! skip_calc ) + { + if ( calc_deps[c][i] in calc_deps ) + add_calc_deps(calcs, calc_deps[c][i]); + calcs[|c|] = calc_deps[c][i]; + #print fmt("add dep for %s [%s] ", c, calc_deps[c][i]); + } + } + + } + function create(ss: SumStat) { if ( (ss?$threshold || ss?$threshold_series) && ! ss?$threshold_val ) @@ -280,14 +360,32 @@ function create(ss: SumStat) Reporter::error("SumStats given a threshold with no $threshold_val function"); } - if ( ! ss?$id ) - ss$id=unique_id(""); - threshold_tracker[ss$id] = table(); - stats_store[ss$id] = ss; + threshold_tracker[ss$name] = table(); + stats_store[ss$name] = ss; for ( reducer in ss$reducers ) { - reducer$sid = ss$id; + reducer$ssname = ss$name; + reducer$calc_funcs = vector(); + for ( calc in reducer$apply ) + { + # Add in dependencies recursively. + if ( calc in calc_deps ) + add_calc_deps(reducer$calc_funcs, calc); + + # Don't add this calculation to the vector if + # it was already added by something else as a + # dependency. + local skip_calc=F; + for ( j in reducer$calc_funcs ) + { + if ( calc == reducer$calc_funcs[j] ) + skip_calc=T; + } + if ( ! skip_calc ) + reducer$calc_funcs[|reducer$calc_funcs|] = calc; + } + if ( reducer$stream !in reducer_store ) reducer_store[reducer$stream] = set(); add reducer_store[reducer$stream][reducer]; @@ -313,7 +411,7 @@ function observe(id: string, key: Key, obs: Observation) if ( r?$pred && ! r$pred(key, obs) ) next; - local ss = stats_store[r$sid]; + local ss = stats_store[r$ssname]; # If there is a threshold and no epoch_finished callback # we don't need to continue counting since the data will @@ -324,17 +422,21 @@ function observe(id: string, key: Key, obs: Observation) # future if on demand access is provided to the # SumStats results. if ( ! ss?$epoch_finished && - r$sid in threshold_tracker && - key in threshold_tracker[r$sid] && ( ss?$threshold && - threshold_tracker[r$sid][key]$is_threshold_crossed ) || + r$ssname in threshold_tracker && + key in threshold_tracker[r$ssname] && + threshold_tracker[r$ssname][key]$is_threshold_crossed ) || ( ss?$threshold_series && - threshold_tracker[r$sid][key]$threshold_series_index+1 == |ss$threshold_series| ) ) + r$ssname in threshold_tracker && + key in threshold_tracker[r$ssname] && + threshold_tracker[r$ssname][key]$threshold_series_index == |ss$threshold_series| ) ) + { next; + } - if ( r$sid !in result_store ) - result_store[ss$id] = table(); - local results = result_store[r$sid]; + if ( r$ssname !in result_store ) + result_store[r$ssname] = table(); + local results = result_store[r$ssname]; if ( key !in results ) results[key] = table(); @@ -350,10 +452,13 @@ function observe(id: string, key: Key, obs: Observation) # If a string was given, fall back to 1.0 as the value. local val = 1.0; - if ( obs?$num || obs?$dbl ) - val = obs?$dbl ? obs$dbl : obs$num; + if ( obs?$num ) + val = obs$num; + else if ( obs?$dbl ) + val = obs$dbl; - hook observe_hook(r, val, obs, result_val); + for ( i in r$calc_funcs ) + calc_store[r$calc_funcs[i]](r, val, obs, result_val); data_added(ss, key, result); } } @@ -366,6 +471,8 @@ function check_thresholds(ss: SumStat, key: Key, result: Result, modify_pct: dou return F; # Add in the extra ResultVals to make threshold_vals easier to write. + # This length comparison should work because we just need to make + # sure that we have the same number of reducers and results. if ( |ss$reducers| != |result| ) { for ( reducer in ss$reducers ) @@ -378,11 +485,11 @@ function check_thresholds(ss: SumStat, key: Key, result: Result, modify_pct: dou local watch = ss$threshold_val(key, result); if ( modify_pct < 1.0 && modify_pct > 0.0 ) - watch = double_to_count(floor(watch/modify_pct)); + watch = watch/modify_pct; - if ( ss$id !in threshold_tracker ) - threshold_tracker[ss$id] = table(); - local t_tracker = threshold_tracker[ss$id]; + if ( ss$name !in threshold_tracker ) + threshold_tracker[ss$name] = table(); + local t_tracker = threshold_tracker[ss$name]; if ( key !in t_tracker ) { @@ -398,7 +505,7 @@ function check_thresholds(ss: SumStat, key: Key, result: Result, modify_pct: dou } if ( ss?$threshold_series && - |ss$threshold_series| >= tt$threshold_series_index && + |ss$threshold_series| > tt$threshold_series_index && watch >= ss$threshold_series[tt$threshold_series_index] ) { # A threshold series was given and the value crossed the next @@ -426,7 +533,7 @@ function threshold_crossed(ss: SumStat, key: Key, result: Result) } ss$threshold_crossed(key, result); - local tt = threshold_tracker[ss$id][key]; + local tt = threshold_tracker[ss$name][key]; tt$is_threshold_crossed = T; # Bump up to the next threshold series index if a threshold series is being used. diff --git a/scripts/base/frameworks/sumstats/non-cluster.bro b/scripts/base/frameworks/sumstats/non-cluster.bro index f27d4b5cfb..265261f1bd 100644 --- a/scripts/base/frameworks/sumstats/non-cluster.bro +++ b/scripts/base/frameworks/sumstats/non-cluster.bro @@ -4,9 +4,9 @@ module SumStats; event SumStats::finish_epoch(ss: SumStat) { - if ( ss$id in result_store ) + if ( ss$name in result_store ) { - local data = result_store[ss$id]; + local data = result_store[ss$name]; if ( ss?$epoch_finished ) ss$epoch_finished(data); @@ -16,9 +16,32 @@ event SumStats::finish_epoch(ss: SumStat) schedule ss$epoch { SumStats::finish_epoch(ss) }; } - function data_added(ss: SumStat, key: Key, result: Result) { if ( check_thresholds(ss, key, result, 1.0) ) threshold_crossed(ss, key, result); } + +function request(ss_name: string): ResultTable + { + # This only needs to be implemented this way for cluster compatibility. + return when ( T ) + { + if ( ss_name in result_store ) + return result_store[ss_name]; + else + return table(); + } + } + +function request_key(ss_name: string, key: Key): Result + { + # This only needs to be implemented this way for cluster compatibility. + return when ( T ) + { + if ( ss_name in result_store && key in result_store[ss_name] ) + return result_store[ss_name][key]; + else + return table(); + } + } \ No newline at end of file diff --git a/scripts/base/frameworks/sumstats/plugins/average.bro b/scripts/base/frameworks/sumstats/plugins/average.bro index a409bb9408..8f7f7b568f 100644 --- a/scripts/base/frameworks/sumstats/plugins/average.bro +++ b/scripts/base/frameworks/sumstats/plugins/average.bro @@ -1,4 +1,4 @@ -@load base/frameworks/sumstats +@load ../main module SumStats; @@ -14,17 +14,18 @@ export { }; } -hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) +hook register_observe_plugins() { - if ( AVERAGE in r$apply ) + register_observe_plugin(AVERAGE, function(r: Reducer, val: double, obs: Observation, rv: ResultVal) { if ( ! rv?$average ) rv$average = val; else rv$average += (val - rv$average) / rv$num; - } + }); } + hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { if ( rv1?$average && rv2?$average ) diff --git a/scripts/base/frameworks/sumstats/plugins/max.bro b/scripts/base/frameworks/sumstats/plugins/max.bro index 6167d31f10..d43ad9dc38 100644 --- a/scripts/base/frameworks/sumstats/plugins/max.bro +++ b/scripts/base/frameworks/sumstats/plugins/max.bro @@ -1,4 +1,4 @@ -@load base/frameworks/sumstats +@load ../main module SumStats; @@ -14,15 +14,15 @@ export { }; } -hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) +hook register_observe_plugins() { - if ( MAX in r$apply ) + register_observe_plugin(MAX, function(r: Reducer, val: double, obs: Observation, rv: ResultVal) { if ( ! rv?$max ) rv$max = val; else if ( val > rv$max ) rv$max = val; - } + }); } hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) diff --git a/scripts/base/frameworks/sumstats/plugins/min.bro b/scripts/base/frameworks/sumstats/plugins/min.bro index a15ed0e733..014755cf32 100644 --- a/scripts/base/frameworks/sumstats/plugins/min.bro +++ b/scripts/base/frameworks/sumstats/plugins/min.bro @@ -1,4 +1,4 @@ -@load base/frameworks/sumstats +@load ../main module SumStats; @@ -14,17 +14,18 @@ export { }; } -hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) +hook register_observe_plugins() { - if ( MIN in r$apply ) + register_observe_plugin(MIN, function(r: Reducer, val: double, obs: Observation, rv: ResultVal) { if ( ! rv?$min ) rv$min = val; else if ( val < rv$min ) rv$min = val; - } + }); } + hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { if ( rv1?$min && rv2?$min ) diff --git a/scripts/base/frameworks/sumstats/plugins/sample.bro b/scripts/base/frameworks/sumstats/plugins/sample.bro index d0587bde08..92d17e503d 100644 --- a/scripts/base/frameworks/sumstats/plugins/sample.bro +++ b/scripts/base/frameworks/sumstats/plugins/sample.bro @@ -1,9 +1,14 @@ -@load base/frameworks/sumstats @load base/utils/queue +@load ../main module SumStats; export { + redef enum Calculation += { + ## Collect a sample of the last few observations. + SAMPLE + }; + redef record Reducer += { ## A number of sample Observations to collect. samples: count &default=0; @@ -27,14 +32,14 @@ function get_samples(rv: ResultVal): vector of Observation return s; } -hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) +hook register_observe_plugins() { - if ( r$samples > 0 ) + register_observe_plugin(SAMPLE, function(r: Reducer, val: double, obs: Observation, rv: ResultVal) { if ( ! rv?$samples ) rv$samples = Queue::init([$max_len=r$samples]); Queue::put(rv$samples, obs); - } + }); } hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) diff --git a/scripts/base/frameworks/sumstats/plugins/std-dev.bro b/scripts/base/frameworks/sumstats/plugins/std-dev.bro index 6411fe4bce..2e5b95b212 100644 --- a/scripts/base/frameworks/sumstats/plugins/std-dev.bro +++ b/scripts/base/frameworks/sumstats/plugins/std-dev.bro @@ -1,5 +1,5 @@ @load ./variance -@load base/frameworks/sumstats +@load ../main module SumStats; @@ -21,11 +21,18 @@ function calc_std_dev(rv: ResultVal) rv$std_dev = sqrt(rv$variance); } -# This depends on the variance plugin which uses priority -5 -hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) &priority=-10 +hook std_dev_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) { - if ( STD_DEV in r$apply ) + calc_std_dev(rv); + } + +hook register_observe_plugins() &priority=-10 + { + register_observe_plugin(STD_DEV, function(r: Reducer, val: double, obs: Observation, rv: ResultVal) + { calc_std_dev(rv); + }); + add_observe_plugin_dependency(STD_DEV, VARIANCE); } hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) &priority=-10 diff --git a/scripts/base/frameworks/sumstats/plugins/sum.bro b/scripts/base/frameworks/sumstats/plugins/sum.bro index 3e5b28e2be..074b4b72f3 100644 --- a/scripts/base/frameworks/sumstats/plugins/sum.bro +++ b/scripts/base/frameworks/sumstats/plugins/sum.bro @@ -1,4 +1,4 @@ -@load base/frameworks/sumstats +@load ../main module SumStats; @@ -14,19 +14,19 @@ export { sum: double &default=0.0; }; - type threshold_function: function(key: SumStats::Key, result: SumStats::Result): count; - global sum_threshold: function(data_id: string): threshold_function; + #type threshold_function: function(key: SumStats::Key, result: SumStats::Result): count; + #global sum_threshold: function(data_id: string): threshold_function; } -function sum_threshold(data_id: string): threshold_function - { - return function(key: SumStats::Key, result: SumStats::Result): count - { - print fmt("data_id: %s", data_id); - print result; - return double_to_count(result[data_id]$sum); - }; - } +#function sum_threshold(data_id: string): threshold_function +# { +# return function(key: SumStats::Key, result: SumStats::Result): count +# { +# print fmt("data_id: %s", data_id); +# print result; +# return double_to_count(result[data_id]$sum); +# }; +# } hook init_resultval_hook(r: Reducer, rv: ResultVal) { @@ -34,10 +34,12 @@ hook init_resultval_hook(r: Reducer, rv: ResultVal) rv$sum = 0; } -hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) +hook register_observe_plugins() { - if ( SUM in r$apply ) + register_observe_plugin(SUM, function(r: Reducer, val: double, obs: Observation, rv: ResultVal) + { rv$sum += val; + }); } hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) diff --git a/scripts/base/frameworks/sumstats/plugins/unique.bro b/scripts/base/frameworks/sumstats/plugins/unique.bro index a407a487a2..15fc28adb6 100644 --- a/scripts/base/frameworks/sumstats/plugins/unique.bro +++ b/scripts/base/frameworks/sumstats/plugins/unique.bro @@ -1,4 +1,4 @@ -@load base/frameworks/sumstats +@load ../main module SumStats; @@ -23,15 +23,15 @@ redef record ResultVal += { unique_vals: set[Observation] &optional; }; -hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) +hook register_observe_plugins() { - if ( UNIQUE in r$apply ) + register_observe_plugin(UNIQUE, function(r: Reducer, val: double, obs: Observation, rv: ResultVal) { if ( ! rv?$unique_vals ) rv$unique_vals=set(); add rv$unique_vals[obs]; rv$unique = |rv$unique_vals|; - } + }); } hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) diff --git a/scripts/base/frameworks/sumstats/plugins/variance.bro b/scripts/base/frameworks/sumstats/plugins/variance.bro index 1e7a00ea97..12d30cc4fe 100644 --- a/scripts/base/frameworks/sumstats/plugins/variance.bro +++ b/scripts/base/frameworks/sumstats/plugins/variance.bro @@ -1,5 +1,5 @@ @load ./average -@load base/frameworks/sumstats +@load ../main module SumStats; @@ -28,17 +28,17 @@ function calc_variance(rv: ResultVal) rv$variance = (rv$num > 1) ? rv$var_s/(rv$num-1) : 0.0; } -# Reduced priority since this depends on the average -hook observe_hook(r: Reducer, val: double, obs: Observation, rv: ResultVal) &priority=-5 +hook register_observe_plugins() &priority=-5 { - if ( VARIANCE in r$apply ) + register_observe_plugin(VARIANCE, function(r: Reducer, val: double, obs: Observation, rv: ResultVal) { if ( rv$num > 1 ) rv$var_s += ((val - rv$prev_avg) * (val - rv$average)); calc_variance(rv); rv$prev_avg = rv$average; - } + }); + add_observe_plugin_dependency(VARIANCE, AVERAGE); } # Reduced priority since this depends on the average diff --git a/scripts/policy/misc/app-stats/__load__.bro b/scripts/policy/misc/app-stats/__load__.bro new file mode 100644 index 0000000000..c468d055ee --- /dev/null +++ b/scripts/policy/misc/app-stats/__load__.bro @@ -0,0 +1,2 @@ +@load ./main +@load ./plugins \ No newline at end of file diff --git a/scripts/policy/misc/app-metrics.bro b/scripts/policy/misc/app-stats/main.bro similarity index 58% rename from scripts/policy/misc/app-metrics.bro rename to scripts/policy/misc/app-stats/main.bro index 3df38ad8ad..e4a38c6893 100644 --- a/scripts/policy/misc/app-metrics.bro +++ b/scripts/policy/misc/app-stats/main.bro @@ -1,3 +1,6 @@ +#! AppStats collects information about web applications in use +#! on the network. + @load base/protocols/http @load base/protocols/ssl @load base/frameworks/sumstats @@ -30,13 +33,17 @@ redef record connection += { resp_hostname: string &optional; }; +global add_sumstats: hook(id: conn_id, hostname: string, size: count); + + event bro_init() &priority=3 { Log::create_stream(AppStats::LOG, [$columns=Info]); local r1: SumStats::Reducer = [$stream="apps.bytes", $apply=set(SumStats::SUM)]; local r2: SumStats::Reducer = [$stream="apps.hits", $apply=set(SumStats::UNIQUE)]; - SumStats::create([$epoch=break_interval, + SumStats::create([$name="app-metrics", + $epoch=break_interval, $reducers=set(r1, r2), $epoch_finished(data: SumStats::ResultTable) = { @@ -55,41 +62,6 @@ event bro_init() &priority=3 }]); } -function add_sumstats(id: conn_id, hostname: string, size: count) - { - if ( /\.youtube\.com$/ in hostname && size > 512*1024 ) - { - SumStats::observe("apps.bytes", [$str="youtube"], [$num=size]); - SumStats::observe("apps.hits", [$str="youtube"], [$str=cat(id$orig_h)]); - } - else if ( /(\.facebook\.com|\.fbcdn\.net)$/ in hostname && size > 20 ) - { - SumStats::observe("apps.bytes", [$str="facebook"], [$num=size]); - SumStats::observe("apps.hits", [$str="facebook"], [$str=cat(id$orig_h)]); - } - else if ( /\.google\.com$/ in hostname && size > 20 ) - { - SumStats::observe("apps.bytes", [$str="google"], [$num=size]); - SumStats::observe("apps.hits", [$str="google"], [$str=cat(id$orig_h)]); - } - else if ( /\.nflximg\.com$/ in hostname && size > 200*1024 ) - { - SumStats::observe("apps.bytes", [$str="netflix"], [$num=size]); - SumStats::observe("apps.hits", [$str="netflix"], [$str=cat(id$orig_h)]); - } - else if ( /\.(pandora|p-cdn)\.com$/ in hostname && size > 512*1024 ) - { - SumStats::observe("apps.bytes", [$str="pandora"], [$num=size]); - SumStats::observe("apps.hits", [$str="pandora"], [$str=cat(id$orig_h)]); - } - else if ( /\.gmail\.com$/ in hostname && size > 20 ) - { - SumStats::observe("apps.bytes", [$str="gmail"], [$num=size]); - SumStats::observe("apps.hits", [$str="gmail"], [$str=cat(id$orig_h)]); - } -} - - event ssl_established(c: connection) { if ( c?$ssl && c$ssl?$server_name ) @@ -99,11 +71,11 @@ event ssl_established(c: connection) event connection_finished(c: connection) { if ( c?$resp_hostname ) - add_sumstats(c$id, c$resp_hostname, c$resp$size); + hook add_sumstats(c$id, c$resp_hostname, c$resp$size); } event HTTP::log_http(rec: HTTP::Info) { if( rec?$host ) - add_sumstats(rec$id, rec$host, rec$response_body_len); + hook add_sumstats(rec$id, rec$host, rec$response_body_len); } diff --git a/scripts/policy/misc/app-stats/plugins/__load__.bro b/scripts/policy/misc/app-stats/plugins/__load__.bro new file mode 100644 index 0000000000..7a3ea2da81 --- /dev/null +++ b/scripts/policy/misc/app-stats/plugins/__load__.bro @@ -0,0 +1,6 @@ +@load ./facebook +@load ./gmail +@load ./google +@load ./netflix +@load ./pandora +@load ./youtube \ No newline at end of file diff --git a/scripts/policy/misc/app-stats/plugins/facebook.bro b/scripts/policy/misc/app-stats/plugins/facebook.bro new file mode 100644 index 0000000000..edcb02b72a --- /dev/null +++ b/scripts/policy/misc/app-stats/plugins/facebook.bro @@ -0,0 +1,12 @@ +@load ../main + +module AppStats; + +hook add_sumstats(id: conn_id, hostname: string, size: count) + { + if ( /\.(facebook\.com|fbcdn\.net)$/ in hostname && size > 20 ) + { + SumStats::observe("apps.bytes", [$str="facebook"], [$num=size]); + SumStats::observe("apps.hits", [$str="facebook"], [$str=cat(id$orig_h)]); + } + } \ No newline at end of file diff --git a/scripts/policy/misc/app-stats/plugins/gmail.bro b/scripts/policy/misc/app-stats/plugins/gmail.bro new file mode 100644 index 0000000000..1642fb7651 --- /dev/null +++ b/scripts/policy/misc/app-stats/plugins/gmail.bro @@ -0,0 +1,12 @@ +@load ../main + +module AppStats; + +hook add_sumstats(id: conn_id, hostname: string, size: count) + { + if ( /\.gmail\.com$/ in hostname && size > 20 ) + { + SumStats::observe("apps.bytes", [$str="gmail"], [$num=size]); + SumStats::observe("apps.hits", [$str="gmail"], [$str=cat(id$orig_h)]); + } + } \ No newline at end of file diff --git a/scripts/policy/misc/app-stats/plugins/google.bro b/scripts/policy/misc/app-stats/plugins/google.bro new file mode 100644 index 0000000000..e1da3a9068 --- /dev/null +++ b/scripts/policy/misc/app-stats/plugins/google.bro @@ -0,0 +1,12 @@ +@load ../main + +module AppStats; + +hook add_sumstats(id: conn_id, hostname: string, size: count) + { + if ( /\.google\.com$/ in hostname && size > 20 ) + { + SumStats::observe("apps.bytes", [$str="google"], [$num=size]); + SumStats::observe("apps.hits", [$str="google"], [$str=cat(id$orig_h)]); + } + } \ No newline at end of file diff --git a/scripts/policy/misc/app-stats/plugins/netflix.bro b/scripts/policy/misc/app-stats/plugins/netflix.bro new file mode 100644 index 0000000000..5d429f0caf --- /dev/null +++ b/scripts/policy/misc/app-stats/plugins/netflix.bro @@ -0,0 +1,12 @@ +@load ../main + +module AppStats; + +hook add_sumstats(id: conn_id, hostname: string, size: count) + { + if ( /\.nflximg\.com$/ in hostname && size > 200*1024 ) + { + SumStats::observe("apps.bytes", [$str="netflix"], [$num=size]); + SumStats::observe("apps.hits", [$str="netflix"], [$str=cat(id$orig_h)]); + } + } \ No newline at end of file diff --git a/scripts/policy/misc/app-stats/plugins/pandora.bro b/scripts/policy/misc/app-stats/plugins/pandora.bro new file mode 100644 index 0000000000..6cfbfab72d --- /dev/null +++ b/scripts/policy/misc/app-stats/plugins/pandora.bro @@ -0,0 +1,12 @@ +@load ../main + +module AppStats; + +hook add_sumstats(id: conn_id, hostname: string, size: count) + { + if ( /\.(pandora|p-cdn)\.com$/ in hostname && size > 512*1024 ) + { + SumStats::observe("apps.bytes", [$str="pandora"], [$num=size]); + SumStats::observe("apps.hits", [$str="pandora"], [$str=cat(id$orig_h)]); + } + } \ No newline at end of file diff --git a/scripts/policy/misc/app-stats/plugins/youtube.bro b/scripts/policy/misc/app-stats/plugins/youtube.bro new file mode 100644 index 0000000000..af872cfdac --- /dev/null +++ b/scripts/policy/misc/app-stats/plugins/youtube.bro @@ -0,0 +1,12 @@ +@load ../main + +module AppStats; + +hook add_sumstats(id: conn_id, hostname: string, size: count) + { + if ( /\.youtube\.com$/ in hostname && size > 512*1024 ) + { + SumStats::observe("apps.bytes", [$str="youtube"], [$num=size]); + SumStats::observe("apps.hits", [$str="youtube"], [$str=cat(id$orig_h)]); + } + } \ No newline at end of file diff --git a/scripts/policy/misc/detect-traceroute/main.bro b/scripts/policy/misc/detect-traceroute/main.bro index c194d03e13..0cb7082919 100644 --- a/scripts/policy/misc/detect-traceroute/main.bro +++ b/scripts/policy/misc/detect-traceroute/main.bro @@ -29,7 +29,7 @@ export { ## Defines the threshold for ICMP Time Exceeded messages for a src-dst pair. ## This threshold only comes into play after a host is found to be ## sending low ttl packets. - const icmp_time_exceeded_threshold = 3 &redef; + const icmp_time_exceeded_threshold: double = 3 &redef; ## Interval at which to watch for the ## :bro:id:`ICMPTimeExceeded::icmp_time_exceeded_threshold` variable to be crossed. @@ -57,16 +57,17 @@ event bro_init() &priority=5 local r1: SumStats::Reducer = [$stream="traceroute.time_exceeded", $apply=set(SumStats::UNIQUE)]; local r2: SumStats::Reducer = [$stream="traceroute.low_ttl_packet", $apply=set(SumStats::SUM)]; - SumStats::create([$epoch=icmp_time_exceeded_interval, + SumStats::create([$name="traceroute-detection", + $epoch=icmp_time_exceeded_interval, $reducers=set(r1, r2), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { # Give a threshold value of zero depending on if the host # sends a low ttl packet. if ( require_low_ttl_packets && result["traceroute.low_ttl_packet"]$sum == 0 ) - return 0; + return 0.0; else - return result["traceroute.time_exceeded"]$unique; + return result["traceroute.time_exceeded"]$unique+0; }, $threshold=icmp_time_exceeded_threshold, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = diff --git a/scripts/policy/misc/scan.bro b/scripts/policy/misc/scan.bro index f3dcaf2291..f9c47a0311 100644 --- a/scripts/policy/misc/scan.bro +++ b/scripts/policy/misc/scan.bro @@ -39,15 +39,11 @@ export { ## The threshold of a unique number of hosts a scanning host has to have failed ## connections with on a single port. - const addr_scan_threshold = 25 &redef; + const addr_scan_threshold = 25.0 &redef; ## The threshold of a number of unique ports a scanning host has to have failed ## connections with on a single victim host. - const port_scan_threshold = 15 &redef; - - ## Custom thresholds based on service for address scan. This is primarily - ## useful for setting reduced thresholds for specific ports. - const addr_scan_custom_thresholds: table[port] of count &redef; + const port_scan_threshold = 15.0 &redef; global Scan::addr_scan_policy: hook(scanner: addr, victim: addr, scanned_port: port); global Scan::port_scan_policy: hook(scanner: addr, victim: addr, scanned_port: port); @@ -56,11 +52,12 @@ export { event bro_init() &priority=5 { local r1: SumStats::Reducer = [$stream="scan.addr.fail", $apply=set(SumStats::UNIQUE)]; - SumStats::create([$epoch=addr_scan_interval, + SumStats::create([$name="addr-scan", + $epoch=addr_scan_interval, $reducers=set(r1), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return double_to_count(result["scan.addr.fail"]$unique); + return result["scan.addr.fail"]$unique+0.0; }, #$threshold_func=check_addr_scan_threshold, $threshold=addr_scan_threshold, @@ -80,11 +77,12 @@ event bro_init() &priority=5 # Note: port scans are tracked similar to: table[src_ip, dst_ip] of set(port); local r2: SumStats::Reducer = [$stream="scan.port.fail", $apply=set(SumStats::UNIQUE)]; - SumStats::create([$epoch=port_scan_interval, + SumStats::create([$name="port-scan", + $epoch=port_scan_interval, $reducers=set(r2), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return double_to_count(result["scan.port.fail"]$unique); + return result["scan.port.fail"]$unique+0.0; }, $threshold=port_scan_threshold, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = diff --git a/scripts/policy/protocols/ftp/detect-bruteforcing.bro b/scripts/policy/protocols/ftp/detect-bruteforcing.bro index 21c9c403c7..36dfafb53a 100644 --- a/scripts/policy/protocols/ftp/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ftp/detect-bruteforcing.bro @@ -17,7 +17,7 @@ export { ## How many rejected usernames or passwords are required before being ## considered to be bruteforcing. - const bruteforce_threshold = 20 &redef; + const bruteforce_threshold: double = 20 &redef; ## The time period in which the threshold needs to be crossed before ## being reset. @@ -28,11 +28,12 @@ export { event bro_init() { local r1: SumStats::Reducer = [$stream="ftp.failed_auth", $apply=set(SumStats::UNIQUE)]; - SumStats::create([$epoch=bruteforce_measurement_interval, + SumStats::create([$name="ftp-detect-bruteforcing", + $epoch=bruteforce_measurement_interval, $reducers=set(r1), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return result["ftp.failed_auth"]$num; + return result["ftp.failed_auth"]$num+0.0; }, $threshold=bruteforce_threshold, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = diff --git a/scripts/policy/protocols/http/detect-sqli.bro b/scripts/policy/protocols/http/detect-sqli.bro index 11dba0dc46..1d8d9d0904 100644 --- a/scripts/policy/protocols/http/detect-sqli.bro +++ b/scripts/policy/protocols/http/detect-sqli.bro @@ -28,7 +28,7 @@ export { ## Defines the threshold that determines if an SQL injection attack ## is ongoing based on the number of requests that appear to be SQL ## injection attacks. - const sqli_requests_threshold = 50 &redef; + const sqli_requests_threshold: double = 50.0 &redef; ## Interval at which to watch for the ## :bro:id:`HTTP::sqli_requests_threshold` variable to be crossed. @@ -64,11 +64,12 @@ event bro_init() &priority=3 # determine when it looks like an actual attack and how to respond when # thresholds are crossed. local r1: SumStats::Reducer = [$stream="http.sqli.attacker", $apply=set(SumStats::SUM), $samples=collect_SQLi_samples]; - SumStats::create([$epoch=sqli_requests_interval, + SumStats::create([$name="detect-sqli-attackers", + $epoch=sqli_requests_interval, $reducers=set(r1), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return double_to_count(result["http.sqli.attacker"]$sum); + return result["http.sqli.attacker"]$sum; }, $threshold=sqli_requests_threshold, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = @@ -82,11 +83,12 @@ event bro_init() &priority=3 }]); local r2: SumStats::Reducer = [$stream="http.sqli.victim", $apply=set(SumStats::SUM), $samples=collect_SQLi_samples]; - SumStats::create([$epoch=sqli_requests_interval, + SumStats::create([$name="detect-sqli-victims", + $epoch=sqli_requests_interval, $reducers=set(r2), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return double_to_count(result["http.sqli.victim"]$sum); + return result["http.sqli.victim"]$sum; }, $threshold=sqli_requests_threshold, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro index 309905e939..161a314b8c 100644 --- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -27,7 +27,7 @@ export { ## The number of failed SSH connections before a host is designated as ## guessing passwords. - const password_guesses_limit = 30 &redef; + const password_guesses_limit: double = 30 &redef; ## The amount of time to remember presumed non-successful logins to build ## model of a password guesser. @@ -43,11 +43,12 @@ export { event bro_init() { local r1: SumStats::Reducer = [$stream="ssh.login.failure", $apply=set(SumStats::SUM)]; - SumStats::create([$epoch=guessing_timeout, + SumStats::create([$name="detect-ssh-bruteforcing", + $epoch=guessing_timeout, $reducers=set(r1), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return double_to_count(result["ssh.login.failure"]$sum); + return result["ssh.login.failure"]$sum; }, $threshold=password_guesses_limit, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = diff --git a/scripts/site/local.bro b/scripts/site/local.bro index dfebd9923a..90832b4a07 100644 --- a/scripts/site/local.bro +++ b/scripts/site/local.bro @@ -11,6 +11,13 @@ # Load the scan detection script. @load misc/scan +# Log some information about web applications being used by users +# on your network. +@load misc/app-metrics + +# Detect traceroute being run on the network. +@load misc/detect-traceroute + # Generate notices when vulnerable versions of software are discovered. # The default is to only monitor software found in the address space defined # as "local". Refer to the software framework's documentation for more diff --git a/testing/btest/Baseline/scripts.base.frameworks.sumstats.on-demand-cluster/manager-1..stdout b/testing/btest/Baseline/scripts.base.frameworks.sumstats.on-demand-cluster/manager-1..stdout new file mode 100644 index 0000000000..ed14a1c753 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.sumstats.on-demand-cluster/manager-1..stdout @@ -0,0 +1,7 @@ +Complete SumStat request + Host: 6.5.4.3 -> 1 + Host: 10.10.10.10 -> 5 + Host: 1.2.3.4 -> 169 + Host: 7.2.1.5 -> 145 +SumStat key request + Host: 7.2.1.5 -> 145 diff --git a/testing/btest/Baseline/scripts.base.frameworks.sumstats.on-demand/.stdout b/testing/btest/Baseline/scripts.base.frameworks.sumstats.on-demand/.stdout new file mode 100644 index 0000000000..876c368eb3 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.sumstats.on-demand/.stdout @@ -0,0 +1,5 @@ +Complete SumStat request + Host: 1.2.3.4 -> 42 + Host: 4.3.2.1 -> 7 +Key request for 1.2.3.4 + Host: 1.2.3.4 -> 42 diff --git a/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro b/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro index 1b7903ca1a..956c43a57b 100644 --- a/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro +++ b/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro @@ -23,7 +23,8 @@ global n = 0; event bro_init() &priority=5 { local r1: SumStats::Reducer = [$stream="test", $apply=set(SumStats::SUM, SumStats::MIN, SumStats::MAX, SumStats::AVERAGE, SumStats::STD_DEV, SumStats::VARIANCE, SumStats::UNIQUE)]; - SumStats::create([$epoch=5secs, + SumStats::create([$name="test", + $epoch=5secs, $reducers=set(r1), $epoch_finished(rt: SumStats::ResultTable) = { diff --git a/testing/btest/scripts/base/frameworks/sumstats/basic.bro b/testing/btest/scripts/base/frameworks/sumstats/basic.bro index 0b2851bf10..54160cbf54 100644 --- a/testing/btest/scripts/base/frameworks/sumstats/basic.bro +++ b/testing/btest/scripts/base/frameworks/sumstats/basic.bro @@ -11,16 +11,17 @@ event bro_init() &priority=5 SumStats::MIN, SumStats::STD_DEV, SumStats::UNIQUE)]; - SumStats::create([$epoch=3secs, - $reducers=set(r1), - $epoch_finished(data: SumStats::ResultTable) = - { - for ( key in data ) - { - local r = data[key]["test.metric"]; - print fmt("Host: %s - num:%d - sum:%.1f - var:%.1f - avg:%.1f - max:%.1f - min:%.1f - std_dev:%.1f - unique:%d", key$host, r$num, r$sum, r$variance, r$average, r$max, r$min, r$std_dev, r$unique); - } - } + SumStats::create([$name="test", + $epoch=3secs, + $reducers=set(r1), + $epoch_finished(data: SumStats::ResultTable) = + { + for ( key in data ) + { + local r = data[key]["test.metric"]; + print fmt("Host: %s - num:%d - sum:%.1f - var:%.1f - avg:%.1f - max:%.1f - min:%.1f - std_dev:%.1f - unique:%d", key$host, r$num, r$sum, r$variance, r$average, r$max, r$min, r$std_dev, r$unique); + } + } ]); SumStats::observe("test.metric", [$host=1.2.3.4], [$num=5]); diff --git a/testing/btest/scripts/base/frameworks/sumstats/cluster-intermediate-update.bro b/testing/btest/scripts/base/frameworks/sumstats/cluster-intermediate-update.bro index 303a0dc852..d54e432030 100644 --- a/testing/btest/scripts/base/frameworks/sumstats/cluster-intermediate-update.bro +++ b/testing/btest/scripts/base/frameworks/sumstats/cluster-intermediate-update.bro @@ -20,13 +20,14 @@ redef Log::default_rotation_interval = 0secs; event bro_init() &priority=5 { local r1: SumStats::Reducer = [$stream="test.metric", $apply=set(SumStats::SUM)]; - SumStats::create([$epoch=1hr, + SumStats::create([$name="test", + $epoch=1hr, $reducers=set(r1), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return double_to_count(result["test.metric"]$sum); + return result["test.metric"]$sum; }, - $threshold=100, + $threshold=100.0, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = { print fmt("A test metric threshold was crossed with a value of: %.1f", result["test.metric"]$sum); diff --git a/testing/btest/scripts/base/frameworks/sumstats/on-demand-cluster.bro b/testing/btest/scripts/base/frameworks/sumstats/on-demand-cluster.bro new file mode 100644 index 0000000000..9ee0511b47 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/sumstats/on-demand-cluster.bro @@ -0,0 +1,93 @@ +# @TEST-SERIALIZE: comm +# +# @TEST-EXEC: btest-bg-run manager-1 BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro %INPUT +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT +# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT +# @TEST-EXEC: btest-bg-wait 15 + +# @TEST-EXEC: btest-diff manager-1/.stdout + +@TEST-START-FILE cluster-layout.bro +redef Cluster::nodes = { + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1", "worker-2")], + ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37760/tcp, $manager="manager-1", $interface="eth0"], + ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37761/tcp, $manager="manager-1", $interface="eth1"], +}; +@TEST-END-FILE + +redef Log::default_rotation_interval = 0secs; + +global n = 0; + +event bro_init() &priority=5 + { + local r1: SumStats::Reducer = [$stream="test", $apply=set(SumStats::SUM, SumStats::MIN, SumStats::MAX, SumStats::AVERAGE, SumStats::STD_DEV, SumStats::VARIANCE, SumStats::UNIQUE)]; + SumStats::create([$name="test sumstat", + $epoch=1hr, + $reducers=set(r1)]); + } + +event remote_connection_closed(p: event_peer) + { + terminate(); + } + +global ready_for_data: event(); +redef Cluster::manager2worker_events += /^ready_for_data$/; + +event ready_for_data() + { + if ( Cluster::node == "worker-1" ) + { + SumStats::observe("test", [$host=1.2.3.4], [$num=34]); + SumStats::observe("test", [$host=1.2.3.4], [$num=30]); + SumStats::observe("test", [$host=6.5.4.3], [$num=1]); + SumStats::observe("test", [$host=7.2.1.5], [$num=54]); + } + if ( Cluster::node == "worker-2" ) + { + SumStats::observe("test", [$host=1.2.3.4], [$num=75]); + SumStats::observe("test", [$host=1.2.3.4], [$num=30]); + SumStats::observe("test", [$host=7.2.1.5], [$num=91]); + SumStats::observe("test", [$host=10.10.10.10], [$num=5]); + } + } + + +event on_demand2() + { + local host = 7.2.1.5; + when ( local result = SumStats::request_key("test sumstat", [$host=host]) ) + { + print "SumStat key request"; + print fmt(" Host: %s -> %.0f", host, result["test"]$sum); + terminate(); + } + } + +event on_demand() + { + when ( local results = SumStats::request("test sumstat") ) + { + print "Complete SumStat request"; + for ( key in results ) + print fmt(" Host: %s -> %.0f", key$host, results[key]["test"]$sum); + + event on_demand2(); + } + } + +global peer_count = 0; +event remote_connection_handshake_done(p: event_peer) &priority=-5 + { + ++peer_count; + if ( peer_count == 2 ) + { + if ( Cluster::local_node_type() == Cluster::MANAGER ) + event ready_for_data(); + + schedule 1sec { on_demand() }; + } + } + diff --git a/testing/btest/scripts/base/frameworks/sumstats/on-demand.bro b/testing/btest/scripts/base/frameworks/sumstats/on-demand.bro new file mode 100644 index 0000000000..f93e1a72dc --- /dev/null +++ b/testing/btest/scripts/base/frameworks/sumstats/on-demand.bro @@ -0,0 +1,45 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout + +redef exit_only_after_terminate=T; + + +event on_demand() + { + when ( local results = SumStats::request("test") ) + { + print "Complete SumStat request"; + for ( key in results ) + { + print fmt(" Host: %s -> %.0f", key$host, results[key]["test.reducer"]$sum); + } + } + } + +event on_demand_key() + { + local host = 1.2.3.4; + when ( local result = SumStats::request_key("test", [$host=host]) ) + { + print fmt("Key request for %s", host); + print fmt(" Host: %s -> %.0f", host, result["test.reducer"]$sum); + terminate(); + } + } + +event bro_init() &priority=5 + { + local r1: SumStats::Reducer = [$stream="test.reducer", + $apply=set(SumStats::SUM)]; + SumStats::create([$name="test", + $epoch=1hr, + $reducers=set(r1)]); + + # Seed some data but notice there are no callbacks defined in the sumstat! + SumStats::observe("test.reducer", [$host=1.2.3.4], [$num=42]); + SumStats::observe("test.reducer", [$host=4.3.2.1], [$num=7]); + + schedule 0.1 secs { on_demand() }; + schedule 1 secs { on_demand_key() }; + } + diff --git a/testing/btest/scripts/base/frameworks/sumstats/thresholding.bro b/testing/btest/scripts/base/frameworks/sumstats/thresholding.bro index ddc053bd23..b00b30a375 100644 --- a/testing/btest/scripts/base/frameworks/sumstats/thresholding.bro +++ b/testing/btest/scripts/base/frameworks/sumstats/thresholding.bro @@ -8,14 +8,15 @@ redef enum Notice::Type += { event bro_init() &priority=5 { local r1: SumStats::Reducer = [$stream="test.metric", $apply=set(SumStats::SUM)]; - SumStats::create([$epoch=3secs, + SumStats::create([$name="test1", + $epoch=3secs, $reducers=set(r1), #$threshold_val = SumStats::sum_threshold("test.metric"), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return double_to_count(result["test.metric"]$sum); + return result["test.metric"]$sum; }, - $threshold=5, + $threshold=5.0, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = { local r = result["test.metric"]; @@ -24,14 +25,15 @@ event bro_init() &priority=5 ]); local r2: SumStats::Reducer = [$stream="test.metric", $apply=set(SumStats::SUM)]; - SumStats::create([$epoch=3secs, + SumStats::create([$name="test2", + $epoch=3secs, $reducers=set(r2), #$threshold_val = SumStats::sum_threshold("test.metric"), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { - return double_to_count(result["test.metric"]$sum); + return result["test.metric"]$sum; }, - $threshold_series=vector(3,6,800), + $threshold_series=vector(3.0,6.0,800.0), $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = { local r = result["test.metric"]; @@ -41,19 +43,20 @@ event bro_init() &priority=5 local r3: SumStats::Reducer = [$stream="test.metric", $apply=set(SumStats::SUM)]; local r4: SumStats::Reducer = [$stream="test.metric2", $apply=set(SumStats::SUM)]; - SumStats::create([$epoch=3secs, + SumStats::create([$name="test3", + $epoch=3secs, $reducers=set(r3, r4), $threshold_val(key: SumStats::Key, result: SumStats::Result) = { # Calculate a ratio between sums of two reducers. if ( "test.metric2" in result && "test.metric" in result && result["test.metric"]$sum > 0 ) - return double_to_count(result["test.metric2"]$sum / result["test.metric"]$sum); + return result["test.metric2"]$sum / result["test.metric"]$sum; else - return 0; + return 0.0; }, # Looking for metric2 sum to be 5 times the sum of metric - $threshold=5, + $threshold=5.0, $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = { local thold = result["test.metric2"]$sum / result["test.metric"]$sum; From c4a1f30a87df3a8f04e4dfb7af08c26aead7e841 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 22 May 2013 14:59:31 -0400 Subject: [PATCH 102/881] Hopefully fixing a strange error. --- scripts/base/frameworks/sumstats/cluster.bro | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index 59cb4a8b47..e747c190fa 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -33,7 +33,7 @@ export { ## Event sent by nodes that are collecting sumstats after receiving a request for ## the sumstat from the manager. - global cluster_ss_response: event(uid: string, ss_name: string, data: ResultTable, done: bool); + global cluster_ss_response: event(uid: string, ss_name: string, data: ResultTable, done: bool, cleanup: bool); ## This event is sent by the manager in a cluster to initiate the collection of ## a single key value from a sumstat. It's typically used to get intermediate @@ -115,7 +115,7 @@ event SumStats::send_data(uid: string, ss_name: string, data: ResultTable, clean # Note: copy is needed to compensate serialization caching issue. This should be # changed to something else later. - event SumStats::cluster_ss_response(uid, ss_name, copy(local_data), done); + event SumStats::cluster_ss_response(uid, ss_name, copy(local_data), done, cleanup); if ( ! done ) schedule 0.01 sec { SumStats::send_data(uid, ss_name, incoming_data, T) }; } @@ -175,7 +175,7 @@ event SumStats::thresholds_reset(ss_name: string) # This variable is maintained by manager nodes as they collect and aggregate # results. # Index on a uid. -global stats_results: table[string] of ResultTable &create_expire=1min &default=table(); +global stats_results: table[string] of ResultTable &create_expire=1min; # This variable is maintained by manager nodes to track how many "dones" they # collected per collection unique id. Once the number of results for a uid @@ -292,7 +292,7 @@ event SumStats::cluster_key_intermediate_response(ss_name: string, key: Key) event SumStats::cluster_key_request(uid, ss_name, key, T); } -event SumStats::cluster_ss_response(uid: string, ss_name: string, data: ResultTable, done: bool) +event SumStats::cluster_ss_response(uid: string, ss_name: string, data: ResultTable, done: bool, cleanup: bool) { #print fmt("MANAGER: receiving results from %s", get_event_peer()$descr); @@ -300,6 +300,13 @@ event SumStats::cluster_ss_response(uid: string, ss_name: string, data: ResultTa if ( done ) ++done_with[uid]; + # We had better only be getting requests for stuff that exists. + if ( ss_name !in stats_store ) + return; + + if ( uid !in stats_results ) + stats_results[uid] = table(); + local local_data = stats_results[uid]; local ss = stats_store[ss_name]; @@ -324,8 +331,7 @@ event SumStats::cluster_ss_response(uid: string, ss_name: string, data: ResultTa } # If the data has been collected from all peers, we are done and ready to finish. - if ( Cluster::worker_count == done_with[uid] && - /^dyn-/ !in uid ) + if ( cleanup && Cluster::worker_count == done_with[uid] ) { if ( ss?$epoch_finished ) ss$epoch_finished(local_data); From 6bd9ab3bd671783e969783ca2ddfcc5ac96afcc4 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 22 May 2013 16:41:46 -0400 Subject: [PATCH 103/881] More adjustments to try and correct SumStats memory use. --- scripts/base/frameworks/sumstats/cluster.bro | 2 +- scripts/base/frameworks/sumstats/main.bro | 51 +++++++++++--------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index e747c190fa..01ec237948 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -164,7 +164,7 @@ event SumStats::cluster_threshold_crossed(ss_name: string, key: SumStats::Key, t event SumStats::thresholds_reset(ss_name: string) { - threshold_tracker[ss_name] = table(); + delete threshold_tracker[ss_name]; } @endif diff --git a/scripts/base/frameworks/sumstats/main.bro b/scripts/base/frameworks/sumstats/main.bro index b1e5761483..804b611319 100644 --- a/scripts/base/frameworks/sumstats/main.bro +++ b/scripts/base/frameworks/sumstats/main.bro @@ -204,9 +204,6 @@ global threshold_tracker: table[string] of table[Key] of Thresholding &optional; redef record SumStat += { # Internal use only. ssname: string &optional; - - # Internal use only (mostly for cluster coherency). - id: string &optional; }; # Prototype the hook point for plugins to initialize any result values. @@ -215,7 +212,6 @@ global init_resultval_hook: hook(r: Reducer, rv: ResultVal); # Prototype the hook point for plugins to merge Results. global compose_resultvals_hook: hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal); - # Store of sumstats indexed on the sumstat id. global stats_store: table[string] of SumStat = table(); @@ -322,8 +318,10 @@ function reset(ss: SumStat) result_store[ss$name] = table(); - if ( ss?$threshold || ss?$threshold_series ) + if ( (ss?$threshold || ss?$threshold_series) && + ss$name in threshold_tracker ) { + delete threshold_tracker[ss$name]; threshold_tracker[ss$name] = table(); event SumStats::thresholds_reset(ss$name); } @@ -360,7 +358,6 @@ function create(ss: SumStat) Reporter::error("SumStats given a threshold with no $threshold_val function"); } - threshold_tracker[ss$name] = table(); stats_store[ss$name] = ss; for ( reducer in ss$reducers ) @@ -491,28 +488,38 @@ function check_thresholds(ss: SumStat, key: Key, result: Result, modify_pct: dou threshold_tracker[ss$name] = table(); local t_tracker = threshold_tracker[ss$name]; - if ( key !in t_tracker ) + if ( ss?$threshold ) { - local ttmp: Thresholding; - t_tracker[key] = ttmp; - } - local tt = t_tracker[key]; + local tt: Thresholding; + if ( key in t_tracker ) + tt = t_tracker[key]; + + if ( ! tt$is_threshold_crossed && + watch >= ss$threshold ) + { + t_tracker[key] = tt; - if ( ss?$threshold && ! tt$is_threshold_crossed && watch >= ss$threshold ) - { - # Value crossed the threshold. - return T; + # Value crossed the threshold. + return T; + } } - if ( ss?$threshold_series && - |ss$threshold_series| > tt$threshold_series_index && - watch >= ss$threshold_series[tt$threshold_series_index] ) + if ( ss?$threshold_series ) { - # A threshold series was given and the value crossed the next - # value in the series. - return T; - } + local tt2: Thresholding; + if ( key in t_tracker ) + tt2 = t_tracker[key]; + if ( |ss$threshold_series| > tt2$threshold_series_index && + watch >= ss$threshold_series[tt2$threshold_series_index] ) + { + t_tracker[key] = tt2; + + # A threshold series was given and the value crossed the next + # value in the series. + return T; + } + } return F; } From 4f4ef99a6b12d4d44a7aa2600b5317d2e3806376 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Thu, 23 May 2013 10:12:17 -0400 Subject: [PATCH 104/881] SumStats changes to how thresholding works to simplify and reduce memory use. --- scripts/base/frameworks/sumstats/cluster.bro | 6 +- scripts/base/frameworks/sumstats/main.bro | 101 ++++++++----------- 2 files changed, 47 insertions(+), 60 deletions(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index 01ec237948..a69dd1ab54 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -54,7 +54,7 @@ export { global send_data: event(uid: string, ss_name: string, data: ResultTable, cleanup: bool); ## This event is generated when a threshold is crossed. - global cluster_threshold_crossed: event(ss_name: string, key: SumStats::Key, thold: Thresholding); + global cluster_threshold_crossed: event(ss_name: string, key: SumStats::Key, thold_index: count); } # Add events to the cluster framework to make this work. @@ -154,12 +154,12 @@ event SumStats::cluster_key_request(uid: string, ss_name: string, key: Key, clea } } -event SumStats::cluster_threshold_crossed(ss_name: string, key: SumStats::Key, thold: Thresholding) +event SumStats::cluster_threshold_crossed(ss_name: string, key: SumStats::Key, thold_index: count) { if ( ss_name !in threshold_tracker ) threshold_tracker[ss_name] = table(); - threshold_tracker[ss_name][key] = thold; + threshold_tracker[ss_name][key] = thold_index; } event SumStats::thresholds_reset(ss_name: string) diff --git a/scripts/base/frameworks/sumstats/main.bro b/scripts/base/frameworks/sumstats/main.bro index 804b611319..5c822e9983 100644 --- a/scripts/base/frameworks/sumstats/main.bro +++ b/scripts/base/frameworks/sumstats/main.bro @@ -189,22 +189,30 @@ redef record Reducer += { calc_funcs: vector of Calculation &optional; }; -redef record Thresholding += { - # Internal use only. Indicates if a simple threshold was already crossed. - is_threshold_crossed: bool &default=F; - - # Internal use only. Current key for threshold series. - threshold_series_index: count &default=0; -}; - - # Internal use only. For tracking thresholds per sumstat and key. -global threshold_tracker: table[string] of table[Key] of Thresholding &optional; +# In the case of a single threshold, 0 means the threshold isn't crossed. +# In the case of a threshold series, the number tracks the threshold offset. +global threshold_tracker: table[string] of table[Key] of count; -redef record SumStat += { - # Internal use only. - ssname: string &optional; -}; +function increment_threshold_tracker(ss_name: string, key: Key) + { + if ( ss_name !in threshold_tracker ) + threshold_tracker[ss_name] = table(); + if ( key !in threshold_tracker[ss_name] ) + threshold_tracker[ss_name][key] = 0; + + ++threshold_tracker[ss_name][key]; + } + +function get_threshold_index(ss_name: string, key: Key): count + { + if ( ss_name !in threshold_tracker ) + return 0; + if ( key !in threshold_tracker[ss_name] ) + return 0; + + return threshold_tracker[ss_name][key]; + } # Prototype the hook point for plugins to initialize any result values. global init_resultval_hook: hook(r: Reducer, rv: ResultVal); @@ -318,8 +326,7 @@ function reset(ss: SumStat) result_store[ss$name] = table(); - if ( (ss?$threshold || ss?$threshold_series) && - ss$name in threshold_tracker ) + if ( ss$name in threshold_tracker ) { delete threshold_tracker[ss$name]; threshold_tracker[ss$name] = table(); @@ -360,6 +367,9 @@ function create(ss: SumStat) stats_store[ss$name] = ss; + if ( ss?$threshold || ss?$threshold_series ) + threshold_tracker[ss$name] = table(); + for ( reducer in ss$reducers ) { reducer$ssname = ss$name; @@ -420,13 +430,11 @@ function observe(id: string, key: Key, obs: Observation) # SumStats results. if ( ! ss?$epoch_finished && ( ss?$threshold && - r$ssname in threshold_tracker && key in threshold_tracker[r$ssname] && - threshold_tracker[r$ssname][key]$is_threshold_crossed ) || + threshold_tracker[r$ssname][key] != 0 ) || ( ss?$threshold_series && - r$ssname in threshold_tracker && key in threshold_tracker[r$ssname] && - threshold_tracker[r$ssname][key]$threshold_series_index == |ss$threshold_series| ) ) + threshold_tracker[r$ssname][key] == |ss$threshold_series| ) ) { next; } @@ -464,7 +472,7 @@ function observe(id: string, key: Key, obs: Observation) # mid-break-interval threshold crossing detection for cluster deployments. function check_thresholds(ss: SumStat, key: Key, result: Result, modify_pct: double): bool { - if ( ! (ss?$threshold || ss?$threshold_series) ) + if ( ! (ss?$threshold || ss?$threshold_series || ss?$threshold_crossed) ) return F; # Add in the extra ResultVals to make threshold_vals easier to write. @@ -484,42 +492,25 @@ function check_thresholds(ss: SumStat, key: Key, result: Result, modify_pct: dou if ( modify_pct < 1.0 && modify_pct > 0.0 ) watch = watch/modify_pct; - if ( ss$name !in threshold_tracker ) - threshold_tracker[ss$name] = table(); - local t_tracker = threshold_tracker[ss$name]; + local t_index = get_threshold_index(ss$name, key); - if ( ss?$threshold ) + if ( ss?$threshold && + t_index == 0 && # Check that the threshold hasn't already been crossed. + watch >= ss$threshold ) { - local tt: Thresholding; - if ( key in t_tracker ) - tt = t_tracker[key]; - - if ( ! tt$is_threshold_crossed && - watch >= ss$threshold ) - { - t_tracker[key] = tt; - - # Value crossed the threshold. - return T; - } + # Value crossed the threshold. + return T; } - if ( ss?$threshold_series ) + if ( ss?$threshold_series && + |ss$threshold_series| > t_index && # Check if there are more thresholds. + watch >= ss$threshold_series[t_index] ) { - local tt2: Thresholding; - if ( key in t_tracker ) - tt2 = t_tracker[key]; - - if ( |ss$threshold_series| > tt2$threshold_series_index && - watch >= ss$threshold_series[tt2$threshold_series_index] ) - { - t_tracker[key] = tt2; - - # A threshold series was given and the value crossed the next - # value in the series. - return T; - } + # A threshold series was given and the value crossed the next + # value in the series. + return T; } + return F; } @@ -529,6 +520,8 @@ function threshold_crossed(ss: SumStat, key: Key, result: Result) if ( ! ss?$threshold_crossed ) return; + increment_threshold_tracker(ss$name,key); + # Add in the extra ResultVals to make threshold_crossed callbacks easier to write. if ( |ss$reducers| != |result| ) { @@ -540,11 +533,5 @@ function threshold_crossed(ss: SumStat, key: Key, result: Result) } ss$threshold_crossed(key, result); - local tt = threshold_tracker[ss$name][key]; - tt$is_threshold_crossed = T; - - # Bump up to the next threshold series index if a threshold series is being used. - if ( ss?$threshold_series ) - ++tt$threshold_series_index; } From 190f98f8a901728d507452b09717692c4c227821 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 3 Jun 2013 10:51:53 -0400 Subject: [PATCH 105/881] Beginning some rework. --- scripts/base/files/hash/__load__.bro | 1 + scripts/base/files/hash/main.bro | 22 ++++++++++ .../base/frameworks/file-analysis/main.bro | 40 +++++++++---------- scripts/base/init-default.bro | 2 + 4 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 scripts/base/files/hash/__load__.bro create mode 100644 scripts/base/files/hash/main.bro diff --git a/scripts/base/files/hash/__load__.bro b/scripts/base/files/hash/__load__.bro new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/files/hash/__load__.bro @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/files/hash/main.bro b/scripts/base/files/hash/main.bro new file mode 100644 index 0000000000..cd50d6b291 --- /dev/null +++ b/scripts/base/files/hash/main.bro @@ -0,0 +1,22 @@ + +module FilesHash; + +export { + +} + +event file_hash(f: fa_file, kind: string, hash: string) &priority=5 + { + set_info(f); + switch ( kind ) { + case "md5": + f$info$md5 = hash; + break; + case "sha1": + f$info$sha1 = hash; + break; + case "sha256": + f$info$sha256 = hash; + break; + } + } diff --git a/scripts/base/frameworks/file-analysis/main.bro b/scripts/base/frameworks/file-analysis/main.bro index 142709dcc4..418da53f70 100644 --- a/scripts/base/frameworks/file-analysis/main.bro +++ b/scripts/base/frameworks/file-analysis/main.bro @@ -34,6 +34,9 @@ export { ## For the most part, fields here are derived from ones of the same name ## in :bro:see:`fa_file`. type Info: record { + ## The time when the file was first seen. + ts: time &log; + ## An identifier associated with a single file. id: string &log; @@ -233,25 +236,35 @@ function set_info(f: fa_file) { if ( ! f?$info ) { - local tmp: Info; + local tmp: Info = Info($ts=network_time()); f$info = tmp; } + f$info$ts = network_time(); f$info$id = f$id; - if ( f?$parent_id ) f$info$parent_id = f$parent_id; - if ( f?$source ) f$info$source = f$source; - if ( f?$is_orig ) f$info$is_orig = f$is_orig; + if ( f?$parent_id ) + f$info$parent_id = f$parent_id; + if ( f?$source ) + f$info$source = f$source; + if ( f?$is_orig ) + f$info$is_orig = f$is_orig; f$info$last_active = f$last_active; f$info$seen_bytes = f$seen_bytes; - if ( f?$total_bytes ) f$info$total_bytes = f$total_bytes; + if ( f?$total_bytes ) + f$info$total_bytes = f$total_bytes; f$info$missing_bytes = f$missing_bytes; f$info$overflow_bytes = f$overflow_bytes; f$info$timeout_interval = f$timeout_interval; f$info$bof_buffer_size = f$bof_buffer_size; - if ( f?$mime_type ) f$info$mime_type = f$mime_type; + if ( f?$mime_type ) + f$info$mime_type = f$mime_type; if ( f?$conns ) + { for ( cid in f$conns ) + { add f$info$conn_uids[f$conns[cid]$uid]; + } + } } function set_timeout_interval(f: fa_file, t: interval): bool @@ -324,21 +337,6 @@ event file_timeout(f: fa_file) &priority=5 f$info$timedout = T; } -event file_hash(f: fa_file, kind: string, hash: string) &priority=5 - { - set_info(f); - switch ( kind ) { - case "md5": - f$info$md5 = hash; - break; - case "sha1": - f$info$sha1 = hash; - break; - case "sha256": - f$info$sha256 = hash; - break; - } - } event file_state_remove(f: fa_file) &priority=5 { diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 829a1b9982..03ba474e0b 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -46,4 +46,6 @@ @load base/protocols/ssl @load base/protocols/syslog +@load base/files/hash + @load base/misc/find-checksum-offloading From df2841458d43b71d67082cbb765411d06f8ad81a Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 5 Jul 2013 02:00:14 -0400 Subject: [PATCH 106/881] Large overhaul in name and appearance for file analysis. --- scripts/base/files/extract/__load__.bro | 1 + scripts/base/files/extract/main.bro | 38 +++ scripts/base/files/hash/main.bro | 16 +- .../{file-analysis => files}/__load__.bro | 0 .../{file-analysis => files}/main.bro | 231 +++++++++++------- scripts/base/init-bare.bro | 4 +- scripts/base/init-default.bro | 1 + scripts/base/protocols/ftp/__load__.bro | 1 - scripts/base/protocols/ftp/file-analysis.bro | 37 +-- scripts/base/protocols/ftp/file-extract.bro | 90 ------- scripts/base/protocols/http/__load__.bro | 6 +- scripts/base/protocols/http/file-analysis.bro | 69 +++--- scripts/base/protocols/http/file-extract.bro | 100 -------- scripts/base/protocols/http/file-hash.bro | 68 ------ scripts/base/protocols/http/file-ident.bro | 105 -------- scripts/base/protocols/http/main.bro | 18 +- scripts/base/protocols/irc/__load__.bro | 2 +- scripts/base/protocols/irc/dcc-send.bro | 108 +------- scripts/base/protocols/irc/file-analysis.bro | 18 +- scripts/base/protocols/smtp/__load__.bro | 2 +- scripts/base/protocols/smtp/entities.bro | 212 ++-------------- scripts/base/protocols/smtp/file-analysis.bro | 15 +- .../policy/frameworks/files/detect-MHR.bro | 63 +++++ .../frameworks/files/hash-all-files.bro | 7 + .../frameworks/intel/smtp-url-extraction.bro | 2 +- .../protocols/smtp/entities-excerpt.bro | 0 scripts/site/local.bro | 11 +- src/const.bif | 2 +- src/event.bif | 10 +- src/file_analysis.bif | 22 +- src/file_analysis/Analyzer.h | 4 +- src/file_analysis/AnalyzerSet.cc | 2 +- src/file_analysis/DataEvent.cc | 2 +- src/file_analysis/Extract.cc | 2 +- src/file_analysis/Manager.cc | 4 +- .../file-analysis/bifs/remove_action.bro | 4 +- .../bifs/set_timeout_interval.bro | 2 +- .../frameworks/file-analysis/bifs/stop.bro | 2 +- testing/scripts/file-analysis-test.bro | 14 +- 39 files changed, 420 insertions(+), 875 deletions(-) create mode 100644 scripts/base/files/extract/__load__.bro create mode 100644 scripts/base/files/extract/main.bro rename scripts/base/frameworks/{file-analysis => files}/__load__.bro (100%) rename scripts/base/frameworks/{file-analysis => files}/main.bro (52%) delete mode 100644 scripts/base/protocols/ftp/file-extract.bro delete mode 100644 scripts/base/protocols/http/file-extract.bro delete mode 100644 scripts/base/protocols/http/file-hash.bro delete mode 100644 scripts/base/protocols/http/file-ident.bro create mode 100644 scripts/policy/frameworks/files/detect-MHR.bro create mode 100644 scripts/policy/frameworks/files/hash-all-files.bro rename scripts/{base => policy}/protocols/smtp/entities-excerpt.bro (100%) diff --git a/scripts/base/files/extract/__load__.bro b/scripts/base/files/extract/__load__.bro new file mode 100644 index 0000000000..d551be57d3 --- /dev/null +++ b/scripts/base/files/extract/__load__.bro @@ -0,0 +1 @@ +@load ./main \ No newline at end of file diff --git a/scripts/base/files/extract/main.bro b/scripts/base/files/extract/main.bro new file mode 100644 index 0000000000..70e61c8529 --- /dev/null +++ b/scripts/base/files/extract/main.bro @@ -0,0 +1,38 @@ +@load base/frameworks/files +@load base/utils/paths + +module FileExtract; + +export { + ## The prefix where files are extracted to. + const prefix = "./extract_files/" &redef; + + redef record Files::Info += { + ## Local filenames of extracted file. + extracted: string &optional &log; + }; + + redef record Files::AnalyzerArgs += { + ## The local filename to which to write an extracted file. + ## This field is used in the core by the extraction plugin + ## to know where to write the file to. It's also optional + extract_filename: string &optional; + }; +} + +function on_add(f: fa_file, args: Files::AnalyzerArgs) + { + if ( ! args?$extract_filename ) + args$extract_filename = cat("extract-", f$source, "-", f$id); + + f$info$extracted = args$extract_filename; + args$extract_filename = build_path_compressed(prefix, args$extract_filename); + } + +event bro_init() &priority=10 + { + Files::register_analyzer_add_callback(Files::ANALYZER_EXTRACT, on_add); + + # Create the extraction directory. + mkdir(prefix); + } \ No newline at end of file diff --git a/scripts/base/files/hash/main.bro b/scripts/base/files/hash/main.bro index cd50d6b291..926e39865a 100644 --- a/scripts/base/files/hash/main.bro +++ b/scripts/base/files/hash/main.bro @@ -1,13 +1,23 @@ +@load base/frameworks/files -module FilesHash; +module FileHash; export { - + redef record Files::Info += { + ## An MD5 digest of the file contents. + md5: string &log &optional; + + ## A SHA1 digest of the file contents. + sha1: string &log &optional; + + ## A SHA256 digest of the file contents. + sha256: string &log &optional; + }; + } event file_hash(f: fa_file, kind: string, hash: string) &priority=5 { - set_info(f); switch ( kind ) { case "md5": f$info$md5 = hash; diff --git a/scripts/base/frameworks/file-analysis/__load__.bro b/scripts/base/frameworks/files/__load__.bro similarity index 100% rename from scripts/base/frameworks/file-analysis/__load__.bro rename to scripts/base/frameworks/files/__load__.bro diff --git a/scripts/base/frameworks/file-analysis/main.bro b/scripts/base/frameworks/files/main.bro similarity index 52% rename from scripts/base/frameworks/file-analysis/main.bro rename to scripts/base/frameworks/files/main.bro index 7b1bd7d81c..1c0481a87c 100644 --- a/scripts/base/frameworks/file-analysis/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -3,8 +3,9 @@ @load base/file_analysis.bif @load base/frameworks/logging +@load base/utils/site -module FileAnalysis; +module Files; export { redef enum Log::ID += { @@ -14,21 +15,14 @@ export { ## A structure which represents a desired type of file analysis. type AnalyzerArgs: record { - ## The type of analysis. - tag: Analyzer; - - ## The local filename to which to write an extracted file. Must be - ## set when *tag* is :bro:see:`FileAnalysis::ANALYZER_EXTRACT`. - extract_filename: string &optional; - ## An event which will be generated for all new file contents, ## chunk-wise. Used when *tag* is - ## :bro:see:`FileAnalysis::ANALYZER_DATA_EVENT`. + ## :bro:see:`Files::ANALYZER_DATA_EVENT`. chunk_event: event(f: fa_file, data: string, off: count) &optional; ## An event which will be generated for all new file contents, ## stream-wise. Used when *tag* is - ## :bro:see:`FileAnalysis::ANALYZER_DATA_EVENT`. + ## :bro:see:`Files::ANALYZER_DATA_EVENT`. stream_event: event(f: fa_file, data: string) &optional; } &redef; @@ -40,23 +34,52 @@ export { ts: time &log; ## An identifier associated with a single file. - id: string &log; + fuid: string &log; - ## Identifier associated with a container file from which this one was - ## extracted as part of the file analysis. - parent_id: string &log &optional; + ## If this file was transferred over a network + ## connection this should show the host or hosts that + ## the data sourced from. + tx_hosts: set[addr] &log; + + ## If this file was transferred over a network + ## connection this should show the host or hosts that + ## the data traveled to. + rx_hosts: set[addr] &log; + + ## Connection UIDS over which the file was transferred. + conn_uids: set[string] &log; ## An identification of the source of the file data. E.g. it may be ## a network protocol over which it was transferred, or a local file ## path which was read, or some other input source. source: string &log &optional; - ## If the source of this file is is a network connection, this field - ## may be set to indicate the directionality. - is_orig: bool &log &optional; + ## A value to represent the depth of this file in relation + ## to its source. In SMTP, it is the depth of the MIME + ## attachment on the message. In HTTP, it is the depth of the + ## request within the TCP connection. + depth: count &default=0 &log; - ## The time at which the last activity for the file was seen. - last_active: time &log; + ## A set of analysis types done during the file analysis. + analyzers: set[Analyzer] &log; + + ## A mime type provided by libmagic against the *bof_buffer*, or + ## in the cases where no buffering of the beginning of file occurs, + ## an initial guess of the mime type based on the first data seen. + mime_type: string &log &optional; + + ## A filename for the file if one is available from the source + ## for the file. These will frequently come from + ## "Content-Disposition" headers in network protocols. + filename: string &log &optional; + + ## The duration the file was analyzed for. + duration: interval &log &default=0secs; + + ## If the source of this file is is a network connection, this field + ## indicates if the data originated from the local network or not as + ## determined by the configured bro:see:`Site::local_nets`. + local_orig: bool &log &optional; ## Number of bytes provided to the file analysis engine for the file. seen_bytes: count &log &default=0; @@ -72,49 +95,18 @@ export { ## were delivered to file analyzers due to reassembly buffer overflow. overflow_bytes: count &log &default=0; - ## The amount of time between receiving new data for this file that - ## the analysis engine will wait before giving up on it. - timeout_interval: interval &log &optional; - - ## The number of bytes at the beginning of a file to save for later - ## inspection in *bof_buffer* field. - bof_buffer_size: count &log &optional; - - ## A mime type provided by libmagic against the *bof_buffer*, or - ## in the cases where no buffering of the beginning of file occurs, - ## an initial guess of the mime type based on the first data seen. - mime_type: string &log &optional; - ## Whether the file analysis timed out at least once for the file. timedout: bool &log &default=F; - ## Connection UIDS over which the file was transferred. - conn_uids: set[string] &log; - - ## A set of analysis types done during the file analysis. - analyzers: set[Analyzer]; - - ## Local filenames of extracted files. - extracted_files: set[string] &log; - - ## An MD5 digest of the file contents. - md5: string &log &optional; - - ## A SHA1 digest of the file contents. - sha1: string &log &optional; - - ## A SHA256 digest of the file contents. - sha256: string &log &optional; + ## Identifier associated with a container file from which this one was + ## extracted as part of the file analysis. + parent_fuid: string &log &optional; } &redef; ## A table that can be used to disable file analysis completely for ## any files transferred over given network protocol analyzers. const disable: table[AnalyzerTag] of bool = table() &redef; - ## Event that can be handled to access the Info record as it is sent on - ## to the logging framework. - global log_file_analysis: event(rec: Info); - ## The salt concatenated to unique file handle strings generated by ## :bro:see:`get_file_handle` before hashing them in to a file id ## (the *id* field of :bro:see:`fa_file`). @@ -146,7 +138,9 @@ export { ## Returns: true if the analyzer will be added, or false if analysis ## for the *id* isn't currently active or the *args* ## were invalid for the analyzer type. - global add_analyzer: function(f: fa_file, args: AnalyzerArgs): bool; + global add_analyzer: function(f: fa_file, + tag: Files::Analyzer, + args: AnalyzerArgs &default=AnalyzerArgs()): bool; ## Removes an analyzer from the analysis of a given file. ## @@ -156,7 +150,7 @@ export { ## ## Returns: true if the analyzer will be removed, or false if analysis ## for the *id* isn't currently active. - global remove_analyzer: function(f: fa_file, args: AnalyzerArgs): bool; + global remove_analyzer: function(f: fa_file, tag: Files::Analyzer, args: AnalyzerArgs): bool; ## Stops/ignores any further analysis of a given file. ## @@ -166,45 +160,75 @@ export { ## rest of it's contents, or false if analysis for the *id* ## isn't currently active. global stop: function(f: fa_file): bool; + + ## Register callbacks for protocols that work with the Files framework. + ## The callbacks must uniquely identify a file and each protocol can + ## only have a single callback registered for it. + ## + ## tag: Tag for the protocol analyzer having a callback being registered. + ## + ## callback: Function that can generate a file handle for the protocol analyzer + ## defined previously. + ## + ## Returns: true if the protocol being registered was not previously registered. + global register_protocol: function(tag: AnalyzerTag, callback: function(c: connection, is_orig: bool): string): bool; + + ## Register a callback for file analyzers to use if they need to do some manipulation + ## when they are being added to a file before the core code takes over. This is + ## unlikely to be interesting for users and should only be called by file analyzer + ## authors but it *not required*. + ## + ## tag: Tag for the file analyzer. + ## + ## callback: Function to execute when the given file analyzer is being added. + global register_analyzer_add_callback: function(tag: Files::Analyzer, callback: function(f: fa_file, args: AnalyzerArgs)); + + ## Event that can be handled to access the Info record as it is sent on + ## to the logging framework. + global log_files: event(rec: Info); } redef record fa_file += { info: Info &optional; }; +redef record AnalyzerArgs += { + # This is used interally for the core file analyzer api. + tag: Files::Analyzer &optional; +}; + +# Store the callbacks for protocol analyzers that have files. +global registered_protocols: table[AnalyzerTag] of function(c: connection, is_orig: bool): string = table() + &default=function(c: connection, is_orig: bool): string { return cat(c$uid, is_orig); }; + +global analyzer_add_callbacks: table[Files::Analyzer] of function(f: fa_file, args: AnalyzerArgs) = table(); + +event bro_init() &priority=5 + { + Log::create_stream(Files::LOG, [$columns=Info, $ev=log_files]); + } + function set_info(f: fa_file) { if ( ! f?$info ) { - local tmp: Info = Info($ts=network_time()); + local tmp: Info = Info($ts=f$last_active, + $fuid=f$id); f$info = tmp; } - f$info$ts = network_time(); - f$info$id = f$id; if ( f?$parent_id ) - f$info$parent_id = f$parent_id; + f$info$parent_fuid = f$parent_id; if ( f?$source ) f$info$source = f$source; - if ( f?$is_orig ) - f$info$is_orig = f$is_orig; - f$info$last_active = f$last_active; + f$info$duration = f$last_active - f$info$ts; f$info$seen_bytes = f$seen_bytes; if ( f?$total_bytes ) f$info$total_bytes = f$total_bytes; f$info$missing_bytes = f$missing_bytes; f$info$overflow_bytes = f$overflow_bytes; - f$info$timeout_interval = f$timeout_interval; - f$info$bof_buffer_size = f$bof_buffer_size; if ( f?$mime_type ) f$info$mime_type = f$mime_type; - if ( f?$conns ) - { - for ( cid in f$conns ) - { - add f$info$conn_uids[f$conns[cid]$uid]; - } - } } function set_timeout_interval(f: fa_file, t: interval): bool @@ -212,21 +236,31 @@ function set_timeout_interval(f: fa_file, t: interval): bool return __set_timeout_interval(f$id, t); } -function add_analyzer(f: fa_file, args: AnalyzerArgs): bool +function add_analyzer(f: fa_file, tag: Analyzer, args: AnalyzerArgs): bool { - if ( ! __add_analyzer(f$id, args) ) return F; + # This is to construct the correct args for the core API. + args$tag = tag; + add f$info$analyzers[tag]; - set_info(f); - add f$info$analyzers[args$tag]; - - if ( args$tag == FileAnalysis::ANALYZER_EXTRACT ) - add f$info$extracted_files[args$extract_filename]; + if ( tag in analyzer_add_callbacks ) + analyzer_add_callbacks[tag](f, args); + if ( ! __add_analyzer(f$id, args) ) + { + Reporter::warning(fmt("Analyzer %s not added successfully to file %s.", tag, f$id)); + return F; + } return T; } -function remove_analyzer(f: fa_file, args: AnalyzerArgs): bool +function register_analyzer_add_callback(tag: Files::Analyzer, callback: function(f: fa_file, args: AnalyzerArgs)) { + analyzer_add_callbacks[tag] = callback; + } + +function remove_analyzer(f: fa_file, tag: Files::Analyzer, args: AnalyzerArgs): bool + { + args$tag = tag; return __remove_analyzer(f$id, args); } @@ -235,25 +269,48 @@ function stop(f: fa_file): bool return __stop(f$id); } -event bro_init() &priority=5 +event file_new(f: fa_file) &priority=10 { - Log::create_stream(FileAnalysis::LOG, - [$columns=Info, $ev=log_file_analysis]); + set_info(f); } -event file_timeout(f: fa_file) &priority=5 +event file_over_new_connection(f: fa_file, c: connection) &priority=10 + { + set_info(f); + add f$info$conn_uids[c$uid]; + local cid = c$id; + add f$info$tx_hosts[f$is_orig ? cid$orig_h : cid$resp_h]; + if( |Site::local_nets| > 0 ) + f$info$local_orig=Site::is_local_addr(f$is_orig ? cid$orig_h : cid$resp_h); + + add f$info$rx_hosts[f$is_orig ? cid$resp_h : cid$orig_h]; + } + +event file_timeout(f: fa_file) &priority=10 { set_info(f); f$info$timedout = T; } - -event file_state_remove(f: fa_file) &priority=5 +event file_state_remove(f: fa_file) &priority=10 { set_info(f); } -event file_state_remove(f: fa_file) &priority=-5 +event file_state_remove(f: fa_file) &priority=-10 { - Log::write(FileAnalysis::LOG, f$info); + Log::write(Files::LOG, f$info); + } + +function register_protocol(tag: AnalyzerTag, callback: function(c: connection, is_orig: bool): string): bool + { + local result = (tag !in registered_protocols); + registered_protocols[tag] = callback; + return result; + } + +event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) &priority=5 + { + local handler = registered_protocols[tag]; + set_file_handle(handler(c, is_orig)); } diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index c4245d9052..4e1a5248c8 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -339,7 +339,7 @@ type fa_file: record { ## An identification of the source of the file data. E.g. it may be ## a network protocol over which it was transferred, or a local file ## path which was read, or some other input source. - source: string &optional; + source: string; ## If the source of this file is is a network connection, this field ## may be set to indicate the directionality. @@ -3101,4 +3101,4 @@ const snaplen = 8192 &redef; @load base/frameworks/input -@load base/frameworks/file-analysis +@load base/frameworks/files diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 03ba474e0b..719842af09 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -47,5 +47,6 @@ @load base/protocols/syslog @load base/files/hash +@load base/files/extract @load base/misc/find-checksum-offloading diff --git a/scripts/base/protocols/ftp/__load__.bro b/scripts/base/protocols/ftp/__load__.bro index 464571dc7d..9c839610ac 100644 --- a/scripts/base/protocols/ftp/__load__.bro +++ b/scripts/base/protocols/ftp/__load__.bro @@ -1,5 +1,4 @@ @load ./utils-commands @load ./main @load ./file-analysis -@load ./file-extract @load ./gridftp diff --git a/scripts/base/protocols/ftp/file-analysis.bro b/scripts/base/protocols/ftp/file-analysis.bro index f8fa2d816b..3710a44cee 100644 --- a/scripts/base/protocols/ftp/file-analysis.bro +++ b/scripts/base/protocols/ftp/file-analysis.bro @@ -1,6 +1,6 @@ @load ./main @load base/utils/conn-ids -@load base/frameworks/file-analysis/main +@load base/frameworks/files module FTP; @@ -9,40 +9,15 @@ export { global get_file_handle: function(c: connection, is_orig: bool): string; } -function get_handle_string(c: connection): string - { - return cat(ANALYZER_FTP_DATA, " ", c$start_time, " ", id_string(c$id)); - } - function get_file_handle(c: connection, is_orig: bool): string { - if ( [c$id$resp_h, c$id$resp_p] !in ftp_data_expected ) return ""; + if ( [c$id$resp_h, c$id$resp_p] !in ftp_data_expected ) + return ""; - local info: FTP::Info = ftp_data_expected[c$id$resp_h, c$id$resp_p]; - - if ( info$passive ) - # FTP client initiates data channel. - if ( is_orig ) - # Don't care about FTP client data. - return ""; - else - # Do care about FTP server data. - return get_handle_string(c); - else - # FTP server initiates dta channel. - if ( is_orig ) - # Do care about FTP server data. - return get_handle_string(c); - else - # Don't care about FTP client data. - return ""; + return cat(ANALYZER_FTP_DATA, c$start_time, c$id, is_orig); } -module GLOBAL; - -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) - &priority=5 +event bro_init() &priority=5 { - if ( tag != ANALYZER_FTP_DATA ) return; - set_file_handle(FTP::get_file_handle(c, is_orig)); + Files::register_protocol(ANALYZER_FTP_DATA, FTP::get_file_handle); } diff --git a/scripts/base/protocols/ftp/file-extract.bro b/scripts/base/protocols/ftp/file-extract.bro deleted file mode 100644 index 2b7bb8cd50..0000000000 --- a/scripts/base/protocols/ftp/file-extract.bro +++ /dev/null @@ -1,90 +0,0 @@ -##! File extraction support for FTP. - -@load ./main -@load base/utils/files - -module FTP; - -export { - ## Pattern of file mime types to extract from FTP transfers. - const extract_file_types = /NO_DEFAULT/ &redef; - - ## The on-disk prefix for files to be extracted from FTP-data transfers. - const extraction_prefix = "ftp-item" &redef; -} - -redef record Info += { - ## On disk file where it was extracted to. - extraction_file: string &log &optional; - - ## Indicates if the current command/response pair should attempt to - ## extract the file if a file was transferred. - extract_file: bool &default=F; -}; - -function get_extraction_name(f: fa_file): string - { - local r = fmt("%s-%s.dat", extraction_prefix, f$id); - return r; - } - -event file_new(f: fa_file) &priority=5 - { - if ( ! f?$source ) return; - if ( f$source != "FTP_DATA" ) return; - - if ( f?$mime_type && extract_file_types in f$mime_type ) - { - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename=get_extraction_name(f)]); - return; - } - - if ( ! f?$conns ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( [cid$resp_h, cid$resp_p] !in ftp_data_expected ) next; - - local s = ftp_data_expected[cid$resp_h, cid$resp_p]; - - if ( ! s$extract_file ) next; - - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename=get_extraction_name(f)]); - return; - } - } - -event file_state_remove(f: fa_file) &priority=4 - { - if ( ! f?$source ) return; - if ( f$source != "FTP_DATA" ) return; - if ( ! f?$info ) return; - - for ( filename in f$info$extracted_files ) - { - local s: FTP::Info; - s$ts = network_time(); - s$tags = set(); - s$user = ""; - s$extraction_file = filename; - - if ( f?$conns ) - for ( cid in f$conns ) - { - s$uid = f$conns[cid]$uid; - s$id = cid; - } - - Log::write(FTP::LOG, s); - } - } - -event log_ftp(rec: Info) &priority=-10 - { - delete rec$extraction_file; - delete rec$extract_file; - } diff --git a/scripts/base/protocols/http/__load__.bro b/scripts/base/protocols/http/__load__.bro index 58618dedc7..585b815eed 100644 --- a/scripts/base/protocols/http/__load__.bro +++ b/scripts/base/protocols/http/__load__.bro @@ -1,6 +1,6 @@ @load ./main @load ./utils @load ./file-analysis -@load ./file-ident -@load ./file-hash -@load ./file-extract +#@load ./file-ident +#@load ./file-hash +#@load ./file-extract diff --git a/scripts/base/protocols/http/file-analysis.bro b/scripts/base/protocols/http/file-analysis.bro index 769bb509f5..b79ca041b8 100644 --- a/scripts/base/protocols/http/file-analysis.bro +++ b/scripts/base/protocols/http/file-analysis.bro @@ -1,53 +1,58 @@ @load ./main @load ./utils @load base/utils/conn-ids -@load base/frameworks/file-analysis/main +@load base/frameworks/files module HTTP; export { - redef record HTTP::Info += { - ## Number of MIME entities in the HTTP request message body so far. - request_mime_level: count &default=0; - ## Number of MIME entities in the HTTP response message body so far. - response_mime_level: count &default=0; + redef record Info += { + ## The sniffed mime type of the data being sent by the client. + client_mime_type: string &log &optional; + + ## The sniffed mime type of the data being returned by the server. + mime_type: string &log &optional; }; ## Default file handle provider for HTTP. global get_file_handle: function(c: connection, is_orig: bool): string; } -event http_begin_entity(c: connection, is_orig: bool) &priority=5 - { - if ( ! c?$http ) return; - - if ( is_orig ) - ++c$http$request_mime_level; - else - ++c$http$response_mime_level; - } - function get_file_handle(c: connection, is_orig: bool): string { - if ( ! c?$http ) return ""; - - local mime_level: count = - is_orig ? c$http$request_mime_level : c$http$response_mime_level; - local mime_level_str: string = mime_level > 1 ? cat(mime_level) : ""; + if ( ! c?$http ) + return ""; + local mime_depth = is_orig ? c$http$orig_mime_depth : c$http$resp_mime_depth; if ( c$http$range_request ) - return cat(ANALYZER_HTTP, " ", is_orig, " ", c$id$orig_h, " ", - build_url(c$http)); - - return cat(ANALYZER_HTTP, " ", c$start_time, " ", is_orig, " ", - c$http$trans_depth, mime_level_str, " ", id_string(c$id)); + { + return cat(ANALYZER_HTTP, is_orig, c$id$orig_h, mime_depth, build_url(c$http)); + } + else + { + return cat(ANALYZER_HTTP, c$start_time, is_orig, + c$http$trans_depth, mime_depth, id_string(c$id)); + } } -module GLOBAL; - -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) - &priority=5 +event bro_init() &priority=5 { - if ( tag != ANALYZER_HTTP ) return; - set_file_handle(HTTP::get_file_handle(c, is_orig)); + Files::register_protocol(ANALYZER_HTTP, HTTP::get_file_handle); } + +event file_over_new_connection(f: fa_file, c: connection) &priority=5 + { + if ( c?$http ) + { + #if (!f?$mime_type) + # print f; +# + #if ( f$is_orig ) + # c$http$client_mime_type = f$mime_type; + #else + # c$http$mime_type = f$mime_type; + + if ( c$http?$filename ) + f$info$filename = c$http$filename; + } + } \ No newline at end of file diff --git a/scripts/base/protocols/http/file-extract.bro b/scripts/base/protocols/http/file-extract.bro deleted file mode 100644 index a8c6039395..0000000000 --- a/scripts/base/protocols/http/file-extract.bro +++ /dev/null @@ -1,100 +0,0 @@ -##! Extracts the items from HTTP traffic, one per file. At this time only -##! the message body from the server can be extracted with this script. - -@load ./main -@load ./file-analysis - -module HTTP; - -export { - ## Pattern of file mime types to extract from HTTP response entity bodies. - const extract_file_types = /NO_DEFAULT/ &redef; - - ## The on-disk prefix for files to be extracted from HTTP entity bodies. - const extraction_prefix = "http-item" &redef; - - redef record Info += { - ## On-disk location where files in request body were extracted. - extracted_request_files: vector of string &log &optional; - - ## On-disk location where files in response body were extracted. - extracted_response_files: vector of string &log &optional; - - ## Indicates if the response body is to be extracted or not. Must be - ## set before or by the first :bro:see:`file_new` for the file content. - extract_file: bool &default=F; - }; -} - -function get_extraction_name(f: fa_file): string - { - local r = fmt("%s-%s.dat", extraction_prefix, f$id); - return r; - } - -function add_extraction_file(c: connection, is_orig: bool, fn: string) - { - if ( is_orig ) - { - if ( ! c$http?$extracted_request_files ) - c$http$extracted_request_files = vector(); - c$http$extracted_request_files[|c$http$extracted_request_files|] = fn; - } - else - { - if ( ! c$http?$extracted_response_files ) - c$http$extracted_response_files = vector(); - c$http$extracted_response_files[|c$http$extracted_response_files|] = fn; - } - } - -event file_new(f: fa_file) &priority=5 - { - if ( ! f?$source ) return; - if ( f$source != "HTTP" ) return; - if ( ! f?$conns ) return; - - local fname: string; - local c: connection; - - if ( f?$mime_type && extract_file_types in f$mime_type ) - { - fname = get_extraction_name(f); - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename=fname]); - - for ( cid in f$conns ) - { - c = f$conns[cid]; - if ( ! c?$http ) next; - add_extraction_file(c, f$is_orig, fname); - } - - return; - } - - local extracting: bool = F; - - for ( cid in f$conns ) - { - c = f$conns[cid]; - - if ( ! c?$http ) next; - - if ( ! c$http$extract_file ) next; - - fname = get_extraction_name(f); - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename=fname]); - extracting = T; - break; - } - - if ( extracting ) - for ( cid in f$conns ) - { - c = f$conns[cid]; - if ( ! c?$http ) next; - add_extraction_file(c, f$is_orig, fname); - } - } diff --git a/scripts/base/protocols/http/file-hash.bro b/scripts/base/protocols/http/file-hash.bro deleted file mode 100644 index 34d91e45bb..0000000000 --- a/scripts/base/protocols/http/file-hash.bro +++ /dev/null @@ -1,68 +0,0 @@ -##! Calculate hashes for HTTP body transfers. - -@load ./main -@load ./file-analysis - -module HTTP; - -export { - redef record Info += { - ## MD5 sum for a file transferred over HTTP calculated from the - ## response body. - md5: string &log &optional; - - ## This value can be set per-transfer to determine per request - ## if a file should have an MD5 sum generated. It must be - ## set to T at the time of or before the first chunk of body data. - calc_md5: bool &default=F; - }; - - ## Generate MD5 sums for these filetypes. - const generate_md5 = /application\/x-dosexec/ # Windows and DOS executables - | /application\/x-executable/ # *NIX executable binary - &redef; -} - -event file_new(f: fa_file) &priority=5 - { - if ( ! f?$source ) return; - if ( f$source != "HTTP" ) return; - - if ( f?$mime_type && generate_md5 in f$mime_type ) - { - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_MD5]); - return; - } - - if ( ! f?$conns ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( ! c?$http ) next; - - if ( ! c$http$calc_md5 ) next; - - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_MD5]); - return; - } - } - -event file_state_remove(f: fa_file) &priority=4 - { - if ( ! f?$source ) return; - if ( f$source != "HTTP" ) return; - if ( ! f?$conns ) return; - if ( ! f?$info ) return; - if ( ! f$info?$md5 ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( ! c?$http ) next; - - c$http$md5 = f$info$md5; - } - } diff --git a/scripts/base/protocols/http/file-ident.bro b/scripts/base/protocols/http/file-ident.bro deleted file mode 100644 index 7ed4b58a37..0000000000 --- a/scripts/base/protocols/http/file-ident.bro +++ /dev/null @@ -1,105 +0,0 @@ -##! Identification of file types in HTTP response bodies with file content sniffing. - -@load base/frameworks/notice -@load ./main -@load ./utils -@load ./file-analysis - -module HTTP; - -export { - redef enum Notice::Type += { - ## Indicates when the file extension doesn't seem to match the file - ## contents. - Incorrect_File_Type, - }; - - redef record Info += { - ## Mime type of response body identified by content sniffing. - mime_type: string &log &optional; - }; - - ## Mapping between mime type strings (without character set) and - ## regular expressions for URLs. - ## The :bro:enum:`HTTP::Incorrect_File_Type` notice is generated if the - ## pattern doesn't match the mime type that was discovered. - const mime_types_extensions: table[string] of pattern = { - ["application/x-dosexec"] = /\.([eE][xX][eE]|[dD][lL][lL])/, - } &redef; - - ## A pattern for filtering out :bro:enum:`HTTP::Incorrect_File_Type` urls - ## that are not noteworthy before a notice is created. Each - ## pattern added should match the complete URL (the matched URLs include - ## "http://" at the beginning). - const ignored_incorrect_file_type_urls = /^$/ &redef; -} - -event file_new(f: fa_file) &priority=5 - { - if ( ! f?$source ) return; - if ( f$source != "HTTP" ) return; - if ( ! f?$mime_type ) return; - if ( ! f?$conns ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( ! c?$http ) next; - - c$http$mime_type = f$mime_type; - - local mime_str: string = c$http$mime_type; - - if ( mime_str !in mime_types_extensions ) next; - if ( ! c$http?$uri ) next; - if ( mime_types_extensions[mime_str] in c$http$uri ) next; - - local url = build_url_http(c$http); - - if ( url == ignored_incorrect_file_type_urls ) next; - - local message = fmt("%s %s %s", mime_str, c$http$method, url); - NOTICE([$note=Incorrect_File_Type, - $msg=message, - $conn=c]); - } - } - -event file_over_new_connection(f: fa_file, c: connection) &priority=5 - { - if ( ! f?$source ) return; - if ( f$source != "HTTP" ) return; - if ( ! f?$mime_type ) return; - if ( ! c?$http ) return; - - # Spread the mime around (e.g. for partial content, file_type event only - # happens once for the first connection, but if there's subsequent - # connections to transfer the same file, they'll be lacking the mime_type - # field if we don't do this). - c$http$mime_type = f$mime_type; - } - -# Tracks byte-range request / partial content response mime types, indexed -# by [connection, uri] pairs. This is needed because a person can pipeline -# byte-range requests over multiple connections to the same uri. Without -# the tracking, only the first request in the pipeline for each connection -# would get a mime_type field assigned to it (by the FileAnalysis policy hooks). -global partial_types: table[conn_id, string] of string &read_expire=5mins; - -# Priority 4 so that it runs before the handler that will write to http.log. -event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) - &priority=4 - { - if ( ! c$http$range_request ) return; - if ( ! c$http?$uri ) return; - - if ( c$http?$mime_type ) - { - partial_types[c$id, c$http$uri] = c$http$mime_type; - return; - } - - if ( [c$id, c$http$uri] in partial_types ) - c$http$mime_type = partial_types[c$id, c$http$uri]; - } diff --git a/scripts/base/protocols/http/main.bro b/scripts/base/protocols/http/main.bro index a1771c8e77..ebf412d36e 100644 --- a/scripts/base/protocols/http/main.bro +++ b/scripts/base/protocols/http/main.bro @@ -71,10 +71,14 @@ export { ## All of the headers that may indicate if the request was proxied. proxied: set[string] &log &optional; - + ## Indicates if this request can assume 206 partial content in ## response. - range_request: bool &default=F; + range_request: bool &default=F; + ## Number of MIME entities in the HTTP request message body so far. + orig_mime_depth: count &default=0; + ## Number of MIME entities in the HTTP response message body so far. + resp_mime_depth: count &default=0; }; ## Structure to maintain state for an HTTP connection with multiple @@ -283,6 +287,16 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr } } +event http_begin_entity(c: connection, is_orig: bool) &priority=5 + { + set_state(c, F, is_orig); + + if ( is_orig ) + ++c$http$orig_mime_depth; + else + ++c$http$resp_mime_depth; + } + event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) &priority = 5 { set_state(c, F, is_orig); diff --git a/scripts/base/protocols/irc/__load__.bro b/scripts/base/protocols/irc/__load__.bro index 5123385b0c..d20550c54f 100644 --- a/scripts/base/protocols/irc/__load__.bro +++ b/scripts/base/protocols/irc/__load__.bro @@ -1,3 +1,3 @@ @load ./main -@load ./dcc-send +#@load ./dcc-send @load ./file-analysis diff --git a/scripts/base/protocols/irc/dcc-send.bro b/scripts/base/protocols/irc/dcc-send.bro index 53381d0302..afe01485a2 100644 --- a/scripts/base/protocols/irc/dcc-send.bro +++ b/scripts/base/protocols/irc/dcc-send.bro @@ -15,12 +15,6 @@ module IRC; export { - ## Pattern of file mime types to extract from IRC DCC file transfers. - const extract_file_types = /NO_DEFAULT/ &redef; - - ## On-disk prefix for files to be extracted from IRC DCC file transfers. - const extraction_prefix = "irc-dcc-item" &redef; - redef record Info += { ## DCC filename requested. dcc_file_name: string &log &optional; @@ -28,101 +22,10 @@ export { dcc_file_size: count &log &optional; ## Sniffed mime type of the file. dcc_mime_type: string &log &optional; - - ## The file handle for the file to be extracted - extraction_file: string &log &optional; - - ## A boolean to indicate if the current file transfer should be extracted. - extract_file: bool &default=F; }; } -global dcc_expected_transfers: table[addr, port] of Info &read_expire=5mins; - -function set_dcc_mime(f: fa_file) - { - if ( ! f?$conns ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( [cid$resp_h, cid$resp_p] !in dcc_expected_transfers ) next; - - local s = dcc_expected_transfers[cid$resp_h, cid$resp_p]; - - s$dcc_mime_type = f$mime_type; - } - } - -function set_dcc_extraction_file(f: fa_file, filename: string) - { - if ( ! f?$conns ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( [cid$resp_h, cid$resp_p] !in dcc_expected_transfers ) next; - - local s = dcc_expected_transfers[cid$resp_h, cid$resp_p]; - - s$extraction_file = filename; - } - } - -function get_extraction_name(f: fa_file): string - { - local r = fmt("%s-%s.dat", extraction_prefix, f$id); - return r; - } - -# this handler sets the IRC::Info mime type -event file_new(f: fa_file) &priority=5 - { - if ( ! f?$source ) return; - if ( f$source != "IRC_DATA" ) return; - if ( ! f?$mime_type ) return; - - set_dcc_mime(f); - } - -# this handler check if file extraction is desired -event file_new(f: fa_file) &priority=5 - { - if ( ! f?$source ) return; - if ( f$source != "IRC_DATA" ) return; - - local fname: string; - - if ( f?$mime_type && extract_file_types in f$mime_type ) - { - fname = get_extraction_name(f); - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename=fname]); - set_dcc_extraction_file(f, fname); - return; - } - - if ( ! f?$conns ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( [cid$resp_h, cid$resp_p] !in dcc_expected_transfers ) next; - - local s = dcc_expected_transfers[cid$resp_h, cid$resp_p]; - - if ( ! s$extract_file ) next; - - fname = get_extraction_name(f); - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename=fname]); - s$extraction_file = fname; - return; - } - } +global dcc_expected_transfers: table[addr, port] of Info &synchronized &read_expire=5mins; function log_dcc(f: fa_file) { @@ -143,22 +46,17 @@ function log_dcc(f: fa_file) # Delete these values in case another DCC transfer # happens during the IRC session. - delete irc$extract_file; - delete irc$extraction_file; delete irc$dcc_file_name; delete irc$dcc_file_size; delete irc$dcc_mime_type; - return; } } event file_new(f: fa_file) &priority=-5 { - if ( ! f?$source ) return; - if ( f$source != "IRC_DATA" ) return; - - log_dcc(f); + if ( f?$source && f$source == "IRC_DATA" ) + log_dcc(f); } event irc_dcc_message(c: connection, is_orig: bool, diff --git a/scripts/base/protocols/irc/file-analysis.bro b/scripts/base/protocols/irc/file-analysis.bro index 5159064b27..f2e84fbc22 100644 --- a/scripts/base/protocols/irc/file-analysis.bro +++ b/scripts/base/protocols/irc/file-analysis.bro @@ -1,6 +1,6 @@ -@load ./dcc-send.bro +@load ./dcc-send @load base/utils/conn-ids -@load base/frameworks/file-analysis/main +@load base/frameworks/files module IRC; @@ -11,15 +11,13 @@ export { function get_file_handle(c: connection, is_orig: bool): string { - if ( is_orig ) return ""; - return cat(ANALYZER_IRC_DATA, " ", c$start_time, " ", id_string(c$id)); + if ( [c$id$resp_h, c$id$resp_p] !in dcc_expected_transfers ) + return ""; + + return cat(ANALYZER_IRC_DATA, c$start_time, c$id, is_orig); } -module GLOBAL; - -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) - &priority=5 +event bro_init() &priority=5 { - if ( tag != ANALYZER_IRC_DATA ) return; - set_file_handle(IRC::get_file_handle(c, is_orig)); + Files::register_protocol(ANALYZER_IRC_DATA, IRC::get_file_handle); } diff --git a/scripts/base/protocols/smtp/__load__.bro b/scripts/base/protocols/smtp/__load__.bro index bac9cc118f..1e913d8dff 100644 --- a/scripts/base/protocols/smtp/__load__.bro +++ b/scripts/base/protocols/smtp/__load__.bro @@ -1,4 +1,4 @@ @load ./main @load ./entities -@load ./entities-excerpt +#@load ./entities-excerpt @load ./file-analysis diff --git a/scripts/base/protocols/smtp/entities.bro b/scripts/base/protocols/smtp/entities.bro index b58766e51d..dcb53dc0aa 100644 --- a/scripts/base/protocols/smtp/entities.bro +++ b/scripts/base/protocols/smtp/entities.bro @@ -1,5 +1,6 @@ ##! Analysis and logging for MIME entities found in SMTP sessions. +@load base/frameworks/files @load base/utils/strings @load base/utils/files @load ./main @@ -7,217 +8,56 @@ module SMTP; export { - redef enum Log::ID += { ENTITIES_LOG }; - - type EntityInfo: record { - ## This is the timestamp of when the MIME content transfer began. - ts: time &log; - uid: string &log; - id: conn_id &log; - ## A count to represent the depth of this message transaction in a - ## single connection where multiple messages were transferred. - trans_depth: count &log; - ## The filename seen in the Content-Disposition header. - filename: string &log &optional; - ## Track how many bytes of the MIME encoded file have been seen. - content_len: count &log &default=0; - ## The mime type of the entity discovered through magic bytes identification. - mime_type: string &log &optional; - - ## The calculated MD5 sum for the MIME entity. - md5: string &log &optional; - ## Optionally calculate the file's MD5 sum. Must be set prior to the - ## first data chunk being see in an event. - calc_md5: bool &default=F; - - ## Optionally write the file to disk. Must be set prior to first - ## data chunk being seen in an event. - extract_file: bool &default=F; - ## Store the file handle here for the file currently being extracted. - extraction_file: string &log &optional; + type Entity: record { + filename: string &optional; }; redef record Info += { - ## The in-progress entity information. - current_entity: EntityInfo &optional; + ## The current entity being seen. + entity: Entity &optional; }; redef record State += { - ## Track the number of MIME encoded files transferred during a session. - mime_level: count &default=0; + ## Track the number of MIME encoded files transferred + ## during a session. + mime_depth: count &default=0; }; - - ## Generate MD5 sums for these filetypes. - const generate_md5 = /application\/x-dosexec/ # Windows and DOS executables - | /application\/x-executable/ # *NIX executable binary - &redef; - - ## Pattern of file mime types to extract from MIME bodies. - const extract_file_types = /NO_DEFAULT/ &redef; - - ## The on-disk prefix for files to be extracted from MIME entity bodies. - const extraction_prefix = "smtp-entity" &redef; - - ## If set, never generate MD5s. This is mainly for testing purposes to create - ## reproducable output in the case that the decision whether to create - ## checksums depends on environment specifics. - const never_calc_md5 = F &redef; - - global log_mime: event(rec: EntityInfo); } -event bro_init() &priority=5 - { - Log::create_stream(SMTP::ENTITIES_LOG, [$columns=EntityInfo, $ev=log_mime]); - } - -function set_session(c: connection, new_entity: bool) - { - if ( ! c$smtp?$current_entity || new_entity ) - { - local info: EntityInfo; - info$ts=network_time(); - info$uid=c$uid; - info$id=c$id; - info$trans_depth=c$smtp$trans_depth; - - c$smtp$current_entity = info; - ++c$smtp_state$mime_level; - } - } - -function get_extraction_name(f: fa_file): string - { - local r = fmt("%s-%s.dat", extraction_prefix, f$id); - return r; - } - event mime_begin_entity(c: connection) &priority=10 { - if ( ! c?$smtp ) return; + #print fmt("%s : begin entity", c$uid); - set_session(c, T); + c$smtp$entity = Entity(); + ++c$smtp_state$mime_depth; } -event file_new(f: fa_file) &priority=5 +event file_over_new_connection(f: fa_file, c: connection) &priority=5 { - if ( ! f?$source ) return; - if ( f$source != "SMTP" ) return; - if ( ! f?$conns ) return; - - local fname: string; - local extracting: bool = F; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( ! c?$smtp ) next; - if ( ! c$smtp?$current_entity ) next; - - if ( c$smtp$current_entity$extract_file ) - { - if ( ! extracting ) - { - fname = get_extraction_name(f); - FileAnalysis::add_analyzer(f, - [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename=fname]); - extracting = T; - } - - c$smtp$current_entity$extraction_file = fname; - } - - if ( c$smtp$current_entity$calc_md5 ) - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_MD5]); - } - } - -function check_extract_by_type(f: fa_file) - { - if ( extract_file_types !in f$mime_type ) return; - - if ( f?$info && FileAnalysis::ANALYZER_EXTRACT in f$info$analyzers ) + if ( f$source != "SMTP" ) return; - local fname: string = get_extraction_name(f); - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename=fname]); - - if ( ! f?$conns ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - if ( ! c?$smtp ) next; - c$smtp$current_entity$extraction_file = fname; - } + if ( c$smtp$entity?$filename ) + f$info$filename = c$smtp$entity$filename; + f$info$depth = c$smtp_state$mime_depth; } -function check_md5_by_type(f: fa_file) +event mime_one_header(c: connection, h: mime_header_rec) &priority=5 { - if ( never_calc_md5 ) return; - if ( generate_md5 !in f$mime_type ) return; - - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_MD5]); - } - -event file_new(f: fa_file) &priority=5 - { - if ( ! f?$source ) return; - if ( f$source != "SMTP" ) return; - if ( ! f?$mime_type ) return; - - if ( f?$conns ) - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( ! c?$smtp ) next; - if ( ! c$smtp?$current_entity ) next; - - c$smtp$current_entity$mime_type = f$mime_type; - } - - check_extract_by_type(f); - check_md5_by_type(f); - } - -event file_state_remove(f: fa_file) &priority=4 - { - if ( ! f?$source ) return; - if ( f$source != "SMTP" ) return; - if ( ! f?$conns ) return; - - for ( cid in f$conns ) - { - local c: connection = f$conns[cid]; - - if ( ! c?$smtp ) next; - if ( ! c$smtp?$current_entity ) next; - # Only log if there was some content. - if ( f$seen_bytes == 0 ) next; - - if ( f?$info && f$info?$md5 ) - c$smtp$current_entity$md5 = f$info$md5; - - c$smtp$current_entity$content_len = f$seen_bytes; - Log::write(SMTP::ENTITIES_LOG, c$smtp$current_entity); - delete c$smtp$current_entity; + if ( ! c?$smtp ) return; - } - } -event mime_one_header(c: connection, h: mime_header_rec) - { - if ( ! c?$smtp ) return; - if ( h$name == "CONTENT-DISPOSITION" && /[fF][iI][lL][eE][nN][aA][mM][eE]/ in h$value ) - c$smtp$current_entity$filename = extract_filename_from_content_disposition(h$value); + c$smtp$entity$filename = extract_filename_from_content_disposition(h$value); if ( h$name == "CONTENT-TYPE" && /[nN][aA][mM][eE][:blank:]*=/ in h$value ) - c$smtp$current_entity$filename = extract_filename_from_content_disposition(h$value); + c$smtp$entity$filename = extract_filename_from_content_disposition(h$value); + } + +event mime_end_entity(c: connection) &priority=5 + { + if ( c?$smtp && c$smtp?$entity ) + delete c$smtp$entity; } diff --git a/scripts/base/protocols/smtp/file-analysis.bro b/scripts/base/protocols/smtp/file-analysis.bro index b893cbef7d..44938c8698 100644 --- a/scripts/base/protocols/smtp/file-analysis.bro +++ b/scripts/base/protocols/smtp/file-analysis.bro @@ -1,7 +1,7 @@ @load ./main @load ./entities @load base/utils/conn-ids -@load base/frameworks/file-analysis/main +@load base/frameworks/files module SMTP; @@ -12,16 +12,11 @@ export { function get_file_handle(c: connection, is_orig: bool): string { - if ( ! c?$smtp ) return ""; - return cat(ANALYZER_SMTP, " ", c$start_time, " ", c$smtp$trans_depth, " ", - c$smtp_state$mime_level); + return cat(ANALYZER_SMTP, c$start_time, c$smtp$trans_depth, + c$smtp_state$mime_depth); } -module GLOBAL; - -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) - &priority=5 +event bro_init() &priority=5 { - if ( tag != ANALYZER_SMTP ) return; - set_file_handle(SMTP::get_file_handle(c, is_orig)); + Files::register_protocol(ANALYZER_SMTP, SMTP::get_file_handle); } diff --git a/scripts/policy/frameworks/files/detect-MHR.bro b/scripts/policy/frameworks/files/detect-MHR.bro new file mode 100644 index 0000000000..c896bd56fd --- /dev/null +++ b/scripts/policy/frameworks/files/detect-MHR.bro @@ -0,0 +1,63 @@ +##! Detect file downloads that have hash values matching files in Team +##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). + +@load base/frameworks/files +@load base/frameworks/notice +@load frameworks/files/hash-all-files + +module MalwareHashRegistery; + +export { + redef enum Notice::Type += { + ## The hash value of a file transferred over HTTP matched in the + ## malware hash registry. + Match + }; + + redef record Files::Info += { + ## Team Cymru Malware Hash Registry date of first detection. + mhr_first_detected: time &log &optional; + ## Team Cymru Malware Hash Registry percent of detection + ## among malware scanners. + mhr_detect_rate: count &log &optional; + }; + + ## File types to attempt matching against the Malware Hash Registry. + const match_file_types = /^application\/x-dosexec/ &redef; + + ## The malware hash registry runs each malware sample through several A/V engines. + ## Team Cymru returns a percentage to indicate how many A/V engines flagged the + ## sample as malicious. This threshold allows you to require a minimum detection + ## rate. + const notice_threshold = 10 &redef; +} + +event file_hash(f: fa_file, kind: string, hash: string) + { + if ( kind=="sha1" && match_file_types in f$mime_type ) + { + local hash_domain = fmt("%s.malware.hash.cymru.com", hash); + when ( local MHR_result = lookup_hostname_txt(hash_domain) ) + { + # Data is returned as " " + local MHR_answer = split1(MHR_result, / /); + if ( |MHR_answer| == 2 ) + { + f$info$mhr_first_detected = double_to_time(to_double(MHR_answer[1])); + f$info$mhr_detect_rate = to_count(MHR_answer[2]); + + #print strftime("%Y-%m-%d %H:%M:%S", f$info$mhr_first_detected); + if ( f$info$mhr_detect_rate >= notice_threshold ) + { + local url = ""; + # TODO: Create a generic mechanism for creating file "urls". + #if ( f$source == "HTTP" ) + # url = HTTP::build_url_http(f); + local message = fmt("%s %s", hash, url); + #local message = fmt("Host(s) %s sent a file with SHA1 hash %s to host %s", f$src_host, hash, f$dst_host); + NOTICE([$note=Match, $msg=message]); + } + } + } + } + } diff --git a/scripts/policy/frameworks/files/hash-all-files.bro b/scripts/policy/frameworks/files/hash-all-files.bro new file mode 100644 index 0000000000..931857c2bc --- /dev/null +++ b/scripts/policy/frameworks/files/hash-all-files.bro @@ -0,0 +1,7 @@ +# Perform MD5 and SHA1 hashing on all files. + +event file_new(f: fa_file) + { + Files::add_analyzer(f, Files::ANALYZER_MD5); + Files::add_analyzer(f, Files::ANALYZER_SHA1); + } diff --git a/scripts/policy/frameworks/intel/smtp-url-extraction.bro b/scripts/policy/frameworks/intel/smtp-url-extraction.bro index 2b87f809a6..b4ab32a915 100644 --- a/scripts/policy/frameworks/intel/smtp-url-extraction.bro +++ b/scripts/policy/frameworks/intel/smtp-url-extraction.bro @@ -26,6 +26,6 @@ event file_new(f: fa_file) &priority=5 if ( ! f?$source ) return; if ( f$source != "SMTP" ) return; - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_DATA_EVENT, + Files::add_analyzer(f, [$tag=Files::ANALYZER_DATA_EVENT, $stream_event=intel_mime_data]); } diff --git a/scripts/base/protocols/smtp/entities-excerpt.bro b/scripts/policy/protocols/smtp/entities-excerpt.bro similarity index 100% rename from scripts/base/protocols/smtp/entities-excerpt.bro rename to scripts/policy/protocols/smtp/entities-excerpt.bro diff --git a/scripts/site/local.bro b/scripts/site/local.bro index dfebd9923a..e4b3a44e7a 100644 --- a/scripts/site/local.bro +++ b/scripts/site/local.bro @@ -64,7 +64,14 @@ # Detect logins using "interesting" hostnames. @load protocols/ssh/interesting-hostnames -# Detect MD5 sums in Team Cymru's Malware Hash Registry. -@load protocols/http/detect-MHR # Detect SQL injection attacks. @load protocols/http/detect-sqli + +#### Network File Handling #### + +# Enable MD5 and SHA1 hashing for all files. +@load frameworks/files/hash-all-files + +# Detect SHA1 sums in Team Cymru's Malware Hash Registry. +@load frameworks/files/detect-MHR + diff --git a/src/const.bif b/src/const.bif index 31e6ccee1a..10dceda6ff 100644 --- a/src/const.bif +++ b/src/const.bif @@ -24,4 +24,4 @@ const Tunnel::ip_tunnel_timeout: interval; const Threading::heartbeat_interval: interval; -const FileAnalysis::salt: string; +const Files::salt: string; diff --git a/src/event.bif b/src/event.bif index 5b14c05933..23ebc0591b 100644 --- a/src/event.bif +++ b/src/event.bif @@ -7001,7 +7001,7 @@ event event_queue_flush_point%(%); event get_file_handle%(tag: count, c: connection, is_orig: bool%); ## Indicates that an analysis of a new file has begun. The analysis can be -## augmented at this time via :bro:see:`FileAnalysis::add_analyzer`. +## augmented at this time via :bro:see:`Files::add_analyzer`. ## ## f: The file. ## @@ -7024,8 +7024,8 @@ event file_over_new_connection%(f: fa_file, c: connection%); ## f: The file. ## ## .. bro:see:: file_new file_over_new_connection file_gap file_state_remove -## default_file_timeout_interval FileAnalysis::set_timeout_interval -## FileAnalysis::set_timeout_interval +## default_file_timeout_interval Files::set_timeout_interval +## Files::set_timeout_interval event file_timeout%(f: fa_file%); ## Indicates that a chunk of the file is missing. @@ -7055,8 +7055,8 @@ event file_state_remove%(f: fa_file%); ## ## hash: The result of the hashing. ## -## .. bro:see:: FileAnalysis::add_analyzer FileAnalysis::ANALYZER_MD5 -## FileAnalysis::ANALYZER_SHA1 FileAnalysis::ANALYZER_SHA256 +## .. bro:see:: Files::add_analyzer Files::ANALYZER_MD5 +## Files::ANALYZER_SHA1 Files::ANALYZER_SHA256 event file_hash%(f: fa_file, kind: string, hash: string%); ## Deprecated. Will be removed. diff --git a/src/file_analysis.bif b/src/file_analysis.bif index ef46ccf9c1..648c031221 100644 --- a/src/file_analysis.bif +++ b/src/file_analysis.bif @@ -1,6 +1,6 @@ ##! Internal functions and types used by the logging framework. -module FileAnalysis; +module Files; %%{ #include "file_analysis/Manager.h" @@ -27,35 +27,35 @@ enum Analyzer %{ ANALYZER_DATA_EVENT, %} -## :bro:see:`FileAnalysis::set_timeout_interval`. -function FileAnalysis::__set_timeout_interval%(file_id: string, t: interval%): bool +## :bro:see:`Files::set_timeout_interval`. +function Files::__set_timeout_interval%(file_id: string, t: interval%): bool %{ bool result = file_mgr->SetTimeoutInterval(file_id->CheckString(), t); return new Val(result, TYPE_BOOL); %} -## :bro:see:`FileAnalysis::add_analyzer`. -function FileAnalysis::__add_analyzer%(file_id: string, args: any%): bool +## :bro:see:`Files::add_analyzer`. +function Files::__add_analyzer%(file_id: string, args: any%): bool %{ - using BifType::Record::FileAnalysis::AnalyzerArgs; + using BifType::Record::Files::AnalyzerArgs; RecordVal* rv = args->AsRecordVal()->CoerceTo(AnalyzerArgs); bool result = file_mgr->AddAnalyzer(file_id->CheckString(), rv); Unref(rv); return new Val(result, TYPE_BOOL); %} -## :bro:see:`FileAnalysis::remove_analyzer`. -function FileAnalysis::__remove_analyzer%(file_id: string, args: any%): bool +## :bro:see:`Files::remove_analyzer`. +function Files::__remove_analyzer%(file_id: string, args: any%): bool %{ - using BifType::Record::FileAnalysis::AnalyzerArgs; + using BifType::Record::Files::AnalyzerArgs; RecordVal* rv = args->AsRecordVal()->CoerceTo(AnalyzerArgs); bool result = file_mgr->RemoveAnalyzer(file_id->CheckString(), rv); Unref(rv); return new Val(result, TYPE_BOOL); %} -## :bro:see:`FileAnalysis::stop`. -function FileAnalysis::__stop%(file_id: string%): bool +## :bro:see:`Files::stop`. +function Files::__stop%(file_id: string%): bool %{ bool result = file_mgr->IgnoreFile(file_id->CheckString()); return new Val(result, TYPE_BOOL); diff --git a/src/file_analysis/Analyzer.h b/src/file_analysis/Analyzer.h index d32532b264..c348ab358b 100644 --- a/src/file_analysis/Analyzer.h +++ b/src/file_analysis/Analyzer.h @@ -8,7 +8,7 @@ namespace file_analysis { -typedef BifEnum::FileAnalysis::Analyzer FA_Tag; +typedef BifEnum::Files::Analyzer FA_Tag; class File; @@ -93,7 +93,7 @@ public: */ static FA_Tag ArgsTag(const RecordVal* args) { - using BifType::Record::FileAnalysis::AnalyzerArgs; + using BifType::Record::Files::AnalyzerArgs; return static_cast( args->Lookup(AnalyzerArgs->FieldOffset("tag"))->AsEnum()); } diff --git a/src/file_analysis/AnalyzerSet.cc b/src/file_analysis/AnalyzerSet.cc index 83c60d9abe..d10e78d338 100644 --- a/src/file_analysis/AnalyzerSet.cc +++ b/src/file_analysis/AnalyzerSet.cc @@ -26,7 +26,7 @@ static void analyzer_del_func(void* v) AnalyzerSet::AnalyzerSet(File* arg_file) : file(arg_file) { TypeList* t = new TypeList(); - t->Append(BifType::Record::FileAnalysis::AnalyzerArgs->Ref()); + t->Append(BifType::Record::Files::AnalyzerArgs->Ref()); analyzer_hash = new CompositeHash(t); Unref(t); analyzer_map.SetDeleteFunc(analyzer_del_func); diff --git a/src/file_analysis/DataEvent.cc b/src/file_analysis/DataEvent.cc index 159c8c19cd..1b04111c44 100644 --- a/src/file_analysis/DataEvent.cc +++ b/src/file_analysis/DataEvent.cc @@ -17,7 +17,7 @@ DataEvent::DataEvent(RecordVal* args, File* file, file_analysis::Analyzer* DataEvent::Instantiate(RecordVal* args, File* file) { - using BifType::Record::FileAnalysis::AnalyzerArgs; + using BifType::Record::Files::AnalyzerArgs; int chunk_off = AnalyzerArgs->FieldOffset("chunk_event"); int stream_off = AnalyzerArgs->FieldOffset("stream_event"); diff --git a/src/file_analysis/Extract.cc b/src/file_analysis/Extract.cc index cbe176d4ca..ef37425003 100644 --- a/src/file_analysis/Extract.cc +++ b/src/file_analysis/Extract.cc @@ -29,7 +29,7 @@ Extract::~Extract() file_analysis::Analyzer* Extract::Instantiate(RecordVal* args, File* file) { - using BifType::Record::FileAnalysis::AnalyzerArgs; + using BifType::Record::Files::AnalyzerArgs; Val* v = args->Lookup(AnalyzerArgs->FieldOffset("extract_filename")); if ( ! v ) diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index b247f23efc..61f9f7a10d 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -38,7 +38,7 @@ string Manager::HashHandle(const string& handle) const static string salt; if ( salt.empty() ) - salt = BifConst::FileAnalysis::salt->CheckString(); + salt = BifConst::Files::salt->CheckString(); char tmp[20]; uint64 hash[2]; @@ -310,7 +310,7 @@ void Manager::GetFileHandle(AnalyzerTag::Tag tag, Connection* c, bool is_orig) bool Manager::IsDisabled(AnalyzerTag::Tag tag) { if ( ! disabled ) - disabled = internal_const_val("FileAnalysis::disable")->AsTableVal(); + disabled = internal_const_val("Files::disable")->AsTableVal(); Val* index = new Val(tag, TYPE_COUNT); Val* yield = disabled->Lookup(index); diff --git a/testing/btest/scripts/base/frameworks/file-analysis/bifs/remove_action.bro b/testing/btest/scripts/base/frameworks/file-analysis/bifs/remove_action.bro index 1f15a4221f..e31abe5ea3 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/bifs/remove_action.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/bifs/remove_action.bro @@ -11,8 +11,8 @@ redef test_get_file_name = function(f: fa_file): string event file_new(f: fa_file) &priority=-10 { for ( tag in test_file_analyzers ) - FileAnalysis::remove_analyzer(f, tag); + Files::remove_analyzer(f, tag); local filename = test_get_file_name(f); - FileAnalysis::remove_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, + Files::remove_analyzer(f, [$tag=Files::ANALYZER_EXTRACT, $extract_filename=filename]); } diff --git a/testing/btest/scripts/base/frameworks/file-analysis/bifs/set_timeout_interval.bro b/testing/btest/scripts/base/frameworks/file-analysis/bifs/set_timeout_interval.bro index 8ec4704cdb..c9eac4c31d 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/bifs/set_timeout_interval.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/bifs/set_timeout_interval.bro @@ -20,7 +20,7 @@ redef default_file_timeout_interval = 2sec; event file_timeout(f: fa_file) { if ( timeout_cnt < 1 ) - FileAnalysis::set_timeout_interval(f, f$timeout_interval); + Files::set_timeout_interval(f, f$timeout_interval); else terminate(); ++timeout_cnt; diff --git a/testing/btest/scripts/base/frameworks/file-analysis/bifs/stop.bro b/testing/btest/scripts/base/frameworks/file-analysis/bifs/stop.bro index e994706010..dd40c69684 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/bifs/stop.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/bifs/stop.bro @@ -4,5 +4,5 @@ event file_new(f: fa_file) { - FileAnalysis::stop(f); + Files::stop(f); } diff --git a/testing/scripts/file-analysis-test.bro b/testing/scripts/file-analysis-test.bro index 15929dd4f6..cb1027d8f1 100644 --- a/testing/scripts/file-analysis-test.bro +++ b/testing/scripts/file-analysis-test.bro @@ -1,7 +1,7 @@ global test_file_analysis_source: string = "" &redef; -global test_file_analyzers: set[FileAnalysis::AnalyzerArgs]; +global test_file_analyzers: set[Files::AnalyzerArgs]; global test_get_file_name: function(f: fa_file): string = function(f: fa_file): string { return ""; } &redef; @@ -30,13 +30,13 @@ event file_new(f: fa_file) f$source == test_file_analysis_source ) { for ( tag in test_file_analyzers ) - FileAnalysis::add_analyzer(f, tag); + Files::add_analyzer(f, tag); local filename: string = test_get_file_name(f); if ( filename != "" ) - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, + Files::add_analyzer(f, [$tag=Files::ANALYZER_EXTRACT, $extract_filename=filename]); - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_DATA_EVENT, + Files::add_analyzer(f, [$tag=Files::ANALYZER_DATA_EVENT, $chunk_event=file_chunk, $stream_event=file_stream]); } @@ -94,7 +94,7 @@ event file_state_remove(f: fa_file) event bro_init() { - add test_file_analyzers[[$tag=FileAnalysis::ANALYZER_MD5]]; - add test_file_analyzers[[$tag=FileAnalysis::ANALYZER_SHA1]]; - add test_file_analyzers[[$tag=FileAnalysis::ANALYZER_SHA256]]; + add test_file_analyzers[[$tag=Files::ANALYZER_MD5]]; + add test_file_analyzers[[$tag=Files::ANALYZER_SHA1]]; + add test_file_analyzers[[$tag=Files::ANALYZER_SHA256]]; } From 2b48396d23f2dddb9dcef005fb478d9d12b99dad Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 5 Jul 2013 02:00:35 -0400 Subject: [PATCH 107/881] Check file_over_new_connetion to fire for each connection (including the first). --- src/file_analysis/File.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index e68ee5523c..c1ad92c0ed 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -116,11 +116,8 @@ void File::UpdateConnectionFields(Connection* conn) Val* conns = val->Lookup(conns_idx); - bool is_first = false; - if ( ! conns ) { - is_first = true; conns = empty_connection_table(); val->Assign(conns_idx, conns); } @@ -131,7 +128,7 @@ void File::UpdateConnectionFields(Connection* conn) Val* conn_val = conn->BuildConnVal(); conns->AsTableVal()->Assign(idx, conn_val); - if ( ! is_first && FileEventAvailable(file_over_new_connection) ) + if ( FileEventAvailable(file_over_new_connection) ) { val_list* vl = new val_list(); vl->append(val->Ref()); From cdf6b7864ecab07bf6a6150cbaa3eb58a12251c0 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 9 Jul 2013 11:50:54 -0400 Subject: [PATCH 108/881] More file analysis updates. - Recorrected the module name to Files. - Added Files::analyzer_name to get a more readable name for a file analyzer. - Improved and just overall better handled multipart mime transfers in HTTP and SMTP. HTTP now has orig_fuids and resp_fuids log fields since multiple "files" can be transferred with multipart mime in a single request/response pair. SMTP has an fuids field which has file unique IDs for all parts transferred. FTP and IRC have a log field named fuid added because only a single file can be transferred per irc and ftp log line. --- scripts/base/frameworks/files/main.bro | 51 +++++++++----- scripts/base/protocols/ftp/__load__.bro | 2 +- scripts/base/protocols/ftp/file-analysis.bro | 23 ------ scripts/base/protocols/ftp/files.bro | 40 +++++++++++ scripts/base/protocols/http/__load__.bro | 6 +- scripts/base/protocols/http/entities.bro | 70 +++++++++++++++++++ .../http/{file-analysis.bro => files.bro} | 30 ++++---- scripts/base/protocols/http/main.bro | 26 +------ scripts/base/protocols/irc/__load__.bro | 4 +- scripts/base/protocols/irc/dcc-send.bro | 4 +- scripts/base/protocols/irc/files.bro | 41 +++++++++++ scripts/base/protocols/smtp/__load__.bro | 3 +- scripts/base/protocols/smtp/entities.bro | 3 +- scripts/base/protocols/smtp/file-analysis.bro | 22 ------ scripts/base/protocols/smtp/files.bro | 34 +++++++++ src/file_analysis/Manager.cc | 8 +-- src/file_analysis/analyzer/hash/events.bif | 4 +- src/file_analysis/file_analysis.bif | 6 ++ 18 files changed, 257 insertions(+), 120 deletions(-) delete mode 100644 scripts/base/protocols/ftp/file-analysis.bro create mode 100644 scripts/base/protocols/ftp/files.bro create mode 100644 scripts/base/protocols/http/entities.bro rename scripts/base/protocols/http/{file-analysis.bro => files.bro} (50%) create mode 100644 scripts/base/protocols/irc/files.bro delete mode 100644 scripts/base/protocols/smtp/file-analysis.bro create mode 100644 scripts/base/protocols/smtp/files.bro diff --git a/scripts/base/frameworks/files/main.bro b/scripts/base/frameworks/files/main.bro index d6e26e1833..d5a3ddee67 100644 --- a/scripts/base/frameworks/files/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -61,7 +61,7 @@ export { depth: count &default=0 &log; ## A set of analysis types done during the file analysis. - analyzers: set[Analyzer] &log; + analyzers: set[string] &log; ## A mime type provided by libmagic against the *bof_buffer*, or ## in the cases where no buffering of the beginning of file occurs, @@ -76,11 +76,16 @@ export { ## The duration the file was analyzed for. duration: interval &log &default=0secs; - ## If the source of this file is is a network connection, this field + ## If the source of this file is a network connection, this field ## indicates if the data originated from the local network or not as ## determined by the configured bro:see:`Site::local_nets`. local_orig: bool &log &optional; + ## If the source of this file is a network connection, this field + ## indicates if the file is being sent by the originator of the connection + ## or the responder. + is_orig: bool &log &optional; + ## Number of bytes provided to the file analysis engine for the file. seen_bytes: count &log &default=0; @@ -105,7 +110,7 @@ export { ## A table that can be used to disable file analysis completely for ## any files transferred over given network protocol analyzers. - const disable: table[Analyzer::Tag] of bool = table() &redef; + const disable: table[Files::Tag] of bool = table() &redef; ## The salt concatenated to unique file handle strings generated by ## :bro:see:`get_file_handle` before hashing them in to a file id @@ -139,7 +144,7 @@ export { ## for the *id* isn't currently active or the *args* ## were invalid for the analyzer type. global add_analyzer: function(f: fa_file, - tag: Files::Analyzer, + tag: Files::Tag, args: AnalyzerArgs &default=AnalyzerArgs()): bool; ## Removes an analyzer from the analysis of a given file. @@ -150,7 +155,7 @@ export { ## ## Returns: true if the analyzer will be removed, or false if analysis ## for the *id* isn't currently active. - global remove_analyzer: function(f: fa_file, tag: Files::Analyzer, args: AnalyzerArgs): bool; + global remove_analyzer: function(f: fa_file, tag: Files::Tag, args: AnalyzerArgs): bool; ## Stops/ignores any further analysis of a given file. ## @@ -161,6 +166,13 @@ export { ## isn't currently active. global stop: function(f: fa_file): bool; + ## Translates an file analyzer enum value to a string with the analyzer's name. + ## + ## tag: The analyzer tag. + ## + ## Returns: The analyzer name corresponding to the tag. + global analyzer_name: function(tag: Files::Tag): string; + ## Register callbacks for protocols that work with the Files framework. ## The callbacks must uniquely identify a file and each protocol can ## only have a single callback registered for it. @@ -171,7 +183,7 @@ export { ## defined previously. ## ## Returns: true if the protocol being registered was not previously registered. - global register_protocol: function(tag: AnalyzerTag, callback: function(c: connection, is_orig: bool): string): bool; + global register_protocol: function(tag: Files::Tag, callback: function(c: connection, is_orig: bool): string): bool; ## Register a callback for file analyzers to use if they need to do some manipulation ## when they are being added to a file before the core code takes over. This is @@ -181,7 +193,7 @@ export { ## tag: Tag for the file analyzer. ## ## callback: Function to execute when the given file analyzer is being added. - global register_analyzer_add_callback: function(tag: Files::Analyzer, callback: function(f: fa_file, args: AnalyzerArgs)); + global register_analyzer_add_callback: function(tag: Files::Tag, callback: function(f: fa_file, args: AnalyzerArgs)); ## Event that can be handled to access the Info record as it is sent on ## to the logging framework. @@ -194,14 +206,14 @@ redef record fa_file += { redef record AnalyzerArgs += { # This is used interally for the core file analyzer api. - tag: Files::Analyzer &optional; + tag: Files::Tag &optional; }; # Store the callbacks for protocol analyzers that have files. -global registered_protocols: table[AnalyzerTag] of function(c: connection, is_orig: bool): string = table() +global registered_protocols: table[Files::Tag] of function(c: connection, is_orig: bool): string = table() &default=function(c: connection, is_orig: bool): string { return cat(c$uid, is_orig); }; -global analyzer_add_callbacks: table[Files::Analyzer] of function(f: fa_file, args: AnalyzerArgs) = table(); +global analyzer_add_callbacks: table[Files::Tag] of function(f: fa_file, args: AnalyzerArgs) = table(); event bro_init() &priority=5 { @@ -227,6 +239,8 @@ function set_info(f: fa_file) f$info$total_bytes = f$total_bytes; f$info$missing_bytes = f$missing_bytes; f$info$overflow_bytes = f$overflow_bytes; + if ( f?$is_orig ) + f$info$is_orig = f$is_orig; if ( f?$mime_type ) f$info$mime_type = f$mime_type; } @@ -236,11 +250,11 @@ function set_timeout_interval(f: fa_file, t: interval): bool return __set_timeout_interval(f$id, t); } -function add_analyzer(f: fa_file, tag: Analyzer, args: AnalyzerArgs): bool +function add_analyzer(f: fa_file, tag: Files::Tag, args: AnalyzerArgs): bool { # This is to construct the correct args for the core API. args$tag = tag; - add f$info$analyzers[tag]; + add f$info$analyzers[Files::analyzer_name(tag)]; if ( tag in analyzer_add_callbacks ) analyzer_add_callbacks[tag](f, args); @@ -253,12 +267,12 @@ function add_analyzer(f: fa_file, tag: Analyzer, args: AnalyzerArgs): bool return T; } -function register_analyzer_add_callback(tag: Files::Analyzer, callback: function(f: fa_file, args: AnalyzerArgs)) +function register_analyzer_add_callback(tag: Files::Tag, callback: function(f: fa_file, args: AnalyzerArgs)) { analyzer_add_callbacks[tag] = callback; } -function remove_analyzer(f: fa_file, tag: Files::Analyzer, args: AnalyzerArgs): bool +function remove_analyzer(f: fa_file, tag: Files::Tag, args: AnalyzerArgs): bool { args$tag = tag; return __remove_analyzer(f$id, args); @@ -269,6 +283,11 @@ function stop(f: fa_file): bool return __stop(f$id); } +function analyzer_name(tag: Files::Tag): string + { + return __analyzer_name(tag); + } + event file_new(f: fa_file) &priority=10 { set_info(f); @@ -302,14 +321,14 @@ event file_state_remove(f: fa_file) &priority=-10 Log::write(Files::LOG, f$info); } -function register_protocol(tag: AnalyzerTag, callback: function(c: connection, is_orig: bool): string): bool +function register_protocol(tag: Files::Tag, callback: function(c: connection, is_orig: bool): string): bool { local result = (tag !in registered_protocols); registered_protocols[tag] = callback; return result; } -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) &priority=5 +event get_file_handle(tag: Files::Tag, c: connection, is_orig: bool) &priority=5 { local handler = registered_protocols[tag]; set_file_handle(handler(c, is_orig)); diff --git a/scripts/base/protocols/ftp/__load__.bro b/scripts/base/protocols/ftp/__load__.bro index 9c839610ac..6fffd5ec43 100644 --- a/scripts/base/protocols/ftp/__load__.bro +++ b/scripts/base/protocols/ftp/__load__.bro @@ -1,4 +1,4 @@ @load ./utils-commands @load ./main -@load ./file-analysis +@load ./files @load ./gridftp diff --git a/scripts/base/protocols/ftp/file-analysis.bro b/scripts/base/protocols/ftp/file-analysis.bro deleted file mode 100644 index 3710a44cee..0000000000 --- a/scripts/base/protocols/ftp/file-analysis.bro +++ /dev/null @@ -1,23 +0,0 @@ -@load ./main -@load base/utils/conn-ids -@load base/frameworks/files - -module FTP; - -export { - ## Default file handle provider for FTP. - global get_file_handle: function(c: connection, is_orig: bool): string; -} - -function get_file_handle(c: connection, is_orig: bool): string - { - if ( [c$id$resp_h, c$id$resp_p] !in ftp_data_expected ) - return ""; - - return cat(ANALYZER_FTP_DATA, c$start_time, c$id, is_orig); - } - -event bro_init() &priority=5 - { - Files::register_protocol(ANALYZER_FTP_DATA, FTP::get_file_handle); - } diff --git a/scripts/base/protocols/ftp/files.bro b/scripts/base/protocols/ftp/files.bro new file mode 100644 index 0000000000..a943adff9d --- /dev/null +++ b/scripts/base/protocols/ftp/files.bro @@ -0,0 +1,40 @@ +@load ./main +@load base/utils/conn-ids +@load base/frameworks/files + +module FTP; + +export { + redef record Info += { + ## File unique ID. + fuid: string &optional &log; + }; + + ## Default file handle provider for FTP. + global get_file_handle: function(c: connection, is_orig: bool): string; +} + +function get_file_handle(c: connection, is_orig: bool): string + { + if ( [c$id$resp_h, c$id$resp_p] !in ftp_data_expected ) + return ""; + + return cat(Analyzer::ANALYZER_FTP_DATA, c$start_time, c$id, is_orig); + } + +event bro_init() &priority=5 + { + Files::register_protocol(Analyzer::ANALYZER_FTP_DATA, FTP::get_file_handle); + } + + +event file_over_new_connection(f: fa_file, c: connection) &priority=5 + { + if ( [c$id$resp_h, c$id$resp_p] !in ftp_data_expected ) + return; + + local ftp = ftp_data_expected[c$id$resp_h, c$id$resp_p]; + ftp$fuid = f$id; + if ( f?$mime_type ) + ftp$mime_type = f$mime_type; + } \ No newline at end of file diff --git a/scripts/base/protocols/http/__load__.bro b/scripts/base/protocols/http/__load__.bro index 585b815eed..f0cec220d3 100644 --- a/scripts/base/protocols/http/__load__.bro +++ b/scripts/base/protocols/http/__load__.bro @@ -1,6 +1,4 @@ @load ./main +@load ./entities @load ./utils -@load ./file-analysis -#@load ./file-ident -#@load ./file-hash -#@load ./file-extract +@load ./files \ No newline at end of file diff --git a/scripts/base/protocols/http/entities.bro b/scripts/base/protocols/http/entities.bro new file mode 100644 index 0000000000..cc852a7e11 --- /dev/null +++ b/scripts/base/protocols/http/entities.bro @@ -0,0 +1,70 @@ +##! Analysis and logging for MIME entities found in HTTP sessions. + +@load base/frameworks/files +@load base/utils/strings +@load base/utils/files +@load ./main + +module HTTP; + +export { + type Entity: record { + ## Depth of the entity if multiple entities are sent in a single transaction. + depth: count &default=0; + + ## Filename for the entity if discovered from a header. + filename: string &optional; + }; + + redef record Info += { + ## The current entity being seen. + entity: Entity &optional; + + ## Current number of MIME entities in the HTTP request message body. + orig_mime_depth: count &default=0; + ## Current number of MIME entities in the HTTP response message body. + resp_mime_depth: count &default=0; + }; +} + +event http_begin_entity(c: connection, is_orig: bool) &priority=10 + { + set_state(c, F, is_orig); + + if ( is_orig ) + ++c$http$orig_mime_depth; + else + ++c$http$resp_mime_depth; + + c$http$entity = Entity($depth = is_orig ? c$http$orig_mime_depth : c$http$resp_mime_depth); + } + +event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=3 + { + if ( name == "CONTENT-DISPOSITION" && + /[fF][iI][lL][eE][nN][aA][mM][eE]/ in value ) + { + c$http$entity$filename = extract_filename_from_content_disposition(value); + } + else if ( name == "CONTENT-TYPE" && + /[nN][aA][mM][eE][:blank:]*=/ in value ) + { + c$http$entity$filename = extract_filename_from_content_disposition(value); + } + } + +event file_over_new_connection(f: fa_file, c: connection) &priority=5 + { + if ( f$source == "HTTP" && c$http?$entity ) + { + f$info$depth = c$http$entity$depth; + if ( c$http$entity?$filename ) + f$info$filename = c$http$entity$filename; + } + } + +event http_end_entity(c: connection, is_orig: bool) &priority=5 + { + if ( c?$http && c$http?$entity ) + delete c$http$entity; + } diff --git a/scripts/base/protocols/http/file-analysis.bro b/scripts/base/protocols/http/files.bro similarity index 50% rename from scripts/base/protocols/http/file-analysis.bro rename to scripts/base/protocols/http/files.bro index b79ca041b8..44fdc4c1f4 100644 --- a/scripts/base/protocols/http/file-analysis.bro +++ b/scripts/base/protocols/http/files.bro @@ -1,17 +1,17 @@ @load ./main +@load ./entities @load ./utils -@load base/utils/conn-ids @load base/frameworks/files module HTTP; export { redef record Info += { - ## The sniffed mime type of the data being sent by the client. - client_mime_type: string &log &optional; + ## An ordered vector of file unique IDs seen sent by the originator (client). + orig_fuids: vector of string &log &default=string_vec(); - ## The sniffed mime type of the data being returned by the server. - mime_type: string &log &optional; + ## An ordered vector of file unique IDs seen sent by the responder (server). + resp_fuids: vector of string &log &default=string_vec(); }; ## Default file handle provider for HTTP. @@ -26,33 +26,27 @@ function get_file_handle(c: connection, is_orig: bool): string local mime_depth = is_orig ? c$http$orig_mime_depth : c$http$resp_mime_depth; if ( c$http$range_request ) { - return cat(ANALYZER_HTTP, is_orig, c$id$orig_h, mime_depth, build_url(c$http)); + return cat(Analyzer::ANALYZER_HTTP, is_orig, c$id$orig_h, mime_depth, build_url(c$http)); } else { - return cat(ANALYZER_HTTP, c$start_time, is_orig, + return cat(Analyzer::ANALYZER_HTTP, c$start_time, is_orig, c$http$trans_depth, mime_depth, id_string(c$id)); } } event bro_init() &priority=5 { - Files::register_protocol(ANALYZER_HTTP, HTTP::get_file_handle); + Files::register_protocol(Analyzer::ANALYZER_HTTP, HTTP::get_file_handle); } event file_over_new_connection(f: fa_file, c: connection) &priority=5 { if ( c?$http ) { - #if (!f?$mime_type) - # print f; -# - #if ( f$is_orig ) - # c$http$client_mime_type = f$mime_type; - #else - # c$http$mime_type = f$mime_type; - - if ( c$http?$filename ) - f$info$filename = c$http$filename; + if ( f$is_orig ) + c$http$orig_fuids[|c$http$orig_fuids|] = f$id; + else + c$http$resp_fuids[|c$http$resp_fuids|] = f$id; } } \ No newline at end of file diff --git a/scripts/base/protocols/http/main.bro b/scripts/base/protocols/http/main.bro index a982fdc9c6..d96384ee5f 100644 --- a/scripts/base/protocols/http/main.bro +++ b/scripts/base/protocols/http/main.bro @@ -75,10 +75,6 @@ export { ## Indicates if this request can assume 206 partial content in ## response. range_request: bool &default=F; - ## Number of MIME entities in the HTTP request message body so far. - orig_mime_depth: count &default=0; - ## Number of MIME entities in the HTTP response message body so far. - resp_mime_depth: count &default=0; }; ## Structure to maintain state for an HTTP connection with multiple @@ -104,8 +100,8 @@ export { } &redef; ## A list of HTTP methods. Other methods will generate a weird. Note - ## that the HTTP analyzer will only accept methods consisting solely - ## of letters ``[A-Za-z]``. + ## that the HTTP analyzer will only accept methods consisting solely + ## of letters ``[A-Za-z]``. const http_methods: set[string] = { "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "CONNECT", @@ -275,25 +271,9 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr } } } - - else # server headers - { - if ( name == "CONTENT-DISPOSITION" && - /[fF][iI][lL][eE][nN][aA][mM][eE]/ in value ) - c$http$filename = extract_filename_from_content_disposition(value); - } + } -event http_begin_entity(c: connection, is_orig: bool) &priority=5 - { - set_state(c, F, is_orig); - - if ( is_orig ) - ++c$http$orig_mime_depth; - else - ++c$http$resp_mime_depth; - } - event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) &priority = 5 { set_state(c, F, is_orig); diff --git a/scripts/base/protocols/irc/__load__.bro b/scripts/base/protocols/irc/__load__.bro index d20550c54f..afb7fecc62 100644 --- a/scripts/base/protocols/irc/__load__.bro +++ b/scripts/base/protocols/irc/__load__.bro @@ -1,3 +1,3 @@ @load ./main -#@load ./dcc-send -@load ./file-analysis +@load ./dcc-send +@load ./files \ No newline at end of file diff --git a/scripts/base/protocols/irc/dcc-send.bro b/scripts/base/protocols/irc/dcc-send.bro index b79eb370e6..83b32faf2b 100644 --- a/scripts/base/protocols/irc/dcc-send.bro +++ b/scripts/base/protocols/irc/dcc-send.bro @@ -49,13 +49,15 @@ function log_dcc(f: fa_file) delete irc$dcc_file_name; delete irc$dcc_file_size; delete irc$dcc_mime_type; + + delete dcc_expected_transfers[cid$resp_h, cid$resp_p]; return; } } event file_new(f: fa_file) &priority=-5 { - if ( f?$source && f$source == "IRC_DATA" ) + if ( f$source == "IRC_DATA" ) log_dcc(f); } diff --git a/scripts/base/protocols/irc/files.bro b/scripts/base/protocols/irc/files.bro new file mode 100644 index 0000000000..f4553b534a --- /dev/null +++ b/scripts/base/protocols/irc/files.bro @@ -0,0 +1,41 @@ +@load ./dcc-send +@load base/utils/conn-ids +@load base/frameworks/files + +module IRC; + +export { + redef record Info += { + ## File unique ID. + fuid: string &log &optional; + }; + + ## Default file handle provider for IRC. + global get_file_handle: function(c: connection, is_orig: bool): string; +} + +function get_file_handle(c: connection, is_orig: bool): string + { + if ( [c$id$resp_h, c$id$resp_p] !in dcc_expected_transfers ) + return ""; + + return cat(Analyzer::ANALYZER_IRC_DATA, c$start_time, c$id, is_orig); + } + +event bro_init() &priority=5 + { + Files::register_protocol(Analyzer::ANALYZER_IRC_DATA, IRC::get_file_handle); + } + +event file_over_new_connection(f: fa_file, c: connection) &priority=5 + { + if ( [c$id$resp_h, c$id$resp_p] !in dcc_expected_transfers ) + return; + + local irc = dcc_expected_transfers[c$id$resp_h, c$id$resp_p]; + irc$fuid = f$id; + if ( irc?$dcc_file_name ) + f$info$filename = irc$dcc_file_name; + if ( f?$mime_type ) + irc$dcc_mime_type = f$mime_type; + } \ No newline at end of file diff --git a/scripts/base/protocols/smtp/__load__.bro b/scripts/base/protocols/smtp/__load__.bro index 1e913d8dff..a37c2ed3de 100644 --- a/scripts/base/protocols/smtp/__load__.bro +++ b/scripts/base/protocols/smtp/__load__.bro @@ -1,4 +1,3 @@ @load ./main @load ./entities -#@load ./entities-excerpt -@load ./file-analysis +@load ./files \ No newline at end of file diff --git a/scripts/base/protocols/smtp/entities.bro b/scripts/base/protocols/smtp/entities.bro index dcb53dc0aa..067b8acf8e 100644 --- a/scripts/base/protocols/smtp/entities.bro +++ b/scripts/base/protocols/smtp/entities.bro @@ -9,6 +9,7 @@ module SMTP; export { type Entity: record { + ## Filename for the entity if discovered from a header. filename: string &optional; }; @@ -26,8 +27,6 @@ export { event mime_begin_entity(c: connection) &priority=10 { - #print fmt("%s : begin entity", c$uid); - c$smtp$entity = Entity(); ++c$smtp_state$mime_depth; } diff --git a/scripts/base/protocols/smtp/file-analysis.bro b/scripts/base/protocols/smtp/file-analysis.bro deleted file mode 100644 index 44938c8698..0000000000 --- a/scripts/base/protocols/smtp/file-analysis.bro +++ /dev/null @@ -1,22 +0,0 @@ -@load ./main -@load ./entities -@load base/utils/conn-ids -@load base/frameworks/files - -module SMTP; - -export { - ## Default file handle provider for SMTP. - global get_file_handle: function(c: connection, is_orig: bool): string; -} - -function get_file_handle(c: connection, is_orig: bool): string - { - return cat(ANALYZER_SMTP, c$start_time, c$smtp$trans_depth, - c$smtp_state$mime_depth); - } - -event bro_init() &priority=5 - { - Files::register_protocol(ANALYZER_SMTP, SMTP::get_file_handle); - } diff --git a/scripts/base/protocols/smtp/files.bro b/scripts/base/protocols/smtp/files.bro new file mode 100644 index 0000000000..e67181d6bc --- /dev/null +++ b/scripts/base/protocols/smtp/files.bro @@ -0,0 +1,34 @@ +@load ./main +@load ./entities +@load base/utils/conn-ids +@load base/frameworks/files + +module SMTP; + +export { + redef record Info += { + ## An ordered vector of file unique IDs seen attached to + ## the message. + fuids: vector of string &log &default=string_vec(); + }; + + ## Default file handle provider for SMTP. + global get_file_handle: function(c: connection, is_orig: bool): string; +} + +function get_file_handle(c: connection, is_orig: bool): string + { + return cat(Analyzer::ANALYZER_SMTP, c$start_time, c$smtp$trans_depth, + c$smtp_state$mime_depth); + } + +event bro_init() &priority=5 + { + Files::register_protocol(Analyzer::ANALYZER_SMTP, SMTP::get_file_handle); + } + +event file_over_new_connection(f: fa_file, c: connection) &priority=5 + { + if ( c?$smtp ) + c$smtp$fuids[|c$smtp$fuids|] = f$id; + } \ No newline at end of file diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index 02af4aa9f1..453c6f7902 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -19,8 +19,8 @@ string Manager::salt; Manager::Manager() { - tag_enum_type = new EnumType("FileAnalysis::Tag"); - ::ID* id = install_ID("Tag", "FileAnalysis", true, true); + tag_enum_type = new EnumType("Files::Tag"); + ::ID* id = install_ID("Tag", "Files", true, true); add_type(id, tag_enum_type, 0, 0); } @@ -42,7 +42,7 @@ void Manager::RegisterAnalyzerComponent(Component* component) { const char* cname = component->CanonicalName(); - if ( tag_enum_type->Lookup("FileAnalysis", cname) != -1 ) + if ( tag_enum_type->Lookup("Files", cname) != -1 ) reporter->FatalError("File Analyzer %s defined more than once", cname); DBG_LOG(DBG_FILE_ANALYSIS, "Registering analyzer %s (tag %s)", @@ -54,7 +54,7 @@ void Manager::RegisterAnalyzerComponent(Component* component) component->Tag().AsEnumVal()->InternalInt(), component)); string id = fmt("ANALYZER_%s", cname); - tag_enum_type->AddName("FileAnalysis", id.c_str(), + tag_enum_type->AddName("Files", id.c_str(), component->Tag().AsEnumVal()->InternalInt(), true); } diff --git a/src/file_analysis/analyzer/hash/events.bif b/src/file_analysis/analyzer/hash/events.bif index b4a8de1c74..e03cbf359a 100644 --- a/src/file_analysis/analyzer/hash/events.bif +++ b/src/file_analysis/analyzer/hash/events.bif @@ -7,6 +7,6 @@ ## ## hash: The result of the hashing. ## -## .. bro:see:: FileAnalysis::add_analyzer FileAnalysis::ANALYZER_MD5 -## FileAnalysis::ANALYZER_SHA1 FileAnalysis::ANALYZER_SHA256 +## .. bro:see:: Files::add_analyzer Files::ANALYZER_MD5 +## Files::ANALYZER_SHA1 Files::ANALYZER_SHA256 event file_hash%(f: fa_file, kind: string, hash: string%); diff --git a/src/file_analysis/file_analysis.bif b/src/file_analysis/file_analysis.bif index 148e6360da..b6c80ac800 100644 --- a/src/file_analysis/file_analysis.bif +++ b/src/file_analysis/file_analysis.bif @@ -42,6 +42,12 @@ function Files::__stop%(file_id: string%): bool return new Val(result, TYPE_BOOL); %} +## :bro:see:`Files::analyzer_name`. +function Files::__analyzer_name%(tag: Files::Tag%) : string + %{ + return new StringVal(file_mgr->GetAnalyzerName(tag->InternalInt())); + %} + module GLOBAL; ## For use within a :bro:see:`get_file_handle` handler to set a unique From ecfac31de0b5d69254b590939c3a56be4038e0d6 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 9 Jul 2013 11:51:23 -0400 Subject: [PATCH 109/881] Fixed SMTP URL extraction for the Intel framework with Files updates. --- .../frameworks/intel/smtp-url-extraction.bro | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/scripts/policy/frameworks/intel/smtp-url-extraction.bro b/scripts/policy/frameworks/intel/smtp-url-extraction.bro index b4ab32a915..2478eba9f8 100644 --- a/scripts/policy/frameworks/intel/smtp-url-extraction.bro +++ b/scripts/policy/frameworks/intel/smtp-url-extraction.bro @@ -1,11 +1,12 @@ @load base/frameworks/intel -@load base/protocols/smtp/file-analysis +@load base/protocols/smtp @load base/utils/urls @load ./where-locations event intel_mime_data(f: fa_file, data: string) { - if ( ! f?$conns ) return; + if ( ! f?$conns ) + return; for ( cid in f$conns ) { @@ -21,11 +22,8 @@ event intel_mime_data(f: fa_file, data: string) } } -event file_new(f: fa_file) &priority=5 +event file_new(f: fa_file) { - if ( ! f?$source ) return; - if ( f$source != "SMTP" ) return; - - Files::add_analyzer(f, [$tag=Files::ANALYZER_DATA_EVENT, - $stream_event=intel_mime_data]); + if ( f$source == "SMTP" ) + Files::add_analyzer(f, Files::ANALYZER_DATA_EVENT, [$stream_event=intel_mime_data]); } From 5dbc354898454bb3e8b0970119925b42bec213f7 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 9 Jul 2013 14:05:36 -0400 Subject: [PATCH 110/881] extract_filename_from_content_disposition is still hacky but more closely aligns with RFC5987 --- scripts/base/utils/files.bro | 14 ++++++++++---- .../btest/Baseline/scripts.base.utils.files/output | 3 +++ testing/btest/scripts/base/utils/files.test | 7 +++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/scripts/base/utils/files.bro b/scripts/base/utils/files.bro index 76d2ecea4f..fedd93ab47 100644 --- a/scripts/base/utils/files.bro +++ b/scripts/base/utils/files.bro @@ -19,9 +19,15 @@ function generate_extraction_filename(prefix: string, c: connection, suffix: str ## the filename. function extract_filename_from_content_disposition(data: string): string { - local filename = sub(data, /^.*[nN][aA][mM][eE][[:blank:]]*=[[:blank:]]*/, ""); + local filename = sub(data, /^.*[nN][aA][mM][eE][[:blank:]]*\*?=[[:blank:]]*/, ""); + # Remove quotes around the filename if they are there. if ( /^\"/ in filename ) - filename = split_n(filename, /\"/, F, 2)[2]; - return filename; - } + filename = split_n(filename, /\"/, F, 2)[2]; + + # Remove the language and encoding if it's there. + if ( /^[a-zA-Z0-9\!#$%&+-^_`{}~]+'[a-zA-Z0-9\!#$%&+-^_`{}~]*'/ in filename ) + filename = sub(filename, /^.+'.*'/, ""); + + return unescape_URI(filename); + } \ No newline at end of file diff --git a/testing/btest/Baseline/scripts.base.utils.files/output b/testing/btest/Baseline/scripts.base.utils.files/output index ab92c3a624..4d53bcedd3 100644 --- a/testing/btest/Baseline/scripts.base.utils.files/output +++ b/testing/btest/Baseline/scripts.base.utils.files/output @@ -1,3 +1,6 @@ +Economy +US-$ rates +\xa3 rates test-prefix_141.142.220.118:48649-208.80.152.118:80_test-suffix test-prefix_141.142.220.118:48649-208.80.152.118:80 141.142.220.118:48649-208.80.152.118:80_test-suffix diff --git a/testing/btest/scripts/base/utils/files.test b/testing/btest/scripts/base/utils/files.test index 84eff13187..3324522030 100644 --- a/testing/btest/scripts/base/utils/files.test +++ b/testing/btest/scripts/base/utils/files.test @@ -11,3 +11,10 @@ event connection_established(c: connection) print generate_extraction_filename("", c, "test-suffix"); print generate_extraction_filename("", c, ""); } + +event bro_init() + { + print extract_filename_from_content_disposition("attachment; filename=Economy"); + print extract_filename_from_content_disposition("attachment; name=\"US-$ rates\""); + print extract_filename_from_content_disposition("attachment; filename*=iso-8859-1'en'%A3%20rates"); + } \ No newline at end of file From 6a5b8250589e7e9d9b2036fa4fe2230561e5428f Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 9 Jul 2013 14:25:41 -0500 Subject: [PATCH 111/881] Delay file_over_new_connection events until after file_new occurs. --- src/file_analysis/File.cc | 23 +++++++++++++++++++++-- src/file_analysis/File.h | 4 ++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index b5edfaedc9..ed3d2ae9a8 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -75,7 +75,8 @@ void File::StaticInit() File::File(const string& file_id, Connection* conn, analyzer::Tag tag, bool is_orig) : id(file_id), val(0), postpone_timeout(false), first_chunk(true), - missed_bof(false), need_reassembly(false), done(false), analyzers(this) + missed_bof(false), need_reassembly(false), done(false), + did_file_new_event(false), analyzers(this) { StaticInit(); @@ -99,6 +100,7 @@ File::~File() { DBG_LOG(DBG_FILE_ANALYSIS, "Destroying File object %s", id.c_str()); Unref(val); + assert(fonc_queue.empty()); } void File::UpdateLastActivityTime() @@ -135,7 +137,12 @@ void File::UpdateConnectionFields(Connection* conn) val_list* vl = new val_list(); vl->append(val->Ref()); vl->append(conn_val->Ref()); - FileEvent(file_over_new_connection, vl); + + if ( did_file_new_event ) + FileEvent(file_over_new_connection, vl); + else + fonc_queue.push(pair( + file_over_new_connection, vl)); } } @@ -432,6 +439,18 @@ void File::FileEvent(EventHandlerPtr h, val_list* vl) { mgr.QueueEvent(h, vl); + if ( h == file_new ) + { + did_file_new_event = true; + + while ( ! fonc_queue.empty() ) + { + pair p = fonc_queue.front(); + mgr.QueueEvent(p.first, p.second); + fonc_queue.pop(); + } + } + if ( h == file_new || h == file_timeout ) { // immediate feedback is required for these events. diff --git a/src/file_analysis/File.h b/src/file_analysis/File.h index ac54c75bc5..5d967e7356 100644 --- a/src/file_analysis/File.h +++ b/src/file_analysis/File.h @@ -3,7 +3,9 @@ #ifndef FILE_ANALYSIS_FILE_H #define FILE_ANALYSIS_FILE_H +#include #include +#include #include #include "Conn.h" @@ -239,7 +241,9 @@ private: bool missed_bof; /**< Flags that we missed start of file. */ bool need_reassembly; /**< Whether file stream reassembly is needed. */ bool done; /**< If this object is about to be deleted. */ + bool did_file_new_event; /**< Whether the file_new event has been done. */ AnalyzerSet analyzers; /**< A set of attached file analyzer. */ + queue > fonc_queue; struct BOF_Buffer { BOF_Buffer() : full(false), replayed(false), size(0) {} From da4a0bed03dd9b4904716844a271c7074fcc17ee Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 9 Jul 2013 15:55:33 -0500 Subject: [PATCH 112/881] Disable more libmagic builtin checks that override the magic database. --- src/util.cc | 2 +- src/util.h | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/util.cc b/src/util.cc index cff36f0f23..5a63be22cb 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1578,7 +1578,7 @@ void bro_init_magic(magic_t* cookie_ptr, int flags) if ( ! cookie_ptr || *cookie_ptr ) return; - *cookie_ptr = magic_open(flags|MAGIC_NO_CHECK_TOKENS); + *cookie_ptr = magic_open(flags|DISABLE_LIBMAGIC_BUILTIN_CHECKS); // Use our custom database for mime types, but the default database // from libmagic for the verbose file type. diff --git a/src/util.h b/src/util.h index cafa63b7e8..91ed8f2888 100644 --- a/src/util.h +++ b/src/util.h @@ -377,6 +377,23 @@ struct CompareString } }; +// Older versions of libmagic may not define the MAGIC_NO_CHECK_BUILTIN +// convenience macro and other newer versions seem to have a typo that makes +// it unusable, so just make a different one now with all known flags for +// builtin libmagic components that should be disabled so that Bro only +// uses the custom magic database shipped with it. +#define DISABLE_LIBMAGIC_BUILTIN_CHECKS ( \ + MAGIC_NO_CHECK_COMPRESS | \ + MAGIC_NO_CHECK_TAR | \ +/* MAGIC_NO_CHECK_SOFT | */ \ + MAGIC_NO_CHECK_APPTYPE | \ + MAGIC_NO_CHECK_ELF | \ + MAGIC_NO_CHECK_TEXT | \ + MAGIC_NO_CHECK_CDF | \ + MAGIC_NO_CHECK_TOKENS | \ + MAGIC_NO_CHECK_ENCODING \ +) + extern magic_t magic_desc_cookie; extern magic_t magic_mime_cookie; From efe878f3de6999c7b3f28fde79af7e4b43fd1180 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 9 Jul 2013 15:56:47 -0500 Subject: [PATCH 113/881] Make magic for emitting application/msword mime type less strict. --- magic/msdos | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/magic/msdos b/magic/msdos index 59a9d2caac..cc411aeeb7 100644 --- a/magic/msdos +++ b/magic/msdos @@ -349,12 +349,13 @@ # False positive with PPT (also currently this string is too long) #0 string/b \xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3E\x00\x03\x00\xFE\xFF\x09\x00\x06 Microsoft Installer 0 string/b \320\317\021\340\241\261\032\341 Microsoft Office Document +!:mime application/msword #>48 byte 0x1B Excel Document #!:mime application/vnd.ms-excel ->546 string bjbj Microsoft Word Document -!:mime application/msword ->546 string jbjb Microsoft Word Document -!:mime application/msword +#>546 string bjbj Microsoft Word Document +#!:mime application/msword +#>546 string jbjb Microsoft Word Document +#!:mime application/msword 0 string/b \224\246\056 Microsoft Word Document !:mime application/msword From 73155c321bdd82a762b9642b1bcf55f45e784e94 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 9 Jul 2013 15:58:28 -0500 Subject: [PATCH 114/881] Add an is_orig parameter to file_over_new_connection event. --- scripts/base/frameworks/files/main.bro | 2 +- scripts/base/protocols/ftp/files.bro | 4 ++-- scripts/base/protocols/http/entities.bro | 2 +- scripts/base/protocols/http/files.bro | 4 ++-- scripts/base/protocols/irc/files.bro | 4 ++-- scripts/base/protocols/smtp/entities.bro | 2 +- scripts/base/protocols/smtp/files.bro | 4 ++-- src/event.bif | 4 +++- src/file_analysis/File.cc | 5 +++-- src/file_analysis/File.h | 3 ++- src/file_analysis/Manager.cc | 2 +- testing/scripts/file-analysis-test.bro | 2 +- 12 files changed, 21 insertions(+), 17 deletions(-) diff --git a/scripts/base/frameworks/files/main.bro b/scripts/base/frameworks/files/main.bro index d5a3ddee67..8dd07fcb53 100644 --- a/scripts/base/frameworks/files/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -293,7 +293,7 @@ event file_new(f: fa_file) &priority=10 set_info(f); } -event file_over_new_connection(f: fa_file, c: connection) &priority=10 +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=10 { set_info(f); add f$info$conn_uids[c$uid]; diff --git a/scripts/base/protocols/ftp/files.bro b/scripts/base/protocols/ftp/files.bro index a943adff9d..c68717c8a2 100644 --- a/scripts/base/protocols/ftp/files.bro +++ b/scripts/base/protocols/ftp/files.bro @@ -28,7 +28,7 @@ event bro_init() &priority=5 } -event file_over_new_connection(f: fa_file, c: connection) &priority=5 +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 { if ( [c$id$resp_h, c$id$resp_p] !in ftp_data_expected ) return; @@ -37,4 +37,4 @@ event file_over_new_connection(f: fa_file, c: connection) &priority=5 ftp$fuid = f$id; if ( f?$mime_type ) ftp$mime_type = f$mime_type; - } \ No newline at end of file + } diff --git a/scripts/base/protocols/http/entities.bro b/scripts/base/protocols/http/entities.bro index cc852a7e11..fc8ab753ae 100644 --- a/scripts/base/protocols/http/entities.bro +++ b/scripts/base/protocols/http/entities.bro @@ -53,7 +53,7 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr } } -event file_over_new_connection(f: fa_file, c: connection) &priority=5 +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 { if ( f$source == "HTTP" && c$http?$entity ) { diff --git a/scripts/base/protocols/http/files.bro b/scripts/base/protocols/http/files.bro index 44fdc4c1f4..e45ff8cadb 100644 --- a/scripts/base/protocols/http/files.bro +++ b/scripts/base/protocols/http/files.bro @@ -40,7 +40,7 @@ event bro_init() &priority=5 Files::register_protocol(Analyzer::ANALYZER_HTTP, HTTP::get_file_handle); } -event file_over_new_connection(f: fa_file, c: connection) &priority=5 +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 { if ( c?$http ) { @@ -49,4 +49,4 @@ event file_over_new_connection(f: fa_file, c: connection) &priority=5 else c$http$resp_fuids[|c$http$resp_fuids|] = f$id; } - } \ No newline at end of file + } diff --git a/scripts/base/protocols/irc/files.bro b/scripts/base/protocols/irc/files.bro index f4553b534a..8708270bfd 100644 --- a/scripts/base/protocols/irc/files.bro +++ b/scripts/base/protocols/irc/files.bro @@ -27,7 +27,7 @@ event bro_init() &priority=5 Files::register_protocol(Analyzer::ANALYZER_IRC_DATA, IRC::get_file_handle); } -event file_over_new_connection(f: fa_file, c: connection) &priority=5 +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 { if ( [c$id$resp_h, c$id$resp_p] !in dcc_expected_transfers ) return; @@ -38,4 +38,4 @@ event file_over_new_connection(f: fa_file, c: connection) &priority=5 f$info$filename = irc$dcc_file_name; if ( f?$mime_type ) irc$dcc_mime_type = f$mime_type; - } \ No newline at end of file + } diff --git a/scripts/base/protocols/smtp/entities.bro b/scripts/base/protocols/smtp/entities.bro index 067b8acf8e..ec43b39ce1 100644 --- a/scripts/base/protocols/smtp/entities.bro +++ b/scripts/base/protocols/smtp/entities.bro @@ -31,7 +31,7 @@ event mime_begin_entity(c: connection) &priority=10 ++c$smtp_state$mime_depth; } -event file_over_new_connection(f: fa_file, c: connection) &priority=5 +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 { if ( f$source != "SMTP" ) return; diff --git a/scripts/base/protocols/smtp/files.bro b/scripts/base/protocols/smtp/files.bro index e67181d6bc..1cf9ec01e1 100644 --- a/scripts/base/protocols/smtp/files.bro +++ b/scripts/base/protocols/smtp/files.bro @@ -27,8 +27,8 @@ event bro_init() &priority=5 Files::register_protocol(Analyzer::ANALYZER_SMTP, SMTP::get_file_handle); } -event file_over_new_connection(f: fa_file, c: connection) &priority=5 +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 { if ( c?$smtp ) c$smtp$fuids[|c$smtp$fuids|] = f$id; - } \ No newline at end of file + } diff --git a/src/event.bif b/src/event.bif index df22902094..e4d6f8c844 100644 --- a/src/event.bif +++ b/src/event.bif @@ -911,8 +911,10 @@ event file_new%(f: fa_file%); ## ## c: The new connection over which the file is seen being transferred. ## +## is_orig: true if the originator of *c* is the one sending the file. +## ## .. bro:see:: file_new file_timeout file_gap file_state_remove -event file_over_new_connection%(f: fa_file, c: connection%); +event file_over_new_connection%(f: fa_file, c: connection, is_orig: bool%); ## Indicates that file analysis has timed out because no activity was seen ## for the file in a while. diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index ed3d2ae9a8..9a06fa3db9 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -90,7 +90,7 @@ File::File(const string& file_id, Connection* conn, analyzer::Tag tag, // add source, connection, is_orig fields SetSource(analyzer_mgr->GetAnalyzerName(tag)); val->Assign(is_orig_idx, new Val(is_orig, TYPE_BOOL)); - UpdateConnectionFields(conn); + UpdateConnectionFields(conn, is_orig); } UpdateLastActivityTime(); @@ -113,7 +113,7 @@ double File::GetLastActivityTime() const return val->Lookup(last_active_idx)->AsTime(); } -void File::UpdateConnectionFields(Connection* conn) +void File::UpdateConnectionFields(Connection* conn, bool is_orig) { if ( ! conn ) return; @@ -137,6 +137,7 @@ void File::UpdateConnectionFields(Connection* conn) val_list* vl = new val_list(); vl->append(val->Ref()); vl->append(conn_val->Ref()); + vl->append(new Val(is_orig, TYPE_BOOL)); if ( did_file_new_event ) FileEvent(file_over_new_connection, vl); diff --git a/src/file_analysis/File.h b/src/file_analysis/File.h index 5d967e7356..794734d24b 100644 --- a/src/file_analysis/File.h +++ b/src/file_analysis/File.h @@ -173,8 +173,9 @@ protected: * Updates the "conn_ids" and "conn_uids" fields in #val record with the * \c conn_id and UID taken from \a conn. * @param conn the connection over which a part of the file has been seen. + * @param is_orig true if the connection originator is sending the file. */ - void UpdateConnectionFields(Connection* conn); + void UpdateConnectionFields(Connection* conn, bool is_orig); /** * Increment a byte count field of #val record by \a size. diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index 453c6f7902..4e25bb0b0e 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -250,7 +250,7 @@ File* Manager::GetFile(const string& file_id, Connection* conn, rval->UpdateLastActivityTime(); if ( update_conn ) - rval->UpdateConnectionFields(conn); + rval->UpdateConnectionFields(conn, is_orig); } return rval; diff --git a/testing/scripts/file-analysis-test.bro b/testing/scripts/file-analysis-test.bro index 9df640c893..cf2bbf2d59 100644 --- a/testing/scripts/file-analysis-test.bro +++ b/testing/scripts/file-analysis-test.bro @@ -66,7 +66,7 @@ event file_new(f: fa_file) } } -event file_over_new_connection(f: fa_file, c: connection) +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) { print "FILE_OVER_NEW_CONNECTION"; } From 99d604c9b565d18a73c12b91512aebebade7d57d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 10 Jul 2013 14:06:51 -0500 Subject: [PATCH 115/881] Make the custom libmagic database a git submodule. The magic files couldn't be in the root of that repo or else libmagic would abort when it ran in to the .git* files and tried to treat them like magic files, too. --- .gitmodules | 3 + CMakeLists.txt | 7 +- magic | 1 + magic/COPYING | 29 ---- magic/animation | 208 ------------------------ magic/archive | 242 ---------------------------- magic/assembler | 19 --- magic/audio | 149 ----------------- magic/c-lang | 47 ------ magic/cafebabe | 31 ---- magic/commands | 82 ---------- magic/compress | 77 --------- magic/database | 47 ------ magic/diff | 25 --- magic/elf | 43 ----- magic/epoc | 34 ---- magic/filesystems | 12 -- magic/flash | 18 --- magic/fonts | 32 ---- magic/fortran | 7 - magic/frame | 31 ---- magic/gimp | 13 -- magic/gnu | 23 --- magic/gnumeric | 8 - magic/icc | 51 ------ magic/iff | 21 --- magic/images | 255 ------------------------------ magic/java | 16 -- magic/javascript | 17 -- magic/jpeg | 31 ---- magic/kde | 11 -- magic/kml | 30 ---- magic/linux | 22 --- magic/lisp | 42 ----- magic/lua | 17 -- magic/m4 | 7 - magic/macintosh | 21 --- magic/mail.news | 35 ---- magic/make | 16 -- magic/marc21 | 29 ---- magic/matroska | 17 -- magic/misctools | 9 -- magic/msdos | 369 ------------------------------------------- magic/neko | 12 -- magic/pascal | 11 -- magic/pdf | 8 - magic/perl | 26 --- magic/pgp | 27 ---- magic/pkgadd | 7 - magic/printer | 14 -- magic/python | 46 ------ magic/riff | 36 ----- magic/rpm | 12 -- magic/rtf | 9 -- magic/ruby | 28 ---- magic/sc | 7 - magic/sgml | 82 ---------- magic/sniffer | 17 -- magic/tcl | 23 --- magic/tex | 56 ------- magic/troff | 22 --- magic/vorbis | 26 --- magic/warc | 14 -- magic/windows | 19 --- magic/wordprocessors | 43 ----- magic/xwindows | 11 -- 66 files changed, 7 insertions(+), 2753 deletions(-) create mode 160000 magic delete mode 100644 magic/COPYING delete mode 100644 magic/animation delete mode 100644 magic/archive delete mode 100644 magic/assembler delete mode 100644 magic/audio delete mode 100644 magic/c-lang delete mode 100644 magic/cafebabe delete mode 100644 magic/commands delete mode 100644 magic/compress delete mode 100644 magic/database delete mode 100644 magic/diff delete mode 100644 magic/elf delete mode 100644 magic/epoc delete mode 100644 magic/filesystems delete mode 100644 magic/flash delete mode 100644 magic/fonts delete mode 100644 magic/fortran delete mode 100644 magic/frame delete mode 100644 magic/gimp delete mode 100644 magic/gnu delete mode 100644 magic/gnumeric delete mode 100644 magic/icc delete mode 100644 magic/iff delete mode 100644 magic/images delete mode 100644 magic/java delete mode 100644 magic/javascript delete mode 100644 magic/jpeg delete mode 100644 magic/kde delete mode 100644 magic/kml delete mode 100644 magic/linux delete mode 100644 magic/lisp delete mode 100644 magic/lua delete mode 100644 magic/m4 delete mode 100644 magic/macintosh delete mode 100644 magic/mail.news delete mode 100644 magic/make delete mode 100644 magic/marc21 delete mode 100644 magic/matroska delete mode 100644 magic/misctools delete mode 100644 magic/msdos delete mode 100644 magic/neko delete mode 100644 magic/pascal delete mode 100644 magic/pdf delete mode 100644 magic/perl delete mode 100644 magic/pgp delete mode 100644 magic/pkgadd delete mode 100644 magic/printer delete mode 100644 magic/python delete mode 100644 magic/riff delete mode 100644 magic/rpm delete mode 100644 magic/rtf delete mode 100644 magic/ruby delete mode 100644 magic/sc delete mode 100644 magic/sgml delete mode 100644 magic/sniffer delete mode 100644 magic/tcl delete mode 100644 magic/tex delete mode 100644 magic/troff delete mode 100644 magic/vorbis delete mode 100644 magic/warc delete mode 100644 magic/windows delete mode 100644 magic/wordprocessors delete mode 100644 magic/xwindows diff --git a/.gitmodules b/.gitmodules index 95053091cf..2ede715f49 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "cmake"] path = cmake url = git://git.bro-ids.org/cmake +[submodule "magic"] + path = magic + url = git://git.bro.org/bromagic diff --git a/CMakeLists.txt b/CMakeLists.txt index b95b637770..0f64f304b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ get_filename_component(BRO_SCRIPT_INSTALL_PATH ${BRO_SCRIPT_INSTALL_PATH} ABSOLUTE) set(BRO_MAGIC_INSTALL_PATH ${BRO_ROOT_DIR}/share/bro/magic) -set(BRO_MAGIC_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/magic) +set(BRO_MAGIC_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/magic/database) configure_file(bro-path-dev.in ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.sh @@ -201,9 +201,8 @@ CheckOptionalBuildSources(aux/broctl Broctl INSTALL_BROCTL) CheckOptionalBuildSources(aux/bro-aux Bro-Aux INSTALL_AUX_TOOLS) CheckOptionalBuildSources(aux/broccoli Broccoli INSTALL_BROCCOLI) -install(DIRECTORY ./magic/ DESTINATION ${BRO_MAGIC_INSTALL_PATH} FILES_MATCHING - PATTERN "COPYING" EXCLUDE - PATTERN "*" +install(DIRECTORY ./magic/database/ + DESTINATION ${BRO_MAGIC_INSTALL_PATH} ) ######################################################################## diff --git a/magic b/magic new file mode 160000 index 0000000000..e87fe13a7b --- /dev/null +++ b/magic @@ -0,0 +1 @@ +Subproject commit e87fe13a7b776182ffc8c75076d42702f5c28fed diff --git a/magic/COPYING b/magic/COPYING deleted file mode 100644 index 7d2bf1e711..0000000000 --- a/magic/COPYING +++ /dev/null @@ -1,29 +0,0 @@ -# $File: LEGAL.NOTICE,v 1.15 2006/05/03 18:48:33 christos Exp $ -# Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995. -# Software written by Ian F. Darwin and others; -# maintained 1994- Christos Zoulas. -# -# This software is not subject to any export provision of the United States -# Department of Commerce, and may be exported to any country or planet. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice immediately at the beginning of the file, without modification, -# this list of conditions, and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. diff --git a/magic/animation b/magic/animation deleted file mode 100644 index 0cec03d511..0000000000 --- a/magic/animation +++ /dev/null @@ -1,208 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: animation,v 1.47 2013/02/06 14:18:52 christos Exp $ -# animation: file(1) magic for animation/movie formats -# -# animation formats -# MPEG, FLI, DL originally from vax@ccwf.cc.utexas.edu (VaX#n8) -# FLC, SGI, Apple originally from Daniel Quinlan (quinlan@yggdrasil.com) - -# SGI and Apple formats -0 string MOVI Silicon Graphics movie file -!:mime video/x-sgi-movie -4 string moov Apple QuickTime -!:mime video/quicktime -4 string mdat Apple QuickTime movie (unoptimized) -!:mime video/quicktime -#4 string wide Apple QuickTime movie (unoptimized) -#!:mime video/quicktime -#4 string skip Apple QuickTime movie (modified) -#!:mime video/quicktime -#4 string free Apple QuickTime movie (modified) -#!:mime video/quicktime -4 string idsc Apple QuickTime image (fast start) -!:mime image/x-quicktime -#4 string idat Apple QuickTime image (unoptimized) -#!:mime image/x-quicktime -4 string pckg Apple QuickTime compressed archive -!:mime application/x-quicktime-player -4 string/W jP JPEG 2000 image -!:mime image/jp2 -4 string ftyp ISO Media ->8 string isom \b, MPEG v4 system, version 1 -!:mime video/mp4 ->8 string mp41 \b, MPEG v4 system, version 1 -!:mime video/mp4 ->8 string mp42 \b, MPEG v4 system, version 2 -!:mime video/mp4 ->8 string/W jp2 \b, JPEG 2000 -!:mime image/jp2 ->8 string 3ge \b, MPEG v4 system, 3GPP -!:mime video/3gpp ->8 string 3gg \b, MPEG v4 system, 3GPP -!:mime video/3gpp ->8 string 3gp \b, MPEG v4 system, 3GPP -!:mime video/3gpp ->8 string 3gs \b, MPEG v4 system, 3GPP -!:mime video/3gpp ->8 string 3g2 \b, MPEG v4 system, 3GPP2 -!:mime video/3gpp2 ->8 string mmp4 \b, MPEG v4 system, 3GPP Mobile -!:mime video/mp4 ->8 string avc1 \b, MPEG v4 system, 3GPP JVT AVC -!:mime video/3gpp ->8 string/W M4A \b, MPEG v4 system, iTunes AAC-LC -!:mime audio/mp4 ->8 string/W M4V \b, MPEG v4 system, iTunes AVC-LC -!:mime video/mp4 ->8 string/W qt \b, Apple QuickTime movie -!:mime video/quicktime - -# MPEG sequences -# Scans for all common MPEG header start codes -0 belong&0xFFFFFF00 0x00000100 ->3 byte 0xBA MPEG sequence -!:mime video/mpeg -# GRR too general as it catches also FoxPro Memo example NG.FPT ->3 byte 0xB0 MPEG sequence, v4 -!:mime video/mpeg4-generic ->3 byte 0xB5 MPEG sequence, v4 -!:mime video/mpeg4-generic ->3 byte 0xB3 MPEG sequence -!:mime video/mpeg - -# MPEG ADTS Audio (*.mpx/mxa/aac) -# from dreesen@math.fu-berlin.de -# modified to fully support MPEG ADTS - -# MP3, M1A -# modified by Joerg Jenderek -# GRR the original test are too common for many DOS files -# so don't accept as MP3 until we've tested the rate -0 beshort&0xFFFE 0xFFFA -# rates ->2 byte&0xF0 0x10 MPEG ADTS, layer III, v1, 32 kbps -!:mime audio/mpeg ->2 byte&0xF0 0x20 MPEG ADTS, layer III, v1, 40 kbps -!:mime audio/mpeg ->2 byte&0xF0 0x30 MPEG ADTS, layer III, v1, 48 kbps -!:mime audio/mpeg ->2 byte&0xF0 0x40 MPEG ADTS, layer III, v1, 56 kbps -!:mime audio/mpeg ->2 byte&0xF0 0x50 MPEG ADTS, layer III, v1, 64 kbps -!:mime audio/mpeg ->2 byte&0xF0 0x60 MPEG ADTS, layer III, v1, 80 kbps -!:mime audio/mpeg ->2 byte&0xF0 0x70 MPEG ADTS, layer III, v1, 96 kbps -!:mime audio/mpeg ->2 byte&0xF0 0x80 MPEG ADTS, layer III, v1, 112 kbps -!:mime audio/mpeg ->2 byte&0xF0 0x90 MPEG ADTS, layer III, v1, 128 kbps -!:mime audio/mpeg ->2 byte&0xF0 0xA0 MPEG ADTS, layer III, v1, 160 kbps -!:mime audio/mpeg ->2 byte&0xF0 0xB0 MPEG ADTS, layer III, v1, 192 kbps -!:mime audio/mpeg ->2 byte&0xF0 0xC0 MPEG ADTS, layer III, v1, 224 kbps -!:mime audio/mpeg ->2 byte&0xF0 0xD0 MPEG ADTS, layer III, v1, 256 kbps -!:mime audio/mpeg ->2 byte&0xF0 0xE0 MPEG ADTS, layer III, v1, 320 kbps -!:mime audio/mpeg - -# MP2, M1A -0 beshort&0xFFFE 0xFFFC MPEG ADTS, layer II, v1 -!:mime audio/mpeg - -# MP3, M2A -0 beshort&0xFFFE 0xFFF2 MPEG ADTS, layer III, v2 -!:mime audio/mpeg - -# MPA, M2A -0 beshort&0xFFFE 0xFFF6 MPEG ADTS, layer I, v2 -!:mime audio/mpeg - -# MP3, M25A -0 beshort&0xFFFE 0xFFE2 MPEG ADTS, layer III, v2.5 -!:mime audio/mpeg - -# Stored AAC streams (instead of the MP4 format) -0 string ADIF MPEG ADIF, AAC -!:mime audio/x-hx-aac-adif - -# Live or stored single AAC stream (used with MPEG-2 systems) -0 beshort&0xFFF6 0xFFF0 MPEG ADTS, AAC -!:mime audio/x-hx-aac-adts - -# Live MPEG-4 audio streams (instead of RTP FlexMux) -0 beshort&0xFFE0 0x56E0 MPEG-4 LOAS -!:mime audio/x-mp4a-latm - -# This magic isn't strong enough (matches plausible ISO-8859-1 text) -#0 beshort 0x4DE1 MPEG-4 LO-EP audio stream -#!:mime audio/x-mp4a-latm - -# Summary: FLI animation format -# Created by: Daniel Quinlan -# Modified by (1): Abel Cheung (avoid over-generic detection) -4 leshort 0xAF11 -# standard FLI always has 320x200 resolution and 8 bit color ->8 leshort 320 ->>10 leshort 200 ->>>12 leshort 8 FLI animation, 320x200x8 -!:mime video/x-fli - -# Summary: FLC animation format -# Created by: Daniel Quinlan -# Modified by (1): Abel Cheung (avoid over-generic detection) -4 leshort 0xAF12 -# standard FLC always use 8 bit color ->12 leshort 8 FLC animation -!:mime video/x-flc - -# Microsoft Advanced Streaming Format (ASF) -0 belong 0x3026b275 Microsoft ASF -!:mime video/x-ms-asf - -# MNG Video Format, -0 string \x8aMNG MNG video data, -!:mime video/x-mng - -# JNG Video Format, -0 string \x8bJNG JNG video data, -!:mime video/x-jng - -# VRML (Virtual Reality Modelling Language) -0 string/w #VRML\ V1.0\ ascii VRML 1 file -!:mime model/vrml -0 string/w #VRML\ V2.0\ utf8 ISO/IEC 14772 VRML 97 file -!:mime model/vrml - -# X3D (Extensible 3D) [http://www.web3d.org/specifications/x3d-3.0.dtd] -# From Michel Briand -0 string/t \20 search/1000/cw \4 byte &0x40 -!:mime video/mp2p ->4 byte ^0x40 -!:mime video/mpeg -0 belong 0x000001BB -!:mime video/mpeg -0 belong 0x000001B0 -!:mime video/mp4v-es -0 belong 0x000001B5 -!:mime video/mp4v-es -0 belong 0x000001B3 -!:mime video/mpv -0 belong&0xFF5FFF1F 0x47400010 -!:mime video/mp2t -0 belong 0x00000001 ->4 byte&0x1F 0x07 -!:mime video/h264 diff --git a/magic/archive b/magic/archive deleted file mode 100644 index 35cbef4012..0000000000 --- a/magic/archive +++ /dev/null @@ -1,242 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: archive,v 1.78 2013/02/06 14:18:52 christos Exp $ -# archive: file(1) magic for archive formats (see also "msdos" for self- -# extracting compressed archives) -# -# cpio, ar, arc, arj, hpack, lha/lharc, rar, squish, uc2, zip, zoo, etc. -# pre-POSIX "tar" archives are handled in the C code. - -# POSIX tar archives -257 string ustar\0 POSIX tar archive -!:mime application/x-tar # encoding: posix -257 string ustar\040\040\0 GNU tar archive -!:mime application/x-tar # encoding: gnu - -# cpio archives -# -# Yes, the top two "cpio archive" formats *are* supposed to just be "short". -# The idea is to indicate archives produced on machines with the same -# byte order as the machine running "file" with "cpio archive", and -# to indicate archives produced on machines with the opposite byte order -# from the machine running "file" with "byte-swapped cpio archive". -# -# The SVR4 "cpio(4)" hints that there are additional formats, but they -# are defined as "short"s; I think all the new formats are -# character-header formats and thus are strings, not numbers. -0 short 070707 cpio archive -!:mime application/x-cpio -0 short 0143561 byte-swapped cpio archive -!:mime application/x-cpio # encoding: swapped - -# -# System V Release 1 portable(?) archive format. -# -0 string = System V Release 1 ar archive -!:mime application/x-archive - -# -# Debian package; it's in the portable archive format, and needs to go -# before the entry for regular portable archives, as it's recognized as -# a portable archive whose first member has a name beginning with -# "debian". -# -0 string =!\ndebian -!:mime application/x-debian-package - -# -# MIPS archive; they're in the portable archive format, and need to go -# before the entry for regular portable archives, as it's recognized as -# a portable archive whose first member has a name beginning with -# "__________E". -# -0 string =!\n__________E MIPS archive -!:mime application/x-archive - -# -# BSD/SVR2-and-later portable archive formats. -# -0 string =! current ar archive -!:mime application/x-archive - -# ARC archiver, from Daniel Quinlan (quinlan@yggdrasil.com) -# -# The first byte is the magic (0x1a), byte 2 is the compression type for -# the first file (0x01 through 0x09), and bytes 3 to 15 are the MS-DOS -# filename of the first file (null terminated). Since some types collide -# we only test some types on basis of frequency: 0x08 (83%), 0x09 (5%), -# 0x02 (5%), 0x03 (3%), 0x04 (2%), 0x06 (2%). 0x01 collides with terminfo. -0 lelong&0x8080ffff 0x0000081a ARC archive data, dynamic LZW -!:mime application/x-arc -0 lelong&0x8080ffff 0x0000091a ARC archive data, squashed -!:mime application/x-arc -0 lelong&0x8080ffff 0x0000021a ARC archive data, uncompressed -!:mime application/x-arc -0 lelong&0x8080ffff 0x0000031a ARC archive data, packed -!:mime application/x-arc -0 lelong&0x8080ffff 0x0000041a ARC archive data, squeezed -!:mime application/x-arc -0 lelong&0x8080ffff 0x0000061a ARC archive data, crunched -!:mime application/x-arc -# [JW] stuff taken from idarc, obviously ARC successors: -0 lelong&0x8080ffff 0x00000a1a PAK archive data -!:mime application/x-arc -0 lelong&0x8080ffff 0x0000141a ARC+ archive data -!:mime application/x-arc -0 lelong&0x8080ffff 0x0000481a HYP archive data -!:mime application/x-arc - -# ARJ archiver (jason@jarthur.Claremont.EDU) -0 leshort 0xea60 ARJ archive data -!:mime application/x-arj - -# LHARC/LHA archiver (Greg Roelofs, newt@uchicago.edu) -2 string -lh0- LHarc 1.x/ARX archive data [lh0] -!:mime application/x-lharc -2 string -lh1- LHarc 1.x/ARX archive data [lh1] -!:mime application/x-lharc -2 string -lz4- LHarc 1.x archive data [lz4] -!:mime application/x-lharc -2 string -lz5- LHarc 1.x archive data [lz5] -!:mime application/x-lharc -# [never seen any but the last; -lh4- reported in comp.compression:] -2 string -lzs- LHa/LZS archive data [lzs] -!:mime application/x-lha -2 string -lh\40- LHa 2.x? archive data [lh ] -!:mime application/x-lha -2 string -lhd- LHa 2.x? archive data [lhd] -!:mime application/x-lha -2 string -lh2- LHa 2.x? archive data [lh2] -!:mime application/x-lha -2 string -lh3- LHa 2.x? archive data [lh3] -!:mime application/x-lha -2 string -lh4- LHa (2.x) archive data [lh4] -!:mime application/x-lha -2 string -lh5- LHa (2.x) archive data [lh5] -!:mime application/x-lha -2 string -lh6- LHa (2.x) archive data [lh6] -!:mime application/x-lha -2 string -lh7- LHa (2.x)/LHark archive data [lh7] -!:mime application/x-lha - -# RAR archiver (Greg Roelofs, newt@uchicago.edu) -0 string Rar! RAR archive data, -!:mime application/x-rar - -# PKZIP multi-volume archive -0 string PK\x07\x08PK\x03\x04 Zip multi-volume archive data, at least PKZIP v2.50 to extract -!:mime application/zip - -# Zip archives (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu) -0 string PK\003\004 - -# Specialised zip formats which start with a member named 'mimetype' -# (stored uncompressed, with no 'extra field') containing the file's MIME type. -# Check for have 8-byte name, 0-byte extra field, name "mimetype", and -# contents starting with "application/": ->26 string \x8\0\0\0mimetypeapplication/ - -# OpenDocument formats (for OpenOffice 2.x / StarOffice >= 8) -# http://lists.oasis-open.org/archives/office/200505/msg00006.html -# (mimetype contains "application/vnd.oasis.opendocument.") ->>50 string vnd.oasis.opendocument. OpenDocument ->>>73 string text ->>>>77 byte !0x2d Text -!:mime application/vnd.oasis.opendocument.text ->>>>77 string -template Text Template -!:mime application/vnd.oasis.opendocument.text-template ->>>>77 string -web HTML Document Template -!:mime application/vnd.oasis.opendocument.text-web ->>>>77 string -master Master Document -!:mime application/vnd.oasis.opendocument.text-master ->>>73 string graphics ->>>>81 byte !0x2d Drawing -!:mime application/vnd.oasis.opendocument.graphics ->>>>81 string -template Template -!:mime application/vnd.oasis.opendocument.graphics-template ->>>73 string presentation ->>>>85 byte !0x2d Presentation -!:mime application/vnd.oasis.opendocument.presentation ->>>>85 string -template Template -!:mime application/vnd.oasis.opendocument.presentation-template ->>>73 string spreadsheet ->>>>84 byte !0x2d Spreadsheet -!:mime application/vnd.oasis.opendocument.spreadsheet ->>>>84 string -template Template -!:mime application/vnd.oasis.opendocument.spreadsheet-template ->>>73 string chart ->>>>78 byte !0x2d Chart -!:mime application/vnd.oasis.opendocument.chart ->>>>78 string -template Template -!:mime application/vnd.oasis.opendocument.chart-template ->>>73 string formula ->>>>80 byte !0x2d Formula -!:mime application/vnd.oasis.opendocument.formula ->>>>80 string -template Template -!:mime application/vnd.oasis.opendocument.formula-template ->>>73 string database Database -!:mime application/vnd.oasis.opendocument.database ->>>73 string image ->>>>78 byte !0x2d Image -!:mime application/vnd.oasis.opendocument.image ->>>>78 string -template Template -!:mime application/vnd.oasis.opendocument.image-template - -# EPUB (OEBPS) books using OCF (OEBPS Container Format) -# http://www.idpf.org/ocf/ocf1.0/download/ocf10.htm, section 4. -# From: Ralf Brown ->0x1E string mimetypeapplication/epub+zip EPUB document -!:mime application/epub+zip - -# Catch other ZIP-with-mimetype formats -# In a ZIP file, the bytes immediately after a member's contents are -# always "PK". The 2 regex rules here print the "mimetype" member's -# contents up to the first 'P'. Luckily, most MIME types don't contain -# any capital 'P's. This is a kludge. -# (mimetype contains "application/") ->>50 string !epub+zip ->>>50 string !vnd.oasis.opendocument. ->>>>50 string !vnd.sun.xml. ->>>>>50 string !vnd.kde. ->>>>>>38 regex [!-OQ-~]+ Zip data (MIME type "%s"?) -!:mime application/zip -# (mimetype contents other than "application/*") ->26 string \x8\0\0\0mimetype ->>38 string !application/ ->>>38 regex [!-OQ-~]+ Zip data (MIME type "%s"?) -!:mime application/zip - -# Java Jar files ->(26.s+30) leshort 0xcafe Java Jar file data (zip) -!:mime application/jar - -# Generic zip archives (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu) -# Next line excludes specialized formats: ->(26.s+30) leshort !0xcafe ->>26 string !\x8\0\0\0mimetype Zip archive data -!:mime application/zip - -# Zoo archiver -20 lelong 0xfdc4a7dc Zoo archive data -!:mime application/x-zoo - -# Shell archives -10 string #\ This\ is\ a\ shell\ archive shell archive text -!:mime application/octet-stream - -# Felix von Leitner -0 string d8:announce BitTorrent file -!:mime application/x-bittorrent - -# EET archive -# From: Tilman Sauerbeck -0 belong 0x1ee7ff00 EET archive -!:mime application/x-eet - -# Symbian installation files -# http://www.thouky.co.uk/software/psifs/sis.html -# http://developer.symbian.com/main/downloads/papers/SymbianOSv91/softwareinstallsis.pdf -8 lelong 0x10000419 Symbian installation file -!:mime application/vnd.symbian.install -0 lelong 0x10201A7A Symbian installation file (Symbian OS 9.x) -!:mime x-epoc/x-sisx-app diff --git a/magic/assembler b/magic/assembler deleted file mode 100644 index 242b6e19e2..0000000000 --- a/magic/assembler +++ /dev/null @@ -1,19 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: assembler,v 1.3 2013/01/04 17:23:28 christos Exp $ -# make: file(1) magic for assembler source -# -0 regex \^[\020\t]*\\.asciiz assembler source text -!:mime text/x-asm -0 regex \^[\020\t]*\\.byte assembler source text -!:mime text/x-asm -0 regex \^[\020\t]*\\.even assembler source text -!:mime text/x-asm -0 regex \^[\020\t]*\\.globl assembler source text -!:mime text/x-asm -0 regex \^[\020\t]*\\.text assembler source text -!:mime text/x-asm -0 regex \^[\020\t]*\\.file assembler source text -!:mime text/x-asm -0 regex \^[\020\t]*\\.type assembler source text -!:mime text/x-asm diff --git a/magic/audio b/magic/audio deleted file mode 100644 index 75a9dc536c..0000000000 --- a/magic/audio +++ /dev/null @@ -1,149 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: audio,v 1.65 2012/10/31 13:38:40 christos Exp $ -# audio: file(1) magic for sound formats (see also "iff") -# -# Jan Nicolai Langfeldt (janl@ifi.uio.no), Dan Quinlan (quinlan@yggdrasil.com), -# and others -# - -# Sun/NeXT audio data -0 string .snd Sun/NeXT audio data: ->12 belong 1 8-bit ISDN mu-law, -!:mime audio/basic ->12 belong 2 8-bit linear PCM [REF-PCM], -!:mime audio/basic ->12 belong 3 16-bit linear PCM, -!:mime audio/basic ->12 belong 4 24-bit linear PCM, -!:mime audio/basic ->12 belong 5 32-bit linear PCM, -!:mime audio/basic ->12 belong 6 32-bit IEEE floating point, -!:mime audio/basic ->12 belong 7 64-bit IEEE floating point, -!:mime audio/basic ->12 belong 23 8-bit ISDN mu-law compressed (CCITT G.721 ADPCM voice enc.), -!:mime audio/x-adpcm - -# DEC systems (e.g. DECstation 5000) use a variant of the Sun/NeXT format -# that uses little-endian encoding and has a different magic number -0 lelong 0x0064732E DEC audio data: ->12 lelong 1 8-bit ISDN mu-law, -!:mime audio/x-dec-basic ->12 lelong 2 8-bit linear PCM [REF-PCM], -!:mime audio/x-dec-basic ->12 lelong 3 16-bit linear PCM, -!:mime audio/x-dec-basic ->12 lelong 4 24-bit linear PCM, -!:mime audio/x-dec-basic ->12 lelong 5 32-bit linear PCM, -!:mime audio/x-dec-basic ->12 lelong 6 32-bit IEEE floating point, -!:mime audio/x-dec-basic ->12 lelong 7 64-bit IEEE floating point, -!:mime audio/x-dec-basic ->12 lelong 23 8-bit ISDN mu-law compressed (CCITT G.721 ADPCM voice enc.), -!:mime audio/x-dec-basic - -# Creative Labs AUDIO stuff -0 string MThd Standard MIDI data -!:mime audio/midi - -0 string CTMF Creative Music (CMF) data -!:mime audio/x-unknown -0 string SBI SoundBlaster instrument data -!:mime audio/x-unknown -0 string Creative\ Voice\ File Creative Labs voice data -!:mime audio/x-unknown - -# Real Audio (Magic .ra\0375) -0 belong 0x2e7261fd RealAudio sound file -!:mime audio/x-pn-realaudio -0 string .RMF\0\0\0 RealMedia file -!:mime application/vnd.rn-realmedia - -# mime types according to http://www.geocities.com/nevilo/mod.htm: -# audio/it .it -# audio/x-zipped-it .itz -# audio/xm fasttracker modules -# audio/x-s3m screamtracker modules -# audio/s3m screamtracker modules -# audio/x-zipped-mod mdz -# audio/mod mod -# audio/x-mod All modules (mod, s3m, 669, mtm, med, xm, it, mdz, stm, itz, xmz, s3z) - -# -# Taken from loader code from mikmod version 2.14 -# by Steve McIntyre (stevem@chiark.greenend.org.uk) -# added title printing on 2003-06-24 -0 string MAS_UTrack_V00 ->14 string >/0 ultratracker V1.%.1s module sound data -!:mime audio/x-mod -#audio/x-tracker-module - -0 string Extended\ Module: Fasttracker II module sound data -!:mime audio/x-mod -#audio/x-tracker-module - -21 string/c =!SCREAM! Screamtracker 2 module sound data -!:mime audio/x-mod -#audio/x-screamtracker-module -21 string BMOD2STM Screamtracker 2 module sound data -!:mime audio/x-mod -#audio/x-screamtracker-module -1080 string M.K. 4-channel Protracker module sound data -!:mime audio/x-mod -#audio/x-protracker-module -1080 string M!K! 4-channel Protracker module sound data -!:mime audio/x-mod -#audio/x-protracker-module -1080 string FLT4 4-channel Startracker module sound data -!:mime audio/x-mod -#audio/x-startracker-module -1080 string FLT8 8-channel Startracker module sound data -!:mime audio/x-mod -#audio/x-startracker-module -1080 string 4CHN 4-channel Fasttracker module sound data -!:mime audio/x-mod -#audio/x-fasttracker-module -1080 string 6CHN 6-channel Fasttracker module sound data -!:mime audio/x-mod -#audio/x-fasttracker-module -1080 string 8CHN 8-channel Fasttracker module sound data -!:mime audio/x-mod -#audio/x-fasttracker-module -1080 string CD81 8-channel Octalyser module sound data -!:mime audio/x-mod -#audio/x-octalysertracker-module -1080 string OKTA 8-channel Octalyzer module sound data -!:mime audio/x-mod -#audio/x-octalysertracker-module -# Not good enough. -#1082 string CH -#>1080 string >/0 %.2s-channel Fasttracker "oktalyzer" module sound data -1080 string 16CN 16-channel Taketracker module sound data -!:mime audio/x-mod -#audio/x-taketracker-module -1080 string 32CN 32-channel Taketracker module sound data -!:mime audio/x-mod -#audio/x-taketracker-module - -# Impulse tracker module (audio/x-it) -0 string IMPM Impulse Tracker module sound data - -!:mime audio/x-mod - -# Free lossless audio codec -# From: Przemyslaw Augustyniak -0 string fLaC FLAC audio bitstream data -!:mime audio/x-flac - -# Monkey's Audio compressed audio format (.ape) -# From danny.milo@gmx.net (Danny Milosavljevic) -# New version from Abel Cheung -0 string MAC\040 Monkey's Audio compressed format -!:mime audio/x-ape - -# musepak support From: "Jiri Pejchal" -0 string MP+ Musepack audio -!:mime audio/x-musepack diff --git a/magic/c-lang b/magic/c-lang deleted file mode 100644 index 525dc6b599..0000000000 --- a/magic/c-lang +++ /dev/null @@ -1,47 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: c-lang,v 1.16 2011/12/09 08:02:16 rrt Exp $ -# c-lang: file(1) magic for C and related languages programs -# - -# BCPL -0 search/8192 "libhdr" BCPL source text -!:mime text/x-bcpl -0 search/8192 "LIBHDR" BCPL source text -!:mime text/x-bcpl - -# C -0 regex \^#include C source text -!:mime text/x-c -0 regex \^char C source text -!:mime text/x-c -0 regex \^double C source text -!:mime text/x-c -0 regex \^extern C source text -!:mime text/x-c -0 regex \^float C source text -!:mime text/x-c -0 regex \^struct C source text -!:mime text/x-c -0 regex \^union C source text -!:mime text/x-c -0 search/8192 main( C source text -!:mime text/x-c - -# C++ -# The strength of these rules is increased so they beat the C rules above -0 regex \^template C++ source text -!:strength + 5 -!:mime text/x-c++ -0 regex \^virtual C++ source text -!:strength + 5 -!:mime text/x-c++ -0 regex \^class C++ source text -!:strength + 5 -!:mime text/x-c++ -0 regex \^public: C++ source text -!:strength + 5 -!:mime text/x-c++ -0 regex \^private: C++ source text -!:strength + 5 -!:mime text/x-c++ diff --git a/magic/cafebabe b/magic/cafebabe deleted file mode 100644 index 29fefd5f1e..0000000000 --- a/magic/cafebabe +++ /dev/null @@ -1,31 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: cafebabe,v 1.13 2013/02/26 21:04:38 christos Exp $ -# Cafe Babes unite! -# -# Since Java bytecode and Mach-O universal binaries have the same magic number, -# the test must be performed in the same "magic" sequence to get both right. -# The long at offset 4 in a Mach-O universal binary tells the number of -# architectures; the short at offset 4 in a Java bytecode file is the JVM minor -# version and the short at offset 6 is the JVM major version. Since there are only -# only 18 labeled Mach-O architectures at current, and the first released -# Java class format was version 43.0, we can safely choose any number -# between 18 and 39 to test the number of architectures against -# (and use as a hack). Let's not use 18, because the Mach-O people -# might add another one or two as time goes by... -# -### JAVA START ### -0 belong 0xcafebabe -!:mime application/x-java-applet - -0 belong 0xcafed00d JAR compressed with pack200, ->5 byte x version %d. ->4 byte x \b%d -!:mime application/x-java-pack200 - -0 belong 0xcafed00d JAR compressed with pack200, ->5 byte x version %d. ->4 byte x \b%d -!:mime application/x-java-pack200 - -### JAVA END ### diff --git a/magic/commands b/magic/commands deleted file mode 100644 index 6ad7699c5e..0000000000 --- a/magic/commands +++ /dev/null @@ -1,82 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: commands,v 1.44 2013/02/05 15:20:47 christos Exp $ -# commands: file(1) magic for various shells and interpreters -# -#0 string/w : shell archive or script for antique kernel text -0 string/wt #!\ /bin/sh POSIX shell script text executable -!:mime text/x-shellscript -0 string/wt #!\ /bin/csh C shell script text executable -!:mime text/x-shellscript -# korn shell magic, sent by George Wu, gwu@clyde.att.com -0 string/wt #!\ /bin/ksh Korn shell script text executable -!:mime text/x-shellscript -0 string/wt #!\ /bin/tcsh Tenex C shell script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/bin/tcsh Tenex C shell script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/local/tcsh Tenex C shell script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/local/bin/tcsh Tenex C shell script text executable -!:mime text/x-shellscript - -# -# zsh/ash/ae/nawk/gawk magic from cameron@cs.unsw.oz.au (Cameron Simpson) -0 string/wt #!\ /bin/zsh Paul Falstad's zsh script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/bin/zsh Paul Falstad's zsh script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/local/bin/zsh Paul Falstad's zsh script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/local/bin/ash Neil Brown's ash script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/local/bin/ae Neil Brown's ae script text executable -!:mime text/x-shellscript -0 string/wt #!\ /bin/nawk new awk script text executable -!:mime text/x-nawk -0 string/wt #!\ /usr/bin/nawk new awk script text executable -!:mime text/x-nawk -0 string/wt #!\ /usr/local/bin/nawk new awk script text executable -!:mime text/x-nawk -0 string/wt #!\ /bin/gawk GNU awk script text executable -!:mime text/x-gawk -0 string/wt #!\ /usr/bin/gawk GNU awk script text executable -!:mime text/x-gawk -0 string/wt #!\ /usr/local/bin/gawk GNU awk script text executable -!:mime text/x-gawk -# -0 string/wt #!\ /bin/awk awk script text executable -!:mime text/x-awk -0 string/wt #!\ /usr/bin/awk awk script text executable -!:mime text/x-awk - -# bash shell magic, from Peter Tobias (tobias@server.et-inf.fho-emden.de) -0 string/wt #!\ /bin/bash Bourne-Again shell script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/bin/bash Bourne-Again shell script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/local/bash Bourne-Again shell script text executable -!:mime text/x-shellscript -0 string/wt #!\ /usr/local/bin/bash Bourne-Again shell script text executable -!:mime text/x-shellscript - -# PHP scripts -# Ulf Harnhammar -0 search/1/c = -0 string =24 regex [0-9.]+ \b, version %s -!:mime text/x-php diff --git a/magic/compress b/magic/compress deleted file mode 100644 index f2598b783f..0000000000 --- a/magic/compress +++ /dev/null @@ -1,77 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: compress,v 1.48 2011/12/07 18:39:43 christos Exp $ -# compress: file(1) magic for pure-compression formats (no archives) -# -# compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, etc. -# -# Formats for various forms of compressed data -# Formats for "compress" proper have been moved into "compress.c", -# because it tries to uncompress it to figure out what's inside. - -# standard unix compress -0 string \037\235 compress'd data -!:mime application/x-compress -!:apple LZIVZIVU - -# gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver) -# Edited by Chris Chittleborough , March 2002 -# * Original filename is only at offset 10 if "extra field" absent -# * Produce shorter output - notably, only report compression methods -# other than 8 ("deflate", the only method defined in RFC 1952). -0 string \037\213 gzip compressed data -!:mime application/x-gzip - -# packed data, Huffman (minimum redundancy) codes on a byte-by-byte basis -0 string \037\036 packed data -!:mime application/octet-stream - -# -# This magic number is byte-order-independent. -0 short 0x1f1f old packed data -!:mime application/octet-stream - -# XXX - why *two* entries for "compacted data", one of which is -# byte-order independent, and one of which is byte-order dependent? -# -0 short 0x1fff compacted data -!:mime application/octet-stream -# This string is valid for SunOS (BE) and a matching "short" is listed -# in the Ultrix (LE) magic file. -0 string \377\037 compacted data -!:mime application/octet-stream -0 short 0145405 huf output -!:mime application/octet-stream - -# bzip2 -0 string BZh bzip2 compressed data -!:mime application/x-bzip2 - -# lzip -0 string LZIP lzip compressed data -!:mime application/x-lzip - -# 7-zip archiver, from Thomas Klausner (wiz@danbala.tuwien.ac.at) -# http://www.7-zip.org or DOC/7zFormat.txt -# -0 string 7z\274\257\047\034 7-zip archive data, ->6 byte x version %d ->7 byte x \b.%d -!:mime application/x-7z-compressed - -# Type: LZMA -0 lelong&0xffffff =0x5d ->12 leshort =0xff LZMA compressed data, ->>5 lequad =0xffffffffffffffff streamed ->>5 lequad !0xffffffffffffffff non-streamed, size %lld -!:mime application/x-lzma - -# http://tukaani.org/xz/xz-file-format.txt -0 ustring \xFD7zXZ\x00 XZ compressed data -!:mime application/x-xz - -# https://github.com/ckolivas/lrzip/blob/master/doc/magic.header.txt -0 string LRZI LRZIP compressed data ->4 byte x - version %d ->5 byte x \b.%d -!:mime application/x-lrzip diff --git a/magic/database b/magic/database deleted file mode 100644 index f1c09c0629..0000000000 --- a/magic/database +++ /dev/null @@ -1,47 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: database,v 1.32 2013/02/06 14:18:52 christos Exp $ -# database: file(1) magic for various databases -# -# extracted from header/code files by Graeme Wilford (eep2gw@ee.surrey.ac.uk) -# -# -# GDBM magic numbers -# Will be maintained as part of the GDBM distribution in the future. -# -0 belong 0x13579ace GNU dbm 1.x or ndbm database, big endian -!:mime application/x-gdbm -0 lelong 0x13579ace GNU dbm 1.x or ndbm database, little endian -!:mime application/x-gdbm -0 string GDBM GNU dbm 2.x database -!:mime application/x-gdbm -# -# Berkeley DB -# -# Ian Darwin's file /etc/magic files: big/little-endian version. -# -# Hash 1.85/1.86 databases store metadata in network byte order. -# Btree 1.85/1.86 databases store the metadata in host byte order. -# Hash and Btree 2.X and later databases store the metadata in host byte order. - -0 long 0x00061561 Berkeley DB -!:mime application/x-dbm - -# MS Access database -4 string Standard\ Jet\ DB Microsoft Access Database -!:mime application/x-msaccess -4 string Standard\ ACE\ DB Microsoft Access Database -!:mime application/x-msaccess - -# Tokyo Cabinet magic data -# http://tokyocabinet.sourceforge.net/index.html -0 string ToKyO\ CaBiNeT\n Tokyo Cabinet ->14 string x \b (%s) ->32 byte 0 \b, Hash -!:mime application/x-tokyocabinet-hash ->32 byte 1 \b, B+ tree -!:mime application/x-tokyocabinet-btree ->32 byte 2 \b, Fixed-length -!:mime application/x-tokyocabinet-fixed ->32 byte 3 \b, Table -!:mime application/x-tokyocabinet-table diff --git a/magic/diff b/magic/diff deleted file mode 100644 index b6504f17a0..0000000000 --- a/magic/diff +++ /dev/null @@ -1,25 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: diff,v 1.13 2012/06/16 14:43:36 christos Exp $ -# diff: file(1) magic for diff(1) output -# -0 search/1 diff\ diff output text -!:mime text/x-diff -0 search/1 ***\ diff output text -!:mime text/x-diff -0 search/1 Only\ in\ diff output text -!:mime text/x-diff -0 search/1 Common\ subdirectories:\ diff output text -!:mime text/x-diff - -0 search/1 Index: RCS/CVS diff output text -!:mime text/x-diff - -# unified diff -0 search/4096 ---\ ->&0 search/1024 \n ->>&0 search/1 +++\ ->>>&0 search/1024 \n ->>>>&0 search/1 @@ unified diff output text -!:mime text/x-diff -!:strength + 90 diff --git a/magic/elf b/magic/elf deleted file mode 100644 index aaf80cf10e..0000000000 --- a/magic/elf +++ /dev/null @@ -1,43 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# elf: file(1) magic for ELF executables -# -# We have to check the byte order flag to see what byte order all the -# other stuff in the header is in. -# -# What're the correct byte orders for the nCUBE and the Fujitsu VPP500? -# -# Created by: unknown -# Modified by (1): Daniel Quinlan -# Modified by (2): Peter Tobias (core support) -# Modified by (3): Christian 'Dr. Disk' Hechelmann (fix of core support) -# Modified by (4): (VMS Itanium) -# Modified by (5): Matthias Urlichs (Listing of many architectures) -0 string \177ELF ELF ->4 byte 0 invalid class ->4 byte 1 32-bit ->4 byte 2 64-bit ->5 byte 0 invalid byte order ->5 byte 1 LSB ->>16 leshort 0 no file type, -!:strength *2 -!:mime application/octet-stream ->>16 leshort 1 relocatable, -!:mime application/x-object ->>16 leshort 2 executable, -!:mime application/x-executable ->>16 leshort 3 shared object, -!:mime application/x-sharedlib ->>16 leshort 4 core file -!:mime application/x-coredump ->5 byte 2 MSB ->>16 beshort 0 no file type, -!:mime application/octet-stream ->>16 beshort 1 relocatable, -!:mime application/x-object ->>16 beshort 2 executable, -!:mime application/x-executable ->>16 beshort 3 shared object, -!:mime application/x-sharedlib ->>16 beshort 4 core file, -!:mime application/x-coredump diff --git a/magic/epoc b/magic/epoc deleted file mode 100644 index d7397145fb..0000000000 --- a/magic/epoc +++ /dev/null @@ -1,34 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: epoc,v 1.7 2009/09/19 16:28:09 christos Exp $ -# EPOC : file(1) magic for EPOC documents [Psion Series 5/Osaris/Geofox 1] -# Stefan Praszalowicz and Peter Breitenlohner -# Useful information for improving this file can be found at: -# http://software.frodo.looijaard.name/psiconv/formats/Index.html -#------------------------------------------------------------------------------ -0 lelong 0x10000037 Psion Series 5 ->4 lelong 0x10000042 multi-bitmap image -!:mime image/x-epoc-mbm ->4 lelong 0x1000006D ->>8 lelong 0x1000007D Sketch image -!:mime image/x-epoc-sketch ->>8 lelong 0x1000007F Word file -!:mime application/x-epoc-word ->>8 lelong 0x10000085 OPL program (TextEd) -!:mime application/x-epoc-opl ->>8 lelong 0x10000088 Sheet file -!:mime application/x-epoc-sheet ->4 lelong 0x10000073 OPO module -!:mime application/x-epoc-opo ->4 lelong 0x10000074 OPL application -!:mime application/x-epoc-app - - -0 lelong 0x10000050 Psion Series 5 ->4 lelong 0x1000006D database ->>8 lelong 0x10000084 Agenda file -!:mime application/x-epoc-agenda ->>8 lelong 0x10000086 Data file -!:mime application/x-epoc-data ->>8 lelong 0x10000CEA Jotter file -!:mime application/x-epoc-jotter diff --git a/magic/filesystems b/magic/filesystems deleted file mode 100644 index d2178296e0..0000000000 --- a/magic/filesystems +++ /dev/null @@ -1,12 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: filesystems,v 1.76 2013/02/18 18:45:41 christos Exp $ -# filesystems: file(1) magic for different filesystems -# - -# CDROM Filesystems -# Modified for UDF by gerardo.cacciari@gmail.com -32769 string CD001 # -!:mime application/x-iso9660-image -37633 string CD001 ISO 9660 CD-ROM filesystem data (raw 2352 byte sectors) -!:mime application/x-iso9660-image diff --git a/magic/flash b/magic/flash deleted file mode 100644 index b64761b12d..0000000000 --- a/magic/flash +++ /dev/null @@ -1,18 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: flash,v 1.8 2009/09/19 16:28:09 christos Exp $ -# flash: file(1) magic for Macromedia Flash file format -# -# See -# -# http://www.macromedia.com/software/flash/open/ -# -0 string FWS Macromedia Flash data, ->3 byte x version %d -!:mime application/x-shockwave-flash -0 string CWS Macromedia Flash data (compressed), -!:mime application/x-shockwave-flash - -# From: Cal Peake -0 string FLV Macromedia Flash Video -!:mime video/x-flv diff --git a/magic/fonts b/magic/fonts deleted file mode 100644 index 8189131d15..0000000000 --- a/magic/fonts +++ /dev/null @@ -1,32 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: fonts,v 1.25 2013/02/06 14:18:52 christos Exp $ -# fonts: file(1) magic for font data -# - -# X11 font files in SNF (Server Natural Format) format -# updated by Joerg Jenderek at Feb 2013 -# http://computer-programming-forum.com/51-perl/8f22fb96d2e34bab.htm -0 belong 00000004 X11 SNF font data, MSB first -#>104 belong 00000004 X11 SNF font data, MSB first -!:mime application/x-font-sfn -# GRR: line below too general as it catches also Xbase index file t3-CHAR.NDX -0 lelong 00000004 ->104 lelong 00000004 X11 SNF font data, LSB first -!:mime application/x-font-sfn - -# True Type fonts -0 string \000\001\000\000\000 TrueType font data -!:mime application/x-font-ttf - -# Opentype font data from Avi Bercovich -0 string OTTO OpenType font data -!:mime application/vnd.ms-opentype - -# Gurkan Sengun , www.linuks.mine.nu -0 string SplineFontDB: Spline Font Database -!:mime application/vnd.font-fontforge-sfd - -# EOT -34 string LP Embedded OpenType (EOT) -!:mime application/vnd.ms-fontobject diff --git a/magic/fortran b/magic/fortran deleted file mode 100644 index 498eeacf8a..0000000000 --- a/magic/fortran +++ /dev/null @@ -1,7 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: fortran,v 1.6 2009/09/19 16:28:09 christos Exp $ -# FORTRAN source -0 regex/100 \^[Cc][\ \t] FORTRAN program -!:mime text/x-fortran -!:strength - 5 diff --git a/magic/frame b/magic/frame deleted file mode 100644 index b42943bfcd..0000000000 --- a/magic/frame +++ /dev/null @@ -1,31 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# frame: file(1) magic for FrameMaker files -# -# This stuff came on a FrameMaker demo tape, most of which is -# copyright, but this file is "published" as witness the following: -# -# Note that this is the Framemaker Maker Interchange Format, not the -# Normal format which would be application/vnd.framemaker. -# -0 string \6 string 3.0 (3.0) -#>6 string 2.0 (2.0) -#>6 string 1.0 (1.0) -0 string \ - -#------------------------------------------------------------------------------ -# XCF: file(1) magic for the XCF image format used in the GIMP developed -# by Spencer Kimball and Peter Mattis -# ('Bucky' LaDieu, nega@vt.edu) - -0 string gimp\ xcf GIMP XCF image data, -!:mime image/x-xcf diff --git a/magic/gnu b/magic/gnu deleted file mode 100644 index bf1f631751..0000000000 --- a/magic/gnu +++ /dev/null @@ -1,23 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: gnu,v 1.13 2012/01/03 17:16:54 christos Exp $ -# gnu: file(1) magic for various GNU tools -# -# GNU nlsutils message catalog file format -# -# GNU message catalog (.mo and .gmo files) - -# GnuPG -# The format is very similar to pgp -# Note: magic.mime had 0x8501 for the next line instead of 0x8502 -0 beshort 0x8502 GPG encrypted data -!:mime text/PGP # encoding: data - -# This magic is not particularly good, as the keyrings don't have true -# magic. Nevertheless, it covers many keyrings. -0 beshort 0x9901 GPG key public ring -!:mime application/x-gnupg-keyring - -# gettext message catalogue -0 regex \^msgid\ GNU gettext message catalogue text -!:mime text/x-po diff --git a/magic/gnumeric b/magic/gnumeric deleted file mode 100644 index b5edca93c1..0000000000 --- a/magic/gnumeric +++ /dev/null @@ -1,8 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# gnumeric: file(1) magic for Gnumeric spreadsheet -# This entry is only semi-helpful, as Gnumeric compresses its files, so -# they will ordinarily reported as "compressed", but at least -z helps -39 string =4 belong x \b, FORM is %d bytes long -# audio formats ->8 string AIFF \b, AIFF audio -!:mime audio/x-aiff ->8 string AIFC \b, AIFF-C compressed audio -!:mime audio/x-aiff ->8 string 8SVX \b, 8SVX 8-bit sampled sound voice -!:mime audio/x-aiff diff --git a/magic/images b/magic/images deleted file mode 100644 index 281aba4706..0000000000 --- a/magic/images +++ /dev/null @@ -1,255 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: images,v 1.80 2013/02/06 14:18:52 christos Exp $ -# images: file(1) magic for image formats (see also "iff", and "c-lang" for -# XPM bitmaps) -# -# originally from jef@helios.ee.lbl.gov (Jef Poskanzer), -# additions by janl@ifi.uio.no as well as others. Jan also suggested -# merging several one- and two-line files into here. -# -# little magic: PCX (first byte is 0x0a) - -# PBMPLUS images -# The next byte following the magic is always whitespace. -# strength is changed to try these patterns before "x86 boot sector" -0 search/1 P1 ->3 regex =[0-9]*\ [0-9]* Netpbm PBM image text ->3 regex =[0-9]+\ \b, size = %sx ->>3 regex =\ [0-9]+ \b%s -!:strength + 45 -!:mime image/x-portable-bitmap -0 search/1 P2 ->3 regex =[0-9]*\ [0-9]* Netpbm PGM image text ->3 regex =[0-9]+\ \b, size = %sx ->>3 regex =\ [0-9]+ \b%s -!:strength + 45 -!:mime image/x-portable-greymap -0 search/1 P3 Netpbm PPM image text ->3 regex =[0-9]*\ [0-9]* Netpbm PPM image text ->3 regex =[0-9]+\ \b, size = %sx ->>3 regex =\ [0-9]+ \b%s -!:strength + 45 -!:mime image/x-portable-pixmap -0 string P4 ->3 regex =[0-9]*\ [0-9]* Netpbm PBM "rawbits" image data ->3 regex =[0-9]+\ \b, size = %sx ->>3 regex =\ [0-9]+ \b%s -!:strength + 45 -!:mime image/x-portable-bitmap -0 string P5 ->3 regex =[0-9]*\ [0-9]* Netpbm PGM "rawbits" image data ->3 regex =[0-9]+\ \b, size = %sx ->>3 regex =\ [0-9]+ \b%s -!:strength + 45 -!:mime image/x-portable-greymap -0 string P6 ->3 regex =[0-9]*\ [0-9]* Netpbm PPM "rawbits" image data ->3 regex =[0-9]+\ \b, size = %sx ->>3 regex =\ [0-9]+ \b%s -!:strength + 45 -!:mime image/x-portable-pixmap -0 string P7 Netpbm PAM image file -!:mime image/x-portable-pixmap - -# NIFF (Navy Interchange File Format, a modification of TIFF) images -# [GRR: this *must* go before TIFF] -0 string IIN1 NIFF image data -!:mime image/x-niff - -# Canon RAW version 1 (CRW) files are a type of Canon Image File Format -# (CIFF) file. These are apparently all little-endian. -# From: Adam Buchbinder -# URL: http://www.sno.phy.queensu.ca/~phil/exiftool/canon_raw.html -0 string II\x1a\0\0\0HEAPCCDR Canon CIFF raw image data -!:mime image/x-canon-crw - -# Canon RAW version 2 (CR2) files are a kind of TIFF with an extra magic -# number. Put this above the TIFF test to make sure we detect them. -# These are apparently all little-endian. -# From: Adam Buchbinder -# URL: http://libopenraw.freedesktop.org/wiki/Canon_CR2 -0 string II\x2a\0\x10\0\0\0CR Canon CR2 raw image data -!:mime image/x-canon-cr2 - -# Tag Image File Format, from Daniel Quinlan (quinlan@yggdrasil.com) -# The second word of TIFF files is the TIFF version number, 42, which has -# never changed. The TIFF specification recommends testing for it. -0 string MM\x00\x2a TIFF image data, big-endian -!:mime image/tiff -0 string II\x2a\x00 TIFF image data, little-endian -!:mime image/tiff - -0 string MM\x00\x2b Big TIFF image data, big-endian -!:mime image/tiff -0 string II\x2b\x00 Big TIFF image data, little-endian -!:mime image/tiff - -# PNG [Portable Network Graphics, or "PNG's Not GIF"] images -# (Greg Roelofs, newt@uchicago.edu) -# (Albert Cahalan, acahalan@cs.uml.edu) -# -# 137 P N G \r \n ^Z \n [4-byte length] H E A D [HEAD data] [HEAD crc] ... -# -0 string \x89PNG\x0d\x0a\x1a\x0a PNG image data -!:mime image/png - -# possible GIF replacements; none yet released! -# (Greg Roelofs, newt@uchicago.edu) -# -# GRR 950115: this was mine ("Zip GIF"): -0 string GIF94z ZIF image (GIF+deflate alpha) -!:mime image/x-unknown -# -# GRR 950115: this is Jeremy Wohl's Free Graphics Format (better): -# -0 string FGF95a FGF image (GIF+deflate beta) -!:mime image/x-unknown -# -# GRR 950115: this is Thomas Boutell's Portable Bitmap Format proposal -# (best; not yet implemented): -# -0 string PBF PBF image (deflate compression) -!:mime image/x-unknown - -# GIF -0 string GIF8 GIF image data -!:mime image/gif -!:apple 8BIMGIFf - -# From: Joerg Jenderek -# most files with the extension .EPA and some with .BMP -0 string \x11\x06 Award BIOS Logo, 136 x 84 -!:mime image/x-award-bioslogo -0 string \x11\x09 Award BIOS Logo, 136 x 126 -!:mime image/x-award-bioslogo -#0 string \x07\x1f BIOS Logo corrupted? -# http://www.blackfiveservices.co.uk/awbmtools.shtml -# http://biosgfx.narod.ru/v3/ -# http://biosgfx.narod.ru/abr-2/ -0 string AWBM ->4 leshort <1981 Award BIOS bitmap -!:mime image/x-award-bmp - -# PC bitmaps (OS/2, Windows BMP files) (Greg Roelofs, newt@uchicago.edu) -0 string BM ->14 leshort 12 PC bitmap, OS/2 1.x format -!:mime image/x-ms-bmp ->14 leshort 64 PC bitmap, OS/2 2.x format -!:mime image/x-ms-bmp ->14 leshort 40 PC bitmap, Windows 3.x format -!:mime image/x-ms-bmp ->14 leshort 128 PC bitmap, Windows NT/2000 format -!:mime image/x-ms-bmp - -# XPM icons (Greg Roelofs, newt@uchicago.edu) -0 search/1 /*\ XPM\ */ X pixmap image text -!:mime image/x-xpmi - -# DICOM medical imaging data -128 string DICM DICOM medical imaging data -!:mime application/dicom - -# XWD - X Window Dump file. -# As described in /usr/X11R6/include/X11/XWDFile.h -# used by the xwd program. -# Bradford Castalia, idaeim, 1/01 -# updated by Adam Buchbinder, 2/09 -# The following assumes version 7 of the format; the first long is the length -# of the header, which is at least 25 4-byte longs, and the one at offset 8 -# is a constant which is always either 1 or 2. Offset 12 is the pixmap depth, -# which is a maximum of 32. -0 belong >100 ->8 belong <3 ->>12 belong <33 ->>>4 belong 7 XWD X Window Dump image data -!:mime image/x-xwindowdump - -# PCX image files -# From: Dan Fandrich -# updated by Joerg Jenderek at Feb 2013 by http://de.wikipedia.org/wiki/PCX -# http://web.archive.org/web/20100206055706/http://www.qzx.com/pc-gpe/pcx.txt -# GRR: original test was still too general as it catches xbase examples T5.DBT,T6.DBT with 0xa000000 -# test for bytes 0x0a,version byte (0,2,3,4,5),compression byte flag(0,1), bit depth (>0) of PCX or T5.DBT,T6.DBT -0 ubelong&0xffF8fe00 0x0a000000 -# for PCX bit depth > 0 ->3 ubyte >0 -# test for valid versions ->>1 ubyte <6 ->>>1 ubyte !1 PCX -!:mime image/x-pcx - -# Adobe Photoshop -# From: Asbjoern Sloth Toennesen -0 string 8BPS Adobe Photoshop Image -!:mime image/vnd.adobe.photoshop - -# Summary: DjVu image / document -# Extension: .djvu -# Reference: http://djvu.org/docs/DjVu3Spec.djvu -# Submitted by: Stephane Loeuillet -# Modified by (1): Abel Cheung -0 string AT&TFORM ->12 string DJVM DjVu multiple page document -!:mime image/vnd.djvu ->12 string DJVU DjVu image or single page document -!:mime image/vnd.djvu ->12 string DJVI DjVu shared document -!:mime image/vnd.djvu ->12 string THUM DjVu page thumbnails -!:mime image/vnd.djvu - -# Originally by Marc Espie -# Modified by Robert Minsk -# http://www.openexr.com/openexrfilelayout.pdf -0 lelong 20000630 OpenEXR image data, -!:mime image/x-exr - -# SMPTE Digital Picture Exchange Format, SMPTE DPX -# -# ANSI/SMPTE 268M-1994, SMPTE Standard for File Format for Digital -# Moving-Picture Exchange (DPX), v1.0, 18 February 1994 -# Robert Minsk -0 string SDPX DPX image data, big-endian, -!:mime image/x-dpx - -#----------------------------------------------------------------------- -# Hierarchical Data Format, used to facilitate scientific data exchange -# specifications at http://hdf.ncsa.uiuc.edu/ -0 belong 0x0e031301 Hierarchical Data Format (version 4) data -!:mime application/x-hdf -0 string \211HDF\r\n\032\n Hierarchical Data Format (version 5) data -!:mime application/x-hdf - -# http://www.cartesianinc.com/Tech/ -0 string CPC\262 Cartesian Perceptual Compression image -!:mime image/x-cpi - - -# Polar Monitor Bitmap (.pmb) used as logo for Polar Electro watches -# From: Markus Heidelberg -0 string/t [BitmapInfo2] Polar Monitor Bitmap text -!:mime image/x-polar-monitor-bitmap - -# Type: Olympus ORF raw images. -# URL: http://libopenraw.freedesktop.org/wiki/Olympus_ORF -# From: Adam Buchbinder -0 string MMOR Olympus ORF raw image data, big-endian -!:mime image/x-olympus-orf -0 string IIRO Olympus ORF raw image data, little-endian -!:mime image/x-olympus-orf -0 string IIRS Olympus ORF raw image data, little-endian -!:mime image/x-olympus-orf - -# Type: Foveon X3F -# URL: http://www.photofo.com/downloads/x3f-raw-format.pdf -# From: Adam Buchbinder -# Note that the MIME type isn't defined anywhere that I can find; if -# there's a canonical type for this format, it should replace this one. -0 string FOVb Foveon X3F raw image data -!:mime image/x-x3f - -# Paint.NET file -# From Adam Buchbinder -0 string PDN3 Paint.NET image data -!:mime image/x-paintnet diff --git a/magic/java b/magic/java deleted file mode 100644 index 481ffec160..0000000000 --- a/magic/java +++ /dev/null @@ -1,16 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------ -# $File: java,v 1.13 2011/12/08 12:12:46 rrt Exp $ -# Java ByteCode and Mach-O binaries (e.g., Mac OS X) use the -# same magic number, 0xcafebabe, so they are both handled -# in the entry called "cafebabe". -#------------------------------------------------------------ - -0 belong 0xfeedfeed Java KeyStore -!:mime application/x-java-keystore -0 belong 0xcececece Java JCE KeyStore -!:mime application/x-java-jce-keystore - -# Java source -0 regex ^import.*;$ Java source -!:mime text/x-java diff --git a/magic/javascript b/magic/javascript deleted file mode 100644 index a1311d0e71..0000000000 --- a/magic/javascript +++ /dev/null @@ -1,17 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: $ -# javascript: magic for javascript and node.js scripts. -# -0 search/1/w #!/bin/node Node.js script text executable -!:mime application/javascript -0 search/1/w #!/usr/bin/node Node.js script text executable -!:mime application/javascript -0 search/1/w #!/bin/nodejs Node.js script text executable -!:mime application/javascript -0 search/1/w #!/usr/bin/nodejs Node.js script text executable -!:mime application/javascript -0 search/1 #!/usr/bin/env\ node Node.js script text executable -!:mime application/javascript -0 search/1 #!/usr/bin/env\ nodejs Node.js script text executable -!:mime application/javascript diff --git a/magic/jpeg b/magic/jpeg deleted file mode 100644 index 55fedae4b4..0000000000 --- a/magic/jpeg +++ /dev/null @@ -1,31 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: jpeg,v 1.18 2012/08/01 12:12:36 christos Exp $ -# JPEG images -# SunOS 5.5.1 had -# -# 0 string \377\330\377\340 JPEG file -# 0 string \377\330\377\356 JPG file -# -# both of which turn into "JPEG image data" here. -# -0 beshort 0xffd8 JPEG image data -!:mime image/jpeg -!:apple 8BIMJPEG -!:strength +2 - -# From: David Santinoli -0 string \x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A JPEG 2000 -# From: Johan van der Knijff -# Added sub-entries for JP2, JPX, JPM and MJ2 formats; added mimetypes -# https://github.com/bitsgalore/jp2kMagic -# -# Now read value of 'Brand' field, which yields a few possibilities: ->20 string \x6a\x70\x32\x20 Part 1 (JP2) -!:mime image/jp2 ->20 string \x6a\x70\x78\x20 Part 2 (JPX) -!:mime image/jpx ->20 string \x6a\x70\x6d\x20 Part 6 (JPM) -!:mime image/jpm ->20 string \x6d\x6a\x70\x32 Part 3 (MJ2) -!:mime video/mj2 diff --git a/magic/kde b/magic/kde deleted file mode 100644 index 2b66ee611d..0000000000 --- a/magic/kde +++ /dev/null @@ -1,11 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: kde,v 1.4 2009/09/19 16:28:10 christos Exp $ -# kde: file(1) magic for KDE - -0 string/t [KDE\ Desktop\ Entry] KDE desktop entry -!:mime application/x-kdelnk -0 string/t #\ KDE\ Config\ File KDE config file -!:mime application/x-kdelnk -0 string/t #\ xmcd xmcd database file for kscd -!:mime text/x-xmcd diff --git a/magic/kml b/magic/kml deleted file mode 100644 index 608ff0e1b0..0000000000 --- a/magic/kml +++ /dev/null @@ -1,30 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: kml,v 1.2 2009/09/19 16:28:10 christos Exp $ -# Type: Google KML, formerly Keyhole Markup Language -# Future development of this format has been handed -# over to the Open Geospatial Consortium. -# http://www.opengeospatial.org/standards/kml/ -# From: Asbjoern Sloth Toennesen -0 string/t \20 search/400 \ xmlns= ->>&0 regex ['"]http://earth.google.com/kml Google KML document -!:mime application/vnd.google-earth.kml+xml - -#------------------------------------------------------------------------------ -# Type: OpenGIS KML, formerly Keyhole Markup Language -# This standard is maintained by the -# Open Geospatial Consortium. -# http://www.opengeospatial.org/standards/kml/ -# From: Asbjoern Sloth Toennesen ->>&0 regex ['"]http://www.opengis.net/kml OpenGIS KML document -!:mime application/vnd.google-earth.kml+xml - -#------------------------------------------------------------------------------ -# Type: Google KML Archive (ZIP based) -# http://code.google.com/apis/kml/documentation/kml_tut.html -# From: Asbjoern Sloth Toennesen -0 string PK\003\004 ->4 byte 0x14 ->>30 string doc.kml Compressed Google KML Document, including resources. -!:mime application/vnd.google-earth.kmz diff --git a/magic/linux b/magic/linux deleted file mode 100644 index 4a5c935760..0000000000 --- a/magic/linux +++ /dev/null @@ -1,22 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: linux,v 1.46 2013/01/06 21:26:48 christos Exp $ -# linux: file(1) magic for Linux files -# -# Values for Linux/i386 binaries, from Daniel Quinlan -# The following basic Linux magic is useful for reference, but using -# "long" magic is a better practice in order to avoid collisions. -# -# 2 leshort 100 Linux/i386 -# >0 leshort 0407 impure executable (OMAGIC) -# >0 leshort 0410 pure executable (NMAGIC) -# >0 leshort 0413 demand-paged executable (ZMAGIC) -# >0 leshort 0314 demand-paged executable (QMAGIC) -# - -# SYSLINUX boot logo files (from 'ppmtolss16' sources) -# http://www.syslinux.org/wiki/index.php/SYSLINUX#Display_graphic_from_filename: -# file extension .lss .16 -0 lelong =0x1413f33d SYSLINUX' LSS16 image data -# syslinux-4.05/mime/image/x-lss16.xml -!:mime image/x-lss16 diff --git a/magic/lisp b/magic/lisp deleted file mode 100644 index f5a06c8964..0000000000 --- a/magic/lisp +++ /dev/null @@ -1,42 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# lisp: file(1) magic for lisp programs -# -# various lisp types, from Daniel Quinlan (quinlan@yggdrasil.com) - -# updated by Joerg Jenderek -# GRR: This lot is too weak -#0 string ;; -# windows INF files often begin with semicolon and use CRLF as line end -# lisp files are mainly created on unix system with LF as line end -#>2 search/4096 !\r Lisp/Scheme program text -#>2 search/4096 \r Windows INF file - -0 search/4096 (setq\ Lisp/Scheme program text -!:mime text/x-lisp -0 search/4096 (defvar\ Lisp/Scheme program text -!:mime text/x-lisp -0 search/4096 (defparam\ Lisp/Scheme program text -!:mime text/x-lisp -0 search/4096 (defun\ Lisp/Scheme program text -!:mime text/x-lisp -0 search/4096 (autoload\ Lisp/Scheme program text -!:mime text/x-lisp -0 search/4096 (custom-set-variables\ Lisp/Scheme program text -!:mime text/x-lisp - -# Emacs 18 - this is always correct, but not very magical. -0 string \012( Emacs v18 byte-compiled Lisp data -!:mime application/x-elc -# Emacs 19+ - ver. recognition added by Ian Springer -# Also applies to XEmacs 19+ .elc files; could tell them apart with regexs -# - Chris Chittleborough -0 string ;ELC ->4 byte >18 ->4 byte <32 Emacs/XEmacs v%d byte-compiled Lisp data -!:mime application/x-elc - -# From: David Allouche -0 search/1 \, Seo Sanghyeon - -# Lua scripts -0 search/1/w #!\ /usr/bin/lua Lua script text executable -!:mime text/x-lua -0 search/1/w #!\ /usr/local/bin/lua Lua script text executable -!:mime text/x-lua -0 search/1 #!/usr/bin/env\ lua Lua script text executable -!:mime text/x-lua -0 search/1 #!\ /usr/bin/env\ lua Lua script text executable -!:mime text/x-lua - diff --git a/magic/m4 b/magic/m4 deleted file mode 100644 index 7262fca81b..0000000000 --- a/magic/m4 +++ /dev/null @@ -1,7 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# make: file(1) magic for M4 scripts -# -0 regex \^dnl\ M4 macro processor script text -!:mime text/x-m4 diff --git a/magic/macintosh b/magic/macintosh deleted file mode 100644 index 6398fc2ff2..0000000000 --- a/magic/macintosh +++ /dev/null @@ -1,21 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: macintosh,v 1.21 2010/09/20 19:19:17 rrt Exp $ -# macintosh description -# -# BinHex is the Macintosh ASCII-encoded file format (see also "apple") -# Daniel Quinlan, quinlan@yggdrasil.com -11 string must\ be\ converted\ with\ BinHex BinHex binary text -!:mime application/mac-binhex40 - -# Stuffit archives are the de facto standard of compression for Macintosh -# files obtained from most archives. (franklsm@tuns.ca) -0 string SIT! StuffIt Archive (data) -!:mime application/x-stuffit -!:apple SIT!SIT! - -# Newer StuffIt archives (grant@netbsd.org) -0 string StuffIt StuffIt Archive -!:mime application/x-stuffit -!:apple SIT!SIT! -#>162 string >0 : %s diff --git a/magic/mail.news b/magic/mail.news deleted file mode 100644 index c1a446d4ca..0000000000 --- a/magic/mail.news +++ /dev/null @@ -1,35 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: mail.news,v 1.21 2012/06/21 01:44:52 christos Exp $ -# mail.news: file(1) magic for mail and news -# -# Unfortunately, saved netnews also has From line added in some news software. -#0 string From mail text -0 string/t Relay-Version: old news text -!:mime message/rfc822 -0 string/t #!\ rnews batched news text -!:mime message/rfc822 -0 string/t N#!\ rnews mailed, batched news text -!:mime message/rfc822 -0 string/t Forward\ to mail forwarding text -!:mime message/rfc822 -0 string/t Pipe\ to mail piping text -!:mime message/rfc822 -0 string/tc delivered-to: SMTP mail text -!:mime message/rfc822 -0 string/tc return-path: SMTP mail text -!:mime message/rfc822 -0 string/t Path: news text -!:mime message/news -0 string/t Xref: news text -!:mime message/news -0 string/t From: news or mail text -!:mime message/rfc822 -0 string/t Article saved news text -!:mime message/news -0 string/t Received: RFC 822 mail text -!:mime message/rfc822 - -# TNEF files... -0 lelong 0x223E9F78 Transport Neutral Encapsulation Format -!:mime application/vnd.ms-tnef diff --git a/magic/make b/magic/make deleted file mode 100644 index 83d6a012dd..0000000000 --- a/magic/make +++ /dev/null @@ -1,16 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# make: file(1) magic for makefiles -# -0 regex \^CFLAGS makefile script text -!:mime text/x-makefile -0 regex \^LDFLAGS makefile script text -!:mime text/x-makefile -0 regex \^all: makefile script text -!:mime text/x-makefile -0 regex \^.PRECIOUS makefile script text -!:mime text/x-makefile - -0 regex \^SUBDIRS automake makefile script text -!:mime text/x-makefile diff --git a/magic/marc21 b/magic/marc21 deleted file mode 100644 index 26899d2e70..0000000000 --- a/magic/marc21 +++ /dev/null @@ -1,29 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#-------------------------------------------- -# marc21: file(1) magic for MARC 21 Format -# -# Kevin Ford (kefo@loc.gov) -# -# MARC21 formats are for the representation and communication -# of bibliographic and related information in machine-readable -# form. For more info, see http://www.loc.gov/marc/ - - -# leader position 20-21 must be 45 -20 string 45 - -# leader starts with 5 digits, followed by codes specific to MARC format ->0 regex/1 (^[0-9]{5})[acdnp][^bhlnqsu-z] MARC21 Bibliographic -!:mime application/marc ->0 regex/1 (^[0-9]{5})[acdnosx][z] MARC21 Authority -!:mime application/marc ->0 regex/1 (^[0-9]{5})[cdn][uvxy] MARC21 Holdings -!:mime application/marc -0 regex/1 (^[0-9]{5})[acdn][w] MARC21 Classification -!:mime application/marc ->0 regex/1 (^[0-9]{5})[cdn][q] MARC21 Community -!:mime application/marc - -# leader position 22-23, should be "00" but is it? ->0 regex/1 (^.{21})([^0]{2}) (non-conforming) -!:mime application/marc diff --git a/magic/matroska b/magic/matroska deleted file mode 100644 index c1791413cb..0000000000 --- a/magic/matroska +++ /dev/null @@ -1,17 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: matroska,v 1.7 2012/08/26 10:06:15 christos Exp $ -# matroska: file(1) magic for Matroska files -# -# See http://www.matroska.org/ -# - -# EBML id: -0 belong 0x1a45dfa3 -# DocType id: ->4 search/4096 \x42\x82 -# DocType contents: ->>&1 string webm WebM -!:mime video/webm ->>&1 string matroska Matroska data -!:mime video/x-matroska diff --git a/magic/misctools b/magic/misctools deleted file mode 100644 index 35fddaa61a..0000000000 --- a/magic/misctools +++ /dev/null @@ -1,9 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#----------------------------------------------------------------------------- -# $File: misctools,v 1.12 2010/09/29 18:36:49 rrt Exp $ -# misctools: file(1) magic for miscellaneous UNIX tools. -# -0 string/c BEGIN:VCALENDAR vCalendar calendar file -!:mime text/calendar -0 string/c BEGIN:VCARD vCard visiting card -!:mime text/x-vcard diff --git a/magic/msdos b/magic/msdos deleted file mode 100644 index cc411aeeb7..0000000000 --- a/magic/msdos +++ /dev/null @@ -1,369 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: msdos,v 1.84 2013/02/05 13:55:22 christos Exp $ -# msdos: file(1) magic for MS-DOS files -# - -# .BAT files (Daniel Quinlan, quinlan@yggdrasil.com) -# updated by Joerg Jenderek at Oct 2008,Apr 2011 -0 string/t @ ->1 string/cW \ echo\ off DOS batch file text -!:mime text/x-msdos-batch ->1 string/cW echo\ off DOS batch file text -!:mime text/x-msdos-batch ->1 string/cW rem DOS batch file text -!:mime text/x-msdos-batch ->1 string/cW set\ DOS batch file text -!:mime text/x-msdos-batch - -# Tests for various EXE types. -# -# Many of the compressed formats were extraced from IDARC 1.23 source code. -# -0 string/b MZ DOS MZ -!:mime application/x-dosexec -# All non-DOS EXE extensions have the relocation table more than 0x40 bytes into the file. ->0x18 leshort <0x40 MS-DOS executable -# These traditional tests usually work but not always. When test quality support is -# implemented these can be turned on. -#>>0x18 leshort 0x1c (Borland compiler) -#>>0x18 leshort 0x1e (MS compiler) - -# If the relocation table is 0x40 or more bytes into the file, it's definitely -# not a DOS EXE. ->0x18 leshort >0x3f - -# Maybe it's a PE? ->>(0x3c.l) string PE\0\0 PE ->>>(0x3c.l+24) leshort 0x010b \b32 executable ->>>(0x3c.l+24) leshort 0x020b \b32+ executable ->>>(0x3c.l+24) leshort 0x0107 ROM image ->>>(0x3c.l+24) default x Unknown PE signature ->>>>&0 leshort x 0x%x ->>>(0x3c.l+22) leshort&0x2000 >0 (DLL) ->>>(0x3c.l+92) leshort 1 (native) ->>>(0x3c.l+92) leshort 2 (GUI) ->>>(0x3c.l+92) leshort 3 (console) ->>>(0x3c.l+92) leshort 7 (POSIX) ->>>(0x3c.l+92) leshort 9 (Windows CE) ->>>(0x3c.l+92) leshort 10 (EFI application) ->>>(0x3c.l+92) leshort 11 (EFI boot service driver) ->>>(0x3c.l+92) leshort 12 (EFI runtime driver) ->>>(0x3c.l+92) leshort 13 (EFI ROM) ->>>(0x3c.l+92) leshort 14 (XBOX) ->>>(0x3c.l+92) leshort 15 (Windows boot application) ->>>(0x3c.l+92) default x (Unknown subsystem ->>>>&0 leshort x 0x%x) ->>>(0x3c.l+4) leshort 0x14c Intel 80386 ->>>(0x3c.l+4) leshort 0x166 MIPS R4000 ->>>(0x3c.l+4) leshort 0x168 MIPS R10000 ->>>(0x3c.l+4) leshort 0x184 Alpha ->>>(0x3c.l+4) leshort 0x1a2 Hitachi SH3 ->>>(0x3c.l+4) leshort 0x1a6 Hitachi SH4 ->>>(0x3c.l+4) leshort 0x1c0 ARM ->>>(0x3c.l+4) leshort 0x1c2 ARM Thumb ->>>(0x3c.l+4) leshort 0x1c4 ARMv7 Thumb ->>>(0x3c.l+4) leshort 0x1f0 PowerPC ->>>(0x3c.l+4) leshort 0x200 Intel Itanium ->>>(0x3c.l+4) leshort 0x266 MIPS16 ->>>(0x3c.l+4) leshort 0x268 Motorola 68000 ->>>(0x3c.l+4) leshort 0x290 PA-RISC ->>>(0x3c.l+4) leshort 0x366 MIPSIV ->>>(0x3c.l+4) leshort 0x466 MIPS16 with FPU ->>>(0x3c.l+4) leshort 0xebc EFI byte code ->>>(0x3c.l+4) leshort 0x8664 x86-64 ->>>(0x3c.l+4) leshort 0xc0ee MSIL ->>>(0x3c.l+4) default x Unknown processor type ->>>>&0 leshort x 0x%x ->>>(0x3c.l+22) leshort&0x0200 >0 (stripped to external PDB) ->>>(0x3c.l+22) leshort&0x1000 >0 system file ->>>(0x3c.l+24) leshort 0x010b ->>>>(0x3c.l+232) lelong >0 Mono/.Net assembly ->>>(0x3c.l+24) leshort 0x020b ->>>>(0x3c.l+248) lelong >0 Mono/.Net assembly - -# hooray, there's a DOS extender using the PE format, with a valid PE -# executable inside (which just prints a message and exits if run in win) ->>>(8.s*16) string 32STUB \b, 32rtm DOS extender ->>>(8.s*16) string !32STUB \b, for MS Windows ->>>(0x3c.l+0xf8) string UPX0 \b, UPX compressed ->>>(0x3c.l+0xf8) search/0x140 PEC2 \b, PECompact2 compressed ->>>(0x3c.l+0xf8) search/0x140 UPX2 ->>>>(&0x10.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) ->>>(0x3c.l+0xf8) search/0x140 .idata ->>>>(&0xe.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) ->>>>(&0xe.l+(-4)) string ZZ0 \b, ZZip self-extracting archive ->>>>(&0xe.l+(-4)) string ZZ1 \b, ZZip self-extracting archive ->>>(0x3c.l+0xf8) search/0x140 .rsrc ->>>>(&0x0f.l+(-4)) string a\\\4\5 \b, WinHKI self-extracting archive ->>>>(&0x0f.l+(-4)) string Rar! \b, RAR self-extracting archive ->>>>(&0x0f.l+(-4)) search/0x3000 MSCF \b, InstallShield self-extracting archive ->>>>(&0x0f.l+(-4)) search/32 Nullsoft \b, Nullsoft Installer self-extracting archive ->>>(0x3c.l+0xf8) search/0x140 .data ->>>>(&0x0f.l) string WEXTRACT \b, MS CAB-Installer self-extracting archive ->>>(0x3c.l+0xf8) search/0x140 .petite\0 \b, Petite compressed ->>>>(0x3c.l+0xf7) byte x ->>>>>(&0x104.l+(-4)) string =!sfx! \b, ACE self-extracting archive ->>>(0x3c.l+0xf8) search/0x140 .WISE \b, WISE installer self-extracting archive ->>>(0x3c.l+0xf8) search/0x140 .dz\0\0\0 \b, Dzip self-extracting archive ->>>&(0x3c.l+0xf8) search/0x100 _winzip_ \b, ZIP self-extracting archive (WinZip) ->>>&(0x3c.l+0xf8) search/0x100 SharedD \b, Microsoft Installer self-extracting archive ->>>0x30 string Inno \b, InnoSetup self-extracting archive - -# Hmm, not a PE but the relocation table is too high for a traditional DOS exe, -# must be one of the unusual subformats. ->>(0x3c.l) string !PE\0\0 MS-DOS executable - ->>(0x3c.l) string NE \b, NE ->>>(0x3c.l+0x36) byte 1 for OS/2 1.x ->>>(0x3c.l+0x36) byte 2 for MS Windows 3.x ->>>(0x3c.l+0x36) byte 3 for MS-DOS ->>>(0x3c.l+0x36) byte 4 for Windows 386 ->>>(0x3c.l+0x36) byte 5 for Borland Operating System Services ->>>(0x3c.l+0x36) default x ->>>>(0x3c.l+0x36) byte x (unknown OS %x) ->>>(0x3c.l+0x36) byte 0x81 for MS-DOS, Phar Lap DOS extender ->>>(0x3c.l+0x0c) leshort&0x8003 0x8002 (DLL) ->>>(0x3c.l+0x0c) leshort&0x8003 0x8001 (driver) ->>>&(&0x24.s-1) string ARJSFX \b, ARJ self-extracting archive ->>>(0x3c.l+0x70) search/0x80 WinZip(R)\ Self-Extractor \b, ZIP self-extracting archive (WinZip) - ->>(0x3c.l) string LX\0\0 \b, LX ->>>(0x3c.l+0x0a) leshort <1 (unknown OS) ->>>(0x3c.l+0x0a) leshort 1 for OS/2 ->>>(0x3c.l+0x0a) leshort 2 for MS Windows ->>>(0x3c.l+0x0a) leshort 3 for DOS ->>>(0x3c.l+0x0a) leshort >3 (unknown OS) ->>>(0x3c.l+0x10) lelong&0x28000 =0x8000 (DLL) ->>>(0x3c.l+0x10) lelong&0x20000 >0 (device driver) ->>>(0x3c.l+0x10) lelong&0x300 0x300 (GUI) ->>>(0x3c.l+0x10) lelong&0x28300 <0x300 (console) ->>>(0x3c.l+0x08) leshort 1 i80286 ->>>(0x3c.l+0x08) leshort 2 i80386 ->>>(0x3c.l+0x08) leshort 3 i80486 ->>>(8.s*16) string emx \b, emx ->>>>&1 string x %s ->>>&(&0x54.l-3) string arjsfx \b, ARJ self-extracting archive - -# MS Windows system file, supposedly a collection of LE executables ->>(0x3c.l) string W3 \b, W3 for MS Windows - ->>(0x3c.l) string LE\0\0 \b, LE executable ->>>(0x3c.l+0x0a) leshort 1 -# some DOS extenders use LE files with OS/2 header ->>>>0x240 search/0x100 DOS/4G for MS-DOS, DOS4GW DOS extender ->>>>0x240 search/0x200 WATCOM\ C/C++ for MS-DOS, DOS4GW DOS extender ->>>>0x440 search/0x100 CauseWay\ DOS\ Extender for MS-DOS, CauseWay DOS extender ->>>>0x40 search/0x40 PMODE/W for MS-DOS, PMODE/W DOS extender ->>>>0x40 search/0x40 STUB/32A for MS-DOS, DOS/32A DOS extender (stub) ->>>>0x40 search/0x80 STUB/32C for MS-DOS, DOS/32A DOS extender (configurable stub) ->>>>0x40 search/0x80 DOS/32A for MS-DOS, DOS/32A DOS extender (embedded) -# this is a wild guess; hopefully it is a specific signature ->>>>&0x24 lelong <0x50 ->>>>>(&0x4c.l) string \xfc\xb8WATCOM ->>>>>>&0 search/8 3\xdbf\xb9 \b, 32Lite compressed -# another wild guess: if real OS/2 LE executables exist, they probably have higher start EIP -#>>>>(0x3c.l+0x1c) lelong >0x10000 for OS/2 -# fails with DOS-Extenders. ->>>(0x3c.l+0x0a) leshort 2 for MS Windows ->>>(0x3c.l+0x0a) leshort 3 for DOS ->>>(0x3c.l+0x0a) leshort 4 for MS Windows (VxD) ->>>(&0x7c.l+0x26) string UPX \b, UPX compressed ->>>&(&0x54.l-3) string UNACE \b, ACE self-extracting archive - -# looks like ASCII, probably some embedded copyright message. -# and definitely not NE/LE/LX/PE ->>0x3c lelong >0x20000000 ->>>(4.s*512) leshort !0x014c \b, MZ for MS-DOS -# header data too small for extended executable ->2 long !0 ->>0x18 leshort <0x40 ->>>(4.s*512) leshort !0x014c - ->>>>&(2.s-514) string !LE ->>>>>&-2 string !BW \b, MZ for MS-DOS ->>>>&(2.s-514) string LE \b, LE ->>>>>0x240 search/0x100 DOS/4G for MS-DOS, DOS4GW DOS extender -# educated guess since indirection is still not capable enough for complex offset -# calculations (next embedded executable would be at &(&2*512+&0-2) -# I suspect there are only LE executables in these multi-exe files ->>>>&(2.s-514) string BW ->>>>>0x240 search/0x100 DOS/4G ,\b LE for MS-DOS, DOS4GW DOS extender (embedded) ->>>>>0x240 search/0x100 !DOS/4G ,\b BW collection for MS-DOS - -# This sequence skips to the first COFF segment, usually .text ->(4.s*512) leshort 0x014c \b, COFF ->>(8.s*16) string go32stub for MS-DOS, DJGPP go32 DOS extender ->>(8.s*16) string emx ->>>&1 string x for DOS, Win or OS/2, emx %s ->>&(&0x42.l-3) byte x ->>>&0x26 string UPX \b, UPX compressed -# and yet another guess: small .text, and after large .data is unusal, could be 32lite ->>&0x2c search/0xa0 .text ->>>&0x0b lelong <0x2000 ->>>>&0 lelong >0x6000 \b, 32lite compressed - ->(8.s*16) string $WdX \b, WDos/X DOS extender - -# By now an executable type should have been printed out. The executable -# may be a self-uncompressing archive, so look for evidence of that and -# print it out. -# -# Some signatures below from Greg Roelofs, newt@uchicago.edu. -# ->0x35 string \x8e\xc0\xb9\x08\x00\xf3\xa5\x4a\x75\xeb\x8e\xc3\x8e\xd8\x33\xff\xbe\x30\x00\x05 \b, aPack compressed ->0xe7 string LH/2\ Self-Extract \b, %s ->0x1c string UC2X \b, UCEXE compressed ->0x1c string WWP\ \b, WWPACK compressed ->0x1c string RJSX \b, ARJ self-extracting archive ->0x1c string diet \b, diet compressed ->0x1c string LZ09 \b, LZEXE v0.90 compressed ->0x1c string LZ91 \b, LZEXE v0.91 compressed ->0x1c string tz \b, TinyProg compressed ->0x1e string Copyright\ 1989-1990\ PKWARE\ Inc. Self-extracting PKZIP archive -!:mime application/zip -# Yes, this really is "Copr", not "Corp." ->0x1e string PKLITE\ Copr. Self-extracting PKZIP archive -!:mime application/zip -# winarj stores a message in the stub instead of the sig in the MZ header ->0x20 search/0xe0 aRJsfX \b, ARJ self-extracting archive ->0x20 string AIN ->>0x23 string 2 \b, AIN 2.x compressed ->>0x23 string <2 \b, AIN 1.x compressed ->>0x23 string >2 \b, AIN 1.x compressed ->0x24 string LHa's\ SFX \b, LHa self-extracting archive -!:mime application/x-lha ->0x24 string LHA's\ SFX \b, LHa self-extracting archive -!:mime application/x-lha ->0x24 string \ $ARX \b, ARX self-extracting archive ->0x24 string \ $LHarc \b, LHarc self-extracting archive ->0x20 string SFX\ by\ LARC \b, LARC self-extracting archive ->0x40 string aPKG \b, aPackage self-extracting archive ->0x64 string W\ Collis\0\0 \b, Compack compressed ->0x7a string Windows\ self-extracting\ ZIP \b, ZIP self-extracting archive ->>&0xf4 search/0x140 \x0\x40\x1\x0 ->>>(&0.l+(4)) string MSCF \b, WinHKI CAB self-extracting archive ->1638 string -lh5- \b, LHa self-extracting archive v2.13S ->0x17888 string Rar! \b, RAR self-extracting archive - -# Skip to the end of the EXE. This will usually work fine in the PE case -# because the MZ image is hardcoded into the toolchain and almost certainly -# won't match any of these signatures. ->(4.s*512) long x ->>&(2.s-517) byte x ->>>&0 string PK\3\4 \b, ZIP self-extracting archive ->>>&0 string Rar! \b, RAR self-extracting archive ->>>&0 string =!\x11 \b, AIN 2.x self-extracting archive ->>>&0 string =!\x12 \b, AIN 2.x self-extracting archive ->>>&0 string =!\x17 \b, AIN 1.x self-extracting archive ->>>&0 string =!\x18 \b, AIN 1.x self-extracting archive ->>>&7 search/400 **ACE** \b, ACE self-extracting archive ->>>&0 search/0x480 UC2SFX\ Header \b, UC2 self-extracting archive - -# a few unknown ZIP sfxes, no idea if they are needed or if they are -# already captured by the generic patterns above ->(8.s*16) search/0x20 PKSFX \b, ZIP self-extracting archive (PKZIP) -# TODO: how to add this? >FileSize-34 string Windows\ Self-Installing\ Executable \b, ZIP self-extracting archive -# - -# TELVOX Teleinformatica CODEC self-extractor for OS/2: ->49801 string \x79\xff\x80\xff\x76\xff \b, CODEC archive v3.21 ->>49824 leshort =1 \b, 1 file ->>49824 leshort >1 \b, %u files - -# Popular applications -2080 string Microsoft\ Word\ 6.0\ Document %s -!:mime application/msword -2080 string Documento\ Microsoft\ Word\ 6 Spanish Microsoft Word 6 document data -!:mime application/msword -# Pawel Wiecek (for polish Word) -2112 string MSWordDoc Microsoft Word document data -!:mime application/msword -# -0 belong 0x31be0000 Microsoft Word Document -!:mime application/msword -# -0 string/b PO^Q` Microsoft Word 6.0 Document -!:mime application/msword -# -0 string/b \376\067\0\043 Microsoft Office Document -!:mime application/msword -0 string/b \333\245-\0\0\0 Microsoft Office Document -!:mime application/msword -512 string/b \354\245\301 Microsoft Word Document -!:mime application/msword - -# -0 string/b \xDB\xA5\x2D\x00 Microsoft WinWord 2.0 Document -!:mime application/msword -# -2080 string Microsoft\ Excel\ 5.0\ Worksheet %s -!:mime application/vnd.ms-excel -# -0 string/b \xDB\xA5\x2D\x00 Microsoft WinWord 2.0 Document -!:mime application/msword - -2080 string Foglio\ di\ lavoro\ Microsoft\ Exce %s -!:mime application/vnd.ms-excel -# -# Pawel Wiecek (for polish Excel) -2114 string Biff5 Microsoft Excel 5.0 Worksheet -!:mime application/vnd.ms-excel -# Italian MS-Excel -2121 string Biff5 Microsoft Excel 5.0 Worksheet -!:mime application/vnd.ms-excel -0 string/b \x09\x04\x06\x00\x00\x00\x10\x00 Microsoft Excel Worksheet -!:mime application/vnd.ms-excel -# -0 belong 0x00001a00 Lotus 1-2-3 -!:mime application/x-123 -# -0 belong 0x00000200 Lotus 1-2-3 -!:mime application/x-123 -0 string/b WordPro\0 Lotus WordPro -!:mime application/vnd.lotus-wordpro -0 string/b WordPro\r\373 Lotus WordPro -!:mime application/vnd.lotus-wordpro - -# Windows icons (Ian Springer ) -0 string/b \000\000\001\000 MS Windows icon resource -!:mime image/x-icon - -# .PIF files added by Joerg Jenderek from http://smsoft.ru/en/pifdoc.htm -# only for windows versions equal or greater 3.0 -0x171 string MICROSOFT\ PIFEX\0 Windows Program Information File -!:mime application/x-dosexec - -# TNEF magic From "Joomy" -# Microsoft Outlook's Transport Neutral Encapsulation Format (TNEF) -0 leshort 0x223e9f78 TNEF -!:mime application/vnd.ms-tnef - -#------------------------------------------------------------------------------ -# From Stuart Caie (developer of cabextract) -# Microsoft Cabinet files -0 string/b MSCF\0\0\0\0 Microsoft Cabinet archive data -!:mime application/vnd.ms-cab-compressed - -# from http://filext.com by Derek M Jones -# False positive with PPT (also currently this string is too long) -#0 string/b \xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3E\x00\x03\x00\xFE\xFF\x09\x00\x06 Microsoft Installer -0 string/b \320\317\021\340\241\261\032\341 Microsoft Office Document -!:mime application/msword -#>48 byte 0x1B Excel Document -#!:mime application/vnd.ms-excel -#>546 string bjbj Microsoft Word Document -#!:mime application/msword -#>546 string jbjb Microsoft Word Document -#!:mime application/msword - -0 string/b \224\246\056 Microsoft Word Document -!:mime application/msword - -512 string R\0o\0o\0t\0\ \0E\0n\0t\0r\0y Microsoft Word Document -!:mime application/msword - -# MS eBook format (.lit) -0 string/b ITOLITLS Microsoft Reader eBook Data ->8 lelong x \b, version %u -!:mime application/x-ms-reader diff --git a/magic/neko b/magic/neko deleted file mode 100644 index 50163a0861..0000000000 --- a/magic/neko +++ /dev/null @@ -1,12 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------ -# $File: java,v 1.12 2009/09/19 16:28:10 christos Exp $ - -# From: Mikhail Gusarov -# NekoVM (http://nekovm.org/) bytecode -0 string NEKO NekoVM bytecode ->4 lelong x (%d global symbols, ->8 lelong x %d global fields, ->12 lelong x %d bytecode ops) -!:mime application/x-nekovm-bytecode - diff --git a/magic/pascal b/magic/pascal deleted file mode 100644 index 911eea3c0c..0000000000 --- a/magic/pascal +++ /dev/null @@ -1,11 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# pascal: file(1) magic for Pascal source -# -0 search/8192 (input, Pascal source text -!:mime text/x-pascal -0 regex \^program Pascal source text -!:mime text/x-pascal -0 regex \^record Pascal source text -!:mime text/x-pascal diff --git a/magic/pdf b/magic/pdf deleted file mode 100644 index 761006ffe6..0000000000 --- a/magic/pdf +++ /dev/null @@ -1,8 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# pdf: file(1) magic for Portable Document Format -# - -0 string %PDF- PDF document -!:mime application/pdf diff --git a/magic/perl b/magic/perl deleted file mode 100644 index 12ec33b73a..0000000000 --- a/magic/perl +++ /dev/null @@ -1,26 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: perl,v 1.19 2012/06/20 21:16:25 christos Exp $ -# perl: file(1) magic for Larry Wall's perl language. -# -# The `eval' lines recognizes an outrageously clever hack. -# Keith Waclena -# Send additions to -0 search/1/w #!\ /bin/perl Perl script text executable -!:mime text/x-perl -0 search/1 eval\ "exec\ /bin/perl Perl script text -!:mime text/x-perl -0 search/1/w #!\ /usr/bin/perl Perl script text executable -!:mime text/x-perl -0 search/1 eval\ "exec\ /usr/bin/perl Perl script text -!:mime text/x-perl -0 search/1/w #!\ /usr/local/bin/perl Perl script text executable -!:mime text/x-perl -0 search/1 eval\ "exec\ /usr/local/bin/perl Perl script text -!:mime text/x-perl -0 search/1 eval\ '(exit\ $?0)'\ &&\ eval\ 'exec Perl script text -!:mime text/x-perl -0 search/1 #!/usr/bin/env\ perl Perl script text executable -!:mime text/x-perl -0 search/1 #!\ /usr/bin/env\ perl Perl script text executable -!:mime text/x-perl diff --git a/magic/pgp b/magic/pgp deleted file mode 100644 index 2bdfb77981..0000000000 --- a/magic/pgp +++ /dev/null @@ -1,27 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# pgp: file(1) magic for Pretty Good Privacy -# see http://lists.gnupg.org/pipermail/gnupg-devel/1999-September/016052.html -# -0 beshort 0x9900 PGP key public ring -!:mime application/x-pgp-keyring -0 beshort 0x9501 PGP key security ring -!:mime application/x-pgp-keyring -0 beshort 0x9500 PGP key security ring -!:mime application/x-pgp-keyring -0 beshort 0xa600 PGP encrypted data -#!:mime application/pgp-encrypted -#0 string -----BEGIN\040PGP text/PGP armored data -!:mime text/PGP # encoding: armored data -#>15 string PUBLIC\040KEY\040BLOCK- public key block -#>15 string MESSAGE- message -#>15 string SIGNED\040MESSAGE- signed message -#>15 string PGP\040SIGNATURE- signature - -2 string ---BEGIN\ PGP\ PUBLIC\ KEY\ BLOCK- PGP public key block -!:mime application/pgp-keys -0 string -----BEGIN\040PGP\40MESSAGE- PGP message -!:mime application/pgp -0 string -----BEGIN\040PGP\40SIGNATURE- PGP signature -!:mime application/pgp-signature diff --git a/magic/pkgadd b/magic/pkgadd deleted file mode 100644 index 602b4ec21d..0000000000 --- a/magic/pkgadd +++ /dev/null @@ -1,7 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# pkgadd: file(1) magic for SysV R4 PKG Datastreams -# -0 string #\ PaCkAgE\ DaTaStReAm pkg Datastream (SVR4) -!:mime application/x-svr4-package diff --git a/magic/printer b/magic/printer deleted file mode 100644 index cdce275b12..0000000000 --- a/magic/printer +++ /dev/null @@ -1,14 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: printer,v 1.24 2011/05/08 16:34:51 christos Exp $ -# printer: file(1) magic for printer-formatted files -# - -# PostScript, updated by Daniel Quinlan (quinlan@yggdrasil.com) -0 string %! PostScript document text -!:mime application/postscript -!:apple ASPSTEXT -# Some PCs have the annoying habit of adding a ^D as a document separator -0 string \004%! PostScript document text -!:mime application/postscript -!:apple ASPSTEXT diff --git a/magic/python b/magic/python deleted file mode 100644 index 1cd724bc59..0000000000 --- a/magic/python +++ /dev/null @@ -1,46 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: python,v 1.21 2012/06/21 01:12:51 christos Exp $ -# python: file(1) magic for python -# - -0 search/1/w #!\ /usr/bin/python Python script text executable -!:mime text/x-python -0 search/1/w #!\ /usr/local/bin/python Python script text executable -!:mime text/x-python -0 search/1 #!/usr/bin/env\ python Python script text executable -!:mime text/x-python -0 search/1 #!\ /usr/bin/env\ python Python script text executable -!:mime text/x-python - -# from module.submodule import func1, func2 -0 regex \^from\\s+(\\w|\\.)+\\s+import.*$ Python script text executable -!:mime text/x-python - -# def __init__ (self, ...): -0 search/4096 def\ __init__ ->&0 search/64 self Python script text executable -!:mime text/x-python - -# comments -0 search/4096 ''' ->&0 regex .*'''$ Python script text executable -!:mime text/x-python - -0 search/4096 """ ->&0 regex .*"""$ Python script text executable -!:mime text/x-python - -# try: -# except: or finally: -# block -0 search/4096 try: ->&0 regex \^\\s*except.*: Python script text executable -!:mime text/x-python ->&0 search/4096 finally: Python script text executable -!:mime text/x-python - -# def name(args, args): -0 regex \^(\ |\\t)*def\ +[a-zA-Z]+ ->&0 regex \ *\\(([a-zA-Z]|,|\ )*\\):$ Python script text executable -!:mime text/x-python diff --git a/magic/riff b/magic/riff deleted file mode 100644 index 929dc9aa89..0000000000 --- a/magic/riff +++ /dev/null @@ -1,36 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: riff,v 1.22 2011/09/06 11:00:06 christos Exp $ -# riff: file(1) magic for RIFF format -# See -# -# http://www.seanet.com/users/matts/riffmci/riffmci.htm -# -# AVI section extended by Patrik Radman -# -0 string RIFF RIFF (little-endian) data -# Microsoft WAVE format (*.wav) ->8 string WAVE \b, WAVE audio -!:mime audio/x-wav -# Corel Draw Picture ->8 string CDRA \b, Corel Draw Picture -!:mime image/x-coreldraw -# AVI == Audio Video Interleave ->8 string AVI\040 \b, AVI -!:mime video/x-msvideo - -#------------------------------------------------------------------------------ -# Sony Wave64 -# see http://www.vcs.de/fileadmin/user_upload/MBS/PDF/Whitepaper/Informations_about_Sony_Wave64.pdf -# 128 bit RIFF-GUID { 66666972-912E-11CF-A5D6-28DB04C10000 } in little-endian -0 string riff\x2E\x91\xCF\x11\xA5\xD6\x28\xDB\x04\xC1\x00\x00 Sony Wave64 RIFF data -# 128 bit + total file size (64 bits) so 24 bytes -# then WAVE-GUID { 65766177-ACF3-11D3-8CD1-00C04F8EDB8A } ->24 string wave\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A \b, WAVE 64 audio -!:mime audio/x-w64 - -#------------------------------------------------------------------------------ -# MBWF/RF64 -# see EBU TECH 3306 http://tech.ebu.ch/docs/tech/tech3306-2009.pdf -0 string RF64\xff\xff\xff\xffWAVEds64 MBWF/RF64 audio -!:mime audio/x-wav diff --git a/magic/rpm b/magic/rpm deleted file mode 100644 index 2558ebeef1..0000000000 --- a/magic/rpm +++ /dev/null @@ -1,12 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: rpm,v 1.11 2011/06/14 12:47:41 christos Exp $ -# -# RPM: file(1) magic for Red Hat Packages Erik Troan (ewt@redhat.com) -# -0 belong 0xedabeedb RPM -!:mime application/x-rpm - -#delta RPM Daniel Novotny (dnovotny@redhat.com) -0 string drpm Delta RPM -!:mime application/x-rpm diff --git a/magic/rtf b/magic/rtf deleted file mode 100644 index 0719264e47..0000000000 --- a/magic/rtf +++ /dev/null @@ -1,9 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# rtf: file(1) magic for Rich Text Format (RTF) -# -# Duncan P. Simpson, D.P.Simpson@dcs.warwick.ac.uk -# -0 string {\\rtf Rich Text Format data, -!:mime text/rtf diff --git a/magic/ruby b/magic/ruby deleted file mode 100644 index 41682a89ad..0000000000 --- a/magic/ruby +++ /dev/null @@ -1,28 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: ruby,v 1.4 2010/07/08 20:24:13 christos Exp $ -# ruby: file(1) magic for Ruby scripting language -# URL: http://www.ruby-lang.org/ -# From: Reuben Thomas - -# Ruby scripts -0 search/1/w #!\ /usr/bin/ruby Ruby script text executable -!:mime text/x-ruby -0 search/1/w #!\ /usr/local/bin/ruby Ruby script text executable -!:mime text/x-ruby -0 search/1 #!/usr/bin/env\ ruby Ruby script text executable -!:mime text/x-ruby -0 search/1 #!\ /usr/bin/env\ ruby Ruby script text executable -!:mime text/x-ruby - -# What looks like ruby, but does not have a shebang -# (modules and such) -# From: Lubomir Rintel -0 regex \^[\ \t]*require[\ \t]'[A-Za-z_/]+' ->0 regex include\ [A-Z]|def\ [a-z]|\ do$ ->>0 regex \^[\ \t]*end([\ \t]*[;#].*)?$ Ruby script text -!:mime text/x-ruby -0 regex \^[\ \t]*(class|module)[\ \t][A-Z] ->0 regex (modul|includ)e\ [A-Z]|def\ [a-z] ->>0 regex \^[\ \t]*end([\ \t]*[;#].*)?$ Ruby module source text -!:mime text/x-ruby diff --git a/magic/sc b/magic/sc deleted file mode 100644 index 75333b3916..0000000000 --- a/magic/sc +++ /dev/null @@ -1,7 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# sc: file(1) magic for "sc" spreadsheet -# -38 string Spreadsheet sc spreadsheet file -!:mime application/x-sc diff --git a/magic/sgml b/magic/sgml deleted file mode 100644 index 64efa2c153..0000000000 --- a/magic/sgml +++ /dev/null @@ -1,82 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: sgml,v 1.28 2012/04/28 21:20:26 christos Exp $ -# Type: SVG Vectorial Graphics -# From: Noel Torres -0 string \15 string >\0 ->>19 search/4096 \>19 search/4096 \15 string >\0 ->>19 search/4096/cWbt \15 string >\0 ->>19 search/4096/cWbt \15 string >\0 ->>19 search/4096/cWbt \ - -# Although we may know the offset of certain text fields in TeX DVI -# and font files, we can't use them reliably because they are not -# zero terminated. [but we do anyway, christos] -0 string \367\002 TeX DVI file -!:mime application/x-dvi - -# There is no way to detect TeX Font Metric (*.tfm) files without -# breaking them apart and reading the data. The following patterns -# match most *.tfm files generated by METAFONT or afm2tfm. -2 string \000\021 TeX font metric data -!:mime application/x-tex-tfm -2 string \000\022 TeX font metric data -!:mime application/x-tex-tfm - -# Texinfo and GNU Info, from Daniel Quinlan (quinlan@yggdrasil.com) -0 search/1 \\input\ texinfo Texinfo source text -!:mime text/x-texinfo -0 search/1 This\ is\ Info\ file GNU Info text -!:mime text/x-info - -# TeX documents, from Daniel Quinlan (quinlan@yggdrasil.com) -0 search/4096 \\input TeX document text -!:mime text/x-tex -!:strength + 15 -0 search/4096 \\section LaTeX document text -!:mime text/x-tex -!:strength + 18 -0 search/4096 \\setlength LaTeX document text -!:mime text/x-tex -!:strength + 15 -0 search/4096 \\documentstyle LaTeX document text -!:mime text/x-tex -!:strength + 18 -0 search/4096 \\chapter LaTeX document text -!:mime text/x-tex -!:strength + 18 -0 search/4096 \\documentclass LaTeX 2e document text -!:mime text/x-tex -!:strength + 15 -0 search/4096 \\relax LaTeX auxiliary file -!:mime text/x-tex -!:strength + 15 -0 search/4096 \\contentsline LaTeX table of contents -!:mime text/x-tex -!:strength + 15 -0 search/4096 %\ -*-latex-*- LaTeX document text -!:mime text/x-tex diff --git a/magic/troff b/magic/troff deleted file mode 100644 index 7f60b1d9b3..0000000000 --- a/magic/troff +++ /dev/null @@ -1,22 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# troff: file(1) magic for *roff -# -# updated by Daniel Quinlan (quinlan@yggdrasil.com) - -# troff input -0 search/1 .\\" troff or preprocessor input text -!:mime text/troff -0 search/1 '\\" troff or preprocessor input text -!:mime text/troff -0 search/1 '.\\" troff or preprocessor input text -!:mime text/troff -0 search/1 \\" troff or preprocessor input text -!:mime text/troff -0 search/1 ''' troff or preprocessor input text -!:mime text/troff -0 regex/20 \^\\.[A-Za-z0-9][A-Za-z0-9][\ \t] troff or preprocessor input text -!:mime text/troff -0 regex/20 \^\\.[A-Za-z0-9][A-Za-z0-9]$ troff or preprocessor input text -!:mime text/troff diff --git a/magic/vorbis b/magic/vorbis deleted file mode 100644 index 4d25c3c3cd..0000000000 --- a/magic/vorbis +++ /dev/null @@ -1,26 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File$ -# vorbis: file(1) magic for Ogg/Vorbis files -# -# From Felix von Leitner -# Extended by Beni Cherniavsky -# Further extended by Greg Wooledge -# -# Most (everything but the number of channels and bitrate) is commented -# out with `##' as it's not interesting to the average user. The most -# probable things advanced users would want to uncomment are probably -# the number of comments and the encoder version. -# -# FIXME: The first match has been made a search, so that it can skip -# over prepended ID3 tags. This will work for MIME type detection, but -# won't work for detecting other properties of the file (they all need -# to be made relative to the search). In any case, if the file has ID3 -# tags, the ID3 information will be printed, not the Ogg information, -# so until that's fixed, this doesn't matter. -# FIXME[2]: Disable the above for now, since search assumes text mode. -# -# --- Ogg Framing --- -#0 search/1000 OggS Ogg data -0 string OggS Ogg data -!:mime application/ogg diff --git a/magic/warc b/magic/warc deleted file mode 100644 index 2a2aeb6fae..0000000000 --- a/magic/warc +++ /dev/null @@ -1,14 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: warc,v 1.2 2009/09/19 16:28:13 christos Exp $ -# warc: file(1) magic for WARC files - -0 string WARC/ WARC Archive ->5 string x version %.4s -!:mime application/warc - -#------------------------------------------------------------------------------ -# Arc File Format from Internet Archive -# see http://www.archive.org/web/researcher/ArcFileFormat.php -0 string filedesc:// Internet Archive File -!:mime application/x-ia-arc diff --git a/magic/windows b/magic/windows deleted file mode 100644 index 6a529782a9..0000000000 --- a/magic/windows +++ /dev/null @@ -1,19 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: windows,v 1.4 2009/09/19 16:28:13 christos Exp $ -# windows: file(1) magic for Microsoft Windows -# -# This file is mainly reserved for files where programs -# using them are run almost always on MS Windows 3.x or -# above, or files only used exclusively in Windows OS, -# where there is no better category to allocate for. -# For example, even though WinZIP almost run on Windows -# only, it is better to treat them as "archive" instead. -# For format usable in DOS, such as generic executable -# format, please specify under "msdos" file. -# - -# From: Pal Tamas -# Autorun File -0 string/c [autorun]\r\n Microsoft Windows Autorun file. -!:mime application/x-setupscript. diff --git a/magic/wordprocessors b/magic/wordprocessors deleted file mode 100644 index 7de3413c0a..0000000000 --- a/magic/wordprocessors +++ /dev/null @@ -1,43 +0,0 @@ -# See COPYING file in this directory for original libmagic copyright. -#------------------------------------------------------------------------------ -# $File: wordprocessors,v 1.16 2012/10/29 17:36:49 christos Exp $ -# wordprocessors: file(1) magic fo word processors. -# - -# Hangul (Korean) Word Processor File -# From: Won-Kyu Park -512 string R\0o\0o\0t\0 Hangul (Korean) Word Processor File 2000 -!:mime application/x-hwp - -# Quark Express from http://www.garykessler.net/library/file_sigs.html -2 string MMXPR3 Motorola Quark Express Document (English) -!:mime application/x-quark-xpress-3 - -#------------------------------------------------------------------------------ -# ichitaro456: file(1) magic for Just System Word Processor Ichitaro -# -# Contributor kenzo-: -# Reversed-engineered JS Ichitaro magic numbers -# - -0 string DOC ->43 byte 0x14 Just System Word Processor Ichitaro v4 -!:mime application/x-ichitaro4 - -0 string DOC ->43 byte 0x15 Just System Word Processor Ichitaro v5 -!:mime application/x-ichitaro5 - -0 string DOC ->43 byte 0x16 Just System Word Processor Ichitaro v6 -!:mime application/x-ichitaro6 - -# Type: Freemind mindmap documents -# From: Jamie Thompson -0 string/w \ -0 string \ Date: Wed, 10 Jul 2013 16:29:07 -0400 Subject: [PATCH 116/881] Added support for files to the notice framework. --- scripts/base/frameworks/notice/main.bro | 34 ++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/scripts/base/frameworks/notice/main.bro b/scripts/base/frameworks/notice/main.bro index 30e0013517..f47ed79940 100644 --- a/scripts/base/frameworks/notice/main.bro +++ b/scripts/base/frameworks/notice/main.bro @@ -68,6 +68,19 @@ export { ## the notice policy. iconn: icmp_conn &optional; + ## A file record if the notice is relted to a file. The + ## reference to the actual fa_file record will be deleted after applying + ## the notice policy. + f: fa_file &optional; + + ## A file unique ID if this notice is related to a file. If the $f + ## field is provided, this will be automatically filled out. + fuid: string &log &optional; + + ## A mime type if the notice is related to a file. If the $f field + ## is provided, this will be automatically filled out. + mime_type: string &log &optional; + ## The transport protocol. Filled automatically when either conn, iconn ## or p is specified. proto: transport_proto &log &optional; @@ -460,6 +473,19 @@ function apply_policy(n: Notice::Info) if ( ! n?$ts ) n$ts = network_time(); + if ( n?$f ) + { + if ( ! n?$fuid ) + n$fuid = n$f$id; + if ( ! n?$mime_type && n$f?$mime_type ) + n$mime_type = n$f$mime_type; + if ( |n$f$conns| == 1 ) + { + for ( id in n$f$conns ) + n$conn = n$f$conns[id]; + } + } + if ( n?$conn ) { if ( ! n?$id ) @@ -513,13 +539,15 @@ function apply_policy(n: Notice::Info) if ( ! n?$suppress_for ) n$suppress_for = default_suppression_interval; - # Delete the connection record if it's there so we aren't sending that - # to remote machines. It can cause problems due to the size of the - # connection record. + # Delete the connection and file records if they're there so we + # aren't sending that to remote machines. It can cause problems + # due to the size of those records. if ( n?$conn ) delete n$conn; if ( n?$iconn ) delete n$iconn; + if ( n?$f ) + delete n$f; } function internal_NOTICE(n: Notice::Info) From 22b4f8dd90f1b5b1262240efb94a3f65546ace04 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 10 Jul 2013 16:51:22 -0400 Subject: [PATCH 117/881] Fix a small issue with finding smtp entities. --- scripts/base/protocols/smtp/entities.bro | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/base/protocols/smtp/entities.bro b/scripts/base/protocols/smtp/entities.bro index ec43b39ce1..159c10b5ab 100644 --- a/scripts/base/protocols/smtp/entities.bro +++ b/scripts/base/protocols/smtp/entities.bro @@ -33,12 +33,12 @@ event mime_begin_entity(c: connection) &priority=10 event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 { - if ( f$source != "SMTP" ) - return; - - if ( c$smtp$entity?$filename ) - f$info$filename = c$smtp$entity$filename; - f$info$depth = c$smtp_state$mime_depth; + if ( f$source == "SMTP" && c?$smtp ) + { + if ( c$smtp?$entity && c$smtp$entity?$filename ) + f$info$filename = c$smtp$entity$filename; + f$info$depth = c$smtp_state$mime_depth; + } } event mime_one_header(c: connection, h: mime_header_rec) &priority=5 From bf4f57383f5f0639257ecac3651c7b01004a3a02 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 10 Jul 2013 16:52:39 -0400 Subject: [PATCH 118/881] Improve malware hash registry script. - Include a link to a virustotal search in the notice sub message field. - Give all information returned from Team Cymru in the notice message. - Add more file types to match on to the default set. --- .../policy/frameworks/files/detect-MHR.bro | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/scripts/policy/frameworks/files/detect-MHR.bro b/scripts/policy/frameworks/files/detect-MHR.bro index c896bd56fd..ebfc97fd26 100644 --- a/scripts/policy/frameworks/files/detect-MHR.bro +++ b/scripts/policy/frameworks/files/detect-MHR.bro @@ -5,7 +5,7 @@ @load base/frameworks/notice @load frameworks/files/hash-all-files -module MalwareHashRegistery; +module TeamCymruMalwareHashRegistry; export { redef enum Notice::Type += { @@ -14,16 +14,12 @@ export { Match }; - redef record Files::Info += { - ## Team Cymru Malware Hash Registry date of first detection. - mhr_first_detected: time &log &optional; - ## Team Cymru Malware Hash Registry percent of detection - ## among malware scanners. - mhr_detect_rate: count &log &optional; - }; - ## File types to attempt matching against the Malware Hash Registry. - const match_file_types = /^application\/x-dosexec/ &redef; + const match_file_types = /application\/x-dosexec/ | + /application\/pdf/ | + /application\/x-shockwave-flash/ | + /application\/x-java-applet/ | + /video\/mp4/ &redef; ## The malware hash registry runs each malware sample through several A/V engines. ## Team Cymru returns a percentage to indicate how many A/V engines flagged the @@ -43,19 +39,15 @@ event file_hash(f: fa_file, kind: string, hash: string) local MHR_answer = split1(MHR_result, / /); if ( |MHR_answer| == 2 ) { - f$info$mhr_first_detected = double_to_time(to_double(MHR_answer[1])); - f$info$mhr_detect_rate = to_count(MHR_answer[2]); + local mhr_first_detected = double_to_time(to_double(MHR_answer[1])); + local mhr_detect_rate = to_count(MHR_answer[2]); - #print strftime("%Y-%m-%d %H:%M:%S", f$info$mhr_first_detected); - if ( f$info$mhr_detect_rate >= notice_threshold ) + local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected); + if ( mhr_detect_rate >= notice_threshold ) { - local url = ""; - # TODO: Create a generic mechanism for creating file "urls". - #if ( f$source == "HTTP" ) - # url = HTTP::build_url_http(f); - local message = fmt("%s %s", hash, url); - #local message = fmt("Host(s) %s sent a file with SHA1 hash %s to host %s", f$src_host, hash, f$dst_host); - NOTICE([$note=Match, $msg=message]); + local message = fmt("Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected); + local virustotal_url = fmt("https://www.virustotal.com/en/file/%s/analysis/", hash); + NOTICE([$note=Match, $msg=message, $sub=virustotal_url, $f=f]); } } } From be8c947c040ac828036a70938bcc3f721a5a480d Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 10 Jul 2013 17:04:09 -0400 Subject: [PATCH 119/881] Adding CAB files for MHR checking. --- scripts/policy/frameworks/files/detect-MHR.bro | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/policy/frameworks/files/detect-MHR.bro b/scripts/policy/frameworks/files/detect-MHR.bro index ebfc97fd26..18875ade4c 100644 --- a/scripts/policy/frameworks/files/detect-MHR.bro +++ b/scripts/policy/frameworks/files/detect-MHR.bro @@ -16,6 +16,7 @@ export { ## File types to attempt matching against the Malware Hash Registry. const match_file_types = /application\/x-dosexec/ | + /application\/vnd.ms-cab-compressed/ | /application\/pdf/ | /application\/x-shockwave-flash/ | /application\/x-java-applet/ | From 8a0cc31d0a0a433627b599a648dea1fd98cfabf6 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 10 Jul 2013 14:59:40 -0700 Subject: [PATCH 120/881] Switching btest to topic/robin/parts branch. --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 3585dc9a7a..7b5055a664 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 3585dc9a7afe20d70cb77fc2472cc6bce3850b67 +Subproject commit 7b5055a664f8f26f45fed2d10f9e900776f1bac0 From ef6b4885dd5d4955c7c5d09520a6d9ad450e7bc1 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 10 Jul 2013 15:07:44 -0700 Subject: [PATCH 121/881] Adding some temporary testing/demonstration to front page. --- doc/index.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/index.rst b/doc/index.rst index 32c01a6e7d..f5df8f95e4 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -17,3 +17,29 @@ Bro Documentation misc/index.rst components/index.rst indices/index.rst + +Just Testing +============ + +.. code:: bro + + print "Hey Bro!" + +.. btest:: test + + @TEST-COPY-FILE: ${TRACES}/wikipedia.trace + @TEST-EXEC: btest-rst-cmd bro -r wikipedia.trace + @TEST-EXEC: btest-rst-cmd "cat http.log | bro-cut ts id.orig_h | head -5" + +Test part 1 coming up. + +.. btest:: test-parts + + @TEST-EXEC: echo It works! >output + +Something else here. + +.. btest:: test-parts + + @TEST-EXEC: btest-rst-include output + From 3d5c17e9e01b812398d5cc928c63d883d2a89d55 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 10 Jul 2013 23:46:01 -0400 Subject: [PATCH 122/881] Add jar files to the default MHR lookups. --- scripts/policy/frameworks/files/detect-MHR.bro | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/policy/frameworks/files/detect-MHR.bro b/scripts/policy/frameworks/files/detect-MHR.bro index 18875ade4c..71d73217e0 100644 --- a/scripts/policy/frameworks/files/detect-MHR.bro +++ b/scripts/policy/frameworks/files/detect-MHR.bro @@ -20,6 +20,7 @@ export { /application\/pdf/ | /application\/x-shockwave-flash/ | /application\/x-java-applet/ | + /application\/jar/ | /video\/mp4/ &redef; ## The malware hash registry runs each malware sample through several A/V engines. From 1a60fae41c057bb150604d53fa6a15ed3bf2b629 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 11 Jul 2013 11:28:55 -0500 Subject: [PATCH 123/881] Clean up queued but unused file_over_new_connections event args. --- src/file_analysis/File.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index 9a06fa3db9..7189d90932 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -100,7 +100,12 @@ File::~File() { DBG_LOG(DBG_FILE_ANALYSIS, "Destroying File object %s", id.c_str()); Unref(val); - assert(fonc_queue.empty()); + // Queue may not be empty in the case where only content gaps were seen. + while ( ! fonc_queue.empty() ) + { + delete_vals(fonc_queue.front().second); + fonc_queue.pop(); + } } void File::UpdateLastActivityTime() From b14f5a853eb67a5e312bc612a062889b594d1a58 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 12 Jul 2013 16:06:40 -0400 Subject: [PATCH 124/881] Added mime types to http.log --- scripts/base/protocols/http/entities.bro | 54 +++++++++++++++++++++--- scripts/base/protocols/http/files.bro | 19 --------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/scripts/base/protocols/http/entities.bro b/scripts/base/protocols/http/entities.bro index fc8ab753ae..dcddf6fc4f 100644 --- a/scripts/base/protocols/http/entities.bro +++ b/scripts/base/protocols/http/entities.bro @@ -9,14 +9,23 @@ module HTTP; export { type Entity: record { - ## Depth of the entity if multiple entities are sent in a single transaction. - depth: count &default=0; - ## Filename for the entity if discovered from a header. filename: string &optional; }; redef record Info += { + ## An ordered vector of file unique IDs. + orig_fuids: vector of string &log &optional; + + ## An ordered vector of mime types. + orig_mime_types: vector of string &log &optional; + + ## An ordered vector of file unique IDs. + resp_fuids: vector of string &log &optional; + + ## An ordered vector of mime types. + resp_mime_types: vector of string &log &optional; + ## The current entity being seen. entity: Entity &optional; @@ -36,7 +45,7 @@ event http_begin_entity(c: connection, is_orig: bool) &priority=10 else ++c$http$resp_mime_depth; - c$http$entity = Entity($depth = is_orig ? c$http$orig_mime_depth : c$http$resp_mime_depth); + c$http$entity = Entity(); } event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=3 @@ -55,12 +64,43 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 { - if ( f$source == "HTTP" && c$http?$entity ) + if ( f$source == "HTTP" && c?$http ) { - f$info$depth = c$http$entity$depth; - if ( c$http$entity?$filename ) + if ( c$http?$entity && c$http$entity?$filename ) f$info$filename = c$http$entity$filename; + + if ( f$is_orig ) + { + if ( ! c$http?$resp_mime_types ) + c$http$resp_fuids = string_vec(f$id); + else + c$http$orig_fuids[|c$http$orig_fuids|] = f$id; + + if ( f?$mime_type ) + { + if ( ! c$http?$orig_mime_types ) + c$http$orig_mime_types = string_vec(f$mime_type); + else + c$http$orig_mime_types[|c$http$orig_mime_types|] = f$mime_type; + } + } + else + { + if ( ! c$http?$resp_mime_types ) + c$http$resp_fuids = string_vec(f$id); + else + c$http$resp_fuids[|c$http$resp_fuids|] = f$id; + + if ( f?$mime_type ) + { + if ( ! c$http?$resp_mime_types ) + c$http$resp_mime_types = string_vec(f$mime_type); + else + c$http$resp_mime_types[|c$http$resp_mime_types|] = f$mime_type; + } + } } + } event http_end_entity(c: connection, is_orig: bool) &priority=5 diff --git a/scripts/base/protocols/http/files.bro b/scripts/base/protocols/http/files.bro index e45ff8cadb..09324b5f45 100644 --- a/scripts/base/protocols/http/files.bro +++ b/scripts/base/protocols/http/files.bro @@ -6,14 +6,6 @@ module HTTP; export { - redef record Info += { - ## An ordered vector of file unique IDs seen sent by the originator (client). - orig_fuids: vector of string &log &default=string_vec(); - - ## An ordered vector of file unique IDs seen sent by the responder (server). - resp_fuids: vector of string &log &default=string_vec(); - }; - ## Default file handle provider for HTTP. global get_file_handle: function(c: connection, is_orig: bool): string; } @@ -39,14 +31,3 @@ event bro_init() &priority=5 { Files::register_protocol(Analyzer::ANALYZER_HTTP, HTTP::get_file_handle); } - -event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 - { - if ( c?$http ) - { - if ( f$is_orig ) - c$http$orig_fuids[|c$http$orig_fuids|] = f$id; - else - c$http$resp_fuids[|c$http$resp_fuids|] = f$id; - } - } From 4dd4c5344e071cf2f9996852369fa2a5a90909bd Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 12 Jul 2013 16:12:26 -0400 Subject: [PATCH 125/881] Fix a bug where orig file information in http wasn't working right. --- scripts/base/protocols/http/entities.bro | 31 ++++++++++++------------ 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/scripts/base/protocols/http/entities.bro b/scripts/base/protocols/http/entities.bro index dcddf6fc4f..e9376a0c0c 100644 --- a/scripts/base/protocols/http/entities.bro +++ b/scripts/base/protocols/http/entities.bro @@ -15,24 +15,23 @@ export { redef record Info += { ## An ordered vector of file unique IDs. - orig_fuids: vector of string &log &optional; + orig_fuids: vector of string &log &optional; ## An ordered vector of mime types. orig_mime_types: vector of string &log &optional; ## An ordered vector of file unique IDs. - resp_fuids: vector of string &log &optional; + resp_fuids: vector of string &log &optional; ## An ordered vector of mime types. resp_mime_types: vector of string &log &optional; - ## The current entity being seen. - entity: Entity &optional; - + ## The current entity. + current_entity: Entity &optional; ## Current number of MIME entities in the HTTP request message body. - orig_mime_depth: count &default=0; + orig_mime_depth: count &default=0; ## Current number of MIME entities in the HTTP response message body. - resp_mime_depth: count &default=0; + resp_mime_depth: count &default=0; }; } @@ -45,7 +44,7 @@ event http_begin_entity(c: connection, is_orig: bool) &priority=10 else ++c$http$resp_mime_depth; - c$http$entity = Entity(); + c$http$current_entity = Entity(); } event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=3 @@ -53,12 +52,12 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr if ( name == "CONTENT-DISPOSITION" && /[fF][iI][lL][eE][nN][aA][mM][eE]/ in value ) { - c$http$entity$filename = extract_filename_from_content_disposition(value); + c$http$current_entity$filename = extract_filename_from_content_disposition(value); } else if ( name == "CONTENT-TYPE" && /[nN][aA][mM][eE][:blank:]*=/ in value ) { - c$http$entity$filename = extract_filename_from_content_disposition(value); + c$http$current_entity$filename = extract_filename_from_content_disposition(value); } } @@ -66,13 +65,13 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori { if ( f$source == "HTTP" && c?$http ) { - if ( c$http?$entity && c$http$entity?$filename ) - f$info$filename = c$http$entity$filename; + if ( c$http?$current_entity && c$http$current_entity?$filename ) + f$info$filename = c$http$current_entity$filename; if ( f$is_orig ) { - if ( ! c$http?$resp_mime_types ) - c$http$resp_fuids = string_vec(f$id); + if ( ! c$http?$orig_mime_types ) + c$http$orig_fuids = string_vec(f$id); else c$http$orig_fuids[|c$http$orig_fuids|] = f$id; @@ -105,6 +104,6 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori event http_end_entity(c: connection, is_orig: bool) &priority=5 { - if ( c?$http && c$http?$entity ) - delete c$http$entity; + if ( c?$http && c$http?$current_entity ) + delete c$http$current_entity; } From 0bfdcc1fbca326e563ea4a6db5e69be05f2fbed5 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 16 Jul 2013 12:01:50 -0400 Subject: [PATCH 126/881] Added protocol description functions that provide a super compressed log representation. --- scripts/base/frameworks/analyzer/main.bro | 12 +++++ scripts/base/frameworks/files/main.bro | 50 ++++++++++++++++---- scripts/base/frameworks/notice/main.bro | 19 ++++++-- scripts/base/protocols/ftp/__load__.bro | 1 + scripts/base/protocols/ftp/files.bro | 21 +++++++- scripts/base/protocols/ftp/main.bro | 50 +++++++------------- scripts/base/protocols/http/files.bro | 21 +++++++- scripts/base/protocols/http/utils.bro | 8 ++++ scripts/base/protocols/irc/file-analysis.bro | 23 --------- scripts/base/protocols/irc/files.bro | 3 +- scripts/base/protocols/smtp/files.bro | 21 +++++++- scripts/base/protocols/smtp/main.bro | 31 +++++++++++- src/analyzer/analyzer.bif | 5 ++ 13 files changed, 190 insertions(+), 75 deletions(-) delete mode 100644 scripts/base/protocols/irc/file-analysis.bro diff --git a/scripts/base/frameworks/analyzer/main.bro b/scripts/base/frameworks/analyzer/main.bro index c4ee5c943b..e266eb8c7a 100644 --- a/scripts/base/frameworks/analyzer/main.bro +++ b/scripts/base/frameworks/analyzer/main.bro @@ -81,6 +81,13 @@ export { ## Returns: The analyzer name corresponding to the tag. global name: function(tag: Analyzer::Tag) : string; + ## Translates an analyzer's name to a tag enum value. + ## + ## name: The analyzer name. + ## + ## Returns: The analyzer tag corresponding to the name. + global get_tag: function(name: string): Analyzer::Tag; + ## Schedules an analyzer for a future connection originating from a given IP ## address and port. ## @@ -187,6 +194,11 @@ function name(atype: Analyzer::Tag) : string return __name(atype); } +function get_tag(name: string): Analyzer::Tag + { + return __tag(name); + } + function schedule_analyzer(orig: addr, resp: addr, resp_p: port, analyzer: Analyzer::Tag, tout: interval) : bool { diff --git a/scripts/base/frameworks/files/main.bro b/scripts/base/frameworks/files/main.bro index 8dd07fcb53..cc92932bbf 100644 --- a/scripts/base/frameworks/files/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -2,6 +2,7 @@ ##! any network protocol over which they're transported. @load base/bif/file_analysis.bif +@load base/frameworks/analyzer @load base/frameworks/logging @load base/utils/site @@ -173,17 +174,36 @@ export { ## Returns: The analyzer name corresponding to the tag. global analyzer_name: function(tag: Files::Tag): string; + ## Provides a text description regarding metadata of the file. + ## For example, with HTTP it would return a URL. + ## + ## f: The file to be described. + ## + ## Returns a text description regarding metadata of the file. + global describe: function(f: fa_file): string; + + type ProtoRegistration: record { + ## A callback to generate a file handle on demand when + ## one is needed by the core. + get_file_handle: function(c: connection, is_orig: bool): string; + + ## A callback to "describe" a file. In the case of an HTTP + ## transfer the most obvious description would be the URL. + ## It's like an extremely compressed version of the normal log. + describe: function(f: fa_file): string + &default=function(f: fa_file): string { return ""; }; + }; + ## Register callbacks for protocols that work with the Files framework. ## The callbacks must uniquely identify a file and each protocol can ## only have a single callback registered for it. ## ## tag: Tag for the protocol analyzer having a callback being registered. ## - ## callback: Function that can generate a file handle for the protocol analyzer - ## defined previously. + ## reg: A :bro:see:`ProtoRegistration` record. ## ## Returns: true if the protocol being registered was not previously registered. - global register_protocol: function(tag: Files::Tag, callback: function(c: connection, is_orig: bool): string): bool; + global register_protocol: function(tag: Analyzer::Tag, reg: ProtoRegistration): bool; ## Register a callback for file analyzers to use if they need to do some manipulation ## when they are being added to a file before the core code takes over. This is @@ -210,8 +230,7 @@ redef record AnalyzerArgs += { }; # Store the callbacks for protocol analyzers that have files. -global registered_protocols: table[Files::Tag] of function(c: connection, is_orig: bool): string = table() - &default=function(c: connection, is_orig: bool): string { return cat(c$uid, is_orig); }; +global registered_protocols: table[Analyzer::Tag] of ProtoRegistration = table(); global analyzer_add_callbacks: table[Files::Tag] of function(f: fa_file, args: AnalyzerArgs) = table(); @@ -321,15 +340,28 @@ event file_state_remove(f: fa_file) &priority=-10 Log::write(Files::LOG, f$info); } -function register_protocol(tag: Files::Tag, callback: function(c: connection, is_orig: bool): string): bool +function register_protocol(tag: Analyzer::Tag, reg: ProtoRegistration): bool { local result = (tag !in registered_protocols); - registered_protocols[tag] = callback; + registered_protocols[tag] = reg; return result; } -event get_file_handle(tag: Files::Tag, c: connection, is_orig: bool) &priority=5 +function describe(f: fa_file): string { + local tag = Analyzer::get_tag(f$source); + if ( tag !in registered_protocols ) + return ""; + local handler = registered_protocols[tag]; - set_file_handle(handler(c, is_orig)); + return handler$describe(f); + } + +event get_file_handle(tag: Analyzer::Tag, c: connection, is_orig: bool) &priority=5 + { + if ( tag !in registered_protocols ) + return; + + local handler = registered_protocols[tag]; + set_file_handle(handler$get_file_handle(c, is_orig)); } diff --git a/scripts/base/frameworks/notice/main.bro b/scripts/base/frameworks/notice/main.bro index f47ed79940..5bd01e0982 100644 --- a/scripts/base/frameworks/notice/main.bro +++ b/scripts/base/frameworks/notice/main.bro @@ -79,7 +79,13 @@ export { ## A mime type if the notice is related to a file. If the $f field ## is provided, this will be automatically filled out. - mime_type: string &log &optional; + file_mime_type: string &log &optional; + + ## Frequently files can be "described" to give a bit more context. + ## This field will typically be automatically filled out from an + ## fa_file record. For example, if a notice was related to a + ## file over HTTP, the URL of the request would be shown. + file_desc: string &log &optional; ## The transport protocol. Filled automatically when either conn, iconn ## or p is specified. @@ -477,9 +483,13 @@ function apply_policy(n: Notice::Info) { if ( ! n?$fuid ) n$fuid = n$f$id; - if ( ! n?$mime_type && n$f?$mime_type ) - n$mime_type = n$f$mime_type; - if ( |n$f$conns| == 1 ) + + if ( ! n?$file_mime_type && n$f?$mime_type ) + n$file_mime_type = n$f$mime_type; + + n$file_desc = Files::describe(n$f); + + if ( n$f?$conns && |n$f$conns| == 1 ) { for ( id in n$f$conns ) n$conn = n$f$conns[id]; @@ -490,6 +500,7 @@ function apply_policy(n: Notice::Info) { if ( ! n?$id ) n$id = n$conn$id; + if ( ! n?$uid ) n$uid = n$conn$uid; } diff --git a/scripts/base/protocols/ftp/__load__.bro b/scripts/base/protocols/ftp/__load__.bro index bc68f61cea..ebb09e702c 100644 --- a/scripts/base/protocols/ftp/__load__.bro +++ b/scripts/base/protocols/ftp/__load__.bro @@ -1,5 +1,6 @@ @load ./utils-commands @load ./main +@load ./utils @load ./files @load ./gridftp diff --git a/scripts/base/protocols/ftp/files.bro b/scripts/base/protocols/ftp/files.bro index c68717c8a2..1d7b7670f4 100644 --- a/scripts/base/protocols/ftp/files.bro +++ b/scripts/base/protocols/ftp/files.bro @@ -12,6 +12,9 @@ export { ## Default file handle provider for FTP. global get_file_handle: function(c: connection, is_orig: bool): string; + + ## Describe the file being transferred. + global describe_file: function(f: fa_file): string; } function get_file_handle(c: connection, is_orig: bool): string @@ -22,9 +25,25 @@ function get_file_handle(c: connection, is_orig: bool): string return cat(Analyzer::ANALYZER_FTP_DATA, c$start_time, c$id, is_orig); } +function describe_file(f: fa_file): string + { + # This shouldn't be needed, but just in case... + if ( f$source != "FTP" ) + return ""; + + for ( cid in f$conns ) + { + if ( f$conns[cid]?$ftp ) + return FTP::describe(f$conns[cid]$ftp); + } + return ""; + } + event bro_init() &priority=5 { - Files::register_protocol(Analyzer::ANALYZER_FTP_DATA, FTP::get_file_handle); + Files::register_protocol(Analyzer::ANALYZER_FTP_DATA, + [$get_file_handle = FTP::get_file_handle, + $describe = FTP::describe_file]); } diff --git a/scripts/base/protocols/ftp/main.bro b/scripts/base/protocols/ftp/main.bro index 7bf9d6cc4c..f525c7792b 100644 --- a/scripts/base/protocols/ftp/main.bro +++ b/scripts/base/protocols/ftp/main.bro @@ -63,8 +63,6 @@ export { reply_code: count &log &optional; ## Reply message from the server in response to the command. reply_msg: string &log &optional; - ## Arbitrary tags that may indicate a particular attribute of this command. - tags: set[string] &log; ## Expected FTP data channel. data_channel: ExpectedDataChannel &log &optional; @@ -171,37 +169,22 @@ function set_ftp_session(c: connection) function ftp_message(s: Info) { - # If it either has a tag associated with it (something detected) - # or it's a deliberately logged command. - if ( |s$tags| > 0 || (s?$cmdarg && s$cmdarg$cmd in logged_commands) ) + s$ts=s$cmdarg$ts; + s$command=s$cmdarg$cmd; + s$arg=s$cmdarg$arg; + if ( s$arg == "" ) + delete s$arg; + + if ( s?$password && + ! s$capture_password && + to_lower(s$user) !in guest_ids ) { - if ( s?$password && - ! s$capture_password && - to_lower(s$user) !in guest_ids ) - { - s$password = ""; - } - - local arg = s$cmdarg$arg; - if ( s$cmdarg$cmd in file_cmds ) - { - local comp_path = build_path_compressed(s$cwd, arg); - if ( comp_path[0] != "/" ) - comp_path = cat("/", comp_path); - - arg = fmt("ftp://%s%s", addr_to_uri(s$id$resp_h), comp_path); - } - - s$ts=s$cmdarg$ts; - s$command=s$cmdarg$cmd; - if ( arg == "" ) - delete s$arg; - else - s$arg=arg; - - Log::write(FTP::LOG, s); + s$password = ""; } + if ( s?$cmdarg && s$command in logged_commands) + Log::write(FTP::LOG, s); + # The MIME and file_size fields are specific to file transfer commands # and may not be used in all commands so they need reset to "blank" # values after logging. @@ -209,8 +192,6 @@ function ftp_message(s: Info) delete s$file_size; # Same with data channel. delete s$data_channel; - # Tags are cleared everytime too. - s$tags = set(); } function add_expected_data_channel(s: Info, chan: ExpectedDataChannel) @@ -218,8 +199,9 @@ function add_expected_data_channel(s: Info, chan: ExpectedDataChannel) s$passive = chan$passive; s$data_channel = chan; ftp_data_expected[chan$resp_h, chan$resp_p] = s; - Analyzer::schedule_analyzer(chan$orig_h, chan$resp_h, chan$resp_p, Analyzer::ANALYZER_FTP_DATA, - 5mins); + Analyzer::schedule_analyzer(chan$orig_h, chan$resp_h, chan$resp_p, + Analyzer::ANALYZER_FTP_DATA, + 5mins); } event ftp_request(c: connection, command: string, arg: string) &priority=5 diff --git a/scripts/base/protocols/http/files.bro b/scripts/base/protocols/http/files.bro index 09324b5f45..fd07dc096a 100644 --- a/scripts/base/protocols/http/files.bro +++ b/scripts/base/protocols/http/files.bro @@ -8,6 +8,9 @@ module HTTP; export { ## Default file handle provider for HTTP. global get_file_handle: function(c: connection, is_orig: bool): string; + + ## Default file describer for HTTP. + global describe_file: function(f: fa_file): string; } function get_file_handle(c: connection, is_orig: bool): string @@ -27,7 +30,23 @@ function get_file_handle(c: connection, is_orig: bool): string } } +function describe_file(f: fa_file): string + { + # This shouldn't be needed, but just in case... + if ( f$source != "HTTP" ) + return ""; + + for ( cid in f$conns ) + { + if ( f$conns[cid]?$http ) + return build_url_http(f$conns[cid]$http); + } + return ""; + } + event bro_init() &priority=5 { - Files::register_protocol(Analyzer::ANALYZER_HTTP, HTTP::get_file_handle); + Files::register_protocol(Analyzer::ANALYZER_HTTP, + [$get_file_handle = HTTP::get_file_handle, + $describe = HTTP::describe_file]); } diff --git a/scripts/base/protocols/http/utils.bro b/scripts/base/protocols/http/utils.bro index a74a2fe696..fe8c076780 100644 --- a/scripts/base/protocols/http/utils.bro +++ b/scripts/base/protocols/http/utils.bro @@ -32,6 +32,9 @@ export { ## ## Returns: A URL prefixed with "http://". global build_url_http: function(rec: Info): string; + + ## Create an extremely shortened representation of a log line. + global describe: function(rec: Info): string; } @@ -62,3 +65,8 @@ function build_url_http(rec: Info): string { return fmt("http://%s", build_url(rec)); } + +function describe(rec: Info): string + { + return build_url_http(rec); + } diff --git a/scripts/base/protocols/irc/file-analysis.bro b/scripts/base/protocols/irc/file-analysis.bro deleted file mode 100644 index f2e84fbc22..0000000000 --- a/scripts/base/protocols/irc/file-analysis.bro +++ /dev/null @@ -1,23 +0,0 @@ -@load ./dcc-send -@load base/utils/conn-ids -@load base/frameworks/files - -module IRC; - -export { - ## Default file handle provider for IRC. - global get_file_handle: function(c: connection, is_orig: bool): string; -} - -function get_file_handle(c: connection, is_orig: bool): string - { - if ( [c$id$resp_h, c$id$resp_p] !in dcc_expected_transfers ) - return ""; - - return cat(ANALYZER_IRC_DATA, c$start_time, c$id, is_orig); - } - -event bro_init() &priority=5 - { - Files::register_protocol(ANALYZER_IRC_DATA, IRC::get_file_handle); - } diff --git a/scripts/base/protocols/irc/files.bro b/scripts/base/protocols/irc/files.bro index 8708270bfd..a6321d3f2f 100644 --- a/scripts/base/protocols/irc/files.bro +++ b/scripts/base/protocols/irc/files.bro @@ -24,7 +24,8 @@ function get_file_handle(c: connection, is_orig: bool): string event bro_init() &priority=5 { - Files::register_protocol(Analyzer::ANALYZER_IRC_DATA, IRC::get_file_handle); + Files::register_protocol(Analyzer::ANALYZER_IRC_DATA, + [$get_file_handle = IRC::get_file_handle]); } event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 diff --git a/scripts/base/protocols/smtp/files.bro b/scripts/base/protocols/smtp/files.bro index 1cf9ec01e1..f9ae2ab05f 100644 --- a/scripts/base/protocols/smtp/files.bro +++ b/scripts/base/protocols/smtp/files.bro @@ -14,6 +14,9 @@ export { ## Default file handle provider for SMTP. global get_file_handle: function(c: connection, is_orig: bool): string; + + ## Default file describer for SMTP. + global describe_file: function(f: fa_file): string; } function get_file_handle(c: connection, is_orig: bool): string @@ -22,9 +25,25 @@ function get_file_handle(c: connection, is_orig: bool): string c$smtp_state$mime_depth); } +function describe_file(f: fa_file): string + { + # This shouldn't be needed, but just in case... + if ( f$source != "SMTP" ) + return ""; + + for ( cid in f$conns ) + { + local c = f$conns[cid]; + return SMTP::describe(c$smtp); + } + return ""; + } + event bro_init() &priority=5 { - Files::register_protocol(Analyzer::ANALYZER_SMTP, SMTP::get_file_handle); + Files::register_protocol(Analyzer::ANALYZER_SMTP, + [$get_file_handle = SMTP::get_file_handle, + $describe = SMTP::describe_file]); } event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 diff --git a/scripts/base/protocols/smtp/main.bro b/scripts/base/protocols/smtp/main.bro index d53128b06c..702cb9fc0e 100644 --- a/scripts/base/protocols/smtp/main.bro +++ b/scripts/base/protocols/smtp/main.bro @@ -72,7 +72,10 @@ export { ## ALL_HOSTS - always capture the entire path. ## NO_HOSTS - never capture the path. const mail_path_capture = ALL_HOSTS &redef; - + + ## Create an extremely shortened representation of a log line. + global describe: function(rec: Info): string; + global log_smtp: event(rec: Info); } @@ -268,3 +271,29 @@ event connection_state_remove(c: connection) &priority=-5 if ( c?$smtp ) smtp_message(c); } + +function describe(rec: Info): string + { + if ( rec?$mailfrom && rec?$rcptto ) + { + local one_to = ""; + for ( to in rec$rcptto ) + { + one_to = to; + break; + } + local abbrev_subject = ""; + if ( rec?$subject ) + { + if ( |rec$subject| > 20 ) + { + abbrev_subject = rec$subject[0:20] + "..."; + } + } + + return fmt("%s -> %s%s%s", rec$mailfrom, one_to, + (|rec$rcptto|>1 ? fmt(" (plus %d others)", |rec$rcptto|-1) : ""), + (abbrev_subject != "" ? fmt(": %s", abbrev_subject) : "")); + } + return ""; + } \ No newline at end of file diff --git a/src/analyzer/analyzer.bif b/src/analyzer/analyzer.bif index 7f3cc6ed94..8b5a85956c 100644 --- a/src/analyzer/analyzer.bif +++ b/src/analyzer/analyzer.bif @@ -43,3 +43,8 @@ function __name%(atype: Analyzer::Tag%) : string %{ return new StringVal(analyzer_mgr->GetAnalyzerName(atype)); %} + +function __tag%(name: string%) : Analyzer::Tag + %{ + return new Val(analyzer_mgr->GetAnalyzerTag(name->CheckString()), TYPE_ENUM); + %} From eb7ceb3e9ac4bc49f7a337bcc56046350aaa89d5 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 16 Jul 2013 12:07:33 -0400 Subject: [PATCH 127/881] Forgot a file. --- scripts/base/protocols/ftp/utils.bro | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 scripts/base/protocols/ftp/utils.bro diff --git a/scripts/base/protocols/ftp/utils.bro b/scripts/base/protocols/ftp/utils.bro new file mode 100644 index 0000000000..629b87e5a8 --- /dev/null +++ b/scripts/base/protocols/ftp/utils.bro @@ -0,0 +1,47 @@ +##! Utilities specific for FTP processing. + +@load ./main +@load base/utils/addrs + +module FTP; + +export { + ## Creates a URL from an :bro:type:`FTP::Info` record. + ## + ## rec: An :bro:type:`FTP::Info` record. + ## + ## Returns: A URL, not prefixed by "ftp://". + global build_url: function(rec: Info): string; + + ## Creates a URL from an :bro:type:`FTP::Info` record. + ## + ## rec: An :bro:type:`FTP::Info` record. + ## + ## Returns: A URL prefixed with "ftp://". + global build_url_ftp: function(rec: Info): string; + + ## Create an extremely shortened representation of a log line. + global describe: function(rec: Info): string; +} + +function build_url(rec: Info): string + { + if ( !rec?$arg ) + return ""; + + local comp_path = build_path_compressed(rec$cwd, rec$arg); + if ( comp_path[0] != "/" ) + comp_path = cat("/", comp_path); + + return fmt("%s%s", addr_to_uri(rec$id$resp_h), comp_path); + } + +function build_url_ftp(rec: Info): string + { + return fmt("ftp://%s", build_url(rec)); + } + +function describe(rec: Info): string + { + return build_url_ftp(rec); + } \ No newline at end of file From 9b444b2617c0a910a24ea938a3064eb092f26537 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 19 Jul 2013 13:16:12 -0400 Subject: [PATCH 128/881] Updates for the Intel Framework. - Intel importing format has changed (refer to docs). - All string matching is now case insensitive. - SMTP intel script has been updated to extract email addresses correctly. - Small fix sneaking into the smtp base script to actually extract individual email addresses in the To: field correctly. --- doc/intel.rst | 20 +-- scripts/base/frameworks/intel/main.bro | 141 ++++++++---------- scripts/base/protocols/smtp/main.bro | 5 +- .../frameworks/intel/conn-established.bro | 8 +- scripts/policy/frameworks/intel/dns.bro | 4 +- .../frameworks/intel/http-host-header.bro | 4 +- scripts/policy/frameworks/intel/http-url.bro | 4 +- .../frameworks/intel/http-user-agents.bro | 4 +- .../frameworks/intel/smtp-url-extraction.bro | 4 +- scripts/policy/frameworks/intel/smtp.bro | 70 ++++++--- scripts/policy/frameworks/intel/ssl.bro | 12 +- .../manager-1.intel.log | 10 +- .../broproc.intel.log | 12 +- .../manager-1.intel.log | 16 +- .../frameworks/intel/cluster-transparency.bro | 8 +- .../base/frameworks/intel/input-and-match.bro | 12 +- .../intel/read-file-dist-cluster.bro | 10 +- 17 files changed, 178 insertions(+), 166 deletions(-) diff --git a/doc/intel.rst b/doc/intel.rst index 390313461a..2a59a98974 100644 --- a/doc/intel.rst +++ b/doc/intel.rst @@ -29,9 +29,6 @@ Framework to be checked by loading this script in local.bro:: @load policy/frameworks/intel -(TODO: find some good mechanism for getting setup with good data -quickly) - Refer to the "Loading Intelligence" section below to see the format for Intelligence Framework text files, then load those text files with this line in local.bro:: @@ -61,16 +58,14 @@ data out to all of the nodes that need it. Here is an example of the intelligence data format. Note that all whitespace separators are literal tabs and fields containing only a -hyphen a considered to be null values.:: +hyphen are considered to be null values.:: - #fields host net str str_type meta.source meta.desc meta.url - 1.2.3.4 - - - source1 Sending phishing email http://source1.com/badhosts/1.2.3.4 - - 31.131.248.0/21 - - spamhaus-drop SBL154982 - - - - - a.b.com Intel::DOMAIN source2 Name used for data exfiltration - + #fields indicator indicator_type meta.source meta.desc meta.url + 1.2.3.4 Intel::ADDR source1 Sending phishing email http://source1.com/badhosts/1.2.3.4 + a.b.com Intel::DOMAIN source2 Name used for data exfiltration - -For more examples of built in `str_type` values, please refer to the -autogenerated documentation for the intelligence framework (TODO: -figure out how to do this link). +For more examples of built in `indicator_type` values, please refer to the +autogenerated documentation for the intelligence framework. To load the data once files are created, use the following example code to define files to load with your own file names of course:: @@ -90,8 +85,7 @@ When some bit of data is extracted (such as an email address in the "From" header in a message over SMTP), the Intelligence Framework needs to be informed that this data was discovered and it's presence should be checked within the intelligence data set. This is -accomplished through the Intel::seen (TODO: do a reference link) -function. +accomplished through the Intel::seen function. Typically users won't need to work with this function due to built in hook scripts that Bro ships with that will "see" data and send it into diff --git a/scripts/base/frameworks/intel/main.bro b/scripts/base/frameworks/intel/main.bro index aeb7bf4bfc..1b740f538d 100644 --- a/scripts/base/frameworks/intel/main.bro +++ b/scripts/base/frameworks/intel/main.bro @@ -10,13 +10,14 @@ module Intel; export { redef enum Log::ID += { LOG }; - ## String data needs to be further categoried since it could represent - ## and number of types of data. - type StrType: enum { + ## Enum type to represent various types of intelligence data. + type Type: enum { + ## An IP address. + ADDR, ## A complete URL without the prefix "http://". URL, - ## User-Agent string, typically HTTP or mail message body. - USER_AGENT, + ## Software name. + SOFTWARE, ## Email address. EMAIL, ## DNS domain name. @@ -44,18 +45,15 @@ export { ## Represents a piece of intelligence. type Item: record { - ## The IP address if the intelligence is about an IP address. - host: addr &optional; - ## The network if the intelligence is about a CIDR block. - net: subnet &optional; - ## The string if the intelligence is about a string. - str: string &optional; - ## The type of data that is in the string if the $str field is set. - str_type: StrType &optional; + ## The intelligence indicator. + indicator: string; + + ## The type of data that the indicator field represents. + indicator_type: Type; - ## Metadata for the item. Typically represents more deeply \ + ## Metadata for the item. Typically represents more deeply ## descriptive data for a piece of intelligence. - meta: MetaData; + meta: MetaData; }; ## Enum to represent where data came from when it was discovered. @@ -69,19 +67,22 @@ export { ## exclusive. These records *must* represent either an IP address being ## seen or a string being seen. type Seen: record { - ## The IP address if the data seen is an IP address. - host: addr &log &optional; ## The string if the data is about a string. - str: string &log &optional; - ## The type of data that is in the string if the $str field is set. - str_type: StrType &log &optional; + indicator: string &log &optional; + + ## The type of data that the indicator represents. + indicator_type: Type &log &optional; + + ## If the indicator type was :bro:enum:`Intel::ADDR`, then this + ## field will be present. + host: addr &optional; ## Where the data was discovered. - where: Where &log; + where: Where &log; ## If the data was discovered within a connection, the ## connection record should go into get to give context to the data. - conn: connection &optional; + conn: connection &optional; }; ## Record used for the logging framework representing a positive @@ -100,7 +101,7 @@ export { ## Where the data was seen. seen: Seen &log; ## Sources which supplied data that resulted in this match. - sources: set[string] &log; + sources: set[string] &log &default=string_set(); }; ## Intelligence data manipulation functions. @@ -135,8 +136,8 @@ const have_full_data = T &redef; # The in memory data structure for holding intelligence. type DataStore: record { - net_data: table[subnet] of set[MetaData]; - string_data: table[string, StrType] of set[MetaData]; + host_data: table[addr] of set[MetaData]; + string_data: table[string, Type] of set[MetaData]; }; global data_store: DataStore &redef; @@ -144,8 +145,8 @@ global data_store: DataStore &redef; # This is primarily for workers to do the initial quick matches and store # a minimal amount of data for the full match to happen on the manager. type MinDataStore: record { - net_data: set[subnet]; - string_data: set[string, StrType]; + host_data: set[addr]; + string_data: set[string, Type]; }; global min_data_store: MinDataStore &redef; @@ -157,15 +158,13 @@ event bro_init() &priority=5 function find(s: Seen): bool { - if ( s?$host && - ((have_full_data && s$host in data_store$net_data) || - (s$host in min_data_store$net_data))) + if ( s?$host ) { - return T; + return ((s$host in min_data_store$host_data) || + (have_full_data && s$host in data_store$host_data)); } - else if ( s?$str && s?$str_type && - ((have_full_data && [s$str, s$str_type] in data_store$string_data) || - ([s$str, s$str_type] in min_data_store$string_data))) + else if ( ([to_lower(s$indicator), s$indicator_type] in min_data_store$string_data) || + (have_full_data && [to_lower(s$indicator), s$indicator_type] in data_store$string_data) ) { return T; } @@ -177,8 +176,7 @@ function find(s: Seen): bool function get_items(s: Seen): set[Item] { - local item: Item; - local return_data: set[Item] = set(); + local return_data: set[Item]; if ( ! have_full_data ) { @@ -191,26 +189,23 @@ function get_items(s: Seen): set[Item] if ( s?$host ) { # See if the host is known about and it has meta values - if ( s$host in data_store$net_data ) + if ( s$host in data_store$host_data ) { - for ( m in data_store$net_data[s$host] ) + for ( m in data_store$host_data[s$host] ) { - # TODO: the lookup should be finding all and not just most specific - # and $host/$net should have the correct value. - item = [$host=s$host, $meta=m]; - add return_data[item]; + add return_data[Item($indicator=cat(s$host), $indicator_type=ADDR, $meta=m)]; } } } - else if ( s?$str && s?$str_type ) + else { + local lower_indicator = to_lower(s$indicator); # See if the string is known about and it has meta values - if ( [s$str, s$str_type] in data_store$string_data ) + if ( [lower_indicator, s$indicator_type] in data_store$string_data ) { - for ( m in data_store$string_data[s$str, s$str_type] ) + for ( m in data_store$string_data[lower_indicator, s$indicator_type] ) { - item = [$str=s$str, $str_type=s$str_type, $meta=m]; - add return_data[item]; + add return_data[Item($indicator=s$indicator, $indicator_type=s$indicator_type, $meta=m)]; } } } @@ -222,6 +217,12 @@ function Intel::seen(s: Seen) { if ( find(s) ) { + if ( s?$host ) + { + s$indicator = cat(s$host); + s$indicator_type = Intel::ADDR; + } + if ( have_full_data ) { local items = get_items(s); @@ -250,8 +251,7 @@ function has_meta(check: MetaData, metas: set[MetaData]): bool event Intel::match(s: Seen, items: set[Item]) &priority=5 { - local empty_set: set[string] = set(); - local info: Info = [$ts=network_time(), $seen=s, $sources=empty_set]; + local info: Info = [$ts=network_time(), $seen=s]; if ( s?$conn ) { @@ -267,52 +267,37 @@ event Intel::match(s: Seen, items: set[Item]) &priority=5 function insert(item: Item) { - if ( item?$str && !item?$str_type ) - { - event reporter_warning(network_time(), fmt("You must provide a str_type for strings or this item doesn't make sense. Item: %s", item), ""); - return; - } - # Create and fill out the meta data item. local meta = item$meta; local metas: set[MetaData]; - if ( item?$host ) + # All intelligence is case insensitive at the moment. + local lower_indicator = to_lower(item$indicator); + + if ( item$indicator_type == ADDR ) { - local host = mask_addr(item$host, is_v4_addr(item$host) ? 32 : 128); + local host = to_addr(item$indicator); if ( have_full_data ) { - if ( host !in data_store$net_data ) - data_store$net_data[host] = set(); + if ( host !in data_store$host_data ) + data_store$host_data[host] = set(); - metas = data_store$net_data[host]; + metas = data_store$host_data[host]; } - add min_data_store$net_data[host]; + add min_data_store$host_data[host]; } - else if ( item?$net ) + else { if ( have_full_data ) { - if ( item$net !in data_store$net_data ) - data_store$net_data[item$net] = set(); + if ( [lower_indicator, item$indicator_type] !in data_store$string_data ) + data_store$string_data[lower_indicator, item$indicator_type] = set(); - metas = data_store$net_data[item$net]; + metas = data_store$string_data[lower_indicator, item$indicator_type]; } - add min_data_store$net_data[item$net]; - } - else if ( item?$str ) - { - if ( have_full_data ) - { - if ( [item$str, item$str_type] !in data_store$string_data ) - data_store$string_data[item$str, item$str_type] = set(); - - metas = data_store$string_data[item$str, item$str_type]; - } - - add min_data_store$string_data[item$str, item$str_type]; + add min_data_store$string_data[lower_indicator, item$indicator_type]; } local updated = F; diff --git a/scripts/base/protocols/smtp/main.bro b/scripts/base/protocols/smtp/main.bro index d53128b06c..0d510e645d 100644 --- a/scripts/base/protocols/smtp/main.bro +++ b/scripts/base/protocols/smtp/main.bro @@ -223,7 +223,10 @@ event mime_one_header(c: connection, h: mime_header_rec) &priority=5 { if ( ! c$smtp?$to ) c$smtp$to = set(); - add c$smtp$to[h$value]; + + local to_parts = split(h$value, /[[:blank:]]*,[[:blank:]]*/); + for ( i in to_parts ) + add c$smtp$to[to_parts[i]]; } else if ( h$name == "X-ORIGINATING-IP" ) diff --git a/scripts/policy/frameworks/intel/conn-established.bro b/scripts/policy/frameworks/intel/conn-established.bro index a2e67b292b..20cec43e04 100644 --- a/scripts/policy/frameworks/intel/conn-established.bro +++ b/scripts/policy/frameworks/intel/conn-established.bro @@ -3,6 +3,10 @@ event connection_established(c: connection) { - Intel::seen([$host=c$id$orig_h, $conn=c, $where=Conn::IN_ORIG]); - Intel::seen([$host=c$id$resp_h, $conn=c, $where=Conn::IN_RESP]); + if ( c$orig$state == TCP_ESTABLISHED && + c$resp$state == TCP_ESTABLISHED ) + { + Intel::seen([$host=c$id$orig_h, $conn=c, $where=Conn::IN_ORIG]); + Intel::seen([$host=c$id$resp_h, $conn=c, $where=Conn::IN_RESP]); + } } diff --git a/scripts/policy/frameworks/intel/dns.bro b/scripts/policy/frameworks/intel/dns.bro index a0dee47acf..9218586c95 100644 --- a/scripts/policy/frameworks/intel/dns.bro +++ b/scripts/policy/frameworks/intel/dns.bro @@ -3,8 +3,8 @@ event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) { - Intel::seen([$str=query, - $str_type=Intel::DOMAIN, + Intel::seen([$indicator=query, + $indicator_type=Intel::DOMAIN, $conn=c, $where=DNS::IN_REQUEST]); } diff --git a/scripts/policy/frameworks/intel/http-host-header.bro b/scripts/policy/frameworks/intel/http-host-header.bro index f16b1628aa..3fd28b8ef9 100644 --- a/scripts/policy/frameworks/intel/http-host-header.bro +++ b/scripts/policy/frameworks/intel/http-host-header.bro @@ -4,8 +4,8 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) { if ( is_orig && name == "HOST" ) - Intel::seen([$str=value, - $str_type=Intel::DOMAIN, + Intel::seen([$indicator=value, + $indicator_type=Intel::DOMAIN, $conn=c, $where=HTTP::IN_HOST_HEADER]); } diff --git a/scripts/policy/frameworks/intel/http-url.bro b/scripts/policy/frameworks/intel/http-url.bro index feef4f0dac..340ae3c5ab 100644 --- a/scripts/policy/frameworks/intel/http-url.bro +++ b/scripts/policy/frameworks/intel/http-url.bro @@ -5,8 +5,8 @@ event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) { if ( is_orig && c?$http ) - Intel::seen([$str=HTTP::build_url(c$http), - $str_type=Intel::URL, + Intel::seen([$indicator=HTTP::build_url(c$http), + $indicator_type=Intel::URL, $conn=c, $where=HTTP::IN_URL]); } diff --git a/scripts/policy/frameworks/intel/http-user-agents.bro b/scripts/policy/frameworks/intel/http-user-agents.bro index 93445c1e43..7c4558d2a5 100644 --- a/scripts/policy/frameworks/intel/http-user-agents.bro +++ b/scripts/policy/frameworks/intel/http-user-agents.bro @@ -4,8 +4,8 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) { if ( is_orig && name == "USER-AGENT" ) - Intel::seen([$str=value, - $str_type=Intel::USER_AGENT, + Intel::seen([$indicator=value, + $indicator_type=Intel::SOFTWARE, $conn=c, $where=HTTP::IN_USER_AGENT_HEADER]); } diff --git a/scripts/policy/frameworks/intel/smtp-url-extraction.bro b/scripts/policy/frameworks/intel/smtp-url-extraction.bro index 2b87f809a6..a3ba410641 100644 --- a/scripts/policy/frameworks/intel/smtp-url-extraction.bro +++ b/scripts/policy/frameworks/intel/smtp-url-extraction.bro @@ -13,8 +13,8 @@ event intel_mime_data(f: fa_file, data: string) local urls = find_all_urls_without_scheme(data); for ( url in urls ) { - Intel::seen([$str=url, - $str_type=Intel::URL, + Intel::seen([$indicator=url, + $indicator_type=Intel::URL, $conn=c, $where=SMTP::IN_MESSAGE]); } diff --git a/scripts/policy/frameworks/intel/smtp.bro b/scripts/policy/frameworks/intel/smtp.bro index 02e97ea54a..d760995e51 100644 --- a/scripts/policy/frameworks/intel/smtp.bro +++ b/scripts/policy/frameworks/intel/smtp.bro @@ -18,8 +18,8 @@ event mime_end_entity(c: connection) } if ( c$smtp?$user_agent ) - Intel::seen([$str=c$smtp$user_agent, - $str_type=Intel::USER_AGENT, + Intel::seen([$indicator=c$smtp$user_agent, + $indicator_type=Intel::SOFTWARE, $conn=c, $where=SMTP::IN_HEADER]); @@ -29,43 +29,69 @@ event mime_end_entity(c: connection) $where=SMTP::IN_X_ORIGINATING_IP_HEADER]); if ( c$smtp?$mailfrom ) - Intel::seen([$str=c$smtp$mailfrom, - $str_type=Intel::EMAIL, - $conn=c, - $where=SMTP::IN_MAIL_FROM]); + { + local mailfromparts = split_n(c$smtp$mailfrom, /<.+>/, T, 1); + if ( |mailfromparts| > 2 ) + { + Intel::seen([$indicator=mailfromparts[2][1:-2], + $indicator_type=Intel::EMAIL, + $conn=c, + $where=SMTP::IN_MAIL_FROM]); + } + } if ( c$smtp?$rcptto ) { for ( rcptto in c$smtp$rcptto ) { - Intel::seen([$str=rcptto, - $str_type=Intel::EMAIL, - $conn=c, - $where=SMTP::IN_RCPT_TO]); + local rcpttoparts = split_n(rcptto, /<.+>/, T, 1); + if ( |rcpttoparts| > 2 ) + { + Intel::seen([$indicator=rcpttoparts[2][1:-2], + $indicator_type=Intel::EMAIL, + $conn=c, + $where=SMTP::IN_RCPT_TO]); + } } } if ( c$smtp?$from ) - Intel::seen([$str=c$smtp$from, - $str_type=Intel::EMAIL, - $conn=c, - $where=SMTP::IN_FROM]); + { + local fromparts = split_n(c$smtp$from, /<.+>/, T, 1); + if ( |fromparts| > 2 ) + { + Intel::seen([$indicator=fromparts[2][1:-2], + $indicator_type=Intel::EMAIL, + $conn=c, + $where=SMTP::IN_FROM]); + } + } if ( c$smtp?$to ) { for ( email_to in c$smtp$to ) { - Intel::seen([$str=email_to, - $str_type=Intel::EMAIL, - $conn=c, - $where=SMTP::IN_TO]); + local toparts = split_n(email_to, /<.+>/, T, 1); + if ( |toparts| > 2 ) + { + Intel::seen([$indicator=toparts[2][1:-2], + $indicator_type=Intel::EMAIL, + $conn=c, + $where=SMTP::IN_TO]); + } } } if ( c$smtp?$reply_to ) - Intel::seen([$str=c$smtp$reply_to, - $str_type=Intel::EMAIL, - $conn=c, - $where=SMTP::IN_REPLY_TO]); + { + local replytoparts = split_n(c$smtp$reply_to, /<.+>/, T, 1); + if ( |replytoparts| > 2 ) + { + Intel::seen([$indicator=replytoparts[2][1:-2], + $indicator_type=Intel::EMAIL, + $conn=c, + $where=SMTP::IN_REPLY_TO]); + } + } } } diff --git a/scripts/policy/frameworks/intel/ssl.bro b/scripts/policy/frameworks/intel/ssl.bro index 3f18a11e6e..e404c39e5b 100644 --- a/scripts/policy/frameworks/intel/ssl.bro +++ b/scripts/policy/frameworks/intel/ssl.bro @@ -10,14 +10,14 @@ event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: coun { local email = sub(cert$subject, /^.*emailAddress=/, ""); email = sub(email, /,.*$/, ""); - Intel::seen([$str=email, - $str_type=Intel::EMAIL, + Intel::seen([$indicator=email, + $indicator_type=Intel::EMAIL, $conn=c, $where=(is_orig ? SSL::IN_CLIENT_CERT : SSL::IN_SERVER_CERT)]); } - Intel::seen([$str=sha1_hash(der_cert), - $str_type=Intel::CERT_HASH, + Intel::seen([$indicator=sha1_hash(der_cert), + $indicator_type=Intel::CERT_HASH, $conn=c, $where=(is_orig ? SSL::IN_CLIENT_CERT : SSL::IN_SERVER_CERT)]); } @@ -27,8 +27,8 @@ event ssl_extension(c: connection, is_orig: bool, code: count, val: string) { if ( is_orig && SSL::extensions[code] == "server_name" && c?$ssl && c$ssl?$server_name ) - Intel::seen([$str=c$ssl$server_name, - $str_type=Intel::DOMAIN, + Intel::seen([$indicator=c$ssl$server_name, + $indicator_type=Intel::DOMAIN, $conn=c, $where=SSL::IN_SERVER_NAME]); } diff --git a/testing/btest/Baseline/scripts.base.frameworks.intel.cluster-transparency/manager-1.intel.log b/testing/btest/Baseline/scripts.base.frameworks.intel.cluster-transparency/manager-1.intel.log index 26efc039c4..00871e7d93 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.intel.cluster-transparency/manager-1.intel.log +++ b/testing/btest/Baseline/scripts.base.frameworks.intel.cluster-transparency/manager-1.intel.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path intel -#open 2012-10-03-20-20-39 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p seen.host seen.str seen.str_type seen.where sources -#types time string addr port addr port addr string enum enum table[string] -1349295639.424940 - - - - - 123.123.123.123 - - Intel::IN_ANYWHERE worker-1 -#close 2012-10-03-20-20-49 +#open 2013-07-19-17-05-48 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p seen.indicator seen.indicator_type seen.where sources +#types time string addr port addr port string enum enum table[string] +1374253548.038580 - - - - - 123.123.123.123 Intel::ADDR Intel::IN_ANYWHERE worker-1 +#close 2013-07-19-17-05-57 diff --git a/testing/btest/Baseline/scripts.base.frameworks.intel.input-and-match/broproc.intel.log b/testing/btest/Baseline/scripts.base.frameworks.intel.input-and-match/broproc.intel.log index d72e9efed3..8c01ae5c27 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.intel.input-and-match/broproc.intel.log +++ b/testing/btest/Baseline/scripts.base.frameworks.intel.input-and-match/broproc.intel.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path intel -#open 2012-10-03-20-18-05 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p seen.host seen.str seen.str_type seen.where sources -#types time string addr port addr port addr string enum enum table[string] -1349295485.114156 - - - - - - e@mail.com Intel::EMAIL SOMEWHERE source1 -1349295485.114156 - - - - - 1.2.3.4 - - SOMEWHERE source1 -#close 2012-10-03-20-18-05 +#open 2013-07-19-17-04-26 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p seen.indicator seen.indicator_type seen.where sources +#types time string addr port addr port string enum enum table[string] +1374253466.857185 - - - - - e@mail.com Intel::EMAIL SOMEWHERE source1 +1374253466.857185 - - - - - 1.2.3.4 Intel::ADDR SOMEWHERE source1 +#close 2013-07-19-17-04-26 diff --git a/testing/btest/Baseline/scripts.base.frameworks.intel.read-file-dist-cluster/manager-1.intel.log b/testing/btest/Baseline/scripts.base.frameworks.intel.read-file-dist-cluster/manager-1.intel.log index 8069bad528..70d92a3604 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.intel.read-file-dist-cluster/manager-1.intel.log +++ b/testing/btest/Baseline/scripts.base.frameworks.intel.read-file-dist-cluster/manager-1.intel.log @@ -3,11 +3,11 @@ #empty_field (empty) #unset_field - #path intel -#open 2012-10-10-15-05-23 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p seen.host seen.str seen.str_type seen.where sources -#types time string addr port addr port addr string enum enum table[string] -1349881523.548946 - - - - - 1.2.3.4 - - Intel::IN_A_TEST source1 -1349881523.548946 - - - - - - e@mail.com Intel::EMAIL Intel::IN_A_TEST source1 -1349881524.567896 - - - - - 1.2.3.4 - - Intel::IN_A_TEST source1 -1349881524.567896 - - - - - - e@mail.com Intel::EMAIL Intel::IN_A_TEST source1 -#close 2012-10-10-15-05-24 +#open 2013-07-19-17-06-57 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p seen.indicator seen.indicator_type seen.where sources +#types time string addr port addr port string enum enum table[string] +1374253617.312158 - - - - - 1.2.3.4 Intel::ADDR Intel::IN_A_TEST source1 +1374253617.312158 - - - - - e@mail.com Intel::EMAIL Intel::IN_A_TEST source1 +1374253618.332565 - - - - - 1.2.3.4 Intel::ADDR Intel::IN_A_TEST source1 +1374253618.332565 - - - - - e@mail.com Intel::EMAIL Intel::IN_A_TEST source1 +#close 2013-07-19-17-07-06 diff --git a/testing/btest/scripts/base/frameworks/intel/cluster-transparency.bro b/testing/btest/scripts/base/frameworks/intel/cluster-transparency.bro index 3810de5d4b..4d977d475d 100644 --- a/testing/btest/scripts/base/frameworks/intel/cluster-transparency.bro +++ b/testing/btest/scripts/base/frameworks/intel/cluster-transparency.bro @@ -28,7 +28,7 @@ event remote_connection_handshake_done(p: event_peer) # Insert the data once both workers are connected. if ( Cluster::local_node_type() == Cluster::MANAGER && Cluster::worker_count == 2 ) { - Intel::insert([$host=1.2.3.4,$meta=[$source="manager"]]); + Intel::insert([$indicator="1.2.3.4", $indicator_type=Intel::ADDR, $meta=[$source="manager"]]); } } @@ -39,7 +39,7 @@ event Intel::cluster_new_item(item: Intel::Item) if ( ! is_remote_event() ) return; - print fmt("cluster_new_item: %s inserted by %s (from peer: %s)", item$host, item$meta$source, get_event_peer()$descr); + print fmt("cluster_new_item: %s inserted by %s (from peer: %s)", item$indicator, item$meta$source, get_event_peer()$descr); if ( ! sent_data ) { @@ -47,9 +47,9 @@ event Intel::cluster_new_item(item: Intel::Item) # full cluster is constructed. sent_data = T; if ( Cluster::node == "worker-1" ) - Intel::insert([$host=123.123.123.123,$meta=[$source="worker-1"]]); + Intel::insert([$indicator="123.123.123.123", $indicator_type=Intel::ADDR, $meta=[$source="worker-1"]]); if ( Cluster::node == "worker-2" ) - Intel::insert([$host=4.3.2.1,$meta=[$source="worker-2"]]); + Intel::insert([$indicator="4.3.2.1", $indicator_type=Intel::ADDR, $meta=[$source="worker-2"]]); } # We're forcing worker-2 to do a lookup when it has three intelligence items diff --git a/testing/btest/scripts/base/frameworks/intel/input-and-match.bro b/testing/btest/scripts/base/frameworks/intel/input-and-match.bro index f77f5c0f1d..7150d30993 100644 --- a/testing/btest/scripts/base/frameworks/intel/input-and-match.bro +++ b/testing/btest/scripts/base/frameworks/intel/input-and-match.bro @@ -5,10 +5,10 @@ # @TEST-EXEC: btest-diff broproc/intel.log @TEST-START-FILE intel.dat -#fields host net str str_type meta.source meta.desc meta.url -1.2.3.4 - - - source1 this host is just plain baaad http://some-data-distributor.com/1234 -1.2.3.4 - - - source1 this host is just plain baaad http://some-data-distributor.com/1234 -- - e@mail.com Intel::EMAIL source1 Phishing email source http://some-data-distributor.com/100000 +#fields indicator indicator_type meta.source meta.desc meta.url +1.2.3.4 Intel::ADDR source1 this host is just plain baaad http://some-data-distributor.com/1234 +1.2.3.4 Intel::ADDR source1 this host is just plain baaad http://some-data-distributor.com/1234 +e@mail.com Intel::EMAIL source1 Phishing email source http://some-data-distributor.com/100000 @TEST-END-FILE @load frameworks/communication/listen @@ -18,8 +18,8 @@ redef enum Intel::Where += { SOMEWHERE }; event do_it() { - Intel::seen([$str="e@mail.com", - $str_type=Intel::EMAIL, + Intel::seen([$indicator="e@mail.com", + $indicator_type=Intel::EMAIL, $where=SOMEWHERE]); Intel::seen([$host=1.2.3.4, diff --git a/testing/btest/scripts/base/frameworks/intel/read-file-dist-cluster.bro b/testing/btest/scripts/base/frameworks/intel/read-file-dist-cluster.bro index 6838736249..f336fe24b3 100644 --- a/testing/btest/scripts/base/frameworks/intel/read-file-dist-cluster.bro +++ b/testing/btest/scripts/base/frameworks/intel/read-file-dist-cluster.bro @@ -19,10 +19,10 @@ redef Cluster::nodes = { @TEST-END-FILE @TEST-START-FILE intel.dat -#fields host net str str_type meta.source meta.desc meta.url -1.2.3.4 - - - source1 this host is just plain baaad http://some-data-distributor.com/1234 -1.2.3.4 - - - source1 this host is just plain baaad http://some-data-distributor.com/1234 -- - e@mail.com Intel::EMAIL source1 Phishing email source http://some-data-distributor.com/100000 +#fields indicator indicator_type meta.source meta.desc meta.url +1.2.3.4 Intel::ADDR source1 this host is just plain baaad http://some-data-distributor.com/1234 +1.2.3.4 Intel::ADDR source1 this host is just plain baaad http://some-data-distributor.com/1234 +e@mail.com Intel::EMAIL source1 Phishing email source http://some-data-distributor.com/100000 @TEST-END-FILE @load base/frameworks/control @@ -41,7 +41,7 @@ redef enum Intel::Where += { event do_it() { Intel::seen([$host=1.2.3.4, $where=Intel::IN_A_TEST]); - Intel::seen([$str="e@mail.com", $str_type=Intel::EMAIL, $where=Intel::IN_A_TEST]); + Intel::seen([$indicator="e@mail.com", $indicator_type=Intel::EMAIL, $where=Intel::IN_A_TEST]); } event bro_init() From 9dae9dd3e26627d50c3a3620205eee3db88b2e4b Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 19 Jul 2013 13:53:15 -0400 Subject: [PATCH 129/881] Remove the intel insertion after heuristically detecting ssh bruteforcing. --- scripts/policy/protocols/ssh/detect-bruteforcing.bro | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro index 309905e939..ada418e61f 100644 --- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -58,10 +58,6 @@ event bro_init() $msg=fmt("%s appears to be guessing SSH passwords (seen in %d connections).", key$host, r$num), $src=key$host, $identifier=cat(key$host)]); - # Insert the guesser into the intel framework. - Intel::insert([$host=key$host, - $meta=[$source="local", - $desc=fmt("Bro observed %d apparently failed SSH connections.", r$num)]]); }]); } From 26f8bd7ad7d07a0cb03197bce6076ae0833f8b33 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Sat, 20 Jul 2013 01:21:01 -0400 Subject: [PATCH 130/881] Fix a reporter message in sumstats. --- scripts/base/frameworks/sumstats/main.bro | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/base/frameworks/sumstats/main.bro b/scripts/base/frameworks/sumstats/main.bro index 5c822e9983..3afa507c7a 100644 --- a/scripts/base/frameworks/sumstats/main.bro +++ b/scripts/base/frameworks/sumstats/main.bro @@ -122,6 +122,12 @@ export { ## A callback with the full collection of Results for ## this SumStat. epoch_finished: function(rt: SumStats::ResultTable) &optional; + #epoch_finished: function(num_keys: count) &optional; + + ## A callback that receives each of the results at the + ## end of the analysis epoch. The function will be + ## called once for each key. + #epoch_finished_result: function(key::SumStats::Key, result: SumStats::Result) &optional; }; ## Create a summary statistic. @@ -162,9 +168,6 @@ export { ## Returns: The result for the requested sumstat key. global request_key: function(ss_name: string, key: Key): Result; - ## This record is primarily used for internal threshold tracking. - type Thresholding: record {}; - ## This event is generated when thresholds are reset for a SumStat. ## ## name: SumStats name that thresholds were reset for. @@ -429,6 +432,7 @@ function observe(id: string, key: Key, obs: Observation) # future if on demand access is provided to the # SumStats results. if ( ! ss?$epoch_finished && + r$ssname in threshold_tracker && ( ss?$threshold && key in threshold_tracker[r$ssname] && threshold_tracker[r$ssname][key] != 0 ) || From 58f59b9bc3f00adeb46a0a1259ec3ab8ef05d355 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Sat, 20 Jul 2013 02:08:52 -0400 Subject: [PATCH 131/881] Add server samples to SSH bruteforce detection. --- scripts/policy/protocols/ssh/detect-bruteforcing.bro | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro index 161a314b8c..f8d41db2b8 100644 --- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -42,7 +42,7 @@ export { event bro_init() { - local r1: SumStats::Reducer = [$stream="ssh.login.failure", $apply=set(SumStats::SUM)]; + local r1: SumStats::Reducer = [$stream="ssh.login.failure", $apply=set(SumStats::SUM, SumStats::SAMPLE), $num_samples=5]; SumStats::create([$name="detect-ssh-bruteforcing", $epoch=guessing_timeout, $reducers=set(r1), @@ -54,9 +54,15 @@ event bro_init() $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = { local r = result["ssh.login.failure"]; + local sub_msg = fmt("Sampled servers: "); + for ( i in r$samples ) + { + sub_msg = fmt("%s%s %s", sub_msg, i==0 ? "":",", r$samples[i]$str); + } # Generate the notice. NOTICE([$note=Password_Guessing, $msg=fmt("%s appears to be guessing SSH passwords (seen in %d connections).", key$host, r$num), + $sub=sub_msg, $src=key$host, $identifier=cat(key$host)]); # Insert the guesser into the intel framework. @@ -83,5 +89,5 @@ event SSH::heuristic_failed_login(c: connection) # be ignored. if ( ! (id$orig_h in ignore_guessers && id$resp_h in ignore_guessers[id$orig_h]) ) - SumStats::observe("ssh.login.failure", [$host=id$orig_h], [$num=1]); + SumStats::observe("ssh.login.failure", [$host=id$orig_h], [$str=cat(id$resp_h)]); } From deeb5ec38e2f0c3dadcb7138d672cf1ff905d577 Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Thu, 18 Jul 2013 21:17:06 -0400 Subject: [PATCH 132/881] Rework the DHCP analyzer to make it compatible again. --- scripts/base/init-default.bro | 1 + scripts/base/protocols/dhcp/__load__.bro | 2 + scripts/base/protocols/dhcp/consts.bro | 20 ++ scripts/base/protocols/dhcp/main.bro | 74 +++++ scripts/base/protocols/dhcp/utils.bro | 21 ++ .../protocols/dhcp/handle_extra_msg_types.bro | 256 +++++++++++++++++ src/analyzer/protocol/dhcp/DHCP.cc | 1 - src/analyzer/protocol/dhcp/DHCP.h | 3 + src/analyzer/protocol/dhcp/dhcp-analyzer.pac | 269 ++++++++++-------- src/analyzer/protocol/dhcp/dhcp-protocol.pac | 34 +-- src/analyzer/protocol/dhcp/dhcp.pac | 1 + src/analyzer/protocol/dhcp/events.bif | 195 ++++--------- src/util.cc | 20 ++ src/util.h | 1 + 14 files changed, 623 insertions(+), 275 deletions(-) create mode 100644 scripts/base/protocols/dhcp/__load__.bro create mode 100644 scripts/base/protocols/dhcp/consts.bro create mode 100644 scripts/base/protocols/dhcp/main.bro create mode 100644 scripts/base/protocols/dhcp/utils.bro create mode 100644 scripts/policy/protocols/dhcp/handle_extra_msg_types.bro diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 72ba0bf115..6aaf7446b9 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -36,6 +36,7 @@ @load base/frameworks/tunnels @load base/protocols/conn +@load base/protocols/dhcp @load base/protocols/dns @load base/protocols/ftp @load base/protocols/http diff --git a/scripts/base/protocols/dhcp/__load__.bro b/scripts/base/protocols/dhcp/__load__.bro new file mode 100644 index 0000000000..0098b81a7a --- /dev/null +++ b/scripts/base/protocols/dhcp/__load__.bro @@ -0,0 +1,2 @@ +@load ./consts +@load ./main \ No newline at end of file diff --git a/scripts/base/protocols/dhcp/consts.bro b/scripts/base/protocols/dhcp/consts.bro new file mode 100644 index 0000000000..81914a98c3 --- /dev/null +++ b/scripts/base/protocols/dhcp/consts.bro @@ -0,0 +1,20 @@ +##! Types, errors, and fields for analyzing DHCP data. A helper file +##! for DHCP analysis scripts. + +module DHCP; + +export { + + ## Types of DHCP messages. See RFC 1533. + const message_types = { + [1] = "DHCP_DISCOVER", + [2] = "DHCP_OFFER", + [3] = "DHCP_REQUEST", + [4] = "DHCP_DECLINE", + [5] = "DHCP_ACK", + [6] = "DHCP_NAK", + [7] = "DHCP_RELEASE", + [8] = "DHCP_INFORM", + } &default = function(n: count): string { return fmt("unknown-message-type-%d", n); }; + +} \ No newline at end of file diff --git a/scripts/base/protocols/dhcp/main.bro b/scripts/base/protocols/dhcp/main.bro new file mode 100644 index 0000000000..9fc63df152 --- /dev/null +++ b/scripts/base/protocols/dhcp/main.bro @@ -0,0 +1,74 @@ +##! Analyzes DHCP traffic in order to log DHCP leases given to clients. +##! This script ignores large swaths of the protocol, since it is rather +##! noisy on most networks, and focuses on the end-result: assigned leases. +##! +##! To enable further analysis and log output for DHCP, see the optional +##! scripts in the policy/protocols/dhcp directory. + +@load ./utils.bro + +module DHCP; + +export { + redef enum Log::ID += { LOG }; + + ## The record type which contains the column fields of the DHCP log. + type Info: record { + ## The earliest time at which a DHCP message over the + ## associated connection is observed. + ts: time &log; + ## A unique identifier of the connection over which DHCP is + ## occuring. + uid: string &log; + ## The connection's 4-tuple of endpoint addresses/ports. + id: conn_id &log; + ## Client's hardware address. + mac: string &log &optional; + ## Client's actual assigned IP address. + assigned_ip: addr &log &optional; + ## IP address lease interval. + lease_time: interval &log &optional; + ## A random number choosen by the client for this transaction. + trans_id: count &log; + }; + + ## Event that can be handled to access the DHCP + ## record as it is sent on to the logging framework. + global log_dhcp: event(rec: Info); +} + +# Add the dhcp info to the connection record +redef record connection += { + dhcp: Info &optional; +}; + +const ports = { 67/udp, 68/udp }; +redef likely_server_ports += { 67/udp }; + +event bro_init() &priority=5 + { + Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp]); + Analyzer::register_for_ports(Analyzer::ANALYZER_DHCP, ports); + } + +event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=5 + { + local info: Info; + info$ts = network_time(); + info$id = c$id; + info$uid = c$uid; + info$assigned_ip = reverse_ip(msg$yiaddr); + info$lease_time = lease; + info$trans_id = msg$xid; + + if ( msg$h_addr != "" ) + info$mac = msg$h_addr; + + c$dhcp = info; + } + +# We let policy scripts add stuff too, so we run this at a lower priority +event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=1 + { + Log::write(DHCP::LOG, c$dhcp); + } diff --git a/scripts/base/protocols/dhcp/utils.bro b/scripts/base/protocols/dhcp/utils.bro new file mode 100644 index 0000000000..cb06450088 --- /dev/null +++ b/scripts/base/protocols/dhcp/utils.bro @@ -0,0 +1,21 @@ +##! Utilities specific for DHCP processing. + +@load ./main + +module DHCP; + +export { + ## Reverse the octets of an IPv4 IP. + ## + ## ip: An :bro:type:`addr` IPv4 address. + ## + ## Returns: A reversed addr. + global reverse_ip: function(ip: addr): addr; +} + +function reverse_ip(ip: addr): addr + { + local octets = split(cat(ip), /\./); + return to_addr(cat(octets[4], ".", octets[3], ".", octets[2], ".", octets[1])); + } + diff --git a/scripts/policy/protocols/dhcp/handle_extra_msg_types.bro b/scripts/policy/protocols/dhcp/handle_extra_msg_types.bro new file mode 100644 index 0000000000..e5fa713da4 --- /dev/null +++ b/scripts/policy/protocols/dhcp/handle_extra_msg_types.bro @@ -0,0 +1,256 @@ +##! Handlers for DHCP message types other than DHCPACK, which is handled in base/protocols/dhcp. +##! For networks that wish to get more details from their DHCP logs, at the expense +##! of a significantly higher log rate. + +@load base/protocols/dhcp + +module DHCP; + +export { + redef record Info += { + ## The value of the host name option, if seen + host_name: string &log &optional; + ## The IP requested by the client, if any + requested_ip: addr &log &optional; + ## The type of the DHCP message (DHCPOFFER, DHCPRELEASE, etc.) + msg_type: string &log &optional; + }; + + #### Enabled by default + + ## A boolean value to determine if DHCPREQUEST messages are logged. + ## Often useful to see client activity, and because host_name is often available. + const log_dhcprequest = T &redef; + + ## A boolean value to determine if DHCPDECLINE messages are logged. + ## A client declines a lease if it detects that the IP is already in use (usually via ARP). + const log_dhcpdecline = T &redef; + + ## A boolean value to determine if DHCPNAK messages are logged. + ## A server issues a DHCPNAK if a client DHCPREQUEST is invalid. + const log_dhcpnak = T &redef; + + ## A boolean value to determine if DHCPRELEASE messages are logged. + ## A client issues a DHCPRELEASE when it no longer needs the lease (e.g. it's shutting down). + const log_dhcprelease = T &redef; + + #### Not enabled by default + + ## A boolean value to determine if DHCPOFFER messages are logged. + ## Used to profile server -> client communication. + const log_dhcpoffer = F &redef; + + ## A boolean value to determine if DHCPDISCOVER messages are logged. + ## Used to profile broadcast client discovery requests. + const log_dhcpdiscover = F &redef; + + ## A boolean value to determine if DHCPINFORM messages are logged. + ## Used to profile clients attempting to request/renew specific IPs. + const log_dhcpinform = F &redef; + +} + +event dhcp_offer(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=5 + { + if ( ! log_dhcpoffer ) + return; + + local info: Info; + info$ts = network_time(); + info$id = c$id; + info$uid = c$uid; + info$assigned_ip = reverse_ip(msg$yiaddr); + info$lease_time = lease; + info$trans_id = msg$xid; + info$msg_type = "DHCPOFFER"; + + if ( msg$h_addr != "" ) + info$mac = msg$h_addr; + + if ( host_name != "" ) + info$host_name = host_name; + + c$dhcp = info; + } + +event dhcp_discover(c: connection, msg: dhcp_msg, req_addr: addr, host_name: string) &priority=5 + { + if ( ! log_dhcpdiscover ) + return; + + local info: Info; + info$ts = network_time(); + info$id = c$id; + info$uid = c$uid; + info$requested_ip = req_addr; + info$trans_id = msg$xid; + info$msg_type = "DHCPDISCOVER"; + + if ( msg$h_addr != "" ) + info$mac = msg$h_addr; + + if ( host_name != "" ) + info$host_name = host_name; + + c$dhcp = info; + } + +event dhcp_request(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr, host_name: string) &priority=5 + { + if ( ! log_dhcprequest ) + return; + + local info: Info; + info$ts = network_time(); + info$id = c$id; + info$uid = c$uid; + info$requested_ip = req_addr; + info$trans_id = msg$xid; + info$msg_type = "DHCPREQUEST"; + + if ( msg$h_addr != "" ) + info$mac = msg$h_addr; + + if ( host_name != "" ) + info$host_name = host_name; + + c$dhcp = info; + } + +event dhcp_decline(c: connection, msg: dhcp_msg, host_name: string) &priority=5 + { + if ( ! log_dhcpdecline ) + return; + + local info: Info; + info$ts = network_time(); + info$id = c$id; + info$uid = c$uid; + info$trans_id = msg$xid; + info$msg_type = "DHCPDECLINE"; + + if ( msg$h_addr != "" ) + info$mac = msg$h_addr; + + if ( host_name != "" ) + info$host_name = host_name; + + c$dhcp = info; + } + +event dhcp_nak(c: connection, msg: dhcp_msg, host_name: string) &priority=5 + { + if ( ! log_dhcpnak ) + return; + + local info: Info; + info$ts = network_time(); + info$id = c$id; + info$uid = c$uid; + info$trans_id = msg$xid; + info$msg_type = "DHCPNAK"; + + if ( msg$h_addr != "" ) + info$mac = msg$h_addr; + + if ( host_name != "" ) + info$host_name = host_name; + + c$dhcp = info; + } + +event dhcp_release(c: connection, msg: dhcp_msg, host_name: string) &priority=5 + { + if ( ! log_dhcprelease ) + return; + + local info: Info; + info$ts = network_time(); + info$id = c$id; + info$uid = c$uid; + info$trans_id = msg$xid; + info$msg_type = "DHCPRELEASE"; + + if ( msg$h_addr != "" ) + info$mac = msg$h_addr; + + if ( host_name != "" ) + info$host_name = host_name; + + c$dhcp = info; + } + +event dhcp_inform(c: connection, msg: dhcp_msg, host_name: string) &priority=5 + { + if ( ! log_dhcpinform ) + return; + + local info: Info; + info$ts = network_time(); + info$id = c$id; + info$uid = c$uid; + info$trans_id = msg$xid; + info$msg_type = "DHCPINFORM"; + + if ( msg$h_addr != "" ) + info$mac = msg$h_addr; + + if ( host_name != "" ) + info$host_name = host_name; + + c$dhcp = info; + } + +event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=4 + { + ## For the sake of consistency, let's add msg_type to DHCPACK as well. + c$dhcp$msg_type = "DHCPACK"; + ## host_name is generally not in ACKs, but let's check anyway. + if ( host_name != "" ) + c$dhcp$host_name = host_name; + } + +#### We log stuff at a lower priority, in case any other scripts would like to extend the Info record first. + +event dhcp_offer(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=1 + { + if ( log_dhcpoffer ) + Log::write(DHCP::LOG, c$dhcp); + } + +event dhcp_discover(c: connection, msg: dhcp_msg, req_addr: addr, host_name: string) &priority=1 + { + if ( log_dhcpdiscover ) + Log::write(DHCP::LOG, c$dhcp); + } + +event dhcp_request(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr, host_name: string) &priority=1 + { + if ( log_dhcprequest ) + Log::write(DHCP::LOG, c$dhcp); + } + +event dhcp_decline(c: connection, msg: dhcp_msg, host_name: string) &priority=1 + { + if ( log_dhcpdecline ) + Log::write(DHCP::LOG, c$dhcp); + } + +event dhcp_nak(c: connection, msg: dhcp_msg, host_name: string) &priority=1 + { + if ( log_dhcpnak ) + Log::write(DHCP::LOG, c$dhcp); + } + +event dhcp_release(c: connection, msg: dhcp_msg, host_name: string) &priority=1 + { + if ( log_dhcprelease ) + Log::write(DHCP::LOG, c$dhcp); + } + +event dhcp_inform(c: connection, msg: dhcp_msg, host_name: string) &priority=1 + { + if ( log_dhcpinform ) + Log::write(DHCP::LOG, c$dhcp); + } + diff --git a/src/analyzer/protocol/dhcp/DHCP.cc b/src/analyzer/protocol/dhcp/DHCP.cc index 8d05aef37d..1fa8759fbf 100644 --- a/src/analyzer/protocol/dhcp/DHCP.cc +++ b/src/analyzer/protocol/dhcp/DHCP.cc @@ -1,4 +1,3 @@ - #include "DHCP.h" #include "events.bif.h" diff --git a/src/analyzer/protocol/dhcp/DHCP.h b/src/analyzer/protocol/dhcp/DHCP.h index a1c06e8b85..b9784d34f1 100644 --- a/src/analyzer/protocol/dhcp/DHCP.h +++ b/src/analyzer/protocol/dhcp/DHCP.h @@ -19,6 +19,9 @@ public: static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new DHCP_Analyzer(conn); } + static bool Available() + { return dhcp_discover || dhcp_offer || dhcp_request || dhcp_decline || dhcp_ack || dhcp_nak || dhcp_release || dhcp_inform; } + protected: binpac::DHCP::DHCP_Conn* interp; }; diff --git a/src/analyzer/protocol/dhcp/dhcp-analyzer.pac b/src/analyzer/protocol/dhcp/dhcp-analyzer.pac index 5267075445..df928b4be4 100644 --- a/src/analyzer/protocol/dhcp/dhcp-analyzer.pac +++ b/src/analyzer/protocol/dhcp/dhcp-analyzer.pac @@ -8,12 +8,10 @@ flow DHCP_Flow(is_orig: bool) { %member{ BroVal dhcp_msg_val_; - BroAnalyzer interp; %} %init{ dhcp_msg_val_ = 0; - interp = connection->bro_analyzer(); %} %cleanup{ @@ -45,7 +43,7 @@ flow DHCP_Flow(is_orig: bool) { } if ( type == 0 ) - interp->Weird("DHCP_no_type_option"); + connection()->bro_analyzer()->ProtocolViolation("no DHCP message type option"); return type; %} @@ -56,54 +54,63 @@ flow DHCP_Flow(is_orig: bool) { // Requested IP address to the server. ::uint32 req_addr = 0, serv_addr = 0; + StringVal* host_name = 0; - for ( ptr = options->begin(); - ptr != options->end() && ! (*ptr)->last(); ++ptr ) + for ( ptr = options->begin(); ptr != options->end() && ! (*ptr)->last(); ++ptr ) { - switch ( (*ptr)->code() ) { - case REQ_IP_OPTION: - req_addr = htonl((*ptr)->info()->req_addr()); - break; + switch ( (*ptr)->code() ) + { + case REQ_IP_OPTION: + req_addr = htonl((*ptr)->info()->req_addr()); + break; - case SERV_ID_OPTION: - serv_addr = htonl((*ptr)->info()->serv_addr()); - break; - } + case SERV_ID_OPTION: + serv_addr = htonl((*ptr)->info()->serv_addr()); + break; + + case HOST_NAME_OPTION: + host_name = new StringVal((*ptr)->info()->host_name().length(), + (const char*) (*ptr)->info()->host_name().begin()); + break; + } } + if ( host_name == 0 ) + host_name = new StringVal(""); + switch ( type ) - { - case DHCPDISCOVER: - BifEvent::generate_dhcp_discover(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref(), new AddrVal(req_addr)); - break; + { + case DHCPDISCOVER: + BifEvent::generate_dhcp_discover(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dhcp_msg_val_->Ref(), new AddrVal(req_addr), host_name); + break; - case DHCPREQUEST: - BifEvent::generate_dhcp_request(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref(), new AddrVal(req_addr), - new AddrVal(serv_addr)); - break; + case DHCPREQUEST: + BifEvent::generate_dhcp_request(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dhcp_msg_val_->Ref(), new AddrVal(req_addr), + new AddrVal(serv_addr), host_name); + break; - case DHCPDECLINE: - BifEvent::generate_dhcp_decline(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref()); - break; + case DHCPDECLINE: + BifEvent::generate_dhcp_decline(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dhcp_msg_val_->Ref(), host_name); + break; - case DHCPRELEASE: - BifEvent::generate_dhcp_release(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref()); - break; + case DHCPRELEASE: + BifEvent::generate_dhcp_release(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dhcp_msg_val_->Ref(), host_name); + break; - case DHCPINFORM: - BifEvent::generate_dhcp_inform(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref()); - break; - } + case DHCPINFORM: + BifEvent::generate_dhcp_inform(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dhcp_msg_val_->Ref(), host_name); + break; + } return true; %} @@ -118,72 +125,83 @@ flow DHCP_Flow(is_orig: bool) { ::uint32 subnet_mask = 0, serv_addr = 0; uint32 lease = 0; + StringVal* host_name = 0; for ( ptr = options->begin(); ptr != options->end() && ! (*ptr)->last(); ++ptr ) { - switch ( (*ptr)->code() ) { - case SUBNET_OPTION: - subnet_mask = htonl((*ptr)->info()->mask()); - break; - - case ROUTER_OPTION: - // Let's hope there aren't multiple - // such options. - Unref(router_list); - router_list = new TableVal(dhcp_router_list); - + switch ( (*ptr)->code() ) { - int num_routers = - (*ptr)->info()->router_list()->size(); + case SUBNET_OPTION: + subnet_mask = htonl((*ptr)->info()->mask()); + break; - for ( int i = 0; i < num_routers; ++i ) - { - vector* rlist = - (*ptr)->info()->router_list(); - uint32 raddr = (*rlist)[i]; - ::uint32 tmp_addr; - tmp_addr = htonl(raddr); - // index starting from 1 - Val* index = new Val(i + 1, TYPE_COUNT); - router_list->Assign(index, new AddrVal(tmp_addr)); - Unref(index); - } + case ROUTER_OPTION: + // Let's hope there aren't multiple + // such options. + Unref(router_list); + router_list = new TableVal(dhcp_router_list); + + { + int num_routers = (*ptr)->info()->router_list()->size(); + + for ( int i = 0; i < num_routers; ++i ) + { + vector* rlist = (*ptr)->info()->router_list(); + + uint32 raddr = (*rlist)[i]; + ::uint32 tmp_addr; + tmp_addr = htonl(raddr); + + // index starting from 1 + Val* index = new Val(i + 1, TYPE_COUNT); + router_list->Assign(index, new AddrVal(tmp_addr)); + Unref(index); + } + } + break; + + case LEASE_OPTION: + lease = (*ptr)->info()->lease(); + break; + + case SERV_ID_OPTION: + serv_addr = htonl((*ptr)->info()->serv_addr()); + break; + + case HOST_NAME_OPTION: + host_name = new StringVal((*ptr)->info()->host_name().length(), + (const char*) (*ptr)->info()->host_name().begin()); + break; } - break; - - case LEASE_OPTION: - lease = (*ptr)->info()->lease(); - break; - - case SERV_ID_OPTION: - serv_addr = htonl((*ptr)->info()->serv_addr()); - break; - } } - switch ( type ) { - case DHCPOFFER: - BifEvent::generate_dhcp_offer(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref(), new AddrVal(subnet_mask), - router_list, lease, new AddrVal(serv_addr)); - break; + if ( host_name == 0 ) + host_name = new StringVal(""); - case DHCPACK: - BifEvent::generate_dhcp_ack(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref(), new AddrVal(subnet_mask), - router_list, lease, new AddrVal(serv_addr)); - break; + switch ( type ) + { + case DHCPOFFER: + BifEvent::generate_dhcp_offer(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dhcp_msg_val_->Ref(), new AddrVal(subnet_mask), + router_list, lease, new AddrVal(serv_addr), host_name); + break; - case DHCPNAK: - BifEvent::generate_dhcp_nak(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref()); - break; + case DHCPACK: + BifEvent::generate_dhcp_ack(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dhcp_msg_val_->Ref(), new AddrVal(subnet_mask), + router_list, lease, new AddrVal(serv_addr), host_name); + break; - } + case DHCPNAK: + BifEvent::generate_dhcp_nak(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dhcp_msg_val_->Ref(), host_name); + break; + + } return true; @@ -195,7 +213,10 @@ flow DHCP_Flow(is_orig: bool) { // DHCP or BOOTP. If not, we are unable to interpret // the message options. if ( ${msg.cookie} != 0x63825363 ) + { + connection()->bro_analyzer()->ProtocolViolation(fmt("bad cookie (%d)", ${msg.cookie})); return false; + } Unref(dhcp_msg_val_); RecordVal* r = new RecordVal(dhcp_msg); @@ -203,40 +224,44 @@ flow DHCP_Flow(is_orig: bool) { r->Assign(0, new Val(${msg.op}, TYPE_COUNT)); r->Assign(1, new Val(${msg.type}, TYPE_COUNT)); r->Assign(2, new Val(${msg.xid}, TYPE_COUNT)); - - // We want only 6 bytes for Ethernet address. - r->Assign(3, new StringVal(6, (const char*) ${msg.chaddr}.begin())); - + r->Assign(3, new StringVal(format_mac(${msg.chaddr}.data()))); r->Assign(4, new AddrVal(${msg.ciaddr})); r->Assign(5, new AddrVal(${msg.yiaddr})); dhcp_msg_val_ = r; - switch ( ${msg.op} ) { - case BOOTREQUEST: // presumablye from client to server - if ( ${msg.type} == DHCPDISCOVER || - ${msg.type} == DHCPREQUEST || - ${msg.type} == DHCPDECLINE || - ${msg.type} == DHCPRELEASE || - ${msg.type} == DHCPINFORM ) - parse_request(${msg.options}, ${msg.type}); - else - interp->Weird("DHCP_wrong_msg_type"); - break; + switch ( ${msg.op} ) + { + case BOOTREQUEST: // presumably from client to server + if ( ${msg.type} == DHCPDISCOVER || + ${msg.type} == DHCPREQUEST || + ${msg.type} == DHCPDECLINE || + ${msg.type} == DHCPRELEASE || + ${msg.type} == DHCPINFORM ) + parse_request(${msg.options}, ${msg.type}); + else + connection()->bro_analyzer()->ProtocolViolation(fmt("unknown DHCP message type option for BOOTREQUEST (%d)", + ${msg.type})); + break; - case BOOTREPLY: // presumably from server to client - if ( ${msg.type} == DHCPOFFER || - ${msg.type} == DHCPACK || ${msg.type} == DHCPNAK ) - parse_reply(${msg.options}, ${msg.type}); - else - interp->Weird("DHCP_wrong_msg_type"); - break; - - default: - interp->Weird("DHCP_wrong_op_type"); - break; - } + case BOOTREPLY: // presumably from server to client + if ( ${msg.type} == DHCPOFFER || + ${msg.type} == DHCPACK || + ${msg.type} == DHCPNAK ) + parse_reply(${msg.options}, ${msg.type}); + else + connection()->bro_analyzer()->ProtocolViolation(fmt("unknown DHCP message type option for BOOTREPLY (%d)", + ${msg.type})); + + break; + default: + connection()->bro_analyzer()->ProtocolViolation(fmt("unknown DHCP message op code (%d). Known codes: 1=BOOTREQUEST, 2=BOOTREPLY", + ${msg.op})); + break; + } + + connection()->bro_analyzer()->ProtocolConfirmation(); return true; %} }; diff --git a/src/analyzer/protocol/dhcp/dhcp-protocol.pac b/src/analyzer/protocol/dhcp/dhcp-protocol.pac index d77780b1b3..1eb5b399e5 100644 --- a/src/analyzer/protocol/dhcp/dhcp-protocol.pac +++ b/src/analyzer/protocol/dhcp/dhcp-protocol.pac @@ -10,13 +10,14 @@ enum OP_type { # The option types are by no means complete. # Anyone can add a new option type in RFC 1533 to be parsed here. enum OPTION_type { - SUBNET_OPTION = 1, - ROUTER_OPTION = 3, - REQ_IP_OPTION = 50, - LEASE_OPTION = 51, - MSG_TYPE_OPTION = 53, - SERV_ID_OPTION = 54, # Server address, actually :) - END_OPTION = 255, + SUBNET_OPTION = 1, + ROUTER_OPTION = 3, + HOST_NAME_OPTION = 12, + REQ_IP_OPTION = 50, + LEASE_OPTION = 51, + MSG_TYPE_OPTION = 53, + SERV_ID_OPTION = 54, # Server address, actually :) + END_OPTION = 255, }; # Refer to RFC 1533 for message types (with option = 53). @@ -34,21 +35,22 @@ enum DHCP_message_type { type Option_Info(code: uint8) = record { length : uint8; value : case code of { - SUBNET_OPTION -> mask : uint32; - ROUTER_OPTION -> router_list: uint32[length/4]; - REQ_IP_OPTION -> req_addr : uint32; - LEASE_OPTION -> lease : uint32; - MSG_TYPE_OPTION -> msg_type : uint8; - SERV_ID_OPTION -> serv_addr: uint32; - default -> other: bytestring &length = length; + SUBNET_OPTION -> mask : uint32; + ROUTER_OPTION -> router_list : uint32[length/4]; + REQ_IP_OPTION -> req_addr : uint32; + LEASE_OPTION -> lease : uint32; + MSG_TYPE_OPTION -> msg_type : uint8; + SERV_ID_OPTION -> serv_addr : uint32; + HOST_NAME_OPTION -> host_name : bytestring &length = length; + default -> other : bytestring &length = length; }; }; type DHCP_Option = record { code : uint8; data : case code of { - 0, 255 -> none : empty; - default -> info : Option_Info(code); + 0, 255 -> none : empty; + default -> info : Option_Info(code); }; } &let { last: bool = (code == 255); # Mark the end of a list of options diff --git a/src/analyzer/protocol/dhcp/dhcp.pac b/src/analyzer/protocol/dhcp/dhcp.pac index c4a684badc..706be31e10 100644 --- a/src/analyzer/protocol/dhcp/dhcp.pac +++ b/src/analyzer/protocol/dhcp/dhcp.pac @@ -1,3 +1,4 @@ +%include binpac.pac %include bro.pac %extern{ diff --git a/src/analyzer/protocol/dhcp/events.bif b/src/analyzer/protocol/dhcp/events.bif index 741504185e..987213dad3 100644 --- a/src/analyzer/protocol/dhcp/events.bif +++ b/src/analyzer/protocol/dhcp/events.bif @@ -1,8 +1,5 @@ -## Generated for DHCP messages of type *discover*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. +## Generated for DHCP messages of type *DHCPDISCOVER* (client broadcast to locate +## available servers). ## ## c: The connection record describing the underlying UDP flow. ## @@ -10,33 +7,23 @@ ## ## req_addr: The specific address requested by the client. ## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +## host_name: The value of the host name option, if specified by the client. +## +## .. bro:see:: dhcp_discover dhcp_offer dhcp_request dhcp_decline dhcp_ack dhcp_nak +## dhcp_release dhcp_inform ## ## .. note:: Bro does not support broadcast packets (as used by the DHCP ## protocol). It treats broadcast addresses just like any other and ## associates packets into transport-level flows in the same way as usual. ## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to -## register a port for it or add a DPD payload signature. -event dhcp_discover%(c: connection, msg: dhcp_msg, req_addr: addr%); +event dhcp_discover%(c: connection, msg: dhcp_msg, req_addr: addr, host_name: string%); -## Generated for DHCP messages of type *offer*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. +## Generated for DHCP messages of type *DHCPOFFER* (server to client in response to +## DHCPDISCOVER with offer of configuration parameters). ## ## c: The connection record describing the underlying UDP flow. ## -## msg: TODO. +## msg: The parsed type-independent part of the DHCP message. ## ## mask: The subnet mask specified by the message. ## @@ -46,28 +33,21 @@ event dhcp_discover%(c: connection, msg: dhcp_msg, req_addr: addr%); ## ## serv_addr: The server address specified by the message. ## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request +## host_name: The value of the host name option, if specified by the client. +## +## .. bro:see:: dhcp_discover dhcp_request dhcp_decline dhcp_ack dhcp_nak +## dhcp_release dhcp_inform ## ## .. note:: Bro does not support broadcast packets (as used by the DHCP ## protocol). It treats broadcast addresses just like any other and ## associates packets into transport-level flows in the same way as usual. ## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to -## register a port for it or add a DPD payload signature. -event dhcp_offer%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%); +event dhcp_offer%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string%); -## Generated for DHCP messages of type *request*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. +## Generated for DHCP messages of type *DHCPREQUEST* (Client message to servers either +## (a) requesting offered parameters from one server and implicitly declining offers +## from all others, (b) confirming correctness of previously allocated address after, +## e.g., system reboot, or (c) extending the lease on a particular network address.) ## ## c: The connection record describing the underlying UDP flow. ## @@ -77,55 +57,37 @@ event dhcp_offer%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_ ## ## serv_addr: The server address specified by the message. ## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request +## host_name: The value of the host name option, if specified by the client. +## +## .. bro:see:: dhcp_discover dhcp_offer dhcp_decline dhcp_ack dhcp_nak +## dhcp_release dhcp_inform ## ## .. note:: Bro does not support broadcast packets (as used by the DHCP ## protocol). It treats broadcast addresses just like any other and ## associates packets into transport-level flows in the same way as usual. ## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to -## register a port for it or add a DPD payload signature. -event dhcp_request%(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr%); +event dhcp_request%(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr, host_name: string%); -## Generated for DHCP messages of type *decline*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. +## Generated for DHCP messages of type *DHCPDECLINE* (Client to server indicating +## network address is already in use). ## ## c: The connection record describing the underlying UDP flow. ## ## msg: The parsed type-independent part of the DHCP message. ## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request +## host_name: The value of the host name option, if specified by the client. +## +## .. bro:see:: dhcp_discover dhcp_offer dhcp_request dhcp_ack dhcp_nak +## dhcp_release dhcp_inform ## ## .. note:: Bro does not support broadcast packets (as used by the DHCP ## protocol). It treats broadcast addresses just like any other and ## associates packets into transport-level flows in the same way as usual. ## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to -## register a port for it or add a DPD payload signature. -event dhcp_decline%(c: connection, msg: dhcp_msg%); +event dhcp_decline%(c: connection, msg: dhcp_msg, host_name: string%); -## Generated for DHCP messages of type *acknowledgment*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. +## Generated for DHCP messages of type *DHCPACK* (Server to client with configuration +## parameters, including committed network address). ## ## c: The connection record describing the underlying UDP flow. ## @@ -139,101 +101,62 @@ event dhcp_decline%(c: connection, msg: dhcp_msg%); ## ## serv_addr: The server address specified by the message. ## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request +## host_name: The value of the host name option, if specified by the client. ## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. +## .. bro:see:: dhcp_discover dhcp_offer dhcp_request dhcp_decline dhcp_nak +## dhcp_release dhcp_inform ## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to -## register a port for it or add a DPD payload signature. -event dhcp_ack%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%); +event dhcp_ack%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string%); -## Generated for DHCP messages of type *negative acknowledgment*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. +## Generated for DHCP messages of type *DHCPNAK* (Server to client indicating client's +## notion of network address is incorrect (e.g., client has moved to new subnet) or +## client's lease has expired). ## ## c: The connection record describing the underlying UDP flow. ## ## msg: The parsed type-independent part of the DHCP message. ## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request +## host_name: The value of the host name option, if specified by the client. +## +## .. bro:see:: dhcp_discover dhcp_offer dhcp_request dhcp_decline dhcp_ack dhcp_release +## dhcp_inform ## ## .. note:: Bro does not support broadcast packets (as used by the DHCP ## protocol). It treats broadcast addresses just like any other and ## associates packets into transport-level flows in the same way as usual. ## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to -## register a port for it or add a DPD payload signature. -event dhcp_nak%(c: connection, msg: dhcp_msg%); +event dhcp_nak%(c: connection, msg: dhcp_msg, host_name: string%); -## Generated for DHCP messages of type *release*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. +## Generated for DHCP messages of type *DHCPRELEASE* (Client to server relinquishing +## network address and cancelling remaining lease). ## ## c: The connection record describing the underlying UDP flow. ## ## msg: The parsed type-independent part of the DHCP message. ## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request +## host_name: The value of the host name option, if specified by the client. ## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. +## .. bro:see:: dhcp_discover dhcp_offer dhcp_request dhcp_decline dhcp_ack dhcp_nak +## dhcp_inform ## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to -## register a port for it or add a DPD payload signature. -event dhcp_release%(c: connection, msg: dhcp_msg%); +event dhcp_release%(c: connection, msg: dhcp_msg, host_name: string%); -## Generated for DHCP messages of type *inform*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. +## Generated for DHCP messages of type *DHCPINFORM* (Client to server, asking only for +## local configuration parameters; client already has externally configured network +## address). ## ## c: The connection record describing the underlying UDP flow. ## ## msg: The parsed type-independent part of the DHCP message. ## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request +## host_name: The value of the host name option, if specified by the client. +## +## .. bro:see:: dhcp_discover dhcp_offer dhcp_request dhcp_decline dhcp_ack dhcp_nak +## dhcp_release ## ## .. note:: Bro does not support broadcast packets (as used by the DHCP ## protocol). It treats broadcast addresses just like any other and ## associates packets into transport-level flows in the same way as usual. ## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to -## register a port for it or add a DPD payload signature. -event dhcp_inform%(c: connection, msg: dhcp_msg%); +event dhcp_inform%(c: connection, msg: dhcp_msg, host_name: string%); diff --git a/src/util.cc b/src/util.cc index 5a63be22cb..0a349ccce2 100644 --- a/src/util.cc +++ b/src/util.cc @@ -78,6 +78,26 @@ std::string extract_ip_and_len(const std::string& i, int* len) return extract_ip(i.substr(0, pos)); } +/** +* Given a MAC address, formats it as 00:de:ad:be:ef +* Supports both EUI-48 and EUI-64. If it's neither, returns +* an empty string. +* +* @param m EUI-48 or EUI-64 MAC address to format, as a char array +* @return A string of the formatted MAC +*/ +char* format_mac(const unsigned char* m) +{ + char* buf = new char[24]; + if (m[6] == 0 && m[7] == 0) // EUI-48 + snprintf(buf, 18, "%02x:%02x:%02x:%02x:%02x:%02x", + m[0], m[1], m[2], m[3], m[4], m[5]); + else + snprintf(buf, 24, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7]); + return buf; +} + /** * Takes a string, unescapes all characters that are escaped as hex codes * (\x##) and turns them into the equivalent ascii-codes. Returns a string diff --git a/src/util.h b/src/util.h index 91ed8f2888..8201456b45 100644 --- a/src/util.h +++ b/src/util.h @@ -106,6 +106,7 @@ std::string get_escaped_string(const std::string& str, bool escape_all); extern char* copy_string(const char* s); extern int streq(const char* s1, const char* s2); +extern char* format_mac(const unsigned char* m); // Returns the character corresponding to the given escape sequence (s points // just past the '\'), and updates s to point just beyond the last character From 325f0c2a3f087508dc0817739b9c312bcc5873d5 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 22 Jul 2013 14:15:35 -0500 Subject: [PATCH 133/881] Coverage test fixes and whitespace/doc tweaks. --- doc/scripts/DocSourcesList.cmake | 3 ++ scripts/base/utils/active-http.bro | 26 ++++++------ scripts/base/utils/exec.bro | 40 +++++++++---------- .../canonified_loaded_scripts.log | 13 +++--- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index 529b03ca83..bd264bfcb4 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -164,9 +164,12 @@ rest_target(${psd} base/protocols/ssl/main.bro) rest_target(${psd} base/protocols/ssl/mozilla-ca-list.bro) rest_target(${psd} base/protocols/syslog/consts.bro) rest_target(${psd} base/protocols/syslog/main.bro) +rest_target(${psd} base/utils/active-http.bro) rest_target(${psd} base/utils/addrs.bro) rest_target(${psd} base/utils/conn-ids.bro) +rest_target(${psd} base/utils/dir.bro) rest_target(${psd} base/utils/directions-and-hosts.bro) +rest_target(${psd} base/utils/exec.bro) rest_target(${psd} base/utils/files.bro) rest_target(${psd} base/utils/numbers.bro) rest_target(${psd} base/utils/paths.bro) diff --git a/scripts/base/utils/active-http.bro b/scripts/base/utils/active-http.bro index 5522cc108a..3f475a378b 100644 --- a/scripts/base/utils/active-http.bro +++ b/scripts/base/utils/active-http.bro @@ -1,21 +1,21 @@ -##! A module for performing active HTTP requests and +##! A module for performing active HTTP requests and ##! getting the reply at runtime. @load ./exec module ActiveHTTP; - + export { ## The default timeout for HTTP requests. const default_max_time = 1min &redef; - + ## The default HTTP method/verb to use for requests. const default_method = "GET" &redef; - - type Response: record { + + type Response: record { ## Numeric response code from the server. code: count; - ## String response messgae from the server. + ## String response message from the server. msg: string; ## Full body of the response. body: string &optional; @@ -29,24 +29,24 @@ export { ## The HTTP method/verb to use for the request. method: string &default=default_method; ## Data to send to the server in the client body. Keep in - ## mind that you will probably need to set the $method field + ## mind that you will probably need to set the *method* field ## to "POST" or "PUT". client_data: string &optional; - ## Arbitrary headers to pass to the server. Some headers + ## Arbitrary headers to pass to the server. Some headers ## will be included by libCurl. #custom_headers: table[string] of string &optional; ## Timeout for the request. max_time: interval &default=default_max_time; - ## Additional curl command line arguments. Be very careful + ## Additional curl command line arguments. Be very careful ## with this option since shell injection could take place ## if careful handling of untrusted data is not applied. addl_curl_args: string &optional; }; ## Perform an HTTP request according to the :bro:type:`Request` record. - ## This is an asynchronous function and must be called within a "when" + ## This is an asynchronous function and must be called within a "when" ## statement. - ## + ## ## req: A record instance representing all options for an HTTP request. ## ## Returns: A record with the full response message. @@ -55,7 +55,7 @@ export { function request2curl(r: Request, bodyfile: string, headersfile: string): string { - local cmd = fmt("curl -s -g -o \"%s\" -D \"%s\" -X \"%s\"", + local cmd = fmt("curl -s -g -o \"%s\" -D \"%s\" -X \"%s\"", str_shell_escape(bodyfile), str_shell_escape(headersfile), str_shell_escape(r$method)); @@ -91,7 +91,7 @@ function request(req: Request): ActiveHTTP::Response # If there is no response line then nothing else will work either. if ( ! (result?$files && headersfile in result$files) ) Reporter::error(fmt("There was a failure when requesting \"%s\" with ActiveHTTP.", req$url)); - + local headers = result$files[headersfile]; for ( i in headers ) { diff --git a/scripts/base/utils/exec.bro b/scripts/base/utils/exec.bro index 45cd8cb287..f896a68064 100644 --- a/scripts/base/utils/exec.bro +++ b/scripts/base/utils/exec.bro @@ -1,6 +1,4 @@ ##! A module for executing external command line programs. -##! This requires code that is still in topic branches and -##! definitely won't currently work on any released version of Bro. @load base/frameworks/input @@ -8,15 +6,13 @@ module Exec; export { type Command: record { - ## The command line to execute. - ## Use care to avoid injection attacks! + ## The command line to execute. Use care to avoid injection attacks. + ## I.e. if the command uses untrusted/variable data, sanitize it. cmd: string; - ## Provide standard in to the program as a - ## string. + ## Provide standard in to the program as a string. stdin: string &default=""; - ## If additional files are required to be read - ## in as part of the output of the command they - ## can be defined here. + ## If additional files are required to be read in as part of the output + ## of the command they can be defined here. read_files: set[string] &optional; }; @@ -27,7 +23,7 @@ export { signal_exit: bool &default=F; ## Each line of standard out. stdout: vector of string &optional; - ## Each line of standard error. + ## Each line of standard error. stderr: vector of string &optional; ## If additional files were requested to be read in ## the content of the files will be available here. @@ -35,7 +31,7 @@ export { }; ## Function for running command line programs and getting - ## output. This is an asynchronous function which is meant + ## output. This is an asynchronous function which is meant ## to be run with the `when` statement. ## ## cmd: The command to run. Use care to avoid injection attacks! @@ -56,12 +52,12 @@ redef record Command += { global results: table[string] of Result = table(); global finished_commands: set[string]; global currently_tracked_files: set[string] = set(); -type OneLine: record { +type OneLine: record { s: string; is_stderr: bool; }; -type FileLine: record { +type FileLine: record { s: string; }; @@ -93,7 +89,7 @@ event Exec::file_line(description: Input::EventDescription, tpe: Input::Event, s local result = results[name]; if ( ! result?$files ) result$files = table(); - + if ( track_file !in result$files ) result$files[track_file] = vector(s); else @@ -136,16 +132,16 @@ function run(cmd: Command): Result } } - local config_strings: table[string] of string = { + local config_strings: table[string] of string = { ["stdin"] = cmd$stdin, ["read_stderr"] = "1", }; - Input::add_event([$name=cmd$uid, - $source=fmt("%s |", cmd$cmd), - $reader=Input::READER_RAW, - $fields=Exec::OneLine, - $ev=Exec::line, - $want_record=F, + Input::add_event([$name=cmd$uid, + $source=fmt("%s |", cmd$cmd), + $reader=Input::READER_RAW, + $fields=Exec::OneLine, + $ev=Exec::line, + $want_record=F, $config=config_strings]); return when ( cmd$uid in finished_commands ) @@ -164,4 +160,4 @@ event bro_done() { system(fmt("rm \"%s\"", str_shell_escape(fname))); } - } \ No newline at end of file + } diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index 999fd7c841..37f1c739f8 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-07-10-21-18-31 +#open 2013-07-22-16-01-22 #fields name #types string scripts/base/init-bare.bro @@ -90,12 +90,17 @@ scripts/base/init-bare.bro scripts/base/init-default.bro scripts/base/utils/site.bro scripts/base/utils/patterns.bro + scripts/base/utils/active-http.bro + scripts/base/utils/exec.bro scripts/base/utils/addrs.bro scripts/base/utils/conn-ids.bro + scripts/base/utils/dir.bro + scripts/base/frameworks/reporter/__load__.bro + scripts/base/frameworks/reporter/main.bro + scripts/base/utils/paths.bro scripts/base/utils/directions-and-hosts.bro scripts/base/utils/files.bro scripts/base/utils/numbers.bro - scripts/base/utils/paths.bro scripts/base/utils/queue.bro scripts/base/utils/strings.bro scripts/base/utils/thresholds.bro @@ -129,8 +134,6 @@ scripts/base/init-default.bro scripts/base/frameworks/intel/__load__.bro scripts/base/frameworks/intel/main.bro scripts/base/frameworks/intel/input.bro - scripts/base/frameworks/reporter/__load__.bro - scripts/base/frameworks/reporter/main.bro scripts/base/frameworks/sumstats/__load__.bro scripts/base/frameworks/sumstats/main.bro scripts/base/frameworks/sumstats/plugins/__load__.bro @@ -195,4 +198,4 @@ scripts/base/init-default.bro scripts/base/protocols/tunnels/__load__.bro scripts/base/misc/find-checksum-offloading.bro scripts/policy/misc/loaded-scripts.bro -#close 2013-07-10-21-18-31 +#close 2013-07-22-16-01-22 From 4b9d8b2c733abc336d7a565c98909f4e8dd6449e Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 22 Jul 2013 15:38:04 -0400 Subject: [PATCH 134/881] Tiny fix to account for missing str field (not sure how this happens yet) --- scripts/policy/protocols/ssh/detect-bruteforcing.bro | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro index f8d41db2b8..7e8ec2d911 100644 --- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -55,9 +55,11 @@ event bro_init() { local r = result["ssh.login.failure"]; local sub_msg = fmt("Sampled servers: "); - for ( i in r$samples ) + local samples = r$samples; + for ( i in samples ) { - sub_msg = fmt("%s%s %s", sub_msg, i==0 ? "":",", r$samples[i]$str); + if ( samples[i]?$str ) + sub_msg = fmt("%s%s %s", sub_msg, i==0 ? "":",", samples[i]$str); } # Generate the notice. NOTICE([$note=Password_Guessing, From 636914b8f12a27145ce2fcb2b4e1e4be8f6ad381 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 22 Jul 2013 17:01:31 -0400 Subject: [PATCH 135/881] Some tests work now (at least they all don't fail anymore!) --- testing/btest/btest.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/btest/btest.cfg b/testing/btest/btest.cfg index 4a13833094..7ccf99eea8 100644 --- a/testing/btest/btest.cfg +++ b/testing/btest/btest.cfg @@ -7,7 +7,7 @@ IgnoreFiles = *.tmp *.swp #* *.trace .DS_Store [environment] BROPATH=`bash -c %(testbase)s/../../build/bro-path-dev` -BROMAGIC=%(testbase)s/../../magic +BROMAGIC=%(testbase)s/../../magic/database BRO_SEED_FILE=%(testbase)s/random.seed TZ=UTC LC_ALL=C From f098b17429151d2169aff30ead87801146fb376f Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 23 Jul 2013 11:18:49 -0400 Subject: [PATCH 136/881] A few test updates. --- scripts/base/protocols/irc/files.bro | 3 -- .../policy/frameworks/files/detect-MHR.bro | 2 +- .../Baseline/core.tunnels.ayiya/http.log | 10 +++--- .../canonified_loaded_scripts.log | 31 ++++++++++--------- .../out | 3 +- .../out | 15 +++++++++ .../http.log | 8 ++--- .../notice.log | 10 +++--- .../smtp_entities.log | 12 ------- .../scripts/base/protocols/smtp/mime.test | 6 ---- testing/scripts/file-analysis-test.bro | 18 +++++------ 11 files changed, 57 insertions(+), 61 deletions(-) delete mode 100644 testing/btest/Baseline/scripts.base.protocols.smtp.mime/smtp_entities.log delete mode 100644 testing/btest/scripts/base/protocols/smtp/mime.test diff --git a/scripts/base/protocols/irc/files.bro b/scripts/base/protocols/irc/files.bro index a6321d3f2f..7e077c8331 100644 --- a/scripts/base/protocols/irc/files.bro +++ b/scripts/base/protocols/irc/files.bro @@ -16,9 +16,6 @@ export { function get_file_handle(c: connection, is_orig: bool): string { - if ( [c$id$resp_h, c$id$resp_p] !in dcc_expected_transfers ) - return ""; - return cat(Analyzer::ANALYZER_IRC_DATA, c$start_time, c$id, is_orig); } diff --git a/scripts/policy/frameworks/files/detect-MHR.bro b/scripts/policy/frameworks/files/detect-MHR.bro index 71d73217e0..8a2e33b7f4 100644 --- a/scripts/policy/frameworks/files/detect-MHR.bro +++ b/scripts/policy/frameworks/files/detect-MHR.bro @@ -47,7 +47,7 @@ event file_hash(f: fa_file, kind: string, hash: string) local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected); if ( mhr_detect_rate >= notice_threshold ) { - local message = fmt("Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected); + local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected); local virustotal_url = fmt("https://www.virustotal.com/en/file/%s/analysis/", hash); NOTICE([$note=Match, $msg=message, $sub=virustotal_url, $f=f]); } diff --git a/testing/btest/Baseline/core.tunnels.ayiya/http.log b/testing/btest/Baseline/core.tunnels.ayiya/http.log index cd49c4cc89..04692a3547 100644 --- a/testing/btest/Baseline/core.tunnels.ayiya/http.log +++ b/testing/btest/Baseline/core.tunnels.ayiya/http.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-20 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1257655301.652206 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 10102 200 OK - - - (empty) - - - text/html - - - +#open 2013-07-23-05-12-58 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1257655301.652206 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 10102 200 OK - - - (empty) - - - - - meGKu6goEyd application/octet-stream 1257655302.514424 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 2 GET ipv6.google.com /csi?v=3&s=webhp&action=&tran=undefined&e=17259,19771,21517,21766,21887,22212&ei=BUz2Su7PMJTglQfz3NzCAw&rt=prt.77,xjs.565,ol.645 http://ipv6.google.com/ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 0 204 No Content - - - (empty) - - - - - - - 1257655303.603569 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 3 GET ipv6.google.com /gen_204?atyp=i&ct=fade&cad=1254&ei=BUz2Su7PMJTglQfz3NzCAw&zx=1257655303600 http://ipv6.google.com/ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 0 204 No Content - - - (empty) - - - - - - - -#close 2013-05-21-21-11-20 +#close 2013-07-23-05-12-58 diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index 999fd7c841..f67d4b6158 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-07-10-21-18-31 +#open 2013-07-23-05-48-10 #fields name #types string scripts/base/init-bare.bro @@ -84,12 +84,12 @@ scripts/base/init-bare.bro scripts/base/frameworks/analyzer/main.bro scripts/base/frameworks/packet-filter/utils.bro build/scripts/base/bif/analyzer.bif.bro - scripts/base/frameworks/file-analysis/__load__.bro - scripts/base/frameworks/file-analysis/main.bro + scripts/base/frameworks/files/__load__.bro + scripts/base/frameworks/files/main.bro build/scripts/base/bif/file_analysis.bif.bro + scripts/base/utils/site.bro + scripts/base/utils/patterns.bro scripts/base/init-default.bro - scripts/base/utils/site.bro - scripts/base/utils/patterns.bro scripts/base/utils/addrs.bro scripts/base/utils/conn-ids.bro scripts/base/utils/directions-and-hosts.bro @@ -157,8 +157,8 @@ scripts/base/init-default.bro scripts/base/protocols/ftp/__load__.bro scripts/base/protocols/ftp/utils-commands.bro scripts/base/protocols/ftp/main.bro - scripts/base/protocols/ftp/file-analysis.bro - scripts/base/protocols/ftp/file-extract.bro + scripts/base/protocols/ftp/utils.bro + scripts/base/protocols/ftp/files.bro scripts/base/protocols/ftp/gridftp.bro scripts/base/protocols/ssl/__load__.bro scripts/base/protocols/ssl/consts.bro @@ -166,15 +166,13 @@ scripts/base/init-default.bro scripts/base/protocols/ssl/mozilla-ca-list.bro scripts/base/protocols/http/__load__.bro scripts/base/protocols/http/main.bro + scripts/base/protocols/http/entities.bro scripts/base/protocols/http/utils.bro - scripts/base/protocols/http/file-analysis.bro - scripts/base/protocols/http/file-ident.bro - scripts/base/protocols/http/file-hash.bro - scripts/base/protocols/http/file-extract.bro + scripts/base/protocols/http/files.bro scripts/base/protocols/irc/__load__.bro scripts/base/protocols/irc/main.bro scripts/base/protocols/irc/dcc-send.bro - scripts/base/protocols/irc/file-analysis.bro + scripts/base/protocols/irc/files.bro scripts/base/protocols/modbus/__load__.bro scripts/base/protocols/modbus/consts.bro scripts/base/protocols/modbus/main.bro @@ -182,8 +180,7 @@ scripts/base/init-default.bro scripts/base/protocols/smtp/__load__.bro scripts/base/protocols/smtp/main.bro scripts/base/protocols/smtp/entities.bro - scripts/base/protocols/smtp/entities-excerpt.bro - scripts/base/protocols/smtp/file-analysis.bro + scripts/base/protocols/smtp/files.bro scripts/base/protocols/socks/__load__.bro scripts/base/protocols/socks/consts.bro scripts/base/protocols/socks/main.bro @@ -193,6 +190,10 @@ scripts/base/init-default.bro scripts/base/protocols/syslog/consts.bro scripts/base/protocols/syslog/main.bro scripts/base/protocols/tunnels/__load__.bro + scripts/base/files/hash/__load__.bro + scripts/base/files/hash/main.bro + scripts/base/files/extract/__load__.bro + scripts/base/files/extract/main.bro scripts/base/misc/find-checksum-offloading.bro scripts/policy/misc/loaded-scripts.bro -#close 2013-07-10-21-18-31 +#close 2013-07-23-05-48-10 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out index 4463db6958..c810ce15e5 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out @@ -3,7 +3,8 @@ file #0, 0, 0 FILE_BOF_BUFFER The Nationa MIME_TYPE -text/x-pascal +application/octet-stream +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 16557, 0 [orig_h=141.142.228.5, orig_p=50737/tcp, resp_h=141.142.192.162, resp_p=38141/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.irc/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.irc/out index 36da7bdeed..fcd30b2253 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.irc/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.irc/out @@ -4,6 +4,21 @@ FILE_BOF_BUFFER PK^C^D^T\0\0\0^H\0\xae MIME_TYPE application/zip +FILE_OVER_NEW_CONNECTION +FILE_NEW +file #1, 0, 0 +FILE_BOF_BUFFER +\0\0^Ex\0\0^J\xf0\0\0^P +MIME_TYPE +application/octet-stream +FILE_OVER_NEW_CONNECTION +FILE_STATE_REMOVE +file #1, 124, 0 +[orig_h=192.168.1.77, orig_p=57655/tcp, resp_h=209.197.168.151, resp_p=1024/tcp] +source: IRC_DATA +MD5: 35288fd50a74c7d675909ff83424d7a1 +SHA1: 8a98f177cb47e6bf771bf57c2f7e94c4b5e79ffa +SHA256: b24dde52b933a0d76e885ab418cb6d697b14a4e2fef45fce66e12ecc5a6a81aa FILE_STATE_REMOVE file #0, 42208, 0 [orig_h=192.168.1.77, orig_p=57655/tcp, resp_h=209.197.168.151, resp_p=1024/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.writer-path-conflict/http.log b/testing/btest/Baseline/scripts.base.frameworks.logging.writer-path-conflict/http.log index 6b7bea88c9..8f9d553d9a 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.writer-path-conflict/http.log +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.writer-path-conflict/http.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-23 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] +#open 2013-07-23-05-48-35 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] 1300475168.784020 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 1 GET bits.wikimedia.org /skins-1.5/monobook/main.css http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - 1300475168.916018 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - 1300475168.916183 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - @@ -20,4 +20,4 @@ 1300475169.014619 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - 1300475169.014593 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - 1300475169.014927 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -#close 2013-05-21-21-11-23 +#close 2013-07-23-05-48-35 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/notice.log b/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/notice.log index 051f1c6266..04c80407f6 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/notice.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/notice.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path notice -#open 2013-04-02-02-19-21 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude -#types time string addr port addr port enum enum string string addr addr port count string table[enum] interval bool string string string double double -1348168976.558309 arKYeMETxOg 192.168.57.103 35391 192.168.57.101 55968 tcp GridFTP::Data_Channel GridFTP data channel over threshold 2 bytes - 192.168.57.103 192.168.57.101 55968 - bro Notice::ACTION_LOG 3600.000000 F - - - - - -#close 2013-04-02-02-19-21 +#open 2013-07-23-05-19-25 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fuid file_mime_type file_desc proto note msg sub src dst p n peer_descr actions suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude +#types time string addr port addr port string string string enum enum string string addr addr port count string table[enum] interval bool string string string double double +1348168976.558309 arKYeMETxOg 192.168.57.103 35391 192.168.57.101 55968 - - - tcp GridFTP::Data_Channel GridFTP data channel over threshold 2 bytes - 192.168.57.103 192.168.57.101 55968 - bro Notice::ACTION_LOG 3600.000000 F - - - - - +#close 2013-07-23-05-19-25 diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime/smtp_entities.log b/testing/btest/Baseline/scripts.base.protocols.smtp.mime/smtp_entities.log deleted file mode 100644 index 135c644855..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.smtp.mime/smtp_entities.log +++ /dev/null @@ -1,12 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path smtp_entities -#open 2013-03-26-20-39-07 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth filename content_len mime_type md5 extraction_file excerpt -#types time string addr port addr port count string count string string string string -1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 79 text/plain 92bca2e6cdcde73647125da7dccbdd07 - (empty) -1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 1918 text/html - - (empty) -1254722770.692804 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 NEWS.txt 10823 text/plain a968bb0f9f9d95835b2e74c845877e87 - (empty) -#close 2013-03-26-20-39-07 diff --git a/testing/btest/scripts/base/protocols/smtp/mime.test b/testing/btest/scripts/base/protocols/smtp/mime.test deleted file mode 100644 index 8e7a336987..0000000000 --- a/testing/btest/scripts/base/protocols/smtp/mime.test +++ /dev/null @@ -1,6 +0,0 @@ -# @TEST-EXEC: bro -r $TRACES/smtp.trace %INPUT -# @TEST-EXEC: btest-diff smtp_entities.log - -@load base/protocols/smtp - -redef SMTP::generate_md5=/text\/plain/; diff --git a/testing/scripts/file-analysis-test.bro b/testing/scripts/file-analysis-test.bro index cf2bbf2d59..8fe78b218e 100644 --- a/testing/scripts/file-analysis-test.bro +++ b/testing/scripts/file-analysis-test.bro @@ -1,7 +1,7 @@ global test_file_analysis_source: string = "" &redef; -global test_file_analyzers: set[Files::AnalyzerArgs]; +global test_file_analyzers: set[Files::Tag]; global test_get_file_name: function(f: fa_file): string = function(f: fa_file): string { return ""; } &redef; @@ -46,11 +46,11 @@ event file_new(f: fa_file) local filename: string = test_get_file_name(f); if ( filename != "" ) - Files::add_analyzer(f, [$tag=Files::ANALYZER_EXTRACT, - $extract_filename=filename]); - Files::add_analyzer(f, [$tag=Files::ANALYZER_DATA_EVENT, - $chunk_event=file_chunk, - $stream_event=file_stream]); + Files::add_analyzer(f, Files::ANALYZER_EXTRACT, + [$extract_filename=filename]); + Files::add_analyzer(f, Files::ANALYZER_DATA_EVENT, + [$chunk_event=file_chunk, + $stream_event=file_stream]); } if ( f?$bof_buffer ) @@ -106,7 +106,7 @@ event file_state_remove(f: fa_file) event bro_init() { - add test_file_analyzers[[$tag=Files::ANALYZER_MD5]]; - add test_file_analyzers[[$tag=Files::ANALYZER_SHA1]]; - add test_file_analyzers[[$tag=Files::ANALYZER_SHA256]]; + add test_file_analyzers[Files::ANALYZER_MD5]; + add test_file_analyzers[Files::ANALYZER_SHA1]; + add test_file_analyzers[Files::ANALYZER_SHA256]; } From 73eb87a41ef5d79f5f84d8aebe42ce9b61aadc5a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 23 Jul 2013 14:16:39 -0500 Subject: [PATCH 137/881] Exec module changes/fixes. - Give Dir::monitor() a param for the polling interval, so different dirs can be monitored at different frequencies. - Fix race in Exec::run() when reading extra output files produced by a process -- it was possible for Exec::run() to return before all extra output files had been fully read. - Add test cases. --- scripts/base/utils/active-http.bro | 3 + scripts/base/utils/dir.bro | 34 +++++--- scripts/base/utils/exec.bro | 85 ++++++++++++------- .../bro..stdout | 5 ++ .../scripts.base.utils.dir/bro..stdout | 10 +++ .../scripts.base.utils.exec/bro..stdout | 7 ++ .../btest/scripts/base/utils/active-http.test | 25 ++++++ testing/btest/scripts/base/utils/dir.test | 58 +++++++++++++ testing/btest/scripts/base/utils/exec.test | 74 ++++++++++++++++ testing/scripts/httpd.py | 40 +++++++++ 10 files changed, 299 insertions(+), 42 deletions(-) create mode 100644 testing/btest/Baseline/scripts.base.utils.active-http/bro..stdout create mode 100644 testing/btest/Baseline/scripts.base.utils.dir/bro..stdout create mode 100644 testing/btest/Baseline/scripts.base.utils.exec/bro..stdout create mode 100644 testing/btest/scripts/base/utils/active-http.test create mode 100644 testing/btest/scripts/base/utils/dir.test create mode 100644 testing/btest/scripts/base/utils/exec.test create mode 100755 testing/scripts/httpd.py diff --git a/scripts/base/utils/active-http.bro b/scripts/base/utils/active-http.bro index 3f475a378b..eb9a212221 100644 --- a/scripts/base/utils/active-http.bro +++ b/scripts/base/utils/active-http.bro @@ -90,7 +90,10 @@ function request(req: Request): ActiveHTTP::Response { # If there is no response line then nothing else will work either. if ( ! (result?$files && headersfile in result$files) ) + { Reporter::error(fmt("There was a failure when requesting \"%s\" with ActiveHTTP.", req$url)); + return resp; + } local headers = result$files[headersfile]; for ( i in headers ) diff --git a/scripts/base/utils/dir.bro b/scripts/base/utils/dir.bro index b154fe000e..3329dc6306 100644 --- a/scripts/base/utils/dir.bro +++ b/scripts/base/utils/dir.bro @@ -5,6 +5,10 @@ module Dir; export { + ## The default interval this module checks for files in directories when + ## using the :bro:see:`Dir::monitor` function. + const polling_interval = 30sec &redef; + ## Register a directory to monitor with a callback that is called ## every time a previously unseen file is seen. If a file is deleted ## and seen to be gone, the file is available for being seen again in @@ -14,14 +18,15 @@ export { ## ## callback: Callback that gets executed with each file name ## that is found. Filenames are provided with the full path. - global monitor: function(dir: string, callback: function(fname: string)); - - ## The interval this module checks for files in directories when using - ## the :bro:see:`Dir::monitor` function. - const polling_interval = 30sec &redef; + ## + ## poll_interval: An interval at which to check for new files. + global monitor: function(dir: string, callback: function(fname: string), + poll_interval: interval &default=polling_interval); } -event Dir::monitor_ev(dir: string, last_files: set[string], callback: function(fname: string)) +event Dir::monitor_ev(dir: string, last_files: set[string], + callback: function(fname: string), + poll_interval: interval) { when ( local result = Exec::run([$cmd=fmt("ls -i \"%s/\"", str_shell_escape(dir))]) ) { @@ -32,7 +37,11 @@ event Dir::monitor_ev(dir: string, last_files: set[string], callback: function(f } local current_files: set[string] = set(); - local files = result$stdout; + local files: vector of string = vector(); + + if ( result?$stdout ) + files = result$stdout; + for ( i in files ) { local parts = split1(files[i], / /); @@ -40,13 +49,18 @@ event Dir::monitor_ev(dir: string, last_files: set[string], callback: function(f callback(build_path_compressed(dir, parts[2])); add current_files[parts[1]]; } - schedule polling_interval { Dir::monitor_ev(dir, current_files, callback) }; + + schedule poll_interval + { + Dir::monitor_ev(dir, current_files, callback, poll_interval) + }; } } -function monitor(dir: string, callback: function(fname: string)) +function monitor(dir: string, callback: function(fname: string), + poll_interval: interval &default=polling_interval) { - event Dir::monitor_ev(dir, set(), callback); + event Dir::monitor_ev(dir, set(), callback, poll_interval); } diff --git a/scripts/base/utils/exec.bro b/scripts/base/utils/exec.bro index f896a68064..4ffae29303 100644 --- a/scripts/base/utils/exec.bro +++ b/scripts/base/utils/exec.bro @@ -14,6 +14,8 @@ export { ## If additional files are required to be read in as part of the output ## of the command they can be defined here. read_files: set[string] &optional; + # The unique id for tracking executors. + uid: string &default=unique_id(""); }; type Result: record { @@ -44,14 +46,11 @@ export { const tmp_dir = "/tmp" &redef; } -redef record Command += { - # The unique id for tracking executors. - uid: string &optional; -}; +# Indexed by command uid. +global results: table[string] of Result; +global pending_commands: set[string]; +global pending_files: table[string] of set[string]; -global results: table[string] of Result = table(); -global finished_commands: set[string]; -global currently_tracked_files: set[string] = set(); type OneLine: record { s: string; is_stderr: bool; @@ -96,39 +95,63 @@ event Exec::file_line(description: Input::EventDescription, tpe: Input::Event, s result$files[track_file][|result$files[track_file]|] = s; } +event Input::end_of_data(name: string, source:string) + { + local parts = split1(name, /_/); + name = parts[1]; + + if ( name !in pending_commands || |parts| < 2 ) + return; + + local track_file = parts[2]; + + Input::remove(name); + + if ( name !in pending_files ) + delete pending_commands[name]; + else + { + delete pending_files[name][track_file]; + if ( |pending_files[name]| == 0 ) + delete pending_commands[name]; + system(fmt("rm \"%s\"", str_shell_escape(track_file))); + } + } + event InputRaw::process_finished(name: string, source:string, exit_code:count, signal_exit:bool) { + if ( name !in pending_commands ) + return; + + Input::remove(name); results[name]$exit_code = exit_code; results[name]$signal_exit = signal_exit; - Input::remove(name); - # Indicate to the "when" async watcher that this command is done. - add finished_commands[name]; - } - -event Exec::start_watching_file(uid: string, read_file: string) - { - Input::add_event([$source=fmt("%s", read_file), - $name=fmt("%s_%s", uid, read_file), - $reader=Input::READER_RAW, - $mode=Input::STREAM, - $want_record=F, - $fields=FileLine, - $ev=Exec::file_line]); + if ( name !in pending_files || |pending_files[name]| == 0 ) + # No extra files to read, command is done. + delete pending_commands[name]; + else + for ( read_file in pending_files[name] ) + Input::add_event([$source=fmt("%s", read_file), + $name=fmt("%s_%s", name, read_file), + $reader=Input::READER_RAW, + $want_record=F, + $fields=FileLine, + $ev=Exec::file_line]); } function run(cmd: Command): Result { - cmd$uid = unique_id(""); + add pending_commands[cmd$uid]; results[cmd$uid] = []; if ( cmd?$read_files ) { for ( read_file in cmd$read_files ) { - add currently_tracked_files[read_file]; - system(fmt("touch \"%s\" 2>/dev/null", str_shell_escape(read_file))); - schedule 1msec { Exec::start_watching_file(cmd$uid, read_file) }; + if ( cmd$uid !in pending_files ) + pending_files[cmd$uid] = set(); + add pending_files[cmd$uid][read_file]; } } @@ -144,9 +167,8 @@ function run(cmd: Command): Result $want_record=F, $config=config_strings]); - return when ( cmd$uid in finished_commands ) + return when ( cmd$uid !in pending_commands ) { - delete finished_commands[cmd$uid]; local result = results[cmd$uid]; delete results[cmd$uid]; return result; @@ -155,9 +177,8 @@ function run(cmd: Command): Result event bro_done() { - # We are punting here and just deleting any files that haven't been processed yet. - for ( fname in currently_tracked_files ) - { - system(fmt("rm \"%s\"", str_shell_escape(fname))); - } + # We are punting here and just deleting any unprocessed files. + for ( uid in pending_files ) + for ( fname in pending_files[uid] ) + system(fmt("rm \"%s\"", str_shell_escape(fname))); } diff --git a/testing/btest/Baseline/scripts.base.utils.active-http/bro..stdout b/testing/btest/Baseline/scripts.base.utils.active-http/bro..stdout new file mode 100644 index 0000000000..0284eb19b3 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.utils.active-http/bro..stdout @@ -0,0 +1,5 @@ +[code=200, msg=OK^M, body=It works!, headers={ +[Server] = 1.0, +[Content-type] = text/plain, +[Date] = July 22, 2013 +}] diff --git a/testing/btest/Baseline/scripts.base.utils.dir/bro..stdout b/testing/btest/Baseline/scripts.base.utils.dir/bro..stdout new file mode 100644 index 0000000000..c3103b7f64 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.utils.dir/bro..stdout @@ -0,0 +1,10 @@ +new_file1, ../testdir/bye +new_file1, ../testdir/hi +new_file1, ../testdir/howsitgoing +new_file2, ../testdir/bye +new_file2, ../testdir/hi +new_file2, ../testdir/howsitgoing +new_file1, ../testdir/bye +new_file1, ../testdir/newone +new_file2, ../testdir/bye +new_file2, ../testdir/newone diff --git a/testing/btest/Baseline/scripts.base.utils.exec/bro..stdout b/testing/btest/Baseline/scripts.base.utils.exec/bro..stdout new file mode 100644 index 0000000000..5352d15d18 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.utils.exec/bro..stdout @@ -0,0 +1,7 @@ +test1, [exit_code=0, signal_exit=F, stdout=[done, exit, stop], stderr=, files={ +[out1] = [insert text here, and here], +[out2] = [insert more text here, and there] +}] +test2, [exit_code=1, signal_exit=F, stdout=[here's something on stdout, some more stdout, last stdout], stderr=[and some stderr, more stderr, last stderr], files=] +test3, [exit_code=9, signal_exit=F, stdout=[FML], stderr=, files=] +test4, [exit_code=0, signal_exit=F, stdout=[hibye], stderr=, files=] diff --git a/testing/btest/scripts/base/utils/active-http.test b/testing/btest/scripts/base/utils/active-http.test new file mode 100644 index 0000000000..9ac762b9b7 --- /dev/null +++ b/testing/btest/scripts/base/utils/active-http.test @@ -0,0 +1,25 @@ +# @TEST-EXEC: btest-bg-run httpd python $SCRIPTS/httpd.py --max 1 +# @TEST-EXEC: sleep 3 +# @TEST-EXEC: btest-bg-run bro bro -b %INPUT +# @TEST-EXEC: btest-bg-wait 15 +# @TEST-EXEC: btest-diff bro/.stdout + +@load base/utils/active-http + +redef exit_only_after_terminate = T; + +event bro_init() + { + local req = ActiveHTTP::Request($url="localhost:32123"); + + when ( local resp = ActiveHTTP::request(req) ) + { + print resp; + terminate(); + } + timeout 1min + { + print "HTTP request timeout"; + terminate(); + } + } diff --git a/testing/btest/scripts/base/utils/dir.test b/testing/btest/scripts/base/utils/dir.test new file mode 100644 index 0000000000..44fee3860f --- /dev/null +++ b/testing/btest/scripts/base/utils/dir.test @@ -0,0 +1,58 @@ +# @TEST-EXEC: btest-bg-run bro bro -b ../dirtest.bro +# @TEST-EXEC: btest-bg-wait 10 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-sort btest-diff bro/.stdout + +@TEST-START-FILE dirtest.bro + +@load base/utils/dir + +redef exit_only_after_terminate = T; + +global c: count = 0; + +function check_terminate_condition() + { + c += 1; + + if ( c == 10 ) + terminate(); + } + +function new_file1(fname: string) + { + print "new_file1", fname; + check_terminate_condition(); + } + +function new_file2(fname: string) + { + print "new_file2", fname; + check_terminate_condition(); + } + +event change_things() + { + system("touch ../testdir/newone"); + system("rm ../testdir/bye && touch ../testdir/bye"); + } + +event bro_init() + { + Dir::monitor("../testdir", new_file1, .5sec); + Dir::monitor("../testdir", new_file2, 1sec); + schedule 1sec { change_things() }; + } + +@TEST-END-FILE + +@TEST-START-FILE testdir/hi +123 +@TEST-END-FILE + +@TEST-START-FILE testdir/howsitgoing +abc +@TEST-END-FILE + +@TEST-START-FILE testdir/bye +!@# +@TEST-END-FILE diff --git a/testing/btest/scripts/base/utils/exec.test b/testing/btest/scripts/base/utils/exec.test new file mode 100644 index 0000000000..8876f0f49b --- /dev/null +++ b/testing/btest/scripts/base/utils/exec.test @@ -0,0 +1,74 @@ +# @TEST-EXEC: btest-bg-run bro bro -b ../exectest.bro +# @TEST-EXEC: btest-bg-wait 10 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-sort btest-diff bro/.stdout + +@TEST-START-FILE exectest.bro + +@load base/utils/exec + +redef exit_only_after_terminate = T; + +global c: count = 0; + +function check_exit_condition() + { + c += 1; + + if ( c == 4 ) + terminate(); + } + +function test_cmd(label: string, cmd: Exec::Command) + { + when ( local result = Exec::run(cmd) ) + { + print label, result; + check_exit_condition(); + } + } + +event bro_init() + { + test_cmd("test1", [$cmd="bash ../somescript.sh", + $read_files=set("out1", "out2")]); + test_cmd("test2", [$cmd="bash ../nofiles.sh"]); + test_cmd("test3", [$cmd="bash ../suicide.sh"]); + test_cmd("test4", [$cmd="bash ../stdin.sh", $stdin="hibye"]); + } + +@TEST-END-FILE + +@TEST-START-FILE somescript.sh +#! /usr/bin/env bash +echo "insert text here" > out1 +echo "and here" >> out1 +echo "insert more text here" > out2 +echo "and there" >> out2 +echo "done" +echo "exit" +echo "stop" +@TEST-END-FILE + +@TEST-START-FILE nofiles.sh +#! /usr/bin/env bash +echo "here's something on stdout" +echo "some more stdout" +echo "last stdout" +echo "and some stderr" 1>&2 +echo "more stderr" 1>&2 +echo "last stderr" 1>&2 +exit 1 +@TEST-END-FILE + +@TEST-START-FILE suicide.sh +#! /usr/bin/env bash +echo "FML" +kill -9 $$ +echo "nope" +@TEST-END-FILE + +@TEST-START-FILE stdin.sh +#! /usr/bin/env bash +read -r line +echo "$line" +@TEST-END-FILE diff --git a/testing/scripts/httpd.py b/testing/scripts/httpd.py new file mode 100755 index 0000000000..0732614bc2 --- /dev/null +++ b/testing/scripts/httpd.py @@ -0,0 +1,40 @@ +#! /usr/bin/env python + +import BaseHTTPServer + +class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): + + def do_GET(self): + self.send_response(200) + self.send_header("Content-type", "text/plain") + self.end_headers() + self.wfile.write("It works!") + + def version_string(self): + return "1.0" + + def date_time_string(self): + return "July 22, 2013" + + +if __name__ == "__main__": + from optparse import OptionParser + p = OptionParser() + p.add_option("-a", "--addr", type="string", default="localhost", + help=("listen on given address (numeric IP or host name), " + "an empty string (the default) means INADDR_ANY")) + p.add_option("-p", "--port", type="int", default=32123, + help="listen on given TCP port number") + p.add_option("-m", "--max", type="int", default=-1, + help="max number of requests to respond to, -1 means no max") + options, args = p.parse_args() + + httpd = BaseHTTPServer.HTTPServer((options.addr, options.port), + MyRequestHandler) + if options.max == -1: + httpd.serve_forever() + else: + served_count = 0 + while served_count != options.max: + httpd.handle_request() + served_count += 1 From 75814e58e481f723868b644ba9fd06dba2fffa20 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 24 Jul 2013 00:35:46 -0400 Subject: [PATCH 138/881] Fix a bug with getting analyzer tags. --- src/analyzer/analyzer.bif | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyzer/analyzer.bif b/src/analyzer/analyzer.bif index 8b5a85956c..4d70816075 100644 --- a/src/analyzer/analyzer.bif +++ b/src/analyzer/analyzer.bif @@ -46,5 +46,6 @@ function __name%(atype: Analyzer::Tag%) : string function __tag%(name: string%) : Analyzer::Tag %{ - return new Val(analyzer_mgr->GetAnalyzerTag(name->CheckString()), TYPE_ENUM); + analyzer::Tag t = analyzer_mgr->GetAnalyzerTag(name->CheckString()); + return t.AsEnumVal()->Ref(); %} From b7cdfc0e6eb627b2df451b81355466f35936a64a Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 24 Jul 2013 12:50:01 -0700 Subject: [PATCH 139/881] adapt to new structure --- scripts/base/init-bare.bro | 1 + src/CMakeLists.txt | 1 - src/Func.cc | 2 + src/OpaqueVal.cc | 6 +- src/OpaqueVal.h | 15 ++- src/bro.bif | 125 ------------------------- src/probabilistic/CMakeLists.txt | 7 +- src/{ => probabilistic}/HyperLogLog.cc | 2 +- src/{ => probabilistic}/HyperLogLog.h | 4 + 9 files changed, 23 insertions(+), 140 deletions(-) rename src/{ => probabilistic}/HyperLogLog.cc (98%) rename src/{ => probabilistic}/HyperLogLog.h (99%) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index c368b9d610..33978091f1 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -706,6 +706,7 @@ type entropy_test_result: record { @load base/bif/bro.bif @load base/bif/reporter.bif @load base/bif/bloom-filter.bif +@load base/bif/hyper-loglog.bif ## Deprecated. This is superseded by the new logging framework. global log_file_name: function(tag: string): string &redef; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3d23f7a2b4..0c979df19f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -277,7 +277,6 @@ set(bro_SRCS Frame.cc Func.cc Hash.cc - HyperLogLog.cc ID.cc IntSet.cc IOSource.cc diff --git a/src/Func.cc b/src/Func.cc index 483699668f..4d8d7f3193 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -562,6 +562,7 @@ void builtin_error(const char* msg, BroObj* arg) // TODO: Add a nicer mechanism to pull in subdirectory bifs automatically. #include "probabilistic/bloom-filter.bif.h" +#include "probabilistic/hyper-loglog.bif.h" void init_builtin_funcs() { @@ -579,6 +580,7 @@ void init_builtin_funcs() // TODO: Add a nicer mechanism to pull in subdirectory bifs automatically. #include "probabilistic/bloom-filter.bif.init.cc" +#include "probabilistic/hyper-loglog.bif.init.cc" did_builtin_init = true; } diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 1d8214fd85..67e39aa2cc 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -4,7 +4,7 @@ #include "NetVar.h" #include "Reporter.h" #include "Serializer.h" -#include "HyperLogLog.h" +#include "probabilistic/HyperLogLog.h" CardinalityVal::CardinalityVal() : OpaqueVal(cardinality_type) @@ -54,7 +54,7 @@ bool CardinalityVal::DoUnserialize(UnserialInfo* info) uint64_t m; serialvalid &= UNSERIALIZE(&m); - c = new CardinalityCounter(m); + c = new probabilistic::CardinalityCounter(m); serialvalid &= UNSERIALIZE(&c->V); serialvalid &= UNSERIALIZE(&c->alpha_m); @@ -67,7 +67,7 @@ bool CardinalityVal::DoUnserialize(UnserialInfo* info) return valid; } -bool CardinalityVal::Init(CardinalityCounter* arg_c) +bool CardinalityVal::Init(probabilistic::CardinalityCounter* arg_c) { if ( valid ) return false; diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index 23df0d50d7..aeae4d9d51 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -10,28 +10,27 @@ #include "digest.h" #include "probabilistic/BloomFilter.h" -class CardinalityCounter; +namespace probabilistic { + class BloomFilter; + class CardinalityCounter; +} class CardinalityVal: public OpaqueVal { public: CardinalityVal(); ~CardinalityVal(); - bool Init(CardinalityCounter*); + bool Init(probabilistic::CardinalityCounter*); bool IsValid() const { return valid; }; - CardinalityCounter* Get() { return c; }; + probabilistic::CardinalityCounter* Get() { return c; }; private: bool valid; - CardinalityCounter* c; + probabilistic::CardinalityCounter* c; DECLARE_SERIAL(CardinalityVal); }; -namespace probabilistic { - class BloomFilter; -} - class HashVal : public OpaqueVal { public: virtual bool IsValid() const; diff --git a/src/bro.bif b/src/bro.bif index c3e46b501d..a01d68c585 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -4974,130 +4974,5 @@ function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr } %} -## This is where my code starts... -##Just a note about notation. I'm specifying everything with the prefix hll just -## in case in the future, there's a better way to count cardinalities or something. -## That way, code written that depends on the HyperLogLog algorithm will still be -## working. Though, I'm fairly certain that anything that might be better won't -## be significantly better. -%%{ -#include "HyperLogLog.h" -%%} - -## Initializes the hash for the HyperLogLog cardinality counting algorithm. -## It returns true if it was successful in creating a structure and false -## if it wasn't. - -function hll_cardinality_init%(err: double%): opaque of cardinality - %{ - CardinalityCounter* c = new CardinalityCounter(err); - CardinalityVal* cv = new CardinalityVal(); - - if ( !c ) - reporter->Error("Failed initialize Cardinality counter"); - else - cv->Init(c); - - return cv; - %} - -## Adds an element to the HyperLogLog data structure located at index. - -##elem->Type() to get the type of elem. - -function hll_cardinality_add%(handle: opaque of cardinality, elem: any%): bool - %{ - if ( !((CardinalityVal*) handle)->IsValid() ) { - reporter->Error("Need valid handle"); - return new Val(0, TYPE_BOOL); - } - - int status = 0; - uint64_t a = 123456; - - TypeList* tl = new TypeList(elem->Type()); - tl->Append(elem->Type()); - CompositeHash* hll_hash = new CompositeHash(tl); - Unref(tl); - - CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); - HashKey* key = hll_hash->ComputeHash(elem, 1); - a = key->Hash(); - h->addElement(a); - - delete hll_hash; - return new Val(1, TYPE_BOOL); - %} - -## The data structure at index1 will contain the combined count for the -## elements measured by index1 and index2. -## It returns true if it either cloned the value at index2 into index1 -## or if it merged the two data structures together. - -function hll_cardinality_merge_into%(handle1: opaque of cardinality, handle2: opaque of cardinality%): bool - %{ - CardinalityVal* v1 = (CardinalityVal*) handle1; - CardinalityVal* v2 = (CardinalityVal*) handle2; - - if ( !v1->IsValid() || !v2->IsValid() ) { - reporter->Error("need valid handles"); - return new Val(0, TYPE_BOOL); - } - - CardinalityCounter* h1 = v1->Get(); - CardinalityCounter* h2 = v2->Get(); - - h1->merge(h2); - - return new Val(1, TYPE_BOOL); - %} - -## Returns true if it destroyed something. False if it didn't. -#function hll_cardinality_destroy%(handle: opaque of cardinality%): bool -# %{ -# if ( !((CardinalityVal*) handle)->IsValid() ) { -# reporter->Error("Need valid handle"); -# return new Val(0, TYPE_BOOL); -# } -# CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); -# delete h; -# h = 0; -# return new Val(1, TYPE_BOOL); -# %} - -## Returns the cardinality estimate. Returns -1.0 if there is nothing in that index. -function hll_cardinality_estimate%(handle: opaque of cardinality%): double - %{ - if ( !((CardinalityVal*) handle)->IsValid() ) { - reporter->Error("Need valid handle"); - return new Val(0, TYPE_BOOL); - } - CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); - - double estimate = h->size(); - - return new Val(estimate, TYPE_DOUBLE); - %} - -## Stores the data structure at index2 into index1. Deletes the data structure at index1 -## if there was any. Returns True if the data structure at index1 was changed in any way. - -function hll_cardinality_clone%(handle: opaque of cardinality%): opaque of cardinality - %{ - if ( !((CardinalityVal*) handle)->IsValid() ) { - reporter->Error("Need valid handle"); - return new Val(0, TYPE_BOOL); - } - CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); - - - uint64_t m = h->getM(); - CardinalityCounter* h2 = new CardinalityCounter(m); - int i = 0; - h2->merge(h); - CardinalityVal* cv = new CardinalityVal(); - cv->Init(h2); - return cv; - %} diff --git a/src/probabilistic/CMakeLists.txt b/src/probabilistic/CMakeLists.txt index 961c07fb33..6f3c64f67e 100644 --- a/src/probabilistic/CMakeLists.txt +++ b/src/probabilistic/CMakeLists.txt @@ -10,9 +10,12 @@ set(probabilistic_SRCS BitVector.cc BloomFilter.cc CounterVector.cc - Hasher.cc) + Hasher.cc + HyperLogLog.cc) bif_target(bloom-filter.bif) +set(BIF_OUTPUT_CC_SAVE ${BIF_OUTPUT_CC}) +bif_target(hyper-loglog.bif) -bro_add_subdir_library(probabilistic ${probabilistic_SRCS} ${BIF_OUTPUT_CC}) +bro_add_subdir_library(probabilistic ${probabilistic_SRCS} ${BIF_OUTPUT_CC_SAVE} ${BIF_OUTPUT_CC}) add_dependencies(bro_probabilistic generate_outputs) diff --git a/src/HyperLogLog.cc b/src/probabilistic/HyperLogLog.cc similarity index 98% rename from src/HyperLogLog.cc rename to src/probabilistic/HyperLogLog.cc index 6dacab33a2..b1deb39552 100644 --- a/src/HyperLogLog.cc +++ b/src/probabilistic/HyperLogLog.cc @@ -5,7 +5,7 @@ #include "HyperLogLog.h" #include -using namespace std; +using namespace probabilistic; int CardinalityCounter::optimalB(double error) { diff --git a/src/HyperLogLog.h b/src/probabilistic/HyperLogLog.h similarity index 99% rename from src/HyperLogLog.h rename to src/probabilistic/HyperLogLog.h index f07167502a..0a7ea6ac2f 100644 --- a/src/HyperLogLog.h +++ b/src/probabilistic/HyperLogLog.h @@ -6,6 +6,8 @@ #include #include +namespace probabilistic { + /* * "conf" is how confident the estimate given by the counter is. * @@ -118,4 +120,6 @@ class CardinalityCounter { uint64_t getM(); }; +} + #endif From efdffaec9e810482edcf9aad7afcdf4f779ea8b9 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 24 Jul 2013 12:51:31 -0700 Subject: [PATCH 140/881] and forgot a file... --- src/probabilistic/hyper-loglog.bif | 131 +++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/probabilistic/hyper-loglog.bif diff --git a/src/probabilistic/hyper-loglog.bif b/src/probabilistic/hyper-loglog.bif new file mode 100644 index 0000000000..24b18e0c40 --- /dev/null +++ b/src/probabilistic/hyper-loglog.bif @@ -0,0 +1,131 @@ +# =========================================================================== +# +# HyperLogLog Functions +# +# =========================================================================== + + +%%{ +#include "probabilistic/HyperLogLog.h" + +using namespace probabilistic; +%%} + +module GLOBAL; + +## Initializes the hash for the HyperLogLog cardinality counting algorithm. +## It returns true if it was successful in creating a structure and false +## if it wasn't. + +function hll_cardinality_init%(err: double%): opaque of cardinality + %{ + CardinalityCounter* c = new CardinalityCounter(err); + CardinalityVal* cv = new CardinalityVal(); + + if ( !c ) + reporter->Error("Failed initialize Cardinality counter"); + else + cv->Init(c); + + return cv; + %} + +## Adds an element to the HyperLogLog data structure located at index. + +##elem->Type() to get the type of elem. + +function hll_cardinality_add%(handle: opaque of cardinality, elem: any%): bool + %{ + if ( !((CardinalityVal*) handle)->IsValid() ) { + reporter->Error("Need valid handle"); + return new Val(0, TYPE_BOOL); + } + + int status = 0; + uint64_t a = 123456; + + TypeList* tl = new TypeList(elem->Type()); + tl->Append(elem->Type()); + CompositeHash* hll_hash = new CompositeHash(tl); + Unref(tl); + + CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); + HashKey* key = hll_hash->ComputeHash(elem, 1); + a = key->Hash(); + h->addElement(a); + + delete hll_hash; + return new Val(1, TYPE_BOOL); + %} + +## The data structure at index1 will contain the combined count for the +## elements measured by index1 and index2. +## It returns true if it either cloned the value at index2 into index1 +## or if it merged the two data structures together. + +function hll_cardinality_merge_into%(handle1: opaque of cardinality, handle2: opaque of cardinality%): bool + %{ + CardinalityVal* v1 = (CardinalityVal*) handle1; + CardinalityVal* v2 = (CardinalityVal*) handle2; + + if ( !v1->IsValid() || !v2->IsValid() ) { + reporter->Error("need valid handles"); + return new Val(0, TYPE_BOOL); + } + + CardinalityCounter* h1 = v1->Get(); + CardinalityCounter* h2 = v2->Get(); + + h1->merge(h2); + + return new Val(1, TYPE_BOOL); + %} + +## Returns true if it destroyed something. False if it didn't. +#function hll_cardinality_destroy%(handle: opaque of cardinality%): bool +# %{ +# if ( !((CardinalityVal*) handle)->IsValid() ) { +# reporter->Error("Need valid handle"); +# return new Val(0, TYPE_BOOL); +# } +# CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); +# delete h; +# h = 0; +# return new Val(1, TYPE_BOOL); +# %} + +## Returns the cardinality estimate. Returns -1.0 if there is nothing in that index. +function hll_cardinality_estimate%(handle: opaque of cardinality%): double + %{ + if ( !((CardinalityVal*) handle)->IsValid() ) { + reporter->Error("Need valid handle"); + return new Val(0, TYPE_BOOL); + } + CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); + + double estimate = h->size(); + + return new Val(estimate, TYPE_DOUBLE); + %} + +## Stores the data structure at index2 into index1. Deletes the data structure at index1 +## if there was any. Returns True if the data structure at index1 was changed in any way. + +function hll_cardinality_clone%(handle: opaque of cardinality%): opaque of cardinality + %{ + if ( !((CardinalityVal*) handle)->IsValid() ) { + reporter->Error("Need valid handle"); + return new Val(0, TYPE_BOOL); + } + CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); + + + uint64_t m = h->getM(); + CardinalityCounter* h2 = new CardinalityCounter(m); + int i = 0; + h2->merge(h); + CardinalityVal* cv = new CardinalityVal(); + cv->Init(h2); + return cv; + %} + From e482897f885e2f1039b96782d5e4bc080d74a535 Mon Sep 17 00:00:00 2001 From: Matthias Vallentin Date: Thu, 25 Jul 2013 15:16:53 +0200 Subject: [PATCH 141/881] Add docs and use default value for hasher names. --- src/probabilistic/Hasher.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/probabilistic/Hasher.h b/src/probabilistic/Hasher.h index 62c5d58d1f..d266565284 100644 --- a/src/probabilistic/Hasher.h +++ b/src/probabilistic/Hasher.h @@ -63,7 +63,9 @@ public: size_t K() const { return k; } /** - * Returns the hasher's name. TODO: What's this? + * Returns the hasher's name. If not empty, the hasher uses this descriptor + * to seed its *k* hash functions. Otherwise the hasher mixes in the initial + * seed derived from the environment variable `$BRO_SEED`. */ const std::string& Name() const { return name; } @@ -83,7 +85,7 @@ public: protected: Hasher(size_t k, const std::string& name); - private: +private: const size_t k; std::string name; }; @@ -166,7 +168,7 @@ public: * * @param name The name of the hasher. */ - DefaultHasher(size_t k, const std::string& name); + DefaultHasher(size_t k, const std::string& name = ""); // Overridden from Hasher. virtual digest_vector Hash(const void* x, size_t n) const /* final */; @@ -190,7 +192,7 @@ public: * * @param name The name of the hasher. */ - DoubleHasher(size_t k, const std::string& name); + DoubleHasher(size_t k, const std::string& name = ""); // Overridden from Hasher. virtual digest_vector Hash(const void* x, size_t n) const /* final */; From 2fc5ca53ff8f90aa959b2bc65626b319a1dee529 Mon Sep 17 00:00:00 2001 From: Matthias Vallentin Date: Thu, 25 Jul 2013 17:35:35 +0200 Subject: [PATCH 142/881] Make hashers serializable. There exists still a small bug that I could not find; the unit test istate/opaque.bro fails. If someone sees why, please chime in. --- src/SerialTypes.h | 6 ++ src/probabilistic/BloomFilter.cc | 19 +----- src/probabilistic/BloomFilter.h | 3 - src/probabilistic/Hasher.cc | 99 ++++++++++++++++++++++++++---- src/probabilistic/Hasher.h | 33 +++++----- src/probabilistic/bloom-filter.bif | 4 +- 6 files changed, 117 insertions(+), 47 deletions(-) diff --git a/src/SerialTypes.h b/src/SerialTypes.h index 85aed10bda..9933d005f0 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -52,6 +52,7 @@ SERIAL_IS(RE_MATCHER, 0x1400) SERIAL_IS(BITVECTOR, 0x1500) SERIAL_IS(COUNTERVECTOR, 0x1600) SERIAL_IS(BLOOMFILTER, 0x1700) +SERIAL_IS(HASHER, 0x1800) // These are the externally visible types. const SerialType SER_NONE = 0; @@ -206,6 +207,11 @@ SERIAL_BLOOMFILTER(BLOOMFILTER, 1) SERIAL_BLOOMFILTER(BASICBLOOMFILTER, 2) SERIAL_BLOOMFILTER(COUNTINGBLOOMFILTER, 3) +#define SERIAL_HASHER(name, val) SERIAL_CONST(name, val, HASHER) +SERIAL_HASHER(HASHER, 1) +SERIAL_HASHER(DEFAULTHASHER, 2) +SERIAL_HASHER(DOUBLEHASHER, 3) + SERIAL_CONST2(ID) SERIAL_CONST2(STATE_ACCESS) SERIAL_CONST2(CASE) diff --git a/src/probabilistic/BloomFilter.cc b/src/probabilistic/BloomFilter.cc index 7f769cbf7c..d446643ed3 100644 --- a/src/probabilistic/BloomFilter.cc +++ b/src/probabilistic/BloomFilter.cc @@ -38,28 +38,15 @@ bool BloomFilter::DoSerialize(SerialInfo* info) const { DO_SERIALIZE(SER_BLOOMFILTER, SerialObj); - if ( ! SERIALIZE(static_cast(hasher->K())) ) - return false; - - return SERIALIZE_STR(hasher->Name().c_str(), hasher->Name().size()); + return hasher->Serialize(info); } bool BloomFilter::DoUnserialize(UnserialInfo* info) { DO_UNSERIALIZE(SerialObj); - uint16 k; - if ( ! UNSERIALIZE(&k) ) - return false; - - const char* name; - if ( ! UNSERIALIZE_STR(&name, 0) ) - return false; - - hasher = Hasher::Create(k, name); - - delete [] name; - return true; + hasher = Hasher::Unserialize(info); + return hasher != 0; } size_t BasicBloomFilter::M(double fp, size_t capacity) diff --git a/src/probabilistic/BloomFilter.h b/src/probabilistic/BloomFilter.h index b6cf18672f..4865ae145c 100644 --- a/src/probabilistic/BloomFilter.h +++ b/src/probabilistic/BloomFilter.h @@ -13,9 +13,6 @@ class CounterVector; /** * The abstract base class for Bloom filters. - * - * At this point we won't let the user choose the hasher, but we might open - * up the interface in the future. */ class BloomFilter : public SerialObj { public: diff --git a/src/probabilistic/Hasher.cc b/src/probabilistic/Hasher.cc index f9ce7bdd6b..7db363142d 100644 --- a/src/probabilistic/Hasher.cc +++ b/src/probabilistic/Hasher.cc @@ -4,9 +4,56 @@ #include "Hasher.h" #include "digest.h" +#include "Serializer.h" using namespace probabilistic; +bool Hasher::Serialize(SerialInfo* info) const + { + return SerialObj::Serialize(info); + } + +Hasher* Hasher::Unserialize(UnserialInfo* info) + { + return reinterpret_cast(SerialObj::Unserialize(info, SER_HASHER)); + } + +bool Hasher::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_HASHER, SerialObj); + + if ( ! SERIALIZE(static_cast(k)) ) + return false; + + return SERIALIZE_STR(name.c_str(), name.size()); + } + +bool Hasher::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(SerialObj); + + uint16 serial_k; + if ( ! UNSERIALIZE(&serial_k) ) + return false; + k = serial_k; + assert(k > 0); + + const char* serial_name; + if ( ! UNSERIALIZE_STR(&serial_name, 0) ) + return false; + name = serial_name; + delete [] serial_name; + + return true; + } + +Hasher::Hasher(size_t k, const std::string& arg_name) + : k(k) + { + name = arg_name; + } + + UHF::UHF(size_t seed, const std::string& extra) : h(compute_seed(seed, extra)) { @@ -40,17 +87,6 @@ size_t UHF::compute_seed(size_t seed, const std::string& extra) return *reinterpret_cast(buf); } -Hasher* Hasher::Create(size_t k, const std::string& name) - { - return new DefaultHasher(k, name); - } - -Hasher::Hasher(size_t k, const std::string& arg_name) - : k(k) - { - name = arg_name; - } - DefaultHasher::DefaultHasher(size_t k, const std::string& name) : Hasher(k, name) { @@ -82,6 +118,27 @@ bool DefaultHasher::Equals(const Hasher* other) const return hash_functions == o->hash_functions; } +IMPLEMENT_SERIAL(DefaultHasher, SER_DEFAULTHASHER) + +bool DefaultHasher::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_DEFAULTHASHER, Hasher); + + // Nothing to do here, the base class has all we need serialized already. + return true; + } + +bool DefaultHasher::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(Hasher); + + hash_functions.clear(); + for ( size_t i = 0; i < K(); ++i ) + hash_functions.push_back(UHF(i, Name())); + + return true; + } + DoubleHasher::DoubleHasher(size_t k, const std::string& name) : Hasher(k, name), h1(1, name), h2(2, name) { @@ -112,3 +169,23 @@ bool DoubleHasher::Equals(const Hasher* other) const const DoubleHasher* o = static_cast(other); return h1 == o->h1 && h2 == o->h2; } + +IMPLEMENT_SERIAL(DoubleHasher, SER_DOUBLEHASHER) + +bool DoubleHasher::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_DOUBLEHASHER, Hasher); + + // Nothing to do here, the base class has all we need serialized already. + return true; + } + +bool DoubleHasher::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(Hasher); + + h1 = UHF(1, Name()); + h2 = UHF(2, Name()); + + return true; + } diff --git a/src/probabilistic/Hasher.h b/src/probabilistic/Hasher.h index d266565284..7e6a8ba134 100644 --- a/src/probabilistic/Hasher.h +++ b/src/probabilistic/Hasher.h @@ -5,6 +5,7 @@ #include "Hash.h" #include "H3.h" +#include "SerialObj.h" namespace probabilistic { @@ -12,7 +13,7 @@ namespace probabilistic { * Abstract base class for hashers. A hasher creates a family of hash * functions to hash an element *k* times. */ -class Hasher { +class Hasher : public SerialObj { public: typedef hash_t digest; typedef std::vector digest_vector; @@ -69,24 +70,18 @@ public: */ const std::string& Name() const { return name; } - /** - * Constructs the hasher used by the implementation. This hardcodes a - * specific hashing policy. It exists only because the HashingPolicy - * class hierachy is not yet serializable. - * - * @param k The number of hash functions to apply. - * - * @param name The hasher's name. - * - * @return Returns a new hasher instance. - */ - static Hasher* Create(size_t k, const std::string& name); + bool Serialize(SerialInfo* info) const; + static Hasher* Unserialize(UnserialInfo* info); protected: + DECLARE_ABSTRACT_SERIAL(Hasher); + + Hasher() { } + Hasher(size_t k, const std::string& name); private: - const size_t k; + size_t k; std::string name; }; @@ -106,7 +101,7 @@ public: * seed to compute the seed for t to compute the seed NUL-terminated * string as additional seed. */ - UHF(size_t seed, const std::string& extra = ""); + UHF(size_t seed = 0, const std::string& extra = ""); template Hasher::digest operator()(const T& x) const @@ -175,7 +170,11 @@ public: virtual DefaultHasher* Clone() const /* final */; virtual bool Equals(const Hasher* other) const /* final */; + DECLARE_SERIAL(DefaultHasher); + private: + DefaultHasher() { } + std::vector hash_functions; }; @@ -199,7 +198,11 @@ public: virtual DoubleHasher* Clone() const /* final */; virtual bool Equals(const Hasher* other) const /* final */; + DECLARE_SERIAL(DoubleHasher); + private: + DoubleHasher() { } + UHF h1; UHF h2; }; diff --git a/src/probabilistic/bloom-filter.bif b/src/probabilistic/bloom-filter.bif index dd21688fdd..f03e3d149b 100644 --- a/src/probabilistic/bloom-filter.bif +++ b/src/probabilistic/bloom-filter.bif @@ -40,7 +40,7 @@ function bloomfilter_basic_init%(fp: double, capacity: count, size_t cells = BasicBloomFilter::M(fp, capacity); size_t optimal_k = BasicBloomFilter::K(cells, capacity); - const Hasher* h = Hasher::Create(optimal_k, name->CheckString()); + const Hasher* h = new DefaultHasher(optimal_k, name->CheckString()); return new BloomFilterVal(new BasicBloomFilter(h, cells)); %} @@ -68,7 +68,7 @@ function bloomfilter_counting_init%(k: count, cells: count, max: count, return 0; } - const Hasher* h = Hasher::Create(k, name->CheckString()); + const Hasher* h = new DefaultHasher(k, name->CheckString()); uint16 width = 1; while ( max >>= 1 ) From 939619889d41b3233e72e0c109301355bee25173 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 25 Jul 2013 16:51:16 -0500 Subject: [PATCH 143/881] File analysis fixes and test updates. - Several places were just using old variable names or not loading scripts correctly after they'd been renamed/moved. - Revert/adjust a change in how HTTP file handles are generated that broke partial content responses. - Turn some libmagic builtin checks back on; seems some are actually useful (e.g. text detection seems to be a builtin). The rule going forward probably will be only to turn off a builtin if we confirm it causes issues. - Removed some tests that are redundant or not necessary anymore because the generic file analysis tests cover them. - A couple FTP tests still fail that I think need an actual solution via script changes. --- doc/scripts/CMakeLists.txt | 4 +- doc/scripts/DocSourcesList.cmake | 23 +- scripts/base/frameworks/files/main.bro | 8 +- scripts/base/protocols/ftp/files.bro | 1 + scripts/base/protocols/http/files.bro | 10 +- scripts/policy/protocols/http/detect-MHR.bro | 44 --- .../protocols/smtp/entities-excerpt.bro | 7 +- scripts/test-all-policy.bro | 4 +- src/util.cc | 14 + src/util.h | 17 - .../Baseline/core.tunnels.ayiya/http.log | 6 +- .../http.log | 12 +- .../core.tunnels.gtp.outer_ip_frag/http.log | 10 +- .../Baseline/core.tunnels.teredo/http.log | 16 +- .../http.log | 12 +- .../canonified_loaded_scripts.log | 10 +- .../istate.events-ssl/receiver.http.log | 10 +- .../istate.events-ssl/sender.http.log | 10 +- .../Baseline/istate.events/receiver.http.log | 10 +- .../Baseline/istate.events/sender.http.log | 10 +- .../out | 1 + .../get.out | 1 + .../bro..stdout | 2 + .../get.out | 1 + .../out | 2 +- .../get-gzip.out | 1 + .../get.out | 1 + .../out | 4 + .../a.out | 1 + .../b.out | 2 + .../c.out | 1 + .../out | 5 + .../out | 2 + .../file_analysis.log | 10 - .../files.log | 10 + .../out | 3 + .../http.log | 10 +- .../manager-1.notice.log | 10 +- .../manager-1.notice.log | 10 +- .../notice.log | 10 +- .../conn.log | 14 - .../extractions | 22 -- .../ftp.log | 21 -- .../http.log | 10 +- .../http-item.dat | 304 ------------------ .../http.log | 10 - .../http.log | 100 +++--- .../http.log | 14 - .../http.log | 18 +- .../http.log | 10 +- .../scripts.base.protocols.irc.basic/irc.log | 6 +- .../irc-dcc-item.dat | Bin 42208 -> 0 bytes .../irc.log | 13 - .../smtp.log | 10 +- .../extractions | 277 ---------------- .../filecount | 1 - .../smtp_entities.log | 12 - .../notice.log | 12 +- testing/btest/istate/events-ssl.bro | 21 +- testing/btest/istate/events.bro | 15 +- .../file-analysis/bifs/remove_action.bro | 4 +- .../base/frameworks/file-analysis/irc.bro | 16 +- .../base/frameworks/file-analysis/logging.bro | 2 +- .../base/protocols/ftp/ftp-extract.bro | 10 - .../protocols/http/http-extract-files.bro | 6 - .../base/protocols/http/http-mime-and-md5.bro | 6 - .../base/protocols/http/multipart-extract.bro | 8 +- .../base/protocols/irc/dcc-extract.test | 11 - .../base/protocols/smtp/mime-extract.test | 11 - testing/external/subdir-btest.cfg | 2 +- testing/scripts/file-analysis-test.bro | 4 + 71 files changed, 293 insertions(+), 1002 deletions(-) delete mode 100644 scripts/policy/protocols/http/detect-MHR.bro delete mode 100644 testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/file_analysis.log create mode 100644 testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/files.log delete mode 100644 testing/btest/Baseline/scripts.base.protocols.ftp.ftp-extract/conn.log delete mode 100644 testing/btest/Baseline/scripts.base.protocols.ftp.ftp-extract/extractions delete mode 100644 testing/btest/Baseline/scripts.base.protocols.ftp.ftp-extract/ftp.log delete mode 100644 testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item.dat delete mode 100644 testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log delete mode 100644 testing/btest/Baseline/scripts.base.protocols.http.http-mime-and-md5/http.log delete mode 100644 testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item.dat delete mode 100644 testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log delete mode 100644 testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/extractions delete mode 100644 testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/filecount delete mode 100644 testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log delete mode 100644 testing/btest/scripts/base/protocols/ftp/ftp-extract.bro delete mode 100644 testing/btest/scripts/base/protocols/http/http-extract-files.bro delete mode 100644 testing/btest/scripts/base/protocols/http/http-mime-and-md5.bro delete mode 100644 testing/btest/scripts/base/protocols/irc/dcc-extract.test delete mode 100644 testing/btest/scripts/base/protocols/smtp/mime-extract.test diff --git a/doc/scripts/CMakeLists.txt b/doc/scripts/CMakeLists.txt index ddb09bb29c..e7e39d0b3f 100644 --- a/doc/scripts/CMakeLists.txt +++ b/doc/scripts/CMakeLists.txt @@ -99,7 +99,7 @@ macro(REST_TARGET srcDir broInput) COMMAND "${CMAKE_COMMAND}" ARGS -E remove_directory .state # generate the reST documentation using bro - COMMAND BROPATH=${BROPATH}:${srcDir} BROMAGIC=${CMAKE_SOURCE_DIR}/magic ${CMAKE_BINARY_DIR}/src/bro + COMMAND BROPATH=${BROPATH}:${srcDir} BROMAGIC=${CMAKE_SOURCE_DIR}/magic/database ${CMAKE_BINARY_DIR}/src/bro ARGS -b -Z ${broInput} || (rm -rf .state *.log *.rst && exit 1) # move generated doc into a new directory tree that # defines the final structure of documents @@ -130,7 +130,7 @@ add_custom_command(OUTPUT proto-analyzers.rst COMMAND "${CMAKE_COMMAND}" ARGS -E remove_directory .state # generate the reST documentation using bro - COMMAND BROPATH=${BROPATH}:${srcDir} BROMAGIC=${CMAKE_SOURCE_DIR}/magic ${CMAKE_BINARY_DIR}/src/bro + COMMAND BROPATH=${BROPATH}:${srcDir} BROMAGIC=${CMAKE_SOURCE_DIR}/magic/database ${CMAKE_BINARY_DIR}/src/bro ARGS -b -Z base/init-bare.bro || (rm -rf .state *.log *.rst && exit 1) # move generated doc into a new directory tree that # defines the final structure of documents diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index 529b03ca83..b2c932d117 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -73,6 +73,8 @@ rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_ZIP.events.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/reporter.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/strings.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/types.bif.bro) +rest_target(${psd} base/files/extract/main.bro) +rest_target(${psd} base/files/hash/main.bro) rest_target(${psd} base/frameworks/analyzer/main.bro) rest_target(${psd} base/frameworks/cluster/main.bro) rest_target(${psd} base/frameworks/cluster/nodes/manager.bro) @@ -82,7 +84,7 @@ rest_target(${psd} base/frameworks/cluster/setup-connections.bro) rest_target(${psd} base/frameworks/communication/main.bro) rest_target(${psd} base/frameworks/control/main.bro) rest_target(${psd} base/frameworks/dpd/main.bro) -rest_target(${psd} base/frameworks/file-analysis/main.bro) +rest_target(${psd} base/frameworks/files/main.bro) rest_target(${psd} base/frameworks/input/main.bro) rest_target(${psd} base/frameworks/input/readers/ascii.bro) rest_target(${psd} base/frameworks/input/readers/benchmark.bro) @@ -136,25 +138,22 @@ rest_target(${psd} base/protocols/conn/main.bro) rest_target(${psd} base/protocols/conn/polling.bro) rest_target(${psd} base/protocols/dns/consts.bro) rest_target(${psd} base/protocols/dns/main.bro) -rest_target(${psd} base/protocols/ftp/file-analysis.bro) -rest_target(${psd} base/protocols/ftp/file-extract.bro) +rest_target(${psd} base/protocols/ftp/files.bro) rest_target(${psd} base/protocols/ftp/gridftp.bro) rest_target(${psd} base/protocols/ftp/main.bro) rest_target(${psd} base/protocols/ftp/utils-commands.bro) -rest_target(${psd} base/protocols/http/file-analysis.bro) -rest_target(${psd} base/protocols/http/file-extract.bro) -rest_target(${psd} base/protocols/http/file-hash.bro) -rest_target(${psd} base/protocols/http/file-ident.bro) +rest_target(${psd} base/protocols/ftp/utils.bro) +rest_target(${psd} base/protocols/http/entities.bro) +rest_target(${psd} base/protocols/http/files.bro) rest_target(${psd} base/protocols/http/main.bro) rest_target(${psd} base/protocols/http/utils.bro) rest_target(${psd} base/protocols/irc/dcc-send.bro) -rest_target(${psd} base/protocols/irc/file-analysis.bro) +rest_target(${psd} base/protocols/irc/files.bro) rest_target(${psd} base/protocols/irc/main.bro) rest_target(${psd} base/protocols/modbus/consts.bro) rest_target(${psd} base/protocols/modbus/main.bro) -rest_target(${psd} base/protocols/smtp/entities-excerpt.bro) rest_target(${psd} base/protocols/smtp/entities.bro) -rest_target(${psd} base/protocols/smtp/file-analysis.bro) +rest_target(${psd} base/protocols/smtp/files.bro) rest_target(${psd} base/protocols/smtp/main.bro) rest_target(${psd} base/protocols/socks/consts.bro) rest_target(${psd} base/protocols/socks/main.bro) @@ -182,6 +181,8 @@ rest_target(${psd} policy/frameworks/control/controllee.bro) rest_target(${psd} policy/frameworks/control/controller.bro) rest_target(${psd} policy/frameworks/dpd/detect-protocols.bro) rest_target(${psd} policy/frameworks/dpd/packet-segment-logging.bro) +rest_target(${psd} policy/frameworks/files/detect-MHR.bro) +rest_target(${psd} policy/frameworks/files/hash-all-files.bro) rest_target(${psd} policy/frameworks/intel/conn-established.bro) rest_target(${psd} policy/frameworks/intel/dns.bro) rest_target(${psd} policy/frameworks/intel/http-host-header.bro) @@ -214,7 +215,6 @@ rest_target(${psd} policy/protocols/dns/detect-external-names.bro) rest_target(${psd} policy/protocols/ftp/detect-bruteforcing.bro) rest_target(${psd} policy/protocols/ftp/detect.bro) rest_target(${psd} policy/protocols/ftp/software.bro) -rest_target(${psd} policy/protocols/http/detect-MHR.bro) rest_target(${psd} policy/protocols/http/detect-sqli.bro) rest_target(${psd} policy/protocols/http/detect-webapps.bro) rest_target(${psd} policy/protocols/http/header-names.bro) @@ -226,6 +226,7 @@ rest_target(${psd} policy/protocols/modbus/known-masters-slaves.bro) rest_target(${psd} policy/protocols/modbus/track-memmap.bro) rest_target(${psd} policy/protocols/smtp/blocklists.bro) rest_target(${psd} policy/protocols/smtp/detect-suspicious-orig.bro) +rest_target(${psd} policy/protocols/smtp/entities-excerpt.bro) rest_target(${psd} policy/protocols/smtp/software.bro) rest_target(${psd} policy/protocols/ssh/detect-bruteforcing.bro) rest_target(${psd} policy/protocols/ssh/geo-data.bro) diff --git a/scripts/base/frameworks/files/main.bro b/scripts/base/frameworks/files/main.bro index cc92932bbf..d0c381545b 100644 --- a/scripts/base/frameworks/files/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -139,7 +139,9 @@ export { ## ## f: the file. ## - ## args: the analyzer type to add along with any arguments it takes. + ## tag: the analyzer type. + ## + ## args: any parameters the analyzer takes. ## ## Returns: true if the analyzer will be added, or false if analysis ## for the *id* isn't currently active or the *args* @@ -156,7 +158,9 @@ export { ## ## Returns: true if the analyzer will be removed, or false if analysis ## for the *id* isn't currently active. - global remove_analyzer: function(f: fa_file, tag: Files::Tag, args: AnalyzerArgs): bool; + global remove_analyzer: function(f: fa_file, + tag: Files::Tag, + args: AnalyzerArgs &default=AnalyzerArgs()): bool; ## Stops/ignores any further analysis of a given file. ## diff --git a/scripts/base/protocols/ftp/files.bro b/scripts/base/protocols/ftp/files.bro index 1d7b7670f4..9ed17ab2a4 100644 --- a/scripts/base/protocols/ftp/files.bro +++ b/scripts/base/protocols/ftp/files.bro @@ -1,4 +1,5 @@ @load ./main +@load ./utils @load base/utils/conn-ids @load base/frameworks/files diff --git a/scripts/base/protocols/http/files.bro b/scripts/base/protocols/http/files.bro index fd07dc096a..14dbb12989 100644 --- a/scripts/base/protocols/http/files.bro +++ b/scripts/base/protocols/http/files.bro @@ -1,6 +1,7 @@ @load ./main @load ./entities @load ./utils +@load base/utils/conn-ids @load base/frameworks/files module HTTP; @@ -18,13 +19,16 @@ function get_file_handle(c: connection, is_orig: bool): string if ( ! c?$http ) return ""; - local mime_depth = is_orig ? c$http$orig_mime_depth : c$http$resp_mime_depth; - if ( c$http$range_request ) + if ( c$http$range_request && ! is_orig ) { - return cat(Analyzer::ANALYZER_HTTP, is_orig, c$id$orig_h, mime_depth, build_url(c$http)); + # Any multipart responses from the server are pieces of same file + # that correspond to range requests, so don't use mime depth to + # identify the file. + return cat(Analyzer::ANALYZER_HTTP, is_orig, c$id$orig_h, build_url(c$http)); } else { + local mime_depth = is_orig ? c$http$orig_mime_depth : c$http$resp_mime_depth; return cat(Analyzer::ANALYZER_HTTP, c$start_time, is_orig, c$http$trans_depth, mime_depth, id_string(c$id)); } diff --git a/scripts/policy/protocols/http/detect-MHR.bro b/scripts/policy/protocols/http/detect-MHR.bro deleted file mode 100644 index 0594276c93..0000000000 --- a/scripts/policy/protocols/http/detect-MHR.bro +++ /dev/null @@ -1,44 +0,0 @@ -##! Detect file downloads over HTTP that have MD5 sums matching files in Team -##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). -##! By default, not all file transfers will have MD5 sums calculated. Read the -##! documentation for the :doc:base/protocols/http/file-hash.bro script to see -##! how to configure which transfers will have hashes calculated. - -@load base/frameworks/notice -@load base/protocols/http - -module HTTP; - -export { - redef enum Notice::Type += { - ## The MD5 sum of a file transferred over HTTP matched in the - ## malware hash registry. - Malware_Hash_Registry_Match - }; - - ## The malware hash registry runs each malware sample through several A/V engines. - ## Team Cymru returns a percentage to indicate how many A/V engines flagged the - ## sample as malicious. This threshold allows you to require a minimum detection - ## rate (default: 50%). - const MHR_threshold = 50 &redef; -} - -event log_http(rec: HTTP::Info) - { - if ( rec?$md5 ) - { - local hash_domain = fmt("%s.malware.hash.cymru.com", rec$md5); - when ( local MHR_result = lookup_hostname_txt(hash_domain) ) - { - # Data is returned as " " - local MHR_answer = split1(MHR_result, / /); - if ( |MHR_answer| == 2 && to_count(MHR_answer[2]) >= MHR_threshold ) - { - local url = HTTP::build_url_http(rec); - local message = fmt("%s %s %s", rec$id$orig_h, rec$md5, url); - NOTICE([$note=Malware_Hash_Registry_Match, - $msg=message, $id=rec$id]); - } - } - } - } diff --git a/scripts/policy/protocols/smtp/entities-excerpt.bro b/scripts/policy/protocols/smtp/entities-excerpt.bro index 1ecd100571..423fae1ada 100644 --- a/scripts/policy/protocols/smtp/entities-excerpt.bro +++ b/scripts/policy/protocols/smtp/entities-excerpt.bro @@ -1,12 +1,12 @@ ##! This script is for optionally adding a body excerpt to the SMTP ##! entities log. -@load ./entities +@load base/protocols/smtp/entities module SMTP; export { - redef record SMTP::EntityInfo += { + redef record SMTP::Entity+= { ## The entity body excerpt. excerpt: string &log &default=""; }; @@ -31,7 +31,6 @@ event file_new(f: fa_file) &priority=5 if ( ! c?$smtp ) next; if ( default_entity_excerpt_len > 0 ) - c$smtp$current_entity$excerpt = - f$bof_buffer[0:default_entity_excerpt_len]; + c$smtp$entity$excerpt = f$bof_buffer[0:default_entity_excerpt_len]; } } diff --git a/scripts/test-all-policy.bro b/scripts/test-all-policy.bro index 1fd34d6f2f..2164343d37 100644 --- a/scripts/test-all-policy.bro +++ b/scripts/test-all-policy.bro @@ -14,6 +14,8 @@ # @load frameworks/control/controller.bro @load frameworks/dpd/detect-protocols.bro @load frameworks/dpd/packet-segment-logging.bro +@load frameworks/files/detect-MHR.bro +@load frameworks/files/hash-all-files.bro @load frameworks/intel/__load__.bro @load frameworks/intel/conn-established.bro @load frameworks/intel/dns.bro @@ -50,7 +52,6 @@ @load protocols/ftp/detect-bruteforcing.bro @load protocols/ftp/detect.bro @load protocols/ftp/software.bro -@load protocols/http/detect-MHR.bro @load protocols/http/detect-sqli.bro @load protocols/http/detect-webapps.bro @load protocols/http/header-names.bro @@ -62,6 +63,7 @@ @load protocols/modbus/track-memmap.bro @load protocols/smtp/blocklists.bro @load protocols/smtp/detect-suspicious-orig.bro +@load protocols/smtp/entities-excerpt.bro @load protocols/smtp/software.bro @load protocols/ssh/detect-bruteforcing.bro @load protocols/ssh/geo-data.bro diff --git a/src/util.cc b/src/util.cc index 5a63be22cb..0651925898 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1573,6 +1573,20 @@ void operator delete[](void* v) #endif +// Being selective of which components of MAGIC_NO_CHECK_BUILTIN are actually +// known to be problematic, but keeping rest of libmagic's builtin checks. +#define DISABLE_LIBMAGIC_BUILTIN_CHECKS ( \ +/* MAGIC_NO_CHECK_COMPRESS | */ \ +/* MAGIC_NO_CHECK_TAR | */ \ +/* MAGIC_NO_CHECK_SOFT | */ \ +/* MAGIC_NO_CHECK_APPTYPE | */ \ +/* MAGIC_NO_CHECK_ELF | */ \ +/* MAGIC_NO_CHECK_TEXT | */ \ + MAGIC_NO_CHECK_CDF | \ + MAGIC_NO_CHECK_TOKENS \ +/* MAGIC_NO_CHECK_ENCODING */ \ +) + void bro_init_magic(magic_t* cookie_ptr, int flags) { if ( ! cookie_ptr || *cookie_ptr ) diff --git a/src/util.h b/src/util.h index 91ed8f2888..cafa63b7e8 100644 --- a/src/util.h +++ b/src/util.h @@ -377,23 +377,6 @@ struct CompareString } }; -// Older versions of libmagic may not define the MAGIC_NO_CHECK_BUILTIN -// convenience macro and other newer versions seem to have a typo that makes -// it unusable, so just make a different one now with all known flags for -// builtin libmagic components that should be disabled so that Bro only -// uses the custom magic database shipped with it. -#define DISABLE_LIBMAGIC_BUILTIN_CHECKS ( \ - MAGIC_NO_CHECK_COMPRESS | \ - MAGIC_NO_CHECK_TAR | \ -/* MAGIC_NO_CHECK_SOFT | */ \ - MAGIC_NO_CHECK_APPTYPE | \ - MAGIC_NO_CHECK_ELF | \ - MAGIC_NO_CHECK_TEXT | \ - MAGIC_NO_CHECK_CDF | \ - MAGIC_NO_CHECK_TOKENS | \ - MAGIC_NO_CHECK_ENCODING \ -) - extern magic_t magic_desc_cookie; extern magic_t magic_mime_cookie; diff --git a/testing/btest/Baseline/core.tunnels.ayiya/http.log b/testing/btest/Baseline/core.tunnels.ayiya/http.log index 04692a3547..cc0cf32148 100644 --- a/testing/btest/Baseline/core.tunnels.ayiya/http.log +++ b/testing/btest/Baseline/core.tunnels.ayiya/http.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-23-05-12-58 +#open 2013-07-25-21-12-29 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1257655301.652206 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 10102 200 OK - - - (empty) - - - - - meGKu6goEyd application/octet-stream +1257655301.652206 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 10102 200 OK - - - (empty) - - - - - meGKu6goEyd text/html 1257655302.514424 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 2 GET ipv6.google.com /csi?v=3&s=webhp&action=&tran=undefined&e=17259,19771,21517,21766,21887,22212&ei=BUz2Su7PMJTglQfz3NzCAw&rt=prt.77,xjs.565,ol.645 http://ipv6.google.com/ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 0 204 No Content - - - (empty) - - - - - - - 1257655303.603569 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 3 GET ipv6.google.com /gen_204?atyp=i&ct=fade&cad=1254&ei=BUz2Su7PMJTglQfz3NzCAw&zx=1257655303600 http://ipv6.google.com/ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 0 204 No Content - - - (empty) - - - - - - - -#close 2013-07-23-05-12-58 +#close 2013-07-25-21-12-29 diff --git a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log index e88be88763..8f9ac07c96 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log +++ b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-21 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1333458850.340368 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 1 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=4&cac=1&t=728x90&cb=1333458879 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&channel=4&cb=1333458905296 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - application/x-shockwave-flash - - - -1333458850.399501 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 2 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=0&cac=1&t=728x90&cb=1333458881 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&cb=1333458920207 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - application/x-shockwave-flash - - - -#close 2013-05-21-21-11-21 +#open 2013-07-25-16-23-41 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1333458850.340368 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 1 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=4&cac=1&t=728x90&cb=1333458879 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&channel=4&cb=1333458905296 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - - - 6jqjOyeITn5 application/x-shockwave-flash +1333458850.399501 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 2 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=0&cac=1&t=728x90&cb=1333458881 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&cb=1333458920207 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - - - A0xot7xPc22 application/x-shockwave-flash +#close 2013-07-25-16-23-41 diff --git a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log index 8f2893caa7..45b88b7813 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log +++ b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-22 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1333458850.375568 arKYeMETxOg 10.131.47.185 1923 79.101.110.141 80 1 GET o-o.preferred.telekomrs-beg1.v2.lscache8.c.youtube.com /videoplayback?upn=MTU2MDY5NzQ5OTM0NTI3NDY4NDc&sparams=algorithm,burst,cp,factor,id,ip,ipbits,itag,source,upn,expire&fexp=912300,907210&algorithm=throttle-factor&itag=34&ip=212.0.0.0&burst=40&sver=3&signature=832FB1042E20780CFCA77A4DB5EA64AC593E8627.D1166C7E8365732E52DAFD68076DAE0146E0AE01&source=youtube&expire=1333484980&key=yt1&ipbits=8&factor=1.25&cp=U0hSSFRTUl9NSkNOMl9MTVZKOjh5eEN2SG8tZF84&id=ebf1e932d4bd1286&cm2=1 http://s.ytimg.com/yt/swfbin/watch_as3-vflqrJwOA.swf Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko; X-SBLSP) Chrome/17.0.963.83 Safari/535.11 0 56320 206 Partial Content - - - (empty) - - - application/octet-stream - - - -#close 2013-05-21-21-11-22 +#open 2013-07-25-21-12-32 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1333458850.375568 arKYeMETxOg 10.131.47.185 1923 79.101.110.141 80 1 GET o-o.preferred.telekomrs-beg1.v2.lscache8.c.youtube.com /videoplayback?upn=MTU2MDY5NzQ5OTM0NTI3NDY4NDc&sparams=algorithm,burst,cp,factor,id,ip,ipbits,itag,source,upn,expire&fexp=912300,907210&algorithm=throttle-factor&itag=34&ip=212.0.0.0&burst=40&sver=3&signature=832FB1042E20780CFCA77A4DB5EA64AC593E8627.D1166C7E8365732E52DAFD68076DAE0146E0AE01&source=youtube&expire=1333484980&key=yt1&ipbits=8&factor=1.25&cp=U0hSSFRTUl9NSkNOMl9MTVZKOjh5eEN2SG8tZF84&id=ebf1e932d4bd1286&cm2=1 http://s.ytimg.com/yt/swfbin/watch_as3-vflqrJwOA.swf Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko; X-SBLSP) Chrome/17.0.963.83 Safari/535.11 0 56320 206 Partial Content - - - (empty) - - - - - oypNlaRdgs7 application/octet-stream +#close 2013-07-25-21-12-32 diff --git a/testing/btest/Baseline/core.tunnels.teredo/http.log b/testing/btest/Baseline/core.tunnels.teredo/http.log index 4e3cdfd61d..1ecf0884e2 100644 --- a/testing/btest/Baseline/core.tunnels.teredo/http.log +++ b/testing/btest/Baseline/core.tunnels.teredo/http.log @@ -3,11 +3,11 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-21 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1210953057.917183 3PKsZ2Uye21 192.168.2.16 1578 75.126.203.78 80 1 POST download913.avast.com /cgi-bin/iavs4stats.cgi - Syncer/4.80 (av_pro-1169;f) 589 0 204 - - - (empty) - - - text/plain - - - -1210953061.585996 70MGiRM1Qf4 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 6640 200 OK - - - (empty) - - - text/html - - - -1210953073.381474 70MGiRM1Qf4 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 2 GET ipv6.google.com /search?hl=en&q=Wireshark+!&btnG=Google+Search http://ipv6.google.com/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 25119 200 OK - - - (empty) - - - text/html - - - -1210953074.674817 c4Zw9TmAE05 192.168.2.16 1580 67.228.110.120 80 1 GET www.wireshark.org / http://ipv6.google.com/search?hl=en&q=Wireshark+%21&btnG=Google+Search Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 11845 200 OK - - - (empty) - - - application/xml - - - -#close 2013-05-21-21-11-21 +#open 2013-07-25-16-23-17 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1210953057.917183 3PKsZ2Uye21 192.168.2.16 1578 75.126.203.78 80 1 POST download913.avast.com /cgi-bin/iavs4stats.cgi - Syncer/4.80 (av_pro-1169;f) 589 0 204 - - - (empty) - - - tZX578lAmo3 text/plain - - +1210953061.585996 70MGiRM1Qf4 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 6640 200 OK - - - (empty) - - - - - nkfWSsPnjX7 text/html +1210953073.381474 70MGiRM1Qf4 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 2 GET ipv6.google.com /search?hl=en&q=Wireshark+!&btnG=Google+Search http://ipv6.google.com/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 25119 200 OK - - - (empty) - - - - - fk5lVax7K37 text/html +1210953074.674817 c4Zw9TmAE05 192.168.2.16 1580 67.228.110.120 80 1 GET www.wireshark.org / http://ipv6.google.com/search?hl=en&q=Wireshark+%21&btnG=Google+Search Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 11845 200 OK - - - (empty) - - - - - 6wF1NFmBUza application/xml +#close 2013-07-25-16-23-17 diff --git a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/http.log b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/http.log index 65ec33186e..0c8c448e30 100644 --- a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/http.log +++ b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/http.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-22 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1340127577.361683 FrJExwHcSal 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 6640 200 OK - - - (empty) - - - text/html - - - -1340127577.379360 FrJExwHcSal 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 2 GET ipv6.google.com /search?hl=en&q=Wireshark+!&btnG=Google+Search http://ipv6.google.com/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 25119 200 OK - - - (empty) - - - text/html - - - -#close 2013-05-21-21-11-22 +#open 2013-07-25-16-22-21 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1340127577.361683 FrJExwHcSal 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 6640 200 OK - - - (empty) - - - - - RzAMHHXJral text/html +1340127577.379360 FrJExwHcSal 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 2 GET ipv6.google.com /search?hl=en&q=Wireshark+!&btnG=Google+Search http://ipv6.google.com/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 25119 200 OK - - - (empty) - - - - - vOmb3ToMKRg text/html +#close 2013-07-25-16-22-21 diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index b7585a1477..4bcda86272 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-07-05-05-20-50 +#open 2013-07-25-19-59-47 #fields name #types string scripts/base/init-bare.bro @@ -84,9 +84,11 @@ scripts/base/init-bare.bro scripts/base/frameworks/analyzer/main.bro scripts/base/frameworks/packet-filter/utils.bro build/scripts/base/bif/analyzer.bif.bro - scripts/base/frameworks/file-analysis/__load__.bro - scripts/base/frameworks/file-analysis/main.bro + scripts/base/frameworks/files/__load__.bro + scripts/base/frameworks/files/main.bro build/scripts/base/bif/file_analysis.bif.bro + scripts/base/utils/site.bro + scripts/base/utils/patterns.bro scripts/policy/misc/loaded-scripts.bro scripts/base/utils/paths.bro -#close 2013-07-05-05-20-50 +#close 2013-07-25-19-59-47 diff --git a/testing/btest/Baseline/istate.events-ssl/receiver.http.log b/testing/btest/Baseline/istate.events-ssl/receiver.http.log index be7e6e5692..dd61de5424 100644 --- a/testing/btest/Baseline/istate.events-ssl/receiver.http.log +++ b/testing/btest/Baseline/istate.events-ssl/receiver.http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-32 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1369170691.550143 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - -#close 2013-05-21-21-11-33 +#open 2013-07-25-21-10-36 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1374786635.573905 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - +#close 2013-07-25-21-10-37 diff --git a/testing/btest/Baseline/istate.events-ssl/sender.http.log b/testing/btest/Baseline/istate.events-ssl/sender.http.log index be7e6e5692..dd61de5424 100644 --- a/testing/btest/Baseline/istate.events-ssl/sender.http.log +++ b/testing/btest/Baseline/istate.events-ssl/sender.http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-32 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1369170691.550143 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - -#close 2013-05-21-21-11-33 +#open 2013-07-25-21-10-36 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1374786635.573905 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - +#close 2013-07-25-21-10-37 diff --git a/testing/btest/Baseline/istate.events/receiver.http.log b/testing/btest/Baseline/istate.events/receiver.http.log index ae693399c3..aebe4dea7b 100644 --- a/testing/btest/Baseline/istate.events/receiver.http.log +++ b/testing/btest/Baseline/istate.events/receiver.http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-40 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1369170699.511968 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - -#close 2013-05-21-21-11-41 +#open 2013-07-25-20-26-59 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1374784018.898860 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - +#close 2013-07-25-20-27-00 diff --git a/testing/btest/Baseline/istate.events/sender.http.log b/testing/btest/Baseline/istate.events/sender.http.log index ae693399c3..b70ba733bd 100644 --- a/testing/btest/Baseline/istate.events/sender.http.log +++ b/testing/btest/Baseline/istate.events/sender.http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-40 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1369170699.511968 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - -#close 2013-05-21-21-11-41 +#open 2013-07-25-21-05-37 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1374786336.338273 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - +#close 2013-07-25-21-05-38 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.actions.data_event/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.actions.data_event/out index ddc3449a4c..cbd60840bf 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.actions.data_event/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.actions.data_event/out @@ -4,6 +4,7 @@ FILE_BOF_BUFFER ^J0.26 | 201 MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION file_stream, file #0, 1500, ^J0.26 | 2012-08-24 15:10:04 -0700^J^J * Fixing update-changes, which could pick the wrong control file. (Robin Sommer)^J^J * Fixing GPG signing script. (Robin Sommer)^J^J0.25 | 2012-08-01 13:55:46 -0500^J^J * Fix configure script to exit with non-zero status on error (Jon Siwek)^J^J0.24 | 2012-07-05 12:50:43 -0700^J^J * Raise minimum required CMake version to 2.6.3 (Jon Siwek)^J^J * Adding script to delete old fully-merged branches. (Robin Sommer)^J^J0.23-2 | 2012-01-25 13:24:01 -0800^J^J * Fix a bro-cut error message. (Daniel Thayer)^J^J0.23 | 2012-01-11 12:16:11 -0800^J^J * Tweaks to release scripts, plus a new one for signing files.^J (Robin Sommer)^J^J0.22 | 2012-01-10 16:45:19 -0800^J^J * Tweaks for OpenBSD support. (Jon Siwek)^J^J * bro-cut extensions and fixes. (Robin Sommer)^J ^J - If no field names are given on the command line, we now pass through^J all fields. Adresses #657.^J^J - Removing some GNUism from awk script. Addresses #653.^J^J - Added option for time output in UTC. Addresses #668.^J^J - Added output field separator option -F. Addresses #649.^J^J - Fixing option -c: only some header lines were passed through^J rather than all. (Robin Sommer)^J^J * Fix parallel make portability. (Jon Siwek)^J^J0.21-9 | 2011-11-07 05:44:14 -0800^J^J * Fixing compiler warnings. Addresses #388. (Jon Siwek)^J^J0.21-2 | 2011-11-02 18:12:13 -0700^J^J * Fix for misnaming temp file in update-changes script. (Robin Sommer)^J^J0.21-1 | 2011-11-02 18:10:39 -0700^J^J * Little fix for make-relea file_chunk, file #0, 1500, 0, ^J0.26 | 2012-08-24 15:10:04 -0700^J^J * Fixing update-changes, which could pick the wrong control file. (Robin Sommer)^J^J * Fixing GPG signing script. (Robin Sommer)^J^J0.25 | 2012-08-01 13:55:46 -0500^J^J * Fix configure script to exit with non-zero status on error (Jon Siwek)^J^J0.24 | 2012-07-05 12:50:43 -0700^J^J * Raise minimum required CMake version to 2.6.3 (Jon Siwek)^J^J * Adding script to delete old fully-merged branches. (Robin Sommer)^J^J0.23-2 | 2012-01-25 13:24:01 -0800^J^J * Fix a bro-cut error message. (Daniel Thayer)^J^J0.23 | 2012-01-11 12:16:11 -0800^J^J * Tweaks to release scripts, plus a new one for signing files.^J (Robin Sommer)^J^J0.22 | 2012-01-10 16:45:19 -0800^J^J * Tweaks for OpenBSD support. (Jon Siwek)^J^J * bro-cut extensions and fixes. (Robin Sommer)^J ^J - If no field names are given on the command line, we now pass through^J all fields. Adresses #657.^J^J - Removing some GNUism from awk script. Addresses #653.^J^J - Added option for time output in UTC. Addresses #668.^J^J - Added output field separator option -F. Addresses #649.^J^J - Fixing option -c: only some header lines were passed through^J rather than all. (Robin Sommer)^J^J * Fix parallel make portability. (Jon Siwek)^J^J0.21-9 | 2011-11-07 05:44:14 -0800^J^J * Fixing compiler warnings. Addresses #388. (Jon Siwek)^J^J0.21-2 | 2011-11-02 18:12:13 -0700^J^J * Fix for misnaming temp file in update-changes script. (Robin Sommer)^J^J0.21-1 | 2011-11-02 18:10:39 -0700^J^J * Little fix for make-relea file_stream, file #0, 1024, se script, which could pick out the wrong^J tag. (Robin Sommer)^J^J0.21 | 2011-10-27 17:40:45 -0700^J^J * Fixing bro-cut's usage message and argument error handling. (Robin Sommer)^J^J * Bugfix in update-changes script. (Robin Sommer)^J^J * update-changes now ignores commits it did itself. (Robin Sommer)^J^J * Fix a bug in the update-changes script. (Robin Sommer)^J^J * bro-cut now always installs to $prefix/bin by `make install`. (Jon Siwek)^J^J * Options to adjust time format for bro-cut. (Robin Sommer)^J^J The default with -d is now ISO format. The new option "-D "^J specifies a custom strftime()-style format string. Alternatively,^J the environment variable BRO_CUT_TIMEFMT can set the format as^J well.^J^J * bro-cut now understands the field separator header. (Robin Sommer)^J^J * Renaming options -h/-H -> -c/-C, and doing some general cleanup.^J^J0.2 | 2011-10-25 19:53:57 -0700^J^J * Adding support for replacing version string in a setup.py. (Robin^J Sommer)^J^J * Change generated root cert DN indices f diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.remove_action/get.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.remove_action/get.out index 4b572d5df9..eb62690f91 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.remove_action/get.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.remove_action/get.out @@ -4,6 +4,7 @@ FILE_BOF_BUFFER ^J0.26 | 201 MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 4705, 0 [orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.set_timeout_interval/bro..stdout b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.set_timeout_interval/bro..stdout index 160a51a543..e78f5c8c17 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.set_timeout_interval/bro..stdout +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.set_timeout_interval/bro..stdout @@ -2,6 +2,7 @@ FILE_NEW file #0, 0, 0 MIME_TYPE application/x-dosexec +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 1022920, 0 [orig_h=192.168.72.14, orig_p=3254/tcp, resp_h=65.54.95.206, resp_p=80/tcp] @@ -11,6 +12,7 @@ FILE_NEW file #1, 0, 0 MIME_TYPE application/octet-stream +FILE_OVER_NEW_CONNECTION FILE_TIMEOUT FILE_TIMEOUT FILE_STATE_REMOVE diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.stop/get.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.stop/get.out index f7182027aa..13cfe5de58 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.stop/get.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.stop/get.out @@ -4,3 +4,4 @@ FILE_BOF_BUFFER ^J0.26 | 201 MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out index c810ce15e5..eba43b94a4 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out @@ -3,7 +3,7 @@ file #0, 0, 0 FILE_BOF_BUFFER The Nationa MIME_TYPE -application/octet-stream +text/x-pascal FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 16557, 0 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get-gzip.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get-gzip.out index 2b46d02042..d42db4b90a 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get-gzip.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get-gzip.out @@ -4,6 +4,7 @@ FILE_BOF_BUFFER {^J "origin MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 197, 0 [orig_h=141.142.228.5, orig_p=50153/tcp, resp_h=54.243.118.187, resp_p=80/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get.out index bb2f622969..219aad4eff 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get.out @@ -4,6 +4,7 @@ FILE_BOF_BUFFER ^J0.26 | 201 MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 4705, 0 [orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.multipart/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.multipart/out index 4b6fa76c0c..da42f4fd68 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.multipart/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.multipart/out @@ -4,6 +4,7 @@ FILE_BOF_BUFFER test^M^J MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 6, 0 [orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp] @@ -17,6 +18,7 @@ FILE_BOF_BUFFER test2^M^J MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #1, 7, 0 [orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp] @@ -30,6 +32,7 @@ FILE_BOF_BUFFER test3^M^J MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #2, 7, 0 [orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp] @@ -43,6 +46,7 @@ FILE_BOF_BUFFER {^J "data": MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #3, 465, 0 [orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.out index f8f2538e92..077fb5282c 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.out @@ -3,6 +3,7 @@ file #0, 0, 0 MIME_TYPE application/pdf FILE_OVER_NEW_CONNECTION +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 555523, 0 [orig_h=10.101.84.70, orig_p=10978/tcp, resp_h=129.174.93.161, resp_p=80/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.out index b2a0cb66a2..9c05f311f3 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.out @@ -2,6 +2,7 @@ FILE_NEW file #0, 0, 0 MIME_TYPE application/x-dosexec +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 1022920, 0 [orig_h=192.168.72.14, orig_p=3254/tcp, resp_h=65.54.95.206, resp_p=80/tcp] @@ -11,6 +12,7 @@ FILE_NEW file #1, 0, 0 MIME_TYPE application/octet-stream +FILE_OVER_NEW_CONNECTION FILE_TIMEOUT FILE_STATE_REMOVE file #1, 206024, 0 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.out index 7c5e9dfeca..d85a9de314 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.out @@ -3,6 +3,7 @@ file #0, 0, 0 MIME_TYPE application/octet-stream FILE_OVER_NEW_CONNECTION +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 498702, 0 [orig_h=10.45.179.94, orig_p=19950/tcp, resp_h=129.174.93.170, resp_p=80/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/out index 02ac2f0a7e..b85485cd1a 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/out @@ -4,6 +4,7 @@ FILE_BOF_BUFFER /*^J******** MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 2675, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] @@ -17,6 +18,7 @@ FILE_BOF_BUFFER //-- Google MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #1, 21421, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] @@ -30,6 +32,7 @@ FILE_BOF_BUFFER GIF89a^D\0^D\0\xb3 MIME_TYPE image/gif +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #2, 94, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] @@ -44,6 +47,7 @@ FILE_BOF_BUFFER \x89PNG^M^J^Z^J\0\0\0 MIME_TYPE image/png +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #3, 2349, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] @@ -58,6 +62,7 @@ FILE_BOF_BUFFER \x89PNG^M^J^Z^J\0\0\0 MIME_TYPE image/png +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #4, 27579, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/out index 3103ecb39e..cedc396254 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/out @@ -4,6 +4,7 @@ FILE_BOF_BUFFER hello world MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 11, 0 [orig_h=141.142.228.5, orig_p=53595/tcp, resp_h=54.243.55.129, resp_p=80/tcp] @@ -18,6 +19,7 @@ FILE_BOF_BUFFER {^J "origin MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #1, 366, 0 [orig_h=141.142.228.5, orig_p=53595/tcp, resp_h=54.243.55.129, resp_p=80/tcp] diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/file_analysis.log b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/file_analysis.log deleted file mode 100644 index f95a70d50a..0000000000 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/file_analysis.log +++ /dev/null @@ -1,10 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path file_analysis -#open 2013-06-07-18-51-45 -#fields id parent_id source is_orig last_active seen_bytes total_bytes missing_bytes overflow_bytes timeout_interval bof_buffer_size mime_type timedout conn_uids extracted_files md5 sha1 sha256 -#types string string string bool time count count count count interval count string bool table[string] table[string] string string string -BYYd1GSNX5c - HTTP F 1362692527.009775 4705 4705 0 0 120.000000 1024 text/plain F UWkUyAuUGXf BYYd1GSNX5c-file 397168fd09991a0e712254df7bc639ac 1dd7ac0398df6cbc0696445a91ec681facf4dc47 4e7c7ef0984119447e743e3ec77e1de52713e345cde03fe7df753a35849bed18 -#close 2013-06-07-18-51-46 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/files.log b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/files.log new file mode 100644 index 0000000000..2663184b88 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/files.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path files +#open 2013-07-25-16-57-31 +#fields ts fuid tx_hosts rx_hosts conn_uids source depth analyzers mime_type filename duration local_orig is_orig seen_bytes total_bytes missing_bytes overflow_bytes timedout parent_fuid md5 sha1 sha256 extracted +#types time string table[addr] table[addr] table[string] string count table[string] string string interval bool bool count count count count bool string string string string string +1362692527.009721 G75mcAsU764 192.150.187.43 141.142.228.5 UWkUyAuUGXf HTTP 0 SHA256,DATA_EVENT,MD5,EXTRACT,SHA1 text/plain - 0.000054 - F 4705 4705 0 0 F - 397168fd09991a0e712254df7bc639ac 1dd7ac0398df6cbc0696445a91ec681facf4dc47 4e7c7ef0984119447e743e3ec77e1de52713e345cde03fe7df753a35849bed18 G75mcAsU764-file +#close 2013-07-25-16-57-31 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.smtp/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.smtp/out index ac4e6e50fa..57f1f97b9c 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.smtp/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.smtp/out @@ -4,6 +4,7 @@ FILE_BOF_BUFFER Hello^M^J^M^J ^M MIME_TYPE text/plain +FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE file #0, 79, 0 [orig_h=10.10.1.4, orig_p=1470/tcp, resp_h=74.53.140.153, resp_p=25/tcp] @@ -17,6 +18,7 @@ FILE_BOF_BUFFER pub/NetBSD/README.export-control -lrwxrwxr-x 1 root wheel 32 Aug 16 2009 .message -> pub/NetBSD/README.export-control -total 98028 -total 98028 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-extract/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-extract/ftp.log deleted file mode 100644 index e77f59dc44..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-extract/ftp.log +++ /dev/null @@ -1,21 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path ftp -#open 2013-06-07-18-57-22 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg tags data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p extraction_file -#types time string addr port addr port string string string string string count count string table[string] bool addr addr port string -1329843175.680248 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,90) (empty) T 141.142.220.235 199.233.217.249 56666 - -1329843175.791528 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test LIST - - - 226 Transfer complete. (empty) - - - - - -1329843179.815947 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,91) (empty) T 141.142.220.235 199.233.217.249 56667 - -1329843193.984222 arKYeMETxOg 141.142.220.235 37604 199.233.217.249 56666 - - - - - - - (empty) - - - - ftp-item-pVhQhhFsB2b.dat -1329843193.984222 k6kgXLOoSKl 141.142.220.235 59378 199.233.217.249 56667 - - - - - - - (empty) - - - - ftp-item-fFCPkV1sEsc.dat -1329843179.926563 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. (empty) - - - - - -1329843194.040188 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,131,46 - - 200 PORT command successful. (empty) F 199.233.217.249 141.142.220.235 33582 - -1329843194.095782 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test LIST - - - 226 Transfer complete. (empty) - - - - - -1329843197.672179 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,147,203 - - 200 PORT command successful. (empty) F 199.233.217.249 141.142.220.235 37835 - -1329843199.968212 nQcgTWjvg4c 199.233.217.249 61920 141.142.220.235 33582 - - - - - - - (empty) - - - - ftp-item-g3zS3MuJFh.dat -1329843197.727769 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. (empty) - - - - - -1329843200.079930 j4u32Pc5bif 199.233.217.249 61918 141.142.220.235 37835 - - - - - - - (empty) - - - - ftp-item-lMf4UWRkEO5.dat -#close 2013-06-07-18-57-22 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log b/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log index edbee28991..a81c0d4a2d 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-24 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1237440095.634312 UWkUyAuUGXf 192.168.3.103 54102 128.146.216.51 80 1 POST www.osu.edu / - curl/7.17.1 (i386-apple-darwin8.11.1) libcurl/7.17.1 zlib/1.2.3 2001 60731 200 OK 100 Continue - (empty) - - - text/html - - - -#close 2013-05-21-21-11-24 +#open 2013-07-25-19-39-08 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1237440095.634312 UWkUyAuUGXf 192.168.3.103 54102 128.146.216.51 80 1 POST www.osu.edu / - curl/7.17.1 (i386-apple-darwin8.11.1) libcurl/7.17.1 zlib/1.2.3 2001 60731 200 OK 100 Continue - (empty) - - - 8TXBHVmBGD7 text/plain ATGo7hdUXdi text/html +#close 2013-07-25-19-39-08 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item.dat b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item.dat deleted file mode 100644 index 73c369dd14..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item.dat +++ /dev/null @@ -1,304 +0,0 @@ - -ICIR - -ICIR
-

-ICIR (The ICSI Center for Internet Research) -is a -non-profit -research institute at -ICSI -in -Berkeley, -California.
-For the three years from 1999 to 2001 we were named -ACIRI, the AT&T Center for Internet Research at ICSI, -and were funded by AT&T.
- -The goals of ICIR are to: -

    -
  • Pursue research on the Internet architecture and related networking issues, -
  • -Participate actively in the research (SIGCOMM and IRTF) and -standards (IETF) communities, -
  • Bridge the gap between the Internet research community and commercial -interests by providing a neutral forum where topics of mutual technical -interest can be addressed. -
-

- -


- -
- - - - - - - - - - -
- -

-People -

- - -
- -

-Publications -

- - -

-Projects -

- - - -
- -

Research

-   Transport and Congestion - - -   Traffic and Topology -
    -
  • -IDMaps -(Internet Distance Mapping). -
  • The -Internet Traffic Archive. -
  • -MINC -(Multicast-based Inference of Network-internal Characteristics). -
  • -NIMI -(National Internet Measurement Infrastructure). -
- -

- -Collaborators -

- - - -
-
- -
-

Information for visitors and local users.

-
-Last modified: June 2004. Copyright notice. - -Older versions of this web page, in its ACIRI incarnation.. -
-For more information about this server, mail www@aciri.org. -
-To report unusual activity by any of our hosts, mail abuse@aciri.org. - diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log deleted file mode 100644 index 53b80e5e9e..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log +++ /dev/null @@ -1,10 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path http -#open 2013-06-07-19-04-27 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1128727435.634189 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - text/html - - http-item-54zlJFqn0x6.dat -#close 2013-06-07-19-04-27 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log index 54a75f4697..674e355631 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log @@ -3,56 +3,56 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-25 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1354328870.191989 UWkUyAuUGXf 128.2.6.136 46562 173.194.75.103 80 1 OPTIONS www.google.com * - - 0 962 405 Method Not Allowed - - - (empty) - - - text/html - - - -1354328874.237327 arKYeMETxOg 128.2.6.136 46563 173.194.75.103 80 1 OPTIONS www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328874.299063 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328874.342591 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328874.364020 j4u32Pc5bif 128.2.6.136 46566 173.194.75.103 80 1 GET www.google.com / - - 0 43911 200 OK - - - (empty) - - - text/html - - - -1354328878.470424 TEfuqmmG4bh 128.2.6.136 46567 173.194.75.103 80 1 GET www.google.com / - - 0 43983 200 OK - - - (empty) - - - text/html - - - -1354328882.575456 FrJExwHcSal 128.2.6.136 46568 173.194.75.103 80 1 GET www.google.com /HTTP/1.1 - - 0 1207 403 Forbidden - - - (empty) - - - text/html - - - -1354328882.928027 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328882.968948 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328882.990373 VW0XPVINV8a 128.2.6.136 46571 173.194.75.103 80 1 GET www.google.com / - - 0 43913 200 OK - - - (empty) - - - text/html - - - -1354328887.114613 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 0 - - - - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - - -1354328891.161077 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328891.204740 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328891.287655 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - - -1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 1 CCM_POST www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328895.416133 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - text/html - - - -1354328899.526682 EAr0uf4mhq 128.2.6.136 46582 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328903.572533 GvmoxJFXdTa 128.2.6.136 46583 173.194.75.103 80 1 CONNECT www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328903.634196 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328903.676395 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328903.697693 UfGkYA2HI2g 128.2.6.136 46586 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328907.743696 i2rO3KD1Syg 128.2.6.136 46587 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - text/html - - - -1354328911.790590 2cx26uAvUPl 128.2.6.136 46588 173.194.75.103 80 1 TRACE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328911.853464 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328911.897044 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328911.918511 zno26fFZkrh 128.2.6.136 46591 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - text/html - - - -1354328915.964678 v5rgkJBig5l 128.2.6.136 46592 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - - -1354328920.010458 eWZCH7OONC1 128.2.6.136 46593 173.194.75.103 80 1 DELETE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328920.072101 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328920.114526 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328920.136714 yC2d6kVg709 128.2.6.136 46596 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - text/html - - - -1354328924.183211 VcgagLjnO92 128.2.6.136 46597 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - - -1354328924.224567 bdRoHfaPBo3 128.2.6.136 46598 173.194.75.103 80 1 PUT www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - text/html - - - -1354328924.287402 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328924.328257 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328924.350343 xNYSS2hJkle 128.2.6.136 46601 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - - -1354328924.391728 vMVjlplKKbd 128.2.6.136 46602 173.194.75.103 80 1 POST www.google.com / - - 0 934 411 Length Required - - - (empty) - - - text/html - - - -1354328924.433150 3omNawSNrxj 128.2.6.136 46603 173.194.75.103 80 1 POST www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - text/html - - - -1354328924.496732 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328924.537671 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - +#open 2013-07-25-19-41-27 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1354328870.191989 UWkUyAuUGXf 128.2.6.136 46562 173.194.75.103 80 1 OPTIONS www.google.com * - - 0 962 405 Method Not Allowed - - - (empty) - - - - - VTrFjxi3V27 text/html +1354328874.237327 arKYeMETxOg 128.2.6.136 46563 173.194.75.103 80 1 OPTIONS www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - jeoiUX9q8v9 text/html +1354328874.299063 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - 6dL7NPgFhil text/html +1354328874.342591 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - cix6gzDRCob text/html +1354328874.364020 j4u32Pc5bif 128.2.6.136 46566 173.194.75.103 80 1 GET www.google.com / - - 0 43911 200 OK - - - (empty) - - - - - tCZHDKUkBdi text/html +1354328878.470424 TEfuqmmG4bh 128.2.6.136 46567 173.194.75.103 80 1 GET www.google.com / - - 0 43983 200 OK - - - (empty) - - - - - iVzFNTeQnnc text/html +1354328882.575456 FrJExwHcSal 128.2.6.136 46568 173.194.75.103 80 1 GET www.google.com /HTTP/1.1 - - 0 1207 403 Forbidden - - - (empty) - - - - - boBAqw2JcFi text/html +1354328882.928027 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - r3w183FJvW3 text/html +1354328882.968948 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - bncugeoItlf text/html +1354328882.990373 VW0XPVINV8a 128.2.6.136 46571 173.194.75.103 80 1 GET www.google.com / - - 0 43913 200 OK - - - (empty) - - - - - NkYD5vo8Gy text/html +1354328887.114613 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 0 - - - - - 0 961 405 Method Not Allowed - - - (empty) - - - - - S85THffBTLh text/html +1354328891.161077 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - 2m6kUZZS0wd text/html +1354328891.204740 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - UoqtpOgJZSk text/html +1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - mqs8p4wwsS7 text/html +1354328891.287655 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - S36eCQJUY5k text/html +1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - - - LeNRDWYrpS7 text/html +1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 1 CCM_POST www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - ZwKUASlWzYk text/html +1354328895.416133 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - uj62KNQhsG3 text/html +1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - taBxWzrYquk text/html +1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - - - bHBxZULKI0k text/html +1354328899.526682 EAr0uf4mhq 128.2.6.136 46582 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - - - t6k8zHaGZk5 text/html +1354328903.572533 GvmoxJFXdTa 128.2.6.136 46583 173.194.75.103 80 1 CONNECT www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - c11un7ZO6nc text/html +1354328903.634196 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - iWCHzW5XJWk text/html +1354328903.676395 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - dzvHktkjD9a text/html +1354328903.697693 UfGkYA2HI2g 128.2.6.136 46586 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - - - vEO9iYqh3Zc text/html +1354328907.743696 i2rO3KD1Syg 128.2.6.136 46587 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - - - 8seYaeRVuV2 text/html +1354328911.790590 2cx26uAvUPl 128.2.6.136 46588 173.194.75.103 80 1 TRACE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - 0kkHkmLHFl3 text/html +1354328911.853464 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - koHEYsvMVBa text/html +1354328911.897044 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - 50tlwxQjBCb text/html +1354328911.918511 zno26fFZkrh 128.2.6.136 46591 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - - - DdECXqOZjXh text/html +1354328915.964678 v5rgkJBig5l 128.2.6.136 46592 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - - - LIZQeBP0Coi text/html +1354328920.010458 eWZCH7OONC1 128.2.6.136 46593 173.194.75.103 80 1 DELETE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - hjPo0BdP973 text/html +1354328920.072101 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - d6K2onvteNa text/html +1354328920.114526 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - BY1g634OMv6 text/html +1354328920.136714 yC2d6kVg709 128.2.6.136 46596 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - - - 5aAa2m40fZd text/html +1354328924.183211 VcgagLjnO92 128.2.6.136 46597 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - y3Syn85ve8e text/html +1354328924.224567 bdRoHfaPBo3 128.2.6.136 46598 173.194.75.103 80 1 PUT www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - - - P92nMD5z6D4 text/html +1354328924.287402 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - qIPObDBIhSj text/html +1354328924.328257 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - su86MWxyjne text/html +1354328924.350343 xNYSS2hJkle 128.2.6.136 46601 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - r2aysGE6ve8 text/html +1354328924.391728 vMVjlplKKbd 128.2.6.136 46602 173.194.75.103 80 1 POST www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - Zosv3c0p2Zb text/html +1354328924.433150 3omNawSNrxj 128.2.6.136 46603 173.194.75.103 80 1 POST www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - - - L02QmCl2lX4 text/html +1354328924.496732 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - uh9TwTMdWI9 text/html +1354328924.537671 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - 4gLQ9WVkuYd text/html 1354328924.559704 E490YZTUozc 128.2.6.136 46606 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - - 1354328928.625437 YIeWJmXWNWj 128.2.6.136 46607 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - - 1354328932.692706 ydiZblvsYri 128.2.6.136 46608 173.194.75.103 80 1 HEAD www.google.com /HTTP/1.1 - - 0 0 400 Bad Request - - - (empty) - - - - - - - -1354328932.754657 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - text/html - - - -#close 2013-05-21-21-11-25 +1354328932.754657 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - NIV5LGdqSk2 text/html +1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - SlC7NZIgx1d text/html +#close 2013-07-25-19-41-27 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-mime-and-md5/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-mime-and-md5/http.log deleted file mode 100644 index 97e797b4fb..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-mime-and-md5/http.log +++ /dev/null @@ -1,14 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path http -#open 2013-05-21-21-11-25 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1258577884.844956 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 1 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2675 200 OK - - - (empty) - - - text/plain - - - -1258577884.960135 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 2 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 21421 200 OK - - - (empty) - - - text/plain - - - -1258577885.317160 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 3 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 94 200 OK - - - (empty) - - - image/gif - - - -1258577885.349639 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 4 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2349 200 OK - - - (empty) - - - image/png e0029eea80812e9a8e57b8d05d52938a - - -1258577885.394612 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 5 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 27579 200 OK - - - (empty) - - - image/png 30aa926344f58019d047e85ba049ca1e - - -#close 2013-05-21-21-11-25 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log index e22fb53103..6779485f91 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log @@ -3,12 +3,12 @@ #empty_field (empty) #unset_field - #path http -#open 2013-05-21-21-11-25 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string vector[string] vector[string] -1258577884.844956 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 1 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2675 200 OK - - - (empty) - - - - - - -1258577884.960135 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 2 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 21421 200 OK - - - (empty) - - - - - - -1258577885.317160 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 3 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 94 200 OK - - - (empty) - - - - - - -1258577885.349639 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 4 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2349 200 OK - - - (empty) - - - - - - -1258577885.394612 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 5 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 27579 200 OK - - - (empty) - - - - - - -#close 2013-05-21-21-11-25 +#open 2013-07-25-19-43-06 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1258577884.844956 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 1 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2675 200 OK - - - (empty) - - - - - XRu8VItOvLc text/plain +1258577884.960135 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 2 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 21421 200 OK - - - (empty) - - - - - m1D1wMxW9y8 text/plain +1258577885.317160 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 3 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 94 200 OK - - - (empty) - - - - - ZwnCaxWANNb image/gif +1258577885.349639 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 4 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2349 200 OK - - - (empty) - - - - - 3WVi9g0Caei image/png +1258577885.394612 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 5 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 27579 200 OK - - - (empty) - - - - - ta9bGBff1Wl image/png +#close 2013-07-25-19-43-06 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.multipart-extract/http.log b/testing/btest/Baseline/scripts.base.protocols.http.multipart-extract/http.log index 0bd15badef..ae71680dfa 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.multipart-extract/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.multipart-extract/http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-06-07-19-57-15 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files -#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string vector[string] vector[string] -1369159408.455878 UWkUyAuUGXf 141.142.228.5 57262 54.243.88.146 80 1 POST httpbin.org /post - curl/7.30.0 370 465 200 OK - - - (empty) - - - text/plain - http-item-lcf92jVphSl.dat,http-item-z8gOS6arddh.dat,http-item-tBYz7eElzTb.dat http-item-GVJrSB2Vxk6.dat -#close 2013-06-07-19-57-15 +#open 2013-07-25-19-50-23 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] +1369159408.455878 UWkUyAuUGXf 141.142.228.5 57262 54.243.88.146 80 1 POST httpbin.org /post - curl/7.30.0 370 465 200 OK - - - (empty) - - - UB09X6VFGTd,wFP689pOsIa,g5yDIGBH4i5 text/plain,text/plain,text/plain yv4qm3EsdOc text/plain +#close 2013-07-25-19-50-23 diff --git a/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log b/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log index 64bdb41861..8249c94938 100644 --- a/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log +++ b/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log @@ -3,11 +3,11 @@ #empty_field (empty) #unset_field - #path irc -#open 2013-03-27-18-51-40 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user command value addl dcc_file_name dcc_file_size extraction_file +#open 2013-07-25-19-51-43 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user command value addl dcc_file_name dcc_file_size fuid #types time string addr port addr port string string string string string string count string 1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 - - NICK bloed - - - - 1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - 1311189174.474127 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje JOIN #easymovies (empty) - - - 1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje DCC #easymovies (empty) ladyvampress-default(2011-07-07)-OS.zip 42208 - -#close 2013-03-27-18-51-40 +#close 2013-07-25-19-51-43 diff --git a/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item.dat b/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item.dat deleted file mode 100644 index d4ec9e374b118f65fbb1f67c14ee1a15a26e58e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42208 zcmV(&K;geoO9KQH000080IopiK0{>y#G<1B069wo04D%_0Bm7od3IrKaB^jHb1h_L zW?^+~bSN?~F)=MLH!UzXDJ@S^E_8TwQ$%P0tN;K200;o*oh`XzWMF9#VPIe|V1NK0 zAZBC*Gg(D}MCT7p)zh*&8`5UIR(ipVTaJ;5fq{u3fq?}iDT0Cw3 z@#jCTYGsv|y{cBut{(bk^&f*-ZSL?FwO!raeWd@b@rldD|Ec`yS5-P&5&5sb`iEP2 z^*@8cXXI*!zw*thblvIOPKI8sdbjEuwJIBFtujK0)gS(eWBvTk)n9-3@%x{@`|10Y zs$c%_Cs{db_Y9kAyRy*(7xLOwOpjJm!1l=pzJ^lAj7ytSCtAGFaTPfS{&8iQ-efjVHU}SYV z$hPw;gjH!|XoTAdP!_%Jr40hiyA$BPJm}Txx{bbOZB^*^CkPY@2>xLBfZB5T;D4%?&IMaX?CJ8&Q+rG z+VZ5{Go*Cgh)_1p8PN_wm(qx>2+C^b#fi?pxx0J3CiZZ5C+@C~u5G2Im0+4xSYoTV zxjjUna_#vdN`DGHz7zI?F+AxH3~BGIXeI6$*jYIvRX4AThA@pT;2Plc)DJ+ zhxQ8@!i}uoTXzIwcm^FlDV)fxn3Rrw5Lw+*0m39lk&K>f%NGTrkpl!rMFr} zq6c@9wK|`ul1ED$lohPNZF{6;op+rJP(SSJiL+^soE$_JIaZvAuAf8#BB)}M82@Usq zp>1T8ce0we&M4eHr!{E;*J`)r31n>sdl*uF?l4e&MO!%n%P4QipX4~gx+KVosL3z( z4Xo{Sp#`&kEk0b|X93G2`({!&pS#jWpaJIl1!UKolW4RtuwIRB28sWTZfwnyVlhHt zB>YPix07S#6DL^X;&8l>DNdppJ6I6!Aora9(1(GAw$R3Aj$CdsAbAb#O z%SI_UFj4`aH4@}To#0@|t3k3uZXfGMPB2UD;bX|Ac2duong?dRvj<)F+SyB;;tb6b zhs#pSug%N@dy}pcZpa%I7M&v!X-Cf*y`c9X-y^q46GTo*h`qV zO+pS5=B!dJfdc`*8qRB%IEYFeH0)4k#b5s%nU1`Ld zp1cjkAMH@?M_9<2W+K5zAWve$lAyCNyHM2#E6BFPtc2&w;0+Ta3mFQWQQ|1TL7W7I z()p`kIG{cQCpiyB(3P}6yaWDxMk<&s>}0DU(Dg9wK@+wDxRf{E#Ew!4ez_v;01O~R z2H#eplpV00hh^+Ekp0($hM< zac&vRX*1Y433}xGK;wGR4~6Jq)d87-uWU|a_#_D6c9fVRrY)9V8=`Tr9O?o;dP3MB zDlco7gIW}BbEg3ph}2%6Z;v;JtlVi~NMEo4(Gl9jy4HEGL&C$bywIg2@yjb6BYd9- zU!D^_g+lPwOOua)*o4C;XJrHFos)k?jEHIK9J2lQ^=X+*+TK!9C7STXC*H?6C!YD) zb|)PNbJFB`4goQU*u*Sg1f!HfjmEo|+SD+ez%{c6GM7%ej7?UbT~=jv28^O67)R+7Vp7#aMDBiBtg2_aM9 z4Z+o;3a+Ktv6Y{7`xYw)s0AklS_tCY8=wKyQd;L*Y*HfjIcQSSESY;YE2?Da%A9q* ze_C^DLcq#4a{0j#FIcG9hon|Ma8iw5;gRVwDMYx<0pZt5_Rhb`)bLRyw@-fcwMl*A zOlmiDog(pwXcj^eCVF^3)MG)+y9p?HHFs{>-LaMSrWsj zv?nRw6GS0ruZ}VPFe;rGx^p3f&q3dFl_l49(U+Yl!rR~qTUEN2GEWKr$Y$ol;1Bu$ z*K;l)DVfjPuobyp?v>A^(Gyq?SMQx4Qwoc{5AF6r$m)QYJSI4B0$fCq-G8FQLbT+& zUddDfHd#3<5aPVU{gE%shIVXTq z<&7Ej*y^QA@xu?x0aou2j*6YsK9@h?ndAr3G2JiL&7(Fk8Kg?1F9Y$V>#aJ97NKw2 zTru1lY^6gt^srM}Ye;vc+HS^1B|`bZQq!OA&sGyCr2}eH*HX5vAV2@ z8Z3ZP*Tq~|O0pSr1z*-^yMI}hOgS*ZLch@jNWw4^jz4m`acsaUam=I11fDp02mBXJ zAmO>ZZYGL>$0M|Q^d|W8iVR|j*y3y#uQl~?!zOKK>0DX&?fa1*FP%73lg{1KZC?Qk9giyLnW%N z{<8Tf_4WHFe)Fc#*1?Ad9*m`u0W~p~b>cL8*kCHIA9FgfDI+A9!+LCK!Oe4xA$_UuIjXBt5ilNPapVfjwdYD4j3n`|qt(=@Oexp!3=M|#%pbQBcb}`|93e`}NhgzXe zg7R6^A7NZuXgPB#j+m}RA?xUA5Rad-6xiH8QP|16A7y=U0YkcQ*6R}89J=C7h~OM0%^Ic;`oJ#`FGLb9~G4a;17Q%SyZ7! zwDIhnGM1U8Nj5L84jpd1 zC~|_G(pR{X;Ova6XPG(`GLJG3+*mwc_`$l&EpmsA4~?FiE`}_;A@j=8psf6k8nAW| z^--_AIj5)=YDdQ4E|R&tH8jf_31FZsS43D#$pjd5y5{uxm!shS=2 zID6uR+Qro{b#oAbYw0y^s8006r-5apmyBf$idz^tD%GTrS;A+OW+)1k6QTrED4my6 zp=lvJD&5c_dVYt1i7YezzoTLUZ$_7_zqK#kOKP5t`!>3b37q7~xt?}UK0U(xgEPIX z^E}}D(a+t~?r;(Ka;TWaiRIXnOk(ejbB2%;qQPqlnrr1ewl78O$^|&u10B8O@AGoa zX~k>0wF7RO*Gtw}Rt60AQn*P#D%s{QC6SPbVP{EYAD_pF?~|)zJ`(KHUj%8N z54vKDUmLbv{036j!p=TiKpaB&Xa8(o8N zZ@)a!O)fLOL&zJPL>2V>03miX>aPJtzx$QbH$bp{(*8(x;vzu;e^}sM6V9W`n#0*spYG zW!`$Ry#)gYWPU}_75`G&ZgTBu3S zUV7PcaD*i=_BSkyjPW-Q^tkl72|ITaoOSWfS+1-nO}*%le%6*SyQUWA@WnHfG>H$K zNl+%JIkcL94-x4W4j8N&%j^qzPH&PZK(AvnpSi8qLKm|QFOq*v$^BReGE=Jlran!bKRP1-Z1^RKjQ2!bz?b9M!*7o%=Zhj4( zCvs!;{M9?c9QxsI6Y5)NTg~O%_}x?D!@Aj&DR=z{T`WCXI?5nE#fdfByV$HSzCGYf z?h*sp=n;S*#vB(9HqH}ECj>d>I1^_L%rKVCJd9EWA>FGt z<$P$nOVGjPl2~Dg9kw_0iSRS95cmlEqVqnVpF1TQYLBE2DAG{4{5)t%WEL)7g0|Tb zUE(nxB?2g26h{o5yT#!wf~1i+S1%tDT0vC$R%NeCn6vN($EfWNMtQCblXxDc?Nmf7%%Em`5<9esp8vdtdC9Mg#J#`h+(`5pq>M+}V z#fVTG%+@!jsY;(0LGBr=EMVto9?M*&nfbVpFgdt+ud))Cc;6H2+kP%OW}{rAVvI*P z+RKnis*-PE{KL!p%<+Xm{?1u*XY@2|5LY+^?Jk(dqgw9xl+LY&SdKnQAIAwS&Z-jl zH>a0*S4%I@xhVV;xKhK@4N!`cp*$6?*@ry}#DP+1`HmMh^AMenrAEYZF0IY-p_P@A zW2FS*{7LG38jj^cD+3Kq)ez~KiZbhn+la)V!V#MRqs0`}Vk|&UvsXJgn7lNwH9=Y{ zLPJR_dR|Q>Bu%fYUD>;Cn6nRzX>64@^qTG5FEBj>g2fBj1Z~2}f*cjdWF>1E%52NS z`hhJEwfKeR`Vl;cTOu;5^x0%pqHVv`Wh0dl>(H@bUfEGDAY)Ux^sa?~^>YIqgDzM= zW!2|C#!ynvB?TDvO%qzCk|5&Pp@mw-BG-ghLaX}*imIuMdsFAHr8{V8P&WYXTlxV( z;FHW0uDQt=&Qn{G6){aWXX_cQpzJr?1f{!fisacn#3XM`Q>*7r&6p)Sv;`#ZDN{aS z3$qaQ*hI43}mF5tMao2-Of>K0+n;$@Gz!xNAk{Nc4cXB zgI~*7>M0}{m1+K!MaX0XV0}Z?${@S0$#+qb$KozB4*v&&>%5C^ra&LRg*LwBoV1;| zs$tK^V!t@l6lyRITyLp$OzND!NK7pD^ZjZJcgJBeG*ME^mS*M4j?w`%FXHm`#hj3` z;R;QEIp~Z7;-;RIu|iil_Z)Wx33Mm52uC;bpoPuNT~Lgub*P`F>e)(Mk)97cq3NPbuB)*!CQ5Hr1(Y7=mVQmn^L{;>C*W4<6_`o z33G~&>n+D5s`PZ>858kHl=BbV+8alTj%%a4JP-R%?ffyJa6JUBoeA*R#7h`#h{JnJ zqvT9GbfOhG43wOpG1A$BW1@)>!47~@oI9NguGtDcy$mfyFEoCYBA+DYCqu>A6O^v+ z8=8lmKQ}khO76$r-}BQKJJx^mgt((n4^uB^TXDFtDTo5JrO}Jj;~1nlybcAJpc%mi zPlyJEeb-MSxFbwpNKqG?(fDk=sDSt0@|q{Ew&4hodM={h$tN5b_FRnB7iX(BGFS$xL z*LwRt#hCwV?_G8!Ns=tFeFOauF$;EP109C&x8DZ1XmSQM$-w}`G}-7y0i?RQy1T}; zhnGFBUytwQieEuFqH6v!5jC@0&0P(qvoa%7#Ld)HMdfki$blS+<^=!g3mGBbz}ezN zE@Ea>u0(jklj6wDbgH28?l*uSd23{X3M3M4&i^amcl7!26OaHz8$vsZ9bl}YtZEx~ zFCyfL%&w1n_E=_F8=|-0_wM5pnIv2NBX zinvcE!F#U6Oj-v(UGTdDd=?5g?nZ_X#wHZO>pjGC>tgr$O&9%BIS~7c0kNm@+s9GB zu@@-^&{<-G^i8s<+-@k0QGPi$6<6cFX5&z$#V3TTJ9u9yTL?w9{g{-1Y9q^?$qiZB z)Sd@ZYGRu^k6;RPQ+0+;!Y^&;GZ1@cQ=rJDUw~rR!Q!;_qD^-ZqlUlpWRR{NPJbyG z15YZshv)PWy*HJ{43C|tOq1Rb!u^PCt1^4~V0a+ABj(Up`W>G?jowjW!G(o0lhdLh zV#o(~kYZA6X7dF%DrS2XUr15~E$4&rTWAFELB#AZO{VqMb#lJR3wL4E7a+5KaD|DZ zXHl>7ZFKBd6o&L zQJ+Be7QV;hyoidXZgv3sG3A?h9WQEURF+jc*FkS-LRn@{jnFFDKJ@Fz!n$u-rE~O@lO;MKCBn z8+D_13Zs0@LxyT}$Z>JpAjZ8_;+LtPqO{pc?{Rgdq#M-_vDC*ESC)02|ei z8z?4YF7B79_MCpd7(X?b0@Kuvs+cGf{la~9DdUYmiaoxR6&iGpAQeJ2YCp)RASq#f zPFkBHStx=(R^q;Cce`J7FQGOwTrd*d!%GW?4qxMBAFywu!St%UR8f)M{rX{}zK-&{ zpWks_%gS+8pX~;Ri>kXK92(DfT*S_ZVk>_k75YGUDa=kC&f9SRR&czD8}y8 z%!&@=8$@bk9xaN4NUm)zx5M0rz&(n0HwRoVhyl$dTVZ1S*WeW%!^(|y3SI@1+ zSdBXR;G!39(lWb-8e3%fBp%>B1$p#$Z3T)Q8(%bq%DK&&j*KB9D!sKQdV;G=u`)$K zhpsq($HS_xBNpvEQ$TPIS+R3BEpoP2($X;_H+JA5#Kgl*{KJ)*Z&^}*U!izzIU(B& zY+>oQA9$S~_ON`HZ$&F<3dd|o(H9pZFLMTBv#ia)l1r~#`OaEyR@p~?Tss3*|v}j9W5!p6ZmRO|u8?F+Kg3z?(1 zF%+?g7=5*)Gg}^qK8Q$ZJ#YnzQ4mQT-^=%h`2s>~t<0!vYRfcrp~p7-s(59|B;HJ5 z#BJ4}$HKUc>R{6NOURls5X_e6TDvf%O<0ykd&RZAm~JglQ>UYS==zBxmxQ$DaGL$y z11wsIDkKLf_PEm-#P z-f-C`pWi3>_%$JBR8tH@cfNllA95Q-`SLyPV~ItH^h6<(OEce84IYB~U}RO*R%CVa zq`Zg3cJ=hgmz3B`0mkxB#sLE?ZNRKFe%57uGKiq!CqOjfDUeK_C~Epeo1zuNql)jK z6m|W?WET&ei~7k*rn?iYN;1_A#HP5aB;Dq__QwAa*>=*lFN+$Ze$y|>R)wv)>rBMC zOZ()yE34xzX{u~7v5UjsC&@3k!;68lB9h{g>wF+zu8Loy3ZpJN^aYvsGQK-#cS^LI zkgu#A^4%oHOfPz_koh0@OxlxkdM0|P7aDCWPg0q@Iri4XrNm?Csabb69wdn8z>9)R z6oi6bi1|9A+f)pZm9q3*D7vYX#NbmsToo0^8#0-0$WTspHTL%4y7sRv-u$(iicf#0HOGZJU~Oe4WQRd>aSI?4r|un^t*og6+$n^lF-03O zuS|*#?$}lXfq)Soow_xIrVb;c#sfOdf zD4&$F1>|~fj>iF?MC3++cq~_s>$c)S^{HHSJ8VF+69BHislUC#xMKa_Dsg^4EaAiA`W)dz+%Mm=|7(1V6tW#t6 zOmsQm!HbDCi@|L+u&vlVzIij~U`UTZK4fg4XlqVZ%wz!1$Ipl27BQc5a_i}%-8OW{ zBqg5|^wnqkmCT6!Y$|$(d(~&!^9M@k26adJlj~5nSvV;NppdJfrI!Rzb-7V#PKy~1 zyi+H;l74U!lU4j)IkIW{e~g|rF<3(#g1boIXT{T^;+)?Xc{R--{&ZyzOyU*N;YU;L z2h-WocV~b^O*iO3)FgT!2N&3YnLfrM!$samUKYyDB%VBakBXtwTq-)0Rr8f6Da)+B z5eY>0pF~y8l-2wQwW+{zYbpxAvrOh~ly)IltFvo-{TI^3c%X}A=c+Fp_)v=n_x@0p zLXiGb^1mnlsvjANaG7^l-O;!d9bwQkKLXs~bsn0Q`x`{WYTjgOx`*4;=a#apyzcpa zL)&0kG*uakvotnnCd2MXa;8PH82m8cN{L$)?f@X*Oi~s1q@=|_G45>3Gg#Wq4cIZ+ zFJiV4fTD3@h3SgZoX}(Ce*FUABFtIsf6b*#hFxBmNja9>RNRZ>HSemp(dS)?l*8me zmH-cqu?b|xU`w#m-doyxiLKEk=^NCJtzjDMyaZ*~^tu2yxOK#l)3WgpHFV9IUthRr znX$R-iZU>kWI)JXUnN7gkU5|0M+e}5G2a~m`C!&)GYY0eTEIYceFyvK z&$L*|l=N-BqjS)BpFMu2R-&P3i{Xe^+BbnIX4;l<*ys%#{dbV2nt@wb<84lub{8Ln ze9tR7%<52~FOiPndTrh2`GB1jyUyIs#oZY(s|4z6&;t#H=+X}!2TzYgI-Z{~Z|YpS z0VsxuZUJWydGBU0-Vw>B4?}Pq1r|ynvMF3+D%VB}TXNo?{<{EaoVHuQtjP!UC#WPo zJnzjIo2Tgt69>9h2~XRBE<^KvVoOkj-rD%ylhk`Yif$xssHz5+^)@JKn=~Ke9Q&Vi zTl$OIvu2r7;5V5TVf<|KGyAICG%y)`0Pz7EBi>E8sd26{3$C!F>tG`vrfA$(jMlq# z&5+d+j@rBZpfL3Wuixc~Nsc^!qnmv;uqDL`7;~1_o-k|j9+ZS-e2rkI0w7~3&7ydI zLHZosM4GG*xv(9>r#rihT!_rZ^ABno%l7Uy{c^uNWprdeOCQ2-osQ{50(FTj@n%2ZHprW{grj}5L*+jC z_##8%?=9Z-w+8NMiCR{}J=gb}THJm@pKu>g7)WOsNSj&b<^%)AbMGJ4s-vq6`woL4SlK!UrBfwB!#cctrC`Xu&~0p!dTwKD_$oO}X;iX$17x*0@i3f41sNO^D{ z%J@7m^X%_XVsJdBav&?l+$MX{%hg z5U7)V$Lw8Kc!&{tBCnaNtQzAxZk3M3S&vOS(WJauv`UX(oT8Q5H&@DYXLD{PHL>Blnf z!pQZeY6rt{aWuh)$2QjkfIE3A!8OGo)WYn`j@n{!6yxbx+dBCuug3G|d8!Hu=f)(K zq`3uw@zqa}gP|IzuE`JPtLY_knw+r9Jg{+c&WwiwI39wK-j2zXgIBiAy{JC9Ohj&h zsmr`@aW_%isb_PaF%-R{B>wZjOoReY9DAgAZl0ZqKAk;4(a=>REZmvmOmjvZ!G7|e z=+3<;T``|2Xx!+#nNstUrDrD#TV~1Sjh*VH4+QchR%E$jp>-HEpko=`BAF~nij|)p*amQWKL0IUrrkyaH-&rEjaVo=D>&rwZca@%01kx05_LOI$*eDCpa>zRPU{m7FshSF^i>rbTA$(_ABtax*(0~~$0%o% zC9*HH#?()!3fXs*UhMr!HejGPT|823{w^kakJpp5i64k2pMO;*nv%AVBs((GS!ZpI z9u~BeAPw@E4ch0c}7`*=9)|g?sCg+@G+w>1$8aiY}@D))zQuL%nqh*swldlR7<>QCMzd z?g?mOn$u7_p*)uY;=lp=9C;Yg5joFm`CK(FBd59?*wo_l`=Kj?El0B5LJl#s!3?-| z;zSY@mQx!|I;hicD%1%B@nK=>p~Y7xv4jaY6O6SNyC8ZQfO9F2-jes)#ZU1Pvvj)* zf!*{OEV%CnH@bF%xAoZ;12s{lfs`(9a+UYpc-XB51d%vpO`L!!!alrsW7^-LjiF5k zNmGttDCj%2^)8;qjm;>@&L^|uZN`9_$tHr8cv7KrpgoN|g{GhhB+e>^M5PY)3`So$ z-z<$eicLxOG5K)SG5Y)wI&)ybL;p|>z6E-m^Yy0*gD9rmXRHtNfG&?VPY&R;NhT*U zJJmoJlgjT-C$RRTC!$|OWfOm95GhQBJGbA5xrF;JW*QapbVGTb2FXmz{IH6)D4b;wCmgNR zne5g|$gHcv6Jda$Hs!|;VBMG1JA0{>tA|5p<8P$g;?OJPqF-nj|+7?dYqDzqwkADNjFA2-E4x^!>$c zlT#LoRn?V@oZIN<3eh#Tci^?)PNI0yP8+3TewnJ}>Cr!J`UO5vKMJTY$7)G>+*b{fdrU3RVodO$@Xp7L6aJI*v@WX@17F z^FHU{}5*j;X`;yu81^ zJLLXArB=+9vaZhqW{`VA>*1WM{!TGHk_}Vdtpi-(*whTu`_lD{%6mCTz@^Th1k>hA zj&L;ER+X0q9Vqs*dbkPtpHlnL))nzcRh`#K2ERsvZIBX9O@yG)@{INNDStRH9CMga z88G!j)Yf1K>LAijF@Irb5nm)6OATT@l@D^Cegu|4lSbj+u@PMkc8m$ggJEpITi_G# z7++Qo#APB5G$cIC1IS7K{K_)%ykD-|)^z@?Y2!#>)d(~kl3*0lK$S|3j647j5k+A? z8}f(0(nsz`S%HM4FzySWIS<`KM=`Tn3@|J!<#<19D$9_P*qLfaU**7%*MG*` zo9YJ<51RvIml-24gJBSMBd!Prtsz@H1S(WED8$jR03fvItw03%1?RXtTJ|Q)5zeKb zK;Dg+8pMyt4~GFs)j-Wco{d_5#?#MoJHXQvv-^Cy=^uskGy~{g*|3x4tuYsh9wJ6x ztKBaUuN_$k7j2_Z9~-|ZAJ0n-TBN_W4ICS&^%8nnz|C@ znRY;P@^jq2Am7@Du3Ar>O`(03T`xZ0hfb(3aL_hwQP?c0%pibQ`ap~cBiS+yU( zxU84=luV~QGg+3FoKfjWUP_LD2TCBK1NMM^@4P{dRj#Sh;H9{iZPB1Z+w2DN&SK^I z!({K*s@sg>6eC#*$tPxBKMsS+uIySb}or6)esCDEKDq$2Y!gp zhDWIlRN$q-VWz^R>ghpvDS$JXp2`BKEX;a|2WQfRIh&=Rabhl~s-!5(CO>WQ9*^|2 z#f6`+FKu1;Ix{om#I*>Ym$mprFSiwZ*kiQ5s_YV0!_-?|myC7QhSKpcz){k0%*&m3aEu2Im}_ad2((%)$6OOJ4wl zA!%jk&YmrN`)qfFLhbnr%jgFp_HUd~nQ-KHhZ%i@S7E-kvOuDgVjSk(#B2O2Pozy} zDejM@oB03wlkTSRcngE^CO^URN+81dzuZ3AyI+sxiyzD6M{m_`Y~sbCd@Od)B;ee? z+NM1x_R~K8mrHE~;8$PfuUt<0=ReuvuV2;M^E|JCSO2;Qs5$?);Z^9roChy5;JF%l z=GRBb77Tj)e0iApoUW1Ahv8o~+~x7-=RbeeIs4(Sxe(-Uv?C~zD$K}I)1^|@ldRZm z4a1YZv-w&p*Yi@u4J{ISUT`(Geyo`KxT3{az}MD)QqC+deI_yXV`6}~2}IhFwGpnB zEr7`UYYLcV_G2z~QkWfTR=${bNoH?v)BGMDHdUWMEy`etzqGg&>25{0`n9ZH8AlaZ z4M+_-aDf`m3jvGCkUhU9o%0!4YH2hd{B?Tg?Q)Wj=Ea<&|JoKuCb8}mttJI~ogx?V zC}{mm$-_ZzfRs%OBFwo=O?EvurQ)G#(pYm`sOJ)>{0J-)o>US2=8{Nl$$%hjG; z3KY*b}2Jpo%^lvU;G??{`XRmr|u*R7mscog;-0kpl) zO$`9-sJi=;2C@w)#c{B^*7Q|uX7WtBM-@Cq_)^j#%Tv0n_v(yrdCuIUs*Vi^UGMBL z_MxjA<%2}E%)^*lGP(>8d(pWRGYtbe7vqvyPg;B`Cu@vfcX^@SW@5%7C2z`lhF6UB z^YBT!X=%y90yxS&NXuPi;0UZ=H``(<&KdG!$jVF77OGTPAJNfnEFwvWGtN-r2G@&vM#R^_ zt$A@#7han8bC+Xp-$N+{ZE~8i_I-pzu&x*0p-yiEW zbhW{E#k^%(MI!=v8qSku<)LOG1o8mf4~*L(^hC@P{-gQr4@Mb@n;MVX_LA}|EJgHz zsGupY?dP>trL}eGa*f-v&Q8BEjsGC*_szcBcd#voMBc;TJKU;JNQDD9A?=NwyXSSgm zB)M2~=KO}b4J7XPCt1aZP~7`xS>=9KE}CcANs=%xw6OKrXjv15*6Y^8lpLPieh?M?#ACqnzFQm%IG=^TrB|Af&tWv#IWIWKl$ zzR^d=k8O#g;vkmAZ~j5wY!iWNN~~o!SqN`` zOo~X=%7}fH`XfwnER%l#8^=kzeB|aeOMz8p zFo_z;wC_0>ZQZW!?R>5EnBKz`97{(Ehf@2+gP=>;t;x|lBt$PWxeN1AfqQ~(=LSVn z+t0g+6p&o;F~vKD7rW^<8xusZPd33#@%#m*LRh24#cGcf_smZ@IbO&U7hrD5b>J

o&!pvowVs zbr_et92a%?{!M1Hjzs^;%5V=<*!TLE)r3JF<%^aFTNO&pDbg-Vo2zWo6Ivg%a{NrC zg9wec*hrhV8}y<>UW|7kIw%2qXur?iR@;AkeS?*JsLFijx&NjFM@;vh6rqLWTIoDa1hF?laO zh{g6kZ>eXHGUJNTp0ang{`2dxh!OBxiTh( z;pBQb&SN$g=SN%~u&h(AHj`qimfc5y!mEYo{=?S8R-u(Jj?@rIz{ND29aC4Ds^K2N?YYwk^KZuHp2azz1Mc0 zNH($qX$q&jc*3c=X+^*?U(j?`j#(Lle~2(?Ak6pr{k#=9MR#TS?$jKwT+vO zd1hFjLDmnXa145yxSf{5Za<^88v&rI9P^euv7t^d#IoTDj&RFLwZUZUleTBB@Xe^m20aFld!WFK^m|&LA?7*5+B0W#rji7Y0ja zWm)%e2Vw-3W-VrltDi?KaB>Sk0SpU&YPz=z!DACMD=B?FQ;|$NlpvLatCD^i9fEtL z6Vz`e+oV@v{mvBc9k$i}z;;9JWRoI0bfMG_0;NNXsbBF{Gcmy1^Pr#{+}-AvdTWYN z_P*WQe_{>+x-)ak=u(f442W;v{Z)4|zkUJD{M_6iuf#?i5y(?18uImhU>ruFtLq>f zzZVTZjoRO}6_4+We3<+&C1V#f1Ud#&<&oQ87q1-r2hT$_#ry zrCd)!r?9`g`(Ii@Vz-5FDA;#{oqy_u)wziK3`o@!E>-cJ+p%4Z^d4!=%36Ri%H%{r zPgsPXZE@7v)-nW0Mbx=dSuulGPl zpBgeUWfdk*M@S}wCBQ7YqULen7dy0<1o<2pBwB{t6erU(dh@wBi7q!k%Ud2vDohF2 z*^|tuYsgES&9zqpR)3=CTm_5*iMJFfFIGH_T2OKZ;>OCcfswKS)v@B}uhyd1nA78C z@E8m8aYfNiYE=*pPmazWPF*sqvzD(|iMhF(@R{5jwJCc&6X}>>sgdmm{`%Wk+~1>+ z?g~kd>d1F=_7EmsPw`<9Nnq47sw2#heA^VGY02^`Ik?a7PBWo%d3h@y5T2HPQgGyW zODn|_JK9~t%$u|!B48y+oVn6RAxESqhv!k(|2I8?X)&=^IS1SILNYD4$^d!2=duLW z)$GXu<|%z2QoJmDHc3h0atuS`a?0xt7lC$ylASrmy(-0Ki>fM{T@&AB_p&8cVsb)I zvS*}<`6VrjU?`#*ddF}r?`J`YZL9KZfsr$*@0U`XDUl{uPKTy+hh~ydFgPr`9R1iDM6!3ZL1ICC&tG~!X#|` z>7V{o?*9`INfB!o5oDr24w`j}r?<5TfB}5vklBmRl(PFl5mZ^?LPz}nVm5z>05+t( z(=ryc2`4Y)%FEoG;!dQPD?8ic@tV}+j~yu{$pPvTdZ5IE3R=yKOh)8O<3kCHb>=SD zftyKTia(dt`}H@~w-WP-olH1rp8Ve^G1O`+f-delT+;nLc$Y8$_SNz$FI_j$Or!$8 zJfj2JrCbL*x>R?X#4ZbWbBFV?EgItn4wmQ=SN2@$RY)bg=oTmV(uJ)wdJCbk6Af&O|Udac#RfE|?D5>iuLL;72Rt}NwN z^+!nsvI0q|o8dun@lD?x5-R>dbQ#arD*%j;6bAUPPQhAP1ybzwusUfPHf5f1&*^@UyJTAFQen!ib3est zG8=qNx5>%RI@r165lE2|b6^?phe~!;91{cd*UfV31f}ERrXcU;DF_?PaxjZ?3gyE zh_)X&&qw3q<~n|&Fho&o+Mw9&>{3R2!~sVV%fF?Vp9#dKTzd^C3er=;jYshx)dn`3 z_W@2Bbv&K-0{2|>$vMRqKlz%P*HT`5^?#^?)D9KCo+koV9zva~!wd*$GMkz z{A$|?ngRC!Nsn{Ko<;g0KZPzzE6t-+Pi#Hcc3;sphn*y3|4Gp-ZHPo~ncLl3iWQ~fi~Mdq3@iZ%s<4Q{g|rd7?o zk}AOeCVPBd{DNf8vDN5>zSbL7qh?GdR$6gOr9sE19z8V zfs5R|3`2|cM7{X_43YwQat9wUcsPllcE_XQ0SRfTemfRpCJnX;-hdzy80O& zwU(V;%*6Lys$HiFH~t`_zSLon94W*(`y_6h3`*+t0J3=p{uEPnGtQ^kE#v3-ge+`e zkiCzv8Fda#60k;|eJH-M#J;H9`5$Hw(4~+M#%eB3Xfa`kS%r2nvZD+?)dL>U@i*Nx z)e~(|ioV~!&`xL`=A8~NgqVadX;s#B*JKAeqoMvE>5BrcR{QUX;*7c<&R&QT_hM zAFsXQY7>rW8+T|k58wCUsCp_y`|J@5so7)du9AgU8&F6zjAEUZ`@glW$jC#vYvt%{ zm+X;$Yas$0cDN(KPlkl@Nh*s(uy-#y>Qk${?O5lNy7n@*P8y3c7ovdup?k z2S2p?{nZcgWX_0btwpKvuEebUYd-yJKTCG)KseU+;koD=ogS3O>5~*UGq3BbIKK%W@W8X9nNRs>;nd&hFY1n zl|&{GvgZJt$v?IhUA7c;k5Fow*i%%VuW59ouGaL${S0@5IBp%=>dw=H&S5%ohYYR2 zll-c^2j_7HWpLJ&n9km#GLf668O$h3TcNDJM17yRUuI{+)W)!TF+EpAD2p{t`+0`TxJM}wQE8UBqo2rv z;$Ez#B{g+?o?SHn*cHo>2jCaG=~)^AVj=qU2QGtFnv1bnzi$fBEZmzyh3>~%c?JIOATiKBm6+nVkFU$f=oeD`bh#D@k-^}V zg~VaJB}zP38Ndyod#aPVJTzH^Mn>YihBPf(%TZ+T6(*f2))0;-`#0#$p}5diF;wM7 zq3Kp3+tL z9v##ncP`Lh@aq_+Mmvx<)TH00(3npRMdjqTaN0-xeW_WatzF7B0~a@s;;oYV925EY zEPntL*W`H*j%ks_ z{S=K_bFd}kbBCI4v_?8`p$XgloYaX+`0yev5kILCx)$+J>GmG;rf{c-a#!R|$;-Ux z1IOlK_Lcq$I7DPDrHTYr<1UTV+w5IQe%+Pl1FIhN4-xr+c^F}C$8aHBL=6XiF>g{E zqf)tTW$di2xgO4~lHAM`zf^>!roUj`McQ=ppVAZks{sJCNRCe5D!mPn(pg6Vpp#&g z#*;}*uIbejDt4gpLGvNWH}*_>6!XATzWUWnq#E->!#qEk??6*qA{1s^I$ECAb&C0D z=>F>1*f`r$gFzs^a3VvtxsR`@Tef47aasy;2KhY4@L&8>eA{RsM7X_ZRjx&9CIw&M zJ-=O>VHljpF~(+5tK7-D_ZUI!9eG&H-tNp(04(7f#B2#8W#e>XDr)GRwm4@*qg|Q` z7UVXn2;9K<_#Pth_}%*B>l8P7l&=0XJJBKW?B<@G0=KJ4c!)vY3M+f4pbexCTaWNd zcTl;IW{fCMKI6Hq>ee+L!g@Ym3#-8!VZ@dF^q1D^4f^Wh`?h+Xw3A1All7C=X5`0% zN$41vqA2FBApK#uMocfB4Pak2s(c2rd3;eF!Tsp~<}5dS{gM$-qnXV@YyfCL3R`nm zcw6k_SC5J^<)XwT9D@)V@l_DF2$C+`{^XN$Tf2OR#Hg%!JG3=wPPLA@6i)#wXv&Ms z=q_INZM8$}Q(jOJo$^~ClMV@ThLB%q|D@$-s4Gt1Ko@U*D_6(iKuR9ra&j0(oVdD6 zyiY6aGDfWC0Y&lXQG&Sf_kI|fxKm>NM{lVbtm6-IrX*fGHBnb58sD?^tsvzhgWam~3&bDGAAV}}sK)p%K zp%`S}T(5_DA!F~tf84cF`x$g(ynh;$K3;xsA$kvY9WJ^3c$iw)@wIe=pI-LTN(Q@t zp#_HXQo;&}jO1bsnw>VFGmj-);V8q+TErJTXz;{qK}UqhT6}?zhc!q~?woTwf6SK1 zz%4~l_fMb*jySi{qy42dxv5+cZ$H*?L`Pe=wpIsUD0m!`?|OX`GHPLGs-1fndK+f7 zr>1VQ81zkH8w%P0fQP2!!k1AA3gmGU2(M z8F28?^yPZ1&}s*DQ|>&*C0uW-wzHFXTP=Dko7WiE;(Ak5;)_PX!}}$i961PO%I*C@Ld|(sV5lT;K03jbFpi?s-XMMW zM~OfF7-y5fugMbigNOBeb&5~DU5V2Q9@JqUUVsf8V1O3syl+~{@?6tS#%=1p(1`P( ziSNAoKe}!VOtHV^2M*R|IwEW#dmE2GQ3fxlPJ2Xa>y2o~QeOGqT`vBY99B$wdw8l1 zT2~@Wi(Kzzp>Z!y>9v|G24ioN6*Sm z_BZa1slJip^-s_L@>SoPn0tHH=QsrSq@25}jcc4Q#A@z~#)e`_dP@wxteS6ii^kl6 zCmr+VuK5j_YLs5Tbs77C$DND0EBwVU#*dvbQKN%`CHHh%&Z(l7AYmSq~IqG;Em6AR%6Rm=ui)Iq#e(i$kjoNVrYzn zs^>EVjIO^Yg%vvZjC99~L^4Mns4742R_q2iWNnS1H0Gl5U@2$wK$gTaV)&f~h`{&% zJm7ju3x@s=?lM!ExO7SMSHoHNBeCudBe#{w8LGKhV}8)Jc=Va%FSwbDJLaxK$?AzX z6VR38ydO-FVjb+OQCqx;6CsYKVq7i-t59*Ubv*D{N*8#i#6LmT>6f6R0Dl778SrgI zEt)v@gORJdwr+GP+J#I3{wS!nanHmra4Z-%#y3S(Vp0>EEZ+x;lD{s zQv$7b zsU5{QEJX^6(0OX_e$bTD4hP|ZoV-2n%1Cxp4AOs^^!DN`HEQ|1{uP2@fAeSTLMesUg6>5hUMfa~g7Klb`*f(^f_vy`$md&?aZHaprqx zI66FZh)52Y&!b;YGugR(QazA`7opwzyXB=&H*b=MpoJLzcsF3 z@Y~Kr{3+vSId4zr^lVdb(%XH6)p;X&i4STVCf@E0c$9gji>ziPuKJ@Imz)fJ1=KGZ zqfMFCFxox@%;~bz{R=qg(u!c~(ov@uXu{CvDT!G@91+o^r|+w1N;O!JvB@R}v*Q2| zQl!A=B@4{yszWEC(7VMZlb4Kh&~yCAsnwWmG}QQ=aw3GX*!1VJJk{Y}WJs&K*nnf{ z&99u_pX3~sXCCh2@z35${Eyce>dL!6imKkA*yBQi#}-~BgGJeqK(BNYuOf)q@3U=~ z`oHfOi8s^Pk!^2$raYP?mr=>CDAV-hN<44liZ&-p9-j+Yc#Up^ZHuh%ZQ&YL! z4lM{gGB!6T%>jiGX;%^-P0^|jaaEYbnLQB|M!{?^mSQA9E}bDSr!l=O&PHsIKhw^+ zs$@zcs^eV2d(C~bPLzW{e!?elxppbCX7vT7;-yGOO(wr=2bmAV+--%O;Cy^~u~r?m zEb?I90U_-5KgODq`{#nLrcBCTKt$EJ*|gg?fGc~z#nuBq%Joz8C!o>;Ipufr!MAg zp1%&&R;YIG8j|_<+kMv-V98JiH!C0JL09J|BF1#V|B0D$8HL~1$Md8yUnAZmER#`J z?_8Rml=7n(&8i%LGXFG7OdR{?h1jz`x#|l8t!fIo&j^v;ZBd|-&jent86@!%SIymM(j`!4b;h&zL39|Iy^O zL$r)=qiyJQ@m(M>HFD=lrv|R-j^*<6@+DrBUaTproXLS=M5z*7oe>uu9tt4Kohjl_ z4)JztO!Z6UER``5oP;KKHv*E0^k^7>WyxD;q=%fv6(%i z#4;T(W0l^q!`uacVk=A7KeapdQxjq456igYCSoO4<^?n;s$ zdabTK#efw#_q(hIfd%Qb^2L9eU%#F^Abu|_*wsBGawLV@4J5O(U?kd|QcRO4D3*GG9%b_Wrd#N!q-u;U08RgUmPS1Ud zn(}{+V1Shee3n<+=(J9hXZb02k#ByYFKc~u)%Or!a*#F|WxArsawx`EQ52carzj$S z4AYlT_!ULp^t^rmJPTFQddwJ=iJ-M zyCNHolJBlQzeKw*FsIq+W_R3FgK^-+^G9zczV7}?}-L7hmAXqv$>DGI)DFnfBNS?pUSE#t3N;g`STCYW(oa& ze``0>V4LJuF7Q|iZHrRaSp@2#@-SlBh4`V@>vh-BK!@{pc)op8U75WJ%-k64-k0@jwNj4NH=z65YWd7TT{$oXkb`P4y z7}`_nx6^f=&^+0wC=rd)UQt-02=xz1fjDY1r-h=lEx;Ug8o>RDHD*;~6{#3ZdEtv= z`mx}shtBBfyUFDy2BH-?+z+6NJi&9p7-^4e+PTOqMWr7Qn>2*&{CZOyH80IW7)~+h zzhpsj*IfOajIf}%7gv$PEq#^3U>t+-7`<=h;o#Bc!Xrp)-$_ro%R8Yu1 zi-N>^S)Xh+PFUm`eNBFG@H{~c(MiB)%Z3p=`#ZJJ2iGJfZved-olWHgA z<8m`FDo^V}V;wab^rk1UN!V3BzmMRC(Kdk2oy;DK_=2^ViABLj9p|e23HlHDtFJ|L z8*)4KgBz>hFh#tcKNm52TJ3AI;NI3Lh1Ff!dg51S6?sYV=+L}-^#Ph{GQ5BVYo@lG zHdTDb_{u?E2&sKn1C6X^;_Zl$0QMTEfZ57kRq*N2Wu3O!YbUPW!{~}3r&wz>tw8D8 zlt?N7nI6*l`1gH$=4QJP*T?rCa&eU8{imHAJ?z>zYochdQ}Q&gs*}B1i#gJpkebg} ziCN^-oE!Jyx*^&FgFR)+dehJ~m+yw6D~S@`=0KTTIi`qAhSlZ?oD9>Na1nFbkTkYS zHR9!~2C>n&?;j;K(Tzw7^DL^!ZWnTI>!a)khUn}Ay(rlYErYWV59Fh&4}UukDVizs z7+eUC*}SfB1s5OMYR_uJSG9fg+DX zA%2y6XVU33;H*S3TC0T!iQw?1>nwZ_I5llFkq!{9aWoH$U3goihIF);B! zbY@v=Q4X-2iw$`!TDy$LG{kQ=am)vbtX8XUFXbAGA27na?jD?jsBz-F*S+PTLX96; zKgBjaOaAf4^pxb@lK<>)l~ENHj_~ls-SGr(ZIp}0LbN3{%dhy$x5+8D!!ViAY)@BL zTkQr}Fr=9s{4p4TIO%IX$T|PN0CO2_bc-@`^HGaSD755-fNfzu#!(IzMwoyA3WL=kH^irlwNJ8=jjABur*x8=MFq)M z(bY;EzK!-^w9Ot{m(fii)`qlpSH^eT$4TlaVYz?gfS|Tfyu&w{J_Sj~{S_6;pNwRG zjbj#aA1t@>;u&WP(A2$pqH{4d*%RvzCRg6;Rjwzv5?LmCf**m|5?`16igVNJ7TqkC zV;Cqwi$}He&LD)ErNZr`Vf3H-U$d?CcffV!va;MX%(z7BPz~w{PqB zq(LOWHYxOy$v-bo)|J%Elg56UI=Q7}G#+5(B9nA3LKUMpdM9IVT3R!mNKv%nte7YB z_D_zqv@KwyM}ywt|1e_aaM1l4|bQjaH-+Z+E2MO zy%$oS+*vRBOTE}GCtFp&+iYmgni#_zJ=Uu(C{ok!OR>`MEb1OW*rP7F7jeh@cHjMF zB_BzxrMqlS?%imsCWiS(x?bVyp9iR`F3T_~44<#xKpnklZ!DNKu; zIG(ASY<8>|V;NTJl%Z+-X*m)Gpcdts^-K7x#SV$&ys5~ zS$JZ0*Kq?nM7%Q30VWxgJv54UF+I=;cFwc-ql>wiw>w!2Hprj+KRqa>oX~{b+l8UM z5!9{pT}YCgh}u@)0d)J;>vGx1JK#lZ{+%B|fb1$AKd%ZFtl(Q&eB(-S&yDt~l7Lc-_%`ZVQ*1Nz-A?D3qHEh1aaqjyl$~kG?ARd!8~*_;})Uz9~vH(gbw9XW3*`3UNbycKe~4vdGdD zkP~^?`UFpI_PR5+m7SBIqkD#njbrb`pod8mz!3IccWv-VotbOYO;fITx;@T#5KeD% zhxeq7-WQL!dV*Qtp@6BW&OH3P4#Qp=EjPd3%9Iu_T6~9yf~VHrM9{$)A3fbKeBM_r zp=LRamgi@A9l$0^AF@S#*6g%-)k=c+XIq&XlhSzfRfM`oa3)@4Ju?r_iO_BqkyPYa z$u#z)ccaiRC?)=PfRMmP|LfPJWr7^X4VCkDUCrT(?PTwTJJ2TJDQpVMjKr9M*`$CQ zjmVJ++bFa2zbQOSd{_7JN=CGj8So#)L^)+QJjprjzLWSx9t1ylTHd)o7-u^Zi76gr zKW+_aj6dmJ@FFA2UD}6<4D>QyMObTbIK9!zYS2-HNG79t}zRZ(B8D6}=-sXKiq% z12A%m$uA7>s9edOT+1kK?2)&vs+u&hD(4l{@1cFMzr~juc_=32c2xvYC|<0^H9w!? zH5)PVBJUp*B%5hWIV=V1XL9G|w+{?Tk@Slay#;;lF~?jMhs>p6*Nj#!oI?7~!-lLW zsy0JlGKoWE9x+u)PP3aTmZBB4KM6x$+c zreaSG=2OQ2)e3g&Ma3enLaevEs8C-(I%E*NCP>(eQ^=$ZpSecuCR;5Q zXL8U~w-`C@rtz}Y6rs^o9S=WbUJfR0Vq6Bd997qIqHs+;cmr-PmcH}{;iTdqQ9u3cOU~k7P3wt=IEppKxeo>%? zr!z7C!yC-%!`ang+7N{3?Pivr-dvgn0WGFI!QI(*%JmR0I%WNS9lDSmF!@IQ5mR;7J_b4CWOcem8QtUN4} z{Cs?TczGb4AUqd@W%^n{c=6W=FZ;r?`AU6fFkpm^#fgMOOfgpu)cjS3BoD>3x=o2t zt1(XvAeb8o*{d995+Z}C{+z~j$Se`g7%UR20_ zIZQ&2QA4Q)mAiwdmE}3XSz$CzdhG+$Bg^$5Dbdo>@TKR1q-x!|*OZ`FX={3o(uHjIANd1SHQCcefqT6{47uH02^L4hMbnNki^PPR_1(0xu!nF&{fi7 zS2izopxbICKW!&Pb{{lO^@)j?I6ZMPm)D_27^M@{65u9HNwmZ=aP;_=f! zUx^aKTuu}@81T{??)6F8h)l5p7xLXvqd|Fd9!3if@qLQE^rbQ`5CK*t1w!vb`DkI8 zFI5SDi+w!(L<%0ugJAsSA4yjG|L^br?!W%?pUHdxs=EKSyJEPuWfFd8>pu_4K0ngp zN0PguZ9p_fcJjm7izkiavD##-DO#*Ggv&ziFWh2qWLfCr1!Wq)d$8)jlv@-qvypm; zOd#43S9^bOatjn1ooQpxvu7xub2~z;v??OcF~ljibO=pxf2l7qlbPL>`Tqm(?e{S`V zf_M?@m&(MhLT>iBm}`LyZu-i6ve=5vJMVN0nt=`i;Y)>E^8g0ltDjh+H6F>(fV}1L z#Nmq{T%}>XHw$s%_}NrQ^X9a}O!`PUr}!)4_o1k%Y=CjAM>tzj>;tCl+>dzYj&A-0 zds|@chd1>74=%;Jq=%>Q?r=4O^8M!hDSYutiy-db9l5Z)7V1pgm6jktx}mN+A`v=) zKap8YelpttuZ}cMPHa9HtFFJdMVOT@$b!~7c-dKu!blrX6biFD%WxPqJtJO;7i5Ml z7a2~**GPqZwiHu|-n++8EUmb@U5gA>zHy0Oc#k4$gtuwFkR5AwrBUMYN3`cW_uWgE zd?Uxw9UK7QFsU}9%?QS-Z{eq(D`wjt;$$8};azgE;8A=)Km<+@?)JXi492s<%|=Wf zKae*6@rOtEdPp<&){6%Ew3^=sJOB=Dc_+ktDIdx(4&Tal;E6t>+;Ss2HmTwH$bOW& z{DWJuF(C-jYE>3|6PomDB~sX(OnECSzdYzlMC~z)V`cfA=2lyrxi~6eZ{XkVUqD(f zqOud_@wDfvEDzf9C}e2%>?emQQsR`FJ$X9xElibKd2ujnRj?jF|76?>ft&AD=7&gF z!ib@;?@v7X_Jx`1^+Spc(3sC|d}DDp3B=rIz3b{gEg@`2o?C&@IQKcx&vGj{eS9DK z@baH;#mnSiT!tnL^2aiY4{0OIt1TlOJie7~=CsU}!?qS}#DN@wmfV@uOnW(n>xf*4 zRy&`omFNL^BAzEAp_iANiLSDzzd=831*E<$_V<|ijcY%JQs5maKQ*ZPJ`t^|wThIs8Kxlh6^`mY{yae@hyT4%$+K-DW+hz)HNer1(uw7t6&<81s$cvoMV zmxbpdMO^NaAYk0U|H2=;@*oiF`8bqy6Aw{t$qy)yy+T*}&z25F8hIMwi+63m%HEXM z%u{605vI?s-NJIb+OcaWSFxB($g7ThkCR^jjy~s~8n~NR6oVStRS@a&tvjx$tsnu&v=F#lNjCT-i zQ@P#FVjA9KFQSh=&g9x;@};)fiv9vKuRSp>j}&8e2e^wAG9BGxKhEntA@{1%y=efq zb~Rfk+0T%tw2(XhQKA`Kjq$dkWjMF_nN0TyFZ;*81!()hw)>~lPX7XzhS8H1=24jR z<5t^rvN`3MG?h7O+h8s4dVgM_KZRA`-mF`HfO1y z3z8=cJ&1VN%eBZMO_%MV#&r8B36aL+rZS3g--x>q&FScOJGKb5UhfhO9Q^G}2KnG@ z-x`XQAZ$+Z9+c5A;LROpXs@c{?#BfU>7V z55ZTujwgmoG&Vms>?~{1)0^IYQ&uPpYgt;5%qu^CEccCDO+>%$B z`jnhYr+vKjR$Yf%uYj|emit)Ct{tPJ=ns5lxlV+<;zEqiz2N&p*eTq43l-iUppEqX ze*pof1u|;=Dg!vGK9$;Ht;Ac*OO}s3T>W2EY!EYOrOtOe3Cpw=ORJr0@<y_+qgnzKu*wq4?jB{p#}Tz9VLf3n@1oml@WQ`%w>pj`I*-K!q)Thmt-PQcN;rkySNbLGGU#WzcIZMXzqfTzI=scrn;eQ>KpT63|C&h!kpw?7ac`!*02 zyS$O-TT+ziQ;%tO-9y8=|KnnDG_@H|XSw%XDL*WZKIL8zAidHU5t}@=4Rh(pd>M6Q zlbA3}>6~ao*XAM+kNki_A<;&bP?o4q`kof6sYuQ5EX8zJ{e?793jb=rCx+&3i4RMb z;zo=(%>vrOqOmYcP&eu=gkg44v9>sxBmHhuvb&_ewD9riZ7XxmAN=Z37a#o}`NkZ8 z$YM(|3Bx_B7f*=8%#&|7+>(SC5=(AT9U~!d$i{GA1A+qmkSo;gz-U}lh>pTs>7i@f zSfz}e6gI|z4kpEyU}DKd2=dl;S`!vrGvt2Ku&qu%3y2;ntXg|%rp&M z73eCTWWFhSI9M0M*(rD7p=`N|;hSV9AHxILr|`fU3|fZM9ZeW?)0}K%*x}~KLM+s0 zD3?B!xL*6A#0%q5E_CP~{m>!-3JZk31jsd2Uh}l#_+pEq4MIDYM?6Mlq5|_YdAi>T z?h4}z_y_AKY*7}b5XWeg1Im$giOIX*L>ZeYp^K4P4=~f4UHO-P`(t?jal1#h7pZ!* z83P4lhWsc0t){@cY$yQI`0Nz)csQ;fC;@o~C^PZ)1sS7IFxQznLs|)BNUY2YowiB5 zNq)A)6Beg`eJBw0zM#Y~BnZAEF1^CSU>0MHw@!?f8EWue#<)3zA7w7}ojsw{AEB6+ zKn9PJ4ulE2HuDHuvaj01k5cA3qWp#|$29tf+``p(9Y3>@huwj%fzE84t53}7=8o$J zewe{zj*Hw?Ce7>(;6bM`a-Jm6`t>&Btq%3h!9_{dfLzGrhyDSpz%^{ixa z;1iZ>N9I$BHx#@$_#l1dW~`MwmkhmeAFrT)1wi=l--Dz88ReHvxReX?k8&<>4_s(F z?pv{KTfQ1lE5+2#SYARV!nL)nKD@!<%*14_e5Nx>{Mej3X_(S~vXoixtF~Zg<7Zoi z3wgr*Uz>`qL7*D2S^+8e&``pMYl>q#x{pK|>PYez4q0eX48{5Yuu8$iTCQ_~=MuLN zmpQps!EvYhRYi)$qp2Q+cQ2G=;k@2R%E0Joa7 zS>tlkw6WBul8tUW!(IcJ^K_2UTkhT#)6$S$5Ch({jkKMM7A|yzDMZW>s-0e4Y*c>e zwrl9~L>lF_ikfXg*t1b0m(35A2Is3G;w>huPxed^LXQA+t`@bsxhzf{t}+u(w=bSy zn9_}_b~?>jSICNQVWnux)vT&4bJ*&p*Gw6qrF)T-65?99@L6&(Ub1jS=iz>pISPN* zI5oIkh?(lZ@Rb9Q_0Ch!rZ_Q7SOv1(CV2*OjXn=`n+Mb(^OV=OSt2(A*Wc=!`=^Kd zTm5S`Jm-eiGq2Dgo2j%~axuV1#I*nQX=)pJvI$GN+WE5m*Esq-i}%-vWk0_k9JkW3 zm%#?F<&YOMvbWldY{jZOru(74WG!91yEwCxOr2M9v&C%)^mL0*0V1zRHS?mHz4=H_@FC8&=_TrEWa#j|K{wEb3eZXbmPn9BkMs><-fNC2e4Xh}HnqP4ZE zcz__xKI-?`QlrJ7u%SPE=SkL_8;l(A0~N-Fluz<0d_pS->y+(}!cEQ5+ZTTKq0Q6# zg`TWu+=+crRiTfln1(EPR)IO4h<+01Il;fUn0GZjIxo5WtcpuKnuBlA{?rPlBbIS* z>4prXfx_#L*be(LgDt@DIgp_Ahe(gn0RoovPL)0~aC=mN@)>Zxk;zG7o>)~PevF}~ zIHGOvii?Tt_Mwks5JB%x8W`ijX4W(rDn|-G_n4<4KZ+g4-nRT9&ms|J`@&)-`bju6 zbOB1lUDEw!7}}S)`E)s)Il61F81>SpvDt|6 zkuKi%6=j^klZL;v6rlzyfSpGj0DL3vNcRGj z(}-tyke7;+QnQdI-_Jydu>L3cngZv%PO|d#-@?&u(_5wB9_wqdXVQw*n|9ANU>*YwKpt%P#%KB3q-mt66o&k2NXe)Gd^(V&(g z!KFqludGViWJ9VvH7f?2nC$R{oB9To`BnBD(YFrhJs?kB*RjN9-M{I7418TLekpPQ zmN;mB$t%h2K0O_I;Fy}ayI3~lR>!3_d*WS3WB=i`IgGCw>XW(9{}u1B7U(lkVv8Rl z+DcI8e2eAFRA6rgUzE=0Kn~)$0#3MhyRLGW#S`fm%soj(~r^x`Sd2`y@V3 z$a>kHVUY zGlxAx3~>op{wThtCH&yZ=U-aBO0w5;v5WaBDf ze=Ua=;SDvus>1MhbcFOYh<(J58fHH{)yjQ1P(QjDSjyQfIkmgWy&eE1D0>pcPHcOF ztj9<$!a#whKfQY)gMFUFmwprbWI2ZU^HfPJg2}?uiRCfFuPHx8Q?< z`H$pS+5U!DD%{r(k~4CN=%v9f)3qr{4=|)=-d*E;!z!ZRo`e@{R4Q}^_T1aS<)6c@ z^L8}*j5)t1o{Bjv`@y8#+Xr@HX;VcH#vB%YZwhC#SI=$mY+ZdKoFF#RQ# z^a(zKC7Wtn=P>SNoZ zoUHFVm>hj)>8rRng7QgxmSA!{KnJ(J7@u38e1gaf?@+%!RL%;PaCisJ7Y``z{z62h z7cj(u6=dR9Sil57f^7N^9z8e<7+{dYXzMog>q{hfOVOPedgm3gUAb!-!5Dl; zwPBd$*)$d4BfEA7@XbW?w}1iW5+689roY6NuAibe271iOy@5K{R(`f}-x(j)KxP-c zWbbr^@!svPVbo?VV0gDoYV(D!NA`Aa8}uNF=59!uZhgCJr42XmwaCtbgn$|~yFZn^^7EL7r(pCx>ZpHN z4L$#=GrhIpQMJ?T&XR3+YS05a(O+4@STkQw-_Vbc-7@bz>h6<6oh9rwVy!I9y6S5f z{ARG%WyKt#0tjL--dVz4^KQp|8Tv#-MFW@T62|+zXw!E(`~6FAD223y^}bE5nt14! zFyPySw(r0E_b)8KDs-)uK99nX%`be*+4|PU{C#(|9#TCq8MkCRergW~09%mFOHW4d z!AGpfHo>%{EQ3MtDflmZlQ;5!50-n|CI(MSm~x+6$8JC*SPD~;Mi>?tbRhU9UdKz= z@zhku$vLfM=XZNLAHI$z?}qsjZ=VUd$f2KK`3wp;pgbqW#NS@|y8s=oWxu{QxCK|Z z2DZVq$uQ%YdotlDw@&iyXBjE1wsK|7}phc4XcrAIKGMgbVXJy*u$8qMLt( zTY-CpYwik~XjWFZ7$|zh*du!Mq#F!6@f@#kLmsCK zbQRQQS2pq+M?HZRE&|V8C4KUtXI>^ufeJbTGo(8cZxThs4TAWC*jh)M=x@HLE3IE^Tz-_F{ph+%{TP|a z4?tGvBH&@iNX`KRYsxUuYP$Twv&CWu7xpqag}sI~@|?46eG;H9W1ayS+=g3^&Q;ln zL(9jgStmT&M69I@eZdWUK)OLH-^Mi2p08n&xDs&WnRwHGpF$+JvsE`4ZSpZ>Ka|cO zzM~Wu55EC9Nt%*gAT76l3~QL9Kw+&1K283VWXesJ!$Afa%3dgL4R1&?=QV}b4fp3N5yA@;uEWah zF%GXs?ELy;{=f1Nx$yU+EZ$vi4jZ4Ad)L1(RhO%B2QVaj(Mbh_>&pWF25UsKVD`CQCj6cMY2)brm?Z zz>^|Za^;BXu3}3YrgFu5a;c1z8WqQJcEWGnfN%`|QmS(D)cQ`v?8iUV*5Z>2J65ia z-DPKp<(d=yE-j%LOp1K8o%r1IhVqe}vha)}a?NkRG`jvtACjHZeee7bf-MK&$=bph>MeQX+Km3``Id{rg1KfT4-Uk_ainp+#*>BUnL~If0kQ_^oV?@l+hjtIW z3mpqb=V`ChpN8H5U=aR&PNH{?5E+kSFOw2i#fA0kPM@X~!*oA_%j=cRjVrLP=`Q?M z_gfF*3(Dnn9(-!KpUxi_;j=^?w52bt@ZWc}g;SZiKGtWo5{UutdVu_{nyYB>247{J zxWn!1o=l$iEzVM8?7yo(nj5_rjq4w==+5GzJE!M`^4KcsPI1Nk)D}m2<9Rrjw!;7wWgn~6aFF3wwxTYA0>;;bMLE*KZ z!|PoI@;ksWmm?q3^QZ?^-2#eM+C};XU{6JT06VZ!V~XnVl`gY$nG->qQQ=kMTWQ5=wd~s6h1W@2WON;z#MDOYkjyrG z9g6MAgWn28t-a`04@th=;RQwM5hBuZ3*P8W$NV0@<|t58Y+kTQK z6%Kv5x1=s;M=D7S-F$OW_%&%y zaw2bEqEL3W%-O|sMpEWw=pj~#VdTYPwiLk^(k!o=@H$z)tyanV>DTXdyZc9B<#fxk z=o$me4s$2Q_H*B*w+WA^+Z*w>XChJ1UHXkqPeqm=znAWlR2(z z>dsY}$_`y@+33yEvPk*m8$VIf)E&`>_%s81iA=Q1$>!c22 zPi=F$W+s=7w(dG{C)b)R51n_RU^(y#p@)l8*Az-87whVgpozPVKt4q4cd>X8ss6kb z5(XO2jn8s^yc`1UL1$&@qJfcD>-@|)OBGHLywxOSKi@D20`!i6f*K}WRF zzN?TPY);=Q+ZIyzKlROm-kfL+`VD6TzYYGVa$n0`M$#d<2`+-0*K_RUa==}1$%7y( zpIR8%?0c790gO3S2zfgDdA8#n>AUO(Sdp_Sq@o>AG|?a4GSshjq8BZh-J9fF@*~;& zPZM7h_(TAfJO#qBU#J-R*{*>d{O%kmP86T>*ta^9&r|f#7YQZ=04dj?P*WuI!Lo8M zGj+zbaXt}4jlYF+!E@S$8nON^oJY*uFIor*avS~a1vm}&Qo?UQ(C2a>%v~4dp`)V_ zIgE6(F!%LFPJ&j+L8|l*Dp=nD<5ML!37{WfuaPgzsPLA*Tg;vfD0oX!!<0qf!N4e^ zsY{3Wl|hFH9VwKo|I(siKvJV$Yn)T$LRMx4w=nhui>_0mrW=71<92@0c?R@3+q(NZQY&Rrq7So7cr5hJG9k3=iN-9kPsY$$$UK^mc1SIf zdks9tI@w>bmVsSKJ{to%Hi-pU<6l~|7PQh*=sSZ`Gsv@&t0m>Bg}D4K`Nqs@ilY$U zR3R;6)6AVkR;Ab*hhB_HLBTr zCbDBC=7Mw=o0Bm7%yl7#6S1vAZU}dqnfjWE=PUNrk$hn=EPW`1fq`kclDI4ej2}5A zv$u7x)nw@DgRP^77x|E)i?;H}Z_L5lb-lAAtMWk!Acx;!{Yx|qgii3EZGKM9=mizp zc$5JxcYSF7>k}0Z2+`q7Q+xJk=_#wg_`uT@<{i*24_qvSdsK$Z-L;SpV=%ovAs1X? z0nUK)G#XNL*Rl=#T>S>V zfrE&aISl+_Yz8xuXz#A1qPt9(D=_k%{>me~wZ!%7bD-G|Qep5nXUJau>?Np^SE8?n zdx>kFS0(b~ip$bhv!I0urB!rLh*9q-MHKo~{s@n|;s()w^d<>)eG&oY^mXZUS6qeB0bUx6*!l^L0|vy&43vR~R)x1blhv3v!t zk*^#a&b(CZ4*nK@F@qd}*qtkw`Mxr8;f`&A{uy$!AK9RI^%rnt(%Xw-u9Xc`l zJxa-p?4`?gM&NuNsR6V@f$^Lh9lxq)0Y8PDw4?V{%t^{Qk2!7R@v!r067rjVIXN3Q z@}X9typ+;sI+PU~qiok=?#Ew5E|B4K5-6fM7jT5LaglqAhhLR5T|C8^w^0th9}1IC zGF`zaeGBAR4EPUon_1C9jncCOime7CtxsxyO$&0l6u8m4r)|SkFDaNArD_eRcADAT z7ODS~h|mRwtFa0-)`^^H8nZje zuJEW{CLtpSrDy>J6O$-o7Aj=WxF4O&L(vFWqOq#xxTR{FGBHcSSBJDqvg;=v$1p?8A^BXz6VHfIQFWrmZSnzLP-i>daSAV;kltQP84pq8TT=1GM&84| z&r~A=?j%KYTrZYcI0C*9J}S~rGTLx6_A_+;7kB-q0-xS|+%xZUmwcxscn3 z_jcDeU9~Tmz}Mf!f8p=tt0~^C{pOotMmg4j|AA_UmtUD$~)lA7+%a^!u} zNqGcIhnFAOINJ$(%AvHaL@yxnsv%EF4=nv+0Bm8);H(hZc zIt?B~!ij18jYKUkdsUr+ty%;HfV5mVv;)Y z%A3&H3@8!(37W6J7AcIH`S6PTR8_dqChwE6PN{iEBSO@8DIuB`*#L zkMXu%?jwlFEvterr1NYWFi z4MqZoJF!{tH7)}5H2$>AJ#{9h@%aBpIHicGo_DD19E`!|_SY}5BBGr@&KY-<-{Y+$ z=Z90%GTapAMr8Plyzd&UpNZsV$A5LhDB-K+%P{=y`0JmWjCYPqqoa>B62;z0zA-ZN z>?)Hoo0d$pqW?76SB`D1kfWYOcH?};sQ{)$K#_i2RM833=D0W!@ff*;=D;&C@X|vN zMo*++X-@O|>%MaGoOvY|*on_y#HEa&wxcsXV z_5s}laTNvy(Ebp(h!@S(7R!`VBZ-hYu|H#DZ5iQ@0YM zKkK}FAIm`0NzFXvzLcQQ_By|vDREqv$tAo*7AksMm()5v?ft~acXZtd~^|g~* z-FVgifeTb3c~E3&*Y`mCq6XTL->1#=ZZq=eroQkNwsUl6TqpGgBtPvzx{RFI!l27C zo*({@$SW8ZoptbIF8P^CMhzG@wmqv8UZYT#+e$*aMZ_?q z<}a=5_mjmJY0K1ZM^Ay;nCd8aInm#J3s4pGh$y^=x-@bEWpyqqlTnn71P++qrm4Va z1Gf|V)+17LRBGO>e9dY%G>PQ6T8c?I?e^jMg`Rnw8-FG}>Nfe=?vJ@|5PLndpkCFUl}8q`Gm!J35aX%r$A2Fl zT4;{Eg$`LMj>?Pt_<|yYvun!C&&w5yCy}3C`m~zF${SfQo={kzgpoO!eIfG1>m+Y0 z1e_A3R^%7C366WYX+L%}^-~mV(Z(?;dB{@;_vSddVK7LMiO^WW2Lxw6J1X<$56EKZ z@NrV6GK?B5!2`N;Le)Jgx@4E>+dq7hQY2AHxbN6GmC_v+5nVG=?Nq4^FabaYUj5%l zaMQSkEr#G|Gs5))MlP497oqc2TPwMz`j3*&#eN5w!uL|51&TPAYd^jEQ{)bf{N$Y6 zfFlS&lx$t>XwMfbZhxDP>naBE7t~tnB2Dm52|;V+lD^$f(EyB!d%51w5RPPC{lb zz8&8c-~Hc@-kv<6kah|(v(p}Y>zNhg;(1i^&7;X`U@@n-LdQ7=&H(m*YEYaOh%;r=$2EMJc|7` zc;g^o3nLo-9c>}pP05~AZYE(bww%^Hm2`_81Xyz9#Yu8ml~)spO0w{`Q+~NiZaT@U z(vneI4#F$IOQ(F^E$ndc08LemrLgW~!82=f&{tzF8=1RlKmB$S-=krpA!kKoERAHl zx868swT%?7wFJ?Y9qyAm->~RY-R>>yE#{W(#cX>-Y#C;34Rv0`wP3FtoZ?37AC4?9 z$0mSTiZcKrqJB8MXGl$j?%ha{VGFz4@k8NESIow9p5**&nc~}K*>}0eOS|K?JiOpi za&}-!GJFfG8ys=EnN{XGea*;())%A)%1P#a3nO~IRv^LEo>%Mr=-{U0P}8s0-`WC0 zJPWl~G2$Gh0E3=%XKtK|Ss>=D zO{+uh_6?tPphig-?jqTw8rDjzlzG4O)N@v3L#bEj94 zUS=(ZiLWZwN&P++Ecz-7JZ||up1k^1ehYe>k%^;MS*Mx#8NfW9Lv?Pp&c{# zqv0{LNtoC;;zP5W)lKU`#=On;&U%IJYt4QtM_NXQ}jy2Iy%ZvbI-$GFGeVjZ*V1-5o)cGqldmGM>4 zTXM)sx=6q;1!gaCyD!9u`9&3713V3G*LU9^$C_o!^Pqos7e1%IjBc8`K8t zlkB~W`(R+*eEPHWL`RBz)RCm%9I+*Fr!aRsiVyH1r8&kj%J)?hdqNekkI1L^l>2zVz>~J6$36d|-BTxM zHxP#wj?gk^I|N>JUu5}{a8ShdrdLIaF8Q#tM^}u8OTOv>%U@&Y*q><&h%m$v53_nc zvtQD&POjL&m*imO8QLRsY7|}Qn%Am9M18o z=Z&sc6vg~yj!(ZQ-`*n%T8v@*f?vG!oSlX*Mhs38n(Jvp4&CA0_!bh_mCeOLp<~tx zVC;%V$8zsHwh{1Z>B;T{VBV`Nloex=TZI<8z71<5^64fl##H+cwG$&;4wt%A6Y+i8%Zq#UOvQU){$n`J!QFTDHOFM)>+Q1IOEf(roC5B~W4JUfm#YjL8ll7^y-?iP z`5TKzk$ol4w(7{zMvvZn6<_fv9}7O=QUn+dSrqQtb8wOzeQ^&*=<+zYk$GBID{ZN9 z54h?0+#JXRn8v^}h!k{-6l4g+M&?nfw?mif&?a4V73K=$#O&(rT5+J{=o?yB}Ir)Y+5FyAM5F=x*MGzwMps=yau8Lie`g8TsJOfEqkK3wzjp z1X=G!9X^xj7vf3O-D{D>8c8z!qA6Sp-e$sBvB&k5ZHY#rOF3rL@wf+@>tM(c&%+Iu z_7m;V2#1(e`zsH^eV2GI#>3O9X9sb{?{E@*-60k*&3vzv{6@Uil8%La=Nq9Rr((Ce ze&x$^Zzhk};mZnF=f!Ul&yL5q!(lJl*4!-|a9_j6wtmJY(eoNqVn-?hz{94Ie2hSS18Hs3FY5+JAln5XDSqbyq zNs@w{c$QoS@+a)KJlR*~SQa9TU?tZ&pS7)$`b-X5&0Smlp6OBVvi1XHkCnjCG3u2z z3`4~R_3uF*mGW_f?fR_B=KwIAoNkDmXS8;o>r3D1jh)}xRmuK0llPhI#wY<=K1^mJ zcd9UwgEvYK`ozP$6!z|z_2vtD=I|7LL+Q(Q$ZND#3)O&Obqtv(N)JQXdG=(niZV*o zoTr}pYz<0rS2D?c!?ltP*R!ex5Q(Ni{Q8wASt8LBnl%m%46o;2=k}=QScU2*jA(BA z!_P)3Stsxdzw=cEj|JQ4)pD-nJMUQ$hw8{J- z_-(QQ}^#!TlK7DnE>|U z`aG_~Uzdx+P361AzpxHSlO0iwyn~xLt?5ltAJ;HyQ8vlRHBF~Rz2pWTZX3Wf9fG@+ zK9S(xJ!^UMm@;o}k$?_^%`9Om-Wqj#McBD+UGY%B_I@ifqyrn0A(a}MNu@T&A`MPrf5E- zp$}7*ZML|VJ-UuT-w4%D-;Un?vn8gaWZ0^u41XT~wku5CB~OIwSEFZjD$3R&!ND_E z*^XE`@Vl})$@rx4yJf?kD5rJ8ePjiq?MdJHPE20V?LCqzU(xl(6HORhzTA_Yh(wCq&ERz{0`-i zEXwCJelu(_B5PzpQ&I7jyrUt^6;cXY3hzWU;YPZ3_Ww1@gWKrp@eYrklu|?-uXY|X zA9X5l!cN&#AZ<1K{gq5ZEkLIyJ=7ATySbmI%nn~S$@4DfzIR1IcG+iAzI^x2!*vw0 zbH`TBO^?^M@fk26MnEexawdzS%xC-eQ5d-8=F?zaN{n{Lcs-_vmao+K0)_i!sGn`s6>xTe=D7g zM=?1H+sNHlkAk6bZWw{8`oJt-B<(s1e$<@olEkr29qt?wW`RhY@&TfF?tL)<; zW()BgJ*uNSto4v!Zc4)wpZmiCW^ZCY|D&R}Fff23+mldlo-Z~7Z^k1Wn*@VBD*Jkj z=Yx9?wc+4N0Zru&2a5uz{q{So@%Py)b=vGr>~VY4IFD+a_ce;q%cDlW)7!$OWzT<{ zy={gbXcD{~ZRS73!q20c^}Qds?vS74(4xe4Dx03e z4rHU?%{*${@JSJ-j?CT$Uuqj(N=T{TU4-cLQTi>}xnuAt`i~u72)cYQUM<)OBpF^i zM)3FpI%W^e)y{W>2@eu~3t)!;Uk7Pk4?Q?1TNGcy`N9{h!;1)XMtFn)9iF%k?kuo_ zeLk5v-4pRcJYV^tyrEf!{`AAv;k^Cm9bpA8`>1an(bqe`&?oo`kNP(Bbuc$AYkM{l zZx^?b^DU-~T&3$|PS@6e@LOVX^9vuzk1FYJGgk2b0Z>Z;0v8Ju000080IopiK0{>y z#G<1B069wo04D$u000000096X0Jebu0001NVPtuBVQp}7Wpi^aWMyVyb!>DfGB7bQ zEigANFgGbJPg5>*cyv=l1OTi60031~1po&Kp%qS0O9ci1000010097I0001FqyPW_ E0J|a8F8}}l diff --git a/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log b/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log deleted file mode 100644 index 28ca448e05..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log +++ /dev/null @@ -1,13 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path irc -#open 2013-06-07-19-08-42 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user command value addl dcc_file_name dcc_file_size dcc_mime_type extraction_file -#types time string addr port addr port string string string string string string count string string -1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 - - NICK bloed - - - - - -1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - - -1311189174.474127 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje JOIN #easymovies (empty) - - - - -1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje DCC #easymovies (empty) ladyvampress-default(2011-07-07)-OS.zip 42208 application/zip irc-dcc-item-A3OSdqG9zvk.dat -#close 2013-06-07-19-08-42 diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log b/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log index ba16578dfb..b56b8afab6 100644 --- a/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log +++ b/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path smtp -#open 2009-10-05-06-06-12 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth helo mailfrom rcptto date from to reply_to msg_id in_reply_to subject x_originating_ip first_received second_received last_reply path user_agent -#types time string addr port addr port count string string table[string] string string table[string] string string string string addr string string string vector[addr] string -1254722768.219663 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 GP Mon, 5 Oct 2009 11:36:07 +0530 "Gurpartap Singh" - <000301ca4581$ef9e57f0$cedb07d0$@in> - SMTP - - - 250 OK id=1Mugho-0003Dg-Un 74.53.140.153,10.10.1.4 Microsoft Office Outlook 12.0 -#close 2009-10-05-06-06-16 +#open 2013-07-25-19-52-35 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth helo mailfrom rcptto date from to reply_to msg_id in_reply_to subject x_originating_ip first_received second_received last_reply path user_agent fuids +#types time string addr port addr port count string string table[string] string string table[string] string string string string addr string string string vector[addr] string vector[string] +1254722768.219663 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 GP Mon, 5 Oct 2009 11:36:07 +0530 "Gurpartap Singh" - <000301ca4581$ef9e57f0$cedb07d0$@in> - SMTP - - - 250 OK id=1Mugho-0003Dg-Un 74.53.140.153,10.10.1.4 Microsoft Office Outlook 12.0 A1IqG95k9Tk,VUcocHqaWva,JJPHrvZaGJj +#close 2013-07-25-19-52-35 diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/extractions b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/extractions deleted file mode 100644 index 45d776a8e9..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/extractions +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - k6, k6-2, k6-3, athlon, athlon-tbird, athlon-4, athlon-xp, athlon-mp, winchip-c6, winchip2, k8, c3 and c3-2) - "windows.h", he gets all the WinAPI! If he adds "wx/wx.h", he gets all of - #included directly or indirectly)! - (available when right-clicking the class-browser - (still can be overriden by using "-c" command line parameter). - (the same filename as the project's but with extension ".layout"). If you - - Enable use of processor specific built-in functions (mmmx, sse, sse2, pni, 3dnow) - - Generate instructions for a specific machine (i386, i486, i586, i686, pentium, pentium-mmx, pentiumpro, pentium2, pentium3, pentium4, 20 - - Strip executable - -c - 20 - Instead open the file in an already launched Dev-C++. - It used to be a checkbox, allowing only two states (on or off), but there is - The user can define this in the class browser's context menu under "View mode". - Well, it adds caching to code-completion. Depending on the cache size, - a third relevant option now: "Project classes" so it didn't fit the purpose... - and selecting "View mode"). - cause of many errors (although it should be fixed by now), we are giving the - class inheritance and visibility (shows items only from files - code-completion and the user has all the commands (belonging to the files - compiler: -D__DEBUG__ - displayed in the editor when the mouse moves over a word. Since this was the - have your project under CVS control, you ''ll know why this had to happen... - he added in the cache) at his fingertips. If, for example, the user adds - include files can now be generated. - information definitions - it in the private resource) - its counterpart are highlighted - resource) - the program may take a bit longer to start-up, but provides very fast - the requested CVS action - then we even get a stack trace in the bug report! - user the option to disable this feature. - wxWindows! You get the picture... -* "Build priority" per-unit -* "Compile as C++" per-unit -* "Default" button in Compiler Options is back -* "Include file in compilation process" per-unit -* "Include file in linking process" per-unit -* Added "Add Library" button in Project Options -* Added "Classes" toolbar -* Added "External programs" in Tools/Environment Options (for units "Open with") -* Added "Files" tab in CVS form to allow selection of more than one file for -* Added "Open with" in project units context menu -* Added "Tip of the day" system. -* Added *working* function arguments hint -* Added CVS "login" and "logout" commands -* Added CVS commands "Add" and "Remove" -* Added ExceptionsAnalyzer. If the devcpp.map file is in the devcpp.exe directory -* Added bracket highlighting. When the caret is on a bracket, that bracket and -* Added configuration option for "Templates Directory" in "Environment Options" -* Added display of project filename, project output and a summary of the project files in Project Options General tab. -* Added doxygen-style comments in NewClass, NewMemberFunction and NewMemberVariable wizards -* Added file's date/time stamp in File/Properties window -* Added new WebUpdate module (inactive temporarily). -* Added new code for code-completion caching of files (disabled - work in progress). -* Added new compiler/linker options: 20 -* Added new file menu entry: Save Project As -* Added new option in class-browser: Use colors -* Added possibility to include in a Template the Project's directories (include, libs and ressources) -* Added support for GCC > 3.2 -* Added support for macros in the "default source code" (Tools/Editor Options/Code) -* Added support for the "interface" keyword -* Added support for the '::' member access operator in code-completion -* Added the possibility to modify the value of a variable during debugging (right click on a watch variable and select "Modify value") -* Added the possibility to specify an include directory for the code completion cache to be created at Dev-C++ first startup -* Added two new macros: and -* Allow customizing of per-unit compile command in projects -* Allow user to specify an alternate configuration file in Environment Options 20 -* Backtrace in debugging -* Big speed up in function parameters listing while editing -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug fixes -* Bug-fix for double quotes in devcpp.cfg file read by vUpdate -* CPU Window (still in development) -* CVS support -* Caching of result set of code-completion for speed-up. -* Changed position of compiler/linker parameters in Project Options. -* Changed tint of Class browser pictures colors to match the New Look style -* Class-parser speed-up (50% to 85% improvement timed!!!) -* Code-completion updates -* Compiler set per-project -* Compiler settings per-project -* Compiling progress window -* Current windows listing in Window menu -* Debug variable browser -* Debug variables are now resent during next debug session -* Dev-C++ now traps access violation of your programs (and of itself too ;) -* During Dev-C++ First Time COnfiguration window, users can now choose between using or not class browser and code completion features. -* Each project creates a _private.h file containing version -* Editor colors are initialized properly on Dev-C++ first-run -* Environment options : "Show progress window" and "Auto-close progress window" -* Error messages parsing improved -* Fixed many class browser bugs, including some that had to do with class folders. -* Fixed pre-compilation dependency checks to work correctly -* Fixed the "compiler-dirs-with-spaces" bug that crept-in in 4.9.7.0 -* Fixed the dreaded "Clock skew detected" compiler warning! -* Folders in Project and Class Browser -* Implemented "compiler sets" infrastructure to switch between different compilers easily (e.g. gcc-2.95 and gcc-3.2) -* Implemented new compiler settings framework -* Implemented search in help files for the word at cursor (context sensitive help) -* Implemented the "File/Export/Project to HTML" function. -* Improved Indent/Unindent and Remove Comment -* Improved WebUpdate module -* Improved automatic indent -* Improved code completion cache -* Improved editor -* Improved help file -* Improved installer -* Lots of bug fixes. -* Lots of bugfixes -* MSVC import now creates the folders structure of the original VC project -* Made whole bottom report control floating instead of only debug output. -* Makefile can now be customized. -* Many bug fixes -* Many bug fixes -* Many bug fixes -* Many bug fixes -* Many bug fixes -* Many bug fixes -* Many bug fixes -* Many code-completion updates. Now takes into account context, -* Modified the behaviour of the -c param : 20 -* Multi-select files in project-view (when "double-click to open" is configured in Environment Settings) -* Necessary UI changes in Project Options -* Nested folders in project view -* New "Abort compilation" button -* New WebUpdater module. -* New class browser option: "Show inherited members" -* New code tooltip display -* New debug feature for DLLs: attach to a running process -* New environment options : "watch variable under mouse" and "Report watch errors" -* New feature: compile current file only -* New option "Execution/Parameters" (and "Debug/Parameters"). -* New option in Editor Options (code-completion): Use code-completion cache. -* New option in Editor Options: Show editor hints. User can disable the hints -* New project option: Use custom Makefile. 20 -* New splash screen and association icons -* Now checks for vRoach existance when sending a crash report -* On Dev-C++ first time configuration dialog, a code completion cache of all the standard 20 -* Other bug fixes -* Possibility of changing compilers and tools filename. -* Printing settings are now saved -* Profiling support -* Project manager and debugging window (in Debug tab) can now be trasnformed into floating windows. -* Project version info (creates the relevant VERSIONINFO struct in the private -* Removed "Only show classes from current file" option in class browser settings. -* Resource errors are now reported in the Resource sheet -* Resource files are treated as ordinary files now -* Run to cursor -* Saving of custom syntax parameter group -* Send custom commands to GDB -* Separated C++ compiler options from C compiler options in Makefile (see bug report #654744) -* Separated C++ include dirs from C include dirs in Makefile (see bug report #654744) -* Separated layout info from project file. It is now kept in a different file -* Support XP Themes (creates the CommonControls 6.0 manifest file and includes -* Support for latest Mingw compiler system builds -* ToDo list -* Under NT, 2000 and XP, user application data directory will be used to store config files (i.e : C:\Documents and Settings\Username\Local Settings\Application Data) -* Updates in "Project Options/Files" code -* Watched Variables not in correct context are now kept and updated when it is needed -* WebUpdate should now report installation problems from PackMan -* WebUpdate will now backup downloaded DevPaks in Dev-C++\Packages directory, and Dev-C++ executable in devcpp.exe.BACKUP -* When adding debugging symbols on request, remove "-s" option from linker -* When compiling the current file only, no dependency checks are performed -* When compiling with debugging symbols, an extra definition is passed to the -* When creating a DLL, the created static lib respects now the project-defined output directory -* When running a source file in explorer, don't spawn new instance. -* Window list (in Window menu) -* XP Theme support -* added ENTER key for opening file in project browser, DEL to delete from the project. -* back to gcc 2.95.3 -* bug fixes -* bug fixes -* new update/packages checker (vUpdate) -* support for DLL application hosting, for debugging and executing DLLs under Dev-C++. -* ~300% Speed-up in class parser -Find the attachment -GPS -Hello -I send u smtp pcap file -Version 4.9.4.1 (5.0 beta 4.1): -Version 4.9.5.0 (5.0 beta 5): -Version 4.9.5.1 -Version 4.9.5.2 -Version 4.9.5.3 -Version 4.9.5.4 -Version 4.9.5.5 -Version 4.9.6.5 -Version 4.9.6.6 -Version 4.9.6.7 -Version 4.9.6.8 -Version 4.9.6.9 -Version 4.9.7.0 -Version 4.9.7.1 -Version 4.9.7.2 -Version 4.9.7.3 -Version 4.9.7.4 -Version 4.9.7.5 -Version 4.9.7.6 -Version 4.9.7.7 -Version 4.9.7.8 -Version 4.9.7.9 -Version 4.9.8.0 -Version 4.9.8.1 -Version 4.9.8.2 -Version 4.9.8.3 -Version 4.9.8.4 -Version 4.9.8.5 -Version 4.9.8.7 -Version 4.9.8.9 -Version 4.9.9.0 -Version 4.9.9.1 -version 4.9.6.1 -version 4.9.6.2 -version 4.9.6.3 -version 4.9.6.4 diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/filecount b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/filecount deleted file mode 100644 index 0cfbf08886..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/filecount +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log deleted file mode 100644 index 865694e8a2..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log +++ /dev/null @@ -1,12 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path smtp_entities -#open 2013-06-07-19-32-56 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth filename content_len mime_type md5 extraction_file excerpt -#types time string addr port addr port count string count string string string string -1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 79 text/plain - smtp-entity-mR3f2AAKo11.dat (empty) -1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 1918 text/html - - (empty) -1254722770.692804 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 NEWS.txt 10823 text/plain - smtp-entity-ZNp0KBSLByc.dat (empty) -#close 2013-06-07-19-32-56 diff --git a/testing/btest/Baseline/scripts.policy.frameworks.software.vulnerable/notice.log b/testing/btest/Baseline/scripts.policy.frameworks.software.vulnerable/notice.log index f2cf09cab6..54b04aafae 100644 --- a/testing/btest/Baseline/scripts.policy.frameworks.software.vulnerable/notice.log +++ b/testing/btest/Baseline/scripts.policy.frameworks.software.vulnerable/notice.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path notice -#open 2013-04-28-22-36-26 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude -#types time string addr port addr port enum enum string string addr addr port count string table[enum] interval bool string string string double double -1367188586.649122 - - - - - - Software::Vulnerable_Version 1.2.3.4 is running Java 1.7.0.15 which is vulnerable. Java 1.7.0.15 1.2.3.4 - - - bro Notice::ACTION_LOG 3600.000000 F - - - - - -1367188586.649122 - - - - - - Software::Vulnerable_Version 1.2.3.5 is running Java 1.6.0.43 which is vulnerable. Java 1.6.0.43 1.2.3.5 - - - bro Notice::ACTION_LOG 3600.000000 F - - - - - -#close 2013-04-28-22-36-26 +#open 2013-07-25-19-54-45 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fuid file_mime_type file_desc proto note msg sub src dst p n peer_descr actions suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude +#types time string addr port addr port string string string enum enum string string addr addr port count string table[enum] interval bool string string string double double +1374782085.726121 - - - - - - - - - Software::Vulnerable_Version 1.2.3.4 is running Java 1.7.0.15 which is vulnerable. Java 1.7.0.15 1.2.3.4 - - - bro Notice::ACTION_LOG 3600.000000 F - - - - - +1374782085.726121 - - - - - - - - - Software::Vulnerable_Version 1.2.3.5 is running Java 1.6.0.43 which is vulnerable. Java 1.6.0.43 1.2.3.5 - - - bro Notice::ACTION_LOG 3600.000000 F - - - - - +#close 2013-07-25-19-54-45 diff --git a/testing/btest/istate/events-ssl.bro b/testing/btest/istate/events-ssl.bro index 249ebc3754..d227417c15 100644 --- a/testing/btest/istate/events-ssl.bro +++ b/testing/btest/istate/events-ssl.bro @@ -41,16 +41,25 @@ redef ssl_ca_certificate = "../ca_cert.pem"; redef ssl_private_key = "../bro.pem"; redef ssl_passphrase = "my-password"; +# Make sure the HTTP connection really gets out. +# (We still miss one final connection event because we shutdown before +# it gets propagated but that's ok.) +redef tcp_close_delay = 0secs; + # File-analysis fields in http.log won't get set on receiver side correctly, # one problem is with the way serialization may send a unique ID in place # of a full value and expect the remote side to associate that unique ID with -# a value it received at an earlier time. So sometimes modifications the sender -# makes to the value aren't seen on the receiver (in this case, the mime_type -# field). -event file_new(f: fa_file) &priority=10 +# a value it received at an earlier time. So sometimes modifications the sender# makes to the value aren't seen on the receiver. +function myfh(c: connection, is_orig: bool): string { - delete f$mime_type; - FileAnalysis::stop(f); + return ""; + } + +event bro_init() + { + # Ignore all http files. + Files::register_protocol(Analyzer::ANALYZER_HTTP, + [$get_file_handle = myfh]); } @TEST-END-FILE diff --git a/testing/btest/istate/events.bro b/testing/btest/istate/events.bro index 21f46cf4b3..1edf14fee7 100644 --- a/testing/btest/istate/events.bro +++ b/testing/btest/istate/events.bro @@ -39,12 +39,17 @@ redef tcp_close_delay = 0secs; # File-analysis fields in http.log won't get set on receiver side correctly, # one problem is with the way serialization may send a unique ID in place # of a full value and expect the remote side to associate that unique ID with -# a value it received at an earlier time. So sometimes modifications the sender# makes to the value aren't seen on the receiver (in this case, the mime_type -# field). -event file_new(f: fa_file) &priority=10 +# a value it received at an earlier time. So sometimes modifications the sender# makes to the value aren't seen on the receiver. +function myfh(c: connection, is_orig: bool): string { - delete f$mime_type; - FileAnalysis::stop(f); + return ""; + } + +event bro_init() + { + # Ignore all http files. + Files::register_protocol(Analyzer::ANALYZER_HTTP, + [$get_file_handle = myfh]); } @TEST-END-FILE diff --git a/testing/btest/scripts/base/frameworks/file-analysis/bifs/remove_action.bro b/testing/btest/scripts/base/frameworks/file-analysis/bifs/remove_action.bro index e31abe5ea3..a3704618bd 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/bifs/remove_action.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/bifs/remove_action.bro @@ -13,6 +13,6 @@ event file_new(f: fa_file) &priority=-10 for ( tag in test_file_analyzers ) Files::remove_analyzer(f, tag); local filename = test_get_file_name(f); - Files::remove_analyzer(f, [$tag=Files::ANALYZER_EXTRACT, - $extract_filename=filename]); + Files::remove_analyzer(f, Files::ANALYZER_EXTRACT, + [$extract_filename=filename]); } diff --git a/testing/btest/scripts/base/frameworks/file-analysis/irc.bro b/testing/btest/scripts/base/frameworks/file-analysis/irc.bro index 2b93a59a8f..9fd8e06613 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/irc.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/irc.bro @@ -4,7 +4,17 @@ redef test_file_analysis_source = "IRC_DATA"; -redef test_get_file_name = function(f: fa_file): string +global first: bool = T; + +function myfile(f: fa_file): string { - return "thefile"; - }; + if ( first ) + { + first = F; + return "thefile"; + } + else + return ""; + } + +redef test_get_file_name = myfile; diff --git a/testing/btest/scripts/base/frameworks/file-analysis/logging.bro b/testing/btest/scripts/base/frameworks/file-analysis/logging.bro index 9792017962..1d1f5fd721 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/logging.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/logging.bro @@ -1,5 +1,5 @@ # @TEST-EXEC: bro -r $TRACES/http/get.trace $SCRIPTS/file-analysis-test.bro %INPUT -# @TEST-EXEC: btest-diff file_analysis.log +# @TEST-EXEC: btest-diff files.log redef test_file_analysis_source = "HTTP"; diff --git a/testing/btest/scripts/base/protocols/ftp/ftp-extract.bro b/testing/btest/scripts/base/protocols/ftp/ftp-extract.bro deleted file mode 100644 index 8cbacdbf6f..0000000000 --- a/testing/btest/scripts/base/protocols/ftp/ftp-extract.bro +++ /dev/null @@ -1,10 +0,0 @@ -# This tests FTP file extraction. -# -# @TEST-EXEC: bro -r $TRACES/ftp/ipv4.trace %INPUT -# @TEST-EXEC: btest-diff conn.log -# @TEST-EXEC: btest-diff ftp.log -# @TEST-EXEC: cat ftp-item-*.dat | sort > extractions -# @TEST-EXEC: btest-diff extractions - -redef FTP::logged_commands += {"LIST"}; -redef FTP::extract_file_types=/.*/; diff --git a/testing/btest/scripts/base/protocols/http/http-extract-files.bro b/testing/btest/scripts/base/protocols/http/http-extract-files.bro deleted file mode 100644 index 6156009821..0000000000 --- a/testing/btest/scripts/base/protocols/http/http-extract-files.bro +++ /dev/null @@ -1,6 +0,0 @@ -# @TEST-EXEC: bro -C -r $TRACES/web.trace %INPUT -# @TEST-EXEC: btest-diff http.log -# @TEST-EXEC: mv http-item-*.dat http-item.dat -# @TEST-EXEC: btest-diff http-item.dat - -redef HTTP::extract_file_types += /text\/html/; diff --git a/testing/btest/scripts/base/protocols/http/http-mime-and-md5.bro b/testing/btest/scripts/base/protocols/http/http-mime-and-md5.bro deleted file mode 100644 index b35e491b4d..0000000000 --- a/testing/btest/scripts/base/protocols/http/http-mime-and-md5.bro +++ /dev/null @@ -1,6 +0,0 @@ -# This tests md5 calculation for a specified mime type. - -# @TEST-EXEC: bro -r $TRACES/http/pipelined-requests.trace %INPUT > output -# @TEST-EXEC: btest-diff http.log - -redef HTTP::generate_md5 += /image\/png/; diff --git a/testing/btest/scripts/base/protocols/http/multipart-extract.bro b/testing/btest/scripts/base/protocols/http/multipart-extract.bro index c2789750a3..a919a844b2 100644 --- a/testing/btest/scripts/base/protocols/http/multipart-extract.bro +++ b/testing/btest/scripts/base/protocols/http/multipart-extract.bro @@ -1,5 +1,9 @@ # @TEST-EXEC: bro -C -r $TRACES/http/multipart.trace %INPUT # @TEST-EXEC: btest-diff http.log -# @TEST-EXEC: cat http-item-* | sort > extractions +# @TEST-EXEC: cat extract_files/http-item-* | sort > extractions -redef HTTP::extract_file_types += /.*/; +event file_new(f: fa_file) + { + local fname = fmt("http-item-%s", f$id); + Files::add_analyzer(f, Files::ANALYZER_EXTRACT, [$extract_filename=fname]); + } diff --git a/testing/btest/scripts/base/protocols/irc/dcc-extract.test b/testing/btest/scripts/base/protocols/irc/dcc-extract.test deleted file mode 100644 index cbfc6890da..0000000000 --- a/testing/btest/scripts/base/protocols/irc/dcc-extract.test +++ /dev/null @@ -1,11 +0,0 @@ -# This tests that the contents of a DCC transfer negotiated with IRC can be -# correctly extracted. - -# @TEST-EXEC: bro -r $TRACES/irc-dcc-send.trace %INPUT -# @TEST-EXEC: btest-diff irc.log -# @TEST-EXEC: mv irc-dcc-item-*.dat irc-dcc-item.dat -# @TEST-EXEC: btest-diff irc-dcc-item.dat -# @TEST-EXEC: bro -r $TRACES/irc-dcc-send.trace %INPUT IRC::extraction_prefix="test" -# @TEST-EXEC: test -e test-*.dat - -redef IRC::extract_file_types=/.*/; diff --git a/testing/btest/scripts/base/protocols/smtp/mime-extract.test b/testing/btest/scripts/base/protocols/smtp/mime-extract.test deleted file mode 100644 index 0caa5d530c..0000000000 --- a/testing/btest/scripts/base/protocols/smtp/mime-extract.test +++ /dev/null @@ -1,11 +0,0 @@ -# @TEST-EXEC: bro -r $TRACES/smtp.trace %INPUT -# @TEST-EXEC: btest-diff smtp_entities.log -# @TEST-EXEC: cat smtp-entity-*.dat | sort > extractions -# @TEST-EXEC: btest-diff extractions -# @TEST-EXEC: bro -r $TRACES/smtp.trace %INPUT SMTP::extraction_prefix="test" -# @TEST-EXEC: cnt=0 && for f in test-*.dat; do cnt=$((cnt+1)); done && echo $cnt >filecount -# @TEST-EXEC: btest-diff filecount - -@load base/protocols/smtp - -redef SMTP::extract_file_types=/text\/plain/; diff --git a/testing/external/subdir-btest.cfg b/testing/external/subdir-btest.cfg index b631ba2457..31fce50adc 100644 --- a/testing/external/subdir-btest.cfg +++ b/testing/external/subdir-btest.cfg @@ -7,7 +7,7 @@ IgnoreFiles = *.tmp *.swp #* *.trace .gitignore *.skeleton [environment] BROPATH=`bash -c %(testbase)s/../../../build/bro-path-dev`:%(testbase)s/../scripts -BROMAGIC=%(testbase)s/../../../magic +BROMAGIC=%(testbase)s/../../magic/database BRO_SEED_FILE=%(testbase)s/../random.seed TZ=UTC LC_ALL=C diff --git a/testing/scripts/file-analysis-test.bro b/testing/scripts/file-analysis-test.bro index 8fe78b218e..d84fadae5c 100644 --- a/testing/scripts/file-analysis-test.bro +++ b/testing/scripts/file-analysis-test.bro @@ -1,3 +1,7 @@ +@load base/files/extract +@load base/files/hash + +redef FileExtract::prefix = "./"; global test_file_analysis_source: string = "" &redef; From fb029617a4a8695f5ffffa75721ff978eed58d35 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 26 Jul 2013 16:38:18 -0400 Subject: [PATCH 144/881] Update the last two btest FAF tests. - Small changes were done to the ftp log. --- .../ftp.log | 20 ++++++++--------- .../ftp.log | 22 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log index afa4c97830..b75d6955ba 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log @@ -3,13 +3,13 @@ #empty_field (empty) #unset_field - #path ftp -#open 2013-04-12-16-32-25 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg tags data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p extraction_file -#types time string addr port addr port string string string string string count count string table[string] bool addr addr port string -1329843175.680248 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,90) (empty) T 141.142.220.235 199.233.217.249 56666 - -1329843179.815947 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,91) (empty) T 141.142.220.235 199.233.217.249 56667 - -1329843179.926563 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. (empty) - - - - - -1329843194.040188 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,131,46 - - 200 PORT command successful. (empty) F 199.233.217.249 141.142.220.235 33582 - -1329843197.672179 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,147,203 - - 200 PORT command successful. (empty) F 199.233.217.249 141.142.220.235 37835 - -1329843197.727769 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. (empty) - - - - - -#close 2013-04-12-16-32-25 +#open 2013-07-26-20-37-01 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p fuid +#types time string addr port addr port string string string string string count count string bool addr addr port string +1329843175.680248 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,90) T 141.142.220.235 199.233.217.249 56666 - +1329843179.815947 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,91) T 141.142.220.235 199.233.217.249 56667 - +1329843179.926563 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR robots.txt text/plain 77 226 Transfer complete. - - - - 4VAnSiNGSQh +1329843194.040188 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,131,46 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 33582 4VAnSiNGSQh +1329843197.672179 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,147,203 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 37835 4VAnSiNGSQh +1329843197.727769 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR robots.txt text/plain 77 226 Transfer complete. - - - - aJg8mtdsS86 +#close 2013-07-26-20-37-01 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log index 85207806c4..4177c52e1f 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log @@ -3,14 +3,14 @@ #empty_field (empty) #unset_field - #path ftp -#open 2013-04-12-16-32-25 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg tags data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p extraction_file -#types time string addr port addr port string string string string string count count string table[string] bool addr addr port string -1329327783.207785 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57086|) (empty) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57086 - -1329327786.415755 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57087|) (empty) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57087 - -1329327787.180814 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57088|) (empty) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57088 - -1329327787.396984 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - 77 226 Transfer complete. (empty) - - - - - -1329327795.355248 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49189| - - 200 EPRT command successful. (empty) F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49189 - -1329327795.463946 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - 77 226 Transfer complete. (empty) - - - - - -1329327799.799327 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49190| - - 200 EPRT command successful. (empty) F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49190 - -#close 2013-04-12-16-32-25 +#open 2013-07-26-20-37-22 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p fuid +#types time string addr port addr port string string string string string count count string bool addr addr port string +1329327783.207785 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57086|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57086 - +1329327786.415755 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57087|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57087 - +1329327787.180814 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57088|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57088 - +1329327787.396984 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR robots.txt - 77 226 Transfer complete. - - - - - +1329327795.355248 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49189| - - 200 EPRT command successful. F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49189 4YhNtGvCehl +1329327795.463946 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR robots.txt - 77 226 Transfer complete. - - - - 4YhNtGvCehl +1329327799.799327 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49190| - - 200 EPRT command successful. F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49190 4YhNtGvCehl +#close 2013-07-26-20-37-22 From 1238e5bcf2b6b05471a2b0599c75f9a9e6a4a5ed Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 26 Jul 2013 21:50:19 -0400 Subject: [PATCH 145/881] Undoing the FTP tests I updated earlier. - Fixed the external tests btest config too. --- scripts/base/protocols/ftp/main.bro | 8 +++++++- .../Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log | 8 ++++---- .../Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log | 8 ++++---- testing/external/subdir-btest.cfg | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/scripts/base/protocols/ftp/main.bro b/scripts/base/protocols/ftp/main.bro index f525c7792b..c9549a14ec 100644 --- a/scripts/base/protocols/ftp/main.bro +++ b/scripts/base/protocols/ftp/main.bro @@ -102,6 +102,8 @@ export { global log_ftp: event(rec: Info); } +@load ./utils + # Add the state tracking information variable to the connection record redef record connection += { ftp: Info &optional; @@ -171,7 +173,11 @@ function ftp_message(s: Info) { s$ts=s$cmdarg$ts; s$command=s$cmdarg$cmd; - s$arg=s$cmdarg$arg; + + s$arg = s$cmdarg$arg; + if ( s$cmdarg$cmd in file_cmds ) + s$arg = build_url_ftp(s); + if ( s$arg == "" ) delete s$arg; diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log index b75d6955ba..4cc6d67761 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log @@ -3,13 +3,13 @@ #empty_field (empty) #unset_field - #path ftp -#open 2013-07-26-20-37-01 +#open 2013-07-27-01-49-02 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p fuid #types time string addr port addr port string string string string string count count string bool addr addr port string 1329843175.680248 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,90) T 141.142.220.235 199.233.217.249 56666 - 1329843179.815947 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,91) T 141.142.220.235 199.233.217.249 56667 - -1329843179.926563 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR robots.txt text/plain 77 226 Transfer complete. - - - - 4VAnSiNGSQh +1329843179.926563 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. - - - - 4VAnSiNGSQh 1329843194.040188 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,131,46 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 33582 4VAnSiNGSQh 1329843197.672179 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,147,203 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 37835 4VAnSiNGSQh -1329843197.727769 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR robots.txt text/plain 77 226 Transfer complete. - - - - aJg8mtdsS86 -#close 2013-07-26-20-37-01 +1329843197.727769 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. - - - - aJg8mtdsS86 +#close 2013-07-27-01-49-02 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log index 4177c52e1f..d6f57bcf45 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log @@ -3,14 +3,14 @@ #empty_field (empty) #unset_field - #path ftp -#open 2013-07-26-20-37-22 +#open 2013-07-27-01-49-13 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p fuid #types time string addr port addr port string string string string string count count string bool addr addr port string 1329327783.207785 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57086|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57086 - 1329327786.415755 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57087|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57087 - 1329327787.180814 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57088|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57088 - -1329327787.396984 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR robots.txt - 77 226 Transfer complete. - - - - - +1329327787.396984 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - 77 226 Transfer complete. - - - - - 1329327795.355248 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49189| - - 200 EPRT command successful. F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49189 4YhNtGvCehl -1329327795.463946 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR robots.txt - 77 226 Transfer complete. - - - - 4YhNtGvCehl +1329327795.463946 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - 77 226 Transfer complete. - - - - 4YhNtGvCehl 1329327799.799327 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49190| - - 200 EPRT command successful. F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49190 4YhNtGvCehl -#close 2013-07-26-20-37-22 +#close 2013-07-27-01-49-13 diff --git a/testing/external/subdir-btest.cfg b/testing/external/subdir-btest.cfg index 31fce50adc..fb5873418a 100644 --- a/testing/external/subdir-btest.cfg +++ b/testing/external/subdir-btest.cfg @@ -7,7 +7,7 @@ IgnoreFiles = *.tmp *.swp #* *.trace .gitignore *.skeleton [environment] BROPATH=`bash -c %(testbase)s/../../../build/bro-path-dev`:%(testbase)s/../scripts -BROMAGIC=%(testbase)s/../../magic/database +BROMAGIC=%(testbase)s/../../../magic/database BRO_SEED_FILE=%(testbase)s/../random.seed TZ=UTC LC_ALL=C From 32f1c736f7d425b0d03deb93d5d057075737c3c1 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 29 Jul 2013 16:40:16 -0400 Subject: [PATCH 146/881] Some script reorg and a new intel extension script. - policy/frameworks/intel/seen is the new location for the scripts that push data into the intel framework for checking. - The new policy/frameworks/intel/do_notice script adds an example mechanism for data driven notices. --- doc/intel.rst | 4 +- doc/scripts/DocSourcesList.cmake | 19 ++++---- scripts/base/frameworks/intel/main.bro | 3 -- scripts/policy/frameworks/intel/do_notice.bro | 44 +++++++++++++++++++ .../frameworks/intel/{ => seen}/__load__.bro | 0 .../intel/{ => seen}/conn-established.bro | 0 .../frameworks/intel/{ => seen}/dns.bro | 0 .../intel/{ => seen}/http-host-header.bro | 0 .../frameworks/intel/{ => seen}/http-url.bro | 0 .../intel/{ => seen}/http-user-agents.bro | 0 .../intel/{ => seen}/smtp-url-extraction.bro | 0 .../frameworks/intel/{ => seen}/smtp.bro | 0 .../frameworks/intel/{ => seen}/ssl.bro | 0 .../intel/{ => seen}/where-locations.bro | 0 scripts/test-all-policy.bro | 21 ++++----- 15 files changed, 67 insertions(+), 24 deletions(-) create mode 100644 scripts/policy/frameworks/intel/do_notice.bro rename scripts/policy/frameworks/intel/{ => seen}/__load__.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/conn-established.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/dns.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/http-host-header.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/http-url.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/http-user-agents.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/smtp-url-extraction.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/smtp.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/ssl.bro (100%) rename scripts/policy/frameworks/intel/{ => seen}/where-locations.bro (100%) diff --git a/doc/intel.rst b/doc/intel.rst index 2a59a98974..787524a417 100644 --- a/doc/intel.rst +++ b/doc/intel.rst @@ -27,7 +27,7 @@ Quick Start Load the package of scripts that sends data into the Intelligence Framework to be checked by loading this script in local.bro:: - @load policy/frameworks/intel + @load policy/frameworks/intel/seen Refer to the "Loading Intelligence" section below to see the format for Intelligence Framework text files, then load those text files with @@ -100,7 +100,7 @@ The full package of hook scripts that Bro ships with for sending this "seen" data into the intelligence framework can be loading by adding this line to local.bro:: - @load policy/frameworks/intel + @load policy/frameworks/intel/seen Intelligence Matches ******************** diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index 26a88027ef..f507172161 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -183,15 +183,16 @@ rest_target(${psd} policy/frameworks/control/controllee.bro) rest_target(${psd} policy/frameworks/control/controller.bro) rest_target(${psd} policy/frameworks/dpd/detect-protocols.bro) rest_target(${psd} policy/frameworks/dpd/packet-segment-logging.bro) -rest_target(${psd} policy/frameworks/intel/conn-established.bro) -rest_target(${psd} policy/frameworks/intel/dns.bro) -rest_target(${psd} policy/frameworks/intel/http-host-header.bro) -rest_target(${psd} policy/frameworks/intel/http-url.bro) -rest_target(${psd} policy/frameworks/intel/http-user-agents.bro) -rest_target(${psd} policy/frameworks/intel/smtp-url-extraction.bro) -rest_target(${psd} policy/frameworks/intel/smtp.bro) -rest_target(${psd} policy/frameworks/intel/ssl.bro) -rest_target(${psd} policy/frameworks/intel/where-locations.bro) +rest_target(${psd} policy/frameworks/intel/do_notice.bro) +rest_target(${psd} policy/frameworks/intel/seen/conn-established.bro) +rest_target(${psd} policy/frameworks/intel/seen/dns.bro) +rest_target(${psd} policy/frameworks/intel/seen/http-host-header.bro) +rest_target(${psd} policy/frameworks/intel/seen/http-url.bro) +rest_target(${psd} policy/frameworks/intel/seen/http-user-agents.bro) +rest_target(${psd} policy/frameworks/intel/seen/smtp-url-extraction.bro) +rest_target(${psd} policy/frameworks/intel/seen/smtp.bro) +rest_target(${psd} policy/frameworks/intel/seen/ssl.bro) +rest_target(${psd} policy/frameworks/intel/seen/where-locations.bro) rest_target(${psd} policy/frameworks/packet-filter/shunt.bro) rest_target(${psd} policy/frameworks/software/version-changes.bro) rest_target(${psd} policy/frameworks/software/vulnerable.bro) diff --git a/scripts/base/frameworks/intel/main.bro b/scripts/base/frameworks/intel/main.bro index 1b740f538d..a201a7a041 100644 --- a/scripts/base/frameworks/intel/main.bro +++ b/scripts/base/frameworks/intel/main.bro @@ -63,9 +63,6 @@ export { IN_ANYWHERE, }; - ## The $host field and combination of $str and $str_type fields are mutually - ## exclusive. These records *must* represent either an IP address being - ## seen or a string being seen. type Seen: record { ## The string if the data is about a string. indicator: string &log &optional; diff --git a/scripts/policy/frameworks/intel/do_notice.bro b/scripts/policy/frameworks/intel/do_notice.bro new file mode 100644 index 0000000000..720e29c35c --- /dev/null +++ b/scripts/policy/frameworks/intel/do_notice.bro @@ -0,0 +1,44 @@ + +@load base/frameworks/intel +@load base/frameworks/notice + +module Intel; + +export { + redef enum Notice::Type += { + ## Intel::Notice is a notice that happens when an intelligence + ## indicator is denoted to be notice-worthy. + Intel::Notice + }; + + redef record Intel::MetaData += { + ## A boolean value to allow the data itself to represent + ## if the indicator that this metadata is attached to + ## is notice worthy. + do_notice: bool &default=F; + + ## Restrictions on when notices are created to only create + ## them if the do_notice field is T and the notice was + ## seen in the indicated location. + if_in: Intel::Where &optional; + }; +} + +event Intel::match(s: Seen, items: set[Item]) + { + for ( item in items ) + { + if ( item$meta$do_notice && + (! item$meta?$if_in || s$where == item$meta$if_in) ) + { + local n = Notice::Info($note=Intel::Notice, + $msg=fmt("Intel hit on %s at %s", s$indicator, s$where), + $sub=s$indicator); + + if ( s?$conn ) + n$conn = s$conn; + + NOTICE(n); + } + } + } diff --git a/scripts/policy/frameworks/intel/__load__.bro b/scripts/policy/frameworks/intel/seen/__load__.bro similarity index 100% rename from scripts/policy/frameworks/intel/__load__.bro rename to scripts/policy/frameworks/intel/seen/__load__.bro diff --git a/scripts/policy/frameworks/intel/conn-established.bro b/scripts/policy/frameworks/intel/seen/conn-established.bro similarity index 100% rename from scripts/policy/frameworks/intel/conn-established.bro rename to scripts/policy/frameworks/intel/seen/conn-established.bro diff --git a/scripts/policy/frameworks/intel/dns.bro b/scripts/policy/frameworks/intel/seen/dns.bro similarity index 100% rename from scripts/policy/frameworks/intel/dns.bro rename to scripts/policy/frameworks/intel/seen/dns.bro diff --git a/scripts/policy/frameworks/intel/http-host-header.bro b/scripts/policy/frameworks/intel/seen/http-host-header.bro similarity index 100% rename from scripts/policy/frameworks/intel/http-host-header.bro rename to scripts/policy/frameworks/intel/seen/http-host-header.bro diff --git a/scripts/policy/frameworks/intel/http-url.bro b/scripts/policy/frameworks/intel/seen/http-url.bro similarity index 100% rename from scripts/policy/frameworks/intel/http-url.bro rename to scripts/policy/frameworks/intel/seen/http-url.bro diff --git a/scripts/policy/frameworks/intel/http-user-agents.bro b/scripts/policy/frameworks/intel/seen/http-user-agents.bro similarity index 100% rename from scripts/policy/frameworks/intel/http-user-agents.bro rename to scripts/policy/frameworks/intel/seen/http-user-agents.bro diff --git a/scripts/policy/frameworks/intel/smtp-url-extraction.bro b/scripts/policy/frameworks/intel/seen/smtp-url-extraction.bro similarity index 100% rename from scripts/policy/frameworks/intel/smtp-url-extraction.bro rename to scripts/policy/frameworks/intel/seen/smtp-url-extraction.bro diff --git a/scripts/policy/frameworks/intel/smtp.bro b/scripts/policy/frameworks/intel/seen/smtp.bro similarity index 100% rename from scripts/policy/frameworks/intel/smtp.bro rename to scripts/policy/frameworks/intel/seen/smtp.bro diff --git a/scripts/policy/frameworks/intel/ssl.bro b/scripts/policy/frameworks/intel/seen/ssl.bro similarity index 100% rename from scripts/policy/frameworks/intel/ssl.bro rename to scripts/policy/frameworks/intel/seen/ssl.bro diff --git a/scripts/policy/frameworks/intel/where-locations.bro b/scripts/policy/frameworks/intel/seen/where-locations.bro similarity index 100% rename from scripts/policy/frameworks/intel/where-locations.bro rename to scripts/policy/frameworks/intel/seen/where-locations.bro diff --git a/scripts/test-all-policy.bro b/scripts/test-all-policy.bro index 1fd34d6f2f..809fc1d1ec 100644 --- a/scripts/test-all-policy.bro +++ b/scripts/test-all-policy.bro @@ -14,16 +14,17 @@ # @load frameworks/control/controller.bro @load frameworks/dpd/detect-protocols.bro @load frameworks/dpd/packet-segment-logging.bro -@load frameworks/intel/__load__.bro -@load frameworks/intel/conn-established.bro -@load frameworks/intel/dns.bro -@load frameworks/intel/http-host-header.bro -@load frameworks/intel/http-url.bro -@load frameworks/intel/http-user-agents.bro -@load frameworks/intel/smtp-url-extraction.bro -@load frameworks/intel/smtp.bro -@load frameworks/intel/ssl.bro -@load frameworks/intel/where-locations.bro +@load frameworks/intel/do_notice.bro +@load frameworks/intel/seen/__load__.bro +@load frameworks/intel/seen/conn-established.bro +@load frameworks/intel/seen/dns.bro +@load frameworks/intel/seen/http-host-header.bro +@load frameworks/intel/seen/http-url.bro +@load frameworks/intel/seen/http-user-agents.bro +@load frameworks/intel/seen/smtp-url-extraction.bro +@load frameworks/intel/seen/smtp.bro +@load frameworks/intel/seen/ssl.bro +@load frameworks/intel/seen/where-locations.bro @load frameworks/packet-filter/shunt.bro @load frameworks/software/version-changes.bro @load frameworks/software/vulnerable.bro From 64fc80d7e4a4c1a653a16bf3d3892c50982fcffa Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 25 Jul 2013 13:31:57 -0700 Subject: [PATCH 147/881] Adding a trace with a DNSKEY RR. Still had this sitting in my inbox, but seems Bro is doing everything right. --- CHANGES | 4 ++++ VERSION | 2 +- .../scripts.base.protocols.dns.dns-key/dns.log | 10 ++++++++++ testing/btest/Traces/dns-dnskey.trace | Bin 0 -> 1110 bytes .../btest/scripts/base/protocols/dns/dns-key.bro | 4 ++++ 5 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 testing/btest/Baseline/scripts.base.protocols.dns.dns-key/dns.log create mode 100644 testing/btest/Traces/dns-dnskey.trace create mode 100644 testing/btest/scripts/base/protocols/dns/dns-key.bro diff --git a/CHANGES b/CHANGES index f4b7e43a7e..0c7235bd47 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +2.1-895 | 2013-07-29 14:07:35 -0700 + + * Adding a test for a DNSKEY RR. (Robin Sommer) + 2.1-894 | 2013-07-29 16:44:41 -0400 * Updates for the Intel Framework. (Seth Hall) diff --git a/VERSION b/VERSION index 3131a2159f..9e4a84ae0a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-894 +2.1-895 diff --git a/testing/btest/Baseline/scripts.base.protocols.dns.dns-key/dns.log b/testing/btest/Baseline/scripts.base.protocols.dns.dns-key/dns.log new file mode 100644 index 0000000000..722d2c3912 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dns.dns-key/dns.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dns +#open 2013-07-25-20-29-44 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected +#types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] bool +1359565680.761790 UWkUyAuUGXf 192.168.6.10 53209 192.168.129.36 53 udp 41477 paypal.com 1 C_INTERNET 48 DNSKEY 0 NOERROR F F T F 1 - - F +#close 2013-07-25-20-29-44 diff --git a/testing/btest/Traces/dns-dnskey.trace b/testing/btest/Traces/dns-dnskey.trace new file mode 100644 index 0000000000000000000000000000000000000000..c7a6448e7990c6717c5f8da73cb1c300bcb4f534 GIT binary patch literal 1110 zcmca|c+)~A1{MYw`2U}Qff2|l2<8mjH=mm!5Xc5$1_qw_pW+x)Crs=x;$U!PU~s++ zROui%Py4_MHm(CJ8dc8UWH4pWcg2l zAU9)JaDWG54dZb}4n{_1R%S*9#;dtA^fp+P2bQoGp4N|geL&lL*-Vp7o5g}J zOiDO>LZzj#t#jUXgDH3N+L@~@Bs=(DJ$&)9_txXvJ9M5Uv@@M)`XV5jrn9D|M{BEK zj=kgJuFnx?+O1ZkHpCv_)Yx<#=q5c-a$r2pFpt52m5G6YDI!ogN+96($re3jDJs_1%i&kO`s>{Z8M|mvw@lF;N;3?2080u$S?4>&_C<&yL@pE_lvLnHLi$pWcCLAeH59Sd_SVCU72I2Nv_F-U(Y3u zuF+j~iP2hWx@U{{ansb?GncbZ>{+uk<(5eOq;(DongKd%=l!cz_v1ZwpL^2O!*+=_ zQNB;P&ZV6-%1D@y_C%nUKX3u>mkPzOzfFq-YEE7~c%^ENUE}|3m&h%;YpkYC^3+iV LW^UFVNah9rRu9Wl literal 0 HcmV?d00001 diff --git a/testing/btest/scripts/base/protocols/dns/dns-key.bro b/testing/btest/scripts/base/protocols/dns/dns-key.bro new file mode 100644 index 0000000000..c51788c605 --- /dev/null +++ b/testing/btest/scripts/base/protocols/dns/dns-key.bro @@ -0,0 +1,4 @@ +# Making sure DNSKEY gets logged as such. +# +# @TEST-EXEC: bro -r $TRACES/dns-dnskey.trace +# @TEST-EXEC: btest-diff dns.log From d84f6e012ca726cd37fb1b1fe8131620ba2021a2 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 29 Jul 2013 15:41:34 -0500 Subject: [PATCH 148/881] Fix various documentation, mostly related to file analysis. - Fix examples/references in the file analysis how-to/usage doc. - Add Broxygen-generated docs for file analyzer plugins. - Break FTP::Info type declaration out in to its own file to get rid of some circular dependencies (between s/b/p/ftp/main and s/b/p/ftp/utils). --- doc/file-analysis.rst | 27 +++---- doc/index.rst | 1 + doc/scripts/CMakeLists.txt | 50 +++++++------ doc/scripts/DocSourcesList.cmake | 1 + scripts/base/frameworks/files/main.bro | 2 +- .../base/frameworks/packet-filter/main.bro | 2 +- scripts/base/init-bare.bro | 17 ++--- scripts/base/protocols/ftp/__load__.bro | 1 + scripts/base/protocols/ftp/files.bro | 1 + scripts/base/protocols/ftp/gridftp.bro | 1 + scripts/base/protocols/ftp/info.bro | 72 +++++++++++++++++++ scripts/base/protocols/ftp/main.bro | 67 +---------------- scripts/base/protocols/ftp/utils.bro | 5 +- .../policy/frameworks/packet-filter/shunt.bro | 4 +- scripts/policy/misc/load-balancing.bro | 12 ++-- .../tuning/defaults/packet-fragments.bro | 12 ++-- src/BroDoc.cc | 65 +++++++++++++++-- src/BroDoc.h | 6 ++ src/file_analysis/Manager.cc | 5 ++ src/file_analysis/Manager.h | 6 ++ src/main.cc | 1 + .../canonified_loaded_scripts.log | 7 +- 22 files changed, 227 insertions(+), 138 deletions(-) create mode 100644 scripts/base/protocols/ftp/info.bro diff --git a/doc/file-analysis.rst b/doc/file-analysis.rst index f312e06471..0a96a8efb7 100644 --- a/doc/file-analysis.rst +++ b/doc/file-analysis.rst @@ -82,9 +82,9 @@ attached, they start receiving the contents of the file as Bro extracts it from an ongoing network connection. What they do with the file contents is up to the particular file analyzer implementation, but they'll typically either report further information about the file via -events (e.g. :bro:see:`FileAnalysis::ANALYZER_MD5` will report the +events (e.g. :bro:see:`Files::ANALYZER_MD5` will report the file's MD5 checksum via :bro:see:`file_hash` once calculated) or they'll -have some side effect (e.g. :bro:see:`FileAnalysis::ANALYZER_EXTRACT` +have some side effect (e.g. :bro:see:`Files::ANALYZER_EXTRACT` will write the contents of the file out to the local file system). In the future there may be file analyzers that automatically attach to @@ -98,7 +98,7 @@ explicit attachment decision: { print "new file", f$id; if ( f?$mime_type && f$mime_type == "text/plain" ) - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_MD5]); + Files::add_analyzer(f, Files::ANALYZER_MD5); } event file_hash(f: fa_file, kind: string, hash: string) @@ -113,26 +113,27 @@ output:: file_hash, Cx92a0ym5R8, md5, 397168fd09991a0e712254df7bc639ac Some file analyzers might have tunable parameters that need to be -specified in the call to :bro:see:`FileAnalysis::add_analyzer`: +specified in the call to :bro:see:`Files::add_analyzer`: .. code:: bro event file_new(f: fa_file) { - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_EXTRACT, - $extract_filename="./myfile"]); + Files::add_analyzer(f, Files::ANALYZER_EXTRACT, + [$extract_filename="myfile"]); } In this case, the file extraction analyzer doesn't generate any further -events, but does have the side effect of writing out the file contents -to the local file system at the specified location of ``./myfile``. Of -course, for a network with more than a single file being transferred, -it's probably preferable to specify a different extraction path for each -file, unlike this example. +events, but does have the effect of writing out the file contents to the +local file system at the location resulting from the concatenation of +the path specified by :bro:see:`FileExtract::prefix` and the string, +``myfile``. Of course, for a network with more than a single file being +transferred, it's probably preferable to specify a different extraction +path for each file, unlike this example. Regardless of which file analyzers end up acting on a file, general information about the file (e.g. size, time of last data transferred, -MIME type, etc.) are logged in ``file_analysis.log``. +MIME type, etc.) are logged in ``files.log``. Input Framework Integration =========================== @@ -150,7 +151,7 @@ a network interface it's monitoring. It only requires a call to event file_new(f: fa_file) { print "new file", f$id; - FileAnalysis::add_analyzer(f, [$tag=FileAnalysis::ANALYZER_MD5]); + Files::add_analyzer(f, Files::ANALYZER_MD5); } event file_state_remove(f: fa_file) diff --git a/doc/index.rst b/doc/index.rst index ad05f7bf82..aa33d8797d 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -47,6 +47,7 @@ Script Reference scripts/index scripts/builtins scripts/proto-analyzers + scripts/file-analyzers Other Bro Components -------------------- diff --git a/doc/scripts/CMakeLists.txt b/doc/scripts/CMakeLists.txt index e7e39d0b3f..fa234e74f2 100644 --- a/doc/scripts/CMakeLists.txt +++ b/doc/scripts/CMakeLists.txt @@ -124,28 +124,34 @@ endmacro(REST_TARGET) # Schedule Bro scripts for which to generate documentation. include(DocSourcesList.cmake) -# This reST target is independent of a particular Bro script... -add_custom_command(OUTPUT proto-analyzers.rst - # delete any leftover state from previous bro runs - COMMAND "${CMAKE_COMMAND}" - ARGS -E remove_directory .state - # generate the reST documentation using bro - COMMAND BROPATH=${BROPATH}:${srcDir} BROMAGIC=${CMAKE_SOURCE_DIR}/magic/database ${CMAKE_BINARY_DIR}/src/bro - ARGS -b -Z base/init-bare.bro || (rm -rf .state *.log *.rst && exit 1) - # move generated doc into a new directory tree that - # defines the final structure of documents - COMMAND "${CMAKE_COMMAND}" - ARGS -E make_directory ${dstDir} - COMMAND "${CMAKE_COMMAND}" - ARGS -E copy proto-analyzers.rst ${dstDir} - # clean up the build directory - COMMAND rm - ARGS -rf .state *.log *.rst - DEPENDS bro - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "[Bro] Generating reST docs for proto-analyzers.rst" -) -list(APPEND ALL_REST_OUTPUTS proto-analyzers.rst) +# Macro for generating reST docs that are independent of any particular Bro +# script. +macro(INDEPENDENT_REST_TARGET reST_file) + add_custom_command(OUTPUT ${reST_file} + # delete any leftover state from previous bro runs + COMMAND "${CMAKE_COMMAND}" + ARGS -E remove_directory .state + # generate the reST documentation using bro + COMMAND BROPATH=${BROPATH}:${srcDir} BROMAGIC=${CMAKE_SOURCE_DIR}/magic/database ${CMAKE_BINARY_DIR}/src/bro + ARGS -b -Z base/init-bare.bro || (rm -rf .state *.log *.rst && exit 1) + # move generated doc into a new directory tree that + # defines the final structure of documents + COMMAND "${CMAKE_COMMAND}" + ARGS -E make_directory ${dstDir} + COMMAND "${CMAKE_COMMAND}" + ARGS -E copy ${reST_file} ${dstDir} + # clean up the build directory + COMMAND rm + ARGS -rf .state *.log *.rst + DEPENDS bro + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "[Bro] Generating reST docs for ${reST_file}" + ) + list(APPEND ALL_REST_OUTPUTS ${reST_file}) +endmacro(INDEPENDENT_REST_TARGET) + +independent_rest_target(proto-analyzers.rst) +independent_rest_target(file-analyzers.rst) # create temporary list of all docs to include in the master policy/index file file(WRITE ${MASTER_POLICY_INDEX} "${MASTER_POLICY_INDEX_TEXT}") diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index b2c932d117..d61db99db1 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -140,6 +140,7 @@ rest_target(${psd} base/protocols/dns/consts.bro) rest_target(${psd} base/protocols/dns/main.bro) rest_target(${psd} base/protocols/ftp/files.bro) rest_target(${psd} base/protocols/ftp/gridftp.bro) +rest_target(${psd} base/protocols/ftp/info.bro) rest_target(${psd} base/protocols/ftp/main.bro) rest_target(${psd} base/protocols/ftp/utils-commands.bro) rest_target(${psd} base/protocols/ftp/utils.bro) diff --git a/scripts/base/frameworks/files/main.bro b/scripts/base/frameworks/files/main.bro index d0c381545b..a87608054d 100644 --- a/scripts/base/frameworks/files/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -204,7 +204,7 @@ export { ## ## tag: Tag for the protocol analyzer having a callback being registered. ## - ## reg: A :bro:see:`ProtoRegistration` record. + ## reg: A :bro:see:`Files::ProtoRegistration` record. ## ## Returns: true if the protocol being registered was not previously registered. global register_protocol: function(tag: Analyzer::Tag, reg: ProtoRegistration): bool; diff --git a/scripts/base/frameworks/packet-filter/main.bro b/scripts/base/frameworks/packet-filter/main.bro index 72b2b62f34..929b10fbe1 100644 --- a/scripts/base/frameworks/packet-filter/main.bro +++ b/scripts/base/frameworks/packet-filter/main.bro @@ -109,7 +109,7 @@ export { ## Enables the old filtering approach of "only watch common ports for ## analyzed protocols". - ## + ## ## Unless you know what you are doing, leave this set to F. const enable_auto_protocol_capture_filters = F &redef; diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 594991c85a..92b806092c 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -531,22 +531,19 @@ type record_field_table: table[string] of record_field; # dependent on the names remaining as they are now. ## Set of BPF capture filters to use for capturing, indexed by a user-definable -## ID (which must be unique). If Bro is *not* configured to examine -## :bro:id:`PacketFilter::all_packets`, all packets matching at least -## one of the filters in this table (and all in :bro:id:`restrict_filters`) -## will be analyzed. +## ID (which must be unique). If Bro is *not* configured with +## :bro:id:`PacketFilter::enable_auto_protocol_capture_filters`, +## all packets matching at least one of the filters in this table (and all in +## :bro:id:`restrict_filters`) will be analyzed. ## -## .. bro:see:: PacketFilter PacketFilter::all_packets +## .. bro:see:: PacketFilter PacketFilter::enable_auto_protocol_capture_filters ## PacketFilter::unrestricted_filter restrict_filters global capture_filters: table[string] of string &redef; ## Set of BPF filters to restrict capturing, indexed by a user-definable ID (which -## must be unique). If Bro is *not* configured to examine -## :bro:id:`PacketFilter::all_packets`, only packets matching *all* of the -## filters in this table (and any in :bro:id:`capture_filters`) will be -## analyzed. +## must be unique). ## -## .. bro:see:: PacketFilter PacketFilter::all_packets +## .. bro:see:: PacketFilter PacketFilter::enable_auto_protocol_capture_filters ## PacketFilter::unrestricted_filter capture_filters global restrict_filters: table[string] of string &redef; diff --git a/scripts/base/protocols/ftp/__load__.bro b/scripts/base/protocols/ftp/__load__.bro index ebb09e702c..3ddd8a2dc2 100644 --- a/scripts/base/protocols/ftp/__load__.bro +++ b/scripts/base/protocols/ftp/__load__.bro @@ -1,4 +1,5 @@ @load ./utils-commands +@load ./info @load ./main @load ./utils @load ./files diff --git a/scripts/base/protocols/ftp/files.bro b/scripts/base/protocols/ftp/files.bro index 9ed17ab2a4..b507ca32a7 100644 --- a/scripts/base/protocols/ftp/files.bro +++ b/scripts/base/protocols/ftp/files.bro @@ -1,3 +1,4 @@ +@load ./info @load ./main @load ./utils @load base/utils/conn-ids diff --git a/scripts/base/protocols/ftp/gridftp.bro b/scripts/base/protocols/ftp/gridftp.bro index 57752b1cbd..73bd656544 100644 --- a/scripts/base/protocols/ftp/gridftp.bro +++ b/scripts/base/protocols/ftp/gridftp.bro @@ -19,6 +19,7 @@ ##! sizes are not logged, but at the benefit of saving CPU cycles that ##! otherwise go to analyzing the large (and likely benign) connections. +@load ./info @load ./main @load base/protocols/conn @load base/protocols/ssl diff --git a/scripts/base/protocols/ftp/info.bro b/scripts/base/protocols/ftp/info.bro new file mode 100644 index 0000000000..f6fceb071e --- /dev/null +++ b/scripts/base/protocols/ftp/info.bro @@ -0,0 +1,72 @@ +##! Defines data structures for tracking and logging FTP sessions. + +module FTP; + +@load ./utils-commands + +export { + + ## This setting changes if passwords used in FTP sessions are + ## captured or not. + const default_capture_password = F &redef; + + ## The expected endpoints of an FTP data channel. + type ExpectedDataChannel: record { + ## Whether PASV mode is toggled for control channel. + passive: bool &log; + ## The host that will be initiating the data connection. + orig_h: addr &log; + ## The host that will be accepting the data connection. + resp_h: addr &log; + ## The port at which the acceptor is listening for the data connection. + resp_p: port &log; + }; + + type Info: record { + ## Time when the command was sent. + ts: time &log; + ## Unique ID for the connection. + uid: string &log; + ## The connection's 4-tuple of endpoint addresses/ports. + id: conn_id &log; + ## User name for the current FTP session. + user: string &log &default=""; + ## Password for the current FTP session if captured. + password: string &log &optional; + ## Command given by the client. + command: string &log &optional; + ## Argument for the command if one is given. + arg: string &log &optional; + + ## Libmagic "sniffed" file type if the command indicates a file transfer. + mime_type: string &log &optional; + ## Size of the file if the command indicates a file transfer. + file_size: count &log &optional; + + ## Reply code from the server in response to the command. + reply_code: count &log &optional; + ## Reply message from the server in response to the command. + reply_msg: string &log &optional; + + ## Expected FTP data channel. + data_channel: ExpectedDataChannel &log &optional; + + ## Current working directory that this session is in. By making + ## the default value '.', we can indicate that unless something + ## more concrete is discovered that the existing but unknown + ## directory is ok to use. + cwd: string &default="."; + + ## Command that is currently waiting for a response. + cmdarg: CmdArg &optional; + ## Queue for commands that have been sent but not yet responded to + ## are tracked here. + pending_commands: PendingCmds; + + ## Indicates if the session is in active or passive mode. + passive: bool &default=F; + + ## Determines if the password will be captured for this request. + capture_password: bool &default=default_capture_password; + }; +} diff --git a/scripts/base/protocols/ftp/main.bro b/scripts/base/protocols/ftp/main.bro index c9549a14ec..df66235d49 100644 --- a/scripts/base/protocols/ftp/main.bro +++ b/scripts/base/protocols/ftp/main.bro @@ -3,6 +3,8 @@ ##! will take on the full path that the client is at along with the requested ##! file name. +@load ./info +@load ./utils @load ./utils-commands @load base/utils/paths @load base/utils/numbers @@ -20,72 +22,9 @@ export { "EPSV" } &redef; - ## This setting changes if passwords used in FTP sessions are captured or not. - const default_capture_password = F &redef; - ## User IDs that can be considered "anonymous". const guest_ids = { "anonymous", "ftp", "ftpuser", "guest" } &redef; - ## The expected endpoints of an FTP data channel. - type ExpectedDataChannel: record { - ## Whether PASV mode is toggled for control channel. - passive: bool &log; - ## The host that will be initiating the data connection. - orig_h: addr &log; - ## The host that will be accepting the data connection. - resp_h: addr &log; - ## The port at which the acceptor is listening for the data connection. - resp_p: port &log; - }; - - type Info: record { - ## Time when the command was sent. - ts: time &log; - ## Unique ID for the connection. - uid: string &log; - ## The connection's 4-tuple of endpoint addresses/ports. - id: conn_id &log; - ## User name for the current FTP session. - user: string &log &default=""; - ## Password for the current FTP session if captured. - password: string &log &optional; - ## Command given by the client. - command: string &log &optional; - ## Argument for the command if one is given. - arg: string &log &optional; - - ## Libmagic "sniffed" file type if the command indicates a file transfer. - mime_type: string &log &optional; - ## Size of the file if the command indicates a file transfer. - file_size: count &log &optional; - - ## Reply code from the server in response to the command. - reply_code: count &log &optional; - ## Reply message from the server in response to the command. - reply_msg: string &log &optional; - - ## Expected FTP data channel. - data_channel: ExpectedDataChannel &log &optional; - - ## Current working directory that this session is in. By making - ## the default value '.', we can indicate that unless something - ## more concrete is discovered that the existing but unknown - ## directory is ok to use. - cwd: string &default="."; - - ## Command that is currently waiting for a response. - cmdarg: CmdArg &optional; - ## Queue for commands that have been sent but not yet responded to - ## are tracked here. - pending_commands: PendingCmds; - - ## Indicates if the session is in active or passive mode. - passive: bool &default=F; - - ## Determines if the password will be captured for this request. - capture_password: bool &default=default_capture_password; - }; - ## This record is to hold a parsed FTP reply code. For example, for the ## 201 status code, the digits would be parsed as: x->2, y->0, z=>1. type ReplyCode: record { @@ -102,8 +41,6 @@ export { global log_ftp: event(rec: Info); } -@load ./utils - # Add the state tracking information variable to the connection record redef record connection += { ftp: Info &optional; diff --git a/scripts/base/protocols/ftp/utils.bro b/scripts/base/protocols/ftp/utils.bro index 629b87e5a8..a0b473e086 100644 --- a/scripts/base/protocols/ftp/utils.bro +++ b/scripts/base/protocols/ftp/utils.bro @@ -1,7 +1,8 @@ ##! Utilities specific for FTP processing. -@load ./main +@load ./info @load base/utils/addrs +@load base/utils/paths module FTP; @@ -44,4 +45,4 @@ function build_url_ftp(rec: Info): string function describe(rec: Info): string { return build_url_ftp(rec); - } \ No newline at end of file + } diff --git a/scripts/policy/frameworks/packet-filter/shunt.bro b/scripts/policy/frameworks/packet-filter/shunt.bro index b87369ee62..85ec189a17 100644 --- a/scripts/policy/frameworks/packet-filter/shunt.bro +++ b/scripts/policy/frameworks/packet-filter/shunt.bro @@ -34,8 +34,8 @@ export { global current_shunted_host_pairs: function(): set[conn_id]; redef enum Notice::Type += { - ## Indicative that :bro:id:`max_bpf_shunts` connections are already - ## being shunted with BPF filters and no more are allowed. + ## Indicative that :bro:id:`PacketFilter::max_bpf_shunts` connections + ## are already being shunted with BPF filters and no more are allowed. No_More_Conn_Shunts_Available, ## Limitations in BPF make shunting some connections with BPF impossible. diff --git a/scripts/policy/misc/load-balancing.bro b/scripts/policy/misc/load-balancing.bro index fe07dd64da..889d18119a 100644 --- a/scripts/policy/misc/load-balancing.bro +++ b/scripts/policy/misc/load-balancing.bro @@ -12,12 +12,12 @@ export { ## Apply BPF filters to each worker in a way that causes them to ## automatically flow balance traffic between them. AUTO_BPF, - ## Load balance traffic across the workers by making each one apply - ## a restrict filter to only listen to a single MAC address. This - ## is a somewhat common deployment option for sites doing network - ## based load balancing with MAC address rewriting and passing the - ## traffic to a single interface. Multiple MAC addresses will show - ## up on the same interface and need filtered to a single address. + # Load balance traffic across the workers by making each one apply + # a restrict filter to only listen to a single MAC address. This + # is a somewhat common deployment option for sites doing network + # based load balancing with MAC address rewriting and passing the + # traffic to a single interface. Multiple MAC addresses will show + # up on the same interface and need filtered to a single address. #MAC_ADDR_BPF, }; diff --git a/scripts/policy/tuning/defaults/packet-fragments.bro b/scripts/policy/tuning/defaults/packet-fragments.bro index 24b18d5917..f95c826547 100644 --- a/scripts/policy/tuning/defaults/packet-fragments.bro +++ b/scripts/policy/tuning/defaults/packet-fragments.bro @@ -1,10 +1,10 @@ -## Capture TCP fragments, but not UDP (or ICMP), since those are a lot more -## common due to high-volume, fragmenting protocols such as NFS :-(. +# Capture TCP fragments, but not UDP (or ICMP), since those are a lot more +# common due to high-volume, fragmenting protocols such as NFS :-(. -## This normally isn't used because of the default open packet filter -## but we set it anyway in case the user is using a packet filter. -## Note: This was removed because the default model now is to have a wide -## open packet filter. +# This normally isn't used because of the default open packet filter +# but we set it anyway in case the user is using a packet filter. +# Note: This was removed because the default model now is to have a wide +# open packet filter. #redef capture_filters += { ["frag"] = "(ip[6:2] & 0x3fff != 0) and tcp" }; ## Shorten the fragment timeout from never expiring to expiring fragments after diff --git a/src/BroDoc.cc b/src/BroDoc.cc index c04cd92eca..3cb271bdbf 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -11,6 +11,7 @@ #include "plugin/Manager.h" #include "analyzer/Manager.h" #include "analyzer/Component.h" +#include "file_analysis/Manager.h" BroDoc::BroDoc(const std::string& rel, const std::string& abs) { @@ -479,6 +480,17 @@ static void WriteAnalyzerComponent(FILE* f, const analyzer::Component* c) fprintf(f, ":bro:enum:`Analyzer::%s`\n\n", tag.c_str()); } +static void WriteAnalyzerComponent(FILE* f, const file_analysis::Component* c) + { + EnumType* atag = file_mgr->GetTagEnumType(); + string tag = fmt("ANALYZER_%s", c->CanonicalName()); + + if ( atag->Lookup("Files", tag.c_str()) < 0 ) + reporter->InternalError("missing analyzer tag for %s", tag.c_str()); + + fprintf(f, ":bro:enum:`Files::%s`\n\n", tag.c_str()); + } + static void WritePluginComponents(FILE* f, const plugin::Plugin* p) { plugin::Plugin::component_list components = p->Components(); @@ -494,6 +506,10 @@ static void WritePluginComponents(FILE* f, const plugin::Plugin* p) WriteAnalyzerComponent(f, dynamic_cast(*it)); break; + case plugin::component::FILE_ANALYZER: + WriteAnalyzerComponent(f, + dynamic_cast(*it)); + break; case plugin::component::READER: reporter->InternalError("docs for READER component unimplemented"); case plugin::component::WRITER: @@ -537,12 +553,13 @@ static void WritePluginBifItems(FILE* f, const plugin::Plugin* p, } } -static void WriteAnalyzerTagDefn(FILE* f, EnumType* e) +static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module) { + string tag_id= module + "::Tag"; e = new CommentedEnumType(e); - e->SetTypeID(copy_string("Analyzer::Tag")); + e->SetTypeID(copy_string(tag_id.c_str())); - ID* dummy_id = new ID(copy_string("Analyzer::Tag"), SCOPE_GLOBAL, true); + ID* dummy_id = new ID(copy_string(tag_id.c_str()), SCOPE_GLOBAL, true); dummy_id->SetType(e); dummy_id->MakeType(); @@ -554,13 +571,17 @@ static void WriteAnalyzerTagDefn(FILE* f, EnumType* e) bdo.WriteReST(f); } -static bool IsAnalyzerPlugin(const plugin::Plugin* p) +static bool ComponentsMatch(const plugin::Plugin* p, plugin::component::Type t, + bool match_empty = false) { plugin::Plugin::component_list components = p->Components(); plugin::Plugin::component_list::const_iterator it; + if ( components.empty() ) + return match_empty; + for ( it = components.begin(); it != components.end(); ++it ) - if ( (*it)->Type() != plugin::component::ANALYZER ) + if ( (*it)->Type() != t ) return false; return true; @@ -573,14 +594,44 @@ void CreateProtoAnalyzerDoc(const char* filename) fprintf(f, "Protocol Analyzer Reference\n"); fprintf(f, "===========================\n\n"); - WriteAnalyzerTagDefn(f, analyzer_mgr->GetTagEnumType()); + WriteAnalyzerTagDefn(f, analyzer_mgr->GetTagEnumType(), "Analyzer"); plugin::Manager::plugin_list plugins = plugin_mgr->Plugins(); plugin::Manager::plugin_list::const_iterator it; for ( it = plugins.begin(); it != plugins.end(); ++it ) { - if ( ! IsAnalyzerPlugin(*it) ) + if ( ! ComponentsMatch(*it, plugin::component::ANALYZER, true) ) + continue; + + WritePluginSectionHeading(f, *it); + WritePluginComponents(f, *it); + WritePluginBifItems(f, *it, plugin::BifItem::CONSTANT, + "Options/Constants"); + WritePluginBifItems(f, *it, plugin::BifItem::GLOBAL, "Globals"); + WritePluginBifItems(f, *it, plugin::BifItem::TYPE, "Types"); + WritePluginBifItems(f, *it, plugin::BifItem::EVENT, "Events"); + WritePluginBifItems(f, *it, plugin::BifItem::FUNCTION, "Functions"); + } + + fclose(f); + } + +void CreateFileAnalyzerDoc(const char* filename) + { + FILE* f = fopen(filename, "w"); + + fprintf(f, "File Analyzer Reference\n"); + fprintf(f, "===========================\n\n"); + + WriteAnalyzerTagDefn(f, file_mgr->GetTagEnumType(), "Files"); + + plugin::Manager::plugin_list plugins = plugin_mgr->Plugins(); + plugin::Manager::plugin_list::const_iterator it; + + for ( it = plugins.begin(); it != plugins.end(); ++it ) + { + if ( ! ComponentsMatch(*it, plugin::component::FILE_ANALYZER) ) continue; WritePluginSectionHeading(f, *it); diff --git a/src/BroDoc.h b/src/BroDoc.h index 9f92f821f8..081df698d9 100644 --- a/src/BroDoc.h +++ b/src/BroDoc.h @@ -413,4 +413,10 @@ private: */ void CreateProtoAnalyzerDoc(const char* filename); +/** + * Writes out plugin index documentation for all file analyzer plugins. + * @param filename the name of the file to write. + */ +void CreateFileAnalyzerDoc(const char* filename); + #endif diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index 4e25bb0b0e..fb74a409b4 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -394,3 +394,8 @@ const char* Manager::GetAnalyzerName(int tag) const return it->second->CanonicalName(); } + +EnumType* Manager::GetTagEnumType() + { + return tag_enum_type; + } diff --git a/src/file_analysis/Manager.h b/src/file_analysis/Manager.h index 84b606173d..a93e78c638 100644 --- a/src/file_analysis/Manager.h +++ b/src/file_analysis/Manager.h @@ -214,6 +214,12 @@ public: */ const char* GetAnalyzerName(int tag) const; + /** + * Returns the enum type that corresponds to the script-level type + * \c Files::Tag. + */ + EnumType* GetTagEnumType(); + protected: friend class FileTimer; diff --git a/src/main.cc b/src/main.cc index 56193a935b..6a58832964 100644 --- a/src/main.cc +++ b/src/main.cc @@ -872,6 +872,7 @@ int main(int argc, char** argv) if ( generate_documentation ) { CreateProtoAnalyzerDoc("proto-analyzers.rst"); + CreateFileAnalyzerDoc("file-analyzers.rst"); std::list::iterator it; diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index f67d4b6158..c34e2e2e87 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-07-23-05-48-10 +#open 2013-07-29-20-08-38 #fields name #types string scripts/base/init-bare.bro @@ -156,8 +156,9 @@ scripts/base/init-default.bro scripts/base/protocols/dns/main.bro scripts/base/protocols/ftp/__load__.bro scripts/base/protocols/ftp/utils-commands.bro + scripts/base/protocols/ftp/info.bro scripts/base/protocols/ftp/main.bro - scripts/base/protocols/ftp/utils.bro + scripts/base/protocols/ftp/utils.bro scripts/base/protocols/ftp/files.bro scripts/base/protocols/ftp/gridftp.bro scripts/base/protocols/ssl/__load__.bro @@ -196,4 +197,4 @@ scripts/base/init-default.bro scripts/base/files/extract/main.bro scripts/base/misc/find-checksum-offloading.bro scripts/policy/misc/loaded-scripts.bro -#close 2013-07-23-05-48-10 +#close 2013-07-29-20-08-38 From c7676c5e695b0a4590a2fa18e96241455ff4970e Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 29 Jul 2013 14:29:45 -0700 Subject: [PATCH 149/881] The new magic submodule didn't get merged. --- magic | 1 + 1 file changed, 1 insertion(+) create mode 160000 magic diff --git a/magic b/magic new file mode 160000 index 0000000000..e87fe13a7b --- /dev/null +++ b/magic @@ -0,0 +1 @@ +Subproject commit e87fe13a7b776182ffc8c75076d42702f5c28fed From b76d1d07ca0d0175f57f83379612009c8c09400a Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 29 Jul 2013 15:06:07 -0700 Subject: [PATCH 150/881] Test updates. BIT-1044 #merged --- CHANGES | 40 +++++++++++++++++++ NEWS | 2 +- VERSION | 2 +- .../canonified_loaded_scripts.log | 5 ++- .../canonified_loaded_scripts.log | 7 ++-- .../http.ds.txt | 18 ++++----- testing/btest/coverage/bare-mode-errors.test | 5 ++- 7 files changed, 62 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index 0c7235bd47..1f64cc908a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,44 @@ +2.1-930 | 2013-07-29 15:06:07 -0700 + + * Major file analysis overhaul in naming and appearance, along with + fixes and test updates. (Seth Hall and Jon Siwek) + + Includes: + + * Added protocol description functions that provide a super + compressed log representation. (Seth Hall) + + * Added mime types to http.log (Seth Hall) + + * Add jar files to the default MHR lookups. (Seth Hall) + + * Adding CAB files for MHR checking. (Seth Hall) + + * Improve malware hash registry script. + + - Include a link to a virustotal search in the notice sub message field. + - Give all information returned from Team Cymru in the notice message. + - Add more file types to match on to the default set. + + * Make the custom libmagic database a git submodule. + + * Add an is_orig parameter to file_over_new_connection event. + + * Recorrected the module name to Files. + + * Added Files::analyzer_name to get a more readable name for a + file analyzer. + + * Improved and just overall better handled multipart mime + transfers in HTTP and SMTP. HTTP now has orig_fuids and + resp_fuids log fields since multiple "files" can be transferred + with multipart mime in a single request/response pair. SMTP has + an fuids field which has file unique IDs for all parts + transferred. FTP and IRC have a log field named fuid added + because only a single file can be transferred per irc and ftp + log line. + 2.1-895 | 2013-07-29 14:07:35 -0700 * Adding a test for a DNSKEY RR. (Robin Sommer) diff --git a/NEWS b/NEWS index c3eabf5554..de2ee1b684 100644 --- a/NEWS +++ b/NEWS @@ -80,7 +80,7 @@ New Functionality with the following user-visibible functionality (some of that was already available before, but done differently): - [TODO: This will probably change with further script updates.] + [TODO: Update with changes from 984e9793db56.] - A binary input reader interfaces the input framework with file analysis, allowing to inject files on disk into Bro's diff --git a/VERSION b/VERSION index 9e4a84ae0a..cacffbfffc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-895 +2.1-930 diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index 0caafdf107..e28efc9563 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-07-25-17-54-33 +#open 2013-07-29-21-31-47 #fields name #types string scripts/base/init-bare.bro @@ -90,6 +90,7 @@ scripts/base/init-bare.bro build/scripts/base/bif/file_analysis.bif.bro scripts/base/utils/site.bro scripts/base/utils/patterns.bro + build/scripts/base/bif/__load__.bro scripts/policy/misc/loaded-scripts.bro scripts/base/utils/paths.bro -#close 2013-07-25-19-59-47 +#close 2013-07-29-21-31-47 diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index deffbe364b..faf372222b 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-07-23-05-48-10 +#open 2013-07-29-21-31-48 #fields name #types string scripts/base/init-bare.bro @@ -90,6 +90,7 @@ scripts/base/init-bare.bro build/scripts/base/bif/file_analysis.bif.bro scripts/base/utils/site.bro scripts/base/utils/patterns.bro + build/scripts/base/bif/__load__.bro scripts/base/init-default.bro scripts/base/utils/addrs.bro scripts/base/utils/conn-ids.bro @@ -158,7 +159,7 @@ scripts/base/init-default.bro scripts/base/protocols/ftp/__load__.bro scripts/base/protocols/ftp/utils-commands.bro scripts/base/protocols/ftp/main.bro - scripts/base/protocols/ftp/utils.bro + scripts/base/protocols/ftp/utils.bro scripts/base/protocols/ftp/files.bro scripts/base/protocols/ftp/gridftp.bro scripts/base/protocols/ssl/__load__.bro @@ -197,4 +198,4 @@ scripts/base/init-default.bro scripts/base/files/extract/main.bro scripts/base/misc/find-checksum-offloading.bro scripts/policy/misc/loaded-scripts.bro -#close 2013-07-23-05-48-10 +#close 2013-07-29-21-31-48 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/http.ds.txt b/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/http.ds.txt index e919233b79..fd998057f3 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/http.ds.txt +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/http.ds.txt @@ -32,10 +32,10 @@ - - - - + + + + @@ -60,13 +60,13 @@ - - - - + + + + # Extent, type='http' -ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extracted_request_files extracted_response_files +ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types 1300475168.784020 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 1 GET bits.wikimedia.org /skins-1.5/monobook/main.css http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 1300475168.916018 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 1300475168.916183 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 diff --git a/testing/btest/coverage/bare-mode-errors.test b/testing/btest/coverage/bare-mode-errors.test index 34ba063081..1910ef8e17 100644 --- a/testing/btest/coverage/bare-mode-errors.test +++ b/testing/btest/coverage/bare-mode-errors.test @@ -10,5 +10,8 @@ # # @TEST-EXEC: test -d $DIST/scripts # @TEST-EXEC: for script in `find $DIST/scripts/ -name \*\.bro -not -path '*/site/*'`; do echo "=== $script" >>allerrors; if echo "$script" | egrep -q 'communication/listen|controllee'; then rm -rf load_attempt .bgprocs; btest-bg-run load_attempt bro -b $script; btest-bg-wait -k 2; cat load_attempt/.stderr >>allerrors; else bro -b $script 2>>allerrors; fi done || exit 0 -# @TEST-EXEC: cat allerrors | grep -v "received termination signal" | grep -v '===' | sort | uniq > unique_errors +# @TEST-EXEC: cat allerrors | grep -v "received termination signal" | fgrep -v -f %INPUT | grep -v '===' | sort | uniq > unique_errors # @TEST-EXEC: btest-diff unique_errors + +# White-list of tests to exclude because of cyclic load dependencies. +scripts/base/protocols/ftp/utils.bro From c30fa36d14382c03d08f545002a33f21eb778cfe Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 29 Jul 2013 16:39:40 -0700 Subject: [PATCH 151/881] Updating submodule(s). [nomail] --- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aux/binpac b/aux/binpac index 896ddedde5..314fa8f65f 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 896ddedde55c48ec2163577fc258b49c418abb3e +Subproject commit 314fa8f65fc240e960c23c3bba98623436a72b98 diff --git a/aux/bro-aux b/aux/bro-aux index a9942558c7..91d258cc8b 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit a9942558c7d3dfd80148b8aaded64c82ade3d117 +Subproject commit 91d258cc8b2f74cd02fc93dfe61f73ec9f0dd489 diff --git a/aux/broccoli b/aux/broccoli index 889f9c6594..d59c73b6e0 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 889f9c65944ceac20ad9230efc39d33e6e1221c3 +Subproject commit d59c73b6e0966ad63bbc63a35741b5f68263e7b1 diff --git a/aux/broctl b/aux/broctl index 0cd102805e..52fd91261f 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 0cd102805e73343cab3f9fd4a76552e13940dad9 +Subproject commit 52fd91261f41fa1528f7b964837a364d7991889e From 43825212db25ce540c6a12905844d246f8784c05 Mon Sep 17 00:00:00 2001 From: Matthias Vallentin Date: Tue, 30 Jul 2013 12:17:53 +0200 Subject: [PATCH 152/881] Update submodules. --- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- cmake | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aux/binpac b/aux/binpac index c39bd478b9..314fa8f65f 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit c39bd478b9d0ecd05b1b83aa9d09a7887893977c +Subproject commit 314fa8f65fc240e960c23c3bba98623436a72b98 diff --git a/aux/bro-aux b/aux/bro-aux index a9942558c7..91d258cc8b 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit a9942558c7d3dfd80148b8aaded64c82ade3d117 +Subproject commit 91d258cc8b2f74cd02fc93dfe61f73ec9f0dd489 diff --git a/aux/broccoli b/aux/broccoli index 889f9c6594..d59c73b6e0 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 889f9c65944ceac20ad9230efc39d33e6e1221c3 +Subproject commit d59c73b6e0966ad63bbc63a35741b5f68263e7b1 diff --git a/aux/broctl b/aux/broctl index 0cd102805e..52fd91261f 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 0cd102805e73343cab3f9fd4a76552e13940dad9 +Subproject commit 52fd91261f41fa1528f7b964837a364d7991889e diff --git a/cmake b/cmake index 0187b33a29..026639f836 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 0187b33a29d5ec824f940feff60dc5d8c2fe314f +Subproject commit 026639f8368e56742c0cb5d9fb390ea64e60ec50 From 0e23a8bc9e24e535b2fff61f63232c6360c14638 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 30 Jul 2013 11:46:51 -0400 Subject: [PATCH 153/881] Beginning rework of SumStats API. --- scripts/base/frameworks/sumstats/cluster.bro | 133 +++++++++--------- scripts/base/frameworks/sumstats/main.bro | 31 +--- .../base/frameworks/sumstats/non-cluster.bro | 11 +- 3 files changed, 84 insertions(+), 91 deletions(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index a69dd1ab54..0c005d72a6 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -39,10 +39,10 @@ export { ## a single key value from a sumstat. It's typically used to get intermediate ## updates before the break interval triggers to speed detection of a value ## crossing a threshold. - global cluster_key_request: event(uid: string, ss_name: string, key: Key, cleanup: bool); + global cluster_keys_request: event(uid: string, ss_name: string, key: set[Key], cleanup: bool); ## This event is sent by nodes in response to a - ## :bro:id:`SumStats::cluster_key_request` event. + ## :bro:id:`SumStats::cluster_keys_request` event. global cluster_key_response: event(uid: string, ss_name: string, key: Key, result: Result, cleanup: bool); ## This is sent by workers to indicate that they crossed the percent @@ -89,68 +89,71 @@ function data_added(ss: SumStat, key: Key, result: Result) } } -event SumStats::send_data(uid: string, ss_name: string, data: ResultTable, cleanup: bool) +#event SumStats::send_data(uid: string, ss_name: string, data: ResultTable, cleanup: bool) +# { +# #print fmt("WORKER %s: sending data for uid %s...", Cluster::node, uid); +# +# local local_data: ResultTable = table(); +# local incoming_data: ResultTable = cleanup ? data : copy(data); +# +# local num_added = 0; +# for ( key in incoming_data ) +# { +# local_data[key] = incoming_data[key]; +# delete incoming_data[key]; +# +# # Only send cluster_send_in_groups_of at a time. Queue another +# # event to send the next group. +# if ( cluster_send_in_groups_of == ++num_added ) +# break; +# } +# +# local done = F; +# # If data is empty, this sumstat is done. +# if ( |incoming_data| == 0 ) +# done = T; +# +# # Note: copy is needed to compensate serialization caching issue. This should be +# # changed to something else later. +# event SumStats::cluster_ss_response(uid, ss_name, copy(local_data), done, cleanup); +# if ( ! done ) +# schedule 0.01 sec { SumStats::send_data(uid, ss_name, incoming_data, T) }; +# } + +#event SumStats::cluster_ss_request(uid: string, ss_name: string, cleanup: bool) +# { +# #print fmt("WORKER %s: received the cluster_ss_request event for %s.", Cluster::node, id); +# +# # Initiate sending all of the data for the requested stats. +# if ( ss_name in result_store ) +# event SumStats::send_data(uid, ss_name, result_store[ss_name], cleanup); +# else +# event SumStats::send_data(uid, ss_name, table(), cleanup); +# +# # Lookup the actual sumstats and reset it, the reference to the data +# # currently stored will be maintained internally by the send_data event. +# if ( ss_name in stats_store && cleanup ) +# reset(stats_store[ss_name]); +# } + +event SumStats::cluster_keys_request(uid: string, ss_name: string, keys: set[Key], cleanup: bool) { - #print fmt("WORKER %s: sending data for uid %s...", Cluster::node, uid); - - local local_data: ResultTable = table(); - local incoming_data: ResultTable = cleanup ? data : copy(data); - - local num_added = 0; - for ( key in incoming_data ) + for ( key in keys ) { - local_data[key] = incoming_data[key]; - delete incoming_data[key]; + if ( ss_name in result_store && key in result_store[ss_name] ) + { + #print fmt("WORKER %s: received the cluster_keys_request event for %s=%s.", Cluster::node, key2str(key), data); - # Only send cluster_send_in_groups_of at a time. Queue another - # event to send the next group. - if ( cluster_send_in_groups_of == ++num_added ) - break; - } - - local done = F; - # If data is empty, this sumstat is done. - if ( |incoming_data| == 0 ) - done = T; - - # Note: copy is needed to compensate serialization caching issue. This should be - # changed to something else later. - event SumStats::cluster_ss_response(uid, ss_name, copy(local_data), done, cleanup); - if ( ! done ) - schedule 0.01 sec { SumStats::send_data(uid, ss_name, incoming_data, T) }; - } - -event SumStats::cluster_ss_request(uid: string, ss_name: string, cleanup: bool) - { - #print fmt("WORKER %s: received the cluster_ss_request event for %s.", Cluster::node, id); - - # Initiate sending all of the data for the requested stats. - if ( ss_name in result_store ) - event SumStats::send_data(uid, ss_name, result_store[ss_name], cleanup); - else - event SumStats::send_data(uid, ss_name, table(), cleanup); - - # Lookup the actual sumstats and reset it, the reference to the data - # currently stored will be maintained internally by the send_data event. - if ( ss_name in stats_store && cleanup ) - reset(stats_store[ss_name]); - } - -event SumStats::cluster_key_request(uid: string, ss_name: string, key: Key, cleanup: bool) - { - if ( ss_name in result_store && key in result_store[ss_name] ) - { - #print fmt("WORKER %s: received the cluster_key_request event for %s=%s.", Cluster::node, key2str(key), data); - - # Note: copy is needed to compensate serialization caching issue. This should be - # changed to something else later. - event SumStats::cluster_key_response(uid, ss_name, key, copy(result_store[ss_name][key]), cleanup); - } - else - { - # We need to send an empty response if we don't have the data so that the manager - # can know that it heard back from all of the workers. - event SumStats::cluster_key_response(uid, ss_name, key, table(), cleanup); + # Note: copy is needed to compensate serialization caching issue. This should be + # changed to something else later. + event SumStats::cluster_key_response(uid, ss_name, key, copy(result_store[ss_name][key]), cleanup); + } + else + { + # We need to send an empty response if we don't have the data so that the manager + # can know that it heard back from all of the workers. + event SumStats::cluster_key_response(uid, ss_name, key, table(), cleanup); + } } } @@ -252,6 +255,10 @@ event SumStats::cluster_key_response(uid: string, ss_name: string, key: Key, res threshold_crossed(ss, key, ir); event SumStats::cluster_threshold_crossed(ss$name, key, threshold_tracker[ss$name][key]); } + if () + { + + } if ( cleanup ) { @@ -289,7 +296,7 @@ event SumStats::cluster_key_intermediate_response(ss_name: string, key: Key) local uid = unique_id(""); done_with[uid] = 0; - event SumStats::cluster_key_request(uid, ss_name, key, T); + event SumStats::cluster_keys_request(uid, ss_name, set(key), T); } event SumStats::cluster_ss_response(uid: string, ss_name: string, data: ResultTable, done: bool, cleanup: bool) @@ -378,7 +385,7 @@ function request_key(ss_name: string, key: Key): Result done_with[uid] = 0; key_requests[uid] = table(); - event SumStats::cluster_key_request(uid, ss_name, key, F); + event SumStats::cluster_keys_request(uid, ss_name, set(key), F); return when ( uid in done_with && Cluster::worker_count == done_with[uid] ) { local result = key_requests[uid]; diff --git a/scripts/base/frameworks/sumstats/main.bro b/scripts/base/frameworks/sumstats/main.bro index 3afa507c7a..8d5a668cde 100644 --- a/scripts/base/frameworks/sumstats/main.bro +++ b/scripts/base/frameworks/sumstats/main.bro @@ -74,10 +74,6 @@ export { ## Type to store results for multiple reducers. type Result: table[string] of ResultVal; - ## Type to store a table of sumstats results indexed - ## by keys. - type ResultTable: table[Key] of Result; - ## SumStats represent an aggregation of reducers along with ## mechanisms to handle various situations like the epoch ending ## or thresholds being crossed. @@ -92,7 +88,7 @@ export { name: string; ## The interval at which this filter should be "broken" - ## and the '$epoch_finished' callback called. The + ## and the '$epoch_result' callback called. The ## results are also reset at this time so any threshold ## based detection needs to be set to a ## value that should be expected to happen within @@ -119,15 +115,10 @@ export { ## A callback that is called when a threshold is crossed. threshold_crossed: function(key: SumStats::Key, result: SumStats::Result) &optional; - ## A callback with the full collection of Results for - ## this SumStat. - epoch_finished: function(rt: SumStats::ResultTable) &optional; - #epoch_finished: function(num_keys: count) &optional; - ## A callback that receives each of the results at the ## end of the analysis epoch. The function will be ## called once for each key. - #epoch_finished_result: function(key::SumStats::Key, result: SumStats::Result) &optional; + epoch_result: function(ts: time, key::SumStats::Key, result: SumStats::Result) &optional; }; ## Create a summary statistic. @@ -144,17 +135,6 @@ export { ## obs: The data point to send into the stream. global observe: function(id: string, key: SumStats::Key, obs: SumStats::Observation); - ## Dynamically request a sumstat. This function should be - ## used sparingly and not as a replacement for the callbacks - ## from the :bro:see:`SumStat` record. The function is only - ## available for use within "when" statements as an asynchronous - ## function. - ## - ## ss_name: SumState name. - ## - ## Returns: The result table for the requested sumstat. - global request: function(ss_name: string): ResultTable; - ## Dynamically request a sumstat key. This function should be ## used sparingly and not as a replacement for the callbacks ## from the :bro:see:`SumStat` record. The function is only @@ -182,6 +162,9 @@ export { global key2str: function(key: SumStats::Key): string; } +# Type to store a table of sumstats results indexed by keys. +type ResultTable: table[Key] of Result; + # The function prototype for plugins to do calculations. type ObserveFunc: function(r: Reducer, val: double, data: Observation, rv: ResultVal); @@ -423,7 +406,7 @@ function observe(id: string, key: Key, obs: Observation) local ss = stats_store[r$ssname]; - # If there is a threshold and no epoch_finished callback + # If there is a threshold and no epoch_result callback # we don't need to continue counting since the data will # never be accessed. This was leading # to some state management issues when measuring @@ -431,7 +414,7 @@ function observe(id: string, key: Key, obs: Observation) # NOTE: this optimization could need removed in the # future if on demand access is provided to the # SumStats results. - if ( ! ss?$epoch_finished && + if ( ! ss?$epoch_result && r$ssname in threshold_tracker && ( ss?$threshold && key in threshold_tracker[r$ssname] && diff --git a/scripts/base/frameworks/sumstats/non-cluster.bro b/scripts/base/frameworks/sumstats/non-cluster.bro index 265261f1bd..b7e18bd55a 100644 --- a/scripts/base/frameworks/sumstats/non-cluster.bro +++ b/scripts/base/frameworks/sumstats/non-cluster.bro @@ -6,10 +6,13 @@ event SumStats::finish_epoch(ss: SumStat) { if ( ss$name in result_store ) { - local data = result_store[ss$name]; - if ( ss?$epoch_finished ) - ss$epoch_finished(data); - + if ( ss?$epoch_result ) + { + local data = result_store[ss$name]; + # TODO: don't block here. + for ( key in data ) + ss$epoch_result(network_time(), key, data[key]); + } reset(ss); } From af9e181731b82167187b7a9ec8995b991920c0e1 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 30 Jul 2013 10:29:27 -0700 Subject: [PATCH 154/881] Updating submodule(s). [nomail] --- magic | 1 + 1 file changed, 1 insertion(+) create mode 160000 magic diff --git a/magic b/magic new file mode 160000 index 0000000000..e87fe13a7b --- /dev/null +++ b/magic @@ -0,0 +1 @@ +Subproject commit e87fe13a7b776182ffc8c75076d42702f5c28fed From 8df4df0b8b7c8760d830c0f99e26e8f4db66967a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 30 Jul 2013 15:19:48 -0500 Subject: [PATCH 155/881] Add a distinct tag class for file analyzers. This should prevent assignment mismatches between file and protocol analyzer tags. --- src/CMakeLists.txt | 1 + src/Tag.cc | 82 ++++++++++++++++++ src/Tag.h | 138 +++++++++++++++++++++++++++++++ src/analyzer/Component.cc | 2 +- src/analyzer/Manager.cc | 2 +- src/analyzer/Tag.cc | 84 ++----------------- src/analyzer/Tag.h | 93 ++++++--------------- src/file_analysis/CMakeLists.txt | 1 + src/file_analysis/Component.cc | 8 +- src/file_analysis/Component.h | 16 ++-- src/file_analysis/Manager.h | 2 +- src/file_analysis/Tag.cc | 24 ++++++ src/file_analysis/Tag.h | 115 ++++++++++++++++++++++++++ 13 files changed, 407 insertions(+), 161 deletions(-) create mode 100644 src/Tag.cc create mode 100644 src/Tag.h create mode 100644 src/file_analysis/Tag.cc create mode 100644 src/file_analysis/Tag.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e353dd4695..082f34fba1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -315,6 +315,7 @@ set(bro_SRCS StateAccess.cc Stats.cc Stmt.cc + Tag.cc Timer.cc Traverse.cc Trigger.cc diff --git a/src/Tag.cc b/src/Tag.cc new file mode 100644 index 0000000000..178edaa71e --- /dev/null +++ b/src/Tag.cc @@ -0,0 +1,82 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Tag.h" +#include "Val.h" + +Tag::Tag(EnumType* etype, type_t arg_type, subtype_t arg_subtype) + { + assert(arg_type > 0); + + type = arg_type; + subtype = arg_subtype; + int64_t i = (int64)(type) | ((int64)subtype << 31); + Ref(etype); + val = new EnumVal(i, etype); + } + +Tag::Tag(EnumVal* arg_val) + { + assert(arg_val); + + val = arg_val; + Ref(val); + + int64 i = val->InternalInt(); + type = i & 0xffffffff; + subtype = (i >> 31) & 0xffffffff; + } + +Tag::Tag(const Tag& other) + { + type = other.type; + subtype = other.subtype; + val = other.val; + + if ( val ) + Ref(val); + } + +Tag::Tag() + { + type = 0; + subtype = 0; + val = 0; + } + +Tag::~Tag() + { + Unref(val); + val = 0; + } + +Tag& Tag::operator=(const Tag& other) + { + if ( this != &other ) + { + type = other.type; + subtype = other.subtype; + val = other.val; + + if ( val ) + Ref(val); + } + + return *this; + } + +EnumVal* Tag::AsEnumVal(EnumType* etype) const + { + if ( ! val ) + { + assert(type == 0 && subtype == 0); + Ref(etype); + val = new EnumVal(0, etype); + } + + return val; + } + +std::string Tag::AsString() const + { + return fmt("%" PRIu32 "/%" PRIu32, type, subtype); + } diff --git a/src/Tag.h b/src/Tag.h new file mode 100644 index 0000000000..a0c218019e --- /dev/null +++ b/src/Tag.h @@ -0,0 +1,138 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef TAG_H +#define TAG_H + +#include "config.h" +#include "util.h" +#include "Type.h" + +class EnumVal; + +/** + * Class to identify an analyzer type. + * + * Each analyzer type gets a tag consisting of a main type and subtype. The + * former is an identifier that's unique all analyzer classes. The latter is + * passed through to the analyzer instances for their use, yet not further + * interpreted by the analyzer infrastructure; it allows an analyzer to + * branch out into a set of sub-analyzers internally. Jointly, main type and + * subtype form an analyzer "tag". Each unique tag corresponds to a single + * "analyzer" from the user's perspective. At the script layer, these tags + * are mapped into enums of type \c Analyzer::Tag or Files::Tag. Internally, + * the analyzer::Manager and file_analysis::Manager maintain the mapping of tag + * to analyzer (and it also assigns them their main types), and + * analyzer::Component and file_analysis::Component create new tag. + * + * The Tag class supports all operations necessary to act as an index in a + * \c std::map. + */ +class Tag { +public: + /** + * Type for the analyzer's main type. + */ + typedef uint32 type_t; + + /** + * Type for the analyzer's subtype. + */ + typedef uint32 subtype_t; + + /** + * Returns the tag's main type. + */ + type_t Type() const { return type; } + + /** + * Returns the tag's subtype. + */ + subtype_t Subtype() const { return subtype; } + + /** + * Returns the numerical values for main and subtype inside a string + * suitable for printing. This is primarily for debugging. + */ + std::string AsString() const; + +protected: + /* + * Copy constructor. + */ + Tag(const Tag& other); + + /** + * Default constructor. This initializes the tag with an error value + * that will make \c operator \c bool return false. + */ + Tag(); + + /** + * Destructor. + */ + ~Tag(); + + /** + * Assignment operator. + */ + Tag& operator=(const Tag& other); + + /** + * Compares two tags for equality. + */ + bool operator==(const Tag& other) const + { + return type == other.type && subtype == other.subtype; + } + + /** + * Compares two tags for inequality. + */ + bool operator!=(const Tag& other) const + { + return type != other.type || subtype != other.subtype; + } + + /** + * Compares two tags for less-than relationship. + */ + bool operator<(const Tag& other) const + { + return type != other.type ? type < other.type : (subtype < other.subtype); + } + + /** + * Returns the script-layer enum that corresponds to this tag. + * The returned value does not have its ref-count increased. + * + * @param etype the script-layer enum type associated with the tag. + */ + EnumVal* AsEnumVal(EnumType* etype) const; + + /** + * Constructor. + * + * @param etype the script-layer enum type associated with the tag. + * + * @param type The main type. Note that the manager class manages the + * the value space internally, so noone else should assign main types. + * + * @param subtype The sub type, which is left to an analyzer for + * interpretation. By default it's set to zero. + */ + Tag(EnumType* etype, type_t type, subtype_t subtype = 0); + + /** + * Constructor. + * + * @param val An enum value of script type \c Analyzer::Tag. + */ + Tag(EnumVal* val); + +private: + type_t type; // Main type. + subtype_t subtype; // Subtype. + mutable EnumVal* val; // Script-layer value. +}; + +#endif diff --git a/src/analyzer/Component.cc b/src/analyzer/Component.cc index cbb0f40c20..ded0a1a2d5 100644 --- a/src/analyzer/Component.cc +++ b/src/analyzer/Component.cc @@ -8,7 +8,7 @@ using namespace analyzer; -Tag::type_t Component::type_counter = 0; +analyzer::Tag::type_t Component::type_counter = 0; Component::Component(const char* arg_name, factory_callback arg_factory, Tag::subtype_t arg_subtype, bool arg_enabled, bool arg_partial) : plugin::Component(plugin::component::ANALYZER) diff --git a/src/analyzer/Manager.cc b/src/analyzer/Manager.cc index 5695dec625..3f97cbb0c8 100644 --- a/src/analyzer/Manager.cc +++ b/src/analyzer/Manager.cc @@ -341,7 +341,7 @@ const char* Manager::GetAnalyzerName(Val* val) return GetAnalyzerName(Tag(val->AsEnumVal())); } -Tag Manager::GetAnalyzerTag(const char* name) +analyzer::Tag Manager::GetAnalyzerTag(const char* name) { Component* c = Lookup(name); return c ? c->Tag() : Tag(); diff --git a/src/analyzer/Tag.cc b/src/analyzer/Tag.cc index 2f04ff17da..3ab41daf78 100644 --- a/src/analyzer/Tag.cc +++ b/src/analyzer/Tag.cc @@ -3,90 +3,20 @@ #include "Tag.h" #include "Manager.h" -#include "../NetVar.h" +analyzer::Tag analyzer::Tag::Error; -using namespace analyzer; - -Tag Tag::Error; - -Tag::Tag(type_t arg_type, subtype_t arg_subtype) +analyzer::Tag::Tag(type_t type, subtype_t subtype) + : ::Tag(analyzer_mgr->GetTagEnumType(), type, subtype) { - assert(arg_type > 0); - - type = arg_type; - subtype = arg_subtype; - int64_t i = (int64)(type) | ((int64)subtype << 31); - - EnumType* etype = analyzer_mgr->GetTagEnumType(); - Ref(etype); - val = new EnumVal(i, etype); } -Tag::Tag(EnumVal* arg_val) +analyzer::Tag& analyzer::Tag::operator=(const analyzer::Tag& other) { - assert(arg_val); - - val = arg_val; - Ref(val); - - int64 i = val->InternalInt(); - type = i & 0xffffffff; - subtype = (i >> 31) & 0xffffffff; - } - -Tag::Tag(const Tag& other) - { - type = other.type; - subtype = other.subtype; - val = other.val; - - if ( val ) - Ref(val); - } - -Tag::Tag() - { - type = 0; - subtype = 0; - val = 0; - } - -Tag::~Tag() - { - Unref(val); - val = 0; - } - -Tag& Tag::operator=(const Tag& other) - { - if ( this != &other ) - { - type = other.type; - subtype = other.subtype; - val = other.val; - - if ( val ) - Ref(val); - } - + ::Tag::operator=(other); return *this; } -EnumVal* Tag::AsEnumVal() const +EnumVal* analyzer::Tag::AsEnumVal() const { - if ( ! val ) - { - assert(analyzer_mgr); - assert(type == 0 && subtype == 0); - EnumType* etype = analyzer_mgr->GetTagEnumType(); - Ref(etype); - val = new EnumVal(0, etype); - } - - return val; - } - -std::string Tag::AsString() const - { - return fmt("%" PRIu32 "/%" PRIu32, type, subtype); + return ::Tag::AsEnumVal(analyzer_mgr->GetTagEnumType()); } diff --git a/src/analyzer/Tag.h b/src/analyzer/Tag.h index edb0ade8a7..8ac151e4b5 100644 --- a/src/analyzer/Tag.h +++ b/src/analyzer/Tag.h @@ -5,90 +5,44 @@ #include "config.h" #include "util.h" +#include "../Tag.h" class EnumVal; -namespace file_analysis { -class Manager; -class Component; -} - namespace analyzer { class Manager; class Component; /** - * Class to identify an analyzer type. + * Class to identify a protocol analyzer type. * - * Each analyzer type gets a tag consisting of a main type and subtype. The - * former is an identifier that's unique all analyzer classes. The latter is - * passed through to the analyzer instances for their use, yet not further - * interpreted by the analyzer infrastructure; it allows an analyzer to - * branch out into a set of sub-analyzers internally. Jointly, main type and - * subtype form an analyzer "tag". Each unique tag corresponds to a single - * "analyzer" from the user's perspective. At the script layer, these tags - * are mapped into enums of type \c Analyzer::Tag. Internally, the - * analyzer::Manager maintains the mapping of tag to analyzer (and it also - * assigns them their main types), and analyzer::Component creates new - * tags. - * - * The Tag class supports all operations necessary to act as an index in a - * \c std::map. + * The script-layer analogue is Analyzer::Tag. */ -class Tag { +class Tag : public ::Tag { public: - /** - * Type for the analyzer's main type. - */ - typedef uint32 type_t; - - /** - * Type for the analyzer's subtype. - */ - typedef uint32 subtype_t; - /* * Copy constructor. */ - Tag(const Tag& other); + Tag(const Tag& other) : ::Tag(other) {} /** * Default constructor. This initializes the tag with an error value * that will make \c operator \c bool return false. */ - Tag(); + Tag() : ::Tag() {} /** * Destructor. */ - ~Tag(); - - /** - * Returns the tag's main type. - */ - type_t Type() const { return type; } - - /** - * Returns the tag's subtype. - */ - subtype_t Subtype() const { return subtype; } - - /** - * Returns the \c Analyzer::Tag enum that corresponds to this tag. - * The returned value is \a does not have its ref-count increased. - */ - EnumVal* AsEnumVal() const; - - /** - * Returns the numerical values for main and subtype inside a string - * suitable for printing. This is primarily for debugging. - */ - std::string AsString() const; + ~Tag() {} /** * Returns false if the tag represents an error value rather than a * legal analyzer type. + * TODO: make this conversion operator "explicit" (C++11) or use a + * "safe bool" idiom (not necessary if "explicit" is available), + * otherwise this may allow nonsense/undesired comparison operations. */ operator bool() const { return *this != Tag(); } @@ -102,7 +56,7 @@ public: */ bool operator==(const Tag& other) const { - return type == other.type && subtype == other.subtype; + return ::Tag::operator==(other); } /** @@ -110,7 +64,7 @@ public: */ bool operator!=(const Tag& other) const { - return type != other.type || subtype != other.subtype; + return ::Tag::operator!=(other); } /** @@ -118,23 +72,29 @@ public: */ bool operator<(const Tag& other) const { - return type != other.type ? type < other.type : (subtype < other.subtype); + return ::Tag::operator<(other); } + /** + * Returns the \c Analyzer::Tag enum that corresponds to this tag. + * The returned value does not have its ref-count increased. + * + * @param etype the script-layer enum type associated with the tag. + */ + EnumVal* AsEnumVal() const; + static Tag Error; protected: friend class analyzer::Manager; friend class analyzer::Component; - friend class file_analysis::Manager; - friend class file_analysis::Component; /** * Constructor. * * @param type The main type. Note that the \a analyzer::Manager * manages the value space internally, so noone else should assign - * any main tyoes. + * any main types. * * @param subtype The sub type, which is left to an analyzer for * interpretation. By default it's set to zero. @@ -144,14 +104,9 @@ protected: /** * Constructor. * - * @param val An enuam value of script type \c Analyzer::Tag. + * @param val An enum value of script type \c Analyzer::Tag. */ - Tag(EnumVal* val); - -private: - type_t type; // Main type. - subtype_t subtype; // Subtype. - mutable EnumVal* val; // Analyzer::Tag value. + Tag(EnumVal* val) : ::Tag(val) {} }; } diff --git a/src/file_analysis/CMakeLists.txt b/src/file_analysis/CMakeLists.txt index f22c293cc4..709790cfaf 100644 --- a/src/file_analysis/CMakeLists.txt +++ b/src/file_analysis/CMakeLists.txt @@ -14,6 +14,7 @@ set(file_analysis_SRCS Analyzer.h AnalyzerSet.cc Component.cc + Tag.cc ) bif_target(file_analysis.bif) diff --git a/src/file_analysis/Component.cc b/src/file_analysis/Component.cc index 99531e40f5..8ddd9cceaf 100644 --- a/src/file_analysis/Component.cc +++ b/src/file_analysis/Component.cc @@ -8,17 +8,17 @@ using namespace file_analysis; -analyzer::Tag::type_t Component::type_counter = 0; +file_analysis::Tag::type_t Component::type_counter = 0; Component::Component(const char* arg_name, factory_callback arg_factory, - analyzer::Tag::subtype_t arg_subtype) + file_analysis::Tag::subtype_t arg_subtype) : plugin::Component(plugin::component::FILE_ANALYZER) { name = copy_string(arg_name); canon_name = canonify_name(arg_name); factory = arg_factory; - tag = analyzer::Tag(++type_counter, arg_subtype); + tag = file_analysis::Tag(++type_counter, arg_subtype); } Component::Component(const Component& other) @@ -36,7 +36,7 @@ Component::~Component() delete [] canon_name; } -analyzer::Tag Component::Tag() const +file_analysis::Tag Component::Tag() const { return tag; } diff --git a/src/file_analysis/Component.h b/src/file_analysis/Component.h index 3cdc69efdf..bd690bc081 100644 --- a/src/file_analysis/Component.h +++ b/src/file_analysis/Component.h @@ -3,7 +3,7 @@ #ifndef FILE_ANALYZER_PLUGIN_COMPONENT_H #define FILE_ANALYZER_PLUGIN_COMPONENT_H -#include "analyzer/Tag.h" +#include "Tag.h" #include "plugin/Component.h" #include "Val.h" @@ -41,12 +41,12 @@ public: * * @param subtype A subtype associated with this component that * further distinguishes it. The subtype will be integrated into - * the analyzer::Tag that the manager associates with this analyzer, - * and analyzer instances can accordingly access it via analyzer::Tag(). - * If not used, leave at zero. + * the file_analysis::Tag that the manager associates with this analyzer, + * and analyzer instances can accordingly access it via + * file_analysis::Tag(). If not used, leave at zero. */ Component(const char* name, factory_callback factory, - analyzer::Tag::subtype_t subtype = 0); + file_analysis::Tag::subtype_t subtype = 0); /** * Copy constructor. @@ -84,7 +84,7 @@ public: * generated for each new Components, and hence unique across all of * them. */ - analyzer::Tag Tag() const; + file_analysis::Tag Tag() const; /** * Generates a human-readable description of the component's main @@ -98,10 +98,10 @@ private: const char* name; // The analyzer's name. const char* canon_name; // The analyzer's canonical name. factory_callback factory; // The analyzer's factory callback. - analyzer::Tag tag; // The automatically assigned analyzer tag. + file_analysis::Tag tag; // The automatically assigned analyzer tag. // Global counter used to generate unique tags. - static analyzer::Tag::type_t type_counter; + static file_analysis::Tag::type_t type_counter; }; } diff --git a/src/file_analysis/Manager.h b/src/file_analysis/Manager.h index a93e78c638..55ff0896d7 100644 --- a/src/file_analysis/Manager.h +++ b/src/file_analysis/Manager.h @@ -294,7 +294,7 @@ protected: private: typedef map analyzer_map_by_name; - typedef map analyzer_map_by_tag; + typedef map analyzer_map_by_tag; typedef map analyzer_map_by_val; void RegisterAnalyzerComponent(Component* component); diff --git a/src/file_analysis/Tag.cc b/src/file_analysis/Tag.cc new file mode 100644 index 0000000000..6f0774a4b4 --- /dev/null +++ b/src/file_analysis/Tag.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Tag.h" +#include "Manager.h" + +using namespace file_analysis; + +file_analysis::Tag file_analysis::Tag::Error; + +file_analysis::Tag::Tag(type_t type, subtype_t subtype) + : ::Tag(file_mgr->GetTagEnumType(), type, subtype) + { + } + +file_analysis::Tag& file_analysis::Tag::operator=(const file_analysis::Tag& other) + { + ::Tag::operator=(other); + return *this; + } + +EnumVal* file_analysis::Tag::AsEnumVal() const + { + return ::Tag::AsEnumVal(file_mgr->GetTagEnumType()); + } diff --git a/src/file_analysis/Tag.h b/src/file_analysis/Tag.h new file mode 100644 index 0000000000..85c20da5b5 --- /dev/null +++ b/src/file_analysis/Tag.h @@ -0,0 +1,115 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef FILE_ANALYZER_TAG_H +#define FILE_ANALYZER_TAG_H + +#include "config.h" +#include "util.h" +#include "../Tag.h" + +class EnumVal; + +namespace file_analysis { + +class Manager; +class Component; + +/** + * Class to identify a file analyzer type. + * + * The script-layer analogue is Files::Tag. + */ +class Tag : public ::Tag { +public: + /* + * Copy constructor. + */ + Tag(const Tag& other) : ::Tag(other) {} + + /** + * Default constructor. This initializes the tag with an error value + * that will make \c operator \c bool return false. + */ + Tag() : ::Tag() {} + + /** + * Destructor. + */ + ~Tag() {} + + /** + * Returns false if the tag represents an error value rather than a + * legal analyzer type. + * TODO: make this conversion operator "explicit" (C++11) or use a + * "safe bool" idiom (not necessary if "explicit" is available), + * otherwise this may allow nonsense/undesired comparison operations. + * + */ + operator bool() const { return *this != Tag(); } + + /** + * Assignment operator. + */ + Tag& operator=(const Tag& other); + + /** + * Compares two tags for equality. + */ + bool operator==(const Tag& other) const + { + return ::Tag::operator==(other); + } + + /** + * Compares two tags for inequality. + */ + bool operator!=(const Tag& other) const + { + return ::Tag::operator!=(other); + } + + /** + * Compares two tags for less-than relationship. + */ + bool operator<(const Tag& other) const + { + return ::Tag::operator<(other); + } + + /** + * Returns the \c Files::Tag enum that corresponds to this tag. + * The returned value does not have its ref-count increased. + * + * @param etype the script-layer enum type associated with the tag. + */ + EnumVal* AsEnumVal() const; + + static Tag Error; + +protected: + friend class file_analysis::Manager; + friend class file_analysis::Component; + + /** + * Constructor. + * + * @param type The main type. Note that the \a file_analysis::Manager + * manages the value space internally, so noone else should assign + * main tyoes. + * + * @param subtype The sub type, which is left to an analyzer for + * interpretation. By default it's set to zero. + */ + Tag(type_t type, subtype_t subtype = 0); + + /** + * Constructor. + * + * @param val An enum value of script type \c Files::Tag. + */ + Tag(EnumVal* val) : ::Tag(val) {} +}; + +} + +#endif From edb04e6d8bfe68dddf6968ec37cf39ea3a47feab Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 30 Jul 2013 16:10:06 -0700 Subject: [PATCH 156/881] fix segfault that could be caused by merging an empty bloom-filter with a bloom-filter already containing values. I assume that it is ok to merge an empty bloom-filter with any bloom-filter - if not we have to change the patch to return an error in this case. --- src/OpaqueVal.cc | 5 ++++- src/probabilistic/bloom-filter.bif | 5 ++++- testing/btest/Baseline/bifs.bloomfilter/output | 1 + testing/btest/bifs/bloomfilter.bro | 5 +++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 66b3c081e7..2b3236203b 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -591,7 +591,10 @@ bool BloomFilterVal::Empty() const BloomFilterVal* BloomFilterVal::Merge(const BloomFilterVal* x, const BloomFilterVal* y) { - if ( ! same_type(x->Type(), y->Type()) ) + if ( ( x->Type() != y->Type() ) && // both 0 is ok + ( x->Type() != 0 ) && // any one 0 also is ok + ( y->Type() != 0 ) && + ! same_type(x->Type(), y->Type()) ) { reporter->Error("cannot merge Bloom filters with different types"); return 0; diff --git a/src/probabilistic/bloom-filter.bif b/src/probabilistic/bloom-filter.bif index a3567ad6f7..5b06f95673 100644 --- a/src/probabilistic/bloom-filter.bif +++ b/src/probabilistic/bloom-filter.bif @@ -186,7 +186,10 @@ function bloomfilter_merge%(bf1: opaque of bloomfilter, const BloomFilterVal* bfv1 = static_cast(bf1); const BloomFilterVal* bfv2 = static_cast(bf2); - if ( ! same_type(bfv1->Type(), bfv2->Type()) ) + if ( ( bfv1->Type() != bfv2->Type() ) && // both 0 is ok + (bfv1->Type() != 0) && + (bfv2->Type() != 0) && + ! same_type(bfv1->Type(), bfv2->Type()) ) { reporter->Error("incompatible Bloom filter types"); return 0; diff --git a/testing/btest/Baseline/bifs.bloomfilter/output b/testing/btest/Baseline/bifs.bloomfilter/output index 14e1f038c0..991308e10b 100644 --- a/testing/btest/Baseline/bifs.bloomfilter/output +++ b/testing/btest/Baseline/bifs.bloomfilter/output @@ -17,6 +17,7 @@ error: false-positive rate must take value between 0 and 1 1 1 1 +1 2 3 3 diff --git a/testing/btest/bifs/bloomfilter.bro b/testing/btest/bifs/bloomfilter.bro index 3b40f29553..f2c882d175 100644 --- a/testing/btest/bifs/bloomfilter.bro +++ b/testing/btest/bifs/bloomfilter.bro @@ -45,6 +45,11 @@ function test_basic_bloom_filter() print bloomfilter_lookup(bf_merged, 84); print bloomfilter_lookup(bf_merged, 100); print bloomfilter_lookup(bf_merged, 168); + + #empty filter tests + local bf_empty = bloomfilter_basic_init(0.1, 1000); + local bf_empty_merged = bloomfilter_merge(bf_merged, bf_empty); + print bloomfilter_lookup(bf_empty_merged, 42); } function test_counting_bloom_filter() From 18c10f3cb53f63b24d393e56c96044b83e291a77 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 30 Jul 2013 16:47:26 -0700 Subject: [PATCH 157/881] get hll ready for merging --- src/OpaqueVal.cc | 171 +++++++++++------- src/OpaqueVal.h | 38 ++-- src/probabilistic/HyperLogLog.cc | 39 ++-- src/probabilistic/hyper-loglog.bif | 139 +++++++------- .../Baseline/bifs.hll_cardinality/.stderr | 1 + .../{bifs.hll_persistence => istate.hll}/out | 0 testing/btest/bifs/hll_cardinality.bro | 30 +-- .../btest/bifs/hll_persistence_twoseeds.bro | 40 ---- .../hll_persistence.bro => istate/hll.bro} | 0 9 files changed, 240 insertions(+), 218 deletions(-) create mode 100644 testing/btest/Baseline/bifs.hll_cardinality/.stderr rename testing/btest/Baseline/{bifs.hll_persistence => istate.hll}/out (100%) delete mode 100644 testing/btest/bifs/hll_persistence_twoseeds.bro rename testing/btest/{bifs/hll_persistence.bro => istate/hll.bro} (100%) diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 64990af3fc..e2e7e4f967 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -7,75 +7,6 @@ #include "probabilistic/HyperLogLog.h" -CardinalityVal::CardinalityVal() : OpaqueVal(cardinality_type) - { - valid = false; - } - -CardinalityVal::~CardinalityVal() - { - if ( valid && c != 0 ) - delete c; - c = 0; - valid = false; - } -IMPLEMENT_SERIAL(CardinalityVal, SER_CARDINALITY_VAL); - -bool CardinalityVal::DoSerialize(SerialInfo* info) const - { - DO_SERIALIZE(SER_CARDINALITY_VAL, OpaqueVal); - - bool serialvalid = true; - serialvalid &= SERIALIZE(&valid); - - if ( ! IsValid() ) - return serialvalid; - - assert(c); - - serialvalid &= SERIALIZE(c->m); - serialvalid &= SERIALIZE(c->V); - serialvalid &= SERIALIZE(c->alpha_m); - for ( unsigned int i = 0; i < c->m; i++ ) - serialvalid &= SERIALIZE( c->buckets[i] ); - - return serialvalid; - } - -bool CardinalityVal::DoUnserialize(UnserialInfo* info) - { - DO_UNSERIALIZE(OpaqueVal); - - bool serialvalid = UNSERIALIZE(&valid); - - if ( ! IsValid() ) - return serialvalid; - - uint64_t m; - - serialvalid &= UNSERIALIZE(&m); - c = new probabilistic::CardinalityCounter(m); - serialvalid &= UNSERIALIZE(&c->V); - serialvalid &= UNSERIALIZE(&c->alpha_m); - - uint8_t* buckets = c->buckets; - for ( unsigned int i = 0; i < m; i++ ) - { - uint8_t* currbucket = buckets + i; - serialvalid &= UNSERIALIZE( currbucket ); - } - return valid; - } - -bool CardinalityVal::Init(probabilistic::CardinalityCounter* arg_c) - { - if ( valid ) - return false; - - valid = true; - c = arg_c; - return valid; - } bool HashVal::IsValid() const { @@ -738,3 +669,105 @@ bool BloomFilterVal::DoUnserialize(UnserialInfo* info) bloom_filter = probabilistic::BloomFilter::Unserialize(info); return bloom_filter != 0; } + +CardinalityVal::CardinalityVal() : OpaqueVal(cardinality_type) + { + c = 0; + type = 0; + hash = 0; + } + +CardinalityVal::CardinalityVal(probabilistic::CardinalityCounter* arg_c) : OpaqueVal(cardinality_type) + { + c = arg_c; + type = 0; + hash = 0; + } + +CardinalityVal::~CardinalityVal() + { + Unref(type); + delete c; + delete hash; + } + +IMPLEMENT_SERIAL(CardinalityVal, SER_CARDINALITY_VAL); + +bool CardinalityVal::DoSerialize(SerialInfo* info) const + { + DO_SERIALIZE(SER_CARDINALITY_VAL, OpaqueVal); + + bool valid = true; + + bool is_typed = (type != 0); + + valid &= SERIALIZE(is_typed); + + if ( is_typed ) + valid &= type->Serialize(info); + + assert(c); + + valid &= SERIALIZE(c->m); + valid &= SERIALIZE(c->V); + valid &= SERIALIZE(c->alpha_m); + for ( unsigned int i = 0; i < c->m; i++ ) + valid &= SERIALIZE( c->buckets[i] ); + + return valid; + } + +bool CardinalityVal::DoUnserialize(UnserialInfo* info) + { + DO_UNSERIALIZE(OpaqueVal); + + uint64_t m; + bool valid = true; + + bool is_typed; + if ( ! UNSERIALIZE(&is_typed) ) + return false; + + if ( is_typed ) + { + BroType* t = BroType::Unserialize(info); + if ( ! Typify(t) ) + return false; + + Unref(t); + } + + valid &= UNSERIALIZE(&m); + c = new probabilistic::CardinalityCounter(m); + valid &= UNSERIALIZE(&c->V); + valid &= UNSERIALIZE(&c->alpha_m); + + uint8_t* buckets = c->buckets; + for ( unsigned int i = 0; i < m; i++ ) + { + uint8_t* currbucket = buckets + i; + valid &= UNSERIALIZE( currbucket ); + } + return valid; + } + +bool CardinalityVal::Typify(BroType* arg_type) + { + if ( type ) + return false; + + type = arg_type; + type->Ref(); + + TypeList* tl = new TypeList(type); + tl->Append(type); + hash = new CompositeHash(tl); + Unref(tl); + + return true; + } + +BroType* CardinalityVal::Type() const + { + return type; + } diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index a4414acd73..3a4b548308 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -15,22 +15,6 @@ namespace probabilistic { class CardinalityCounter; } -class CardinalityVal: public OpaqueVal { -public: - CardinalityVal(); - ~CardinalityVal(); - bool Init(probabilistic::CardinalityCounter*); - bool IsValid() const { return valid; }; - probabilistic::CardinalityCounter* Get() { return c; }; - -private: - bool valid; - probabilistic::CardinalityCounter* c; - - DECLARE_SERIAL(CardinalityVal); -}; - - class HashVal : public OpaqueVal { public: virtual bool IsValid() const; @@ -164,4 +148,26 @@ private: probabilistic::BloomFilter* bloom_filter; }; + +class CardinalityVal: public OpaqueVal { +public: + explicit CardinalityVal(probabilistic::CardinalityCounter*); + virtual ~CardinalityVal(); + + BroType* Type() const; + bool Typify(BroType* type); + + probabilistic::CardinalityCounter* Get() { return c; }; + +protected: + CardinalityVal(); + +private: + BroType* type; + CompositeHash* hash; + probabilistic::CardinalityCounter* c; + + DECLARE_SERIAL(CardinalityVal); +}; + #endif diff --git a/src/probabilistic/HyperLogLog.cc b/src/probabilistic/HyperLogLog.cc index b1deb39552..ea847b935f 100644 --- a/src/probabilistic/HyperLogLog.cc +++ b/src/probabilistic/HyperLogLog.cc @@ -4,23 +4,24 @@ #include #include "HyperLogLog.h" #include +#include "Reporter.h" using namespace probabilistic; int CardinalityCounter::optimalB(double error) { - double initial_estimate = 2*(log(1.04)-log(error))/log(2); - int answer = (int) floor(initial_estimate); - double k; + double initial_estimate = 2*(log(1.04)-log(error))/log(2); + int answer = (int) floor(initial_estimate); + double k; - do - { - answer++; - k = pow(2, (answer - initial_estimate)/2); - } - while (erf(k/sqrt(2)) < HLL_CONF); + do + { + answer++; + k = pow(2, (answer - initial_estimate)/2); + } + while (erf(k/sqrt(2)) < HLL_CONF); - return answer; + return answer; } CardinalityCounter::CardinalityCounter(uint64_t size) @@ -28,14 +29,16 @@ CardinalityCounter::CardinalityCounter(uint64_t size) m = size; buckets = new uint8_t[m]; - if(m == 16) + if (m == 16) alpha_m = 0.673; - else if(m == 32) + else if (m == 32) alpha_m = 0.697; - else if(m == 64) + else if (m == 64) alpha_m = 0.709; - else + else if (m >= 128) alpha_m = 0.7213/(1+1.079/m); + else + reporter->InternalError("Invalid size %lld. Size either has to be 16, 32, 64 or bigger than 128", size); for (uint64_t i = 0; i < m; i++) buckets[i] = 0; @@ -55,8 +58,10 @@ CardinalityCounter::CardinalityCounter(double error_margin) alpha_m = 0.697; else if(m == 64) alpha_m = 0.709; - else + else if(m >= 128) alpha_m = 0.7213/(1+1.079/m); + else + reporter->InternalError("Invalid m %lld calculated for error margin %f", m, error_margin); for (uint64_t i = 0; i < m; i++) buckets[i] = 0; @@ -96,7 +101,7 @@ void CardinalityCounter::addElement(uint64_t hash) if (temp > buckets[index]) buckets[index] = temp; -} + } double CardinalityCounter::size() { @@ -113,7 +118,7 @@ double CardinalityCounter::size() return answer; else return -pow(2,64)*log(1-answer/pow(2,64)); -} + } void CardinalityCounter::merge(CardinalityCounter* c) { diff --git a/src/probabilistic/hyper-loglog.bif b/src/probabilistic/hyper-loglog.bif index 24b18e0c40..012b2d2988 100644 --- a/src/probabilistic/hyper-loglog.bif +++ b/src/probabilistic/hyper-loglog.bif @@ -14,64 +14,88 @@ using namespace probabilistic; module GLOBAL; ## Initializes the hash for the HyperLogLog cardinality counting algorithm. -## It returns true if it was successful in creating a structure and false -## if it wasn't. - +## +## err: the desired error rate (e.g. 0.01). +## +## Returns: a hll cardinality handle. +## +## .. bro:see:: hll_cardinality_estimate hll_cardinality_merge_into hll_cardinality_add +## hll_cardinality_copy function hll_cardinality_init%(err: double%): opaque of cardinality %{ CardinalityCounter* c = new CardinalityCounter(err); - CardinalityVal* cv = new CardinalityVal(); - - if ( !c ) - reporter->Error("Failed initialize Cardinality counter"); - else - cv->Init(c); + CardinalityVal* cv = new CardinalityVal(c); return cv; %} -## Adds an element to the HyperLogLog data structure located at index. - -##elem->Type() to get the type of elem. - +## Adds an element to the HyperLogLog data structure +## +## handle: the hll handle. +## +## elem: the element to add +## +## Returns: 1 on success +## +## .. bro:see:: hll_cardinality_estimate hll_cardinality_merge_into +## hll_cardinality_init hll_cardinality_copy function hll_cardinality_add%(handle: opaque of cardinality, elem: any%): bool %{ - if ( !((CardinalityVal*) handle)->IsValid() ) { - reporter->Error("Need valid handle"); + CardinalityVal* cv = static_cast(handle); + + if ( ! cv->Type() && ! cv->Typify(elem->Type()) ) + { + reporter->Error("failed to set HLL type"); return new Val(0, TYPE_BOOL); - } + } + else if ( ! same_type(cv->Type(), elem->Type()) ) + { + reporter->Error("incompatible HLL data type"); + return new Val(0, TYPE_BOOL); + } int status = 0; - uint64_t a = 123456; TypeList* tl = new TypeList(elem->Type()); tl->Append(elem->Type()); CompositeHash* hll_hash = new CompositeHash(tl); Unref(tl); - CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); HashKey* key = hll_hash->ComputeHash(elem, 1); - a = key->Hash(); - h->addElement(a); + uint64_t hash = key->Hash(); + + CardinalityCounter* h = cv->Get(); + h->addElement(hash); delete hll_hash; return new Val(1, TYPE_BOOL); %} -## The data structure at index1 will contain the combined count for the -## elements measured by index1 and index2. -## It returns true if it either cloned the value at index2 into index1 -## or if it merged the two data structures together. - +## Merges the second hll data structure into the first +## +## .. note:: The same restrictions as for bloom-filter merging apply +## +## handle1: the first hll handle, which will contain the merged result +## +## handle2: the second hll handle, which will be merged into the first +## +## Returns: 1 on success +## +## .. bro:see:: hll_cardinality_estimate hll_cardinality_add +## hll_cardinality_init hll_cardinality_copy function hll_cardinality_merge_into%(handle1: opaque of cardinality, handle2: opaque of cardinality%): bool %{ - CardinalityVal* v1 = (CardinalityVal*) handle1; - CardinalityVal* v2 = (CardinalityVal*) handle2; + CardinalityVal* v1 = static_cast(handle1); + CardinalityVal* v2 = static_cast(handle2); - if ( !v1->IsValid() || !v2->IsValid() ) { - reporter->Error("need valid handles"); + if ( ( v1->Type() != v2->Type() ) && // both 0 is ok + ( v1->Type() != 0 ) && // any one 0 also is ok + ( v2->Type() != 0 ) && + ! same_type(v1->Type(), v2->Type()) ) + { + reporter->Error("incompatible HLL types"); return new Val(0, TYPE_BOOL); - } + } CardinalityCounter* h1 = v1->Get(); CardinalityCounter* h2 = v2->Get(); @@ -81,51 +105,42 @@ function hll_cardinality_merge_into%(handle1: opaque of cardinality, handle2: op return new Val(1, TYPE_BOOL); %} -## Returns true if it destroyed something. False if it didn't. -#function hll_cardinality_destroy%(handle: opaque of cardinality%): bool -# %{ -# if ( !((CardinalityVal*) handle)->IsValid() ) { -# reporter->Error("Need valid handle"); -# return new Val(0, TYPE_BOOL); -# } -# CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); -# delete h; -# h = 0; -# return new Val(1, TYPE_BOOL); -# %} - -## Returns the cardinality estimate. Returns -1.0 if there is nothing in that index. +## Estimate the cardinality of the HLL data structure. +## +## handle: the hll handle +## +## Returns the cardinality estimate. Returns -1.0 if the structure is empty +## +## .. bro:see:: hll_cardinality_merge_into hll_cardinality_add +## hll_cardinality_init hll_cardinality_copy function hll_cardinality_estimate%(handle: opaque of cardinality%): double %{ - if ( !((CardinalityVal*) handle)->IsValid() ) { - reporter->Error("Need valid handle"); - return new Val(0, TYPE_BOOL); - } - CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); + CardinalityVal* cv = static_cast(handle); + CardinalityCounter* h = cv->Get(); double estimate = h->size(); return new Val(estimate, TYPE_DOUBLE); %} -## Stores the data structure at index2 into index1. Deletes the data structure at index1 -## if there was any. Returns True if the data structure at index1 was changed in any way. - -function hll_cardinality_clone%(handle: opaque of cardinality%): opaque of cardinality +## Copy a hll data structure +## +## handle: data structure to copy +## +## Returns: copy of handle +## +## .. bro:see:: hll_cardinality_estimate hll_cardinality_merge_into hll_cardinality_add +## hll_cardinality_init +function hll_cardinality_copy%(handle: opaque of cardinality%): opaque of cardinality %{ - if ( !((CardinalityVal*) handle)->IsValid() ) { - reporter->Error("Need valid handle"); - return new Val(0, TYPE_BOOL); - } - CardinalityCounter* h = ((CardinalityVal*) handle)->Get(); - + CardinalityVal* cv = static_cast(handle); + CardinalityCounter* h = cv->Get(); uint64_t m = h->getM(); CardinalityCounter* h2 = new CardinalityCounter(m); int i = 0; h2->merge(h); - CardinalityVal* cv = new CardinalityVal(); - cv->Init(h2); - return cv; + CardinalityVal* out = new CardinalityVal(h2); + return out; %} diff --git a/testing/btest/Baseline/bifs.hll_cardinality/.stderr b/testing/btest/Baseline/bifs.hll_cardinality/.stderr new file mode 100644 index 0000000000..840ee3363e --- /dev/null +++ b/testing/btest/Baseline/bifs.hll_cardinality/.stderr @@ -0,0 +1 @@ +error: incompatible HLL data type diff --git a/testing/btest/Baseline/bifs.hll_persistence/out b/testing/btest/Baseline/istate.hll/out similarity index 100% rename from testing/btest/Baseline/bifs.hll_persistence/out rename to testing/btest/Baseline/istate.hll/out diff --git a/testing/btest/bifs/hll_cardinality.bro b/testing/btest/bifs/hll_cardinality.bro index 774e8f6e28..6d4075a4bf 100644 --- a/testing/btest/bifs/hll_cardinality.bro +++ b/testing/btest/bifs/hll_cardinality.bro @@ -1,35 +1,37 @@ # # @TEST-EXEC: bro %INPUT>out # @TEST-EXEC: btest-diff out +# @TEST-EXEC: btest-diff .stderr event bro_init() { local c1 = hll_cardinality_init(0.01); local c2 = hll_cardinality_init(0.01); - local add1 = "hey"; - local add2 = "hi"; - local add3 = 123; + local add1 = 2001; + local add2 = 2002; + local add3 = 2003; hll_cardinality_add(c1, add1); hll_cardinality_add(c1, add2); hll_cardinality_add(c1, add3); - hll_cardinality_add(c1, "a"); - hll_cardinality_add(c1, "b"); - hll_cardinality_add(c1, "c"); - hll_cardinality_add(c1, "d"); - hll_cardinality_add(c1, "e"); - hll_cardinality_add(c1, "f"); - hll_cardinality_add(c1, "g"); - hll_cardinality_add(c1, "h"); - hll_cardinality_add(c1, "i"); - hll_cardinality_add(c1, "j"); + hll_cardinality_add(c1, 1000); + hll_cardinality_add(c1, 1001); + hll_cardinality_add(c1, 101); + hll_cardinality_add(c1, 1003); + hll_cardinality_add(c1, 1004); + hll_cardinality_add(c1, 1005); + hll_cardinality_add(c1, 1006); + hll_cardinality_add(c1, 1007); + hll_cardinality_add(c1, 1008); + hll_cardinality_add(c1, 1009); hll_cardinality_add(c2, add1); hll_cardinality_add(c2, add2); hll_cardinality_add(c2, add3); hll_cardinality_add(c2, 1); hll_cardinality_add(c2, "b"); + hll_cardinality_add(c2, 101); hll_cardinality_add(c2, 2); hll_cardinality_add(c2, 3); hll_cardinality_add(c2, 4); @@ -49,7 +51,7 @@ event bro_init() print "This value should be around 0:"; print hll_cardinality_estimate(m2); - local c3 = hll_cardinality_clone(c1); + local c3 = hll_cardinality_copy(c1); print "This value should be around 13:"; print hll_cardinality_estimate(c3); diff --git a/testing/btest/bifs/hll_persistence_twoseeds.bro b/testing/btest/bifs/hll_persistence_twoseeds.bro deleted file mode 100644 index 4d828dafc9..0000000000 --- a/testing/btest/bifs/hll_persistence_twoseeds.bro +++ /dev/null @@ -1,40 +0,0 @@ -# @TEST-EXEC: BRO_SEED_FILE="" bro -b %INPUT runnumber=1 >out -# @TEST-EXEC: BRO_SEED_FILE="" bro -b %INPUT runnumber=2 >>out -# @TEST-EXEC: BRO_SEED_FILE="" bro -b %INPUT runnumber=3 >>out -# @TEST-EXEC: btest-diff out - -global runnumber: count &redef; # differentiate first and second run - -global card: opaque of cardinality &persistent; - -event bro_init() - { - print runnumber; - - if ( runnumber == 1 ) - { - card = hll_cardinality_init(0.01); - - hll_cardinality_add(card, "a"); - hll_cardinality_add(card, "b"); - hll_cardinality_add(card, "c"); - hll_cardinality_add(card, "d"); - hll_cardinality_add(card, "e"); - hll_cardinality_add(card, "f"); - hll_cardinality_add(card, "g"); - hll_cardinality_add(card, "h"); - hll_cardinality_add(card, "i"); - hll_cardinality_add(card, "j"); - } - - print hll_cardinality_estimate(card); - - if ( runnumber == 2 ) - { - hll_cardinality_add(card, "a"); - hll_cardinality_add(card, "b"); - hll_cardinality_add(card, "c"); - hll_cardinality_add(card, "aa"); - } - } - diff --git a/testing/btest/bifs/hll_persistence.bro b/testing/btest/istate/hll.bro similarity index 100% rename from testing/btest/bifs/hll_persistence.bro rename to testing/btest/istate/hll.bro From 83ce77e575cc99d1d922ca5bd6f47204e8ffd62e Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 30 Jul 2013 18:48:05 -0700 Subject: [PATCH 158/881] re-use same hash class for all add operations --- src/OpaqueVal.cc | 8 ++++++++ src/OpaqueVal.h | 2 ++ src/probabilistic/hyper-loglog.bif | 15 +-------------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index e2e7e4f967..dcf3e84430 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -771,3 +771,11 @@ BroType* CardinalityVal::Type() const { return type; } + +void CardinalityVal::Add(const Val* val) + { + HashKey* key = hash->ComputeHash(val, 1); + c->addElement(key->Hash()); + delete key; + } + diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index 3a4b548308..a7c51657c4 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -154,6 +154,8 @@ public: explicit CardinalityVal(probabilistic::CardinalityCounter*); virtual ~CardinalityVal(); + void Add(const Val* val); + BroType* Type() const; bool Typify(BroType* type); diff --git a/src/probabilistic/hyper-loglog.bif b/src/probabilistic/hyper-loglog.bif index 012b2d2988..6e69e70735 100644 --- a/src/probabilistic/hyper-loglog.bif +++ b/src/probabilistic/hyper-loglog.bif @@ -54,20 +54,7 @@ function hll_cardinality_add%(handle: opaque of cardinality, elem: any%): bool return new Val(0, TYPE_BOOL); } - int status = 0; - - TypeList* tl = new TypeList(elem->Type()); - tl->Append(elem->Type()); - CompositeHash* hll_hash = new CompositeHash(tl); - Unref(tl); - - HashKey* key = hll_hash->ComputeHash(elem, 1); - uint64_t hash = key->Hash(); - - CardinalityCounter* h = cv->Get(); - h->addElement(hash); - - delete hll_hash; + cv->Add(elem); return new Val(1, TYPE_BOOL); %} From 5fa9c5865b6748c642d91a01f3537331ee5747a9 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 31 Jul 2013 09:48:19 -0500 Subject: [PATCH 159/881] Factor out the need for a tag field in Files::AnalyzerArgs record. This cleans up internals of how analyzer instances get identified by the tag plus any args given to it and doesn't change script code a user would write. --- scripts/base/frameworks/files/main.bro | 12 +--- src/file_analysis/Analyzer.cc | 11 ++++ src/file_analysis/Analyzer.h | 30 ++-------- src/file_analysis/AnalyzerSet.cc | 56 ++++++++++--------- src/file_analysis/AnalyzerSet.h | 26 ++++++--- src/file_analysis/CMakeLists.txt | 2 +- src/file_analysis/File.cc | 18 +++--- src/file_analysis/File.h | 7 ++- src/file_analysis/Manager.cc | 56 ++++++++++++++----- src/file_analysis/Manager.h | 42 ++++++++++++-- .../analyzer/data_event/DataEvent.cc | 5 +- src/file_analysis/analyzer/extract/Extract.cc | 4 +- src/file_analysis/analyzer/hash/Hash.cc | 3 +- src/file_analysis/file_analysis.bif | 12 ++-- 14 files changed, 177 insertions(+), 107 deletions(-) create mode 100644 src/file_analysis/Analyzer.cc diff --git a/scripts/base/frameworks/files/main.bro b/scripts/base/frameworks/files/main.bro index a87608054d..c1883e037f 100644 --- a/scripts/base/frameworks/files/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -228,11 +228,6 @@ redef record fa_file += { info: Info &optional; }; -redef record AnalyzerArgs += { - # This is used interally for the core file analyzer api. - tag: Files::Tag &optional; -}; - # Store the callbacks for protocol analyzers that have files. global registered_protocols: table[Analyzer::Tag] of ProtoRegistration = table(); @@ -275,14 +270,12 @@ function set_timeout_interval(f: fa_file, t: interval): bool function add_analyzer(f: fa_file, tag: Files::Tag, args: AnalyzerArgs): bool { - # This is to construct the correct args for the core API. - args$tag = tag; add f$info$analyzers[Files::analyzer_name(tag)]; if ( tag in analyzer_add_callbacks ) analyzer_add_callbacks[tag](f, args); - if ( ! __add_analyzer(f$id, args) ) + if ( ! __add_analyzer(f$id, tag, args) ) { Reporter::warning(fmt("Analyzer %s not added successfully to file %s.", tag, f$id)); return F; @@ -297,8 +290,7 @@ function register_analyzer_add_callback(tag: Files::Tag, callback: function(f: f function remove_analyzer(f: fa_file, tag: Files::Tag, args: AnalyzerArgs): bool { - args$tag = tag; - return __remove_analyzer(f$id, args); + return __remove_analyzer(f$id, tag, args); } function stop(f: fa_file): bool diff --git a/src/file_analysis/Analyzer.cc b/src/file_analysis/Analyzer.cc new file mode 100644 index 0000000000..d472f4c80c --- /dev/null +++ b/src/file_analysis/Analyzer.cc @@ -0,0 +1,11 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Analyzer.h" +#include "Manager.h" + +file_analysis::Analyzer::~Analyzer() + { + DBG_LOG(DBG_FILE_ANALYSIS, "Destroy file analyzer %s", + file_mgr->GetAnalyzerName(tag)); + Unref(args); + } diff --git a/src/file_analysis/Analyzer.h b/src/file_analysis/Analyzer.h index 0a5aa9e25c..e20e2802cf 100644 --- a/src/file_analysis/Analyzer.h +++ b/src/file_analysis/Analyzer.h @@ -5,14 +5,12 @@ #include "Val.h" #include "NetVar.h" -#include "analyzer/Tag.h" +#include "Tag.h" #include "file_analysis/file_analysis.bif.h" namespace file_analysis { -typedef int FA_Tag; - class File; /** @@ -25,11 +23,7 @@ public: * Destructor. Nothing special about it. Virtual since we definitely expect * to delete instances of derived classes via pointers to this class. */ - virtual ~Analyzer() - { - DBG_LOG(DBG_FILE_ANALYSIS, "Destroy file analyzer %d", tag); - Unref(args); - } + virtual ~Analyzer(); /** * Subclasses may override this metod to receive file data non-sequentially. @@ -76,7 +70,7 @@ public: /** * @return the analyzer type enum value. */ - FA_Tag Tag() const { return tag; } + file_analysis::Tag Tag() const { return tag; } /** * @return the AnalyzerArgs associated with the analyzer. @@ -88,18 +82,6 @@ public: */ File* GetFile() const { return file; } - /** - * Retrieves an analyzer tag field from full analyzer argument record. - * @param args an \c AnalyzerArgs (script-layer type) value. - * @return the analyzer tag equivalent of the 'tag' field from the - * \c AnalyzerArgs value \a args. - */ - static FA_Tag ArgsTag(const RecordVal* args) - { - using BifType::Record::Files::AnalyzerArgs; - return args->Lookup(AnalyzerArgs->FieldOffset("tag"))->AsEnum(); - } - protected: /** @@ -108,15 +90,15 @@ protected: * tunable options, if any, related to a particular analyzer type. * @param arg_file the file to which the the analyzer is being attached. */ - Analyzer(RecordVal* arg_args, File* arg_file) - : tag(file_analysis::Analyzer::ArgsTag(arg_args)), + Analyzer(file_analysis::Tag arg_tag, RecordVal* arg_args, File* arg_file) + : tag(arg_tag), args(arg_args->Ref()->AsRecordVal()), file(arg_file) {} private: - FA_Tag tag; /**< The particular analyzer type of the analyzer instance. */ + file_analysis::Tag tag; /**< The particular type of the analyzer instance. */ RecordVal* args; /**< \c AnalyzerArgs val gives tunable analyzer params. */ File* file; /**< The file to which the analyzer is attached. */ }; diff --git a/src/file_analysis/AnalyzerSet.cc b/src/file_analysis/AnalyzerSet.cc index c710d8b085..befb676c87 100644 --- a/src/file_analysis/AnalyzerSet.cc +++ b/src/file_analysis/AnalyzerSet.cc @@ -15,6 +15,7 @@ static void analyzer_del_func(void* v) AnalyzerSet::AnalyzerSet(File* arg_file) : file(arg_file) { TypeList* t = new TypeList(); + t->Append(file_mgr->GetTagEnumType()); t->Append(BifType::Record::Files::AnalyzerArgs->Ref()); analyzer_hash = new CompositeHash(t); Unref(t); @@ -34,20 +35,20 @@ AnalyzerSet::~AnalyzerSet() delete analyzer_hash; } -bool AnalyzerSet::Add(RecordVal* args) +bool AnalyzerSet::Add(file_analysis::Tag tag, RecordVal* args) { - HashKey* key = GetKey(args); + HashKey* key = GetKey(tag, args); if ( analyzer_map.Lookup(key) ) { - DBG_LOG(DBG_FILE_ANALYSIS, "Instantiate analyzer %d skipped for file id" - " %s: already exists", file_analysis::Analyzer::ArgsTag(args), + DBG_LOG(DBG_FILE_ANALYSIS, "Instantiate analyzer %s skipped for file id" + " %s: already exists", file_mgr->GetAnalyzerName(tag), file->GetID().c_str()); delete key; return true; } - file_analysis::Analyzer* a = InstantiateAnalyzer(args); + file_analysis::Analyzer* a = InstantiateAnalyzer(tag, args); if ( ! a ) { @@ -60,10 +61,10 @@ bool AnalyzerSet::Add(RecordVal* args) return true; } -bool AnalyzerSet::QueueAdd(RecordVal* args) +bool AnalyzerSet::QueueAdd(file_analysis::Tag tag, RecordVal* args) { - HashKey* key = GetKey(args); - file_analysis::Analyzer* a = InstantiateAnalyzer(args); + HashKey* key = GetKey(tag, args); + file_analysis::Analyzer* a = InstantiateAnalyzer(tag, args); if ( ! a ) { @@ -80,8 +81,9 @@ bool AnalyzerSet::AddMod::Perform(AnalyzerSet* set) { if ( set->analyzer_map.Lookup(key) ) { - DBG_LOG(DBG_FILE_ANALYSIS, "Add analyzer %d skipped for file id" - " %s: already exists", a->Tag(), a->GetFile()->GetID().c_str()); + DBG_LOG(DBG_FILE_ANALYSIS, "Add analyzer %s skipped for file id" + " %s: already exists", file_mgr->GetAnalyzerName(a->Tag()), + a->GetFile()->GetID().c_str()); Abort(); return true; @@ -91,12 +93,12 @@ bool AnalyzerSet::AddMod::Perform(AnalyzerSet* set) return true; } -bool AnalyzerSet::Remove(const RecordVal* args) +bool AnalyzerSet::Remove(file_analysis::Tag tag, RecordVal* args) { - return Remove(file_analysis::Analyzer::ArgsTag(args), GetKey(args)); + return Remove(tag, GetKey(tag, args)); } -bool AnalyzerSet::Remove(FA_Tag tag, HashKey* key) +bool AnalyzerSet::Remove(file_analysis::Tag tag, HashKey* key) { file_analysis::Analyzer* a = (file_analysis::Analyzer*) analyzer_map.Remove(key); @@ -105,22 +107,22 @@ bool AnalyzerSet::Remove(FA_Tag tag, HashKey* key) if ( ! a ) { - DBG_LOG(DBG_FILE_ANALYSIS, "Skip remove analyzer %d for file id %s", - tag, file->GetID().c_str()); + DBG_LOG(DBG_FILE_ANALYSIS, "Skip remove analyzer %s for file id %s", + file_mgr->GetAnalyzerName(tag), file->GetID().c_str()); return false; } - DBG_LOG(DBG_FILE_ANALYSIS, "Remove analyzer %d for file id %s", a->Tag(), + DBG_LOG(DBG_FILE_ANALYSIS, "Remove analyzer %s for file id %s", + file_mgr->GetAnalyzerName(tag), file->GetID().c_str()); delete a; return true; } -bool AnalyzerSet::QueueRemove(const RecordVal* args) +bool AnalyzerSet::QueueRemove(file_analysis::Tag tag, RecordVal* args) { - HashKey* key = GetKey(args); - FA_Tag tag = file_analysis::Analyzer::ArgsTag(args); + HashKey* key = GetKey(tag, args); mod_queue.push(new RemoveMod(tag, key)); @@ -132,18 +134,22 @@ bool AnalyzerSet::RemoveMod::Perform(AnalyzerSet* set) return set->Remove(tag, key); } -HashKey* AnalyzerSet::GetKey(const RecordVal* args) const +HashKey* AnalyzerSet::GetKey(file_analysis::Tag t, RecordVal* args) const { - HashKey* key = analyzer_hash->ComputeHash(args, 1); + ListVal* lv = new ListVal(TYPE_ANY); + lv->Append(t.AsEnumVal()->Ref()); + lv->Append(args->Ref()); + HashKey* key = analyzer_hash->ComputeHash(lv, 1); + Unref(lv); if ( ! key ) reporter->InternalError("AnalyzerArgs type mismatch"); return key; } -file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(RecordVal* args) const +file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(Tag tag, + RecordVal* args) const { - FA_Tag tag = file_analysis::Analyzer::ArgsTag(args); file_analysis::Analyzer* a = file_mgr->InstantiateAnalyzer(tag, args, file); if ( ! a ) @@ -158,8 +164,8 @@ file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(RecordVal* args) const void AnalyzerSet::Insert(file_analysis::Analyzer* a, HashKey* key) { - DBG_LOG(DBG_FILE_ANALYSIS, "Add analyzer %d for file id %s", a->Tag(), - file->GetID().c_str()); + DBG_LOG(DBG_FILE_ANALYSIS, "Add analyzer %s for file id %s", + file_mgr->GetAnalyzerName(a->Tag()), file->GetID().c_str()); analyzer_map.Insert(key, a); delete key; } diff --git a/src/file_analysis/AnalyzerSet.h b/src/file_analysis/AnalyzerSet.h index 6f14149e30..42a54f4943 100644 --- a/src/file_analysis/AnalyzerSet.h +++ b/src/file_analysis/AnalyzerSet.h @@ -9,6 +9,7 @@ #include "Dict.h" #include "CompHash.h" #include "Val.h" +#include "Tag.h" namespace file_analysis { @@ -38,31 +39,35 @@ public: /** * Attach an analyzer to #file immediately. + * @param tag the analyzer tag of the file analyzer to add. * @param args an \c AnalyzerArgs value which specifies an analyzer. * @return true if analyzer was instantiated/attached, else false. */ - bool Add(RecordVal* args); + bool Add(file_analysis::Tag tag, RecordVal* args); /** * Queue the attachment of an analyzer to #file. + * @param tag the analyzer tag of the file analyzer to add. * @param args an \c AnalyzerArgs value which specifies an analyzer. * @return true if analyzer was able to be instantiated, else false. */ - bool QueueAdd(RecordVal* args); + bool QueueAdd(file_analysis::Tag tag, RecordVal* args); /** * Remove an analyzer from #file immediately. + * @param tag the analyzer tag of the file analyzer to remove. * @param args an \c AnalyzerArgs value which specifies an analyzer. * @return false if analyzer didn't exist and so wasn't removed, else true. */ - bool Remove(const RecordVal* args); + bool Remove(file_analysis::Tag tag, RecordVal* args); /** * Queue the removal of an analyzer from #file. + * @param tag the analyzer tag of the file analyzer to remove. * @param args an \c AnalyzerArgs value which specifies an analyzer. * @return true if analyzer exists at time of call, else false; */ - bool QueueRemove(const RecordVal* args); + bool QueueRemove(file_analysis::Tag tag, RecordVal* args); /** * Perform all queued modifications to the current analyzer set. @@ -91,17 +96,20 @@ protected: /** * Get a hash key which represents an analyzer instance. + * @param tag the file analyzer tag. * @param args an \c AnalyzerArgs value which specifies an analyzer. * @return the hash key calculated from \a args */ - HashKey* GetKey(const RecordVal* args) const; + HashKey* GetKey(file_analysis::Tag tag, RecordVal* args) const; /** * Create an instance of a file analyzer. + * @param tag the tag of a file analyzer. * @param args an \c AnalyzerArgs value which specifies an analyzer. * @return a new file analyzer instance. */ - file_analysis::Analyzer* InstantiateAnalyzer(RecordVal* args) const; + file_analysis::Analyzer* InstantiateAnalyzer(file_analysis::Tag tag, + RecordVal* args) const; /** * Insert an analyzer instance in to the set. @@ -116,7 +124,7 @@ protected: * just used for debugging messages. * @param key the hash key which represents the analyzer's \c AnalyzerArgs. */ - bool Remove(FA_Tag tag, HashKey* key); + bool Remove(file_analysis::Tag tag, HashKey* key); private: @@ -175,14 +183,14 @@ private: * @param arg_a an analyzer instance to add to an analyzer set. * @param arg_key hash key representing the analyzer's \c AnalyzerArgs. */ - RemoveMod(FA_Tag arg_tag, HashKey* arg_key) + RemoveMod(file_analysis::Tag arg_tag, HashKey* arg_key) : Modification(), tag(arg_tag), key(arg_key) {} virtual ~RemoveMod() {} virtual bool Perform(AnalyzerSet* set); virtual void Abort() { delete key; } protected: - FA_Tag tag; + file_analysis::Tag tag; HashKey* key; }; diff --git a/src/file_analysis/CMakeLists.txt b/src/file_analysis/CMakeLists.txt index 709790cfaf..846fc4bf15 100644 --- a/src/file_analysis/CMakeLists.txt +++ b/src/file_analysis/CMakeLists.txt @@ -11,7 +11,7 @@ set(file_analysis_SRCS Manager.cc File.cc FileTimer.cc - Analyzer.h + Analyzer.cc AnalyzerSet.cc Component.cc Tag.cc diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index 7189d90932..3db8ecdbee 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -230,14 +230,14 @@ void File::ScheduleInactivityTimer() const timer_mgr->Add(new FileTimer(network_time, id, GetTimeoutInterval())); } -bool File::AddAnalyzer(RecordVal* args) +bool File::AddAnalyzer(file_analysis::Tag tag, RecordVal* args) { - return done ? false : analyzers.QueueAdd(args); + return done ? false : analyzers.QueueAdd(tag, args); } -bool File::RemoveAnalyzer(const RecordVal* args) +bool File::RemoveAnalyzer(file_analysis::Tag tag, RecordVal* args) { - return done ? false : analyzers.QueueRemove(args); + return done ? false : analyzers.QueueRemove(tag, args); } bool File::BufferBOF(const u_char* data, uint64 len) @@ -320,7 +320,7 @@ void File::DataIn(const u_char* data, uint64 len, uint64 offset) while ( (a = analyzers.NextEntry(c)) ) { if ( ! a->DeliverChunk(data, len, offset) ) - analyzers.QueueRemove(a->Args()); + analyzers.QueueRemove(a->Tag(), a->Args()); } analyzers.DrainModifications(); @@ -355,7 +355,7 @@ void File::DataIn(const u_char* data, uint64 len) { if ( ! a->DeliverStream(data, len) ) { - analyzers.QueueRemove(a->Args()); + analyzers.QueueRemove(a->Tag(), a->Args()); continue; } @@ -363,7 +363,7 @@ void File::DataIn(const u_char* data, uint64 len) LookupFieldDefaultCount(missing_bytes_idx); if ( ! a->DeliverChunk(data, len, offset) ) - analyzers.QueueRemove(a->Args()); + analyzers.QueueRemove(a->Tag(), a->Args()); } analyzers.DrainModifications(); @@ -388,7 +388,7 @@ void File::EndOfFile() while ( (a = analyzers.NextEntry(c)) ) { if ( ! a->EndOfFile() ) - analyzers.QueueRemove(a->Args()); + analyzers.QueueRemove(a->Tag(), a->Args()); } FileEvent(file_state_remove); @@ -410,7 +410,7 @@ void File::Gap(uint64 offset, uint64 len) while ( (a = analyzers.NextEntry(c)) ) { if ( ! a->Undelivered(offset, len) ) - analyzers.QueueRemove(a->Args()); + analyzers.QueueRemove(a->Tag(), a->Args()); } if ( FileEventAvailable(file_gap) ) diff --git a/src/file_analysis/File.h b/src/file_analysis/File.h index 794734d24b..12c1e061a8 100644 --- a/src/file_analysis/File.h +++ b/src/file_analysis/File.h @@ -10,6 +10,7 @@ #include "Conn.h" #include "Val.h" +#include "Tag.h" #include "AnalyzerSet.h" #include "BroString.h" @@ -94,17 +95,19 @@ public: /** * Queues attaching an analyzer. Only one analyzer per type can be attached * at a time unless the arguments differ. + * @param tag the analyzer tag of the file analyzer to add. * @param args an \c AnalyzerArgs value representing a file analyzer. * @return false if analyzer can't be instantiated, else true. */ - bool AddAnalyzer(RecordVal* args); + bool AddAnalyzer(file_analysis::Tag tag, RecordVal* args); /** * Queues removal of an analyzer. + * @param tag the analyzer tag of the file analyzer to remove. * @param args an \c AnalyzerArgs value representing a file analyzer. * @return true if analyzer was active at time of call, else false. */ - bool RemoveAnalyzer(const RecordVal* args); + bool RemoveAnalyzer(file_analysis::Tag tag, RecordVal* args); /** * Pass in non-sequential data and deliver to attached analyzers. diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index fb74a409b4..c7fb1fc3b0 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -206,24 +206,26 @@ bool Manager::SetTimeoutInterval(const string& file_id, double interval) const return true; } -bool Manager::AddAnalyzer(const string& file_id, RecordVal* args) const +bool Manager::AddAnalyzer(const string& file_id, file_analysis::Tag tag, + RecordVal* args) const { File* file = Lookup(file_id); if ( ! file ) return false; - return file->AddAnalyzer(args); + return file->AddAnalyzer(tag, args); } -bool Manager::RemoveAnalyzer(const string& file_id, const RecordVal* args) const +bool Manager::RemoveAnalyzer(const string& file_id, file_analysis::Tag tag, + RecordVal* args) const { File* file = Lookup(file_id); if ( ! file ) return false; - return file->RemoveAnalyzer(args); + return file->RemoveAnalyzer(tag, args); } File* Manager::GetFile(const string& file_id, Connection* conn, @@ -367,13 +369,13 @@ bool Manager::IsDisabled(analyzer::Tag tag) return rval; } -Analyzer* Manager::InstantiateAnalyzer(int tag, RecordVal* args, File* f) const +Analyzer* Manager::InstantiateAnalyzer(Tag tag, RecordVal* args, File* f) const { - analyzer_map_by_val::const_iterator it = analyzers_by_val.find(tag); + analyzer_map_by_tag::const_iterator it = analyzers_by_tag.find(tag); - if ( it == analyzers_by_val.end() ) - reporter->InternalError("cannot instantiate unknown file analyzer: %d", - tag); + if ( it == analyzers_by_tag.end() ) + reporter->InternalError("cannot instantiate unknown file analyzer: %s", + tag.AsString().c_str()); Component* c = it->second; @@ -384,17 +386,43 @@ Analyzer* Manager::InstantiateAnalyzer(int tag, RecordVal* args, File* f) const return c->Factory()(args, f); } -const char* Manager::GetAnalyzerName(int tag) const +const char* Manager::GetAnalyzerName(Val* v) const { - analyzer_map_by_val::const_iterator it = analyzers_by_val.find(tag); + return GetAnalyzerName(file_analysis::Tag(v->AsEnumVal())); + } - if ( it == analyzers_by_val.end() ) - reporter->InternalError("cannot get name of unknown file analyzer: %d", - tag); +const char* Manager::GetAnalyzerName(file_analysis::Tag tag) const + { + analyzer_map_by_tag::const_iterator it = analyzers_by_tag.find(tag); + + if ( it == analyzers_by_tag.end() ) + reporter->InternalError("cannot get name of unknown file analyzer: %s", + tag.AsString().c_str()); return it->second->CanonicalName(); } +file_analysis::Tag Manager::GetAnalyzerTag(const char* name) const + { + analyzer_map_by_name::const_iterator it = analyzers_by_name.find(name); + + if ( it == analyzers_by_name.end() ) + return file_analysis::Tag(); + + return it->second->Tag(); + } + +file_analysis::Tag Manager::GetAnalyzerTag(Val* v) const + { + analyzer_map_by_val::const_iterator it = + analyzers_by_val.find(v->AsEnumVal()->InternalInt()); + + if ( it == analyzers_by_val.end() ) + return file_analysis::Tag(); + + return it->second->Tag(); + } + EnumType* Manager::GetTagEnumType() { return tag_enum_type; diff --git a/src/file_analysis/Manager.h b/src/file_analysis/Manager.h index 55ff0896d7..9a37042669 100644 --- a/src/file_analysis/Manager.h +++ b/src/file_analysis/Manager.h @@ -177,18 +177,22 @@ public: * analyzers of a given type can be attached per file identifier at a time * as long as the arguments differ. * @param file_id the file identifier/hash. + * @param tag the analyzer tag of the file analyzer to add. * @param args a \c AnalyzerArgs value which describes a file analyzer. * @return false if the analyzer failed to be instantiated, else true. */ - bool AddAnalyzer(const string& file_id, RecordVal* args) const; + bool AddAnalyzer(const string& file_id, file_analysis::Tag tag, + RecordVal* args) const; /** * Queue removal of an analyzer for a given file identifier. * @param file_id the file identifier/hash. + * @param tag the analyzer tag of the file analyzer to remove. * @param args a \c AnalyzerArgs value which describes a file analyzer. * @return true if the analyzer is active at the time of call, else false. */ - bool RemoveAnalyzer(const string& file_id, const RecordVal* args) const; + bool RemoveAnalyzer(const string& file_id, file_analysis::Tag tag, + RecordVal* args) const; /** * Tells whether analysis for a file is active or ignored. @@ -204,15 +208,43 @@ public: * @param f The file analzer is to be associated with. * @return The new analyzer instance or null if tag is invalid. */ - Analyzer* InstantiateAnalyzer(int tag, RecordVal* args, File* f) const; + Analyzer* InstantiateAnalyzer(Tag tag, RecordVal* args, File* f) const; /** * Translates a script-level file analyzer tag in to corresponding file * analyzer name. - * @param tag The enum val of a file analyzer. + * @param v The enum val of a file analyzer. * @return The human-readable name of the file analyzer. */ - const char* GetAnalyzerName(int tag) const; + const char* GetAnalyzerName(Val* v) const; + + /** + * Translates a script-level file analyzer tag in to corresponding file + * analyzer name. + * @param tag The analyzer tag of a file analyzer. + * @return The human-readable name of the file analyzer. + */ + const char* GetAnalyzerName(file_analysis::Tag tag) const; + + /** + * Translates an analyzer name into the corresponding tag. + * + * @param name The name. + * + * @return The tag. If the name does not correspond to a valid + * analyzer, the returned tag will evaluate to false. + */ + file_analysis::Tag GetAnalyzerTag(const char* name) const; + + /** + * Translates an analyzer enum value into the corresponding tag. + * + * @param v the enum val of the file analyzer. + * + * @return The tag. If the val does not correspond to a valid + * analyzer, the returned tag will evaluate to false. + */ + file_analysis::Tag GetAnalyzerTag(Val* v) const; /** * Returns the enum type that corresponds to the script-level type diff --git a/src/file_analysis/analyzer/data_event/DataEvent.cc b/src/file_analysis/analyzer/data_event/DataEvent.cc index 1b04111c44..44498f41e1 100644 --- a/src/file_analysis/analyzer/data_event/DataEvent.cc +++ b/src/file_analysis/analyzer/data_event/DataEvent.cc @@ -6,12 +6,15 @@ #include "EventRegistry.h" #include "Event.h" #include "util.h" +#include "file_analysis/Manager.h" using namespace file_analysis; DataEvent::DataEvent(RecordVal* args, File* file, EventHandlerPtr ce, EventHandlerPtr se) - : file_analysis::Analyzer(args, file), chunk_event(ce), stream_event(se) + : file_analysis::Analyzer(file_mgr->GetAnalyzerTag("DATA_EVENT"), + args, file), + chunk_event(ce), stream_event(se) { } diff --git a/src/file_analysis/analyzer/extract/Extract.cc b/src/file_analysis/analyzer/extract/Extract.cc index ef37425003..0de1402939 100644 --- a/src/file_analysis/analyzer/extract/Extract.cc +++ b/src/file_analysis/analyzer/extract/Extract.cc @@ -4,11 +4,13 @@ #include "Extract.h" #include "util.h" +#include "file_analysis/Manager.h" using namespace file_analysis; Extract::Extract(RecordVal* args, File* file, const string& arg_filename) - : file_analysis::Analyzer(args, file), filename(arg_filename) + : file_analysis::Analyzer(file_mgr->GetAnalyzerTag("EXTRACT"), args, file), + filename(arg_filename) { fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666); diff --git a/src/file_analysis/analyzer/hash/Hash.cc b/src/file_analysis/analyzer/hash/Hash.cc index 9835f343b6..12463df8bf 100644 --- a/src/file_analysis/analyzer/hash/Hash.cc +++ b/src/file_analysis/analyzer/hash/Hash.cc @@ -5,11 +5,12 @@ #include "Hash.h" #include "util.h" #include "Event.h" +#include "file_analysis/Manager.h" using namespace file_analysis; Hash::Hash(RecordVal* args, File* file, HashVal* hv, const char* arg_kind) - : file_analysis::Analyzer(args, file), hash(hv), fed(false), kind(arg_kind) + : file_analysis::Analyzer(file_mgr->GetAnalyzerTag(to_upper(string(arg_kind)).c_str()), args, file), hash(hv), fed(false), kind(arg_kind) { hash->Init(); } diff --git a/src/file_analysis/file_analysis.bif b/src/file_analysis/file_analysis.bif index b6c80ac800..7e07ddf6bb 100644 --- a/src/file_analysis/file_analysis.bif +++ b/src/file_analysis/file_analysis.bif @@ -16,21 +16,23 @@ function Files::__set_timeout_interval%(file_id: string, t: interval%): bool %} ## :bro:see:`Files::add_analyzer`. -function Files::__add_analyzer%(file_id: string, args: any%): bool +function Files::__add_analyzer%(file_id: string, tag: Files::Tag, args: any%): bool %{ using BifType::Record::Files::AnalyzerArgs; RecordVal* rv = args->AsRecordVal()->CoerceTo(AnalyzerArgs); - bool result = file_mgr->AddAnalyzer(file_id->CheckString(), rv); + bool result = file_mgr->AddAnalyzer(file_id->CheckString(), + file_mgr->GetAnalyzerTag(tag), rv); Unref(rv); return new Val(result, TYPE_BOOL); %} ## :bro:see:`Files::remove_analyzer`. -function Files::__remove_analyzer%(file_id: string, args: any%): bool +function Files::__remove_analyzer%(file_id: string, tag: Files::Tag, args: any%): bool %{ using BifType::Record::Files::AnalyzerArgs; RecordVal* rv = args->AsRecordVal()->CoerceTo(AnalyzerArgs); - bool result = file_mgr->RemoveAnalyzer(file_id->CheckString(), rv); + bool result = file_mgr->RemoveAnalyzer(file_id->CheckString(), + file_mgr->GetAnalyzerTag(tag) , rv); Unref(rv); return new Val(result, TYPE_BOOL); %} @@ -45,7 +47,7 @@ function Files::__stop%(file_id: string%): bool ## :bro:see:`Files::analyzer_name`. function Files::__analyzer_name%(tag: Files::Tag%) : string %{ - return new StringVal(file_mgr->GetAnalyzerName(tag->InternalInt())); + return new StringVal(file_mgr->GetAnalyzerName(tag)); %} module GLOBAL; From 8ca76dd4eea561f196b8ee39083a479121092337 Mon Sep 17 00:00:00 2001 From: Matthias Vallentin Date: Wed, 31 Jul 2013 17:59:08 +0200 Subject: [PATCH 160/881] Introduce global_hash_seed script variable. This commit adds support for script-level specification of a seed to be used by hashers. For example, if the given name of a Bloom filter is not empty, then the seed used by the underlying hasher only depends on the Bloom filter name. If the name is empty, we check whether the user defined a non-empty global_hash_seed string variable at script and use it instead. If that script variable does not exist, then we fall back to the initial seed computed a Bro startup (which is affected ultimately by $BRO_SEED). See Hasher::MakeSeed for details. --- src/NetVar.cc | 4 ++ src/NetVar.h | 2 + src/probabilistic/Hasher.cc | 85 ++++++++++++++---------------- src/probabilistic/Hasher.h | 45 +++++++++------- src/probabilistic/bloom-filter.bif | 9 +++- testing/btest/bifs/bloomfilter.bro | 4 +- 6 files changed, 82 insertions(+), 67 deletions(-) diff --git a/src/NetVar.cc b/src/NetVar.cc index 388aa46f10..2fee46e2da 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -238,6 +238,8 @@ TableType* record_field_table; StringVal* cmd_line_bpf_filter; +StringVal* global_hash_seed; + OpaqueType* md5_type; OpaqueType* sha1_type; OpaqueType* sha256_type; @@ -304,6 +306,8 @@ void init_general_global_var() cmd_line_bpf_filter = internal_val("cmd_line_bpf_filter")->AsStringVal(); + global_hash_seed = opt_internal_string("global_hash_seed"); + md5_type = new OpaqueType("md5"); sha1_type = new OpaqueType("sha1"); sha256_type = new OpaqueType("sha256"); diff --git a/src/NetVar.h b/src/NetVar.h index 7ce33d1a1a..3615108f73 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -242,6 +242,8 @@ extern TableType* record_field_table; extern StringVal* cmd_line_bpf_filter; +extern StringVal* global_hash_seed; + class OpaqueType; extern OpaqueType* md5_type; extern OpaqueType* sha1_type; diff --git a/src/probabilistic/Hasher.cc b/src/probabilistic/Hasher.cc index 17597b9a82..e24a207e6e 100644 --- a/src/probabilistic/Hasher.cc +++ b/src/probabilistic/Hasher.cc @@ -3,11 +3,34 @@ #include #include "Hasher.h" +#include "NetVar.h" #include "digest.h" #include "Serializer.h" using namespace probabilistic; +size_t Hasher::MakeSeed(const void* data, size_t size) + { + u_char buf[SHA256_DIGEST_LENGTH]; + SHA256_CTX ctx; + sha256_init(&ctx); + + if ( data ) + sha256_update(&ctx, data, size); + + else if ( global_hash_seed && global_hash_seed->Len() > 0 ) + sha256_update(&ctx, global_hash_seed->Bytes(), global_hash_seed->Len()); + + else + { + unsigned int first_seed = initial_seed(); + sha256_update(&ctx, &first_seed, sizeof(first_seed)); + } + + sha256_final(&ctx, buf); + return *reinterpret_cast(buf); // Use the first bytes as seed. + } + bool Hasher::Serialize(SerialInfo* info) const { return SerialObj::Serialize(info); @@ -25,7 +48,7 @@ bool Hasher::DoSerialize(SerialInfo* info) const if ( ! SERIALIZE(static_cast(k)) ) return false; - return SERIALIZE_STR(name.c_str(), name.size()); + return SERIALIZE(static_cast(seed)); } bool Hasher::DoUnserialize(UnserialInfo* info) @@ -35,30 +58,26 @@ bool Hasher::DoUnserialize(UnserialInfo* info) uint16 serial_k; if ( ! UNSERIALIZE(&serial_k) ) return false; - k = serial_k; assert(k > 0); - const char* serial_name; - if ( ! UNSERIALIZE_STR(&serial_name, 0) ) + uint64 serial_seed; + if ( ! UNSERIALIZE(&serial_seed) ) return false; - - name = serial_name; - delete [] serial_name; + seed = serial_seed; return true; } -Hasher::Hasher(size_t k, const std::string& arg_name) - : k(k) +Hasher::Hasher(size_t arg_k, size_t arg_seed) { - k = k; - name = arg_name; + k = arg_k; + seed = arg_seed; } -UHF::UHF(size_t seed, const std::string& extra) - : h(compute_seed(seed, extra)) +UHF::UHF(size_t seed) + : h(seed) { } @@ -68,33 +87,11 @@ Hasher::digest UHF::hash(const void* x, size_t n) const return n == 0 ? 0 : h(x, n); } -size_t UHF::compute_seed(size_t seed, const std::string& extra) +DefaultHasher::DefaultHasher(size_t k, size_t seed) + : Hasher(k, seed) { - u_char buf[SHA256_DIGEST_LENGTH]; - SHA256_CTX ctx; - sha256_init(&ctx); - - if ( extra.empty() ) - { - unsigned int first_seed = initial_seed(); - sha256_update(&ctx, &first_seed, sizeof(first_seed)); - } - - else - sha256_update(&ctx, extra.c_str(), extra.size()); - - sha256_update(&ctx, &seed, sizeof(seed)); - sha256_final(&ctx, buf); - - // Take the first sizeof(size_t) bytes as seed. - return *reinterpret_cast(buf); - } - -DefaultHasher::DefaultHasher(size_t k, const std::string& name) - : Hasher(k, name) - { - for ( size_t i = 0; i < k; ++i ) - hash_functions.push_back(UHF(i, name)); + for ( size_t i = 1; i <= k; ++i ) + hash_functions.push_back(UHF(Seed() + bro_prng(i))); } Hasher::digest_vector DefaultHasher::Hash(const void* x, size_t n) const @@ -137,13 +134,13 @@ bool DefaultHasher::DoUnserialize(UnserialInfo* info) hash_functions.clear(); for ( size_t i = 0; i < K(); ++i ) - hash_functions.push_back(UHF(i, Name())); + hash_functions.push_back(UHF(Seed() + bro_prng(i))); return true; } -DoubleHasher::DoubleHasher(size_t k, const std::string& name) - : Hasher(k, name), h1(1, name), h2(2, name) +DoubleHasher::DoubleHasher(size_t k, size_t seed) + : Hasher(k, seed), h1(seed + bro_prng(1)), h2(seed + bro_prng(2)) { } @@ -187,8 +184,8 @@ bool DoubleHasher::DoUnserialize(UnserialInfo* info) { DO_UNSERIALIZE(Hasher); - h1 = UHF(1, Name()); - h2 = UHF(2, Name()); + h1 = UHF(Seed() + bro_prng(1)); + h2 = UHF(Seed() + bro_prng(2)); return true; } diff --git a/src/probabilistic/Hasher.h b/src/probabilistic/Hasher.h index 3acd5c5867..bd8f5ce5ff 100644 --- a/src/probabilistic/Hasher.h +++ b/src/probabilistic/Hasher.h @@ -18,6 +18,20 @@ public: typedef hash_t digest; typedef std::vector digest_vector; + /** + * Creates a valid hasher seed from an arbitrary string. + * + * @param data A pointer to contiguous data that should be crunched into a + * seed. If 0, the function tries to find a global_hash_seed script variable + * to derive a seed from. If this variable does not exist, the function uses + * the initial seed generated at Bro startup. + * + * @param size The number of bytes of *data*. + * + * @return A seed suitable for hashers. + */ + static size_t MakeSeed(const void* data, size_t size); + /** * Destructor. */ @@ -64,11 +78,9 @@ public: size_t K() const { return k; } /** - * Returns the hasher's name. If not empty, the hasher uses this descriptor - * to seed its *k* hash functions. Otherwise the hasher mixes in the initial - * seed derived from the environment variable `$BRO_SEED`. + * Returns the seed used to construct the hasher. */ - const std::string& Name() const { return name; } + size_t Seed() const { return seed; } bool Serialize(SerialInfo* info) const; static Hasher* Unserialize(UnserialInfo* info); @@ -81,16 +93,15 @@ protected: /** * Constructor. * - * @param k the number of hash functions. + * @param arg_k the number of hash functions. * - * @param name A name for the hasher. Hashers with the same name - * should provide consistent results. + * @param arg_seed The seed for the hasher. */ - Hasher(size_t k, const std::string& name); + Hasher(size_t arg_k, size_t arg_seed); private: size_t k; - std::string name; + size_t seed; }; /** @@ -104,12 +115,8 @@ public: * optional extra seed to replace the initial Bro seed. * * @param seed The seed to use for this instance. - * - * @param extra If not empty, this parameter replaces the initial - * seed to compute the seed for t to compute the seed NUL-terminated - * string as additional seed. */ - UHF(size_t seed = 0, const std::string& extra = ""); + UHF(size_t seed = 0); template Hasher::digest operator()(const T& x) const @@ -152,7 +159,7 @@ public: } private: - static size_t compute_seed(size_t seed, const std::string& extra); + static size_t compute_seed(size_t seed); H3 h; }; @@ -169,9 +176,9 @@ public: * * @param k The number of hash functions to use. * - * @param name The name of the hasher. + * @param seed The seed for the hasher. */ - DefaultHasher(size_t k, const std::string& name = ""); + DefaultHasher(size_t k, size_t seed); // Overridden from Hasher. virtual digest_vector Hash(const void* x, size_t n) const /* final */; @@ -197,9 +204,9 @@ public: * * @param k The number of hash functions to use. * - * @param name The name of the hasher. + * @param seed The seed for the hasher. */ - DoubleHasher(size_t k, const std::string& name = ""); + DoubleHasher(size_t k, size_t seed); // Overridden from Hasher. virtual digest_vector Hash(const void* x, size_t n) const /* final */; diff --git a/src/probabilistic/bloom-filter.bif b/src/probabilistic/bloom-filter.bif index a3567ad6f7..d936b77e3b 100644 --- a/src/probabilistic/bloom-filter.bif +++ b/src/probabilistic/bloom-filter.bif @@ -48,7 +48,9 @@ function bloomfilter_basic_init%(fp: double, capacity: count, size_t cells = BasicBloomFilter::M(fp, capacity); size_t optimal_k = BasicBloomFilter::K(cells, capacity); - const Hasher* h = new DefaultHasher(optimal_k, name->CheckString()); + size_t seed = Hasher::MakeSeed(name->Len() > 0 ? name->Bytes() : 0, + name->Len()); + const Hasher* h = new DefaultHasher(optimal_k, seed); return new BloomFilterVal(new BasicBloomFilter(h, cells)); %} @@ -86,7 +88,10 @@ function bloomfilter_counting_init%(k: count, cells: count, max: count, return 0; } - const Hasher* h = new DefaultHasher(k, name->CheckString()); + size_t seed = Hasher::MakeSeed(name->Len() > 0 ? name->Bytes() : 0, + name->Len()); + + const Hasher* h = new DefaultHasher(k, seed); uint16 width = 1; while ( max >>= 1 ) diff --git a/testing/btest/bifs/bloomfilter.bro b/testing/btest/bifs/bloomfilter.bro index 3b40f29553..e6091e25fa 100644 --- a/testing/btest/bifs/bloomfilter.bro +++ b/testing/btest/bifs/bloomfilter.bro @@ -21,8 +21,8 @@ function test_basic_bloom_filter() bloomfilter_add(bf_str, "bar"); print bloomfilter_lookup(bf_str, "foo"); print bloomfilter_lookup(bf_str, "bar"); - print bloomfilter_lookup(bf_str, "b4z"); # FP - print bloomfilter_lookup(bf_str, "quux"); # FP + print bloomfilter_lookup(bf_str, "b4zzz"); # FP + print bloomfilter_lookup(bf_str, "quuux"); # FP bloomfilter_add(bf_str, 0.5); # Type mismatch bloomfilter_add(bf_str, 100); # Type mismatch From d50b8a147d739e3fdce9cf235e47d7291adbe212 Mon Sep 17 00:00:00 2001 From: Matthias Vallentin Date: Wed, 31 Jul 2013 18:21:37 +0200 Subject: [PATCH 161/881] Add new BiF for low-level Bloom filter initialization. For symmetry reasons, the new Bif bloomfilter_basic_init2 also allows users to manually specify the memory bounds and number of hash functions to use. --- NEWS | 1 + src/probabilistic/bloom-filter.bif | 69 +++++++++++++++---- .../btest/Baseline/bifs.bloomfilter/output | 2 + testing/btest/bifs/bloomfilter.bro | 7 ++ 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index c421e7d675..64058054d6 100644 --- a/NEWS +++ b/NEWS @@ -113,6 +113,7 @@ New Functionality the frequency of elements. The corresponding functions are: bloomfilter_basic_init(fp: double, capacity: count, name: string &default=""): opaque of bloomfilter + bloomfilter_basic_init2(k: count, cells: count, name: string &default=""): opaque of bloomfilter bloomfilter_counting_init(k: count, cells: count, max: count, name: string &default=""): opaque of bloomfilter bloomfilter_add(bf: opaque of bloomfilter, x: any) bloomfilter_lookup(bf: opaque of bloomfilter, x: any): count diff --git a/src/probabilistic/bloom-filter.bif b/src/probabilistic/bloom-filter.bif index d936b77e3b..0c4a67ac6f 100644 --- a/src/probabilistic/bloom-filter.bif +++ b/src/probabilistic/bloom-filter.bif @@ -35,8 +35,8 @@ module GLOBAL; ## ## Returns: A Bloom filter handle. ## -## .. bro:see:: bloomfilter_counting_init bloomfilter_add bloomfilter_lookup -## bloomfilter_clear bloomfilter_merge +## .. bro:see:: bloomfilter_basic_init2 bloomfilter_counting_init bloomfilter_add +## bloomfilter_lookup bloomfilter_clear bloomfilter_merge function bloomfilter_basic_init%(fp: double, capacity: count, name: string &default=""%): opaque of bloomfilter %{ @@ -55,6 +55,47 @@ function bloomfilter_basic_init%(fp: double, capacity: count, return new BloomFilterVal(new BasicBloomFilter(h, cells)); %} +## Creates a basic Bloom filter. This function serves as a low-level +## alternative to bloomfilter_basic_init where the user has full control over +## the number of hash functions and cells in the underlying bit vector. +## +## .. note:: A Bloom filter can have a name associated with it. In the future, +## Bloom filters with the same name will be compatible across indepedent Bro +## instances, i.e., it will be possible to merge them. Currently, however, that is +## not yet supported. +## +## k: The number of hash functions to use. +## +## cells: The number of cells of the underlying bit vector. +## +## name: A name that uniquely identifies and seeds the Bloom filter. If empty, +## the filter will remain tied to the current Bro process. +## +## Returns: A Bloom filter handle. +## +## .. bro:see:: bloom_filter_basic_init bloomfilter_counting_init bloomfilter_add +## bloomfilter_lookup bloomfilter_clear bloomfilter_merge +function bloomfilter_basic_init2%(k: count, cells: count, + name: string &default=""%): opaque of bloomfilter + %{ + if ( k == 0 ) + { + reporter->Error("number of hash functions must be non-negative"); + return 0; + } + if ( cells == 0 ) + { + reporter->Error("number of cells must be non-negative"); + return 0; + } + + size_t seed = Hasher::MakeSeed(name->Len() > 0 ? name->Bytes() : 0, + name->Len()); + const Hasher* h = new DefaultHasher(k, seed); + + return new BloomFilterVal(new BasicBloomFilter(h, cells)); + %} + ## Creates a counting Bloom filter. ## ## .. note:: A Bloom filter can have a name associated with it. In the future, @@ -77,8 +118,8 @@ function bloomfilter_basic_init%(fp: double, capacity: count, ## ## Returns: A Bloom filter handle. ## -## .. bro:see:: bloomfilter_basic_init bloomfilter_add bloomfilter_lookup -## bloomfilter_clear bloomfilter_merge +## .. bro:see:: bloomfilter_basic_init bloomfilter_basic_init2 bloomfilter_add +## bloomfilter_lookup bloomfilter_clear bloomfilter_merge function bloomfilter_counting_init%(k: count, cells: count, max: count, name: string &default=""%): opaque of bloomfilter %{ @@ -106,8 +147,9 @@ function bloomfilter_counting_init%(k: count, cells: count, max: count, ## ## x: The element to add. ## -## .. bro:see:: bloomfilter_counting_init bloomfilter_basic_init loomfilter_lookup -## bloomfilter_clear bloomfilter_merge +## .. bro:see:: bloomfilter_basic_init bloomfilter_basic_init2 +## bloomfilter_counting_init bloomfilter_lookup bloomfilter_clear +## bloomfilter_merge function bloomfilter_add%(bf: opaque of bloomfilter, x: any%): any %{ BloomFilterVal* bfv = static_cast(bf); @@ -132,8 +174,9 @@ function bloomfilter_add%(bf: opaque of bloomfilter, x: any%): any ## ## Returns: the counter associated with *x* in *bf*. ## -## .. bro:see:: bloomfilter_counting_init bloomfilter_basic_init -## bloomfilter_add bloomfilter_clear bloomfilter_merge +## .. bro:see:: bloomfilter_basic_init bloomfilter_basic_init2 +## bloomfilter_counting_init bloomfilter_add bloomfilter_clear +## bloomfilter_merge function bloomfilter_lookup%(bf: opaque of bloomfilter, x: any%): count %{ const BloomFilterVal* bfv = static_cast(bf); @@ -159,8 +202,9 @@ function bloomfilter_lookup%(bf: opaque of bloomfilter, x: any%): count ## ## bf: The Bloom filter handle. ## -## .. bro:see:: bloomfilter_counting_init bloomfilter_basic_init -## bloomfilter_add bloomfilter_lookup bloomfilter_merge +## .. bro:see:: bloomfilter_basic_init bloomfilter_counting_init2 +## bloomfilter_counting_init bloomfilter_add bloomfilter_lookup +## bloomfilter_merge function bloomfilter_clear%(bf: opaque of bloomfilter%): any %{ BloomFilterVal* bfv = static_cast(bf); @@ -183,8 +227,9 @@ function bloomfilter_clear%(bf: opaque of bloomfilter%): any ## ## Returns: The union of *bf1* and *bf2*. ## -## .. bro:see:: bloomfilter_counting_init bloomfilter_basic_init -## bloomfilter_add bloomfilter_lookup bloomfilter_clear +## .. bro:see:: bloomfilter_basic_init bloomfilter_basic_init2 +## bloomfilter_counting_init bloomfilter_add bloomfilter_lookup +## bloomfilter_clear function bloomfilter_merge%(bf1: opaque of bloomfilter, bf2: opaque of bloomfilter%): opaque of bloomfilter %{ diff --git a/testing/btest/Baseline/bifs.bloomfilter/output b/testing/btest/Baseline/bifs.bloomfilter/output index 14e1f038c0..731b7c7ce9 100644 --- a/testing/btest/Baseline/bifs.bloomfilter/output +++ b/testing/btest/Baseline/bifs.bloomfilter/output @@ -17,6 +17,8 @@ error: false-positive rate must take value between 0 and 1 1 1 1 +1 +1 2 3 3 diff --git a/testing/btest/bifs/bloomfilter.bro b/testing/btest/bifs/bloomfilter.bro index e6091e25fa..c2a1c47ca8 100644 --- a/testing/btest/bifs/bloomfilter.bro +++ b/testing/btest/bifs/bloomfilter.bro @@ -15,6 +15,13 @@ function test_basic_bloom_filter() bloomfilter_add(bf_cnt, 0.5); # Type mismatch bloomfilter_add(bf_cnt, "foo"); # Type mismatch + # Alternative constructor. + local bf_dbl = bloomfilter_basic_init2(4, 10); + bloomfilter_add(bf_dbl, 4.2); + bloomfilter_add(bf_dbl, 3.14); + print bloomfilter_lookup(bf_dbl, 4.2); + print bloomfilter_lookup(bf_dbl, 3.14); + # Basic usage with strings. local bf_str = bloomfilter_basic_init(0.9, 10); bloomfilter_add(bf_str, "foo"); From 5122bf4a7cbe5e78802042729d53009d5cc28ab5 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 31 Jul 2013 12:06:59 -0700 Subject: [PATCH 162/881] adapt to new folder structure --- src/CMakeLists.txt | 1 - src/bro.bif | 114 ---------------- src/probabilistic/CMakeLists.txt | 4 +- src/{ => probabilistic}/Topk.cc | 4 +- src/{ => probabilistic}/Topk.h | 2 +- src/probabilistic/top-k.bif | 122 ++++++++++++++++++ .../out | 0 .../topk_persistence.bro => istate/topk.bro} | 0 8 files changed, 128 insertions(+), 119 deletions(-) rename src/{ => probabilistic}/Topk.cc (99%) rename src/{ => probabilistic}/Topk.h (99%) create mode 100644 src/probabilistic/top-k.bif rename testing/btest/Baseline/{bifs.topk_persistence => istate.topk}/out (100%) rename testing/btest/{bifs/topk_persistence.bro => istate/topk.bro} (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2693e1f280..4a65ddd4d3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -320,7 +320,6 @@ set(bro_SRCS Stats.cc Stmt.cc Timer.cc - Topk.cc Traverse.cc Trigger.cc TunnelEncapsulation.cc diff --git a/src/bro.bif b/src/bro.bif index fab11c7e90..efb913bbf7 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -4976,117 +4976,3 @@ function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr } %} -%%{ -#include "Topk.h" -%%} - -## Creates a top-k data structure which tracks size elements. -## -## Returns: Opaque pointer to the data structure. -function topk_init%(size: count%): opaque of topk - %{ - Topk::TopkVal* v = new Topk::TopkVal(size); - return v; - %} - -## Add a new observed object to the data structure. The first -## added object sets the type of data tracked by the top-k data -## structure. All following values have to be of the same type -function topk_add%(handle: opaque of topk, value: any%): any - %{ - assert(handle); - Topk::TopkVal* h = (Topk::TopkVal*) handle; - h->Encountered(value); - - return 0; - %} - -## Get the first k elements of the top-k data structure -## -## Returns: vector of the first k elements -function topk_get_top%(handle: opaque of topk, k: count%): any - %{ - assert(handle); - Topk::TopkVal* h = (Topk::TopkVal*) handle; - return h->getTopK(k); - %} - -## Get an overestimated count of how often value has been encountered. -## value has to be part of the currently tracked elements, otherwise -## 0 will be returned and an error message will be added to reporter. -## -## Returns: Overestimated number for how often the element has been encountered -function topk_count%(handle: opaque of topk, value: any%): count - %{ - assert(handle); - Topk::TopkVal* h = (Topk::TopkVal*) handle; - return new Val(h->getCount(value), TYPE_COUNT); - %} - -## Get a the maximal overestimation for count. Same restrictiosn as for topk_count -## apply. -## -## Returns: Number which represents the maximal overesimation for the count of this element. -function topk_epsilon%(handle: opaque of topk, value: any%): count - %{ - assert(handle); - Topk::TopkVal* h = (Topk::TopkVal*) handle; - return new Val(h->getEpsilon(value), TYPE_COUNT); - %} - -## Get the number of elements this data structure is supposed to track (given on init). -## Note that the actual number of elements in the data structure can be lower or higher -## than this. (higher due to non-pruned merges) -## -## Returns: size given during initialization -function topk_size%(handle: opaque of topk%): count - %{ - assert(handle); - Topk::TopkVal* h = (Topk::TopkVal*) handle; - return new Val(h->getSize(), TYPE_COUNT); - %} - -## Get the sum of all counts of all elements in the data structure. Is equal to the number -## of all inserted objects if the data structure never has been pruned. Do not use after -## calling topk_merge_prune (will throw a warning message if used afterwards) -## -## Returns: sum of all counts -function topk_sum%(handle: opaque of topk%): count - %{ - assert(handle); - Topk::TopkVal* h = (Topk::TopkVal*) handle; - return new Val(h->getSum(), TYPE_COUNT); - %} - -## Merge the second topk data structure into the first. Does not remove any elements, the -## resulting data structure can be bigger than the maximum size given on initialization. -function topk_merge%(handle1: opaque of topk, handle2: opaque of topk%): any - %{ - assert(handle1); - assert(handle2); - - Topk::TopkVal* h1 = (Topk::TopkVal*) handle1; - Topk::TopkVal* h2 = (Topk::TopkVal*) handle2; - - h1->Merge(h2); - - return 0; - %} - -## Merge the second topk data structure into the first and prunes the final data structure -## back to the size given on initialization. Use with care and only when being aware of the -## restrictions this imposed. Do not call topk_size or topk_add afterwards, results will -## probably not be what you expect. -function topk_merge_prune%(handle1: opaque of topk, handle2: opaque of topk%): any - %{ - assert(handle1); - assert(handle2); - - Topk::TopkVal* h1 = (Topk::TopkVal*) handle1; - Topk::TopkVal* h2 = (Topk::TopkVal*) handle2; - - h1->Merge(h2, true); - - return 0; - %} - diff --git a/src/probabilistic/CMakeLists.txt b/src/probabilistic/CMakeLists.txt index af062b24ae..a36dfbbd6b 100644 --- a/src/probabilistic/CMakeLists.txt +++ b/src/probabilistic/CMakeLists.txt @@ -10,9 +10,11 @@ set(probabilistic_SRCS BitVector.cc BloomFilter.cc CounterVector.cc - Hasher.cc) + Hasher.cc + Topk.cc) bif_target(bloom-filter.bif) +bif_target(top-k.bif) bro_add_subdir_library(probabilistic ${probabilistic_SRCS}) add_dependencies(bro_probabilistic generate_outputs) diff --git a/src/Topk.cc b/src/probabilistic/Topk.cc similarity index 99% rename from src/Topk.cc rename to src/probabilistic/Topk.cc index 10374f3087..d03a10ccfc 100644 --- a/src/Topk.cc +++ b/src/probabilistic/Topk.cc @@ -1,13 +1,13 @@ // See the file "COPYING" in the main distribution directory for copyright. -#include "Topk.h" +#include "probabilistic/Topk.h" #include "CompHash.h" #include "Reporter.h" #include "Serializer.h" #include "NetVar.h" -namespace Topk { +namespace probabilistic { IMPLEMENT_SERIAL(TopkVal, SER_TOPK_VAL); diff --git a/src/Topk.h b/src/probabilistic/Topk.h similarity index 99% rename from src/Topk.h rename to src/probabilistic/Topk.h index 608b810ddb..2c47fbd181 100644 --- a/src/Topk.h +++ b/src/probabilistic/Topk.h @@ -10,7 +10,7 @@ // This class implements the top-k algorithm. Or - to be more precise - my interpretation of it. -namespace Topk { +namespace probabilistic { struct Element; diff --git a/src/probabilistic/top-k.bif b/src/probabilistic/top-k.bif new file mode 100644 index 0000000000..83d8e275c1 --- /dev/null +++ b/src/probabilistic/top-k.bif @@ -0,0 +1,122 @@ +# =========================================================================== +# +# Top-K Functions +# +# =========================================================================== + + +%%{ +#include "probabilistic/Topk.h" +%%} + +## Creates a top-k data structure which tracks size elements. +## +## Returns: Opaque pointer to the data structure. +function topk_init%(size: count%): opaque of topk + %{ + probabilistic::TopkVal* v = new probabilistic::TopkVal(size); + return v; + %} + +## Add a new observed object to the data structure. The first +## added object sets the type of data tracked by the top-k data +## structure. All following values have to be of the same type +function topk_add%(handle: opaque of topk, value: any%): any + %{ + assert(handle); + probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; + h->Encountered(value); + + return 0; + %} + +## Get the first k elements of the top-k data structure +## +## Returns: vector of the first k elements +function topk_get_top%(handle: opaque of topk, k: count%): any + %{ + assert(handle); + probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; + return h->getTopK(k); + %} + +## Get an overestimated count of how often value has been encountered. +## value has to be part of the currently tracked elements, otherwise +## 0 will be returned and an error message will be added to reporter. +## +## Returns: Overestimated number for how often the element has been encountered +function topk_count%(handle: opaque of topk, value: any%): count + %{ + assert(handle); + probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; + return new Val(h->getCount(value), TYPE_COUNT); + %} + +## Get a the maximal overestimation for count. Same restrictiosn as for topk_count +## apply. +## +## Returns: Number which represents the maximal overesimation for the count of this element. +function topk_epsilon%(handle: opaque of topk, value: any%): count + %{ + assert(handle); + probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; + return new Val(h->getEpsilon(value), TYPE_COUNT); + %} + +## Get the number of elements this data structure is supposed to track (given on init). +## Note that the actual number of elements in the data structure can be lower or higher +## than this. (higher due to non-pruned merges) +## +## Returns: size given during initialization +function topk_size%(handle: opaque of topk%): count + %{ + assert(handle); + probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; + return new Val(h->getSize(), TYPE_COUNT); + %} + +## Get the sum of all counts of all elements in the data structure. Is equal to the number +## of all inserted objects if the data structure never has been pruned. Do not use after +## calling topk_merge_prune (will throw a warning message if used afterwards) +## +## Returns: sum of all counts +function topk_sum%(handle: opaque of topk%): count + %{ + assert(handle); + probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; + return new Val(h->getSum(), TYPE_COUNT); + %} + +## Merge the second topk data structure into the first. Does not remove any elements, the +## resulting data structure can be bigger than the maximum size given on initialization. +function topk_merge%(handle1: opaque of topk, handle2: opaque of topk%): any + %{ + assert(handle1); + assert(handle2); + + probabilistic::TopkVal* h1 = (probabilistic::TopkVal*) handle1; + probabilistic::TopkVal* h2 = (probabilistic::TopkVal*) handle2; + + h1->Merge(h2); + + return 0; + %} + +## Merge the second topk data structure into the first and prunes the final data structure +## back to the size given on initialization. Use with care and only when being aware of the +## restrictions this imposed. Do not call topk_size or topk_add afterwards, results will +## probably not be what you expect. +function topk_merge_prune%(handle1: opaque of topk, handle2: opaque of topk%): any + %{ + assert(handle1); + assert(handle2); + + probabilistic::TopkVal* h1 = (probabilistic::TopkVal*) handle1; + probabilistic::TopkVal* h2 = (probabilistic::TopkVal*) handle2; + + h1->Merge(h2, true); + + return 0; + %} + + diff --git a/testing/btest/Baseline/bifs.topk_persistence/out b/testing/btest/Baseline/istate.topk/out similarity index 100% rename from testing/btest/Baseline/bifs.topk_persistence/out rename to testing/btest/Baseline/istate.topk/out diff --git a/testing/btest/bifs/topk_persistence.bro b/testing/btest/istate/topk.bro similarity index 100% rename from testing/btest/bifs/topk_persistence.bro rename to testing/btest/istate/topk.bro From 07634fd95eaefb436ebc26a07156121fc34ab176 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 31 Jul 2013 12:36:56 -0700 Subject: [PATCH 163/881] (hopefully) fix refcounting problem in hll/bloom-filter opaque vals. Thanks Robin. --- src/OpaqueVal.cc | 4 ++-- src/Serializer.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index dcf3e84430..211426a434 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -554,7 +554,7 @@ bool BloomFilterVal::Typify(BroType* arg_type) type->Ref(); TypeList* tl = new TypeList(type); - tl->Append(type); + tl->Append(type->Ref()); hash = new CompositeHash(tl); Unref(tl); @@ -760,7 +760,7 @@ bool CardinalityVal::Typify(BroType* arg_type) type->Ref(); TypeList* tl = new TypeList(type); - tl->Append(type); + tl->Append(type->Ref()); hash = new CompositeHash(tl); Unref(tl); diff --git a/src/Serializer.h b/src/Serializer.h index 719d4dc527..f2cea1000e 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -126,7 +126,7 @@ protected: // This will be increased whenever there is an incompatible change // in the data format. - static const uint32 DATA_FORMAT_VERSION = 23; + static const uint32 DATA_FORMAT_VERSION = 24; ChunkedIO* io; From 39c0f5abadb9c523f056e22eb746cde6754a4ae3 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 31 Jul 2013 12:43:33 -0700 Subject: [PATCH 164/881] make gcc happy --- src/probabilistic/HyperLogLog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/probabilistic/HyperLogLog.h b/src/probabilistic/HyperLogLog.h index 0a7ea6ac2f..f9920ab2a8 100644 --- a/src/probabilistic/HyperLogLog.h +++ b/src/probabilistic/HyperLogLog.h @@ -18,7 +18,7 @@ namespace probabilistic { class CardinalityCounter { - friend class CardinalityVal; + friend class ::CardinalityVal; private: /* From 0f1b0e75b719c2b5755e3d20fa7e42b2f65726e7 Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Wed, 31 Jul 2013 16:32:20 -0400 Subject: [PATCH 165/881] DHCP: - Added the known-devices log, and the script to log DHCP hostname per MAC address, - Added DPD sig, - Removed some scripts following a discussion with Seth. --- scripts/base/protocols/dhcp/__load__.bro | 4 +- scripts/base/protocols/dhcp/dpd.sig | 5 + scripts/base/protocols/dhcp/main.bro | 12 +- scripts/policy/misc/known-devices.bro | 37 +++ .../protocols/dhcp/handle_extra_msg_types.bro | 256 ------------------ .../dhcp/known-devices-and-hostnames.bro | 22 ++ 6 files changed, 71 insertions(+), 265 deletions(-) create mode 100644 scripts/base/protocols/dhcp/dpd.sig create mode 100644 scripts/policy/misc/known-devices.bro delete mode 100644 scripts/policy/protocols/dhcp/handle_extra_msg_types.bro create mode 100644 scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro diff --git a/scripts/base/protocols/dhcp/__load__.bro b/scripts/base/protocols/dhcp/__load__.bro index 0098b81a7a..c04423a855 100644 --- a/scripts/base/protocols/dhcp/__load__.bro +++ b/scripts/base/protocols/dhcp/__load__.bro @@ -1,2 +1,4 @@ @load ./consts -@load ./main \ No newline at end of file +@load ./main + +@load-sigs ./dpd.sig diff --git a/scripts/base/protocols/dhcp/dpd.sig b/scripts/base/protocols/dhcp/dpd.sig new file mode 100644 index 0000000000..010920e2d8 --- /dev/null +++ b/scripts/base/protocols/dhcp/dpd.sig @@ -0,0 +1,5 @@ +signature dhcp_cookie { + ip-proto == udp + payload /^.*\x63\x82\x53\x63/ + enable "dhcp" +} \ No newline at end of file diff --git a/scripts/base/protocols/dhcp/main.bro b/scripts/base/protocols/dhcp/main.bro index 9fc63df152..05491361ff 100644 --- a/scripts/base/protocols/dhcp/main.bro +++ b/scripts/base/protocols/dhcp/main.bro @@ -2,8 +2,8 @@ ##! This script ignores large swaths of the protocol, since it is rather ##! noisy on most networks, and focuses on the end-result: assigned leases. ##! -##! To enable further analysis and log output for DHCP, see the optional -##! scripts in the policy/protocols/dhcp directory. +##! If you'd like to track known DHCP devices and to log the hostname +##! supplied by the client, see policy/protocols/dhcp/known-devices.bro @load ./utils.bro @@ -45,13 +45,13 @@ redef record connection += { const ports = { 67/udp, 68/udp }; redef likely_server_ports += { 67/udp }; -event bro_init() &priority=5 +event bro_init() { Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp]); Analyzer::register_for_ports(Analyzer::ANALYZER_DHCP, ports); } -event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=5 +event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) { local info: Info; info$ts = network_time(); @@ -65,10 +65,6 @@ event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_lis info$mac = msg$h_addr; c$dhcp = info; - } -# We let policy scripts add stuff too, so we run this at a lower priority -event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=1 - { Log::write(DHCP::LOG, c$dhcp); } diff --git a/scripts/policy/misc/known-devices.bro b/scripts/policy/misc/known-devices.bro new file mode 100644 index 0000000000..4c3ed9009c --- /dev/null +++ b/scripts/policy/misc/known-devices.bro @@ -0,0 +1,37 @@ +##! This script logs devices for which Bro has been able to determine the MAC +##! address and logs the MAC address once per day (by default). The log that +##! is output provides an easy way to determine a count of the devices in use +##! on a network per day. + +##! NOTE: This script will not generate any logs. Scripts such as +##! policy/protocols/dhcp/known-devices-and-hostnames are needed. +module Known; + +export { + ## The known-hosts logging stream identifier. + redef enum Log::ID += { DEVICES_LOG }; + + ## The record type which contains the column fields of the known-devices log. + type DevicesInfo: record { + ## The timestamp at which the host was detected. + ts: time &log; + ## The MAC address that was detected. + mac: string &log; + }; + + ## The set of all known MAC addresses to store for preventing duplicate + ## logging of addresses. It can also be used from other scripts to + ## inspect if an address has been seen in use. + ## Maintain the list of known devices for 24 hours so that the existence + ## of each individual address is logged each day. + global known_devices: set[string] &create_expire=1day &synchronized &redef; + + ## An event that can be handled to access the :bro:type:`Known::DevicesInfo` + ## record as it is sent on to the logging framework. + global log_known_devices: event(rec: DevicesInfo); +} + +event bro_init() + { + Log::create_stream(Known::DEVICES_LOG, [$columns=DevicesInfo, $ev=log_known_devices]); + } diff --git a/scripts/policy/protocols/dhcp/handle_extra_msg_types.bro b/scripts/policy/protocols/dhcp/handle_extra_msg_types.bro deleted file mode 100644 index e5fa713da4..0000000000 --- a/scripts/policy/protocols/dhcp/handle_extra_msg_types.bro +++ /dev/null @@ -1,256 +0,0 @@ -##! Handlers for DHCP message types other than DHCPACK, which is handled in base/protocols/dhcp. -##! For networks that wish to get more details from their DHCP logs, at the expense -##! of a significantly higher log rate. - -@load base/protocols/dhcp - -module DHCP; - -export { - redef record Info += { - ## The value of the host name option, if seen - host_name: string &log &optional; - ## The IP requested by the client, if any - requested_ip: addr &log &optional; - ## The type of the DHCP message (DHCPOFFER, DHCPRELEASE, etc.) - msg_type: string &log &optional; - }; - - #### Enabled by default - - ## A boolean value to determine if DHCPREQUEST messages are logged. - ## Often useful to see client activity, and because host_name is often available. - const log_dhcprequest = T &redef; - - ## A boolean value to determine if DHCPDECLINE messages are logged. - ## A client declines a lease if it detects that the IP is already in use (usually via ARP). - const log_dhcpdecline = T &redef; - - ## A boolean value to determine if DHCPNAK messages are logged. - ## A server issues a DHCPNAK if a client DHCPREQUEST is invalid. - const log_dhcpnak = T &redef; - - ## A boolean value to determine if DHCPRELEASE messages are logged. - ## A client issues a DHCPRELEASE when it no longer needs the lease (e.g. it's shutting down). - const log_dhcprelease = T &redef; - - #### Not enabled by default - - ## A boolean value to determine if DHCPOFFER messages are logged. - ## Used to profile server -> client communication. - const log_dhcpoffer = F &redef; - - ## A boolean value to determine if DHCPDISCOVER messages are logged. - ## Used to profile broadcast client discovery requests. - const log_dhcpdiscover = F &redef; - - ## A boolean value to determine if DHCPINFORM messages are logged. - ## Used to profile clients attempting to request/renew specific IPs. - const log_dhcpinform = F &redef; - -} - -event dhcp_offer(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=5 - { - if ( ! log_dhcpoffer ) - return; - - local info: Info; - info$ts = network_time(); - info$id = c$id; - info$uid = c$uid; - info$assigned_ip = reverse_ip(msg$yiaddr); - info$lease_time = lease; - info$trans_id = msg$xid; - info$msg_type = "DHCPOFFER"; - - if ( msg$h_addr != "" ) - info$mac = msg$h_addr; - - if ( host_name != "" ) - info$host_name = host_name; - - c$dhcp = info; - } - -event dhcp_discover(c: connection, msg: dhcp_msg, req_addr: addr, host_name: string) &priority=5 - { - if ( ! log_dhcpdiscover ) - return; - - local info: Info; - info$ts = network_time(); - info$id = c$id; - info$uid = c$uid; - info$requested_ip = req_addr; - info$trans_id = msg$xid; - info$msg_type = "DHCPDISCOVER"; - - if ( msg$h_addr != "" ) - info$mac = msg$h_addr; - - if ( host_name != "" ) - info$host_name = host_name; - - c$dhcp = info; - } - -event dhcp_request(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr, host_name: string) &priority=5 - { - if ( ! log_dhcprequest ) - return; - - local info: Info; - info$ts = network_time(); - info$id = c$id; - info$uid = c$uid; - info$requested_ip = req_addr; - info$trans_id = msg$xid; - info$msg_type = "DHCPREQUEST"; - - if ( msg$h_addr != "" ) - info$mac = msg$h_addr; - - if ( host_name != "" ) - info$host_name = host_name; - - c$dhcp = info; - } - -event dhcp_decline(c: connection, msg: dhcp_msg, host_name: string) &priority=5 - { - if ( ! log_dhcpdecline ) - return; - - local info: Info; - info$ts = network_time(); - info$id = c$id; - info$uid = c$uid; - info$trans_id = msg$xid; - info$msg_type = "DHCPDECLINE"; - - if ( msg$h_addr != "" ) - info$mac = msg$h_addr; - - if ( host_name != "" ) - info$host_name = host_name; - - c$dhcp = info; - } - -event dhcp_nak(c: connection, msg: dhcp_msg, host_name: string) &priority=5 - { - if ( ! log_dhcpnak ) - return; - - local info: Info; - info$ts = network_time(); - info$id = c$id; - info$uid = c$uid; - info$trans_id = msg$xid; - info$msg_type = "DHCPNAK"; - - if ( msg$h_addr != "" ) - info$mac = msg$h_addr; - - if ( host_name != "" ) - info$host_name = host_name; - - c$dhcp = info; - } - -event dhcp_release(c: connection, msg: dhcp_msg, host_name: string) &priority=5 - { - if ( ! log_dhcprelease ) - return; - - local info: Info; - info$ts = network_time(); - info$id = c$id; - info$uid = c$uid; - info$trans_id = msg$xid; - info$msg_type = "DHCPRELEASE"; - - if ( msg$h_addr != "" ) - info$mac = msg$h_addr; - - if ( host_name != "" ) - info$host_name = host_name; - - c$dhcp = info; - } - -event dhcp_inform(c: connection, msg: dhcp_msg, host_name: string) &priority=5 - { - if ( ! log_dhcpinform ) - return; - - local info: Info; - info$ts = network_time(); - info$id = c$id; - info$uid = c$uid; - info$trans_id = msg$xid; - info$msg_type = "DHCPINFORM"; - - if ( msg$h_addr != "" ) - info$mac = msg$h_addr; - - if ( host_name != "" ) - info$host_name = host_name; - - c$dhcp = info; - } - -event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=4 - { - ## For the sake of consistency, let's add msg_type to DHCPACK as well. - c$dhcp$msg_type = "DHCPACK"; - ## host_name is generally not in ACKs, but let's check anyway. - if ( host_name != "" ) - c$dhcp$host_name = host_name; - } - -#### We log stuff at a lower priority, in case any other scripts would like to extend the Info record first. - -event dhcp_offer(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) &priority=1 - { - if ( log_dhcpoffer ) - Log::write(DHCP::LOG, c$dhcp); - } - -event dhcp_discover(c: connection, msg: dhcp_msg, req_addr: addr, host_name: string) &priority=1 - { - if ( log_dhcpdiscover ) - Log::write(DHCP::LOG, c$dhcp); - } - -event dhcp_request(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr, host_name: string) &priority=1 - { - if ( log_dhcprequest ) - Log::write(DHCP::LOG, c$dhcp); - } - -event dhcp_decline(c: connection, msg: dhcp_msg, host_name: string) &priority=1 - { - if ( log_dhcpdecline ) - Log::write(DHCP::LOG, c$dhcp); - } - -event dhcp_nak(c: connection, msg: dhcp_msg, host_name: string) &priority=1 - { - if ( log_dhcpnak ) - Log::write(DHCP::LOG, c$dhcp); - } - -event dhcp_release(c: connection, msg: dhcp_msg, host_name: string) &priority=1 - { - if ( log_dhcprelease ) - Log::write(DHCP::LOG, c$dhcp); - } - -event dhcp_inform(c: connection, msg: dhcp_msg, host_name: string) &priority=1 - { - if ( log_dhcpinform ) - Log::write(DHCP::LOG, c$dhcp); - } - diff --git a/scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro b/scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro new file mode 100644 index 0000000000..95770ce273 --- /dev/null +++ b/scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro @@ -0,0 +1,22 @@ +@load policy/misc/known-devices + +module Known; + +export { + redef record DevicesInfo += { + ## The value of the DHCP host name option, if seen + dhcp_host_name: string &log &optional; + }; +} + +event dhcp_request(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr, host_name: string) + { + if ( msg$h_addr == "" ) + return; + + if ( msg$h_addr !in known_devices ) + { + add known_devices[msg$h_addr]; + Log::write(Known::DEVICES_LOG, [$ts=network_time(), $mac=msg$h_addr, $dhcp_host_name=host_name]); + } + } From 1786a3b92d8bd4f9929decfcf74f59ab59d65334 Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Wed, 31 Jul 2013 17:30:56 -0400 Subject: [PATCH 166/881] DHCP: Adding unit tests. --- scripts/base/protocols/dhcp/main.bro | 8 ++++++-- .../dhcp/known-devices-and-hostnames.bro | 12 ++++++++++++ .../dhcp.log | 10 ++++++++++ .../scripts.base.protocols.dhcp.inform/dhcp.log | 10 ++++++++++ .../known_devices.log | 11 +++++++++++ testing/btest/Traces/dhcp/dhcp.trace | Bin 0 -> 3140 bytes testing/btest/Traces/dhcp/dhcp_inform.trace | Bin 0 -> 687 bytes .../base/protocols/dhcp/dhcp-all-msg-types.btest | 6 ++++++ .../scripts/base/protocols/dhcp/inform.test | 5 +++++ .../dhcp/known-devices-and-hostnames/basic.test | 8 ++++++++ 10 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-all-msg-types/dhcp.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dhcp.inform/dhcp.log create mode 100644 testing/btest/Baseline/scripts.policy.protocols.dhcp.known-devices-and-hostnames.basic/known_devices.log create mode 100644 testing/btest/Traces/dhcp/dhcp.trace create mode 100644 testing/btest/Traces/dhcp/dhcp_inform.trace create mode 100644 testing/btest/scripts/base/protocols/dhcp/dhcp-all-msg-types.btest create mode 100644 testing/btest/scripts/base/protocols/dhcp/inform.test create mode 100644 testing/btest/scripts/policy/protocols/dhcp/known-devices-and-hostnames/basic.test diff --git a/scripts/base/protocols/dhcp/main.bro b/scripts/base/protocols/dhcp/main.bro index 05491361ff..07bd437579 100644 --- a/scripts/base/protocols/dhcp/main.bro +++ b/scripts/base/protocols/dhcp/main.bro @@ -57,13 +57,17 @@ event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_lis info$ts = network_time(); info$id = c$id; info$uid = c$uid; - info$assigned_ip = reverse_ip(msg$yiaddr); info$lease_time = lease; info$trans_id = msg$xid; if ( msg$h_addr != "" ) info$mac = msg$h_addr; - + + if ( reverse_ip(msg$yiaddr) != 0.0.0.0 ) + info$assigned_ip = reverse_ip(msg$yiaddr); + else + info$assigned_ip = c$id$orig_h; + c$dhcp = info; Log::write(DHCP::LOG, c$dhcp); diff --git a/scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro b/scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro index 95770ce273..ddb058f2e0 100644 --- a/scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro +++ b/scripts/policy/protocols/dhcp/known-devices-and-hostnames.bro @@ -20,3 +20,15 @@ event dhcp_request(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr Log::write(Known::DEVICES_LOG, [$ts=network_time(), $mac=msg$h_addr, $dhcp_host_name=host_name]); } } + +event dhcp_inform(c: connection, msg: dhcp_msg, host_name: string) + { + if ( msg$h_addr == "" ) + return; + + if ( msg$h_addr !in known_devices ) + { + add known_devices[msg$h_addr]; + Log::write(Known::DEVICES_LOG, [$ts=network_time(), $mac=msg$h_addr, $dhcp_host_name=host_name]); + } + } diff --git a/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-all-msg-types/dhcp.log b/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-all-msg-types/dhcp.log new file mode 100644 index 0000000000..b52d455a4a --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-all-msg-types/dhcp.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dhcp +#open 2013-07-31-21-00-49 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p mac assigned_ip lease_time trans_id +#types time string addr port addr port string addr interval count +1370200444.371332 nQcgTWjvg4c 128.2.6.189 68 128.2.6.152 67 90:b1:1c:99:49:29 128.2.6.189 900.000000 1984 +#close 2013-07-31-21-00-50 diff --git a/testing/btest/Baseline/scripts.base.protocols.dhcp.inform/dhcp.log b/testing/btest/Baseline/scripts.base.protocols.dhcp.inform/dhcp.log new file mode 100644 index 0000000000..d8f626efe3 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dhcp.inform/dhcp.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dhcp +#open 2013-07-31-21-00-55 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p mac assigned_ip lease_time trans_id +#types time string addr port addr port string addr interval count +1374432420.191205 FrJExwHcSal 128.2.6.122 68 128.2.6.152 67 90:b1:1c:99:49:29 128.2.6.122 0.000000 2754407505 +#close 2013-07-31-21-00-55 diff --git a/testing/btest/Baseline/scripts.policy.protocols.dhcp.known-devices-and-hostnames.basic/known_devices.log b/testing/btest/Baseline/scripts.policy.protocols.dhcp.known-devices-and-hostnames.basic/known_devices.log new file mode 100644 index 0000000000..91d37f8950 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.dhcp.known-devices-and-hostnames.basic/known_devices.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path known_devices +#open 2013-07-31-21-27-41 +#fields ts mac dhcp_host_name +#types time string string +1370200443.344965 90:b1:1c:99:49:29 btest.is.cool +1374432420.186878 90:b1:1c:99:49:29 (empty) +#close 2013-07-31-21-27-41 diff --git a/testing/btest/Traces/dhcp/dhcp.trace b/testing/btest/Traces/dhcp/dhcp.trace new file mode 100644 index 0000000000000000000000000000000000000000..aeb00a133f1f70d493c3152f7c1f3a7ea458c2dd GIT binary patch literal 3140 zcmca|c+)~A1{MYw`2U}Qff2~5nz=eK^&Ja?F^~ho|G{9wMwywOnj8$S42-HEWe$Rs zCqOzuk_;{k&WwUa%NZHjfFkS%K;q~Cq90v!=<<`Bf|E@d8I4#DthjuLhc~GtwYWqt zvsf=VKR@R`C)gaVA+Adfc)>V!5hvCRPDLbkPwV0n?~S~)&J2kt z>?s};kZ*li8Nz^p2*QwnWI&{N4^RL$2yXffifnK|f>OMRojfANH-MCY0Z0vqF+5W| z8zdkt(kEij^luCOx5 z0ZS7Q#weNvphfdtP;|hGW`;lPp(8J?v;40EhSmpFHj+b&r4kxibI^(!Fn4&CzwH0( gfuUtz$VPIt|6~m`w2q9N(Bd#=VbnW(0DEZ)0CO2oasU7T literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/dhcp/dhcp_inform.trace b/testing/btest/Traces/dhcp/dhcp_inform.trace new file mode 100644 index 0000000000000000000000000000000000000000..798ca84149dece44eaf6f1cb91874a5dba63d86a GIT binary patch literal 687 zcmca|c+)~A1{MYw`2U}Qff2}AqVp#3-%Tb4MIZ-+8F(}u_})+0C^OSjlY_yPfl-)& z!GXa+Q0GVk6I&G!&tPz2aAx@b{177}8(25UM35Yah5?9v7;os)$xXq@ri>isjEw(5 z0rvD26GIp=}0&I=&Gj>q$49@^#HDdt< P0wc?RU~&T{IN|{S|HnC| literal 0 HcmV?d00001 diff --git a/testing/btest/scripts/base/protocols/dhcp/dhcp-all-msg-types.btest b/testing/btest/scripts/base/protocols/dhcp/dhcp-all-msg-types.btest new file mode 100644 index 0000000000..752ab91780 --- /dev/null +++ b/testing/btest/scripts/base/protocols/dhcp/dhcp-all-msg-types.btest @@ -0,0 +1,6 @@ +# This tests that DHCP leases are logged in dhcp.log +# The trace has a message of each DHCP message type, +# but only one lease should show up in the logs. + +# @TEST-EXEC: bro -r $TRACES/dhcp/dhcp.trace %INPUT +# @TEST-EXEC: btest-diff dhcp.log diff --git a/testing/btest/scripts/base/protocols/dhcp/inform.test b/testing/btest/scripts/base/protocols/dhcp/inform.test new file mode 100644 index 0000000000..652fd1ae45 --- /dev/null +++ b/testing/btest/scripts/base/protocols/dhcp/inform.test @@ -0,0 +1,5 @@ +# DHCPINFORM leases are special-cased in the code. +# This tests that those leases are correctly logged. + +# @TEST-EXEC: bro -r $TRACES/dhcp/dhcp_inform.trace %INPUT +# @TEST-EXEC: btest-diff dhcp.log diff --git a/testing/btest/scripts/policy/protocols/dhcp/known-devices-and-hostnames/basic.test b/testing/btest/scripts/policy/protocols/dhcp/known-devices-and-hostnames/basic.test new file mode 100644 index 0000000000..c2fcc1397c --- /dev/null +++ b/testing/btest/scripts/policy/protocols/dhcp/known-devices-and-hostnames/basic.test @@ -0,0 +1,8 @@ +# This tests that the known_devices log is created, +# that devices are logged by MAC address, and that +# the DHCP hostname is added, if available. + +# @TEST-EXEC: bro -r $TRACES/dhcp/dhcp.trace -r $TRACES/dhcp/dhcp_inform.trace %INPUT +# @TEST-EXEC: btest-diff known_devices.log + +@load policy/protocols/dhcp/known-devices-and-hostnames \ No newline at end of file From 2a0790c2316380209b5a9d6f3abfffc94aa8120e Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 31 Jul 2013 17:14:02 -0700 Subject: [PATCH 167/881] Changing the Bloom filter hashing so that it's independent of CompositeHash. We do this by hashing values added to a BloomFilter another time more with a stable hash seeded only by either the filter's name or the global_hash_seed (or Bro's random() seed if neither is defined). I'm also adding a new bif bloomfilter_internal_state() that returns a string representation of a Bloom filter's current internal state. This is solely for writing tests that check that the filters end up consistent when seeded with the same value. --- scripts/base/init-bare.bro | 5 ++ src/OpaqueVal.cc | 9 ++- src/OpaqueVal.h | 1 + src/probabilistic/BitVector.cc | 10 ++++ src/probabilistic/BitVector.h | 7 +++ src/probabilistic/BloomFilter.cc | 28 ++++++++-- src/probabilistic/BloomFilter.h | 56 +++++++------------ src/probabilistic/CounterVector.cc | 5 ++ src/probabilistic/CounterVector.h | 7 +++ src/probabilistic/Hasher.cc | 6 +- src/probabilistic/Hasher.h | 9 +++ src/probabilistic/bloom-filter.bif | 25 ++++----- .../Baseline/bifs.bloomfilter-seed/output | 8 +++ testing/btest/bifs/bloomfilter-seed.bro | 40 +++++++++++++ 14 files changed, 157 insertions(+), 59 deletions(-) create mode 100644 testing/btest/Baseline/bifs.bloomfilter-seed/output create mode 100644 testing/btest/bifs/bloomfilter-seed.bro diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 9876ad03f7..e5300cdc9f 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -3042,6 +3042,11 @@ module GLOBAL; ## Number of bytes per packet to capture from live interfaces. const snaplen = 8192 &redef; +## Seed for hashes computed internally for probabilistic data structures. Using +## the same value here will make the hashes compatible between independent Bro +## instances. If left unset, Bro will use a temporary local seed. +const global_hash_seed: string = "" &redef; + # Load BiFs defined by plugins. @load base/bif/plugins diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index 66b3c081e7..e79b4435b3 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -566,14 +566,14 @@ BroType* BloomFilterVal::Type() const void BloomFilterVal::Add(const Val* val) { HashKey* key = hash->ComputeHash(val, 1); - bloom_filter->Add(key->Hash()); + bloom_filter->Add(key); delete key; } size_t BloomFilterVal::Count(const Val* val) const { HashKey* key = hash->ComputeHash(val, 1); - size_t cnt = bloom_filter->Count(key->Hash()); + size_t cnt = bloom_filter->Count(key); delete key; return cnt; } @@ -588,6 +588,11 @@ bool BloomFilterVal::Empty() const return bloom_filter->Empty(); } +string BloomFilterVal::InternalState() const + { + return bloom_filter->InternalState(); + } + BloomFilterVal* BloomFilterVal::Merge(const BloomFilterVal* x, const BloomFilterVal* y) { diff --git a/src/OpaqueVal.h b/src/OpaqueVal.h index 52c9583fc7..08a20b1a31 100644 --- a/src/OpaqueVal.h +++ b/src/OpaqueVal.h @@ -127,6 +127,7 @@ public: size_t Count(const Val* val) const; void Clear(); bool Empty() const; + string InternalState() const; static BloomFilterVal* Merge(const BloomFilterVal* x, const BloomFilterVal* y); diff --git a/src/probabilistic/BitVector.cc b/src/probabilistic/BitVector.cc index 6e642e62c1..f820e6df27 100644 --- a/src/probabilistic/BitVector.cc +++ b/src/probabilistic/BitVector.cc @@ -490,6 +490,16 @@ BitVector::size_type BitVector::FindNext(size_type i) const return block ? bi * bits_per_block + lowest_bit(block) : find_from(bi + 1); } +size_t BitVector::Hash() const + { + size_t hash = 0; + + for ( size_type i = 0; i < Blocks(); ++i ) + hash += bits[i]; + + return hash; + } + BitVector::size_type BitVector::lowest_bit(block_type block) { block_type x = block - (block & (block - 1)); diff --git a/src/probabilistic/BitVector.h b/src/probabilistic/BitVector.h index d9c55d53c6..8e24336345 100644 --- a/src/probabilistic/BitVector.h +++ b/src/probabilistic/BitVector.h @@ -276,6 +276,13 @@ public: */ size_type FindNext(size_type i) const; + /** Computes a hash value of the internal representation. + * This is mainly for debugging/testing purposes. + * + * @return The hash. + */ + size_t Hash() const; + /** * Serializes the bit vector. * diff --git a/src/probabilistic/BloomFilter.cc b/src/probabilistic/BloomFilter.cc index 23b812269c..bcab6c9b54 100644 --- a/src/probabilistic/BloomFilter.cc +++ b/src/probabilistic/BloomFilter.cc @@ -9,6 +9,8 @@ #include "CounterVector.h" #include "Serializer.h" +#include "../util.h" + using namespace probabilistic; BloomFilter::BloomFilter() @@ -107,6 +109,11 @@ BasicBloomFilter* BasicBloomFilter::Clone() const return copy; } +std::string BasicBloomFilter::InternalState() const + { + return fmt("%" PRIu64, (uint64_t)bits->Hash()); + } + BasicBloomFilter::BasicBloomFilter() { bits = 0; @@ -133,14 +140,18 @@ bool BasicBloomFilter::DoUnserialize(UnserialInfo* info) return (bits != 0); } -void BasicBloomFilter::AddImpl(const Hasher::digest_vector& h) +void BasicBloomFilter::Add(const HashKey* key) { + Hasher::digest_vector h = hasher->Hash(key); + for ( size_t i = 0; i < h.size(); ++i ) bits->Set(h[i] % bits->Size()); } -size_t BasicBloomFilter::CountImpl(const Hasher::digest_vector& h) const +size_t BasicBloomFilter::Count(const HashKey* key) const { + Hasher::digest_vector h = hasher->Hash(key); + for ( size_t i = 0; i < h.size(); ++i ) { if ( ! (*bits)[h[i] % bits->Size()] ) @@ -206,6 +217,11 @@ CountingBloomFilter* CountingBloomFilter::Clone() const return copy; } +string CountingBloomFilter::InternalState() const + { + return fmt("%" PRIu64, (uint64_t)cells->Hash()); + } + IMPLEMENT_SERIAL(CountingBloomFilter, SER_COUNTINGBLOOMFILTER) bool CountingBloomFilter::DoSerialize(SerialInfo* info) const @@ -222,14 +238,18 @@ bool CountingBloomFilter::DoUnserialize(UnserialInfo* info) } // TODO: Use partitioning in add/count to allow for reusing CMS bounds. -void CountingBloomFilter::AddImpl(const Hasher::digest_vector& h) +void CountingBloomFilter::Add(const HashKey* key) { + Hasher::digest_vector h = hasher->Hash(key); + for ( size_t i = 0; i < h.size(); ++i ) cells->Increment(h[i] % cells->Size()); } -size_t CountingBloomFilter::CountImpl(const Hasher::digest_vector& h) const +size_t CountingBloomFilter::Count(const HashKey* key) const { + Hasher::digest_vector h = hasher->Hash(key); + CounterVector::size_type min = std::numeric_limits::max(); diff --git a/src/probabilistic/BloomFilter.h b/src/probabilistic/BloomFilter.h index 4865ae145c..65dda2396d 100644 --- a/src/probabilistic/BloomFilter.h +++ b/src/probabilistic/BloomFilter.h @@ -22,27 +22,20 @@ public: virtual ~BloomFilter(); /** - * Adds an element of type T to the Bloom filter. - * @param x The element to add + * Adds an element to the Bloom filter. + * + * @param key The key associated with the element to add. */ - template - void Add(const T& x) - { - AddImpl((*hasher)(x)); - } + virtual void Add(const HashKey* key) = 0; /** * Retrieves the associated count of a given value. * - * @param x The value of type `T` to check. + * @param key The key associated with the element to check. * - * @return The counter associated with *x*. + * @return The counter associated with *key*. */ - template - size_t Count(const T& x) const - { - return CountImpl((*hasher)(x)); - } + virtual size_t Count(const HashKey* key) const = 0; /** * Checks whether the Bloom filter is empty. @@ -72,6 +65,12 @@ public: */ virtual BloomFilter* Clone() const = 0; + /** + * Returns a string with a representation of the Bloom filter's + * internal state. This is for debugging/testing purposes only. + */ + virtual string InternalState() const = 0; + /** * Serializes the Bloom filter. * @@ -106,25 +105,6 @@ protected: */ BloomFilter(const Hasher* hasher); - /** - * Abstract method for implementinng the *Add* operation. - * - * @param hashes A set of *k* hashes for the item to add, computed by - * the internal hasher object. - * - */ - virtual void AddImpl(const Hasher::digest_vector& hashes) = 0; - - /** - * Abstract method for implementing the *Count* operation. - * - * @param hashes A set of *k* hashes for the item to add, computed by - * the internal hasher object. - * - * @return Returns the counter associated with the hashed element. - */ - virtual size_t CountImpl(const Hasher::digest_vector& hashes) const = 0; - const Hasher* hasher; }; @@ -177,6 +157,7 @@ public: virtual void Clear(); virtual bool Merge(const BloomFilter* other); virtual BasicBloomFilter* Clone() const; + virtual string InternalState() const; protected: DECLARE_SERIAL(BasicBloomFilter); @@ -187,8 +168,8 @@ protected: BasicBloomFilter(); // Overridden from BloomFilter. - virtual void AddImpl(const Hasher::digest_vector& h); - virtual size_t CountImpl(const Hasher::digest_vector& h) const; + virtual void Add(const HashKey* key); + virtual size_t Count(const HashKey* key) const; private: BitVector* bits; @@ -216,6 +197,7 @@ public: virtual void Clear(); virtual bool Merge(const BloomFilter* other); virtual CountingBloomFilter* Clone() const; + virtual string InternalState() const; protected: DECLARE_SERIAL(CountingBloomFilter); @@ -226,8 +208,8 @@ protected: CountingBloomFilter(); // Overridden from BloomFilter. - virtual void AddImpl(const Hasher::digest_vector& h); - virtual size_t CountImpl(const Hasher::digest_vector& h) const; + virtual void Add(const HashKey* key); + virtual size_t Count(const HashKey* key) const; private: CounterVector* cells; diff --git a/src/probabilistic/CounterVector.cc b/src/probabilistic/CounterVector.cc index d5635fc0f2..8a6feae5fd 100644 --- a/src/probabilistic/CounterVector.cc +++ b/src/probabilistic/CounterVector.cc @@ -153,6 +153,11 @@ CounterVector operator|(const CounterVector& x, const CounterVector& y) } +size_t CounterVector::Hash() const + { + return bits->Hash(); + } + bool CounterVector::Serialize(SerialInfo* info) const { return SerialObj::Serialize(info); diff --git a/src/probabilistic/CounterVector.h b/src/probabilistic/CounterVector.h index df6fc57ac2..9ce522d61c 100644 --- a/src/probabilistic/CounterVector.h +++ b/src/probabilistic/CounterVector.h @@ -126,6 +126,13 @@ public: */ CounterVector& operator|=(const CounterVector& other); + /** Computes a hash value of the internal representation. + * This is mainly for debugging/testing purposes. + * + * @return The hash. + */ + size_t Hash() const; + /** * Serializes the bit vector. * diff --git a/src/probabilistic/Hasher.cc b/src/probabilistic/Hasher.cc index 8b34aa5c77..b59274df7d 100644 --- a/src/probabilistic/Hasher.cc +++ b/src/probabilistic/Hasher.cc @@ -31,6 +31,11 @@ size_t Hasher::MakeSeed(const void* data, size_t size) return *reinterpret_cast(buf); // Use the first bytes as seed. } +Hasher::digest_vector Hasher::Hash(const HashKey* key) const + { + return Hash(key->Key(), key->Size()); + } + bool Hasher::Serialize(SerialInfo* info) const { return SerialObj::Serialize(info); @@ -77,7 +82,6 @@ Hasher::Hasher(size_t arg_k, size_t arg_seed) seed = arg_seed; } - UHF::UHF(size_t seed) : h(seed) { diff --git a/src/probabilistic/Hasher.h b/src/probabilistic/Hasher.h index bd8f5ce5ff..6b75fa1bea 100644 --- a/src/probabilistic/Hasher.h +++ b/src/probabilistic/Hasher.h @@ -50,6 +50,15 @@ public: return Hash(&x, sizeof(T)); } + /** + * Computes hash values for an element. + * + * @param x The key of the value to hash. + * + * @return Vector of *k* hash values. + */ + digest_vector Hash(const HashKey* key) const; + /** * Computes the hashes for a set of bytes. * diff --git a/src/probabilistic/bloom-filter.bif b/src/probabilistic/bloom-filter.bif index c288171e5d..98c8dd59a8 100644 --- a/src/probabilistic/bloom-filter.bif +++ b/src/probabilistic/bloom-filter.bif @@ -20,11 +20,6 @@ module GLOBAL; ## Creates a basic Bloom filter. ## -## .. note:: A Bloom filter can have a name associated with it. In the future, -## Bloom filters with the same name will be compatible across indepedent Bro -## instances, i.e., it will be possible to merge them. Currently, however, that is -## not yet supported. -## ## fp: The desired false-positive rate. ## ## capacity: the maximum number of elements that guarantees a false-positive @@ -61,11 +56,6 @@ function bloomfilter_basic_init%(fp: double, capacity: count, ## alternative to bloomfilter_basic_init where the user has full control over ## the number of hash functions and cells in the underlying bit vector. ## -## .. note:: A Bloom filter can have a name associated with it. In the future, -## Bloom filters with the same name will be compatible across indepedent Bro -## instances, i.e., it will be possible to merge them. Currently, however, that is -## not yet supported. -## ## k: The number of hash functions to use. ## ## cells: The number of cells of the underlying bit vector. @@ -102,11 +92,6 @@ function bloomfilter_basic_init2%(k: count, cells: count, ## Creates a counting Bloom filter. ## -## .. note:: A Bloom filter can have a name associated with it. In the future, -## Bloom filters with the same name will be compatible across indepedent Bro -## instances, i.e., it will be possible to merge them. Currently, however, that is -## not yet supported. -## ## k: The number of hash functions to use. ## ## cells: The number of cells of the underlying counter vector. As there's no @@ -250,3 +235,13 @@ function bloomfilter_merge%(bf1: opaque of bloomfilter, return BloomFilterVal::Merge(bfv1, bfv2); %} + +## Returns a string with a representation of a Bloom filter's internal +## state. This is for debugging/testing purposes only. +## +## bf: The Bloom filter handle. +function bloomfilter_internal_state%(bf: opaque of bloomfilter%): string + %{ + BloomFilterVal* bfv = static_cast(bf); + return new StringVal(bfv->InternalState()); + %} diff --git a/testing/btest/Baseline/bifs.bloomfilter-seed/output b/testing/btest/Baseline/bifs.bloomfilter-seed/output new file mode 100644 index 0000000000..53e0f583f2 --- /dev/null +++ b/testing/btest/Baseline/bifs.bloomfilter-seed/output @@ -0,0 +1,8 @@ +bf1, global_seed, 1 +bf2, global_seed, 5 +bf3, my_seed, 5 +bf4, my_seed, 6 +bf1, global_seed, 5 +bf2, global_seed, 6 +bf3, my_seed, 5 +bf4, my_seed, 6 diff --git a/testing/btest/bifs/bloomfilter-seed.bro b/testing/btest/bifs/bloomfilter-seed.bro new file mode 100644 index 0000000000..436638e2af --- /dev/null +++ b/testing/btest/bifs/bloomfilter-seed.bro @@ -0,0 +1,40 @@ +# @TEST-EXEC: bro -b %INPUT global_hash_seed="foo" >>output +# @TEST-EXEC: bro -b %INPUT global_hash_seed="my_seed" >>output +# @TEST-EXEC: btest-diff output + +type Foo: record + { + a: count; + b: string; + }; + +function test_bloom_filter() + { + local bf1 = bloomfilter_basic_init(0.9, 10); + bloomfilter_add(bf1, "foo"); + bloomfilter_add(bf1, "bar"); + + local bf2 = bloomfilter_basic_init(0.9, 10); + bloomfilter_add(bf2, Foo($a=1, $b="xx")); + bloomfilter_add(bf2, Foo($a=2, $b="yy")); + + local bf3 = bloomfilter_basic_init(0.9, 10, "my_seed"); + bloomfilter_add(bf3, "foo"); + bloomfilter_add(bf3, "bar"); + + local bf4 = bloomfilter_basic_init(0.9, 10, "my_seed"); + bloomfilter_add(bf4, Foo($a=1, $b="xx")); + bloomfilter_add(bf4, Foo($a=2, $b="yy")); + + print "bf1, global_seed", bloomfilter_internal_state(bf1); + print "bf2, global_seed", bloomfilter_internal_state(bf2); + print "bf3, my_seed", bloomfilter_internal_state(bf3); + print "bf4, my_seed", bloomfilter_internal_state(bf4); + + + } + +event bro_init() + { + test_bloom_filter(); + } From ba12f4af859e68fbc380259aa61ea7fdb9e416a0 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 31 Jul 2013 20:47:47 -0700 Subject: [PATCH 168/881] Updating submodule(s). [nomail] --- aux/bro-aux | 2 +- aux/btest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aux/bro-aux b/aux/bro-aux index 91d258cc8b..d9963983c0 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 91d258cc8b2f74cd02fc93dfe61f73ec9f0dd489 +Subproject commit d9963983c0b4d426b24836f8d154d014d5aecbba diff --git a/aux/btest b/aux/btest index ce366206e3..57c07a2c4d 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit ce366206e3407e534a786ad572c342e9f9fef26b +Subproject commit 57c07a2c4da3693a7e0ec088fae0463361a1f0d5 From 279c7b1af5936d71555eca5b57f2875f49fa5253 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 31 Jul 2013 20:51:01 -0700 Subject: [PATCH 169/881] Updating submodule(s). [nomail] --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 57c07a2c4d..69606f8f3c 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 57c07a2c4da3693a7e0ec088fae0463361a1f0d5 +Subproject commit 69606f8f3cc84d694ca1da14868a5fecd4abbc96 From 2ccc963e221bc747b48f908ec1df7dc167f41723 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Thu, 1 Aug 2013 11:19:23 -0400 Subject: [PATCH 170/881] Small fix to deal with a bug in the SSL log delay mechanism. - It looks like we might have some parser problem, but I just want to work around this problem for the moment. --- CHANGES | 4 ++++ VERSION | 2 +- scripts/base/protocols/ssl/main.bro | 9 +++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index e9b5b1c925..5cfbd0b17a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +2.1-951 | 2013-08-01 11:19:23 -0400 + + * Small fix to deal with a bug in the SSL log delay mechanism. + 2.1-948 | 2013-07-31 20:08:28 -0700 * Fix segfault caused by merging an empty bloom-filter with a diff --git a/VERSION b/VERSION index aaa6984d5f..48cc941701 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-948 +2.1-951 diff --git a/scripts/base/protocols/ssl/main.bro b/scripts/base/protocols/ssl/main.bro index 65526182ac..0d4a8435f0 100644 --- a/scripts/base/protocols/ssl/main.bro +++ b/scripts/base/protocols/ssl/main.bro @@ -67,11 +67,8 @@ export { ## (especially with large file transfers). const disable_analyzer_after_detection = T &redef; - ## The maximum amount of time a script can delay records from being logged. - const max_log_delay = 15secs &redef; - ## Delays an SSL record for a specific token: the record will not be logged - ## as longs the token exists or until :bro:id:`SSL::max_log_delay` elapses. + ## as longs the token exists or until 15 seconds elapses. global delay_log: function(info: Info, token: string); ## Undelays an SSL record for a previously inserted token, allowing the @@ -90,7 +87,7 @@ redef record connection += { redef record Info += { # Adding a string "token" to this set will cause the SSL script # to delay logging the record until either the token has been removed or - # the record has been delayed for :bro:id:`SSL::max_log_delay`. + # the record has been delayed. delay_tokens: set[string] &optional; }; @@ -138,7 +135,7 @@ function log_record(info: Info) { log_record(info); } - timeout SSL::max_log_delay + timeout 15secs { Reporter::info(fmt("SSL delay tokens not released in time (%s tokens remaining)", |info$delay_tokens|)); From 99c89b42d7b945108fd2d75ad59a89a0b93c2144 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 1 Aug 2013 10:35:47 -0500 Subject: [PATCH 171/881] Internal refactoring of how plugin components are tagged/managed. Made some class templates for code that seemed duplicated between file/protocol tags and managers. Seems like it helps a bit and hopefully can be also be used to transition other things that have enum value "tags" (e.g. logging writers, input readers) to the plugin system. --- src/CMakeLists.txt | 2 + src/DebugLogger.cc | 3 +- src/DebugLogger.h | 1 + src/RuleAction.cc | 10 +- src/analyzer/Analyzer.cc | 10 +- src/analyzer/Component.cc | 19 +- src/analyzer/Component.h | 15 +- src/analyzer/Manager.cc | 114 ++------ src/analyzer/Manager.h | 54 +--- src/analyzer/Tag.h | 5 +- src/analyzer/analyzer.bif | 4 +- src/file_analysis/Analyzer.cc | 2 +- src/file_analysis/AnalyzerSet.cc | 12 +- src/file_analysis/Component.cc | 22 +- src/file_analysis/Component.h | 24 +- src/file_analysis/File.cc | 2 +- src/file_analysis/FileTimer.cc | 2 +- src/file_analysis/Manager.cc | 84 +----- src/file_analysis/Manager.h | 59 +---- src/file_analysis/Tag.h | 9 +- .../analyzer/data_event/DataEvent.cc | 2 +- src/file_analysis/analyzer/extract/Extract.cc | 2 +- src/file_analysis/analyzer/hash/Hash.cc | 2 +- src/file_analysis/file_analysis.bif | 6 +- src/plugin/ComponentManager.h | 248 ++++++++++++++++++ src/plugin/TaggedComponent.h | 85 ++++++ 26 files changed, 432 insertions(+), 366 deletions(-) create mode 100644 src/plugin/ComponentManager.h create mode 100644 src/plugin/TaggedComponent.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7960579c8a..e64dcbb9f6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -363,6 +363,8 @@ set(bro_SRCS 3rdparty/sqlite3.c plugin/Component.cc + plugin/ComponentManager.h + plugin/TaggedComponent.h plugin/Manager.cc plugin/Plugin.cc plugin/Macros.h diff --git a/src/DebugLogger.cc b/src/DebugLogger.cc index 380f21aa5f..dc557c4a0a 100644 --- a/src/DebugLogger.cc +++ b/src/DebugLogger.cc @@ -16,7 +16,8 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = { { "notifiers", 0, false }, { "main-loop", 0, false }, { "dpd", 0, false }, { "tm", 0, false }, { "logging", 0, false }, {"input", 0, false }, - { "threading", 0, false }, { "file_analysis", 0, false } + { "threading", 0, false }, { "file_analysis", 0, false }, + { "plugins", 0, false} }; DebugLogger::DebugLogger(const char* filename) diff --git a/src/DebugLogger.h b/src/DebugLogger.h index e293b326a8..c5744642f5 100644 --- a/src/DebugLogger.h +++ b/src/DebugLogger.h @@ -27,6 +27,7 @@ enum DebugStream { DBG_INPUT, // Input streams DBG_THREADING, // Threading system DBG_FILE_ANALYSIS, // File analysis + DBG_PLUGINS, NUM_DBGS // Has to be last }; diff --git a/src/RuleAction.cc b/src/RuleAction.cc index a13392ee40..ec57c96bd2 100644 --- a/src/RuleAction.cc +++ b/src/RuleAction.cc @@ -40,7 +40,7 @@ RuleActionAnalyzer::RuleActionAnalyzer(const char* arg_analyzer) string str(arg_analyzer); string::size_type pos = str.find(':'); string arg = str.substr(0, pos); - analyzer = analyzer_mgr->GetAnalyzerTag(arg.c_str()); + analyzer = analyzer_mgr->GetComponentTag(arg.c_str()); if ( ! analyzer ) reporter->Warning("unknown analyzer '%s' specified in rule", arg.c_str()); @@ -48,7 +48,7 @@ RuleActionAnalyzer::RuleActionAnalyzer(const char* arg_analyzer) if ( pos != string::npos ) { arg = str.substr(pos + 1); - child_analyzer = analyzer_mgr->GetAnalyzerTag(arg.c_str()); + child_analyzer = analyzer_mgr->GetComponentTag(arg.c_str()); if ( ! child_analyzer ) reporter->Warning("unknown analyzer '%s' specified in rule", arg.c_str()); @@ -60,11 +60,11 @@ RuleActionAnalyzer::RuleActionAnalyzer(const char* arg_analyzer) void RuleActionAnalyzer::PrintDebug() { if ( ! child_analyzer ) - fprintf(stderr, "|%s|\n", analyzer_mgr->GetAnalyzerName(analyzer)); + fprintf(stderr, "|%s|\n", analyzer_mgr->GetComponentName(analyzer)); else fprintf(stderr, "|%s:%s|\n", - analyzer_mgr->GetAnalyzerName(analyzer), - analyzer_mgr->GetAnalyzerName(child_analyzer)); + analyzer_mgr->GetComponentName(analyzer), + analyzer_mgr->GetComponentName(child_analyzer)); } diff --git a/src/analyzer/Analyzer.cc b/src/analyzer/Analyzer.cc index ecd3c9f686..b8b739f3cb 100644 --- a/src/analyzer/Analyzer.cc +++ b/src/analyzer/Analyzer.cc @@ -70,12 +70,12 @@ void AnalyzerTimer::Init(Analyzer* arg_analyzer, analyzer_timer_func arg_timer, Ref(analyzer->Conn()); } -analyzer::ID Analyzer::id_counter = 0;; +analyzer::ID Analyzer::id_counter = 0; const char* Analyzer::GetAnalyzerName() const { assert(tag); - return analyzer_mgr->GetAnalyzerName(tag); + return analyzer_mgr->GetComponentName(tag); } void Analyzer::SetAnalyzerTag(const Tag& arg_tag) @@ -87,7 +87,7 @@ void Analyzer::SetAnalyzerTag(const Tag& arg_tag) bool Analyzer::IsAnalyzer(const char* name) { assert(tag); - return strcmp(analyzer_mgr->GetAnalyzerName(tag), name) == 0; + return strcmp(analyzer_mgr->GetComponentName(tag), name) == 0; } // Used in debugging output. @@ -98,7 +98,7 @@ static string fmt_analyzer(Analyzer* a) Analyzer::Analyzer(const char* name, Connection* conn) { - Tag tag = analyzer_mgr->GetAnalyzerTag(name); + Tag tag = analyzer_mgr->GetComponentTag(name); if ( ! tag ) reporter->InternalError("unknown analyzer name %s; mismatch with tag analyzer::Component?", name); @@ -494,7 +494,7 @@ Analyzer* Analyzer::FindChild(Tag arg_tag) Analyzer* Analyzer::FindChild(const char* name) { - Tag tag = analyzer_mgr->GetAnalyzerTag(name); + Tag tag = analyzer_mgr->GetComponentTag(name); return tag ? FindChild(tag) : 0; } diff --git a/src/analyzer/Component.cc b/src/analyzer/Component.cc index ded0a1a2d5..66ab2213bb 100644 --- a/src/analyzer/Component.cc +++ b/src/analyzer/Component.cc @@ -8,29 +8,26 @@ using namespace analyzer; -analyzer::Tag::type_t Component::type_counter = 0; - Component::Component(const char* arg_name, factory_callback arg_factory, Tag::subtype_t arg_subtype, bool arg_enabled, bool arg_partial) - : plugin::Component(plugin::component::ANALYZER) + : plugin::Component(plugin::component::ANALYZER), + plugin::TaggedComponent(arg_subtype) { name = copy_string(arg_name); canon_name = canonify_name(arg_name); factory = arg_factory; enabled = arg_enabled; partial = arg_partial; - - tag = analyzer::Tag(++type_counter, arg_subtype); } Component::Component(const Component& other) - : plugin::Component(Type()) + : plugin::Component(Type()), + plugin::TaggedComponent(other) { name = copy_string(other.name); canon_name = copy_string(other.canon_name); factory = other.factory; enabled = other.enabled; partial = other.partial; - tag = other.tag; } Component::~Component() @@ -39,11 +36,6 @@ Component::~Component() delete [] canon_name; } -analyzer::Tag Component::Tag() const - { - return tag; - } - void Component::Describe(ODesc* d) const { plugin::Component::Describe(d); @@ -63,13 +55,14 @@ void Component::Describe(ODesc* d) const Component& Component::operator=(const Component& other) { + plugin::TaggedComponent::operator=(other); + if ( &other != this ) { name = copy_string(other.name); factory = other.factory; enabled = other.enabled; partial = other.partial; - tag = other.tag; } return *this; diff --git a/src/analyzer/Component.h b/src/analyzer/Component.h index 9e12ed347e..9bc8b357d7 100644 --- a/src/analyzer/Component.h +++ b/src/analyzer/Component.h @@ -5,6 +5,7 @@ #include "Tag.h" #include "plugin/Component.h" +#include "plugin/TaggedComponent.h" #include "../config.h" #include "../util.h" @@ -21,7 +22,8 @@ class Analyzer; * A plugin can provide a specific protocol analyzer by registering this * analyzer component, describing the analyzer. */ -class Component : public plugin::Component { +class Component : public plugin::Component, + public plugin::TaggedComponent { public: typedef Analyzer* (*factory_callback)(Connection* conn); @@ -100,13 +102,6 @@ public: */ bool Enabled() const { return enabled; } - /** - * Returns the analyzer's tag. Note that this is automatically - * generated for each new Components, and hence unique across all of - * them. - */ - analyzer::Tag Tag() const; - /** * Enables or disables this analyzer. * @@ -128,11 +123,7 @@ private: const char* canon_name; // The analyzer's canonical name. factory_callback factory; // The analyzer's factory callback. bool partial; // True if the analyzer supports partial connections. - analyzer::Tag tag; // The automatically assigned analyzer tag. bool enabled; // True if the analyzer is enabled. - - // Global counter used to generate unique tags. - static analyzer::Tag::type_t type_counter; }; } diff --git a/src/analyzer/Manager.cc b/src/analyzer/Manager.cc index 6eb162f204..82453aef06 100644 --- a/src/analyzer/Manager.cc +++ b/src/analyzer/Manager.cc @@ -60,10 +60,8 @@ bool Manager::ConnIndex::operator<(const ConnIndex& other) const } Manager::Manager() + : plugin::ComponentManager("Analyzer") { - tag_enum_type = new EnumType("Analyzer::Tag"); - ::ID* id = install_ID("Tag", "Analyzer", true, true); - add_type(id, tag_enum_type, 0, 0); } Manager::~Manager() @@ -91,14 +89,14 @@ void Manager::InitPreScript() std::list analyzers = plugin_mgr->Components(); for ( std::list::const_iterator i = analyzers.begin(); i != analyzers.end(); i++ ) - RegisterAnalyzerComponent(*i); + RegisterComponent(*i, "ANALYZER_"); // Cache these tags. - analyzer_backdoor = GetAnalyzerTag("BACKDOOR"); - analyzer_connsize = GetAnalyzerTag("CONNSIZE"); - analyzer_interconn = GetAnalyzerTag("INTERCONN"); - analyzer_stepping = GetAnalyzerTag("STEPPINGSTONE"); - analyzer_tcpstats = GetAnalyzerTag("TCPSTATS"); + analyzer_backdoor = GetComponentTag("BACKDOOR"); + analyzer_connsize = GetComponentTag("CONNSIZE"); + analyzer_interconn = GetComponentTag("INTERCONN"); + analyzer_stepping = GetComponentTag("STEPPINGSTONE"); + analyzer_tcpstats = GetComponentTag("TCPSTATS"); } void Manager::InitPostScript() @@ -109,8 +107,9 @@ void Manager::DumpDebug() { #ifdef DEBUG DBG_LOG(DBG_ANALYZER, "Available analyzers after bro_init():"); - for ( analyzer_map_by_name::const_iterator i = analyzers_by_name.begin(); i != analyzers_by_name.end(); i++ ) - DBG_LOG(DBG_ANALYZER, " %s (%s)", i->second->Name(), IsEnabled(i->second->Tag()) ? "enabled" : "disabled"); + list all_analyzers = GetComponents(); + for ( list::const_iterator i = all_analyzers.begin(); i != all_analyzers.end(); ++i ) + DBG_LOG(DBG_ANALYZER, " %s (%s)", (*i)->Name(), IsEnabled((*i)->Tag()) ? "enabled" : "disabled"); DBG_LOG(DBG_ANALYZER, ""); DBG_LOG(DBG_ANALYZER, "Analyzers by port:"); @@ -120,7 +119,7 @@ void Manager::DumpDebug() string s; for ( tag_set::const_iterator j = i->second->begin(); j != i->second->end(); j++ ) - s += string(GetAnalyzerName(*j)) + " "; + s += string(GetComponentName(*j)) + " "; DBG_LOG(DBG_ANALYZER, " %d/tcp: %s", i->first, s.c_str()); } @@ -130,7 +129,7 @@ void Manager::DumpDebug() string s; for ( tag_set::const_iterator j = i->second->begin(); j != i->second->end(); j++ ) - s += string(GetAnalyzerName(*j)) + " "; + s += string(GetComponentName(*j)) + " "; DBG_LOG(DBG_ANALYZER, " %d/udp: %s", i->first, s.c_str()); } @@ -142,25 +141,6 @@ void Manager::Done() { } -void Manager::RegisterAnalyzerComponent(Component* component) - { - const char* cname = component->CanonicalName(); - - if ( Lookup(cname) ) - reporter->FatalError("Analyzer %s defined more than once", cname); - - DBG_LOG(DBG_ANALYZER, "Registering analyzer %s (tag %s)", - component->Name(), component->Tag().AsString().c_str()); - - analyzers_by_name.insert(std::make_pair(cname, component)); - analyzers_by_tag.insert(std::make_pair(component->Tag(), component)); - analyzers_by_val.insert(std::make_pair(component->Tag().AsEnumVal()->InternalInt(), component)); - - // Install enum "Analyzer::ANALYZER_*" - string id = fmt("ANALYZER_%s", cname); - tag_enum_type->AddName("Analyzer", id.c_str(), component->Tag().AsEnumVal()->InternalInt(), true); - } - bool Manager::EnableAnalyzer(Tag tag) { Component* p = Lookup(tag); @@ -217,8 +197,9 @@ void Manager::DisableAllAnalyzers() { DBG_LOG(DBG_ANALYZER, "Disabling all analyzers"); - for ( analyzer_map_by_tag::const_iterator i = analyzers_by_tag.begin(); i != analyzers_by_tag.end(); i++ ) - i->second->SetEnabled(false); + list all_analyzers = GetComponents(); + for ( list::const_iterator i = all_analyzers.begin(); i != all_analyzers.end(); ++i ) + (*i)->SetEnabled(false); } bool Manager::IsEnabled(Tag tag) @@ -270,7 +251,7 @@ bool Manager::RegisterAnalyzerForPort(Tag tag, TransportProto proto, uint32 port tag_set* l = LookupPort(proto, port, true); #ifdef DEBUG - const char* name = GetAnalyzerName(tag); + const char* name = GetComponentName(tag); DBG_LOG(DBG_ANALYZER, "Registering analyzer %s for port %" PRIu32 "/%d", name, port, proto); #endif @@ -283,7 +264,7 @@ bool Manager::UnregisterAnalyzerForPort(Tag tag, TransportProto proto, uint32 po tag_set* l = LookupPort(proto, port, true); #ifdef DEBUG - const char* name = GetAnalyzerName(tag); + const char* name = GetComponentName(tag); DBG_LOG(DBG_ANALYZER, "Unregistering analyzer %s for port %" PRIu32 "/%d", name, port, proto); #endif @@ -302,7 +283,7 @@ Analyzer* Manager::InstantiateAnalyzer(Tag tag, Connection* conn) return 0; if ( ! c->Factory() ) - reporter->InternalError("analyzer %s cannot be instantiated dynamically", GetAnalyzerName(tag)); + reporter->InternalError("analyzer %s cannot be instantiated dynamically", GetComponentName(tag)); Analyzer* a = c->Factory()(conn); @@ -316,59 +297,10 @@ Analyzer* Manager::InstantiateAnalyzer(Tag tag, Connection* conn) Analyzer* Manager::InstantiateAnalyzer(const char* name, Connection* conn) { - Tag tag = GetAnalyzerTag(name); + Tag tag = GetComponentTag(name); return tag ? InstantiateAnalyzer(tag, conn) : 0; } -const char* Manager::GetAnalyzerName(Tag tag) - { - static const char* error = ""; - - if ( ! tag ) - return error; - - Component* c = Lookup(tag); - - if ( ! c ) - reporter->InternalError("request for name of unknown analyzer tag %s", tag.AsString().c_str()); - - return c->CanonicalName(); - } - -const char* Manager::GetAnalyzerName(Val* val) - { - return GetAnalyzerName(Tag(val->AsEnumVal())); - } - -analyzer::Tag Manager::GetAnalyzerTag(const char* name) - { - Component* c = Lookup(name); - return c ? c->Tag() : Tag(); - } - -EnumType* Manager::GetTagEnumType() - { - return tag_enum_type; - } - -Component* Manager::Lookup(const char* name) - { - analyzer_map_by_name::const_iterator i = analyzers_by_name.find(to_upper(name)); - return i != analyzers_by_name.end() ? i->second : 0; - } - -Component* Manager::Lookup(const Tag& tag) - { - analyzer_map_by_tag::const_iterator i = analyzers_by_tag.find(tag); - return i != analyzers_by_tag.end() ? i->second : 0; - } - -Component* Manager::Lookup(EnumVal* val) - { - analyzer_map_by_val::const_iterator i = analyzers_by_val.find(val->InternalInt()); - return i != analyzers_by_val.end() ? i->second : 0; - } - Manager::tag_set* Manager::LookupPort(TransportProto proto, uint32 port, bool add_if_not_found) { analyzer_map_by_port* m = 0; @@ -461,7 +393,7 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn) root->AddChildAnalyzer(analyzer, false); DBG_ANALYZER_ARGS(conn, "activated %s analyzer as scheduled", - analyzer_mgr->GetAnalyzerName(*i)); + analyzer_mgr->GetComponentName(*i)); } } @@ -487,7 +419,7 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn) root->AddChildAnalyzer(analyzer, false); DBG_ANALYZER_ARGS(conn, "activated %s analyzer due to port %d", - analyzer_mgr->GetAnalyzerName(*j), resp_port); + analyzer_mgr->GetComponentName(*j), resp_port); } } } @@ -613,7 +545,7 @@ void Manager::ExpireScheduledAnalyzers() conns.erase(i); DBG_LOG(DBG_ANALYZER, "Expiring expected analyzer %s for connection %s", - analyzer_mgr->GetAnalyzerName(a->analyzer), + analyzer_mgr->GetComponentName(a->analyzer), fmt_conn_id(a->conn.orig, 0, a->conn.resp, a->conn.resp_p)); delete a; @@ -655,7 +587,7 @@ void Manager::ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, TransportProto proto, const char* analyzer, double timeout) { - Tag tag = GetAnalyzerTag(analyzer); + Tag tag = GetComponentTag(analyzer); if ( tag != Tag() ) ScheduleAnalyzer(orig, resp, resp_p, proto, tag, timeout); diff --git a/src/analyzer/Manager.h b/src/analyzer/Manager.h index efae629971..d151709eda 100644 --- a/src/analyzer/Manager.h +++ b/src/analyzer/Manager.h @@ -26,6 +26,7 @@ #include "Analyzer.h" #include "Component.h" #include "Tag.h" +#include "plugin/ComponentManager.h" #include "../Dict.h" #include "../net_util.h" @@ -49,7 +50,7 @@ namespace analyzer { * classes. This allows to external analyzer code to potentially use a * different C++ standard library. */ -class Manager { +class Manager : public plugin::ComponentManager { public: /** * Constructor. @@ -231,42 +232,6 @@ public: */ Analyzer* InstantiateAnalyzer(const char* name, Connection* c); - /** - * Translates an analyzer tag into corresponding analyzer name. - * - * @param tag The analyzer tag. - * - * @return The name, or an empty string if the tag is invalid. - */ - const char* GetAnalyzerName(Tag tag); - - /** - * Translates an script-level analyzer tag into corresponding - * analyzer name. - * - * @param val The analyzer tag as an script-level enum value of type - * \c Analyzer::Tag. - * - * @return The name, or an empty string if the tag is invalid. - */ - const char* GetAnalyzerName(Val* val); - - /** - * Translates an analyzer name into the corresponding tag. - * - * @param name The name. - * - * @return The tag. If the name does not correspond to a valid - * analyzer, the returned tag will evaluate to false. - */ - Tag GetAnalyzerTag(const char* name); - - /** - * Returns the enum type that corresponds to the script-level type \c - * Analyzer::Tag. - */ - EnumType* GetTagEnumType(); - /** * Given the first packet of a connection, builds its initial * analyzer tree. @@ -350,18 +315,8 @@ public: private: typedef set tag_set; - typedef map analyzer_map_by_name; - typedef map analyzer_map_by_tag; - typedef map analyzer_map_by_val; typedef map analyzer_map_by_port; - void RegisterAnalyzerComponent(Component* component); // Takes ownership. - - Component* Lookup(const string& name); - Component* Lookup(const char* name); - Component* Lookup(const Tag& tag); - Component* Lookup(EnumVal* val); - tag_set* LookupPort(PortVal* val, bool add_if_not_found); tag_set* LookupPort(TransportProto proto, uint32 port, bool add_if_not_found); @@ -370,9 +325,6 @@ private: analyzer_map_by_port analyzers_by_port_tcp; analyzer_map_by_port analyzers_by_port_udp; - analyzer_map_by_name analyzers_by_name; - analyzer_map_by_tag analyzers_by_tag; - analyzer_map_by_val analyzers_by_val; Tag analyzer_backdoor; Tag analyzer_connsize; @@ -380,8 +332,6 @@ private: Tag analyzer_stepping; Tag analyzer_tcpstats; - EnumType* tag_enum_type; - //// Data structures to track analyzed scheduled for future connections. // The index for a scheduled connection. diff --git a/src/analyzer/Tag.h b/src/analyzer/Tag.h index 8ac151e4b5..d01c8902ee 100644 --- a/src/analyzer/Tag.h +++ b/src/analyzer/Tag.h @@ -6,6 +6,8 @@ #include "config.h" #include "util.h" #include "../Tag.h" +#include "plugin/TaggedComponent.h" +#include "plugin/ComponentManager.h" class EnumVal; @@ -87,7 +89,8 @@ public: protected: friend class analyzer::Manager; - friend class analyzer::Component; + friend class plugin::ComponentManager; + friend class plugin::TaggedComponent; /** * Constructor. diff --git a/src/analyzer/analyzer.bif b/src/analyzer/analyzer.bif index 4d70816075..ebf8083624 100644 --- a/src/analyzer/analyzer.bif +++ b/src/analyzer/analyzer.bif @@ -41,11 +41,11 @@ function Analyzer::__schedule_analyzer%(orig: addr, resp: addr, resp_p: port, function __name%(atype: Analyzer::Tag%) : string %{ - return new StringVal(analyzer_mgr->GetAnalyzerName(atype)); + return new StringVal(analyzer_mgr->GetComponentName(atype)); %} function __tag%(name: string%) : Analyzer::Tag %{ - analyzer::Tag t = analyzer_mgr->GetAnalyzerTag(name->CheckString()); + analyzer::Tag t = analyzer_mgr->GetComponentTag(name->CheckString()); return t.AsEnumVal()->Ref(); %} diff --git a/src/file_analysis/Analyzer.cc b/src/file_analysis/Analyzer.cc index d472f4c80c..e0b5011aa8 100644 --- a/src/file_analysis/Analyzer.cc +++ b/src/file_analysis/Analyzer.cc @@ -6,6 +6,6 @@ file_analysis::Analyzer::~Analyzer() { DBG_LOG(DBG_FILE_ANALYSIS, "Destroy file analyzer %s", - file_mgr->GetAnalyzerName(tag)); + file_mgr->GetComponentName(tag)); Unref(args); } diff --git a/src/file_analysis/AnalyzerSet.cc b/src/file_analysis/AnalyzerSet.cc index befb676c87..2dc4902314 100644 --- a/src/file_analysis/AnalyzerSet.cc +++ b/src/file_analysis/AnalyzerSet.cc @@ -42,7 +42,7 @@ bool AnalyzerSet::Add(file_analysis::Tag tag, RecordVal* args) if ( analyzer_map.Lookup(key) ) { DBG_LOG(DBG_FILE_ANALYSIS, "Instantiate analyzer %s skipped for file id" - " %s: already exists", file_mgr->GetAnalyzerName(tag), + " %s: already exists", file_mgr->GetComponentName(tag), file->GetID().c_str()); delete key; return true; @@ -82,7 +82,7 @@ bool AnalyzerSet::AddMod::Perform(AnalyzerSet* set) if ( set->analyzer_map.Lookup(key) ) { DBG_LOG(DBG_FILE_ANALYSIS, "Add analyzer %s skipped for file id" - " %s: already exists", file_mgr->GetAnalyzerName(a->Tag()), + " %s: already exists", file_mgr->GetComponentName(a->Tag()), a->GetFile()->GetID().c_str()); Abort(); @@ -108,12 +108,12 @@ bool AnalyzerSet::Remove(file_analysis::Tag tag, HashKey* key) if ( ! a ) { DBG_LOG(DBG_FILE_ANALYSIS, "Skip remove analyzer %s for file id %s", - file_mgr->GetAnalyzerName(tag), file->GetID().c_str()); + file_mgr->GetComponentName(tag), file->GetID().c_str()); return false; } DBG_LOG(DBG_FILE_ANALYSIS, "Remove analyzer %s for file id %s", - file_mgr->GetAnalyzerName(tag), + file_mgr->GetComponentName(tag), file->GetID().c_str()); delete a; @@ -155,7 +155,7 @@ file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(Tag tag, if ( ! a ) { reporter->Error("Failed file analyzer %s instantiation for file id %s", - file_mgr->GetAnalyzerName(tag), file->GetID().c_str()); + file_mgr->GetComponentName(tag), file->GetID().c_str()); return 0; } @@ -165,7 +165,7 @@ file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(Tag tag, void AnalyzerSet::Insert(file_analysis::Analyzer* a, HashKey* key) { DBG_LOG(DBG_FILE_ANALYSIS, "Add analyzer %s for file id %s", - file_mgr->GetAnalyzerName(a->Tag()), file->GetID().c_str()); + file_mgr->GetComponentName(a->Tag()), file->GetID().c_str()); analyzer_map.Insert(key, a); delete key; } diff --git a/src/file_analysis/Component.cc b/src/file_analysis/Component.cc index 8ddd9cceaf..9c47f2c75e 100644 --- a/src/file_analysis/Component.cc +++ b/src/file_analysis/Component.cc @@ -8,26 +8,22 @@ using namespace file_analysis; -file_analysis::Tag::type_t Component::type_counter = 0; - -Component::Component(const char* arg_name, factory_callback arg_factory, - file_analysis::Tag::subtype_t arg_subtype) - : plugin::Component(plugin::component::FILE_ANALYZER) +Component::Component(const char* arg_name, factory_callback arg_factory) + : plugin::Component(plugin::component::FILE_ANALYZER), + plugin::TaggedComponent() { name = copy_string(arg_name); canon_name = canonify_name(arg_name); factory = arg_factory; - - tag = file_analysis::Tag(++type_counter, arg_subtype); } Component::Component(const Component& other) - : plugin::Component(Type()) + : plugin::Component(Type()), + plugin::TaggedComponent(other) { name = copy_string(other.name); canon_name = copy_string(other.canon_name); factory = other.factory; - tag = other.tag; } Component::~Component() @@ -36,11 +32,6 @@ Component::~Component() delete [] canon_name; } -file_analysis::Tag Component::Tag() const - { - return tag; - } - void Component::Describe(ODesc* d) const { plugin::Component::Describe(d); @@ -58,11 +49,12 @@ void Component::Describe(ODesc* d) const Component& Component::operator=(const Component& other) { + plugin::TaggedComponent::operator=(other); + if ( &other != this ) { name = copy_string(other.name); factory = other.factory; - tag = other.tag; } return *this; diff --git a/src/file_analysis/Component.h b/src/file_analysis/Component.h index bd690bc081..4cf2dced60 100644 --- a/src/file_analysis/Component.h +++ b/src/file_analysis/Component.h @@ -5,6 +5,7 @@ #include "Tag.h" #include "plugin/Component.h" +#include "plugin/TaggedComponent.h" #include "Val.h" @@ -22,7 +23,8 @@ class Analyzer; * A plugin can provide a specific file analyzer by registering this * analyzer component, describing the analyzer. */ -class Component : public plugin::Component { +class Component : public plugin::Component, + public plugin::TaggedComponent { public: typedef Analyzer* (*factory_callback)(RecordVal* args, File* file); @@ -38,15 +40,8 @@ public: * from file_analysis::Analyzer. This is typically a static \c * Instatiate() method inside the class that just allocates and * returns a new instance. - * - * @param subtype A subtype associated with this component that - * further distinguishes it. The subtype will be integrated into - * the file_analysis::Tag that the manager associates with this analyzer, - * and analyzer instances can accordingly access it via - * file_analysis::Tag(). If not used, leave at zero. */ - Component(const char* name, factory_callback factory, - file_analysis::Tag::subtype_t subtype = 0); + Component(const char* name, factory_callback factory); /** * Copy constructor. @@ -79,13 +74,6 @@ public: */ factory_callback Factory() const { return factory; } - /** - * Returns the analyzer's tag. Note that this is automatically - * generated for each new Components, and hence unique across all of - * them. - */ - file_analysis::Tag Tag() const; - /** * Generates a human-readable description of the component's main * parameters. This goes into the output of \c "bro -NN". @@ -98,10 +86,6 @@ private: const char* name; // The analyzer's name. const char* canon_name; // The analyzer's canonical name. factory_callback factory; // The analyzer's factory callback. - file_analysis::Tag tag; // The automatically assigned analyzer tag. - - // Global counter used to generate unique tags. - static file_analysis::Tag::type_t type_counter; }; } diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index a27070174b..1197cd06f6 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -88,7 +88,7 @@ File::File(const string& file_id, Connection* conn, analyzer::Tag tag, if ( conn ) { // add source, connection, is_orig fields - SetSource(analyzer_mgr->GetAnalyzerName(tag)); + SetSource(analyzer_mgr->GetComponentName(tag)); val->Assign(is_orig_idx, new Val(is_orig, TYPE_BOOL)); UpdateConnectionFields(conn, is_orig); } diff --git a/src/file_analysis/FileTimer.cc b/src/file_analysis/FileTimer.cc index 575857fd15..6b1d70f136 100644 --- a/src/file_analysis/FileTimer.cc +++ b/src/file_analysis/FileTimer.cc @@ -14,7 +14,7 @@ FileTimer::FileTimer(double t, const string& id, double interval) void FileTimer::Dispatch(double t, int is_expire) { - File* file = file_mgr->Lookup(file_id); + File* file = file_mgr->LookupFile(file_id); if ( ! file ) return; diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index 243786b83a..b7f4335717 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -18,10 +18,8 @@ TableVal* Manager::disabled = 0; string Manager::salt; Manager::Manager() + : ComponentManager("Files") { - tag_enum_type = new EnumType("Files::Tag"); - ::ID* id = install_ID("Tag", "Files", true, true); - add_type(id, tag_enum_type, 0, 0); } Manager::~Manager() @@ -35,27 +33,7 @@ void Manager::InitPreScript() for ( std::list::const_iterator i = analyzers.begin(); i != analyzers.end(); ++i ) - RegisterAnalyzerComponent(*i); - } - -void Manager::RegisterAnalyzerComponent(Component* component) - { - const char* cname = component->CanonicalName(); - - if ( tag_enum_type->Lookup("Files", cname) != -1 ) - reporter->FatalError("File Analyzer %s defined more than once", cname); - - DBG_LOG(DBG_FILE_ANALYSIS, "Registering analyzer %s (tag %s)", - component->Name(), component->Tag().AsString().c_str()); - - analyzers_by_name.insert(std::make_pair(cname, component)); - analyzers_by_tag.insert(std::make_pair(component->Tag(), component)); - analyzers_by_val.insert(std::make_pair( - component->Tag().AsEnumVal()->InternalInt(), component)); - - string id = fmt("ANALYZER_%s", cname); - tag_enum_type->AddName("Files", id.c_str(), - component->Tag().AsEnumVal()->InternalInt(), true); + RegisterComponent(*i, "ANALYZER_"); } void Manager::InitPostScript() @@ -193,7 +171,7 @@ void Manager::SetSize(uint64 size, analyzer::Tag tag, Connection* conn, bool Manager::SetTimeoutInterval(const string& file_id, double interval) const { - File* file = Lookup(file_id); + File* file = LookupFile(file_id); if ( ! file ) return false; @@ -208,7 +186,7 @@ bool Manager::SetTimeoutInterval(const string& file_id, double interval) const bool Manager::AddAnalyzer(const string& file_id, file_analysis::Tag tag, RecordVal* args) const { - File* file = Lookup(file_id); + File* file = LookupFile(file_id); if ( ! file ) return false; @@ -219,7 +197,7 @@ bool Manager::AddAnalyzer(const string& file_id, file_analysis::Tag tag, bool Manager::RemoveAnalyzer(const string& file_id, file_analysis::Tag tag, RecordVal* args) const { - File* file = Lookup(file_id); + File* file = LookupFile(file_id); if ( ! file ) return false; @@ -257,7 +235,7 @@ File* Manager::GetFile(const string& file_id, Connection* conn, return rval; } -File* Manager::Lookup(const string& file_id) const +File* Manager::LookupFile(const string& file_id) const { IDMap::const_iterator it = id_map.find(file_id); @@ -269,7 +247,7 @@ File* Manager::Lookup(const string& file_id) const void Manager::Timeout(const string& file_id, bool is_terminating) { - File* file = Lookup(file_id); + File* file = LookupFile(file_id); if ( ! file ) return; @@ -370,59 +348,15 @@ bool Manager::IsDisabled(analyzer::Tag tag) Analyzer* Manager::InstantiateAnalyzer(Tag tag, RecordVal* args, File* f) const { - analyzer_map_by_tag::const_iterator it = analyzers_by_tag.find(tag); + Component* c = Lookup(tag); - if ( it == analyzers_by_tag.end() ) + if ( ! c ) reporter->InternalError("cannot instantiate unknown file analyzer: %s", tag.AsString().c_str()); - Component* c = it->second; - if ( ! c->Factory() ) reporter->InternalError("file analyzer %s cannot be instantiated " "dynamically", c->CanonicalName()); return c->Factory()(args, f); } - -const char* Manager::GetAnalyzerName(Val* v) const - { - return GetAnalyzerName(file_analysis::Tag(v->AsEnumVal())); - } - -const char* Manager::GetAnalyzerName(file_analysis::Tag tag) const - { - analyzer_map_by_tag::const_iterator it = analyzers_by_tag.find(tag); - - if ( it == analyzers_by_tag.end() ) - reporter->InternalError("cannot get name of unknown file analyzer: %s", - tag.AsString().c_str()); - - return it->second->CanonicalName(); - } - -file_analysis::Tag Manager::GetAnalyzerTag(const char* name) const - { - analyzer_map_by_name::const_iterator it = analyzers_by_name.find(name); - - if ( it == analyzers_by_name.end() ) - return file_analysis::Tag(); - - return it->second->Tag(); - } - -file_analysis::Tag Manager::GetAnalyzerTag(Val* v) const - { - analyzer_map_by_val::const_iterator it = - analyzers_by_val.find(v->AsEnumVal()->InternalInt()); - - if ( it == analyzers_by_val.end() ) - return file_analysis::Tag(); - - return it->second->Tag(); - } - -EnumType* Manager::GetTagEnumType() - { - return tag_enum_type; - } diff --git a/src/file_analysis/Manager.h b/src/file_analysis/Manager.h index 9a37042669..dcf33edc99 100644 --- a/src/file_analysis/Manager.h +++ b/src/file_analysis/Manager.h @@ -18,7 +18,8 @@ #include "File.h" #include "FileTimer.h" #include "Component.h" - +#include "Tag.h" +#include "plugin/ComponentManager.h" #include "analyzer/Tag.h" #include "file_analysis/file_analysis.bif.h" @@ -28,7 +29,7 @@ namespace file_analysis { /** * Main entry point for interacting with file analysis. */ -class Manager { +class Manager : public plugin::ComponentManager { public: /** @@ -210,48 +211,6 @@ public: */ Analyzer* InstantiateAnalyzer(Tag tag, RecordVal* args, File* f) const; - /** - * Translates a script-level file analyzer tag in to corresponding file - * analyzer name. - * @param v The enum val of a file analyzer. - * @return The human-readable name of the file analyzer. - */ - const char* GetAnalyzerName(Val* v) const; - - /** - * Translates a script-level file analyzer tag in to corresponding file - * analyzer name. - * @param tag The analyzer tag of a file analyzer. - * @return The human-readable name of the file analyzer. - */ - const char* GetAnalyzerName(file_analysis::Tag tag) const; - - /** - * Translates an analyzer name into the corresponding tag. - * - * @param name The name. - * - * @return The tag. If the name does not correspond to a valid - * analyzer, the returned tag will evaluate to false. - */ - file_analysis::Tag GetAnalyzerTag(const char* name) const; - - /** - * Translates an analyzer enum value into the corresponding tag. - * - * @param v the enum val of the file analyzer. - * - * @return The tag. If the val does not correspond to a valid - * analyzer, the returned tag will evaluate to false. - */ - file_analysis::Tag GetAnalyzerTag(Val* v) const; - - /** - * Returns the enum type that corresponds to the script-level type - * \c Files::Tag. - */ - EnumType* GetTagEnumType(); - protected: friend class FileTimer; @@ -285,7 +244,7 @@ protected: * @return the File object mapped to \a file_id, or a null pointer if no * mapping exists. */ - File* Lookup(const string& file_id) const; + File* LookupFile(const string& file_id) const; /** * Evaluate timeout policy for a file and remove the File object mapped to @@ -325,20 +284,10 @@ protected: static bool IsDisabled(analyzer::Tag tag); private: - typedef map analyzer_map_by_name; - typedef map analyzer_map_by_tag; - typedef map analyzer_map_by_val; - - void RegisterAnalyzerComponent(Component* component); IDMap id_map; /**< Map file ID to file_analysis::File records. */ IDSet ignored; /**< Ignored files. Will be finally removed on EOF. */ string current_file_id; /**< Hash of what get_file_handle event sets. */ - EnumType* tag_enum_type; /**< File analyzer tag type. */ - - analyzer_map_by_name analyzers_by_name; - analyzer_map_by_tag analyzers_by_tag; - analyzer_map_by_val analyzers_by_val; static TableVal* disabled; /**< Table of disabled analyzers. */ static string salt; /**< A salt added to file handles before hashing. */ diff --git a/src/file_analysis/Tag.h b/src/file_analysis/Tag.h index 85c20da5b5..aa38836403 100644 --- a/src/file_analysis/Tag.h +++ b/src/file_analysis/Tag.h @@ -6,12 +6,13 @@ #include "config.h" #include "util.h" #include "../Tag.h" +#include "plugin/TaggedComponent.h" +#include "plugin/ComponentManager.h" class EnumVal; namespace file_analysis { -class Manager; class Component; /** @@ -87,15 +88,15 @@ public: static Tag Error; protected: - friend class file_analysis::Manager; - friend class file_analysis::Component; + friend class plugin::ComponentManager; + friend class plugin::TaggedComponent; /** * Constructor. * * @param type The main type. Note that the \a file_analysis::Manager * manages the value space internally, so noone else should assign - * main tyoes. + * main types. * * @param subtype The sub type, which is left to an analyzer for * interpretation. By default it's set to zero. diff --git a/src/file_analysis/analyzer/data_event/DataEvent.cc b/src/file_analysis/analyzer/data_event/DataEvent.cc index 44498f41e1..cf2d7e52ec 100644 --- a/src/file_analysis/analyzer/data_event/DataEvent.cc +++ b/src/file_analysis/analyzer/data_event/DataEvent.cc @@ -12,7 +12,7 @@ using namespace file_analysis; DataEvent::DataEvent(RecordVal* args, File* file, EventHandlerPtr ce, EventHandlerPtr se) - : file_analysis::Analyzer(file_mgr->GetAnalyzerTag("DATA_EVENT"), + : file_analysis::Analyzer(file_mgr->GetComponentTag("DATA_EVENT"), args, file), chunk_event(ce), stream_event(se) { diff --git a/src/file_analysis/analyzer/extract/Extract.cc b/src/file_analysis/analyzer/extract/Extract.cc index 0de1402939..28b5cf5a63 100644 --- a/src/file_analysis/analyzer/extract/Extract.cc +++ b/src/file_analysis/analyzer/extract/Extract.cc @@ -9,7 +9,7 @@ using namespace file_analysis; Extract::Extract(RecordVal* args, File* file, const string& arg_filename) - : file_analysis::Analyzer(file_mgr->GetAnalyzerTag("EXTRACT"), args, file), + : file_analysis::Analyzer(file_mgr->GetComponentTag("EXTRACT"), args, file), filename(arg_filename) { fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666); diff --git a/src/file_analysis/analyzer/hash/Hash.cc b/src/file_analysis/analyzer/hash/Hash.cc index 12463df8bf..9829934301 100644 --- a/src/file_analysis/analyzer/hash/Hash.cc +++ b/src/file_analysis/analyzer/hash/Hash.cc @@ -10,7 +10,7 @@ using namespace file_analysis; Hash::Hash(RecordVal* args, File* file, HashVal* hv, const char* arg_kind) - : file_analysis::Analyzer(file_mgr->GetAnalyzerTag(to_upper(string(arg_kind)).c_str()), args, file), hash(hv), fed(false), kind(arg_kind) + : file_analysis::Analyzer(file_mgr->GetComponentTag(to_upper(arg_kind).c_str()), args, file), hash(hv), fed(false), kind(arg_kind) { hash->Init(); } diff --git a/src/file_analysis/file_analysis.bif b/src/file_analysis/file_analysis.bif index 7e07ddf6bb..0e904f298f 100644 --- a/src/file_analysis/file_analysis.bif +++ b/src/file_analysis/file_analysis.bif @@ -21,7 +21,7 @@ function Files::__add_analyzer%(file_id: string, tag: Files::Tag, args: any%): b using BifType::Record::Files::AnalyzerArgs; RecordVal* rv = args->AsRecordVal()->CoerceTo(AnalyzerArgs); bool result = file_mgr->AddAnalyzer(file_id->CheckString(), - file_mgr->GetAnalyzerTag(tag), rv); + file_mgr->GetComponentTag(tag), rv); Unref(rv); return new Val(result, TYPE_BOOL); %} @@ -32,7 +32,7 @@ function Files::__remove_analyzer%(file_id: string, tag: Files::Tag, args: any%) using BifType::Record::Files::AnalyzerArgs; RecordVal* rv = args->AsRecordVal()->CoerceTo(AnalyzerArgs); bool result = file_mgr->RemoveAnalyzer(file_id->CheckString(), - file_mgr->GetAnalyzerTag(tag) , rv); + file_mgr->GetComponentTag(tag) , rv); Unref(rv); return new Val(result, TYPE_BOOL); %} @@ -47,7 +47,7 @@ function Files::__stop%(file_id: string%): bool ## :bro:see:`Files::analyzer_name`. function Files::__analyzer_name%(tag: Files::Tag%) : string %{ - return new StringVal(file_mgr->GetAnalyzerName(tag)); + return new StringVal(file_mgr->GetComponentName(tag)); %} module GLOBAL; diff --git a/src/plugin/ComponentManager.h b/src/plugin/ComponentManager.h new file mode 100644 index 0000000000..16f9d80743 --- /dev/null +++ b/src/plugin/ComponentManager.h @@ -0,0 +1,248 @@ +#ifndef PLUGIN_COMPONENT_MANAGER_H +#define PLUGIN_COMPONENT_MANAGER_H + +#include +#include +#include + +#include "Type.h" +#include "ID.h" +#include "Var.h" +#include "Val.h" +#include "Reporter.h" + +namespace plugin { + +/** + * A class that manages tracking of plugin components (e.g. analyzers) and + * installs identifiers in the script-layer to identify them by a unique tag, + * (a script-layer enum value). + * + * @tparam T A ::Tag type or derivative. + * @tparam C A plugin::TaggedComponent type derivative. + */ +template +class ComponentManager { +public: + + /** + * Constructor creates a new enum type called a "Tag" to associate with + * a component. + * + * @param module The script-layer module in which to install the "Tag" ID + * representing an enum type. + */ + ComponentManager(const string& module); + + /** + * @return The script-layer module in which the component's "Tag" ID lives. + */ + const char* GetModule() const; + + /** + * @return A list of all registered components. + */ + list GetComponents() const; + + /** + * @return The enum type associated with the script-layer "Tag". + */ + EnumType* GetTagEnumType() const; + + /** + * Get a component name from its tag. + * + * @param tag A component's tag. + * @return The canonical component name. + */ + const char* GetComponentName(T tag) const; + + /** + * Get a component name from it's enum value. + * + * @param val A component's enum value. + * @return The canonical component name. + */ + const char* GetComponentName(Val* val) const; + + /** + * Get a component tag from its name. + * + * @param name A component's canonical name. + * @return The component's tag, or a tag representing an error if + * no such component assoicated with the name exists. + */ + T GetComponentTag(const string& name) const; + + /** + * Get a component tag from its enum value. + * + * @param v A component's enum value. + * @return The component's tag, or a tag representing an error if + * no such component assoicated with the value exists. + */ + T GetComponentTag(Val* v) const; + +protected: + + /** + * Add a component the internal maps used to keep track of it and create + * a script-layer ID for the component's enum value. + * + * @param component A component to track. + * @param prefix The script-layer ID associated with the component's enum + * value will be a concatenation of this prefix and the component's + * canonical name. + */ + void RegisterComponent(C* component, const string& prefix = ""); + + /** + * @param name The canonical name of a component. + * @return The component associated with the name or a null pointer if no + * such component exists. + */ + C* Lookup(const string& name) const; + + /** + * @param name A component tag. + * @return The component associated with the tag or a null pointer if no + * such component exists. + */ + C* Lookup(const T& tag) const; + + /** + * @param name A component's enum value. + * @return The component associated with the value or a null pointer if no + * such component exists. + */ + C* Lookup(EnumVal* val) const; + +private: + + string module; /**< Script layer module in which component tags live. */ + EnumType* tag_enum_type; /**< Enum type of component tags. */ + map components_by_name; + map components_by_tag; + map components_by_val; +}; + +template +ComponentManager::ComponentManager(const string& arg_module) + : module(arg_module) + { + tag_enum_type = new EnumType(module + "::Tag"); + ::ID* id = install_ID("Tag", module.c_str(), true, true); + add_type(id, tag_enum_type, 0, 0); + } + +template +const char* ComponentManager::GetModule() const + { + return module.c_str(); + } + +template +list ComponentManager::GetComponents() const + { + list rval; + typename map::const_iterator i; + + for ( i = components_by_tag.begin(); i != components_by_tag.end(); ++i ) + rval.push_back(i->second); + + return rval; + } + +template +EnumType* ComponentManager::GetTagEnumType() const + { + return tag_enum_type; + } + +template +const char* ComponentManager::GetComponentName(T tag) const + { + static const char* error = ""; + + if ( ! tag ) + return error; + + C* c = Lookup(tag); + + if ( ! c ) + reporter->InternalError("request for name of unknown component tag %s", + tag.AsString().c_str()); + + return c->CanonicalName(); + } + +template +const char* ComponentManager::GetComponentName(Val* val) const + { + return GetComponentName(T(val->AsEnumVal())); + } + +template +T ComponentManager::GetComponentTag(const string& name) const + { + C* c = Lookup(name); + return c ? c->Tag() : T(); + } + +template +T ComponentManager::GetComponentTag(Val* v) const + { + C* c = Lookup(v->AsEnumVal()); + return c ? c->Tag() : T(); + } + +template +C* ComponentManager::Lookup(const string& name) const + { + typename map::const_iterator i = + components_by_name.find(to_upper(name)); + return i != components_by_name.end() ? i->second : 0; + } + +template +C* ComponentManager::Lookup(const T& tag) const + { + typename map::const_iterator i = components_by_tag.find(tag); + return i != components_by_tag.end() ? i->second : 0; + } + +template +C* ComponentManager::Lookup(EnumVal* val) const + { + typename map::const_iterator i = + components_by_val.find(val->InternalInt()); + return i != components_by_val.end() ? i->second : 0; + } + +template +void ComponentManager::RegisterComponent(C* component, + const string& prefix) + { + const char* cname = component->CanonicalName(); + + if ( Lookup(cname) ) + reporter->FatalError("Component '%s::%s' defined more than once", + module.c_str(), cname); + + DBG_LOG(DBG_PLUGINS, "Registering component %s (tag %s)", + component->Name(), component->Tag().AsString().c_str()); + + components_by_name.insert(std::make_pair(cname, component)); + components_by_tag.insert(std::make_pair(component->Tag(), component)); + components_by_val.insert(std::make_pair( + component->Tag().AsEnumVal()->InternalInt(), component)); + + // Install an identfier for enum value + string id = fmt("%s%s", prefix.c_str(), cname); + tag_enum_type->AddName(module, id.c_str(), + component->Tag().AsEnumVal()->InternalInt(), true); + } + +} // namespace plugin + +#endif diff --git a/src/plugin/TaggedComponent.h b/src/plugin/TaggedComponent.h new file mode 100644 index 0000000000..99eab9f230 --- /dev/null +++ b/src/plugin/TaggedComponent.h @@ -0,0 +1,85 @@ +#ifndef PLUGIN_TAGGED_COMPONENT_H +#define PLUGIN_TAGGED_COMPONENT_H + +namespace plugin { + +/** + * A class which has a tag of a given type associated with it. + * + * @tparam T A ::Tag type or derivative. + */ +template +class TaggedComponent { +public: + + /** + * Constructor creates a unique tag value for this component. + * + * @param subtype A subtype associated with this component that + * further distinguishes it. The subtype will be integrated into + * the Tag that the manager associates with this component, + * and component instances can accordingly access it via Tag(). + * If not used, leave at zero. + */ + TaggedComponent(typename T::subtype_t subtype = 0); + + /** + * Copy constructor. + * + * @param other Another component from which to copy its tag value. + */ + TaggedComponent(const TaggedComponent& other); + + /** + * Assignment operator. + * + * @param other A component to assign. + * @return The assigned object. + */ + TaggedComponent& operator=(const TaggedComponent& other); + + /** + * @return The component's tag. + */ + T Tag() const; + +private: + + T tag; /**< The automatically assigned analyzer tag. */ + static typename T::type_t type_counter; /**< Used to generate globally + unique tags. */ +}; + +template +TaggedComponent::TaggedComponent(typename T::subtype_t subtype) + { + tag = T(++type_counter, subtype); + } + +template +TaggedComponent::TaggedComponent(const TaggedComponent& other) + { + tag = other.tag; + } + +template +TaggedComponent& +TaggedComponent::operator =(const TaggedComponent& other) + { + if ( &other != this ) + tag = other.tag; + + return *this; + } + +template +T TaggedComponent::Tag() const + { + return tag; + } + +template typename T::type_t TaggedComponent::type_counter(0); + +} // namespace plugin + +#endif From 238e4a8d5c24c5cc2c6637902effe4b322a9fae5 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 1 Aug 2013 10:45:44 -0500 Subject: [PATCH 172/881] Minor fix to file/protocol analyzer plugin reference doc. --- src/BroDoc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 3cb271bdbf..55dc8ce558 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -564,7 +564,7 @@ static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module) dummy_id->MakeType(); list* r = new list(); - r->push_back("Unique identifiers for protocol analyzers."); + r->push_back("Unique identifiers for analyzers."); BroDocObj bdo(dummy_id, r, true); @@ -622,7 +622,7 @@ void CreateFileAnalyzerDoc(const char* filename) FILE* f = fopen(filename, "w"); fprintf(f, "File Analyzer Reference\n"); - fprintf(f, "===========================\n\n"); + fprintf(f, "=======================\n\n"); WriteAnalyzerTagDefn(f, file_mgr->GetTagEnumType(), "Files"); From 34965b4e77b3091dd0d959873b21239f3da02ac4 Mon Sep 17 00:00:00 2001 From: Matthias Vallentin Date: Thu, 1 Aug 2013 19:15:28 +0200 Subject: [PATCH 173/881] Support UHF hashing for >= UHASH_KEY_SIZE bytes. --- src/probabilistic/Hasher.cc | 23 +++++++++++++++++++---- src/probabilistic/Hasher.h | 5 +++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/probabilistic/Hasher.cc b/src/probabilistic/Hasher.cc index b59274df7d..fe8eb66ad9 100644 --- a/src/probabilistic/Hasher.cc +++ b/src/probabilistic/Hasher.cc @@ -1,6 +1,7 @@ // See the file "COPYING" in the main distribution directory for copyright. #include +#include #include "Hasher.h" #include "NetVar.h" @@ -82,15 +83,29 @@ Hasher::Hasher(size_t arg_k, size_t arg_seed) seed = arg_seed; } -UHF::UHF(size_t seed) - : h(seed) +UHF::UHF(size_t arg_seed) + : h(arg_seed) { + seed = arg_seed; } +// This function is almost equivalent to HashKey::HashBytes except that it does +// not depend on global state and that we mix in the seed multiple times. Hasher::digest UHF::hash(const void* x, size_t n) const { - assert(n <= UHASH_KEY_SIZE); - return n == 0 ? 0 : h(x, n); + if ( n <= UHASH_KEY_SIZE ) + return n == 0 ? 0 : h(x, n); + + unsigned char d[16]; + MD5(reinterpret_cast(x), n, d); + + const unsigned char* s = reinterpret_cast(&seed); + for ( size_t i = 0; i < 16; ++i ) + d[i] ^= s[i % sizeof(seed)]; + + MD5(d, 16, d); + + return d[0]; } DefaultHasher::DefaultHasher(size_t k, size_t seed) diff --git a/src/probabilistic/Hasher.h b/src/probabilistic/Hasher.h index 6b75fa1bea..a3322f5e37 100644 --- a/src/probabilistic/Hasher.h +++ b/src/probabilistic/Hasher.h @@ -123,9 +123,9 @@ public: * Constructs an H3 hash function seeded with a given seed and an * optional extra seed to replace the initial Bro seed. * - * @param seed The seed to use for this instance. + * @param arg_seed The seed to use for this instance. */ - UHF(size_t seed = 0); + UHF(size_t arg_seed = 0); template Hasher::digest operator()(const T& x) const @@ -171,6 +171,7 @@ private: static size_t compute_seed(size_t seed); H3 h; + size_t seed; }; From ee7dba806d4016af59f969237a4a06d1cf158013 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 1 Aug 2013 12:17:51 -0500 Subject: [PATCH 174/881] Fix some build errors. On GCC, some namespace sensitivity and file analyzer plugins now need to link in Analyzer since it's not just a header anymore. --- src/file_analysis/Manager.cc | 3 ++- src/file_analysis/analyzer/data_event/CMakeLists.txt | 2 +- src/file_analysis/analyzer/extract/CMakeLists.txt | 2 +- src/file_analysis/analyzer/hash/CMakeLists.txt | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index b7f4335717..5975133356 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -18,7 +18,8 @@ TableVal* Manager::disabled = 0; string Manager::salt; Manager::Manager() - : ComponentManager("Files") + : plugin::ComponentManager("Files") { } diff --git a/src/file_analysis/analyzer/data_event/CMakeLists.txt b/src/file_analysis/analyzer/data_event/CMakeLists.txt index 81551feda2..49e23d49a0 100644 --- a/src/file_analysis/analyzer/data_event/CMakeLists.txt +++ b/src/file_analysis/analyzer/data_event/CMakeLists.txt @@ -4,5 +4,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) bro_plugin_begin(Bro FileDataEvent) -bro_plugin_cc(DataEvent.cc Plugin.cc) +bro_plugin_cc(DataEvent.cc Plugin.cc ../../Analyzer.cc) bro_plugin_end() diff --git a/src/file_analysis/analyzer/extract/CMakeLists.txt b/src/file_analysis/analyzer/extract/CMakeLists.txt index df3fa2646d..e413196db2 100644 --- a/src/file_analysis/analyzer/extract/CMakeLists.txt +++ b/src/file_analysis/analyzer/extract/CMakeLists.txt @@ -4,5 +4,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) bro_plugin_begin(Bro FileExtract) -bro_plugin_cc(Extract.cc Plugin.cc) +bro_plugin_cc(Extract.cc Plugin.cc ../../Analyzer.cc) bro_plugin_end() diff --git a/src/file_analysis/analyzer/hash/CMakeLists.txt b/src/file_analysis/analyzer/hash/CMakeLists.txt index 5734740198..0e3143ee05 100644 --- a/src/file_analysis/analyzer/hash/CMakeLists.txt +++ b/src/file_analysis/analyzer/hash/CMakeLists.txt @@ -4,6 +4,6 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) bro_plugin_begin(Bro FileHash) -bro_plugin_cc(Hash.cc Plugin.cc) +bro_plugin_cc(Hash.cc Plugin.cc ../../Analyzer.cc) bro_plugin_bif(events.bif) bro_plugin_end() From 7ab21706411bb1bb6c191cce7e86b16d2facae78 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 1 Aug 2013 10:46:05 -0700 Subject: [PATCH 175/881] Using a real hash function for hashing a BitVector's internal state. --- src/probabilistic/BitVector.cc | 17 ++++++++++++----- .../btest/Baseline/bifs.bloomfilter-seed/output | 16 ++++++++-------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/probabilistic/BitVector.cc b/src/probabilistic/BitVector.cc index f820e6df27..e8c2b2f80e 100644 --- a/src/probabilistic/BitVector.cc +++ b/src/probabilistic/BitVector.cc @@ -1,10 +1,12 @@ // See the file "COPYING" in the main distribution directory for copyright. -#include "BitVector.h" - +#include #include #include + +#include "BitVector.h" #include "Serializer.h" +#include "digest.h" using namespace probabilistic; @@ -494,10 +496,15 @@ size_t BitVector::Hash() const { size_t hash = 0; - for ( size_type i = 0; i < Blocks(); ++i ) - hash += bits[i]; + u_char buf[SHA256_DIGEST_LENGTH]; + SHA256_CTX ctx; + sha256_init(&ctx); - return hash; + for ( size_type i = 0; i < Blocks(); ++i ) + sha256_update(&ctx, &bits[i], sizeof(bits[i])); + + sha256_final(&ctx, buf); + return *reinterpret_cast(buf); // Use the first bytes as seed. } BitVector::size_type BitVector::lowest_bit(block_type block) diff --git a/testing/btest/Baseline/bifs.bloomfilter-seed/output b/testing/btest/Baseline/bifs.bloomfilter-seed/output index 53e0f583f2..533085900f 100644 --- a/testing/btest/Baseline/bifs.bloomfilter-seed/output +++ b/testing/btest/Baseline/bifs.bloomfilter-seed/output @@ -1,8 +1,8 @@ -bf1, global_seed, 1 -bf2, global_seed, 5 -bf3, my_seed, 5 -bf4, my_seed, 6 -bf1, global_seed, 5 -bf2, global_seed, 6 -bf3, my_seed, 5 -bf4, my_seed, 6 +bf1, global_seed, 11979365913534242684 +bf2, global_seed, 12550100962110750449 +bf3, my_seed, 12550100962110750449 +bf4, my_seed, 945716460325754659 +bf1, global_seed, 12550100962110750449 +bf2, global_seed, 945716460325754659 +bf3, my_seed, 12550100962110750449 +bf4, my_seed, 945716460325754659 From 948441e1761611e6f9f1829519ee0da794f1fa06 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 1 Aug 2013 10:52:15 -0700 Subject: [PATCH 176/881] Test expected false positive, but it isn't one any more. Matthias, please check if this is correct. --- scripts/base/init-bare.bro | 2 +- testing/btest/Baseline/bifs.bloomfilter/output | 1 + testing/btest/bifs/bloomfilter.bro | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index e5300cdc9f..6068796fbd 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -3044,7 +3044,7 @@ const snaplen = 8192 &redef; ## Seed for hashes computed internally for probabilistic data structures. Using ## the same value here will make the hashes compatible between independent Bro -## instances. If left unset, Bro will use a temporary local seed. +## instances. If left unset, Bro will use a temporary local seed. const global_hash_seed: string = "" &redef; # Load BiFs defined by plugins. diff --git a/testing/btest/Baseline/bifs.bloomfilter/output b/testing/btest/Baseline/bifs.bloomfilter/output index 731b7c7ce9..82414f0686 100644 --- a/testing/btest/Baseline/bifs.bloomfilter/output +++ b/testing/btest/Baseline/bifs.bloomfilter/output @@ -12,6 +12,7 @@ error: false-positive rate must take value between 0 and 1 1 1 1 +0, no fp 1 1 1 diff --git a/testing/btest/bifs/bloomfilter.bro b/testing/btest/bifs/bloomfilter.bro index 3d3133fa84..95455bc74c 100644 --- a/testing/btest/bifs/bloomfilter.bro +++ b/testing/btest/bifs/bloomfilter.bro @@ -28,7 +28,7 @@ function test_basic_bloom_filter() bloomfilter_add(bf_str, "bar"); print bloomfilter_lookup(bf_str, "foo"); print bloomfilter_lookup(bf_str, "bar"); - print bloomfilter_lookup(bf_str, "b4zzz"); # FP + print bloomfilter_lookup(bf_str, "b4zzz"), "no fp"; # FP print bloomfilter_lookup(bf_str, "quuux"); # FP bloomfilter_add(bf_str, 0.5); # Type mismatch bloomfilter_add(bf_str, 100); # Type mismatch From 0d39e00bc4b989d36bef379ebae7fcd7cd81ed3a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 1 Aug 2013 14:39:35 -0500 Subject: [PATCH 177/881] Fix a ref counting bug. BIT-1049 #request-merge --- src/file_analysis/AnalyzerSet.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/file_analysis/AnalyzerSet.cc b/src/file_analysis/AnalyzerSet.cc index 2dc4902314..f7abc01dc2 100644 --- a/src/file_analysis/AnalyzerSet.cc +++ b/src/file_analysis/AnalyzerSet.cc @@ -15,7 +15,7 @@ static void analyzer_del_func(void* v) AnalyzerSet::AnalyzerSet(File* arg_file) : file(arg_file) { TypeList* t = new TypeList(); - t->Append(file_mgr->GetTagEnumType()); + t->Append(file_mgr->GetTagEnumType()->Ref()); t->Append(BifType::Record::Files::AnalyzerArgs->Ref()); analyzer_hash = new CompositeHash(t); Unref(t); From 6a45a67eb52e208b3fd1156354b555487e614558 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 1 Aug 2013 14:07:39 -0700 Subject: [PATCH 178/881] update documentation, rename get* to Get* and make hasher persistent --- src/probabilistic/Topk.cc | 54 ++++++------ src/probabilistic/Topk.h | 101 +++++++++++++++++------ src/probabilistic/top-k.bif | 80 +++++++++++++----- testing/btest/Baseline/bifs.topk/.stderr | 22 ++--- 4 files changed, 174 insertions(+), 83 deletions(-) diff --git a/src/probabilistic/Topk.cc b/src/probabilistic/Topk.cc index d03a10ccfc..6828fb0d7f 100644 --- a/src/probabilistic/Topk.cc +++ b/src/probabilistic/Topk.cc @@ -19,21 +19,23 @@ static void topk_element_hash_delete_func(void* val) Element::~Element() { - if ( value ) - Unref(value); - value=0; + Unref(value); + } + +void TopkVal::Typify(BroType* t) + { + assert(!hash && !type); + type = t->Ref(); + TypeList* tl = new TypeList(t); + tl->Append(t->Ref()); + hash = new CompositeHash(tl); + Unref(tl); } HashKey* TopkVal::GetHash(Val* v) const { - TypeList* tl = new TypeList(v->Type()); - tl->Append(v->Type()->Ref()); - CompositeHash* topk_hash = new CompositeHash(tl); - Unref(tl); - - HashKey* key = topk_hash->ComputeHash(v, 1); + HashKey* key = hash->ComputeHash(v, 1); assert(key); - delete topk_hash; return key; } @@ -45,6 +47,7 @@ TopkVal::TopkVal(uint64 arg_size) : OpaqueVal(topk_type) type = 0; numElements = 0; pruned = false; + hash = 0; } TopkVal::TopkVal() : OpaqueVal(topk_type) @@ -54,6 +57,7 @@ TopkVal::TopkVal() : OpaqueVal(topk_type) size = 0; type = 0; numElements = 0; + hash = 0; } TopkVal::~TopkVal() @@ -69,9 +73,8 @@ TopkVal::~TopkVal() bi++; } - if ( type ) - Unref(type); - type = 0; + Unref(type); + delete hash; } void TopkVal::Merge(const TopkVal* value, bool doPrune) @@ -80,7 +83,7 @@ void TopkVal::Merge(const TopkVal* value, bool doPrune) if ( type == 0 ) { assert(numElements == 0); - type = value->type->Ref(); + Typify(value->type); } else if ( !same_type(type, value->type) ) @@ -227,7 +230,10 @@ bool TopkVal::DoUnserialize(UnserialInfo* info) v &= UNSERIALIZE(&type_present); if ( type_present ) { - type = BroType::Unserialize(info); + BroType* deserialized_type = BroType::Unserialize(info); + + Typify(deserialized_type); + Unref(deserialized_type); assert(type); } else @@ -268,7 +274,7 @@ bool TopkVal::DoUnserialize(UnserialInfo* info) } -VectorVal* TopkVal::getTopK(int k) const // returns vector +VectorVal* TopkVal::GetTopK(int k) const // returns vector { if ( numElements == 0 ) { @@ -310,14 +316,14 @@ VectorVal* TopkVal::getTopK(int k) const // returns vector return t; } -uint64_t TopkVal::getCount(Val* value) const +uint64_t TopkVal::GetCount(Val* value) const { HashKey* key = GetHash(value); Element* e = (Element*) elementDict->Lookup(key); if ( e == 0 ) { - reporter->Error("getCount for element that is not in top-k"); + reporter->Error("GetCount for element that is not in top-k"); return 0; } @@ -325,14 +331,14 @@ uint64_t TopkVal::getCount(Val* value) const return e->parent->count; } -uint64_t TopkVal::getEpsilon(Val* value) const +uint64_t TopkVal::GetEpsilon(Val* value) const { HashKey* key = GetHash(value); Element* e = (Element*) elementDict->Lookup(key); if ( e == 0 ) { - reporter->Error("getEpsilon for element that is not in top-k"); + reporter->Error("GetEpsilon for element that is not in top-k"); return 0; } @@ -340,7 +346,7 @@ uint64_t TopkVal::getEpsilon(Val* value) const return e->epsilon; } -uint64_t TopkVal::getSum() const +uint64_t TopkVal::GetSum() const { uint64_t sum = 0; @@ -353,7 +359,7 @@ uint64_t TopkVal::getSum() const } if ( pruned ) - reporter->Warning("TopkVal::getSum() was used on a pruned data structure. Result values do not represent total element count"); + reporter->Warning("TopkVal::GetSum() was used on a pruned data structure. Result values do not represent total element count"); return sum; } @@ -362,10 +368,8 @@ void TopkVal::Encountered(Val* encountered) { // ok, let's see if we already know this one. - //printf("NumElements: %d\n", numElements); - // check type compatibility if ( numElements == 0 ) - type = encountered->Type()->Ref(); + Typify(encountered->Type()); else if ( !same_type(type, encountered->Type()) ) { diff --git a/src/probabilistic/Topk.h b/src/probabilistic/Topk.h index 2c47fbd181..4f0599025d 100644 --- a/src/probabilistic/Topk.h +++ b/src/probabilistic/Topk.h @@ -34,50 +34,101 @@ declare(PDict, Element); class TopkVal : public OpaqueVal { public: - // Initialize a TopkVal. Size specifies how many total elements are tracked + /** + * Construct a TopkVal. + * + * @param size specifies how many total elements are tracked + * + * @return A newly initialized TopkVal + */ TopkVal(uint64 size); + + /** + * Destructor. + */ ~TopkVal(); - // Call this, when a new value is encountered. Note that on the first call, - // the Bro-Type of the value types that are counted is set. All following calls - // to encountered have to specify the same type + /** + * Call this, when a new value is encountered. Note that on the first call, + * the Bro-Type of the value types that are counted is set. All following calls + * to encountered have to specify the same type. + * + * @param value The encountered element + */ void Encountered(Val* value); - // Return the first k elements of the result vector. At the moment, this does - // not check if it is in the right order or if we can prove that these are - // the correct top-k. Use count and epsilon for this. - VectorVal* getTopK(int k) const; // returns vector + /** + * Get the first k elements of the result vector. At the moment, this does + * not check if it is in the right order or if we can prove that these are + * the correct top-k. Use count and epsilon for this. + * + * @param k Number of top-elements to return + * + * @returns The top-k encountered elements + */ + VectorVal* GetTopK(int k) const; - // Get the current count tracked in the top-k data structure for a certain val. - // Returns 0 if the val is unknown (and logs the error to reporter) - uint64_t getCount(Val* value) const; + /** + * Get the current count tracked in the top-k data structure for a certain val. + * Returns 0 if the val is unknown (and logs the error to reporter) + * + * @param value Bro value to get counts for + * + * @returns internal count for val, 0 if unknown + */ + uint64_t GetCount(Val* value) const; - // Get the current epsilon tracked in the top-k data structure for a certain val. - // Returns 0 if the val is unknown (and logs the error to reporter) - uint64_t getEpsilon(Val* value) const; + /** + * Get the current epsilon tracked in the top-k data structure for a certain val. + * + * @param value Bro value to get epsilons for + * + * @returns the epsilon. Returns 0 if the val is unknown (and logs the error to reporter) + */ + uint64_t GetEpsilon(Val* value) const; - // Get the size set in the constructor - uint64_t getSize() const { return size; } + /** + * Get the size set in the constructor + * + * @returns size of the top-k structure + */ + uint64_t GetSize() const { return size; } - // Get the sum of all counts of all tracked elements. This is equal to the number - // of total observations up to this moment, if no elements were pruned from the data - // structure. - uint64_t getSum() const; + /** + * Get the sum of all counts of all tracked elements. This is equal to the number + * of total observations up to this moment, if no elements were pruned from the data + * structure. + * + * @returns sum of all counts + */ + uint64_t GetSum() const; - // Merge another top-k data structure in this one. - // doPrune specifies if the total count of elements is limited to size after - // merging. - // Please note, that pruning will invalidate the results of getSum. + /** + * Merge another top-k data structure into this one. + * doPrune specifies if the total count of elements is limited to size after + * merging. + * Please note, that pruning will invalidate the results of getSum. + * + * @param value TopkVal to merge into this TopkVal + * + * @param doPrune prune resulting TopkVal to size after merging + */ void Merge(const TopkVal* value, bool doPrune=false); protected: - TopkVal(); // for deserialize + /** + * Construct an empty TopkVal. + * Only used for deserialization + */ + TopkVal(); private: void IncrementCounter(Element* e, unsigned int count = 1); HashKey* GetHash(Val*) const; // this probably should go somewhere else. + void Typify(BroType*); BroType* type; + CompositeHash* hash; std::list buckets; PDict(Element)* elementDict; uint64 size; // how many elements are we tracking? diff --git a/src/probabilistic/top-k.bif b/src/probabilistic/top-k.bif index 83d8e275c1..156e96a65e 100644 --- a/src/probabilistic/top-k.bif +++ b/src/probabilistic/top-k.bif @@ -11,6 +11,8 @@ ## Creates a top-k data structure which tracks size elements. ## +## size: number of elements to track +## ## Returns: Opaque pointer to the data structure. function topk_init%(size: count%): opaque of topk %{ @@ -18,9 +20,14 @@ function topk_init%(size: count%): opaque of topk return v; %} -## Add a new observed object to the data structure. The first -## added object sets the type of data tracked by the top-k data -## structure. All following values have to be of the same type +## Add a new observed object to the data structure. +## +## .. note:: The first added object sets the type of data tracked by +## the top-k data structure. All following values have to be of the same type +## +## handle: the TopK handle +## +## value: observed value function topk_add%(handle: opaque of topk, value: any%): any %{ assert(handle); @@ -32,63 +39,86 @@ function topk_add%(handle: opaque of topk, value: any%): any ## Get the first k elements of the top-k data structure ## +## handle: the TopK handle +## +## k: number of elements to return +## ## Returns: vector of the first k elements function topk_get_top%(handle: opaque of topk, k: count%): any %{ assert(handle); probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; - return h->getTopK(k); + return h->GetTopK(k); %} ## Get an overestimated count of how often value has been encountered. -## value has to be part of the currently tracked elements, otherwise -## 0 will be returned and an error message will be added to reporter. +## +## .. note:: value has to be part of the currently tracked elements, otherwise +## 0 will be returned and an error message will be added to reporter. +## +## handle: the TopK handle +## +## value: Value to look up count for. ## ## Returns: Overestimated number for how often the element has been encountered function topk_count%(handle: opaque of topk, value: any%): count %{ assert(handle); probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; - return new Val(h->getCount(value), TYPE_COUNT); + return new Val(h->GetCount(value), TYPE_COUNT); %} -## Get a the maximal overestimation for count. Same restrictiosn as for topk_count -## apply. +## Get a the maximal overestimation for count. +## +## .. note:: Same restrictiosn as for topk_count apply. +## +## handle: the TopK handle +## +## value: Value to look up epsilon for. ## ## Returns: Number which represents the maximal overesimation for the count of this element. function topk_epsilon%(handle: opaque of topk, value: any%): count %{ assert(handle); probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; - return new Val(h->getEpsilon(value), TYPE_COUNT); + return new Val(h->GetEpsilon(value), TYPE_COUNT); %} ## Get the number of elements this data structure is supposed to track (given on init). -## Note that the actual number of elements in the data structure can be lower or higher -## than this. (higher due to non-pruned merges) +## +## .. note ::Note that the actual number of elements in the data structure can be lower +## or higher (due to non-pruned merges) than thiz ## +## handle: the TopK handle +## ## Returns: size given during initialization function topk_size%(handle: opaque of topk%): count %{ assert(handle); probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; - return new Val(h->getSize(), TYPE_COUNT); + return new Val(h->GetSize(), TYPE_COUNT); %} -## Get the sum of all counts of all elements in the data structure. Is equal to the number -## of all inserted objects if the data structure never has been pruned. Do not use after -## calling topk_merge_prune (will throw a warning message if used afterwards) +## Get the sum of all counts of all elements in the data structure. +## +## .. note:: This is equal to the number of all inserted objects if the data structure +## never has been pruned. Do not use after calling topk_merge_prune (will throw a +## warning message if used afterwards) +## +## handle: the TopK handle ## ## Returns: sum of all counts function topk_sum%(handle: opaque of topk%): count %{ assert(handle); probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; - return new Val(h->getSum(), TYPE_COUNT); + return new Val(h->GetSum(), TYPE_COUNT); %} -## Merge the second topk data structure into the first. Does not remove any elements, the -## resulting data structure can be bigger than the maximum size given on initialization. +## Merge the second topk data structure into the first. +## +## .. note:: This does not remove any elements, the resulting data structure can +## be bigger than the maximum size given on initialization. function topk_merge%(handle1: opaque of topk, handle2: opaque of topk%): any %{ assert(handle1); @@ -103,9 +133,15 @@ function topk_merge%(handle1: opaque of topk, handle2: opaque of topk%): any %} ## Merge the second topk data structure into the first and prunes the final data structure -## back to the size given on initialization. Use with care and only when being aware of the -## restrictions this imposed. Do not call topk_size or topk_add afterwards, results will -## probably not be what you expect. +## back to the size given on initialization. +## +## .. note:: Use with care and only when being aware of the restrictions this entails. +## Do not call topk_size or topk_add afterwards, results will probably not be what you +## expect. +## +## handle1: the TopK handle in which the second TopK structure is merged +## +## handle2: the TopK handle in which is merged into the first TopK structure function topk_merge_prune%(handle1: opaque of topk, handle2: opaque of topk%): any %{ assert(handle1); diff --git a/testing/btest/Baseline/bifs.topk/.stderr b/testing/btest/Baseline/bifs.topk/.stderr index 80626107aa..a711333fc0 100644 --- a/testing/btest/Baseline/bifs.topk/.stderr +++ b/testing/btest/Baseline/bifs.topk/.stderr @@ -1,11 +1,11 @@ -error: getCount for element that is not in top-k -error: getEpsilon for element that is not in top-k -error: getCount for element that is not in top-k -error: getEpsilon for element that is not in top-k -error: getCount for element that is not in top-k -error: getEpsilon for element that is not in top-k -error: getCount for element that is not in top-k -error: getEpsilon for element that is not in top-k -warning: TopkVal::getSum() was used on a pruned data structure. Result values do not represent total element count -error: getCount for element that is not in top-k -error: getEpsilon for element that is not in top-k +error: GetCount for element that is not in top-k +error: GetEpsilon for element that is not in top-k +error: GetCount for element that is not in top-k +error: GetEpsilon for element that is not in top-k +error: GetCount for element that is not in top-k +error: GetEpsilon for element that is not in top-k +error: GetCount for element that is not in top-k +error: GetEpsilon for element that is not in top-k +warning: TopkVal::GetSum() was used on a pruned data structure. Result values do not represent total element count +error: GetCount for element that is not in top-k +error: GetEpsilon for element that is not in top-k From 3c0be747595a4e6df146fc7aba0cc1d5359ba231 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 1 Aug 2013 14:13:20 -0700 Subject: [PATCH 179/881] 3 more functions to document. --- src/probabilistic/Topk.h | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/probabilistic/Topk.h b/src/probabilistic/Topk.h index 4f0599025d..48ca5c29a4 100644 --- a/src/probabilistic/Topk.h +++ b/src/probabilistic/Topk.h @@ -123,9 +123,30 @@ protected: TopkVal(); private: + /** + * Increment the counter for a specific element + * + * @param e element to increment counter for + * + * @param count increment counter by this much + */ void IncrementCounter(Element* e, unsigned int count = 1); - HashKey* GetHash(Val*) const; // this probably should go somewhere else. - void Typify(BroType*); + + /** + * get the hashkey for a specific value + * + * @param v value to generate key for + * + * @returns HashKey for value + */ + HashKey* GetHash(Val* v) const; // this probably should go somewhere else. + + /** + * Set the type that this TopK instance tracks + * + * @param t type that is tracked + */ + void Typify(BroType* t); BroType* type; CompositeHash* hash; From 8a9344e3ea3cc35a055b3b5686ba78f166718772 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 1 Aug 2013 15:41:10 -0700 Subject: [PATCH 180/881] Missing base line update. --- doc/scripts/DocSourcesList.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index fecd728afd..570de8bb6f 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -73,6 +73,7 @@ rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_UDP.events.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_ZIP.events.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/reporter.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/strings.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/top-k.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/types.bif.bro) rest_target(${psd} base/files/extract/main.bro) rest_target(${psd} base/files/hash/main.bro) @@ -129,6 +130,7 @@ rest_target(${psd} base/frameworks/sumstats/plugins/min.bro) rest_target(${psd} base/frameworks/sumstats/plugins/sample.bro) rest_target(${psd} base/frameworks/sumstats/plugins/std-dev.bro) rest_target(${psd} base/frameworks/sumstats/plugins/sum.bro) +rest_target(${psd} base/frameworks/sumstats/plugins/topk.bro) rest_target(${psd} base/frameworks/sumstats/plugins/unique.bro) rest_target(${psd} base/frameworks/sumstats/plugins/variance.bro) rest_target(${psd} base/frameworks/tunnels/main.bro) From 306d4fa6f9f480fb70b099c7d6440d70aac38952 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 1 Aug 2013 16:30:12 -0700 Subject: [PATCH 181/881] Pluginizing the DNP3 analyzer, plus a basic script logging requests and replies. Almost ready, but now 1 test fails again ... [Note I broke git history by copying over the files into a new branch.] --- scripts/base/init-default.bro | 1 + scripts/base/protocols/dnp3/__load__.bro | 3 + scripts/base/protocols/dnp3/consts.bro | 49 + scripts/base/protocols/dnp3/dpd.sig | 15 + scripts/base/protocols/dnp3/main.bro | 73 + src/analyzer/protocol/CMakeLists.txt | 1 + src/analyzer/protocol/dnp3/CMakeLists.txt | 10 + src/analyzer/protocol/dnp3/DNP3.cc | 375 +++++ src/analyzer/protocol/dnp3/DNP3.h | 56 + src/analyzer/protocol/dnp3/Plugin.cc | 10 + src/analyzer/protocol/dnp3/dnp3-analyzer.pac | 969 +++++++++++ src/analyzer/protocol/dnp3/dnp3-objects.pac | 1451 +++++++++++++++++ src/analyzer/protocol/dnp3/dnp3-protocol.pac | 257 +++ src/analyzer/protocol/dnp3/dnp3.pac | 16 + src/analyzer/protocol/dnp3/events.bif | 241 +++ .../coverage | 1 + .../dnp3.log | 10 + .../output | 7 + .../coverage | 1 + .../dnp3.log | 10 + .../output | 7 + .../coverage | 1 + .../dnp3.log | 10 + .../output | 9 + .../coverage | 1 + .../dnp3.log | 14 + .../output | 45 + .../coverage | 1 + .../dnp3.log | 12 + .../output | 29 + .../coverage | 1 + .../dnp3.log | 10 + .../output | 88 + .../coverage | 1 + .../dnp3.log | 10 + .../output | 4 + .../coverage | 1 + .../dnp3.log | 11 + .../output | 22 + .../coverage | 1 + .../dnp3.log | 10 + .../output | 6 + .../coverage | 1 + .../scripts.base.protocols.dnp3.events/output | 574 +++++++ testing/btest/Traces/dnp3/dnp3.trace | Bin 0 -> 18790 bytes .../btest/Traces/dnp3/dnp3_del_measure.pcap | Bin 0 -> 804 bytes testing/btest/Traces/dnp3/dnp3_en_spon.pcap | Bin 0 -> 807 bytes testing/btest/Traces/dnp3/dnp3_file_del.pcap | Bin 0 -> 920 bytes testing/btest/Traces/dnp3/dnp3_file_read.pcap | Bin 0 -> 3489 bytes .../btest/Traces/dnp3/dnp3_file_write.pcap | Bin 0 -> 2868 bytes testing/btest/Traces/dnp3/dnp3_read.pcap | Bin 0 -> 928 bytes .../btest/Traces/dnp3/dnp3_read_p20001.pcap | Bin 0 -> 928 bytes testing/btest/Traces/dnp3/dnp3_rec_time.pcap | Bin 0 -> 798 bytes .../Traces/dnp3/dnp3_select_operate.pcap | Bin 0 -> 1120 bytes testing/btest/Traces/dnp3/dnp3_write.pcap | Bin 0 -> 808 bytes .../base/protocols/dnp3/dnp3_del_measure.bro | 9 + .../base/protocols/dnp3/dnp3_en_spon.bro | 9 + .../base/protocols/dnp3/dnp3_file_del.bro | 9 + .../base/protocols/dnp3/dnp3_file_read.bro | 9 + .../base/protocols/dnp3/dnp3_file_write.bro | 9 + .../scripts/base/protocols/dnp3/dnp3_read.bro | 9 + .../base/protocols/dnp3/dnp3_rec_time.bro | 9 + .../protocols/dnp3/dnp3_select_operate.bro | 9 + .../base/protocols/dnp3/dnp3_write.bro | 9 + .../scripts/base/protocols/dnp3/events.bro | 266 +++ 65 files changed, 4772 insertions(+) create mode 100644 scripts/base/protocols/dnp3/__load__.bro create mode 100644 scripts/base/protocols/dnp3/consts.bro create mode 100644 scripts/base/protocols/dnp3/dpd.sig create mode 100644 scripts/base/protocols/dnp3/main.bro create mode 100644 src/analyzer/protocol/dnp3/CMakeLists.txt create mode 100644 src/analyzer/protocol/dnp3/DNP3.cc create mode 100644 src/analyzer/protocol/dnp3/DNP3.h create mode 100644 src/analyzer/protocol/dnp3/Plugin.cc create mode 100644 src/analyzer/protocol/dnp3/dnp3-analyzer.pac create mode 100644 src/analyzer/protocol/dnp3/dnp3-objects.pac create mode 100644 src/analyzer/protocol/dnp3/dnp3-protocol.pac create mode 100644 src/analyzer/protocol/dnp3/dnp3.pac create mode 100644 src/analyzer/protocol/dnp3/events.bif create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_write/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_write/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_write/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_read/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_read/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_read/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_rec_time/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_rec_time/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_rec_time/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_select_operate/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_select_operate/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_select_operate/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_write/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_write/dnp3.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_write/output create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.events/coverage create mode 100644 testing/btest/Baseline/scripts.base.protocols.dnp3.events/output create mode 100644 testing/btest/Traces/dnp3/dnp3.trace create mode 100644 testing/btest/Traces/dnp3/dnp3_del_measure.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_en_spon.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_file_del.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_file_read.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_file_write.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_read.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_read_p20001.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_rec_time.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_select_operate.pcap create mode 100644 testing/btest/Traces/dnp3/dnp3_write.pcap create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_del_measure.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_en_spon.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_file_del.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_file_read.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_file_write.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_read.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_rec_time.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_select_operate.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/dnp3_write.bro create mode 100644 testing/btest/scripts/base/protocols/dnp3/events.bro diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 6e348cfffd..749bd0a024 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -39,6 +39,7 @@ @load base/frameworks/tunnels @load base/protocols/conn +@load base/protocols/dnp3 @load base/protocols/dns @load base/protocols/ftp @load base/protocols/http diff --git a/scripts/base/protocols/dnp3/__load__.bro b/scripts/base/protocols/dnp3/__load__.bro new file mode 100644 index 0000000000..0f41578f8a --- /dev/null +++ b/scripts/base/protocols/dnp3/__load__.bro @@ -0,0 +1,3 @@ +@load ./main + +@load-sigs ./dpd.sig diff --git a/scripts/base/protocols/dnp3/consts.bro b/scripts/base/protocols/dnp3/consts.bro new file mode 100644 index 0000000000..1b2a6206ef --- /dev/null +++ b/scripts/base/protocols/dnp3/consts.bro @@ -0,0 +1,49 @@ + +module DNP3; + +export { + ## Standard defined Modbus function codes. + const function_codes = { + # Requests. + [0x00] = "CONFIRM", + [0x01] = "READ", + [0x02] = "WRITE", + [0x03] = "SELECT", + [0x04] = "OPERATE", + [0x05] = "DIRECT_OPERATE", + [0x06] = "DIRECT_OPERATE_NR", + [0x07] = "IMMED_FREEZE", + [0x08] = "IMMED_FREEZE_NR", + [0x09] = "FREEZE_CLEAR", + [0x0a] = "FREEZE_CLEAR_NR", + [0x0b] = "FREEZE_AT_TIME", + [0x0c] = "FREEZE_AT_TIME_NR", + [0x0d] = "COLD_RESTART", + [0x0e] = "WARM_RESTART", + [0x0f] = "INITIALIZE_DATA", + [0x10] = "INITIALIZE_APPL", + [0x11] = "START_APPL", + [0x12] = "STOP_APPL", + [0x13] = "SAVE_CONFIG", + [0x14] = "ENABLE_UNSOLICITED", + [0x15] = "DISABLE_UNSOLICITED", + [0x16] = "ASSIGN_CLASS", + [0x17] = "DELAY_MEASURE", + [0x18] = "RECORD_CURRENT_TIME", + [0x19] = "OPEN_FILE", + [0x1a] = "CLOSE_FILE", + [0x1b] = "DELETE_FILE", + [0x1c] = "GET_FILE_INFO", + [0x1d] = "AUTHENTICATE_FILE", + [0x1e] = "ABORT_FILE", + [0x1f] = "ACTIVATE_CONFIG", + [0x20] = "AUTHENTICATE_REQ", + [0x21] = "AUTHENTICATE_ERR", + + # Responses. + [0x81] = "RESPONSE", + [0x82] = "UNSOLICITED_RESPONSE", + [0x83] = "AUTHENTICATE_RESP", + } &default=function(i: count):string { return fmt("unknown-%d", i); } &redef; +} + diff --git a/scripts/base/protocols/dnp3/dpd.sig b/scripts/base/protocols/dnp3/dpd.sig new file mode 100644 index 0000000000..691c47d0a9 --- /dev/null +++ b/scripts/base/protocols/dnp3/dpd.sig @@ -0,0 +1,15 @@ + +signature dpd_dnp3_client { + ip-proto == tcp + # dnp3 packets always starts with 0x05 0x64 . + payload /\x05\0x64/ + tcp-state originator +} + +signature dpd_dnp3_server { + ip-proto == tcp + # dnp3 packets always starts with 0x05 0x64 . + payload /\x05\x64/ + tcp-state responder + enable "dnp3" +} diff --git a/scripts/base/protocols/dnp3/main.bro b/scripts/base/protocols/dnp3/main.bro new file mode 100644 index 0000000000..2b014bcc67 --- /dev/null +++ b/scripts/base/protocols/dnp3/main.bro @@ -0,0 +1,73 @@ +##! A very basic DNP3 analysis script that just logs requests and replies. + +module DNP3; + +@load ./consts + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + ## Time of the request. + ts: time &log; + ## Unique identifier for the connnection. + uid: string &log; + ## Identifier for the connection. + id: conn_id &log; + ## The name of the function message in the request. + fc_request: string &log &optional; + ## The name of the function message in the reply. + fc_reply: string &log &optional; + ## The response's "internal indication number". + iin: count &log &optional; + }; + + ## Event that can be handled to access the DNP3 record as it is sent on + ## to the logging framework. + global log_dnp3: event(rec: Info); +} + +redef record connection += { + dnp3: Info &optional; +}; + +const ports = { 502/tcp }; +redef likely_server_ports += { ports }; + +event bro_init() &priority=5 + { + Log::create_stream(DNP3::LOG, [$columns=Info, $ev=log_dnp3]); + Analyzer::register_for_ports(Analyzer::ANALYZER_DNP3, ports); + } + +event dnp3_application_request_header(c: connection, is_orig: bool, fc: count) + { + if ( ! c?$dnp3 ) + c$dnp3 = [$ts=network_time(), $uid=c$uid, $id=c$id]; + + c$dnp3$ts = network_time(); + c$dnp3$fc_request = function_codes[fc]; + } + +event dnp3_application_response_header(c: connection, is_orig: bool, fc: count, iin: count) + { + if ( ! c?$dnp3 ) + c$dnp3 = [$ts=network_time(), $uid=c$uid, $id=c$id]; + + c$dnp3$ts = network_time(); + c$dnp3$fc_reply = function_codes[fc]; + c$dnp3$iin = iin; + + Log::write(LOG, c$dnp3); + + delete c$dnp3; + } + +event connection_state_remove(c: connection) &priority=-5 + { + if ( ! c?$dnp3 ) + return; + + Log::write(LOG, c$dnp3); + delete c$dnp3; + } diff --git a/src/analyzer/protocol/CMakeLists.txt b/src/analyzer/protocol/CMakeLists.txt index a4e170f52b..fc63aa4b66 100644 --- a/src/analyzer/protocol/CMakeLists.txt +++ b/src/analyzer/protocol/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(bittorrent) add_subdirectory(conn-size) add_subdirectory(dce-rpc) add_subdirectory(dhcp) +add_subdirectory(dnp3) add_subdirectory(dns) add_subdirectory(file) add_subdirectory(finger) diff --git a/src/analyzer/protocol/dnp3/CMakeLists.txt b/src/analyzer/protocol/dnp3/CMakeLists.txt new file mode 100644 index 0000000000..b1c0f0b760 --- /dev/null +++ b/src/analyzer/protocol/dnp3/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro DNP3) +bro_plugin_cc(DNP3.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(dnp3.pac dnp3-analyzer.pac dnp3-protocol.pac dnp3-objects.pac) +bro_plugin_end() diff --git a/src/analyzer/protocol/dnp3/DNP3.cc b/src/analyzer/protocol/dnp3/DNP3.cc new file mode 100644 index 0000000000..ec0b02ba37 --- /dev/null +++ b/src/analyzer/protocol/dnp3/DNP3.cc @@ -0,0 +1,375 @@ +// +// DNP3 was initially used over serial links; it defined its own application +// layer, transport layer, and data link layer. This hierarchy cannot be +// mapped to the TCP/IP stack directly. As a result, all three DNP3 layers +// are packed together as a single application layer payload over the TCP +// layer. Each DNP3 packet in the application layer may look like this DNP3 +// Packet: +// +// DNP3 Link Layer | DNP3 Transport Layer | DNP3 Application Layer +// +// (This hierarchy can be viewed in the Wireshark visually.) +// +// === Background on DNP3 +// +// 1. Basic structure of DNP3 Protocol over serial links. This information +// can be found in detail in +// +// DNP3 Specification Volume 2, Part 1 Basic, Application Layer +// DNP3 Specification Volume 4, Data Link Layer +// +// Traditionally, the DNP3 Application Layer in serial links contains a +// "DNP3 Application Layer Fragment". The data that is parsed by the end +// device and then executed. As the "DNP3 Application Layer Fragment" can +// be long (>255 bytes), it may be trunkcated and carried in different +// DNP3 Application Layer of more than one DNP3 packets. +// +// So we may find a long DNP3 Application Layer Fragment to be transmitted in the following format +// +// DNP3 Packet #1 : DNP3 Link Layer | DNP3 Transport Layer | DNP3 Application Layer #1 +// DNP3 Packet #2 : DNP3 Link Layer | DNP3 Transport Layer | DNP3 Application Layer #2 +// .... +// DNP3 Packet #n : DNP3 Link Layer | DNP3 Transport Layer | DNP3 Application Layer #n +// +// So to get the whole DNP3 application layer fragment, we concatenate +// each DNP3 Application Layer Data into a logic DNP3 Application Layer +// Fragment: +// +// DNP3 Application Layer #1 + DNP3 Application Layer #2 + ... + DNP3 Application Layer #n +// +// 2. Packing DNP3 Network Packet into TCP/IP stack +// +// We will call the original DNP3 Link Layer, Transport Layer and Application +// Layer used in serial link as Pseudo Link Layer, Pseudo Transport Layer and +// Pseudo Application Layer. +// +// For a long DNP3 application layer fragment, we may find it tramistted +// over IP network in the following format: +// +// Network Packet #1 : TCP Header | DNP3 Pseudo Link Layer | DNP3 Pseudo Transport Layer | DNP3 Pseudo Application Layer #1 +// Network Packet #2 : TCP Header | DNP3 Pseudo Link Layer | DNP3 Pseudo Transport Layer | DNP3 Pseudo Application Layer #2 +// .... +// Network Packet #n : TCP Header | DNP3 Pseudo Link Layer | DNP3 Pseudo Transport Layer | DNP3 Pseudo Application Layer #n +// +// === Challenges of Writing DNP3 Analyzer on Binpac === +// +// The detailed structure of the DNP3 Link Layer is: +// +// 0x05 0x64 Len Ctrl Dest_LSB Dest_MSB Src_LSB Src_MSB CRC_LSB CRC_MSB +// +// Each field is a byte; LSB: least significant byte; MSB: most significatn byte. +// +// "Len" indicates the length of the byte stream right after this field +// (excluding CRC fields) in the current DNP3 packet. +// +// Since "Len" is of size one byte, the largest length it can represent is +// 255 bytes. The larget DNP3 Application Layer size is "255 - 5 + size of +// all CRC fields". "minus 5" is coming from the 5 bytes after "Len" field in +// the DNP3 Link Layer, i.e. Ctrl Dest_LSB Dest_MSB Src_LSB Src_MSB Hence, +// the largest size of a DNP3 Packet (DNP3 Data Link Layer : DNP3 Transport +// Layer : DNP3 Application Layer) can only be 292 bytes. +// +// The "Len" field indicates the length of of a single chunk of DNP3 Psuedo +// Application Layer data instead of the whole DNP3 Application Layer +// Fragment. However, we can not know the whole length of the DNP3 +// Application Layer Fragment (which Binpac would normally need) until all +// chunks of Pseudo Application Layer Data are received. +// +// We hence exploit the internal flow_buffer class used in Binpac to buffer +// the application layer data until all chunk are received. The trick that I +// used require in-depth understanding on how Binpac parse the application +// layer data and perform incremental parsing. The codes that exploits +// flow_buffer class to buffer the application layer data is included in +// DNP3_ProcessData class. +// +// The binpac analyzer parses the DNP3 Application Layer Fragment. However, +// we manually add the original Pseudo Link Layer data as an additional +// header before the DNP3 Application Fragment. This helps to know how many +// bytes are in the current chunk of DNP3 application layer data (not the +// whole Application Layer Fragment). +// +// Graphically, the procedure is: +// +// DNP3 Packet : DNP3 Pseudo Data Link Layer : DNP3 Pseudo Transport Layer : DNP3 Pseudo Application Layer +// || || +// || (length field) || (original paylad byte stream) +// \/ \/ +// DNP3 Additional Header : Reassembled DNP3 Pseudo Application Layer Data +// || +// \/ +// Binpac DNP3 Analyzer + +#include "DNP3.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" +#include "events.bif.h" + +using namespace analyzer::dnp3; + +const unsigned int PSEUDO_LENGTH_INDEX = 2; // index of len field of DNP3 Pseudo Link Layer +const unsigned int PSEUDO_CONTROL_FIELD_INDEX = 3; // index of ctrl field of DNP3 Pseudo Link Layer +const unsigned int PSEUDO_TRANSPORT_INDEX = 10; // index of DNP3 Pseudo Transport Layer +const unsigned int PSEUDO_APP_LAYER_INDEX = 11; // index of first DNP3 app-layer byte. +const unsigned int PSEUDO_TRANSPORT_LEN = 1; // length of DNP3 Transport Layer +const unsigned int PSEUDO_LINK_LAYER_LEN = 8; // length of DNP3 Pseudo Link Layer + +bool DNP3_Analyzer::crc_table_initialized = false; +unsigned int DNP3_Analyzer::crc_table[256]; + +DNP3_Analyzer::DNP3_Analyzer(Connection* c) : TCP_ApplicationAnalyzer("DNP3", c) + { + interp = new binpac::DNP3::DNP3_Conn(this); + + ClearEndpointState(true); + ClearEndpointState(false); + + if ( ! crc_table_initialized ) + PrecomputeCRCTable(); + } + +DNP3_Analyzer::~DNP3_Analyzer() + { + delete interp; + } + +void DNP3_Analyzer::Done() + { + TCP_ApplicationAnalyzer::Done(); + + interp->FlowEOF(true); + interp->FlowEOF(false); + } + +void DNP3_Analyzer::DeliverStream(int len, const u_char* data, bool orig) + { + TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + + try + { + if ( ! ProcessData(len, data, orig) ) + SetSkip(1); + } + + catch ( const binpac::Exception& e ) + { + SetSkip(1); + throw; + } + + } + +void DNP3_Analyzer::Undelivered(int seq, int len, bool orig) + { + TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); + interp->NewGap(orig, len); + } + +void DNP3_Analyzer::EndpointEOF(tcp::TCP_Reassembler* endp) + { + TCP_ApplicationAnalyzer::EndpointEOF(endp); + interp->FlowEOF(endp->IsOrig()); + } + +bool DNP3_Analyzer::ProcessData(int len, const u_char* data, bool orig) + { + Endpoint* endp = orig ? &orig_state : &resp_state; + + while ( len ) + { + if ( endp->in_hdr ) + { + // We're parsing the DNP3 header and link layer, get that in full. + if ( ! AddToBuffer(endp, PSEUDO_APP_LAYER_INDEX, &data, &len) ) + return true; + + // The first two bytes must always be 0x0564. + if( endp->buffer[0] != 0x05 || endp->buffer[1] != 0x64 ) + { + Weird("dnp3_header_lacks_magic"); + return false; + } + + // Make sure header checksum is correct. + if ( ! CheckCRC(PSEUDO_LINK_LAYER_LEN, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN, "header") ) + { + ProtocolViolation("broken_checksum"); + return false; + } + + // If the checksum works out, we're pretty certainly DNP3. + ProtocolConfirmation(); + + // Double check the direction in case the first + // received packet is a response. + u_char ctrl = endp->buffer[PSEUDO_CONTROL_FIELD_INDEX]; + + if ( orig != (bool)(ctrl & 0x80) ) + Weird("dnp3_unexpected_flow_direction"); + + // Update state. + endp->pkt_length = endp->buffer[PSEUDO_LENGTH_INDEX]; + endp->tpflags = endp->buffer[PSEUDO_TRANSPORT_INDEX]; + endp->in_hdr = false; // Now parsing application layer. + + // For the first packet, we submit the header to + // BinPAC. + if ( ++endp->pkt_cnt == 1 ) + interp->NewData(orig, endp->buffer, endp->buffer + PSEUDO_LINK_LAYER_LEN); + + } + + if ( ! endp->in_hdr ) + { + assert(endp->pkt_length); + + // We're parsing the DNP3 application layer, get that + // in full now as well. We calculate the number of + // raw bytes the application layer consists of from + // the packet length by determining how much 16-byte + // chunks fit in there, and then add 2 bytes CRC for + // each. + int n = PSEUDO_APP_LAYER_INDEX + (endp->pkt_length - 5) + ((endp->pkt_length - 5) / 16) * 2 + 2 - 1; + + if ( ! AddToBuffer(endp, n, &data, &len) ) + return true; + + // Parse the the application layer data. + if ( ! ParseAppLayer(endp) ) + return false; + + // Done with this packet, prepare for next. + endp->buffer_len = 0; + endp->in_hdr = true; + } + } + + return true; + } + +bool DNP3_Analyzer::AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len) + { + if ( ! target_len ) + return true; + + int to_copy = min(*len, target_len - endp->buffer_len); + + memcpy(endp->buffer + endp->buffer_len, *data, to_copy); + *data += to_copy; + *len -= to_copy; + endp->buffer_len += to_copy; + + return endp->buffer_len == target_len; + } + +bool DNP3_Analyzer::ParseAppLayer(Endpoint* endp) + { + bool orig = (endp == &orig_state); + binpac::DNP3::DNP3_Flow* flow = orig ? interp->upflow() : interp->downflow(); + + u_char* data = endp->buffer + PSEUDO_TRANSPORT_INDEX; // The transport layer byte counts as app-layer it seems. + int len = endp->pkt_length - 5; + + //// DNP3 Packet : DNP3 Pseudo Link Layer | DNP3 Pseudo Transport Layer | DNP3 Pseudo Application Layer + //// DNP3 Serial Transport Layer data is always 1 byte. + //// Get FIN FIR seq field in transport header + //// FIR indicate whether the following DNP3 Serial Application Layer is first chunk of bytes or not + //// FIN indicate whether the following DNP3 Serial Application Layer is last chunk of bytes or not + + //// Get FIR and FIN field from the DNP3 Pseudo Transport Layer + + int is_first = (endp->tpflags & 0x40) >> 6; // Initial chunk of data in this packet. + int is_last = (endp->tpflags & 0x80) >> 7; // Last chunk of data in this packet. + + int transport = PSEUDO_TRANSPORT_LEN; + + int i = 0; + while ( len > 0 ) + { + int n = min(len, 16); + + // Make sure chunk has a correct checksum. + if ( ! CheckCRC(n, data, data + n, "app_chunk") ) + return false; + + // Pass on to BinPAC. + assert(data + n < endp->buffer + endp->buffer_len); + flow->flow_buffer()->BufferData(data + transport, data + n); + transport = 0; + + data += n + 2; + len -= n; + } + + if ( is_first ) + endp->encountered_first_chunk = true; + + if ( ! is_first && ! endp->encountered_first_chunk ) + { + // We lost the first chunk. + Weird("dnp3_first_application_layer_chunk_missing"); + return false; + } + + if ( is_last ) + { + flow->flow_buffer()->FinishBuffer(); + flow->FlowEOF(); + ClearEndpointState(orig); + } + + return true; + } + +void DNP3_Analyzer::ClearEndpointState(bool orig) + { + Endpoint* endp = orig ? &orig_state : &resp_state; + binpac::DNP3::DNP3_Flow* flow = orig ? interp->upflow() : interp->downflow(); + + endp->in_hdr = true; + endp->encountered_first_chunk = false; + endp->buffer_len = 0; + endp->pkt_length = 0; + endp->tpflags = 0; + endp->pkt_cnt = 0; + } + +bool DNP3_Analyzer::CheckCRC(int len, const u_char* data, const u_char* crc16, const char* where) + { + unsigned int crc = CalcCRC(len, data); + + if ( crc16[0] == (crc & 0xff) && crc16[1] == (crc & 0xff00) >> 8 ) + return true; + + Weird(fmt("dnp3_corrupt_%s_checksum", where)); + return false; + } + +void DNP3_Analyzer::PrecomputeCRCTable() + { + for( unsigned int i = 0; i < 256; i++) + { + unsigned int crc = i; + + for ( unsigned int j = 0; j < 8; ++j ) + { + if ( crc & 0x0001 ) + crc = (crc >> 1) ^ 0xA6BC; // Generating polynomial. + else + crc >>= 1; + } + + crc_table[i] = crc; + } + } + +unsigned int DNP3_Analyzer::CalcCRC(int len, const u_char* data) + { + unsigned int crc = 0x0000; + + for ( int i = 0; i < len; i++ ) + { + unsigned int index = (crc ^ data[i]) & 0xFF; + crc = crc_table[index] ^ (crc >> 8); + } + + return ~crc & 0xFFFF; + } diff --git a/src/analyzer/protocol/dnp3/DNP3.h b/src/analyzer/protocol/dnp3/DNP3.h new file mode 100644 index 0000000000..d758c2e35a --- /dev/null +++ b/src/analyzer/protocol/dnp3/DNP3.h @@ -0,0 +1,56 @@ +#ifndef ANALYZER_PROTOCOL_DNP3_DNP3_H +#define ANALYZER_PROTOCOL_DNP3_DNP3_H + +#include "analyzer/protocol/tcp/TCP.h" +#include "dnp3_pac.h" + +namespace analyzer { namespace dnp3 { + +class DNP3_Analyzer : public tcp::TCP_ApplicationAnalyzer { +public: + DNP3_Analyzer(Connection* conn); + virtual ~DNP3_Analyzer(); + + virtual void Done(); + virtual void DeliverStream(int len, const u_char* data, bool orig); + virtual void Undelivered(int seq, int len, bool orig); + virtual void EndpointEOF(tcp::TCP_Reassembler* endp); + + static Analyzer* InstantiateAnalyzer(Connection* conn) + { return new DNP3_Analyzer(conn); } + +private: + static const int MAX_BUFFER_SIZE = 300; + + struct Endpoint + { + u_char buffer[MAX_BUFFER_SIZE]; + int buffer_len; + bool in_hdr; + int tpflags; + int pkt_length; + int pkt_cnt; + bool encountered_first_chunk; + }; + + bool ProcessData(int len, const u_char* data, bool orig); + void ClearEndpointState(bool orig); + bool AddToBuffer(Endpoint* endp, int target_len, const u_char** data, int* len); + bool ParseAppLayer(Endpoint* endp); + bool CheckCRC(int len, const u_char* data, const u_char* crc16, const char* where); + unsigned int CalcCRC(int len, const u_char* data); + + binpac::DNP3::DNP3_Conn* interp; + + Endpoint orig_state; + Endpoint resp_state; + + static void PrecomputeCRCTable(); + + static bool crc_table_initialized; + static unsigned int crc_table[256]; +}; + +} } // namespace analyzer::* + +#endif diff --git a/src/analyzer/protocol/dnp3/Plugin.cc b/src/analyzer/protocol/dnp3/Plugin.cc new file mode 100644 index 0000000000..d86413b388 --- /dev/null +++ b/src/analyzer/protocol/dnp3/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "DNP3.h" + +BRO_PLUGIN_BEGIN(Bro, DNP3) + BRO_PLUGIN_DESCRIPTION("DNP3 analyzer"); + BRO_PLUGIN_ANALYZER("DNP3", dnp3::DNP3_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/dnp3/dnp3-analyzer.pac b/src/analyzer/protocol/dnp3/dnp3-analyzer.pac new file mode 100644 index 0000000000..2ae783c82e --- /dev/null +++ b/src/analyzer/protocol/dnp3/dnp3-analyzer.pac @@ -0,0 +1,969 @@ + +connection DNP3_Conn(bro_analyzer: BroAnalyzer) { + upflow = DNP3_Flow(true); + downflow = DNP3_Flow(false); +}; + +flow DNP3_Flow(is_orig: bool) { + flowunit = DNP3_PDU(is_orig) withcontext (connection, this); + + function get_dnp3_header_block(start: uint16, len: uint16, ctrl: uint8, dest_addr: uint16, src_addr: uint16): bool + %{ + if ( ::dnp3_header_block ) + { + BifEvent::generate_dnp3_header_block( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), start, len, ctrl, dest_addr, src_addr); + } + + return true; + %} + + function get_dnp3_application_request_header(fc: uint8): bool + %{ + if ( ::dnp3_application_request_header ) + { + BifEvent::generate_dnp3_application_request_header( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), + fc + ); + } + return true; + %} + + function get_dnp3_application_response_header(fc: uint8, iin: uint16): bool + %{ + if ( ::dnp3_application_response_header ) + { + BifEvent::generate_dnp3_application_response_header( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), + fc, + iin + ); + } + return true; + %} + + function get_dnp3_object_header(obj_type: uint16, qua_field: uint8, number: uint32, rf_low: uint32, rf_high: uint32 ): bool + %{ + if ( ::dnp3_object_header ) + { + BifEvent::generate_dnp3_object_header( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), obj_type, qua_field, number, rf_low, rf_high); + } + + return true; + %} + + function get_dnp3_object_prefix(prefix_value: uint32): bool + %{ + if ( ::dnp3_object_prefix ) + { + BifEvent::generate_dnp3_object_prefix( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), prefix_value); + } + + return true; + %} + + function get_dnp3_response_data_object(data_value: uint8): bool + %{ + if ( ::dnp3_response_data_object ) + { + BifEvent::generate_dnp3_response_data_object( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), data_value); + } + + return true; + %} + + #g0 + function get_dnp3_attribute_common(data_type_code: uint8, leng: uint8, attribute_obj: const_bytestring): bool + %{ + if ( ::dnp3_attribute_common ) + { + BifEvent::generate_dnp3_attribute_common( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), data_type_code, leng, bytestring_to_val(attribute_obj) ); + } + + return true; + %} + + #g12v1 + function get_dnp3_crob(control_code: uint8, count8: uint8, on_time: uint32, off_time: uint32, status_code: uint8): bool + %{ + if ( ::dnp3_crob ) + { + BifEvent::generate_dnp3_crob( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), control_code, count8, on_time, off_time, status_code); + } + + return true; + %} + + #g12v2 + function get_dnp3_pcb(control_code: uint8, count8: uint8, on_time: uint32, off_time: uint32, status_code: uint8): bool + %{ + if ( ::dnp3_pcb ) + { + BifEvent::generate_dnp3_pcb( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), control_code, count8, on_time, off_time, status_code); + } + + return true; + %} + + # g20v1 + function get_dnp3_counter_32wFlag(flag: uint8, count_value: uint32): bool + %{ + if ( ::dnp3_counter_32wFlag ) + { + BifEvent::generate_dnp3_counter_32wFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, count_value); + } + + return true; + %} + + # g20v2 + function get_dnp3_counter_16wFlag(flag: uint8, count_value: uint16): bool + %{ + if ( ::dnp3_counter_16wFlag ) + { + BifEvent::generate_dnp3_counter_16wFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, count_value); + } + + return true; + %} + + # g20v5 + function get_dnp3_counter_32woFlag(count_value: uint32): bool + %{ + if ( ::dnp3_counter_32woFlag ) + { + BifEvent::generate_dnp3_counter_32woFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), count_value); + } + + return true; + %} + + # g20v6 + function get_dnp3_counter_16woFlag(count_value: uint16): bool + %{ + if ( ::dnp3_counter_16woFlag ) + { + BifEvent::generate_dnp3_counter_16woFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), count_value); + } + + return true; + %} + + # g21v1 + function get_dnp3_frozen_counter_32wFlag(flag: uint8, count_value: uint32): bool + %{ + if ( ::dnp3_frozen_counter_32wFlag ) + { + BifEvent::generate_dnp3_frozen_counter_32wFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, count_value); + } + + return true; + %} + + # g21v2 + function get_dnp3_frozen_counter_16wFlag(flag: uint8, count_value: uint16): bool + %{ + if ( ::dnp3_frozen_counter_16wFlag ) + { + BifEvent::generate_dnp3_frozen_counter_16wFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, count_value); + } + + return true; + %} + + # g21v5 + function get_dnp3_frozen_counter_32wFlagTime(flag: uint8, count_value: uint32, time48: const_bytestring): bool + %{ + if ( ::dnp3_frozen_counter_32wFlagTime ) + { + BifEvent::generate_dnp3_frozen_counter_32wFlagTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, count_value, bytestring_to_val(time48)); + } + + return true; + %} + + # g21v6 + function get_dnp3_frozen_counter_16wFlagTime(flag: uint8, count_value: uint16, time48: const_bytestring): bool + %{ + if ( ::dnp3_frozen_counter_16wFlagTime ) + { + BifEvent::generate_dnp3_frozen_counter_16wFlagTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, count_value, bytestring_to_val(time48)); + } + + return true; + %} + + # g21v9 + function get_dnp3_frozen_counter_32woFlag(count_value: uint32): bool + %{ + if ( ::dnp3_frozen_counter_32woFlag ) + { + BifEvent::generate_dnp3_frozen_counter_32woFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), count_value); + } + + return true; + %} + + # g21v10 + function get_dnp3_frozen_counter_16woFlag(count_value: uint16): bool + %{ + if ( ::dnp3_frozen_counter_16woFlag ) + { + BifEvent::generate_dnp3_frozen_counter_16woFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), count_value); + } + + return true; + %} + + # g30v1 + function get_dnp3_analog_input_32wFlag(flag: uint8, value: int32): bool + %{ + if ( ::dnp3_analog_input_32wFlag ) + { + BifEvent::generate_dnp3_analog_input_32wFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value); + } + + return true; + %} + + # g30v2 + function get_dnp3_analog_input_16wFlag(flag: uint8, value: int16): bool + %{ + if ( ::dnp3_analog_input_16wFlag ) + { + BifEvent::generate_dnp3_analog_input_16wFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value); + } + + return true; + %} + + # g30v3 + function get_dnp3_analog_input_32woFlag(value: int32): bool + %{ + if ( ::dnp3_analog_input_32woFlag ) + { + BifEvent::generate_dnp3_analog_input_32woFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), value); + } + + return true; + %} + + #g30v4 + function get_dnp3_analog_input_16woFlag(value: int16): bool + %{ + if ( ::dnp3_analog_input_16woFlag ) + { + BifEvent::generate_dnp3_analog_input_16woFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), value); + } + + return true; + %} + + # g30v5 + function get_dnp3_analog_input_SPwFlag(flag: uint8, value: uint32): bool + %{ + if ( ::dnp3_analog_input_SPwFlag ) + { + BifEvent::generate_dnp3_analog_input_SPwFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value); + } + + return true; + %} + + # g30v6 + function get_dnp3_analog_input_DPwFlag(flag: uint8, value_low: uint32, value_high: uint32): bool + %{ + if ( ::dnp3_analog_input_DPwFlag ) + { + BifEvent::generate_dnp3_analog_input_DPwFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value_low, value_high); + } + + return true; + %} + + # g31v1 + function get_dnp3_frozen_analog_input_32wFlag(flag: uint8, frozen_value: int32): bool + %{ + if ( ::dnp3_frozen_analog_input_32wFlag ) + { + BifEvent::generate_dnp3_frozen_analog_input_32wFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value); + } + + return true; + %} + + # g31v2 + function get_dnp3_frozen_analog_input_16wFlag(flag: uint8, frozen_value: int16): bool + %{ + if ( ::dnp3_frozen_analog_input_16wFlag ) + { + BifEvent::generate_dnp3_frozen_analog_input_16wFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value); + } + + return true; + %} + + # g31v3 + function get_dnp3_frozen_analog_input_32wTime(flag: uint8, frozen_value: int32, time48: const_bytestring): bool + %{ + if ( ::dnp3_frozen_analog_input_32wTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_32wTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value, bytestring_to_val(time48)); + } + + return true; + %} + + # g31v4 + function get_dnp3_frozen_analog_input_16wTime(flag: uint8, frozen_value: int16, time48: const_bytestring): bool + %{ + if ( ::dnp3_frozen_analog_input_16wTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_16wTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value, bytestring_to_val(time48)); + } + + return true; + %} + + # g31v5 + function get_dnp3_frozen_analog_input_32woFlag(frozen_value: int32): bool + %{ + if ( ::dnp3_frozen_analog_input_32woFlag ) + { + BifEvent::generate_dnp3_frozen_analog_input_32woFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), frozen_value); + } + + return true; + %} + + # g31v6 + function get_dnp3_frozen_analog_input_16woFlag(frozen_value: int16): bool + %{ + if ( ::dnp3_frozen_analog_input_16woFlag ) + { + BifEvent::generate_dnp3_frozen_analog_input_16woFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), frozen_value); + } + + return true; + %} + + # g31v7 + function get_dnp3_frozen_analog_input_SPwFlag(flag: uint8, frozen_value: uint32): bool + %{ + if ( ::dnp3_frozen_analog_input_SPwFlag ) + { + BifEvent::generate_dnp3_frozen_analog_input_SPwFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value); + } + + return true; + %} + + # g31v8 + function get_dnp3_frozen_analog_input_DPwFlag(flag: uint8, frozen_value_low: uint32, frozen_value_high: uint32): bool + %{ + if ( ::dnp3_frozen_analog_input_DPwFlag ) + { + BifEvent::generate_dnp3_frozen_analog_input_DPwFlag( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value_low, frozen_value_high); + } + + return true; + %} + + # g32v1 + function get_dnp3_analog_input_event_32woTime(flag: uint8, value: int32): bool + %{ + if ( ::dnp3_analog_input_event_32woTime ) + { + BifEvent::generate_dnp3_analog_input_event_32woTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value); + } + + return true; + %} + + # g32v2 + function get_dnp3_analog_input_event_16woTime(flag: uint8, value: int16): bool + %{ + if ( ::dnp3_analog_input_event_16woTime ) + { + BifEvent::generate_dnp3_analog_input_event_16woTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value); + } + + return true; + %} + + # g32v3 + function get_dnp3_analog_input_event_32wTime(flag: uint8, value: int32, time48: const_bytestring): bool + %{ + if ( ::dnp3_analog_input_event_32wTime ) + { + BifEvent::generate_dnp3_analog_input_event_32wTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value, bytestring_to_val(time48)); + } + + return true; + %} + + # g32v4 + function get_dnp3_analog_input_event_16wTime(flag: uint8, value: int16, time48: const_bytestring): bool + %{ + if ( ::dnp3_analog_input_event_16wTime ) + { + BifEvent::generate_dnp3_analog_input_event_16wTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value, bytestring_to_val(time48)); + } + + return true; + %} + + # g32v5 + function get_dnp3_analog_input_event_SPwoTime(flag: uint8, value: uint32): bool + %{ + if ( ::dnp3_analog_input_event_SPwoTime ) + { + BifEvent::generate_dnp3_analog_input_event_SPwoTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value); + } + + return true; + %} + + # g32v6 + function get_dnp3_analog_input_event_DPwoTime(flag: uint8, value_low: uint32, value_high: uint32): bool + %{ + if ( ::dnp3_analog_input_event_DPwoTime ) + { + BifEvent::generate_dnp3_analog_input_event_DPwoTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value_low, value_high); + } + + return true; + %} + + # g32v7 + function get_dnp3_analog_input_event_SPwTime(flag: uint8, value: uint32, time48: const_bytestring): bool + %{ + if ( ::dnp3_analog_input_event_SPwTime ) + { + BifEvent::generate_dnp3_analog_input_event_SPwTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value, bytestring_to_val(time48)); + } + + return true; + %} + + # g32v8 + function get_dnp3_analog_input_event_DPwTime(flag: uint8, value_low: uint32, value_high: uint32, time48: const_bytestring): bool + %{ + if ( ::dnp3_analog_input_event_DPwTime ) + { + BifEvent::generate_dnp3_analog_input_event_DPwTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, value_low, value_high, bytestring_to_val(time48)); + } + + return true; + %} + + # g33v1 + function get_dnp3_frozen_analog_input_event_32woTime(flag: uint8, frozen_value: int32): bool + %{ + if ( ::dnp3_frozen_analog_input_event_32woTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_event_32woTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value); + } + + return true; + %} + + # g33v2 + function get_dnp3_frozen_analog_input_event_16woTime(flag: uint8, frozen_value: int16): bool + %{ + if ( ::dnp3_frozen_analog_input_event_16woTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_event_16woTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value); + } + + return true; + %} + + # g33v3 + function get_dnp3_frozen_analog_input_event_32wTime(flag: uint8, frozen_value: int32, time48: const_bytestring): bool + %{ + if ( ::dnp3_frozen_analog_input_event_32wTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_event_32wTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value, bytestring_to_val(time48)); + } + + return true; + %} + + # g33v4 + function get_dnp3_frozen_analog_input_event_16wTime(flag: uint8, frozen_value: int16, time48: const_bytestring): bool + %{ + if ( ::dnp3_frozen_analog_input_event_16wTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_event_16wTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value, bytestring_to_val(time48)); + } + + return true; + %} + + # g33v5 + function get_dnp3_frozen_analog_input_event_SPwoTime(flag: uint8, frozen_value: uint32): bool + %{ + if ( ::dnp3_frozen_analog_input_event_SPwoTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_event_SPwoTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value); + } + + return true; + %} + + # g33v6 + function get_dnp3_frozen_analog_input_event_DPwoTime(flag: uint8, frozen_value_low: uint32, frozen_value_high: uint32): bool + %{ + if ( ::dnp3_frozen_analog_input_event_DPwoTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_event_DPwoTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value_low, frozen_value_high); + } + + return true; + %} + + # g33v7 + function get_dnp3_frozen_analog_input_event_SPwTime(flag: uint8, frozen_value: uint32, time48: const_bytestring): bool + %{ + if ( ::dnp3_frozen_analog_input_event_SPwTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_event_SPwTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value, bytestring_to_val(time48)); + } + + return true; + %} + + # g33v8 + function get_dnp3_frozen_analog_input_event_DPwTime(flag: uint8, frozen_value_low: uint32, frozen_value_high: uint32, time48: const_bytestring): bool + %{ + if ( ::dnp3_frozen_analog_input_event_DPwTime ) + { + BifEvent::generate_dnp3_frozen_analog_input_event_DPwTime( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), flag, frozen_value_low, frozen_value_high, bytestring_to_val(time48)); + } + + return true; + %} + + # g70v5 + function get_dnp3_file_transport(file_handle: uint32, block_num: uint32, file_data: const_bytestring): bool + %{ + if ( ::dnp3_file_transport ) + { + BifEvent::generate_dnp3_file_transport( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), file_handle, block_num, bytestring_to_val(file_data)); + } + + return true; + %} + +#### for debug use or unknown data types used in "case" + function get_dnp3_debug_byte(debug: const_bytestring): bool + %{ + if ( ::dnp3_debug_byte ) + { + BifEvent::generate_dnp3_debug_byte ( + connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + is_orig(), bytestring_to_val(debug)); + } + + return true; + %} + +}; + +refine typeattr Header_Block += &let { + get_header: bool = $context.flow.get_dnp3_header_block(start, len, ctrl, dest_addr, src_addr); +}; + +refine typeattr DNP3_Application_Request_Header += &let { + process_request: bool = $context.flow.get_dnp3_application_request_header(function_code); +}; + +refine typeattr DNP3_Application_Response_Header += &let { + process_request: bool = $context.flow.get_dnp3_application_response_header(function_code, internal_indications); +}; + +refine typeattr Object_Header += &let { + process_request: bool = $context.flow.get_dnp3_object_header(object_type_field, qualifier_field, number_of_item, rf_value_low, rf_value_high); +}; + +refine typeattr Prefix_Type += &let { + prefix_called: bool = $context.flow.get_dnp3_object_prefix(prefix_value); +}; + +refine typeattr Response_Data_Object += &let { + process_request: bool = $context.flow.get_dnp3_response_data_object(data_value); +}; + +# g0 +refine typeattr AttributeCommon += &let { + process_request: bool = $context.flow.get_dnp3_attribute_common(data_type_code, leng, attribute_obj); +}; + +# g12v1 +refine typeattr CROB += &let { + process_request: bool = $context.flow.get_dnp3_crob(control_code, count, on_time, off_time, status_code); +}; + +# g12v2 +refine typeattr PCB += &let { + process_request: bool = $context.flow.get_dnp3_pcb(control_code, count, on_time, off_time, status_code); +}; + +# g20v1 +refine typeattr Counter32wFlag += &let { + process_request: bool = $context.flow.get_dnp3_counter_32wFlag(flag, count_value); +}; + +# g20v2 +refine typeattr Counter16wFlag += &let { + process_request: bool = $context.flow.get_dnp3_counter_16wFlag(flag, count_value); +}; + +# g20v5 +refine typeattr Counter32woFlag += &let { + process_request: bool = $context.flow.get_dnp3_counter_32woFlag(count_value); +}; + +# g20v6 +refine typeattr Counter16woFlag += &let { + process_request: bool = $context.flow.get_dnp3_counter_16woFlag(count_value); +}; + +# g21v1 +refine typeattr FrozenCounter32wFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_counter_32wFlag(flag, count_value); +}; + +# g21v2 +refine typeattr FrozenCounter16wFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_counter_16wFlag(flag, count_value); +}; +# g21v5 +refine typeattr FrozenCounter32wFlagTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_counter_32wFlagTime(flag, count_value, time48); +}; + +# g21v6 +refine typeattr FrozenCounter16wFlagTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_counter_16wFlagTime(flag, count_value, time48); +}; + +# g21v9 +refine typeattr FrozenCounter32woFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_counter_32woFlag(count_value); +}; + +# g21v10 +refine typeattr FrozenCounter16woFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_counter_16woFlag(count_value); +}; + +# g30v1 +refine typeattr AnalogInput32wFlag += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_32wFlag(flag, value); +}; + +# g30v2 +refine typeattr AnalogInput16wFlag += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_16wFlag(flag, value); +}; + +# g30v3 +refine typeattr AnalogInput32woFlag += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_32woFlag(value); +}; + +# g30v4 +refine typeattr AnalogInput16woFlag += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_16woFlag(value); +}; + +# g30v5 +refine typeattr AnalogInputSPwFlag += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_SPwFlag(flag, value); +}; + +# g30v6 +refine typeattr AnalogInputDPwFlag += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_DPwFlag(flag, value_low, value_high); +}; + +# g31v1 +refine typeattr FrozenAnalogInput32wFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_32wFlag(flag, frozen_value); +}; + +# g31v2 +refine typeattr FrozenAnalogInput16wFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_16wFlag(flag, frozen_value); +}; + +# g31v3 +refine typeattr FrozenAnalogInput32wTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_32wTime(flag, frozen_value, time48); +}; + +# g31v4 +refine typeattr FrozenAnalogInput16wTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_16wTime(flag, frozen_value, time48); +}; + +# g31v5 +refine typeattr FrozenAnalogInput32woFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_32woFlag(frozen_value); +}; + +# g31v6 +refine typeattr FrozenAnalogInput16woFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_16woFlag(frozen_value); +}; + +# g31v7 +refine typeattr FrozenAnalogInputSPwFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_SPwFlag(flag, frozen_value); +}; + +# g31v8 +refine typeattr FrozenAnalogInputDPwFlag += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_DPwFlag(flag, frozen_value_low, frozen_value_high); +}; + +# g32v1 +refine typeattr AnalogInput32woTime += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_event_32woTime(flag, value); +}; + +# g32v2 +refine typeattr AnalogInput16woTime += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_event_16woTime(flag, value); +}; + +# g32v3 +refine typeattr AnalogInput32wTime += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_event_32wTime(flag, value, time48); +}; + +# g32v4 +refine typeattr AnalogInput16wTime += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_event_16wTime(flag, value, time48); +}; + +# g32v5 +refine typeattr AnalogInputSPwoTime += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_event_SPwoTime(flag, value); +}; + +# g32v6 +refine typeattr AnalogInputDPwoTime += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_event_DPwoTime(flag, value_low, value_high); +}; + +# g32v7 +refine typeattr AnalogInputSPwTime += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_event_SPwTime(flag, value, time48); +}; + +# g32v8 +refine typeattr AnalogInputDPwTime += &let { + process_request: bool = $context.flow.get_dnp3_analog_input_event_DPwTime(flag, value_low, value_high, time48); +}; + +# g33v1 +refine typeattr FrozenAnaInputEve32woTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_event_32woTime(flag, f_value); +}; + +# g33v2 +refine typeattr FrozenAnaInputEve16woTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_event_16woTime(flag, f_value); +}; + +# g33v3 +refine typeattr FrozenAnaInputEve32wTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_event_32wTime(flag, f_value, time48); +}; + +# g33v4 +refine typeattr FrozenAnaInputEve16wTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_event_16wTime(flag, f_value, time48); +}; + +# g33v5 +refine typeattr FrozenAnaInputEveSPwoTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_event_SPwoTime(flag, f_value); +}; + +# g33v6 +refine typeattr FrozenAnaInputEveDPwoTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_event_DPwoTime(flag, f_value_low, f_value_high); +}; + +# g33v7 +refine typeattr FrozenAnaInputEveSPwTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_event_SPwTime(flag, f_value, time48); +}; + +# g33v8 +refine typeattr FrozenAnaInputEveDPwTime += &let { + process_request: bool = $context.flow.get_dnp3_frozen_analog_input_event_DPwTime(flag, f_value_low, f_value_high, time48); +}; + +# g70v5 +refine typeattr File_Transport += &let { + result: bool = $context.flow.get_dnp3_file_transport(file_handle, block_num, file_data); +}; + +refine typeattr Debug_Byte += &let { + process_request: bool = $context.flow.get_dnp3_debug_byte(debug); +}; + diff --git a/src/analyzer/protocol/dnp3/dnp3-objects.pac b/src/analyzer/protocol/dnp3/dnp3-objects.pac new file mode 100644 index 0000000000..35d0d42b92 --- /dev/null +++ b/src/analyzer/protocol/dnp3/dnp3-objects.pac @@ -0,0 +1,1451 @@ +##### moved from dnp3-protocol.pac + +type Prefix_Type(qualifier_field: uint8) = record { + prefix: case ( qualifier_field & 0xf0 ) of { + 0x00 -> none: empty &check(qualifier_field == 0x01 || + qualifier_field == 0x02 || + qualifier_field == 0x03 || + qualifier_field == 0x04 || + qualifier_field == 0x05 || + qualifier_field == 0x06 || + qualifier_field == 0x07 || + qualifier_field == 0x08 || + qualifier_field == 0x09 ); + 0x10 -> prefix8: uint8 &check(qualifier_field == 0x17 || + qualifier_field == 0x18 || + qualifier_field == 0x19 ); + 0x20 -> prefix16: uint16 &check(qualifier_field == 0x27 || + qualifier_field == 0x28 || + qualifier_field == 0x29 ); + 0x30 -> prefix32: uint32 &check(qualifier_field == 0x37 || + qualifier_field == 0x38 || + qualifier_field == 0x39 ); + 0x40 -> object_size8: uint8 &check(qualifier_field == 0x4B); + 0x50 -> object_size16: uint16 &check(qualifier_field == 0x5B); + 0x60 -> object_size32: uint32 &check(qualifier_field == 0x6B); + default -> unknownprefix: empty; + }; +} &let{ + prefix_value: uint32 = case (qualifier_field & 0xf0) of { + 0x00 -> 0; + 0x10 -> prefix8; + 0x20 -> prefix16; + 0x30 -> prefix32; + 0x40 -> object_size8; + 0x50 -> object_size16; + 0x60 -> object_size32; + default -> 0x0; + }; +} &byteorder = littleendian; + +type Request_Data_Object(function_code: uint8, qualifier_field: uint8, object_type_field: uint16) = record { + prefix: Prefix_Type(qualifier_field); + data: case (object_type_field) of { + # device attributes g0 + 0x00D3 -> attrib211: AttributeCommon; + 0x00D4 -> attrib212: AttributeCommon; + 0x00D5 -> attrib213: AttributeCommon; + 0x00D6 -> attrib214: AttributeCommon; + 0x00D7 -> attrib215: AttributeCommon; + 0x00D8 -> attrib216: AttributeCommon; + 0x00D9 -> attrib217: AttributeCommon; + 0x00DA -> attrib218: AttributeCommon; + 0x00DB -> attrib219: AttributeCommon; + 0x00DC -> attrib220: AttributeCommon; + 0x00DD -> attrib221: AttributeCommon; + 0x00DE -> attrib222: AttributeCommon; + 0x00DF -> attrib223: AttributeCommon; + 0x00E0 -> attrib224: AttributeCommon; + 0x00E1 -> attrib225: AttributeCommon; + 0x00E2 -> attrib226: AttributeCommon; + 0x00E3 -> attrib227: AttributeCommon; + 0x00E4 -> attrib228: AttributeCommon; + 0x00E5 -> attrib229: AttributeCommon; + 0x00E6 -> attrib230: AttributeCommon; + 0x00E7 -> attrib231: AttributeCommon; + 0x00E8 -> attrib232: AttributeCommon; + 0x00E9 -> attrib233: AttributeCommon; + 0x00EA -> attrib234: AttributeCommon; + 0x00EB -> attrib235: AttributeCommon; + 0x00EC -> attrib236: AttributeCommon; + 0x00ED -> attrib237: AttributeCommon; + 0x00EE -> attrib238: AttributeCommon; + 0x00EF -> attrib239: AttributeCommon; + 0x00F0 -> attrib240: AttributeCommon; + 0x00F1 -> attrib241: AttributeCommon; + 0x00F2 -> attrib242: AttributeCommon; + 0x00F3 -> attrib243: AttributeCommon; + 0x00F5 -> attrib245: AttributeCommon; + 0x00F6 -> attrib246: AttributeCommon; + 0x00F7 -> attrib247: AttributeCommon; + 0x00F8 -> attrib248: AttributeCommon; + 0x00F9 -> attrib249: AttributeCommon; + 0x00FA -> attrib250: AttributeCommon; + 0x00FC -> attrib252: AttributeCommon; + 0x00FE -> attrib254: AttributeCommon; + 0x00FF -> attrib255: AttributeCommon; + + # binary input g1 + 0x0100 -> bi_default: empty; + 0x0101 -> bi_packed: empty; + 0x0102 -> bi_flag: empty; + + # binary input event g2 + 0x0200 -> biedefault: empty; + 0x0201 -> biewotime: empty; + 0x0202 -> biewatime: empty; + 0x0203 -> biewrtime: empty; + + # double-bit Binary Input g3 + 0x0300 -> dbiDefault: empty; + 0x0301 -> dbibytes: empty; + 0x0302 -> dbiflag: empty; + + # double-bit Binary Input Event g4 + 0x0400 -> dbieDefault: empty; + 0x0401 -> dbieatime: empty; + 0x0402 -> dbiertime: empty; + + # binary output g10 + 0x0a00 -> boDefault: empty; + 0x0a01 -> bowoflag: empty; # warning: returning integer index? + 0x0a02 -> bowflag: empty; # warning: only flag? + + # binary output event g11 + 0x0b00 -> bowDefault: empty; + 0x0b01 -> boewflag: empty; + 0x0b02 -> boewatime: empty; + + # binary output command g12 + 0x0c01 -> bocmd_CROB: CROB &check (function_code == SELECT || function_code == OPERATE || + function_code == DIRECT_OPERATE || function_code == DIRECT_OPERATE_NR ); + 0x0c02 -> bocmd_PCB: PCB &check (function_code == SELECT || function_code == OPERATE || + function_code == DIRECT_OPERATE || function_code == DIRECT_OPERATE_NR || function_code == WRITE ); + 0x0c03 -> bocmd_PM: uint8; + + # binary output command event g13 + 0x0d00 -> boceDefault: empty; + 0x0d01 -> boceFlag: empty; + 0x0d02 -> boceAtime: empty; + + # counter ; g20 + 0x1400 -> counter_default: empty; + 0x1401 -> counter_32_wflag: empty; + 0x1402 -> counter_16_wflag: empty; + 0x1403 -> counter_32_wflag_delta: empty &check (0); # obsolete situation; generate warning + 0x1404 -> counter_16_wflag_delta: empty &check (0); # obsolete situations; generate warning + 0x1405 -> counter_32_woflag: empty; + 0x1406 -> counter_16_woflag: empty; + 0x1407 -> counter_32_woflag_delta: empty &check (0); # obsolete + 0x1408 -> counter_16_woflag_delta: empty &check (0); # obsolete + # frozen counter ; g21 + 0x1500 -> f_counter_default: empty; + 0x1501 -> f_counter_32_wflag: empty; + 0x1502 -> f_counter_16_wflag: empty; + 0x1503 -> f_counter_32_wflag_delta: empty &check (0); # obsolete situation; generate warning + 0x1504 -> f_counter_16_wflag_delta: empty &check (0); # obsolete situations; generate warning + 0x1505 -> f_counter_32_wflag_time: empty; + 0x1506 -> f_counter_16_wflag_time: empty; + 0x1507 -> f_counter_32_wflag_time_delta: empty &check (0); # obsolete + 0x1508 -> f_counter_16_wflag_time_delta: empty &check (0); # obsolete + 0x1509 -> f_counter_32_woflag: empty; + 0x150a -> f_counter_16_woflag: empty; + 0x150b -> f_counter_32_woflag_delta: empty &check (0); # obsolete + 0x150c -> f_counter_16_woflag_delta: empty &check (0); # obsolete + + # counter event g22 + 0x1600 -> counter_event_default: empty; + 0x1601 -> counter_event_32_wflag: empty; + 0x1602 -> counter_event_16_wflag: empty; + 0x1603 -> counter_event_32_wflag_delta: empty &check(0); + 0x1604 -> counter_event_16_wflag_delta: empty &check(0); + 0x1605 -> counter_event_32_wflag_time: empty; + 0x1606 -> counter_event_16_wflag_time: empty; + 0x1607 -> counter_event_32_wflag_time_delta: empty &check(0); + 0x1608 -> counter_event_16_wflag_time_delat: empty &check(0); + + # counter event g23 + 0x1700 -> f_counter_event_default: empty; + 0x1701 -> f_counter_event_32_wflag: empty; + 0x1702 -> f_counter_event_16_wflag: empty; + 0x1703 -> f_counter_event_32_wflag_delta: empty &check(0); + 0x1704 -> f_counter_event_16_wflag_delta: empty &check(0); + 0x1705 -> f_counter_event_32_wflag_time: empty; + 0x1706 -> f_counter_event_16_wflag_time: empty; + 0x1707 -> f_counter_event_32_wflag_time_delta: empty &check(0); + 0x1708 -> f_counter_event_16_wflag_time_delat: empty &check(0); + + #analog input g30 + 0x1e00 -> ai_default: empty; + 0x1e01 -> ai_32_wflag: empty; + 0x1e02 -> ai_16_wflag: empty; + 0x1e03 -> ai_32_woflag: empty; + 0x1e04 -> ai_16_woflag: empty; + 0x1e05 -> ai_sp_wflag: empty; + 0x1e06 -> ai_dp_wflag: empty; + + #frozen analog input g31 + 0x1f00 -> f_ai_default: empty; + 0x1f01 -> f_ai_32_wflag: empty; + 0x1f02 -> f_ai_16_wflag: empty; + 0x1f03 -> f_ai_32_wtime: empty; + 0x1f04 -> f_ai_16_wtime: empty; + 0x1f05 -> f_ai_32_woflag: empty; + 0x1f06 -> f_ai_16_woflag: empty; + 0x1f07 -> f_ai_sp_wflag: empty; + 0x1f08 -> f_ai_dp_wflag: empty; + + #analog input event g32 + 0x2000 -> aie_default: empty; + 0x2001 -> ai32wotime: empty; + 0x2002 -> ai16wotime: empty; + 0x2003 -> ai32wtime: empty; + 0x2004 -> ai16wtime: empty; + 0x2005 -> aispwotime: empty; + 0x2006 -> aidpwotime: empty; + 0x2007 -> aispwtime: empty; + 0x2008 -> aidpwtime: empty; + + # frozen analog input g33 + 0x2100 -> f_aie_default: empty; + 0x2101 -> f_aie_32_wotime: empty; + 0x2102 -> f_aie_16_wotime: empty; + 0x2103 -> f_aie_32_wtime: empty; + 0x2104 -> f_aie_16_wtime: empty; + 0x2105 -> f_aie_sp_wotime: empty; + 0x2106 -> f_aie_dp_wotime: empty; + 0x2107 -> f_aie_sp_wtime: empty; + 0x2108 -> f_aie_dp_wtime: empty; + + # analog input deadband g34 + 0x2200 -> ai_dead: empty; + 0x2201 -> ai_dead_16: empty; + 0x2202 -> ai_dead_32: empty; + 0x2203 -> ai_dead_sp: empty; + + # analog ouput status g40 + 0x2800 -> aos_default: empty; + 0x2801 -> aos_32: empty; + 0x2802 -> aos_16: empty; + 0x2803 -> aos_sp: empty; + 0x2804 -> aos_dp: empty; + + # analog ouput g41 + 0x2901 -> ao_32: AnaOut32; + 0x2902 -> ao_16: AnaOut16; + 0x2903 -> ao_sp: AnaOutSP; + 0x2904 -> ao_dp: AnaOutDP; + + # analog output event g42 + 0x2a00 -> aoe_default: empty; + 0x2a01 -> aoe32wotime: empty; + 0x2a02 -> aoe16wotime: empty; + 0x2a03 -> aoe32wtime: empty; + 0x2a04 -> aoe16wtime: empty; + 0x2a05 -> aoespwotime: empty; + 0x2a06 -> aoedpwotime: empty; + 0x2a07 -> aoespwtime: empty; + 0x2a08 -> aoedpwtime: empty; + + # analog output command event g43 + 0x2b00 -> aoce_default: empty; + 0x2b01 -> aoce32wotime: empty; + 0x2b02 -> aoce16wotime: empty; + 0x2b03 -> aoce32wtime: empty; + 0x2b04 -> aoce16wtime: empty; + 0x2b05 -> aocespwotime: empty; + 0x2b06 -> aocedpwotime: empty; + 0x2b07 -> aocespwtime: empty; + 0x2b08 -> aocedpwtime: empty; + + # time data interval data object g50 + 0x3200 -> time_default: empty; + 0x3201 -> time_abs: AbsTime; + 0x3202 -> time_interval: AbsTimeInterval; + 0x3203 -> time_abs_last: Last_AbsTime; + + # Time and Date Common Time-of-Occurrence g51 + 0x3301 -> time_abs_sync: AbsTime; + 0x3302 -> time_abs_unsync: AbsTime; + + # time delay g52 + 0x3401 -> time_coarse: uint16; + 0x3402 -> time_fine: uint16; + + # class objects g60 + 0x3C01 -> class0data: empty &check(object_header.qualifier_field == 0x06); + #0x3C02 -> class1data: uint8 &check(object_header.qualifier_field == 0x06); + 0x3C02 -> class1data: empty &check(object_header.qualifier_field == 0x06 || + object_header.qualifier_field == 0x07 || object_header.qualifier_field == 0x08); + 0x3C03 -> class2data: empty &check(object_header.qualifier_field == 0x06 || + object_header.qualifier_field == 0x07 || object_header.qualifier_field == 0x08); + 0x3C04 -> class3data: empty &check(object_header.qualifier_field == 0x06 || + object_header.qualifier_field == 0x07 || object_header.qualifier_field == 0x08); + # file control g70 + 0x4601 -> file_control_id: File_Control_ID &check(0); + 0x4602 -> file_control_auth: File_Control_Auth_Wrap(function_code); + 0x4603 -> file_control_cmd: File_Control_Cmd &check( file_control_cmd.op_mode == 0 || file_control_cmd.op_mode == 1 || + file_control_cmd.op_mode == 2 || file_control_cmd.op_mode == 3 ); + #0x4604 -> file_control_cmd_status: File_Control_Cmd_Status_Wrap(function_code, prefix.prefix_value); # example shown in P66 + 0x4604 -> file_control_cmd_status: File_Control_Cmd_Status(prefix.prefix_value); # example shown in P66 + 0x4605 -> file_trans: File_Transport(prefix.prefix_value); + 0x4606 -> file_trans_status: File_Transport_Status(prefix.prefix_value); + #0x4607 -> file_desc: File_Desc_Wrap(function_code); + 0x4607 -> file_desc: File_Desc; + + # internal indication g80 + #0x5001 -> iin: uint16; + 0x5001 -> iin: bytestring &restofdata; # confusion from the real traffic + + # device storage g81 + 0x5101 -> dev_store: empty; + + # device storage g82 + 0x5201 -> dev_profile: empty; + + # device storage g83 + 0x5301 -> priregobj: PrivRegObj; + 0x5302 -> priregobjdesc: PrivRegObjDesc; + + # private data set g85 + 0x5501 -> desc_ele: DescEle; + + # data descriptor table g86 + 0x5601 -> desc_ele86: DescEle; + 0x5602 -> cha: uint8; + 0x5603 -> point_index_attr: Debug_Byte; + + # Data set g87 + 0x5701 -> present_value: Debug_Byte; + + # Data set event g88 + 0x5801 -> snapshot: Debug_Byte; + + # application identification object g90 + #0x5A01 -> app_id: App_Id(qualifier_field, object_size16); + #0x5A01 -> app_id: App_Id(qualifier_field, prefix.prefix_value); + + # status of request operation g91 + 0x5b01 -> activate_conf: ActivateConf; + + # bcd value g101 + 0x6501 -> bcd_small: uint16; + 0x6502 -> bcd_medium: uint32; + 0x6503 -> bcd_large: BCD_Large; + + # unsigned integer g102 + 0x6601 -> unsigned_integer: uint8; + + # authentication challenge g120 + 0x7801 -> challenge: AuthChallenge(prefix.prefix_value); + 0x7802 -> reply: AuthRely(prefix.prefix_value); + 0x7803 -> aggrRequest: AuthAggrRequest(prefix.prefix_value); + 0x7804 -> seesionKeyRequest: uint8; + 0x7805 -> status: AuthSessionKeyStatus(prefix.prefix_value); + 0x7806 -> keyChange: AuthSessionKeyChange(prefix.prefix_value); + 0x7807 -> error: AuthError(prefix.prefix_value); + + default -> unmatched: Default_Wrap(object_type_field); + }; +}; + + +type Response_Data_Object(function_code: uint8, qualifier_field: uint8, object_type_field: uint16) = record { + prefix: Prefix_Type(qualifier_field); + data: case (object_type_field) of { + # device attributes g0 + 0x00D3 -> attrib211: AttributeCommon; + 0x00D4 -> attrib212: AttributeCommon; + 0x00D5 -> attrib213: AttributeCommon; + 0x00D6 -> attrib214: AttributeCommon; + 0x00D7 -> attrib215: AttributeCommon; + 0x00D8 -> attrib216: AttributeCommon; + 0x00D9 -> attrib217: AttributeCommon; + 0x00DA -> attrib218: AttributeCommon; + 0x00DB -> attrib219: AttributeCommon; + 0x00DC -> attrib220: AttributeCommon; + 0x00DD -> attrib221: AttributeCommon; + 0x00DE -> attrib222: AttributeCommon; + 0x00DF -> attrib223: AttributeCommon; + 0x00E0 -> attrib224: AttributeCommon; + 0x00E1 -> attrib225: AttributeCommon; + 0x00E2 -> attrib226: AttributeCommon; + 0x00E3 -> attrib227: AttributeCommon; + 0x00E4 -> attrib228: AttributeCommon; + 0x00E5 -> attrib229: AttributeCommon; + 0x00E6 -> attrib230: AttributeCommon; + 0x00E7 -> attrib231: AttributeCommon; + 0x00E8 -> attrib232: AttributeCommon; + 0x00E9 -> attrib233: AttributeCommon; + 0x00EA -> attrib234: AttributeCommon; + 0x00EB -> attrib235: AttributeCommon; + 0x00EC -> attrib236: AttributeCommon; + 0x00ED -> attrib237: AttributeCommon; + 0x00EE -> attrib238: AttributeCommon; + 0x00EF -> attrib239: AttributeCommon; + 0x00F0 -> attrib240: AttributeCommon; + 0x00F1 -> attrib241: AttributeCommon; + 0x00F2 -> attrib242: AttributeCommon; + 0x00F3 -> attrib243: AttributeCommon; + 0x00F5 -> attrib245: AttributeCommon; + 0x00F6 -> attrib246: AttributeCommon; + 0x00F7 -> attrib247: AttributeCommon; + 0x00F8 -> attrib248: AttributeCommon; + 0x00F9 -> attrib249: AttributeCommon; + 0x00FA -> attrib250: AttributeCommon; + 0x00FC -> attrib252: AttributeCommon; + 0x00FE -> attrib254: AttributeCommon; + 0x00FF -> attrib255: AttributeCommon; + + # binary input g1 + 0x0101 -> biwoflag: uint8; # warning: returning integer index? + 0x0102 -> biwflag: uint8; # warning: only flag? + + # binary input event g2 + 0x0201 -> biewoflag: uint8; + 0x0202 -> biewatime: BinInEveAtime; + 0x0203 -> biewrtime: BinInEveRtime; + + # double-bit Binary Input g3 + 0x0301 -> dbibytes: bytestring &restofdata; # don;t quit understand specification + 0x0302 -> dbiflag: uint8; + + # double-bit Binary Input Event g4 + 0x0401 -> dbieatime: DoubleInEveAtime; + 0x0402 -> dbiertime: DoubleInEveRtime; + + # binary output g10 + 0x0a01 -> bowoflag: uint8; # warning: returning integer index? + 0x0a02 -> bowflag: uint8; # warning: only flag? + + # binary output event g11 + 0x0b01 -> boewflag: uint8; + 0x0b02 -> boewatime: BinOutEveAtime; + + # binary output command g12 + 0x0c01 -> bocmd_CROB: CROB &check (function_code == SELECT || function_code == OPERATE || + function_code == DIRECT_OPERATE || function_code == DIRECT_OPERATE_NR ); + 0x0c02 -> bocmd_PCB: PCB &check (function_code == SELECT || function_code == OPERATE || + function_code == DIRECT_OPERATE || function_code == DIRECT_OPERATE_NR || function_code == WRITE ); + 0x0c03 -> bocmd_PM: uint8; + + # binary output command event g13 + 0x0d01 -> boceFlag: uint8; + 0x0d02 -> boceAtime: BinOutCmdEveAtime; + + # counter ; g20 + 0x1401 -> counter_32_wflag: Counter32wFlag; + 0x1402 -> counter_16_wflag: Counter16wFlag; + 0x1403 -> counter_32_wflag_delta: Debug_Byte &check (0); # obsolete situation; generate warning + 0x1404 -> counter_16_wflag_delta: Debug_Byte &check (0); # obsolete situations; generate warning + 0x1405 -> counter_32_woflag: Counter32woFlag; + 0x1406 -> counter_16_woflag: Counter16woFlag; + 0x1407 -> counter_32_woflag_delta: Debug_Byte &check (0); # obsolete + 0x1408 -> counter_16_woflag_delta: Debug_Byte &check (0); # obsolete + # frozen counter ; g21 + #0x1500 -> f_counter_default: empty; + 0x1501 -> f_counter_32_wflag: FrozenCounter32wFlag; + 0x1502 -> f_counter_16_wflag: FrozenCounter16wFlag; + 0x1503 -> f_counter_32_wflag_delta: Debug_Byte &check (0); # obsolete situation; generate warning + 0x1504 -> f_counter_16_wflag_delta: Debug_Byte &check (0); # obsolete situations; generate warning + 0x1505 -> f_counter_32_wflag_time: FrozenCounter32wFlagTime; + 0x1506 -> f_counter_16_wflag_time: FrozenCounter16wFlagTime; + 0x1507 -> f_counter_32_wflag_time_delta: Debug_Byte &check (0); # obsolete + 0x1508 -> f_counter_16_wflag_time_delta: Debug_Byte &check (0); # obsolete + 0x1509 -> f_counter_32_woflag: FrozenCounter32woFlag &check (f_counter_32_woflag.count_value == 23); + 0x150a -> f_counter_16_woflag: FrozenCounter16woFlag; + 0x150b -> f_counter_32_woflag_delta: Debug_Byte &check (0); # obsolete + 0x150c -> f_counter_16_woflag_delta: Debug_Byte &check (0); # obsolete + + # counter event g22 + 0x1601 -> counter_event_32_wflag: CounterEve32wFlag; + 0x1602 -> counter_event_16_wflag: CounterEve16wFlag; + 0x1603 -> counter_event_32_wflag_delta: Debug_Byte &check(0); + 0x1604 -> counter_event_16_wflag_delta: Debug_Byte &check(0); + 0x1605 -> counter_event_32_wflag_time: CounterEve32wFlagTime; + 0x1606 -> counter_event_16_wflag_time: CounterEve16wFlagTime; + 0x1607 -> counter_event_32_wflag_time_delta: Debug_Byte &check(0); + 0x1608 -> counter_event_16_wflag_time_delat: Debug_Byte &check(0); + + # counter event g23 + 0x1701 -> f_counter_event_32_wflag: CounterEve32wFlag; + 0x1702 -> f_counter_event_16_wflag: CounterEve16wFlag; + 0x1703 -> f_counter_event_32_wflag_delta: Debug_Byte &check(0); + 0x1704 -> f_counter_event_16_wflag_delta: Debug_Byte &check(0); + 0x1705 -> f_counter_event_32_wflag_time: CounterEve32wFlagTime; + 0x1706 -> f_counter_event_16_wflag_time: CounterEve16wFlagTime; + 0x1707 -> f_counter_event_32_wflag_time_delta: Debug_Byte &check(0); + 0x1708 -> f_counter_event_16_wflag_time_delat: Debug_Byte &check(0); + + # analog input g30 + 0x1e01 -> ai_32_wflag: AnalogInput32wFlag; + 0x1e02 -> ai_16_wflag: AnalogInput16wFlag; + 0x1e03 -> ai_32_woflag: AnalogInput32woFlag; + 0x1e04 -> ai_16_woflag: AnalogInput16woFlag; + 0x1e05 -> ai_sp_wflag: AnalogInputSPwFlag; + 0x1e06 -> ai_dp_wflag: AnalogInputDPwFlag; + + # frozen analog input g31 + 0x1f01 -> f_ai_32_wflag: FrozenAnalogInput32wFlag; + 0x1f02 -> f_ai_16_wflag: FrozenAnalogInput16wFlag; + 0x1f03 -> f_ai_32_wtime: FrozenAnalogInput32wTime; + 0x1f04 -> f_ai_16_wtime: FrozenAnalogInput16wTime; + 0x1f05 -> f_ai_32_woflag: AnalogInput32woFlag; + 0x1f06 -> f_ai_16_woflag: AnalogInput16woFlag; + 0x1f07 -> f_ai_sp_wflag: AnalogInputSPwFlag; + 0x1f08 -> f_ai_dp_wflag: AnalogInputDPwFlag; + + # analog input event g32 + 0x2001 -> ai32wotime: AnalogInput32woTime; + 0x2002 -> ai16wotime: AnalogInput16woTime; + 0x2003 -> ai32wtime: AnalogInput32wTime; + 0x2004 -> ai16wtime: AnalogInput16wTime; + 0x2005 -> aispwotime: AnalogInputSPwoTime; + 0x2006 -> aidpwotime: AnalogInputDPwoTime; + 0x2007 -> aispwtime: AnalogInputSPwTime; + 0x2008 -> aidpwtime: AnalogInputDPwTime; + + # frozen analog input event g33 + 0x2101 -> faie_32_wotime: FrozenAnaInputEve32woTime; + 0x2102 -> faie_16_wotime: FrozenAnaInputEve16woTime; + 0x2103 -> faie_32_wtime: FrozenAnaInputEve32wTime; + 0x2104 -> faie_16_wtime: FrozenAnaInputEve16wTime; + 0x2105 -> faie_sp_wotime: FrozenAnaInputEveSPwoTime; + 0x2106 -> faie_dp_wotime: FrozenAnaInputEveDPwoTime; + 0x2107 -> faie_sp_wtime: FrozenAnaInputEveSPwTime; + 0x2108 -> faie_dp_wtime: FrozenAnaInputEveDPwTime; + + # analog input deadband g34 + 0x2201 -> ai_dead_16: uint16; + 0x2202 -> ai_dead_32: uint32; + 0x2203 -> ai_dead_sp: uint32; + + # analog ouput status g40 + 0x2801 -> aos_32: AnaOutStatus32; + 0x2802 -> aos_16: AnaOutStatus16; + 0x2803 -> aos_sp: AnaOutStatusSP; + 0x2804 -> aos_dp: AnaOutStatusDP; + + # analog ouput g41 + 0x2901 -> ao_32: AnaOut32; + 0x2902 -> ao_16: AnaOut16; + 0x2903 -> ao_sp: AnaOutSP; + 0x2904 -> ao_dp: AnaOutDP; + + # analog output event g42 + 0x2a01 -> aoe32wotime: AnaOutEve32woTime; + 0x2a02 -> aoe16wotime: AnaOutEve16woTime; + 0x2a03 -> aoe32wtime: AnaOutEve32wTime; + 0x2a04 -> aoe16wtime: AnaOutEve16wTime; + 0x2a05 -> aoespwotime: AnaOutEveSPwoTime; + 0x2a06 -> aoedpwotime: AnaOutEveDPwoTime; + 0x2a07 -> aoespwtime: AnaOutEveSPwTime; + 0x2a08 -> aoedpwtime: AnaOutEveDPwTime; + + # analog output command event g43 + 0x2b01 -> aoce32wotime: AnaOutEve32woTime; + 0x2b02 -> aoce16wotime: AnaOutEve16woTime; + 0x2b03 -> aoce32wtime: AnaOutEve32wTime; + 0x2b04 -> aoce16wtime: AnaOutEve16wTime; + 0x2b05 -> aocespwotime: AnaOutEveSPwoTime; + 0x2b06 -> aocedpwotime: AnaOutEveDPwoTime; + 0x2b07 -> aocespwtime: AnaOutEveSPwTime; + 0x2b08 -> aocedpwtime: AnaOutEveDPwTime; + + # time data interval data object g50 + 0x3201 -> time_abs: AbsTime; + 0x3202 -> time_interval: AbsTimeInterval; + 0x3203 -> time_abs_last: Last_AbsTime; + + # Time and Date Common Time-of-Occurrence g51 + 0x3301 -> time_abs_sync: AbsTime; + 0x3302 -> time_abs_unsync: AbsTime; + + # time delay g52 + 0x3401 -> time_coarse: uint16; + 0x3402 -> time_fine: uint16; + + # file control g70 + 0x4601 -> file_control_id: File_Control_ID &check(0); + 0x4602 -> file_control_auth: File_Control_Auth &check(file_control_auth.usr_name_size == 0 && file_control_auth.pwd_size == 0); + 0x4603 -> file_control_cmd: File_Control_Cmd &check(file_control_cmd.name_size == 0 && + ( file_control_cmd.op_mode == 0 || file_control_cmd.op_mode == 1 || + file_control_cmd.op_mode == 2 || file_control_cmd.op_mode == 3) ); + 0x4604 -> file_control_cmd_status: File_Control_Cmd_Status(prefix.prefix_value); + 0x4605 -> file_trans: File_Transport(prefix.prefix_value); + 0x4606 -> file_trans_status: File_Transport_Status(prefix.prefix_value); + #0x4607 -> file_desc: File_Desc_Wrap(function_code); + 0x4607 -> file_desc: File_Desc; + + # internal indication g80 + 0x5001 -> iin: uint16; + # device storage g81 + 0x5101 -> dev_store: Dev_Store; + + # device storage g82 + 0x5201 -> dev_profile: Dev_Profile; + + # device storage g83 + 0x5301 -> priregobj: PrivRegObj; + 0x5302 -> priregobjdesc: PrivRegObjDesc; + + # device storage g85 + 0x5501 -> desc_ele: DescEle; + + # data descriptor table g86 + 0x5601 -> desc_ele86: DescEle; + 0x5602 -> cha: uint8; + 0x5603 -> point_index_attr: Debug_Byte; + + # Data set g87 + 0x5701 -> present_value: Debug_Byte; + + # Data set event g88 + 0x5801 -> snapshot: Debug_Byte; + + # status of request operation g91 + 0x5b01 -> activate_conf: ActivateConf; + + # bcd value g101 + 0x6501 -> bcd_small: uint16; + 0x6502 -> bcd_medium: uint32; + 0x6503 -> bcd_large: BCD_Large; + + # unsigned integer g102 + 0x6601 -> unsigned_integer: uint8; + + # authentication challenge g120 + 0x7801 -> challenge: AuthChallenge(prefix.prefix_value); + 0x7802 -> reply: AuthRely(prefix.prefix_value); + 0x7803 -> aggrRequest: AuthAggrRequest(prefix.prefix_value); + 0x7804 -> seesionKeyRequest: uint8; + 0x7805 -> status: AuthSessionKeyStatus(prefix.prefix_value); + 0x7806 -> keyChange: AuthSessionKeyChange(prefix.prefix_value); + 0x7807 -> error: AuthError(prefix.prefix_value); + + #default -> unkonwndata: Debug_Byte &check( T ); + default -> unmatched: Default_Wrap(object_type_field); + }; +} + &let{ + data_value: uint8 = case (object_type_field) of { # this data_value is used for the Bro Event + 0x0101 -> biwoflag; + 0x0102 -> biwflag; + 0x0a01 -> bowoflag; + 0x0a02 -> bowflag; + default -> 0xff; + }; + } +; + + +###### +# this Default_Wrap is created when dealing with g110. Only Group type matters and variations can be all. So too much coding +type Default_Wrap(obj_type: uint32) = record { + unresolved: case (obj_type & 0xFF00) of { + 0x6E00 -> oct_str: bytestring &length = (obj_type & 0x00FF) ; + 0x6F00 -> oct_str_eve: bytestring &length = (obj_type & 0x00FF) ; + 0x7000 -> vir_ter_out_blk: bytestring &length = (obj_type & 0x00FF) ; + 0x7100 -> vir_ter_eve: bytestring &length = (obj_type & 0x00FF) ; + + #default -> unknown: bytestring &restofdata; + default -> unknown: Debug_Byte; + }; +}; + +# contains different objects format +# corresponding to the DNP3Spec-V6-Part2-Objects + +# g0: group 0 objects are used to retrieve substation attributes; +# all variations including variation 249 255, share the same structure; +type AttributeCommon = record { + data_type_code: uint8; + leng: uint8; + attribute_obj: bytestring &length=leng; +} &byteorder = littleendian; + + +# g2v2 +type BinInEveAtime = record { + flag: uint8; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g2v3 +type BinInEveRtime = record { + flag: uint8; + time16: uint16; +} &byteorder = littleendian; + +# g4v2 +type DoubleInEveAtime = record { + flag: uint8; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g4v3 +type DoubleInEveRtime = record { + flag: uint8; + time16: uint16; +} &byteorder = littleendian; + +# g11v2 +type BinOutEveAtime = record { + flag: uint8; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g12v1 group: 12; variation: 1 +type CROB = record { + control_code: uint8 &check ( (control_code & 0xCF) == 0x00 || (control_code & 0xCF) == 0x01 || (control_code & 0xCF) == 0x03 || (control_code & 0xCF) == 0x04 || + (control_code & 0xCF) == 0x41 || (control_code & 0xCF) == 0x81 ); + count: uint8; + on_time: uint32; + off_time: uint32; + status_code: uint8; # contains the reserved bit +} &byteorder = littleendian; + +# g12v2; same as g12v1 +type PCB = record { + control_code: uint8 &check ( (control_code & 0xCF) == 0x00 || (control_code & 0xCF) == 0x01 || (control_code & 0xCF) == 0x03 || (control_code & 0xCF) == 0x04 || + (control_code & 0xCF) == 0x41 || (control_code & 0xCF) == 0x81 ); + count: uint8; + on_time: uint32; + off_time: uint32; + status_code: uint8; # contains the reserved bit +} &byteorder = littleendian; + +# g13v2 +type BinOutCmdEveAtime = record { + flag: uint8; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g20v1; group: 20, variation 1 +type Counter32wFlag = record { + flag: uint8; + count_value: uint32; +} &byteorder = littleendian; + +# g20v2 +type Counter16wFlag = record { + flag: uint8; + count_value: uint16; +} &byteorder = littleendian; + +# g20v3 and g20v4 are obsolete + +# g20v5 +type Counter32woFlag = record { + count_value: uint32; +} &byteorder = littleendian; + +# g20v6 +type Counter16woFlag = record { + count_value: uint16; +} &byteorder = littleendian; + +# g20v7 and g20v8 are obsolete + +# g21v1 +type FrozenCounter32wFlag = record { + flag: uint8; + count_value: uint32; +} &byteorder = littleendian; + +# g21v2 +type FrozenCounter16wFlag = record { + flag: uint8; + count_value: uint16; +} &byteorder = littleendian; + +# g21v3 and g21v4 are obsolete + +# g21v5 +type FrozenCounter32wFlagTime = record { + flag: uint8; + count_value: uint32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g21v6 +type FrozenCounter16wFlagTime = record { + flag: uint8; + count_value: uint16; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g21v7 and g21v8 are obsolete + +# g21v9 +type FrozenCounter32woFlag = record { + count_value: uint32; +} &byteorder = littleendian; + +# g21v10 +type FrozenCounter16woFlag = record { + count_value: uint16; +} &byteorder = littleendian; + +# g21v11 and g21v12 are obsolete + +# Conter event g22 + +# g22v1 +type CounterEve32wFlag = record { + flag: uint8; + count_value: uint32; +} &byteorder = littleendian; + +# g22v2 +type CounterEve16wFlag = record { + flag: uint8; + count_value: uint16; +} &byteorder = littleendian; + +# g22v3 and g22v4 obsolete + +# g22v5 +type CounterEve32wFlagTime = record { + flag: uint8; + count_value: uint32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g22v6 +type CounterEve16wFlagTime = record { + flag: uint8; + count_value: uint16; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g22v7 g22v8 obsolete + +# Conter event g23 + +# g23v1 +type FrozenCounterEve32wFlag = record { + flag: uint8; + count_value: uint32; +} &byteorder = littleendian; + +# g23v2 +type FrozenCounterEve16wFlag = record { + flag: uint8; + count_value: uint16; +} &byteorder = littleendian; + +# g23v3 and g23v4 obsolete + +# g23v5 +type FrozenCounterEve32wFlagTime = record { + flag: uint8; + count_value: uint32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g23v6 +type FrozenCounterEve16wFlagTime = record { + flag: uint8; + count_value: uint16; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g23v7 g23v8 obsolete + +# group: 30; variation: 1 g30v1 +type AnalogInput32wFlag = record { + flag: uint8; + value: int32; +} &byteorder = littleendian; + +# group: 30; variation: 2 +type AnalogInput16wFlag = record { + flag: uint8; + value: int16; +} &byteorder = littleendian; + +# group: 30; variation: 3 +type AnalogInput32woFlag = record { + value: int32; +} &byteorder = littleendian; + +# group: 30; variation: 4 +type AnalogInput16woFlag = record { + value: int16; +} &byteorder = littleendian; + +# group: 30; variation: 5; singple precision 32 bit +type AnalogInputSPwFlag = record { + flag: uint8; + value: uint32; +} &byteorder = littleendian; + +# group: 30; variation: 6; double precision 64 bit +type AnalogInputDPwFlag = record { + flag: uint8; + value_low: uint32; + value_high: uint32; +} &byteorder = littleendian; + +# g31v1 +type FrozenAnalogInput32wFlag = record { + flag: uint8; + frozen_value: int32; +} &byteorder = littleendian; + +# g31v2 +type FrozenAnalogInput16wFlag = record { + flag: uint8; + frozen_value: int16; +} &byteorder = littleendian; + +# g31v3 +type FrozenAnalogInput32wTime = record { + flag: uint8; + frozen_value: int32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g31v4 +type FrozenAnalogInput16wTime = record { + flag: uint8; + frozen_value: int16; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g31v5 +type FrozenAnalogInput32woFlag = record { + frozen_value: int32; +} &byteorder = littleendian; + +# g31v6 +type FrozenAnalogInput16woFlag = record { + frozen_value: uint16; +} &byteorder = littleendian; + +# g31v7 +type FrozenAnalogInputSPwFlag = record { + flag: uint8; + frozen_value: uint32; +} &byteorder = littleendian; + +# g31v8 +type FrozenAnalogInputDPwFlag = record { + flag: uint8; + frozen_value_low: uint32; + frozen_value_high: uint32; +} &byteorder = littleendian; + +# group: 32; variation: 1 g32v1 +type AnalogInput32woTime = record { + flag: uint8; + value: int32; +} &byteorder = littleendian; + +# group: 32; variation: 2 +type AnalogInput16woTime = record { + flag: uint8; + value: int16; +} &byteorder = littleendian; + +# group: 32; variation: 3 +type AnalogInput32wTime = record { + flag: uint8; + value: int32; + #time: uint8[6]; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# group: 32; variation: 4 +type AnalogInput16wTime = record { + flag: uint8; + value: int16; + #time: uint8[6]; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# group: 32; variation: 5; singple precision 32 bit +type AnalogInputSPwoTime = record { + flag: uint8; + value: uint32; +} &byteorder = littleendian; + +# group: 32; variation: 6; double precision 64 bit +type AnalogInputDPwoTime = record { + flag: uint8; + value_low: uint32; + value_high: uint32; +} &byteorder = littleendian; + +# group: 32; variation: 7 +type AnalogInputSPwTime = record { + flag: uint8; + value: uint32; + #time: uint8[6]; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# group: 32; variation: 8 +type AnalogInputDPwTime = record { + flag: uint8; + value_low: uint32; + value_high: uint32; + #time: uint8[6]; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g33v1 +type FrozenAnaInputEve32woTime = record { + flag: uint8; + f_value: int32; +} &byteorder = littleendian; + +# g33v2 +type FrozenAnaInputEve16woTime = record { + flag: uint8; + f_value: int16; +} &byteorder = littleendian; + +# g33v3 +type FrozenAnaInputEve32wTime = record { + flag: uint8; + f_value: int32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g33v4 +type FrozenAnaInputEve16wTime = record { + flag: uint8; + f_value: int32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g33v5 +type FrozenAnaInputEveSPwoTime = record { + flag: uint8; + f_value: uint32; +} &byteorder = littleendian; + +# g33v6 +type FrozenAnaInputEveDPwoTime = record { + flag: uint8; + f_value_low: uint32; + f_value_high: uint32; +} &byteorder = littleendian; + +# g33v7 +type FrozenAnaInputEveSPwTime = record { + flag: uint8; + f_value: uint32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g33v8 +type FrozenAnaInputEveDPwTime = record { + flag: uint8; + f_value_low: uint32; + f_value_high: uint32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# analog output status g40 + +# g40v1 +type AnaOutStatus32 = record { + flag: uint8; + status: int32; +} &byteorder = littleendian; + +# g40v2 +type AnaOutStatus16 = record { + flag: uint8; + status: int16; +} &byteorder = littleendian; + +# g40v3 +type AnaOutStatusSP = record { + flag: uint8; + status: uint32; +} &byteorder = littleendian; + +# g40v4 +type AnaOutStatusDP = record { + flag: uint8; + status_low: uint32; + status_high: uint32; +} &byteorder = littleendian; + +# analog output g41 + +# g41v1 +type AnaOut32 = record { + value: int32; + con_status: uint8; +} &byteorder = littleendian; + +# g41v2 +type AnaOut16 = record { + value: int16; + con_status: uint8; +} &byteorder = littleendian; + +# g41v3 +type AnaOutSP = record { + value: uint32; + con_status: uint8; +} &byteorder = littleendian; + +# g41v4 +type AnaOutDP = record { + value_low: uint32; + value_high: uint32; + con_status: uint8; +} &byteorder = littleendian; + +# analog output event g42 + +# g42v1 +type AnaOutEve32woTime = record { + flag: uint8; + value: int32; +} &byteorder = littleendian; + +# g42v2 +type AnaOutEve16woTime = record { + flag: uint8; + value: int16; +} &byteorder = littleendian; + +# g42v3 +type AnaOutEve32wTime = record { + flag: uint8; + value: int32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g42v4 +type AnaOutEve16wTime = record { + flag: uint8; + value: int16; + time48: bytestring &length = 6; +} &byteorder = littleendian; +# g42v5 +type AnaOutEveSPwoTime = record { + flag: uint8; + value: uint32; +} &byteorder = littleendian; + +# g42v6 +type AnaOutEveDPwoTime = record { + flag: uint8; + value_low: uint32; + value_high: uint32; +} &byteorder = littleendian; + +# g42v7 +type AnaOutEveSPwTime = record { + flag: uint8; + value: uint32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g42v8 +type AnaOutEveDPwTime = record { + flag: uint8; + value_low: uint32; + value_high: uint32; + time48: bytestring &length = 6; +} &byteorder = littleendian; + +## g43 data format is exacatly same as g42 so use g42 directly + +# g50v1 +type AbsTime = record { + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g50v2 +type AbsTimeInterval = record { + time48: bytestring &length = 6; + interval: uint32; +} &byteorder = littleendian; + +# g50v3 +type Last_AbsTime = record { + time48: bytestring &length = 6; +} &byteorder = littleendian; + +# g51v1 and g51v2 are the same structure of g50v1. so reuse it + +# g70v1 +type Record_Obj = record { + record_size: uint16; + record_oct: bytestring &length = record_size; +} &byteorder = littleendian; + +type File_Control_ID = record { + name_size: uint16; + type_code: uint8; + attr_code: uint8; + start_rec: uint16; + end_rec: uint16; + file_size: uint32; + time_create: bytestring &length = 6; + permission: uint16 &check ( (permission & 0xFE00 ) == 0x0000); + file_id: uint32; + owner_id: uint32; + group_id: uint32; + function_code: uint8; + status_code: uint8; + file_name: bytestring &length = name_size; + records: Record_Obj[]; +} &byteorder = littleendian; + +# g70v2 +type File_Control_Auth_Wrap(fc: uint8) = record { + data: case(fc) of { + AUTHENTICATE_FILE -> auth_file: File_Control_Auth &check(auth_file.auth_key == 0) ; + default -> null: empty; + }; +}; + +type File_Control_Auth = record { + usr_name_offset: uint16; + usr_name_size: uint16; + pwd_offset: uint16; + pwd_size: uint16; + auth_key: uint32; + usr_name: bytestring &length = usr_name_size; + pwd: bytestring &length = pwd_size; +} &byteorder = littleendian; + +# g70v3 +type File_Control_Cmd_Wrap(function_code: uint8) = record { + data_obj: case (function_code) of { + OPEN_FILE -> fc_cmd_open: File_Control_Cmd; + DELETE_FILE -> fc_cmd_del: File_Control_Cmd &check( fc_cmd_del.op_mode == 0 && fc_cmd_del.name_size == 0 && fc_cmd_del.time_create == 0x0); + default -> null: empty; + }; + +}; + +type File_Control_Cmd = record { + name_offset: uint16; + name_size: uint16; + time_create: bytestring &length = 6; + permission: uint16 &check ( (permission & 0xFE00 ) == 0x0000); + auth_key: uint32; + file_size: uint32; + op_mode: uint16; + max_block_size: uint16; + req_id: uint16; + file_name: bytestring &length = name_size; +} &byteorder = littleendian; + +# g70v4 +type File_Control_Cmd_Status_Wrap(function_code: uint8, obj_size: uint32) = record { + data_obj: case (function_code) of { + ABORT_FILE -> abort: File_Control_Cmd_Status(obj_size) &check(abort.file_size == 0 && abort.max_block_size ==0 && abort.status_code ==0 ); + RESPONSE -> fc_cmd_status: File_Control_Cmd_Status(obj_size); + default -> null: empty; + }; +}; + +type File_Control_Cmd_Status(obj_size: uint32) = record { + file_handle: uint32; + file_size: uint32; + max_block_size: uint16; + req_id: uint16 ; + status_code: uint8; + #opt_text: bytestring &restofdata; + opt_text: bytestring &length = (obj_size - 8 - 4 - 1); +} &byteorder = littleendian; + +# g70v5 +type File_Transport(obj_size: uint32) = record { + file_handle: uint32; + block_num: uint32; + # file_data: bytestring &restofdata; + file_data: bytestring &length = (obj_size - 8); +} &byteorder = littleendian; + +# g70v6 +type File_Transport_Status(obj_size: uint32) = record { + file_handle: uint32; + block_num: uint32; + status: uint8; + #file_data: bytestring &restofdata; + opt_text: bytestring &length = (obj_size - 4 - 4 - 1); +} &byteorder = littleendian; + +# g70v7 +type File_Desc_Wrap(function_code: uint8) = record { + data: case(function_code) of { + GET_FILE_INFO -> get_file_info: File_Desc &check(get_file_info.type ==0 && + get_file_info.f_size == 0 && + get_file_info.time_create_low == 0 && + get_file_info.time_create_high == 0 && + get_file_info.permission == 0); + default -> null: empty; + }; +} &byteorder = littleendian; + +type File_Desc = record { + name_offset: uint16; + name_size: uint16; + type: uint16; + f_size: uint32; + time_create_low: uint32; + time_create_high: uint16; + permission: uint16 &check ( (permission & 0xFE00 ) == 0x0000); + req_id: uint16; + f_name: bytestring &length = name_size; +} &byteorder = littleendian; + +# g70v8 +type File_Spec_Str = record { + f_spec: bytestring &restofdata; +} &byteorder = littleendian; + +# device storage g81 +# g81v1 +type Dev_Store = record { + overflow: uint8; + obj_group: uint8; + variatiion: uint8; +} &byteorder = littleendian; + +# device profile g82 +# g82v1 +type Dev_Profile = record { + fc_support_low: uint32; + fc_support_high: uint32; + count: uint16; + dev_headers: Dev_Profile_OH[count]; +} &byteorder = littleendian; + +type Dev_Profile_OH = record { + group: uint8; + variation: uint8; + qualifier: uint8; + range: uint8; +} &byteorder = littleendian; + +# data set g983 + +# g83v1 +type PrivRegObj = record { + vendor: uint32; + obj_id: uint16; + len: uint16; + data_objs: bytestring &length = len; +} &byteorder = littleendian; + +# g83v2 +type PrivRegObjDesc = record { + vendor: uint32; + obj_id: uint16; + count: uint16; + data_objs: ObjDescSpec[count]; +} &byteorder = littleendian; + +type ObjDescSpec = record { + obj_quantity: uint16; + obj_group: uint8; + obj_variation: uint8; +} &byteorder = littleendian; + +# data set prototype g85 + +# g85v1 only one descriptor element is defined. number of n is defined by number-of-item +type DescEle = record { + len: uint8; + desc_code: uint8; + data_type: uint8; + max_len: uint8; + ancillary: uint8; +} &byteorder = littleendian; + +# data descriptor element g86 + +# g86v1 is the same structure of DescEle + +# g86v3 does not quite understant specification description + +# g87 doest not quite understand specfication description + +# g88 doest not quite understand specfication description + +# g90v1 +type App_Id(qualifier_field: uint8, object_size16: uint16) = record { + app_id: case (qualifier_field) of { + 0x5B -> app_name: bytestring &length = object_size16; + 0x06 -> all_app: empty; + default -> illegal: empty; + }; +} &byteorder = littleendian; + +# status of request operation g91 +type ActivateConf = record { + time_delay: uint32; + count: uint8; + elements: StatusEle[count]; +} &byteorder = littleendian; + +type StatusEle = record { + len: uint8; + status_code: uint8; + ancillary: bytestring &length = ( len - 1 ); +} &byteorder = littleendian; + +# BCD values + +# g101v3 +type BCD_Large = record { + value_low: uint32; + vlaue_high: uint32; +} &byteorder = littleendian; + +# authentication g120 + +# g120v1 +type AuthChallenge(prefix: uint16) = record { + csqUsr: uint32; + hal: uint8; + reason: uint8; + chan_data: bytestring &length = (prefix - 10); +} &byteorder = littleendian; + +# g120v2 +type AuthRely(prefix: uint16) = record { + csqUsr: uint32; + chan_data: bytestring &length = (prefix - 4); +} &byteorder = littleendian; + +# g120v3 +type AuthAggrRequest(prefix: uint16) = record { + csqUsr: uint32; + chan_data: bytestring &length = (prefix - 4); +} &byteorder = littleendian; + +# g120v5 +type AuthSessionKeyStatus(prefix: uint16) = record { + csqUsr: uint32; + key_alg: uint8; + key_status: uint8; + chan_data: bytestring &length = (prefix - 10); +} &byteorder = littleendian; + +# g120v6 +type AuthSessionKeyChange(prefix: uint16) = record { + csqUsr: uint32; + key_wrap_data: bytestring &length = (prefix - 5); +} &byteorder = littleendian; + +# g120v7 +type AuthError(prefix: uint16) = record { + csqUsr: uint32; + error_code: uint8; + key_wrap_data: bytestring &length = (prefix - 6); +} &byteorder = littleendian; diff --git a/src/analyzer/protocol/dnp3/dnp3-protocol.pac b/src/analyzer/protocol/dnp3/dnp3-protocol.pac new file mode 100644 index 0000000000..02fbd678cc --- /dev/null +++ b/src/analyzer/protocol/dnp3/dnp3-protocol.pac @@ -0,0 +1,257 @@ +# +# This is Binpac code for DNP3 analyzer by Hui Lin. +# + +type DNP3_PDU(is_orig: bool) = case is_orig of { + true -> request: DNP3_Request; + false -> response: DNP3_Response; +} &byteorder = bigendian; + +type Header_Block = record { + start: uint16 &check(start == 0x0564); + len: uint8; + ctrl: uint8; + dest_addr: uint16; + src_addr: uint16; +} &byteorder = littleendian; + +type DNP3_Request = record { + addin_header: Header_Block; ## added by Hui Lin in Bro code + app_header: DNP3_Application_Request_Header; + data: case ( app_header.function_code ) of { + CONFIRM -> none_coonfirm: empty; + READ -> read_requests: Request_Objects(app_header.function_code)[]; + WRITE -> write_requests: Request_Objects(app_header.function_code)[]; + SELECT -> select_requests: Request_Objects(app_header.function_code)[]; + OPERATE -> operate_requests: Request_Objects(app_header.function_code)[]; + DIRECT_OPERATE -> direct_operate_requests: Request_Objects(app_header.function_code)[]; + DIRECT_OPERATE_NR -> direct_operate_nr_requests: Request_Objects(app_header.function_code)[]; + IMMED_FREEZE -> immed_freeze_requests: Request_Objects(app_header.function_code)[]; + IMMED_FREEZE_NR -> immed_freeze_nr_requests: Request_Objects(app_header.function_code)[]; + FREEZE_CLEAR -> freeze_clear_requests: Request_Objects(app_header.function_code)[]; + FREEZE_CLEAR_NR -> freeze_clear_nr_requests: Request_Objects(app_header.function_code)[]; + FREEZE_AT_TIME -> freeze_time_requests: Request_Objects(app_header.function_code)[]; + FREEZE_AT_TIME_NR -> freeze_time_nr_requests: Request_Objects(app_header.function_code)[]; + COLD_RESTART -> cold_restart: empty; + WARM_RESTART -> warm_restart: empty; + INITIALIZE_DATA -> initilize_data: empty &check(0); # obsolete + INITIALIZE_APPL -> initilize_appl: Request_Objects(app_header.function_code)[]; + START_APPL -> start_appl: Request_Objects(app_header.function_code)[]; + STOP_APPL -> stop_appl: Request_Objects(app_header.function_code)[]; + SAVE_CONFIG -> save_config: empty &check(0); # depracated + ENABLE_UNSOLICITED -> enable_unsolicited: Request_Objects(app_header.function_code)[]; + DISABLE_UNSOLICITED -> disable_unsolicited: Request_Objects(app_header.function_code)[]; + ASSIGN_CLASS -> assign_class: Request_Objects(app_header.function_code)[]; + DELAY_MEASURE -> delay_measure: empty; + RECORD_CURRENT_TIME -> record_cur_time: empty; + OPEN_FILE -> open_file: Request_Objects(app_header.function_code)[]; + CLOSE_FILE -> close_file: Request_Objects(app_header.function_code)[]; + DELETE_FILE -> delete_file: Request_Objects(app_header.function_code)[]; + ABORT_FILE -> abort_file: Request_Objects(app_header.function_code)[]; + GET_FILE_INFO -> get_file_info: Request_Objects(app_header.function_code)[]; + AUTHENTICATE_FILE -> auth_file: Request_Objects(app_header.function_code)[]; + ACTIVATE_CONFIG -> active_config: Request_Objects(app_header.function_code)[]; + AUTHENTICATE_REQ -> auth_req: Request_Objects(app_header.function_code)[]; + AUTHENTICATE_ERR -> auth_err: Request_Objects(app_header.function_code)[]; + default -> unknown: bytestring &restofdata; + }; +} &byteorder = bigendian + &length= 9 + addin_header.len - 5 - 1; + +type Debug_Byte = record { + debug: bytestring &restofdata; +}; + +type DNP3_Response = record { + addin_header: Header_Block; + app_header: DNP3_Application_Response_Header; + data: case ( app_header.function_code ) of { + RESPONSE -> response_objects: Response_Objects(app_header.function_code)[]; + UNSOLICITED_RESPONSE -> unsolicited_response_objects: Response_Objects(app_header.function_code)[]; + AUTHENTICATE_RESP -> auth_response: Response_Objects(app_header.function_code)[]; + default -> unknown: Debug_Byte; + }; +} &byteorder = bigendian + &length= 9 + addin_header.len - 5 - 1' + +type DNP3_Application_Request_Header = record { + empty: bytestring &length = 0; # Work-around BinPAC problem. + application_control : uint8; + function_code : uint8 ; +} &length = 2; + +type DNP3_Application_Response_Header = record { + empty: bytestring &length = 0; # Work-around BinPAC problem. + application_control : uint8; + function_code : uint8; + internal_indications : uint16; +} &length = 4; + +type Request_Objects(function_code: uint8) = record { + object_header: Object_Header(function_code); + data: case (object_header.object_type_field) of { + 0x0c03 -> bocmd_PM: Request_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) + 1 ]; + 0x3202 -> time_interval_ojbects: Request_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ object_header.number_of_item] + &check( object_header.qualifer_field == 0x0f && object_header.number_of_item == 0x01); + default -> ojbects: Request_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ object_header.number_of_item]; + }; + # dump_data is always empty; I intend to use it for checking some conditions; + # However, in the current binpac implementation, &check is not implemented + dump_data: case (function_code) of { + OPEN_FILE -> open_file_dump: empty &check(object_header.object_type_field == 0x4603); + CLOSE_FILE -> close_file_dump: empty &check(object_header.object_type_field == 0x4604); + DELETE_FILE -> delete_file_dump: empty &check(object_header.object_type_field == 0x4603); + ABORT_FILE -> abort_file_dump: empty &check(object_header.object_type_field == 0x4604); + GET_FILE_INFO -> get_file_info: empty &check(object_header.object_type_field == 0x4607); + AUTHENTICATE_FILE -> auth_file: empty &check(object_header.object_type_field == 0x4602); + ACTIVATE_CONFIG -> active_config: empty &check(object_header.object_type_field == 0x4608 || (object_header.object_type_field & 0xFF00) == 0x6E00); + default -> default_dump: empty; + }; +}; + +type Response_Objects(function_code: uint8) = record { + object_header: Object_Header(function_code); + data: case (object_header.object_type_field) of { + 0x0101 -> biwoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) ]; + 0x0301 -> diwoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) ]; + 0x0a01 -> bowoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) ]; + 0x0c03 -> bocmd_PM: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) ]; + default -> ojbects: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ object_header.number_of_item]; + }; +}; + +type Object_Header(function_code: uint8) = record { + object_type_field: uint16 ; + qualifier_field: uint8 ; + range_field: case ( qualifier_field & 0x0f ) of { + 0 -> range_field_0: Range_Field_0 &check(range_field_0.stop_index >= range_field_0.start_index); + 1 -> range_field_1: Range_Field_1 &check(range_field_1.stop_index >= range_field_1.start_index); + 2 -> range_field_2: Range_Field_2 &check(range_field_2.stop_index >= range_field_2.start_index); + 3 -> range_field_3: Range_Field_3; + 4 -> range_field_4: Range_Field_4; + 5 -> range_field_5: Range_Field_5; + 6 -> range_field_6: empty; + 7 -> range_field_7: uint8; + 8 -> range_field_8: uint16; + 9 -> range_field_9: uint32; + 0x0b -> range_field_b: uint8; + default -> unknown: bytestring &restofdata &check(0); + }; + # dump_data is always empty; used to check dependency bw object_type_field and qualifier_field + dump_data: case ( object_type_field & 0xff00 ) of { + 0x3C00 -> dump_3c: empty &check( (object_type_field == 0x3C01 || object_type_field == 0x3C02 || object_type_field == 0x3C03 || object_type_field == 0x3C04) && ( qualifier_field == 0x06 ) ); + default -> dump_def: empty; + }; +} + &let{ + number_of_item: int = case (qualifier_field & 0x0f) of { + 0 -> (range_field_0.stop_index - range_field_0.start_index + 1); + 1 -> (range_field_1.stop_index - range_field_1.start_index + 1); + 2 -> (range_field_2.stop_index - range_field_2.start_index + 1); + 7 -> range_field_7; + 8 -> ( range_field_8 & 0x0ff )* 0x100 + ( range_field_8 / 0x100 ) ; + 9 -> ( range_field_9 & 0x000000ff )* 0x1000000 + (range_field_9 & 0x0000ff00) * 0x100 + (range_field_9 & 0x00ff0000) / 0x100 + (range_field_9 & 0xff000000) / 0x1000000 ; + 0x0b -> range_field_b; + default -> 0; + }; + rf_value_low: int = case (qualifier_field & 0x0f) of { + 0 -> 0 + range_field_0.start_index; + 1 -> range_field_1.start_index; + 2 -> range_field_2.start_index; + 3 -> range_field_3.start_addr; + 4 -> range_field_4.start_addr; + 5 -> range_field_5.start_addr; + 6 -> 0xffff; + 7 -> range_field_7; + 8 -> range_field_8; + 9 -> range_field_9; + 0x0b -> range_field_b; + default -> 0 ; + }; + rf_value_high: int = case (qualifier_field & 0x0f) of { + 0 -> 0 + range_field_0.stop_index; + 1 -> range_field_1.stop_index; + 2 -> range_field_2.stop_index; + 3 -> range_field_3.stop_addr; + 4 -> range_field_4.stop_addr; + 5 -> range_field_5.stop_addr; + 6 -> 0xffff; + default -> 0 ; + }; +}; + +type Range_Field_0 = record { + start_index: uint8; + stop_index: uint8; +}; + +type Range_Field_1 = record { + start_index: uint16; + stop_index: uint16; +} + &byteorder = littleendian; + +type Range_Field_2 = record { + start_index: uint32; + stop_index: uint32; +} + &byteorder = littleendian; + +type Range_Field_3 = record { + start_addr: uint8; + stop_addr: uint8; +}; + +type Range_Field_4 = record { + start_addr: uint16; + stop_addr: uint16; +}; + +type Range_Field_5 = record { + start_addr: uint32; + stop_addr: uint32; +}; + +enum function_codes_value { + CONFIRM = 0x00, + READ = 0x01, + WRITE = 0x02, + SELECT = 0x03, + OPERATE = 0x04, + DIRECT_OPERATE = 0x05, + DIRECT_OPERATE_NR = 0x06, + IMMED_FREEZE = 0x07, + IMMED_FREEZE_NR = 0x08, + FREEZE_CLEAR = 0x09, + FREEZE_CLEAR_NR = 0x0a, + FREEZE_AT_TIME = 0x0b, + FREEZE_AT_TIME_NR = 0x0c, + COLD_RESTART = 0x0d, + WARM_RESTART = 0x0e, + INITIALIZE_DATA = 0x0f, + INITIALIZE_APPL = 0x10, + START_APPL = 0x11, + STOP_APPL = 0x12, + SAVE_CONFIG = 0x13, + ENABLE_UNSOLICITED = 0x14, + DISABLE_UNSOLICITED = 0x15, + ASSIGN_CLASS = 0x16, + DELAY_MEASURE = 0x17, + RECORD_CURRENT_TIME = 0x18, + OPEN_FILE = 0x19, + CLOSE_FILE = 0x1a, + DELETE_FILE = 0x1b, + GET_FILE_INFO = 0x1c, + AUTHENTICATE_FILE = 0x1d, + ABORT_FILE = 0x1e, + ACTIVATE_CONFIG = 0x1f, + AUTHENTICATE_REQ = 0x20, + AUTHENTICATE_ERR = 0x21, +# reserved + RESPONSE = 0x81, + UNSOLICITED_RESPONSE = 0x82, + AUTHENTICATE_RESP = 0x83, +# reserved +}; + +%include dnp3-objects.pac diff --git a/src/analyzer/protocol/dnp3/dnp3.pac b/src/analyzer/protocol/dnp3/dnp3.pac new file mode 100644 index 0000000000..57005fd8e1 --- /dev/null +++ b/src/analyzer/protocol/dnp3/dnp3.pac @@ -0,0 +1,16 @@ + +%include binpac.pac +%include bro.pac + +%extern{ +#include "events.bif.h" +%} + +analyzer DNP3 withcontext { + connection: DNP3_Conn; + flow: DNP3_Flow; +}; + +%include dnp3-protocol.pac +%include dnp3-analyzer.pac + diff --git a/src/analyzer/protocol/dnp3/events.bif b/src/analyzer/protocol/dnp3/events.bif new file mode 100644 index 0000000000..b537d2f8a5 --- /dev/null +++ b/src/analyzer/protocol/dnp3/events.bif @@ -0,0 +1,241 @@ + +### event handler that is used to analyze network packets based on DNP3 protocol +### starts with dnp3_ +### In src/DNP3.cc, we include detailed descriptions on how DNP3 Pseudo Link Layer, +### DNP3 Pseudo Transport Layer, DNP3 Pseudo Application Layer are packed into application +### layer payload over TCP +### The event handlers defined for binpac DNP3 analyzer are used to analyze fields +### of the DNP3 Pseudo Application Layer. +### we have tried our best to name the event handler by the field names that is described +### in DNP3 Specification Volum 2, Part 1 Basic, Application Layer, DNP3 Specification +### Volum 4, Data Link Layer, DNP3 Specification Volum 6, Part 1 Basic, DNP3 OBJECT LIBRARY, +### DNP3 Specification Volum 6, Part 2 Objects, DNP3 OBJECT LIBRARY + +event dnp3_debug_bufferBytes%(c: connection , is_orig: bool, buffer_bytes: count%); + + +## Generated for the request header in Pseudo Application Layer. +## The request header contains two fields: +## fc: function code. +event dnp3_application_request_header%(c: connection, is_orig: bool, fc: count%); + +## Generated for the response header in Pseudo Application Layer. +## The response header contains three fields: +## app_control: application control field. +## fc: function code. +## iin: internal indication number +event dnp3_application_response_header%(c: connection, is_orig: bool, fc: count, iin: count%); + +## Generated for the object header found in both DNP3 requests and responses +## obj_type: type of object, which is classified based on an 8-bit group number and an 8-bit variation number +## qua_field: qualifier field +## rf_low, rf_high: the structure of the range field depends on the qualified field. In some cases, range field +## contain only one logic part, e.g., number of objects, so only rf_low contains the useful values; in some +## cases, range field contain two logic parts, e.g., start index and stop index, so rf_low contains the start +## index while rf_high contains the stop index +event dnp3_object_header%(c: connection, is_orig: bool, obj_type: count, qua_field: count, number: count, rf_low: count, rf_high: count%); + +## Generated for the prefix before each object. +## the structure and the meaning of the prefix are defined by the qualifier field +event dnp3_object_prefix%(c: connection, is_orig: bool, prefix_value: count%); + +## Generated for the additional header that is added by the DNP3.cc; +## the reason to add this header is found in DNP3.cc +## start: the first two bytes of the DNP3 Pseudo Link Layer; its value is fixed as 0x0564 +## len: the "length" field in the DNP3 Pseudo Link Layer +## ctrl: the "control" field in the DNP3 Pseudo Link Layer +## dest_addr: the "destination" field in the DNP3 Pseudo Link Layer +## src_addr: the "source" field in the DNP3 Pseudo Link Layer +event dnp3_header_block%(c: connection, is_orig: bool, start: count, len: count, ctrl: count, dest_addr: count, src_addr: count%); + +## Generated for "Response_Data_Object" +## the "Response_Data_Object" contains two parts: object prefix and objects data. +## In most cases, objects data are defined by new record types. But in a few +## cases, objects data are directly basic types, such as int16, or int8; thus we use +## a additional data_value to record the values of those object data. +event dnp3_response_data_object%(c: connection, is_orig: bool, data_value: count%); + +## Different from most binpac scripts, which consists only two pac files: *-analyzer.pac +## and *-protocol.pac. I use a separate pac files, i.e., dnp3-objects.pac to contain +## different types of object data. +## The following event handlers are all generated for the different object data types. + +event dnp3_attribute_common%(c: connection, is_orig: bool, data_type_code: count, leng: count, attribute_obj: string%); + +## Generated for the object with the group number 12 and variation number 1 +## CROB: control relay output block +event dnp3_crob%(c: connection, is_orig: bool, control_code: count, count8: count, on_time: count, off_time: count, status_code: count%); + +## Generated for the object with the group number 12 and variation number 2 +## PCB: Pattern Control Block +event dnp3_pcb%(c: connection, is_orig: bool, control_code: count, count8: count, on_time: count, off_time: count, status_code: count%); + +## Generated for the object with the group number 20 and variation number 1 +## counter 32 bit with flag +event dnp3_counter_32wFlag%(c: connection, is_orig: bool, flag: count, count_value: count%); + +## Generated for the object with the group number 20 and variation number 2 +## counter 16 bit with flag +event dnp3_counter_16wFlag%(c: connection, is_orig: bool, flag: count, count_value: count%); + +## Generated for the object with the group number 20 and variation number 5 +## counter 32 bit without flag +event dnp3_counter_32woFlag%(c: connection, is_orig: bool, count_value: count%); + +## Generated for the object with the group number 20 and variation number 6 +## counter 16 bit without flag +event dnp3_counter_16woFlag%(c: connection, is_orig: bool, count_value: count%); + +## Generated for the object with the group number 21 and variation number 1 +## frozen counter 32 bit with flag +event dnp3_frozen_counter_32wFlag%(c: connection, is_orig: bool, flag:count, count_value: count%); + +## Generated for the object with the group number 21 and variation number 2 +## frozen counter 16 bit with flag +event dnp3_frozen_counter_16wFlag%(c: connection, is_orig: bool, flag:count, count_value: count%); + +## Generated for the object with the group number 21 and variation number 5 +## frozen counter 32 bit with flag and time +event dnp3_frozen_counter_32wFlagTime%(c: connection, is_orig: bool, flag:count, count_value: count, time48: string%); + +## Generated for the object with the group number 21 and variation number 6 +## frozen counter 16 bit with flag and time +event dnp3_frozen_counter_16wFlagTime%(c: connection, is_orig: bool, flag:count, count_value: count, time48: string%); + +## Generated for the object with the group number 21 and variation number 9 +## frozen counter 32 bit without flag +event dnp3_frozen_counter_32woFlag%(c: connection, is_orig: bool, count_value: count%); + +## Generated for the object with the group number 21 and variation number 10 +## frozen counter 16 bit without flag +event dnp3_frozen_counter_16woFlag%(c: connection, is_orig: bool, count_value: count%); + +## Generated for the object with the group number 30 and variation number 1 +## analog input 32 bit with flag +event dnp3_analog_input_32wFlag%(c: connection, is_orig: bool, flag: count, value: count%); + +## Generated for the object with the group number 30 and variation number 2 +## analog input 16 bit with flag +event dnp3_analog_input_16wFlag%(c: connection, is_orig: bool, flag: count, value: count%); + +## Generated for the object with the group number 30 and variation number 3 +## analog input 32 bit without flag +event dnp3_analog_input_32woFlag%(c: connection, is_orig: bool, value: count%); + +## Generated for the object with the group number 30 and variation number 4 +## analog input 16 bit without flag +event dnp3_analog_input_16woFlag%(c: connection, is_orig: bool, value: count%); + +## Generated for the object with the group number 30 and variation number 5 +## analog input single precision, float point with flag +event dnp3_analog_input_SPwFlag%(c: connection, is_orig: bool, flag: count, value: count%); + +## Generated for the object with the group number 30 and variation number 6 +## analog input double precision, float point with flag +event dnp3_analog_input_DPwFlag%(c: connection, is_orig: bool, flag: count, value_low: count, value_high: count%); + +## Generated for the object with the group number 31 and variation number 1 +## frozen analog input 32 bit with flag +event dnp3_frozen_analog_input_32wFlag%(c: connection, is_orig: bool, flag: count, frozen_value: count%); + +## Generated for the object with the group number 31 and variation number 2 +## frozen analog input 16 bit with flag +event dnp3_frozen_analog_input_16wFlag%(c: connection, is_orig: bool, flag: count, frozen_value: count%); + +## Generated for the object with the group number 31 and variation number 3 +## frozen analog input 32 bit with time-of-freeze +event dnp3_frozen_analog_input_32wTime%(c: connection, is_orig: bool, flag: count, frozen_value: count, time48: string%); + +## Generated for the object with the group number 31 and variation number 4 +## frozen analog input 16 bit with time-of-freeze +event dnp3_frozen_analog_input_16wTime%(c: connection, is_orig: bool, flag: count, frozen_value: count, time48: string%); + +## Generated for the object with the group number 31 and variation number 5 +## frozen analog input 32 bit without flag +event dnp3_frozen_analog_input_32woFlag%(c: connection, is_orig: bool, frozen_value: count%); + +## Generated for the object with the group number 31 and variation number 6 +## frozen analog input 16 bit without flag +event dnp3_frozen_analog_input_16woFlag%(c: connection, is_orig: bool, frozen_value: count%); + +## Generated for the object with the group number 31 and variation number 7 +## frozen analog input single-precision, float point with flag +event dnp3_frozen_analog_input_SPwFlag%(c: connection, is_orig: bool, flag: count, frozen_value: count%); + +## Generated for the object with the group number 31 and variation number 8 +## frozen analog input double-precision, float point with flag +event dnp3_frozen_analog_input_DPwFlag%(c: connection, is_orig: bool, flag: count, frozen_value_low: count, frozen_value_high: count%); + +## Generated for the object with the group number 32 and variation number 1 +## analog input event 32 bit without time +event dnp3_analog_input_event_32woTime%(c: connection, is_orig: bool, flag: count, value: count%); + +## Generated for the object with the group number 32 and variation number 2 +## analog input event 16 bit without time +event dnp3_analog_input_event_16woTime%(c: connection, is_orig: bool, flag: count, value: count%); + +## Generated for the object with the group number 32 and variation number 3 +## analog input event 32 bit with time +event dnp3_analog_input_event_32wTime%(c: connection, is_orig: bool, flag: count, value: count, time48: string%); + +## Generated for the object with the group number 32 and variation number 4 +## analog input event 16 bit with time +event dnp3_analog_input_event_16wTime%(c: connection, is_orig: bool, flag: count, value: count, time48: string%); + +## Generated for the object with the group number 32 and variation number 5 +## analog input event single-precision float point without time +event dnp3_analog_input_event_SPwoTime%(c: connection, is_orig: bool, flag: count, value: count%); + +## Generated for the object with the group number 32 and variation number 6 +## analog input event double-precision float point without time +event dnp3_analog_input_event_DPwoTime%(c: connection, is_orig: bool, flag: count, value_low: count, value_high: count%); + +## Generated for the object with the group number 32 and variation number 7 +## analog input event single-precision float point with time +event dnp3_analog_input_event_SPwTime%(c: connection, is_orig: bool, flag: count, value: count, time48: string%); + +## Generated for the object with the group number 32 and variation number 8 +## analog input event double-precisiion float point with time +event dnp3_analog_input_event_DPwTime%(c: connection, is_orig: bool, flag: count, value_low: count, value_high: count, time48: string%); + +## Generated for the object with the group number 33 and variation number 1 +## frozen analog input event 32 bit without time +event dnp3_frozen_analog_input_event_32woTime%(c: connection, is_orig: bool, flag: count, frozen_value: count%); + +## Generated for the object with the group number 33 and variation number 2 +## frozen analog input event 16 bit without time +event dnp3_frozen_analog_input_event_16woTime%(c: connection, is_orig: bool, flag: count, frozen_value: count%); + +## Generated for the object with the group number 33 and variation number 3 +## frozen analog input event 32 bit with time +event dnp3_frozen_analog_input_event_32wTime%(c: connection, is_orig: bool, flag: count, frozen_value: count, time48: string%); + +## Generated for the object with the group number 33 and variation number 4 +## frozen analog input event 16 bit with time +event dnp3_frozen_analog_input_event_16wTime%(c: connection, is_orig: bool, flag: count, frozen_value: count, time48: string%); + +## Generated for the object with the group number 33 and variation number 5 +## frozen analog input event single-precision float point without time +event dnp3_frozen_analog_input_event_SPwoTime%(c: connection, is_orig: bool, flag: count, frozen_value: count%); + +## Generated for the object with the group number 33 and variation number 6 +## frozen analog input event double-precision float point without time +event dnp3_frozen_analog_input_event_DPwoTime%(c: connection, is_orig: bool, flag: count, frozen_value_low: count, frozen_value_high: count%); + +## Generated for the object with the group number 33 and variation number 7 +## frozen analog input event single-precision float point with time +event dnp3_frozen_analog_input_event_SPwTime%(c: connection, is_orig: bool, flag: count, frozen_value: count, time48: string%); + +## Generated for the object with the group number 34 and variation number 8 +## frozen analog input event double-precision float point with time +event dnp3_frozen_analog_input_event_DPwTime%(c: connection, is_orig: bool, flag: count, frozen_value_low: count, frozen_value_high: count, time48: string%); + +## g70 +event dnp3_file_transport%(c: connection, is_orig: bool, file_handle: count, block_num: count, file_data: string%); + +## Generated for the "Debug_Byte" for the binpac analyzer +## This event handler is left for the debug usage. +## For example, in the binpac analyzer, a unknown "case" generated +## this event; the user can base on the debug the byte string to check +## what cause the malformed network packets +event dnp3_debug_byte%(c: connection, is_orig: bool, debug: string%); diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/coverage b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/coverage new file mode 100644 index 0000000000..62a0937c09 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/coverage @@ -0,0 +1 @@ +6 of 52 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/dnp3.log new file mode 100644 index 0000000000..2d702295dc --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/dnp3.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dnp3 +#open 2013-08-02-00-08-47 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin +#types time string addr port addr port string string count +1324503054.884183 UWkUyAuUGXf 130.126.142.250 49413 130.126.140.229 20000 DELAY_MEASURE RESPONSE 0 +#close 2013-08-02-00-08-47 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/output b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/output new file mode 100644 index 0000000000..5bd7d932bc --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/output @@ -0,0 +1,7 @@ +dnp3_header_block, T, 25605, 8, 196, 2, 3 +dnp3_application_request_header, T, 23 +dnp3_header_block, F, 25605, 16, 68, 3, 2 +dnp3_application_response_header, F, 129, 0 +dnp3_object_header, F, 13314, 7, 1, 1, 0 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 255 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/coverage b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/coverage new file mode 100644 index 0000000000..8535338ace --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/coverage @@ -0,0 +1 @@ +4 of 52 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/dnp3.log new file mode 100644 index 0000000000..58127c313d --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/dnp3.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dnp3 +#open 2013-08-02-00-08-48 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin +#types time string addr port addr port string string count +1324916729.150101 UWkUyAuUGXf 130.126.142.250 50059 130.126.140.229 20000 ENABLE_UNSOLICITED RESPONSE 0 +#close 2013-08-02-00-08-48 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/output b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/output new file mode 100644 index 0000000000..16491bb3a5 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/output @@ -0,0 +1,7 @@ +dnp3_header_block, T, 25605, 17, 196, 2, 3 +dnp3_application_request_header, T, 20 +dnp3_object_header, T, 15362, 6, 0, 65535, 65535 +dnp3_object_header, T, 15363, 6, 0, 65535, 65535 +dnp3_object_header, T, 15364, 6, 0, 65535, 65535 +dnp3_header_block, F, 25605, 10, 68, 3, 2 +dnp3_application_response_header, F, 129, 0 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/coverage b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/coverage new file mode 100644 index 0000000000..62a0937c09 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/coverage @@ -0,0 +1 @@ +6 of 52 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/dnp3.log new file mode 100644 index 0000000000..c60080fee0 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/dnp3.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dnp3 +#open 2013-08-02-00-08-48 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin +#types time string addr port addr port string string count +1325044377.992570 UWkUyAuUGXf 130.126.142.250 50301 130.126.140.229 20000 DELETE_FILE RESPONSE 0 +#close 2013-08-02-00-08-48 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/output b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/output new file mode 100644 index 0000000000..37ccbc5bc9 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/output @@ -0,0 +1,9 @@ +dnp3_header_block, T, 25605, 99, 196, 4, 3 +dnp3_application_request_header, T, 27 +dnp3_object_header, T, 17923, 91, 1, 1, 0 +dnp3_object_prefix, T, 85 +dnp3_header_block, F, 25605, 29, 68, 3, 4 +dnp3_application_response_header, F, 129, 0 +dnp3_object_header, F, 17924, 91, 1, 1, 0 +dnp3_object_prefix, F, 13 +dnp3_response_data_object, F, 255 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/coverage b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/coverage new file mode 100644 index 0000000000..c71c9033a1 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/coverage @@ -0,0 +1 @@ +9 of 52 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/dnp3.log new file mode 100644 index 0000000000..80cfa7caec --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/dnp3.log @@ -0,0 +1,14 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dnp3 +#open 2013-08-02-00-08-49 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin +#types time string addr port addr port string string count +1325036012.621691 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 OPEN_FILE RESPONSE 4096 +1325036016.729050 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 READ RESPONSE 4096 +1325036019.765502 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 WRITE RESPONSE 0 +1325036022.292689 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 WRITE RESPONSE 0 +1325036024.820857 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 CLOSE_FILE RESPONSE 0 +#close 2013-08-02-00-08-49 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/output b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/output new file mode 100644 index 0000000000..1a4971a9e3 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/output @@ -0,0 +1,45 @@ +dnp3_header_block, T, 25605, 50, 196, 4, 3 +dnp3_application_request_header, T, 25 +dnp3_object_header, T, 17923, 91, 1, 1, 0 +dnp3_object_prefix, T, 36 +dnp3_header_block, F, 25605, 29, 68, 3, 4 +dnp3_application_response_header, F, 129, 4096 +dnp3_object_header, F, 17924, 91, 1, 1, 0 +dnp3_object_prefix, F, 13 +dnp3_response_data_object, F, 255 +dnp3_header_block, T, 25605, 22, 196, 4, 3 +dnp3_application_request_header, T, 1 +dnp3_object_header, T, 17925, 91, 1, 1, 0 +dnp3_object_prefix, T, 8 +dnp3_file_transport, T, 305419896, 0 + ^J +dnp3_header_block, F, 25605, 255, 68, 3, 4 +dnp3_application_response_header, F, 129, 4096 +dnp3_object_header, F, 17925, 91, 1, 1, 0 +dnp3_object_prefix, F, 838 +dnp3_file_transport, F, 305419896, 2147483648 +0000 ef bb bf 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e .......^J0150 0d 0a 20 20 3c 21 2d 2d 44 6f 63 75 6d 65 6e 74 .. 0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, - PENDING_BYTE, 0, 1, 0))==0 ){ - /* Try 3 times to get the pending lock. This is needed to work - ** around problems caused by indexing and/or anti-virus software on - ** Windows systems. - ** If you are using this code as a model for alternative VFSes, do not - ** copy this retry logic. It is a hack intended for Windows only. - */ - OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n", - pFile->h, cnt, sqlite3ErrName(res))); - if( cnt ) sqlite3_win32_sleep(1); - } - gotPendingLock = res; - if( !res ){ - lastErrno = osGetLastError(); - } - } - - /* Acquire a shared lock - */ - if( locktype==SHARED_LOCK && res ){ - assert( pFile->locktype==NO_LOCK ); - res = getReadLock(pFile); - if( res ){ - newLocktype = SHARED_LOCK; - }else{ - lastErrno = osGetLastError(); - } - } - - /* Acquire a RESERVED lock - */ - if( locktype==RESERVED_LOCK && res ){ - assert( pFile->locktype==SHARED_LOCK ); - res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0); - if( res ){ - newLocktype = RESERVED_LOCK; - }else{ - lastErrno = osGetLastError(); - } - } - - /* Acquire a PENDING lock - */ - if( locktype==EXCLUSIVE_LOCK && res ){ - newLocktype = PENDING_LOCK; - gotPendingLock = 0; - } - - /* Acquire an EXCLUSIVE lock - */ - if( locktype==EXCLUSIVE_LOCK && res ){ - assert( pFile->locktype>=SHARED_LOCK ); - res = unlockReadLock(pFile); - res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, - SHARED_SIZE, 0); - if( res ){ - newLocktype = EXCLUSIVE_LOCK; - }else{ - lastErrno = osGetLastError(); - getReadLock(pFile); - } - } - - /* If we are holding a PENDING lock that ought to be released, then - ** release it now. - */ - if( gotPendingLock && locktype==SHARED_LOCK ){ - winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); - } - - /* Update the state of the lock has held in the file descriptor then - ** return the appropriate result code. - */ - if( res ){ - rc = SQLITE_OK; - }else{ - OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n", - pFile->h, locktype, newLocktype)); - pFile->lastErrno = lastErrno; - rc = SQLITE_BUSY; - } - pFile->locktype = (u8)newLocktype; - OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n", - pFile->h, pFile->locktype, sqlite3ErrName(rc))); - return rc; -} - -/* -** This routine checks if there is a RESERVED lock held on the specified -** file by this or any other process. If such a lock is held, return -** non-zero, otherwise zero. -*/ -static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ - int rc; - winFile *pFile = (winFile*)id; - - SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); - OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut)); - - assert( id!=0 ); - if( pFile->locktype>=RESERVED_LOCK ){ - rc = 1; - OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc)); - }else{ - rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0); - if( rc ){ - winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); - } - rc = !rc; - OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc)); - } - *pResOut = rc; - OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", - pFile->h, pResOut, *pResOut)); - return SQLITE_OK; -} - -/* -** Lower the locking level on file descriptor id to locktype. locktype -** must be either NO_LOCK or SHARED_LOCK. -** -** If the locking level of the file descriptor is already at or below -** the requested locking level, this routine is a no-op. -** -** It is not possible for this routine to fail if the second argument -** is NO_LOCK. If the second argument is SHARED_LOCK then this routine -** might return SQLITE_IOERR; -*/ -static int winUnlock(sqlite3_file *id, int locktype){ - int type; - winFile *pFile = (winFile*)id; - int rc = SQLITE_OK; - assert( pFile!=0 ); - assert( locktype<=SHARED_LOCK ); - OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n", - pFile->h, pFile->locktype, pFile->sharedLockByte, locktype)); - type = pFile->locktype; - if( type>=EXCLUSIVE_LOCK ){ - winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); - if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ - /* This should never happen. We should always be able to - ** reacquire the read lock */ - rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(), - "winUnlock", pFile->zPath); - } - } - if( type>=RESERVED_LOCK ){ - winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); - } - if( locktype==NO_LOCK && type>=SHARED_LOCK ){ - unlockReadLock(pFile); - } - if( type>=PENDING_LOCK ){ - winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); - } - pFile->locktype = (u8)locktype; - OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n", - pFile->h, pFile->locktype, sqlite3ErrName(rc))); - return rc; -} - -/* -** If *pArg is inititially negative then this is a query. Set *pArg to -** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. -** -** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. -*/ -static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){ - if( *pArg<0 ){ - *pArg = (pFile->ctrlFlags & mask)!=0; - }else if( (*pArg)==0 ){ - pFile->ctrlFlags &= ~mask; - }else{ - pFile->ctrlFlags |= mask; - } -} - -/* Forward declaration */ -static int getTempname(int nBuf, char *zBuf); - -/* -** Control and query of the open file handle. -*/ -static int winFileControl(sqlite3_file *id, int op, void *pArg){ - winFile *pFile = (winFile*)id; - OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg)); - switch( op ){ - case SQLITE_FCNTL_LOCKSTATE: { - *(int*)pArg = pFile->locktype; - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_LAST_ERRNO: { - *(int*)pArg = (int)pFile->lastErrno; - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_CHUNK_SIZE: { - pFile->szChunk = *(int *)pArg; - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_SIZE_HINT: { - if( pFile->szChunk>0 ){ - sqlite3_int64 oldSz; - int rc = winFileSize(id, &oldSz); - if( rc==SQLITE_OK ){ - sqlite3_int64 newSz = *(sqlite3_int64*)pArg; - if( newSz>oldSz ){ - SimulateIOErrorBenign(1); - rc = winTruncate(id, newSz); - SimulateIOErrorBenign(0); - } - } - OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); - return rc; - } - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_PERSIST_WAL: { - winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg); - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { - winModeBit(pFile, WINFILE_PSOW, (int*)pArg); - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_VFSNAME: { - *(char**)pArg = sqlite3_mprintf("win32"); - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_WIN32_AV_RETRY: { - int *a = (int*)pArg; - if( a[0]>0 ){ - win32IoerrRetry = a[0]; - }else{ - a[0] = win32IoerrRetry; - } - if( a[1]>0 ){ - win32IoerrRetryDelay = a[1]; - }else{ - a[1] = win32IoerrRetryDelay; - } - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } - case SQLITE_FCNTL_TEMPFILENAME: { - char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname ); - if( zTFile ){ - getTempname(pFile->pVfs->mxPathname, zTFile); - *(char**)pArg = zTFile; - } - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } -#if SQLITE_MAX_MMAP_SIZE>0 - case SQLITE_FCNTL_MMAP_SIZE: { - i64 newLimit = *(i64*)pArg; - if( newLimit>sqlite3GlobalConfig.mxMmap ){ - newLimit = sqlite3GlobalConfig.mxMmap; - } - *(i64*)pArg = pFile->mmapSizeMax; - if( newLimit>=0 ) pFile->mmapSizeMax = newLimit; - OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); - return SQLITE_OK; - } -#endif - } - OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); - return SQLITE_NOTFOUND; -} - -/* -** Return the sector size in bytes of the underlying block device for -** the specified file. This is almost always 512 bytes, but may be -** larger for some devices. -** -** SQLite code assumes this function cannot fail. It also assumes that -** if two files are created in the same file-system directory (i.e. -** a database and its journal file) that the sector size will be the -** same for both. -*/ -static int winSectorSize(sqlite3_file *id){ - (void)id; - return SQLITE_DEFAULT_SECTOR_SIZE; -} - -/* -** Return a vector of device characteristics. -*/ -static int winDeviceCharacteristics(sqlite3_file *id){ - winFile *p = (winFile*)id; - return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | - ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); -} - -/* -** Windows will only let you create file view mappings -** on allocation size granularity boundaries. -** During sqlite3_os_init() we do a GetSystemInfo() -** to get the granularity size. -*/ -SYSTEM_INFO winSysInfo; - -#ifndef SQLITE_OMIT_WAL - -/* -** Helper functions to obtain and relinquish the global mutex. The -** global mutex is used to protect the winLockInfo objects used by -** this file, all of which may be shared by multiple threads. -** -** Function winShmMutexHeld() is used to assert() that the global mutex -** is held when required. This function is only used as part of assert() -** statements. e.g. -** -** winShmEnterMutex() -** assert( winShmMutexHeld() ); -** winShmLeaveMutex() -*/ -static void winShmEnterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); -} -static void winShmLeaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); -} -#ifdef SQLITE_DEBUG -static int winShmMutexHeld(void) { - return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); -} -#endif - -/* -** Object used to represent a single file opened and mmapped to provide -** shared memory. When multiple threads all reference the same -** log-summary, each thread has its own winFile object, but they all -** point to a single instance of this object. In other words, each -** log-summary is opened only once per process. -** -** winShmMutexHeld() must be true when creating or destroying -** this object or while reading or writing the following fields: -** -** nRef -** pNext -** -** The following fields are read-only after the object is created: -** -** fid -** zFilename -** -** Either winShmNode.mutex must be held or winShmNode.nRef==0 and -** winShmMutexHeld() is true when reading or writing any other field -** in this structure. -** -*/ -struct winShmNode { - sqlite3_mutex *mutex; /* Mutex to access this object */ - char *zFilename; /* Name of the file */ - winFile hFile; /* File handle from winOpen */ - - int szRegion; /* Size of shared-memory regions */ - int nRegion; /* Size of array apRegion */ - struct ShmRegion { - HANDLE hMap; /* File handle from CreateFileMapping */ - void *pMap; - } *aRegion; - DWORD lastErrno; /* The Windows errno from the last I/O error */ - - int nRef; /* Number of winShm objects pointing to this */ - winShm *pFirst; /* All winShm objects pointing to this */ - winShmNode *pNext; /* Next in list of all winShmNode objects */ -#ifdef SQLITE_DEBUG - u8 nextShmId; /* Next available winShm.id value */ -#endif -}; - -/* -** A global array of all winShmNode objects. -** -** The winShmMutexHeld() must be true while reading or writing this list. -*/ -static winShmNode *winShmNodeList = 0; - -/* -** Structure used internally by this VFS to record the state of an -** open shared memory connection. -** -** The following fields are initialized when this object is created and -** are read-only thereafter: -** -** winShm.pShmNode -** winShm.id -** -** All other fields are read/write. The winShm.pShmNode->mutex must be held -** while accessing any read/write fields. -*/ -struct winShm { - winShmNode *pShmNode; /* The underlying winShmNode object */ - winShm *pNext; /* Next winShm with the same winShmNode */ - u8 hasMutex; /* True if holding the winShmNode mutex */ - u16 sharedMask; /* Mask of shared locks held */ - u16 exclMask; /* Mask of exclusive locks held */ -#ifdef SQLITE_DEBUG - u8 id; /* Id of this connection with its winShmNode */ -#endif -}; - -/* -** Constants used for locking -*/ -#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ -#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ - -/* -** Apply advisory locks for all n bytes beginning at ofst. -*/ -#define _SHM_UNLCK 1 -#define _SHM_RDLCK 2 -#define _SHM_WRLCK 3 -static int winShmSystemLock( - winShmNode *pFile, /* Apply locks to this open shared-memory segment */ - int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */ - int ofst, /* Offset to first byte to be locked/unlocked */ - int nByte /* Number of bytes to lock or unlock */ -){ - int rc = 0; /* Result code form Lock/UnlockFileEx() */ - - /* Access to the winShmNode object is serialized by the caller */ - assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); - - OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", - pFile->hFile.h, lockType, ofst, nByte)); - - /* Release/Acquire the system-level lock */ - if( lockType==_SHM_UNLCK ){ - rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0); - }else{ - /* Initialize the locking parameters */ - DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; - if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; - rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); - } - - if( rc!= 0 ){ - rc = SQLITE_OK; - }else{ - pFile->lastErrno = osGetLastError(); - rc = SQLITE_BUSY; - } - - OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n", - pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" : - "winLockFile", pFile->lastErrno, sqlite3ErrName(rc))); - - return rc; -} - -/* Forward references to VFS methods */ -static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); -static int winDelete(sqlite3_vfs *,const char*,int); - -/* -** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. -** -** This is not a VFS shared-memory method; it is a utility function called -** by VFS shared-memory methods. -*/ -static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ - winShmNode **pp; - winShmNode *p; - BOOL bRc; - assert( winShmMutexHeld() ); - OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n", - osGetCurrentProcessId(), deleteFlag)); - pp = &winShmNodeList; - while( (p = *pp)!=0 ){ - if( p->nRef==0 ){ - int i; - if( p->mutex ) sqlite3_mutex_free(p->mutex); - for(i=0; inRegion; i++){ - bRc = osUnmapViewOfFile(p->aRegion[i].pMap); - OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n", - osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); - bRc = osCloseHandle(p->aRegion[i].hMap); - OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n", - osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); - } - if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){ - SimulateIOErrorBenign(1); - winClose((sqlite3_file *)&p->hFile); - SimulateIOErrorBenign(0); - } - if( deleteFlag ){ - SimulateIOErrorBenign(1); - sqlite3BeginBenignMalloc(); - winDelete(pVfs, p->zFilename, 0); - sqlite3EndBenignMalloc(); - SimulateIOErrorBenign(0); - } - *pp = p->pNext; - sqlite3_free(p->aRegion); - sqlite3_free(p); - }else{ - pp = &p->pNext; - } - } -} - -/* -** Open the shared-memory area associated with database file pDbFd. -** -** When opening a new shared-memory file, if no other instances of that -** file are currently open, in this process or in other processes, then -** the file must be truncated to zero length or have its header cleared. -*/ -static int winOpenSharedMemory(winFile *pDbFd){ - struct winShm *p; /* The connection to be opened */ - struct winShmNode *pShmNode = 0; /* The underlying mmapped file */ - int rc; /* Result code */ - struct winShmNode *pNew; /* Newly allocated winShmNode */ - int nName; /* Size of zName in bytes */ - - assert( pDbFd->pShm==0 ); /* Not previously opened */ - - /* Allocate space for the new sqlite3_shm object. Also speculatively - ** allocate space for a new winShmNode and filename. - */ - p = sqlite3MallocZero( sizeof(*p) ); - if( p==0 ) return SQLITE_IOERR_NOMEM; - nName = sqlite3Strlen30(pDbFd->zPath); - pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 ); - if( pNew==0 ){ - sqlite3_free(p); - return SQLITE_IOERR_NOMEM; - } - pNew->zFilename = (char*)&pNew[1]; - sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); - sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); - - /* Look to see if there is an existing winShmNode that can be used. - ** If no matching winShmNode currently exists, create a new one. - */ - winShmEnterMutex(); - for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ - /* TBD need to come up with better match here. Perhaps - ** use FILE_ID_BOTH_DIR_INFO Structure. - */ - if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; - } - if( pShmNode ){ - sqlite3_free(pNew); - }else{ - pShmNode = pNew; - pNew = 0; - ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; - pShmNode->pNext = winShmNodeList; - winShmNodeList = pShmNode; - - pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->mutex==0 ){ - rc = SQLITE_IOERR_NOMEM; - goto shm_open_err; - } - - rc = winOpen(pDbFd->pVfs, - pShmNode->zFilename, /* Name of the file (UTF-8) */ - (sqlite3_file*)&pShmNode->hFile, /* File handle here */ - SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, - 0); - if( SQLITE_OK!=rc ){ - goto shm_open_err; - } - - /* Check to see if another process is holding the dead-man switch. - ** If not, truncate the file to zero length. - */ - if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ - rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); - if( rc!=SQLITE_OK ){ - rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), - "winOpenShm", pDbFd->zPath); - } - } - if( rc==SQLITE_OK ){ - winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); - rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); - } - if( rc ) goto shm_open_err; - } - - /* Make the new connection a child of the winShmNode */ - p->pShmNode = pShmNode; -#ifdef SQLITE_DEBUG - p->id = pShmNode->nextShmId++; -#endif - pShmNode->nRef++; - pDbFd->pShm = p; - winShmLeaveMutex(); - - /* The reference count on pShmNode has already been incremented under - ** the cover of the winShmEnterMutex() mutex and the pointer from the - ** new (struct winShm) object to the pShmNode has been set. All that is - ** left to do is to link the new object into the linked list starting - ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex - ** mutex. - */ - sqlite3_mutex_enter(pShmNode->mutex); - p->pNext = pShmNode->pFirst; - pShmNode->pFirst = p; - sqlite3_mutex_leave(pShmNode->mutex); - return SQLITE_OK; - - /* Jump here on any error */ -shm_open_err: - winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); - winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ - sqlite3_free(p); - sqlite3_free(pNew); - winShmLeaveMutex(); - return rc; -} - -/* -** Close a connection to shared-memory. Delete the underlying -** storage if deleteFlag is true. -*/ -static int winShmUnmap( - sqlite3_file *fd, /* Database holding shared memory */ - int deleteFlag /* Delete after closing if true */ -){ - winFile *pDbFd; /* Database holding shared-memory */ - winShm *p; /* The connection to be closed */ - winShmNode *pShmNode; /* The underlying shared-memory file */ - winShm **pp; /* For looping over sibling connections */ - - pDbFd = (winFile*)fd; - p = pDbFd->pShm; - if( p==0 ) return SQLITE_OK; - pShmNode = p->pShmNode; - - /* Remove connection p from the set of connections associated - ** with pShmNode */ - sqlite3_mutex_enter(pShmNode->mutex); - for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} - *pp = p->pNext; - - /* Free the connection p */ - sqlite3_free(p); - pDbFd->pShm = 0; - sqlite3_mutex_leave(pShmNode->mutex); - - /* If pShmNode->nRef has reached 0, then close the underlying - ** shared-memory file, too */ - winShmEnterMutex(); - assert( pShmNode->nRef>0 ); - pShmNode->nRef--; - if( pShmNode->nRef==0 ){ - winShmPurge(pDbFd->pVfs, deleteFlag); - } - winShmLeaveMutex(); - - return SQLITE_OK; -} - -/* -** Change the lock state for a shared-memory segment. -*/ -static int winShmLock( - sqlite3_file *fd, /* Database file holding the shared memory */ - int ofst, /* First lock to acquire or release */ - int n, /* Number of locks to acquire or release */ - int flags /* What to do with the lock */ -){ - winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ - winShm *p = pDbFd->pShm; /* The shared memory being locked */ - winShm *pX; /* For looping over all siblings */ - winShmNode *pShmNode = p->pShmNode; - int rc = SQLITE_OK; /* Result code */ - u16 mask; /* Mask of locks to take or release */ - - assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); - assert( n>=1 ); - assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) - || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) - || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) - || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); - assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); - - mask = (u16)((1U<<(ofst+n)) - (1U<1 || mask==(1<mutex); - if( flags & SQLITE_SHM_UNLOCK ){ - u16 allMask = 0; /* Mask of locks held by siblings */ - - /* See if any siblings hold this same lock */ - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ - if( pX==p ) continue; - assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); - allMask |= pX->sharedMask; - } - - /* Unlock the system-level locks */ - if( (mask & allMask)==0 ){ - rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n); - }else{ - rc = SQLITE_OK; - } - - /* Undo the local locks */ - if( rc==SQLITE_OK ){ - p->exclMask &= ~mask; - p->sharedMask &= ~mask; - } - }else if( flags & SQLITE_SHM_SHARED ){ - u16 allShared = 0; /* Union of locks held by connections other than "p" */ - - /* Find out which shared locks are already held by sibling connections. - ** If any sibling already holds an exclusive lock, go ahead and return - ** SQLITE_BUSY. - */ - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ - if( (pX->exclMask & mask)!=0 ){ - rc = SQLITE_BUSY; - break; - } - allShared |= pX->sharedMask; - } - - /* Get shared locks at the system level, if necessary */ - if( rc==SQLITE_OK ){ - if( (allShared & mask)==0 ){ - rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n); - }else{ - rc = SQLITE_OK; - } - } - - /* Get the local shared locks */ - if( rc==SQLITE_OK ){ - p->sharedMask |= mask; - } - }else{ - /* Make sure no sibling connections hold locks that will block this - ** lock. If any do, return SQLITE_BUSY right away. - */ - for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ - if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ - rc = SQLITE_BUSY; - break; - } - } - - /* Get the exclusive locks at the system level. Then if successful - ** also mark the local connection as being locked. - */ - if( rc==SQLITE_OK ){ - rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n); - if( rc==SQLITE_OK ){ - assert( (p->sharedMask & mask)==0 ); - p->exclMask |= mask; - } - } - } - sqlite3_mutex_leave(pShmNode->mutex); - OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n", - osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask, - sqlite3ErrName(rc))); - return rc; -} - -/* -** Implement a memory barrier or memory fence on shared memory. -** -** All loads and stores begun before the barrier must complete before -** any load or store begun after the barrier. -*/ -static void winShmBarrier( - sqlite3_file *fd /* Database holding the shared memory */ -){ - UNUSED_PARAMETER(fd); - /* MemoryBarrier(); // does not work -- do not know why not */ - winShmEnterMutex(); - winShmLeaveMutex(); -} - -/* -** This function is called to obtain a pointer to region iRegion of the -** shared-memory associated with the database file fd. Shared-memory regions -** are numbered starting from zero. Each shared-memory region is szRegion -** bytes in size. -** -** If an error occurs, an error code is returned and *pp is set to NULL. -** -** Otherwise, if the isWrite parameter is 0 and the requested shared-memory -** region has not been allocated (by any client, including one running in a -** separate process), then *pp is set to NULL and SQLITE_OK returned. If -** isWrite is non-zero and the requested shared-memory region has not yet -** been allocated, it is allocated by this function. -** -** If the shared-memory region has already been allocated or is allocated by -** this call as described above, then it is mapped into this processes -** address space (if it is not already), *pp is set to point to the mapped -** memory and SQLITE_OK returned. -*/ -static int winShmMap( - sqlite3_file *fd, /* Handle open on database file */ - int iRegion, /* Region to retrieve */ - int szRegion, /* Size of regions */ - int isWrite, /* True to extend file if necessary */ - void volatile **pp /* OUT: Mapped memory */ -){ - winFile *pDbFd = (winFile*)fd; - winShm *p = pDbFd->pShm; - winShmNode *pShmNode; - int rc = SQLITE_OK; - - if( !p ){ - rc = winOpenSharedMemory(pDbFd); - if( rc!=SQLITE_OK ) return rc; - p = pDbFd->pShm; - } - pShmNode = p->pShmNode; - - sqlite3_mutex_enter(pShmNode->mutex); - assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); - - if( pShmNode->nRegion<=iRegion ){ - struct ShmRegion *apNew; /* New aRegion[] array */ - int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ - sqlite3_int64 sz; /* Current size of wal-index file */ - - pShmNode->szRegion = szRegion; - - /* The requested region is not mapped into this processes address space. - ** Check to see if it has been allocated (i.e. if the wal-index file is - ** large enough to contain the requested region). - */ - rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz); - if( rc!=SQLITE_OK ){ - rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), - "winShmMap1", pDbFd->zPath); - goto shmpage_out; - } - - if( szhFile, nByte); - if( rc!=SQLITE_OK ){ - rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), - "winShmMap2", pDbFd->zPath); - goto shmpage_out; - } - } - - /* Map the requested memory region into this processes address space. */ - apNew = (struct ShmRegion *)sqlite3_realloc( - pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) - ); - if( !apNew ){ - rc = SQLITE_IOERR_NOMEM; - goto shmpage_out; - } - pShmNode->aRegion = apNew; - - while( pShmNode->nRegion<=iRegion ){ - HANDLE hMap = NULL; /* file-mapping handle */ - void *pMap = 0; /* Mapped memory region */ - -#if SQLITE_OS_WINRT - hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, - NULL, PAGE_READWRITE, nByte, NULL - ); -#elif defined(SQLITE_WIN32_HAS_WIDE) - hMap = osCreateFileMappingW(pShmNode->hFile.h, - NULL, PAGE_READWRITE, 0, nByte, NULL - ); -#elif defined(SQLITE_WIN32_HAS_ANSI) - hMap = osCreateFileMappingA(pShmNode->hFile.h, - NULL, PAGE_READWRITE, 0, nByte, NULL - ); -#endif - OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", - osGetCurrentProcessId(), pShmNode->nRegion, nByte, - hMap ? "ok" : "failed")); - if( hMap ){ - int iOffset = pShmNode->nRegion*szRegion; - int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; -#if SQLITE_OS_WINRT - pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ, - iOffset - iOffsetShift, szRegion + iOffsetShift - ); -#else - pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, - 0, iOffset - iOffsetShift, szRegion + iOffsetShift - ); -#endif - OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n", - osGetCurrentProcessId(), pShmNode->nRegion, iOffset, - szRegion, pMap ? "ok" : "failed")); - } - if( !pMap ){ - pShmNode->lastErrno = osGetLastError(); - rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno, - "winShmMap3", pDbFd->zPath); - if( hMap ) osCloseHandle(hMap); - goto shmpage_out; - } - - pShmNode->aRegion[pShmNode->nRegion].pMap = pMap; - pShmNode->aRegion[pShmNode->nRegion].hMap = hMap; - pShmNode->nRegion++; - } - } - -shmpage_out: - if( pShmNode->nRegion>iRegion ){ - int iOffset = iRegion*szRegion; - int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; - char *p = (char *)pShmNode->aRegion[iRegion].pMap; - *pp = (void *)&p[iOffsetShift]; - }else{ - *pp = 0; - } - sqlite3_mutex_leave(pShmNode->mutex); - return rc; -} - -#else -# define winShmMap 0 -# define winShmLock 0 -# define winShmBarrier 0 -# define winShmUnmap 0 -#endif /* #ifndef SQLITE_OMIT_WAL */ - -/* -** Cleans up the mapped region of the specified file, if any. -*/ -#if SQLITE_MAX_MMAP_SIZE>0 -static int winUnmapfile(winFile *pFile){ - assert( pFile!=0 ); - OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " - "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n", - osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, - pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax)); - if( pFile->pMapRegion ){ - if( !osUnmapViewOfFile(pFile->pMapRegion) ){ - pFile->lastErrno = osGetLastError(); - OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, " - "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile, - pFile->pMapRegion)); - return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, - "winUnmap1", pFile->zPath); - } - pFile->pMapRegion = 0; - pFile->mmapSize = 0; - pFile->mmapSizeActual = 0; - } - if( pFile->hMap!=NULL ){ - if( !osCloseHandle(pFile->hMap) ){ - pFile->lastErrno = osGetLastError(); - OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n", - osGetCurrentProcessId(), pFile, pFile->hMap)); - return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, - "winUnmap2", pFile->zPath); - } - pFile->hMap = NULL; - } - OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFile)); - return SQLITE_OK; -} - -/* -** Memory map or remap the file opened by file-descriptor pFd (if the file -** is already mapped, the existing mapping is replaced by the new). Or, if -** there already exists a mapping for this file, and there are still -** outstanding xFetch() references to it, this function is a no-op. -** -** If parameter nByte is non-negative, then it is the requested size of -** the mapping to create. Otherwise, if nByte is less than zero, then the -** requested size is the size of the file on disk. The actual size of the -** created mapping is either the requested size or the value configured -** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller. -** -** SQLITE_OK is returned if no error occurs (even if the mapping is not -** recreated as a result of outstanding references) or an SQLite error -** code otherwise. -*/ -static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ - sqlite3_int64 nMap = nByte; - int rc; - - assert( nMap>=0 || pFd->nFetchOut==0 ); - OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n", - osGetCurrentProcessId(), pFd, nByte)); - - if( pFd->nFetchOut>0 ) return SQLITE_OK; - - if( nMap<0 ){ - rc = winFileSize((sqlite3_file*)pFd, &nMap); - if( rc ){ - OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n", - osGetCurrentProcessId(), pFd)); - return SQLITE_IOERR_FSTAT; - } - } - if( nMap>pFd->mmapSizeMax ){ - nMap = pFd->mmapSizeMax; - } - nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1); - - if( nMap==0 && pFd->mmapSize>0 ){ - winUnmapfile(pFd); - } - if( nMap!=pFd->mmapSize ){ - void *pNew = 0; - DWORD protect = PAGE_READONLY; - DWORD flags = FILE_MAP_READ; - - winUnmapfile(pFd); - if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){ - protect = PAGE_READWRITE; - flags |= FILE_MAP_WRITE; - } -#if SQLITE_OS_WINRT - pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); -#elif defined(SQLITE_WIN32_HAS_WIDE) - pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, - (DWORD)((nMap>>32) & 0xffffffff), - (DWORD)(nMap & 0xffffffff), NULL); -#elif defined(SQLITE_WIN32_HAS_ANSI) - pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, - (DWORD)((nMap>>32) & 0xffffffff), - (DWORD)(nMap & 0xffffffff), NULL); -#endif - if( pFd->hMap==NULL ){ - pFd->lastErrno = osGetLastError(); - rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, - "winMapfile", pFd->zPath); - /* Log the error, but continue normal operation using xRead/xWrite */ - OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n", - osGetCurrentProcessId(), pFd)); - return SQLITE_OK; - } - assert( (nMap % winSysInfo.dwPageSize)==0 ); -#if SQLITE_OS_WINRT - pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap); -#else - assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff ); - pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap); -#endif - if( pNew==NULL ){ - osCloseHandle(pFd->hMap); - pFd->hMap = NULL; - pFd->lastErrno = osGetLastError(); - winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, - "winMapfile", pFd->zPath); - OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n", - osGetCurrentProcessId(), pFd)); - return SQLITE_OK; - } - pFd->pMapRegion = pNew; - pFd->mmapSize = nMap; - pFd->mmapSizeActual = nMap; - } - - OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), pFd)); - return SQLITE_OK; -} -#endif /* SQLITE_MAX_MMAP_SIZE>0 */ - -/* -** If possible, return a pointer to a mapping of file fd starting at offset -** iOff. The mapping must be valid for at least nAmt bytes. -** -** If such a pointer can be obtained, store it in *pp and return SQLITE_OK. -** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK. -** Finally, if an error does occur, return an SQLite error code. The final -** value of *pp is undefined in this case. -** -** If this function does return a pointer, the caller must eventually -** release the reference by calling winUnfetch(). -*/ -static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ -#if SQLITE_MAX_MMAP_SIZE>0 - winFile *pFd = (winFile*)fd; /* The underlying database file */ -#endif - *pp = 0; - - OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n", - osGetCurrentProcessId(), fd, iOff, nAmt, pp)); - -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFd->mmapSizeMax>0 ){ - if( pFd->pMapRegion==0 ){ - int rc = winMapfile(pFd, -1); - if( rc!=SQLITE_OK ){ - OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n", - osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); - return rc; - } - } - if( pFd->mmapSize >= iOff+nAmt ){ - *pp = &((u8 *)pFd->pMapRegion)[iOff]; - pFd->nFetchOut++; - } - } -#endif - - OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), fd, pp, *pp)); - return SQLITE_OK; -} - -/* -** If the third argument is non-NULL, then this function releases a -** reference obtained by an earlier call to winFetch(). The second -** argument passed to this function must be the same as the corresponding -** argument that was passed to the winFetch() invocation. -** -** Or, if the third argument is NULL, then this function is being called -** to inform the VFS layer that, according to POSIX, any existing mapping -** may now be invalid and should be unmapped. -*/ -static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){ -#if SQLITE_MAX_MMAP_SIZE>0 - winFile *pFd = (winFile*)fd; /* The underlying database file */ - - /* If p==0 (unmap the entire file) then there must be no outstanding - ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), - ** then there must be at least one outstanding. */ - assert( (p==0)==(pFd->nFetchOut==0) ); - - /* If p!=0, it must match the iOff value. */ - assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] ); - - OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n", - osGetCurrentProcessId(), pFd, iOff, p)); - - if( p ){ - pFd->nFetchOut--; - }else{ - /* FIXME: If Windows truly always prevents truncating or deleting a - ** file while a mapping is held, then the following winUnmapfile() call - ** is unnecessary can can be omitted - potentially improving - ** performance. */ - winUnmapfile(pFd); - } - - assert( pFd->nFetchOut>=0 ); -#endif - - OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n", - osGetCurrentProcessId(), fd)); - return SQLITE_OK; -} - -/* -** Here ends the implementation of all sqlite3_file methods. -** -********************** End sqlite3_file Methods ******************************* -******************************************************************************/ - -/* -** This vector defines all the methods that can operate on an -** sqlite3_file for win32. -*/ -static const sqlite3_io_methods winIoMethod = { - 3, /* iVersion */ - winClose, /* xClose */ - winRead, /* xRead */ - winWrite, /* xWrite */ - winTruncate, /* xTruncate */ - winSync, /* xSync */ - winFileSize, /* xFileSize */ - winLock, /* xLock */ - winUnlock, /* xUnlock */ - winCheckReservedLock, /* xCheckReservedLock */ - winFileControl, /* xFileControl */ - winSectorSize, /* xSectorSize */ - winDeviceCharacteristics, /* xDeviceCharacteristics */ - winShmMap, /* xShmMap */ - winShmLock, /* xShmLock */ - winShmBarrier, /* xShmBarrier */ - winShmUnmap, /* xShmUnmap */ - winFetch, /* xFetch */ - winUnfetch /* xUnfetch */ -}; - -/**************************************************************************** -**************************** sqlite3_vfs methods **************************** -** -** This division contains the implementation of methods on the -** sqlite3_vfs object. -*/ - -/* -** Convert a UTF-8 filename into whatever form the underlying -** operating system wants filenames in. Space to hold the result -** is obtained from malloc and must be freed by the calling -** function. -*/ -static void *convertUtf8Filename(const char *zFilename){ - void *zConverted = 0; - if( isNT() ){ - zConverted = utf8ToUnicode(zFilename); - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - zConverted = sqlite3_win32_utf8_to_mbcs(zFilename); - } -#endif - /* caller will handle out of memory */ - return zConverted; -} - -/* -** Create a temporary file name in zBuf. zBuf must be big enough to -** hold at pVfs->mxPathname characters. -*/ -static int getTempname(int nBuf, char *zBuf){ - static char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - size_t i, j; - int nTempPath; - char zTempPath[MAX_PATH+2]; - - /* It's odd to simulate an io-error here, but really this is just - ** using the io-error infrastructure to test that SQLite handles this - ** function failing. - */ - SimulateIOError( return SQLITE_IOERR ); - - memset(zTempPath, 0, MAX_PATH+2); - - if( sqlite3_temp_directory ){ - sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); - } -#if !SQLITE_OS_WINRT - else if( isNT() ){ - char *zMulti; - WCHAR zWidePath[MAX_PATH]; - osGetTempPathW(MAX_PATH-30, zWidePath); - zMulti = unicodeToUtf8(zWidePath); - if( zMulti ){ - sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); - sqlite3_free(zMulti); - }else{ - OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; - } - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - char *zUtf8; - char zMbcsPath[MAX_PATH]; - osGetTempPathA(MAX_PATH-30, zMbcsPath); - zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); - if( zUtf8 ){ - sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); - sqlite3_free(zUtf8); - }else{ - OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); - return SQLITE_IOERR_NOMEM; - } - } -#endif -#endif - - /* Check that the output buffer is large enough for the temporary file - ** name. If it is not, return SQLITE_ERROR. - */ - nTempPath = sqlite3Strlen30(zTempPath); - - if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){ - OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); - return SQLITE_ERROR; - } - - for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){} - zTempPath[i] = 0; - - sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ? - "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX, - zTempPath); - j = sqlite3Strlen30(zBuf); - sqlite3_randomness(15, &zBuf[j]); - for(i=0; i<15; i++, j++){ - zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; - } - zBuf[j] = 0; - zBuf[j+1] = 0; - - OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf)); - return SQLITE_OK; -} - -/* -** Return TRUE if the named file is really a directory. Return false if -** it is something other than a directory, or if there is any kind of memory -** allocation failure. -*/ -static int winIsDir(const void *zConverted){ - DWORD attr; - int rc = 0; - DWORD lastErrno; - - if( isNT() ){ - int cnt = 0; - WIN32_FILE_ATTRIBUTE_DATA sAttrData; - memset(&sAttrData, 0, sizeof(sAttrData)); - while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, - GetFileExInfoStandard, - &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){} - if( !rc ){ - return 0; /* Invalid name? */ - } - attr = sAttrData.dwFileAttributes; -#if SQLITE_OS_WINCE==0 - }else{ - attr = osGetFileAttributesA((char*)zConverted); -#endif - } - return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY); -} - -/* -** Open a file. -*/ -static int winOpen( - sqlite3_vfs *pVfs, /* Not used */ - const char *zName, /* Name of the file (UTF-8) */ - sqlite3_file *id, /* Write the SQLite file handle here */ - int flags, /* Open mode flags */ - int *pOutFlags /* Status return flags */ -){ - HANDLE h; - DWORD lastErrno; - DWORD dwDesiredAccess; - DWORD dwShareMode; - DWORD dwCreationDisposition; - DWORD dwFlagsAndAttributes = 0; -#if SQLITE_OS_WINCE - int isTemp = 0; -#endif - winFile *pFile = (winFile*)id; - void *zConverted; /* Filename in OS encoding */ - const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ - int cnt = 0; - - /* If argument zPath is a NULL pointer, this function is required to open - ** a temporary file. Use this buffer to store the file name in. - */ - char zTmpname[MAX_PATH+2]; /* Buffer used to create temp filename */ - - int rc = SQLITE_OK; /* Function Return Code */ -#if !defined(NDEBUG) || SQLITE_OS_WINCE - int eType = flags&0xFFFFFF00; /* Type of file to open */ -#endif - - int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); - int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); - int isCreate = (flags & SQLITE_OPEN_CREATE); - int isReadonly = (flags & SQLITE_OPEN_READONLY); - int isReadWrite = (flags & SQLITE_OPEN_READWRITE); - -#ifndef NDEBUG - int isOpenJournal = (isCreate && ( - eType==SQLITE_OPEN_MASTER_JOURNAL - || eType==SQLITE_OPEN_MAIN_JOURNAL - || eType==SQLITE_OPEN_WAL - )); -#endif - - OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n", - zUtf8Name, id, flags, pOutFlags)); - - /* Check the following statements are true: - ** - ** (a) Exactly one of the READWRITE and READONLY flags must be set, and - ** (b) if CREATE is set, then READWRITE must also be set, and - ** (c) if EXCLUSIVE is set, then CREATE must also be set. - ** (d) if DELETEONCLOSE is set, then CREATE must also be set. - */ - assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); - assert(isCreate==0 || isReadWrite); - assert(isExclusive==0 || isCreate); - assert(isDelete==0 || isCreate); - - /* The main DB, main journal, WAL file and master journal are never - ** automatically deleted. Nor are they ever temporary files. */ - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); - assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); - - /* Assert that the upper layer has set one of the "file-type" flags. */ - assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB - || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL - || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL - || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL - ); - - assert( pFile!=0 ); - memset(pFile, 0, sizeof(winFile)); - pFile->h = INVALID_HANDLE_VALUE; - -#if SQLITE_OS_WINRT - if( !sqlite3_temp_directory ){ - sqlite3_log(SQLITE_ERROR, - "sqlite3_temp_directory variable should be set for WinRT"); - } -#endif - - /* If the second argument to this function is NULL, generate a - ** temporary file name to use - */ - if( !zUtf8Name ){ - assert(isDelete && !isOpenJournal); - memset(zTmpname, 0, MAX_PATH+2); - rc = getTempname(MAX_PATH+2, zTmpname); - if( rc!=SQLITE_OK ){ - OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc))); - return rc; - } - zUtf8Name = zTmpname; - } - - /* Database filenames are double-zero terminated if they are not - ** URIs with parameters. Hence, they can always be passed into - ** sqlite3_uri_parameter(). - */ - assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || - zUtf8Name[strlen(zUtf8Name)+1]==0 ); - - /* Convert the filename to the system encoding. */ - zConverted = convertUtf8Filename(zUtf8Name); - if( zConverted==0 ){ - OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name)); - return SQLITE_IOERR_NOMEM; - } - - if( winIsDir(zConverted) ){ - sqlite3_free(zConverted); - OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name)); - return SQLITE_CANTOPEN_ISDIR; - } - - if( isReadWrite ){ - dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; - }else{ - dwDesiredAccess = GENERIC_READ; - } - - /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is - ** created. SQLite doesn't use it to indicate "exclusive access" - ** as it is usually understood. - */ - if( isExclusive ){ - /* Creates a new file, only if it does not already exist. */ - /* If the file exists, it fails. */ - dwCreationDisposition = CREATE_NEW; - }else if( isCreate ){ - /* Open existing file, or create if it doesn't exist */ - dwCreationDisposition = OPEN_ALWAYS; - }else{ - /* Opens a file, only if it exists. */ - dwCreationDisposition = OPEN_EXISTING; - } - - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - - if( isDelete ){ -#if SQLITE_OS_WINCE - dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; - isTemp = 1; -#else - dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY - | FILE_ATTRIBUTE_HIDDEN - | FILE_FLAG_DELETE_ON_CLOSE; -#endif - }else{ - dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; - } - /* Reports from the internet are that performance is always - ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ -#if SQLITE_OS_WINCE - dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; -#endif - - if( isNT() ){ -#if SQLITE_OS_WINRT - CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; - extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); - extendedParameters.dwFileAttributes = - dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK; - extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK; - extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; - extendedParameters.lpSecurityAttributes = NULL; - extendedParameters.hTemplateFile = NULL; - while( (h = osCreateFile2((LPCWSTR)zConverted, - dwDesiredAccess, - dwShareMode, - dwCreationDisposition, - &extendedParameters))==INVALID_HANDLE_VALUE && - retryIoerr(&cnt, &lastErrno) ){ - /* Noop */ - } -#else - while( (h = osCreateFileW((LPCWSTR)zConverted, - dwDesiredAccess, - dwShareMode, NULL, - dwCreationDisposition, - dwFlagsAndAttributes, - NULL))==INVALID_HANDLE_VALUE && - retryIoerr(&cnt, &lastErrno) ){ - /* Noop */ - } -#endif - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - while( (h = osCreateFileA((LPCSTR)zConverted, - dwDesiredAccess, - dwShareMode, NULL, - dwCreationDisposition, - dwFlagsAndAttributes, - NULL))==INVALID_HANDLE_VALUE && - retryIoerr(&cnt, &lastErrno) ){ - /* Noop */ - } - } -#endif - logIoerr(cnt); - - OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name, - dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); - - if( h==INVALID_HANDLE_VALUE ){ - pFile->lastErrno = lastErrno; - winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); - sqlite3_free(zConverted); - if( isReadWrite && !isExclusive ){ - return winOpen(pVfs, zName, id, - ((flags|SQLITE_OPEN_READONLY) & - ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), - pOutFlags); - }else{ - return SQLITE_CANTOPEN_BKPT; - } - } - - if( pOutFlags ){ - if( isReadWrite ){ - *pOutFlags = SQLITE_OPEN_READWRITE; - }else{ - *pOutFlags = SQLITE_OPEN_READONLY; - } - } - - OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, " - "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ? - *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); - -#if SQLITE_OS_WINCE - if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB - && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK - ){ - osCloseHandle(h); - sqlite3_free(zConverted); - OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc))); - return rc; - } - if( isTemp ){ - pFile->zDeleteOnClose = zConverted; - }else -#endif - { - sqlite3_free(zConverted); - } - - pFile->pMethod = &winIoMethod; - pFile->pVfs = pVfs; - pFile->h = h; - if( isReadonly ){ - pFile->ctrlFlags |= WINFILE_RDONLY; - } - if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ - pFile->ctrlFlags |= WINFILE_PSOW; - } - pFile->lastErrno = NO_ERROR; - pFile->zPath = zName; -#if SQLITE_MAX_MMAP_SIZE>0 - pFile->hMap = NULL; - pFile->pMapRegion = 0; - pFile->mmapSize = 0; - pFile->mmapSizeActual = 0; - pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; -#endif - - OpenCounter(+1); - return rc; -} - -/* -** Delete the named file. -** -** Note that Windows does not allow a file to be deleted if some other -** process has it open. Sometimes a virus scanner or indexing program -** will open a journal file shortly after it is created in order to do -** whatever it does. While this other process is holding the -** file open, we will be unable to delete it. To work around this -** problem, we delay 100 milliseconds and try to delete again. Up -** to MX_DELETION_ATTEMPTs deletion attempts are run before giving -** up and returning an error. -*/ -static int winDelete( - sqlite3_vfs *pVfs, /* Not used on win32 */ - const char *zFilename, /* Name of file to delete */ - int syncDir /* Not used on win32 */ -){ - int cnt = 0; - int rc; - DWORD attr; - DWORD lastErrno; - void *zConverted; - UNUSED_PARAMETER(pVfs); - UNUSED_PARAMETER(syncDir); - - SimulateIOError(return SQLITE_IOERR_DELETE); - OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir)); - - zConverted = convertUtf8Filename(zFilename); - if( zConverted==0 ){ - return SQLITE_IOERR_NOMEM; - } - if( isNT() ){ - do { -#if SQLITE_OS_WINRT - WIN32_FILE_ATTRIBUTE_DATA sAttrData; - memset(&sAttrData, 0, sizeof(sAttrData)); - if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, - &sAttrData) ){ - attr = sAttrData.dwFileAttributes; - }else{ - lastErrno = osGetLastError(); - if( lastErrno==ERROR_FILE_NOT_FOUND - || lastErrno==ERROR_PATH_NOT_FOUND ){ - rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ - }else{ - rc = SQLITE_ERROR; - } - break; - } -#else - attr = osGetFileAttributesW(zConverted); -#endif - if ( attr==INVALID_FILE_ATTRIBUTES ){ - lastErrno = osGetLastError(); - if( lastErrno==ERROR_FILE_NOT_FOUND - || lastErrno==ERROR_PATH_NOT_FOUND ){ - rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ - }else{ - rc = SQLITE_ERROR; - } - break; - } - if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ - rc = SQLITE_ERROR; /* Files only. */ - break; - } - if ( osDeleteFileW(zConverted) ){ - rc = SQLITE_OK; /* Deleted OK. */ - break; - } - if ( !retryIoerr(&cnt, &lastErrno) ){ - rc = SQLITE_ERROR; /* No more retries. */ - break; - } - } while(1); - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - do { - attr = osGetFileAttributesA(zConverted); - if ( attr==INVALID_FILE_ATTRIBUTES ){ - lastErrno = osGetLastError(); - if( lastErrno==ERROR_FILE_NOT_FOUND - || lastErrno==ERROR_PATH_NOT_FOUND ){ - rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ - }else{ - rc = SQLITE_ERROR; - } - break; - } - if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ - rc = SQLITE_ERROR; /* Files only. */ - break; - } - if ( osDeleteFileA(zConverted) ){ - rc = SQLITE_OK; /* Deleted OK. */ - break; - } - if ( !retryIoerr(&cnt, &lastErrno) ){ - rc = SQLITE_ERROR; /* No more retries. */ - break; - } - } while(1); - } -#endif - if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ - rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, - "winDelete", zFilename); - }else{ - logIoerr(cnt); - } - sqlite3_free(zConverted); - OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc))); - return rc; -} - -/* -** Check the existence and status of a file. -*/ -static int winAccess( - sqlite3_vfs *pVfs, /* Not used on win32 */ - const char *zFilename, /* Name of file to check */ - int flags, /* Type of test to make on this file */ - int *pResOut /* OUT: Result */ -){ - DWORD attr; - int rc = 0; - DWORD lastErrno; - void *zConverted; - UNUSED_PARAMETER(pVfs); - - SimulateIOError( return SQLITE_IOERR_ACCESS; ); - OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", - zFilename, flags, pResOut)); - - zConverted = convertUtf8Filename(zFilename); - if( zConverted==0 ){ - OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); - return SQLITE_IOERR_NOMEM; - } - if( isNT() ){ - int cnt = 0; - WIN32_FILE_ATTRIBUTE_DATA sAttrData; - memset(&sAttrData, 0, sizeof(sAttrData)); - while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, - GetFileExInfoStandard, - &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){} - if( rc ){ - /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file - ** as if it does not exist. - */ - if( flags==SQLITE_ACCESS_EXISTS - && sAttrData.nFileSizeHigh==0 - && sAttrData.nFileSizeLow==0 ){ - attr = INVALID_FILE_ATTRIBUTES; - }else{ - attr = sAttrData.dwFileAttributes; - } - }else{ - logIoerr(cnt); - if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ - winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename); - sqlite3_free(zConverted); - return SQLITE_IOERR_ACCESS; - }else{ - attr = INVALID_FILE_ATTRIBUTES; - } - } - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - attr = osGetFileAttributesA((char*)zConverted); - } -#endif - sqlite3_free(zConverted); - switch( flags ){ - case SQLITE_ACCESS_READ: - case SQLITE_ACCESS_EXISTS: - rc = attr!=INVALID_FILE_ATTRIBUTES; - break; - case SQLITE_ACCESS_READWRITE: - rc = attr!=INVALID_FILE_ATTRIBUTES && - (attr & FILE_ATTRIBUTE_READONLY)==0; - break; - default: - assert(!"Invalid flags argument"); - } - *pResOut = rc; - OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", - zFilename, pResOut, *pResOut)); - return SQLITE_OK; -} - - -/* -** Returns non-zero if the specified path name should be used verbatim. If -** non-zero is returned from this function, the calling function must simply -** use the provided path name verbatim -OR- resolve it into a full path name -** using the GetFullPathName Win32 API function (if available). -*/ -static BOOL winIsVerbatimPathname( - const char *zPathname -){ - /* - ** If the path name starts with a forward slash or a backslash, it is either - ** a legal UNC name, a volume relative path, or an absolute path name in the - ** "Unix" format on Windows. There is no easy way to differentiate between - ** the final two cases; therefore, we return the safer return value of TRUE - ** so that callers of this function will simply use it verbatim. - */ - if ( zPathname[0]=='/' || zPathname[0]=='\\' ){ - return TRUE; - } - - /* - ** If the path name starts with a letter and a colon it is either a volume - ** relative path or an absolute path. Callers of this function must not - ** attempt to treat it as a relative path name (i.e. they should simply use - ** it verbatim). - */ - if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){ - return TRUE; - } - - /* - ** If we get to this point, the path name should almost certainly be a purely - ** relative one (i.e. not a UNC name, not absolute, and not volume relative). - */ - return FALSE; -} - -/* -** Turn a relative pathname into a full pathname. Write the full -** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname -** bytes in size. -*/ -static int winFullPathname( - sqlite3_vfs *pVfs, /* Pointer to vfs object */ - const char *zRelative, /* Possibly relative input path */ - int nFull, /* Size of output buffer in bytes */ - char *zFull /* Output buffer */ -){ - -#if defined(__CYGWIN__) - SimulateIOError( return SQLITE_ERROR ); - UNUSED_PARAMETER(nFull); - assert( pVfs->mxPathname>=MAX_PATH ); - assert( nFull>=pVfs->mxPathname ); - if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ - /* - ** NOTE: We are dealing with a relative path name and the data - ** directory has been set. Therefore, use it as the basis - ** for converting the relative path name to an absolute - ** one by prepending the data directory and a slash. - */ - char zOut[MAX_PATH+1]; - memset(zOut, 0, MAX_PATH+1); - cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut, - MAX_PATH+1); - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s", - sqlite3_data_directory, zOut); - }else{ - cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull); - } - return SQLITE_OK; -#endif - -#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__) - SimulateIOError( return SQLITE_ERROR ); - /* WinCE has no concept of a relative pathname, or so I am told. */ - /* WinRT has no way to convert a relative path to an absolute one. */ - if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ - /* - ** NOTE: We are dealing with a relative path name and the data - ** directory has been set. Therefore, use it as the basis - ** for converting the relative path name to an absolute - ** one by prepending the data directory and a backslash. - */ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s", - sqlite3_data_directory, zRelative); - }else{ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative); - } - return SQLITE_OK; -#endif - -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) - DWORD nByte; - void *zConverted; - char *zOut; - - /* If this path name begins with "/X:", where "X" is any alphabetic - ** character, discard the initial "/" from the pathname. - */ - if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){ - zRelative++; - } - - /* It's odd to simulate an io-error here, but really this is just - ** using the io-error infrastructure to test that SQLite handles this - ** function failing. This function could fail if, for example, the - ** current working directory has been unlinked. - */ - SimulateIOError( return SQLITE_ERROR ); - if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ - /* - ** NOTE: We are dealing with a relative path name and the data - ** directory has been set. Therefore, use it as the basis - ** for converting the relative path name to an absolute - ** one by prepending the data directory and a backslash. - */ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s", - sqlite3_data_directory, zRelative); - return SQLITE_OK; - } - zConverted = convertUtf8Filename(zRelative); - if( zConverted==0 ){ - return SQLITE_IOERR_NOMEM; - } - if( isNT() ){ - LPWSTR zTemp; - nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0); - if( nByte==0 ){ - winLogError(SQLITE_ERROR, osGetLastError(), - "GetFullPathNameW1", zConverted); - sqlite3_free(zConverted); - return SQLITE_CANTOPEN_FULLPATH; - } - nByte += 3; - zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); - if( zTemp==0 ){ - sqlite3_free(zConverted); - return SQLITE_IOERR_NOMEM; - } - nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0); - if( nByte==0 ){ - winLogError(SQLITE_ERROR, osGetLastError(), - "GetFullPathNameW2", zConverted); - sqlite3_free(zConverted); - sqlite3_free(zTemp); - return SQLITE_CANTOPEN_FULLPATH; - } - sqlite3_free(zConverted); - zOut = unicodeToUtf8(zTemp); - sqlite3_free(zTemp); - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - char *zTemp; - nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0); - if( nByte==0 ){ - winLogError(SQLITE_ERROR, osGetLastError(), - "GetFullPathNameA1", zConverted); - sqlite3_free(zConverted); - return SQLITE_CANTOPEN_FULLPATH; - } - nByte += 3; - zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); - if( zTemp==0 ){ - sqlite3_free(zConverted); - return SQLITE_IOERR_NOMEM; - } - nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0); - if( nByte==0 ){ - winLogError(SQLITE_ERROR, osGetLastError(), - "GetFullPathNameA2", zConverted); - sqlite3_free(zConverted); - sqlite3_free(zTemp); - return SQLITE_CANTOPEN_FULLPATH; - } - sqlite3_free(zConverted); - zOut = sqlite3_win32_mbcs_to_utf8(zTemp); - sqlite3_free(zTemp); - } -#endif - if( zOut ){ - sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); - sqlite3_free(zOut); - return SQLITE_OK; - }else{ - return SQLITE_IOERR_NOMEM; - } -#endif -} - -#ifndef SQLITE_OMIT_LOAD_EXTENSION -/* -** Interfaces for opening a shared library, finding entry points -** within the shared library, and closing the shared library. -*/ -/* -** Interfaces for opening a shared library, finding entry points -** within the shared library, and closing the shared library. -*/ -static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ - HANDLE h; - void *zConverted = convertUtf8Filename(zFilename); - UNUSED_PARAMETER(pVfs); - if( zConverted==0 ){ - return 0; - } - if( isNT() ){ -#if SQLITE_OS_WINRT - h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0); -#else - h = osLoadLibraryW((LPCWSTR)zConverted); -#endif - } -#ifdef SQLITE_WIN32_HAS_ANSI - else{ - h = osLoadLibraryA((char*)zConverted); - } -#endif - sqlite3_free(zConverted); - return (void*)h; -} -static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ - UNUSED_PARAMETER(pVfs); - getLastErrorMsg(osGetLastError(), nBuf, zBufOut); -} -static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){ - UNUSED_PARAMETER(pVfs); - return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym); -} -static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ - UNUSED_PARAMETER(pVfs); - osFreeLibrary((HANDLE)pHandle); -} -#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ - #define winDlOpen 0 - #define winDlError 0 - #define winDlSym 0 - #define winDlClose 0 -#endif - - -/* -** Write up to nBuf bytes of randomness into zBuf. -*/ -static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ - int n = 0; - UNUSED_PARAMETER(pVfs); -#if defined(SQLITE_TEST) - n = nBuf; - memset(zBuf, 0, nBuf); -#else - if( sizeof(SYSTEMTIME)<=nBuf-n ){ - SYSTEMTIME x; - osGetSystemTime(&x); - memcpy(&zBuf[n], &x, sizeof(x)); - n += sizeof(x); - } - if( sizeof(DWORD)<=nBuf-n ){ - DWORD pid = osGetCurrentProcessId(); - memcpy(&zBuf[n], &pid, sizeof(pid)); - n += sizeof(pid); - } -#if SQLITE_OS_WINRT - if( sizeof(ULONGLONG)<=nBuf-n ){ - ULONGLONG cnt = osGetTickCount64(); - memcpy(&zBuf[n], &cnt, sizeof(cnt)); - n += sizeof(cnt); - } -#else - if( sizeof(DWORD)<=nBuf-n ){ - DWORD cnt = osGetTickCount(); - memcpy(&zBuf[n], &cnt, sizeof(cnt)); - n += sizeof(cnt); - } -#endif - if( sizeof(LARGE_INTEGER)<=nBuf-n ){ - LARGE_INTEGER i; - osQueryPerformanceCounter(&i); - memcpy(&zBuf[n], &i, sizeof(i)); - n += sizeof(i); - } -#endif - return n; -} - - -/* -** Sleep for a little while. Return the amount of time slept. -*/ -static int winSleep(sqlite3_vfs *pVfs, int microsec){ - sqlite3_win32_sleep((microsec+999)/1000); - UNUSED_PARAMETER(pVfs); - return ((microsec+999)/1000)*1000; -} - -/* -** The following variable, if set to a non-zero value, is interpreted as -** the number of seconds since 1970 and is used to set the result of -** sqlite3OsCurrentTime() during testing. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ -#endif - -/* -** Find the current time (in Universal Coordinated Time). Write into *piNow -** the current time and date as a Julian Day number times 86_400_000. In -** other words, write into *piNow the number of milliseconds since the Julian -** epoch of noon in Greenwich on November 24, 4714 B.C according to the -** proleptic Gregorian calendar. -** -** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date -** cannot be found. -*/ -static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ - /* FILETIME structure is a 64-bit value representing the number of - 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). - */ - FILETIME ft; - static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; -#ifdef SQLITE_TEST - static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; -#endif - /* 2^32 - to avoid use of LL and warnings in gcc */ - static const sqlite3_int64 max32BitValue = - (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + - (sqlite3_int64)294967296; - -#if SQLITE_OS_WINCE - SYSTEMTIME time; - osGetSystemTime(&time); - /* if SystemTimeToFileTime() fails, it returns zero. */ - if (!osSystemTimeToFileTime(&time,&ft)){ - return SQLITE_ERROR; - } -#else - osGetSystemTimeAsFileTime( &ft ); -#endif - - *piNow = winFiletimeEpoch + - ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + - (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000; - -#ifdef SQLITE_TEST - if( sqlite3_current_time ){ - *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch; - } -#endif - UNUSED_PARAMETER(pVfs); - return SQLITE_OK; -} - -/* -** Find the current time (in Universal Coordinated Time). Write the -** current time and date as a Julian Day number into *prNow and -** return 0. Return 1 if the time and date cannot be found. -*/ -static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ - int rc; - sqlite3_int64 i; - rc = winCurrentTimeInt64(pVfs, &i); - if( !rc ){ - *prNow = i/86400000.0; - } - return rc; -} - -/* -** The idea is that this function works like a combination of -** GetLastError() and FormatMessage() on Windows (or errno and -** strerror_r() on Unix). After an error is returned by an OS -** function, SQLite calls this function with zBuf pointing to -** a buffer of nBuf bytes. The OS layer should populate the -** buffer with a nul-terminated UTF-8 encoded error message -** describing the last IO error to have occurred within the calling -** thread. -** -** If the error message is too large for the supplied buffer, -** it should be truncated. The return value of xGetLastError -** is zero if the error message fits in the buffer, or non-zero -** otherwise (if the message was truncated). If non-zero is returned, -** then it is not necessary to include the nul-terminator character -** in the output buffer. -** -** Not supplying an error message will have no adverse effect -** on SQLite. It is fine to have an implementation that never -** returns an error message: -** -** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ -** assert(zBuf[0]=='\0'); -** return 0; -** } -** -** However if an error message is supplied, it will be incorporated -** by sqlite into the error message available to the user using -** sqlite3_errmsg(), possibly making IO errors easier to debug. -*/ -static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ - UNUSED_PARAMETER(pVfs); - return getLastErrorMsg(osGetLastError(), nBuf, zBuf); -} - -/* -** Initialize and deinitialize the operating system interface. -*/ -SQLITE_API int sqlite3_os_init(void){ - static sqlite3_vfs winVfs = { - 3, /* iVersion */ - sizeof(winFile), /* szOsFile */ - MAX_PATH, /* mxPathname */ - 0, /* pNext */ - "win32", /* zName */ - 0, /* pAppData */ - winOpen, /* xOpen */ - winDelete, /* xDelete */ - winAccess, /* xAccess */ - winFullPathname, /* xFullPathname */ - winDlOpen, /* xDlOpen */ - winDlError, /* xDlError */ - winDlSym, /* xDlSym */ - winDlClose, /* xDlClose */ - winRandomness, /* xRandomness */ - winSleep, /* xSleep */ - winCurrentTime, /* xCurrentTime */ - winGetLastError, /* xGetLastError */ - winCurrentTimeInt64, /* xCurrentTimeInt64 */ - winSetSystemCall, /* xSetSystemCall */ - winGetSystemCall, /* xGetSystemCall */ - winNextSystemCall, /* xNextSystemCall */ - }; - - /* Double-check that the aSyscall[] array has been constructed - ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==74 ); - - /* get memory map allocation granularity */ - memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); -#if SQLITE_OS_WINRT - osGetNativeSystemInfo(&winSysInfo); -#else - osGetSystemInfo(&winSysInfo); -#endif - assert( winSysInfo.dwAllocationGranularity>0 ); - assert( winSysInfo.dwPageSize>0 ); - - sqlite3_vfs_register(&winVfs, 1); - return SQLITE_OK; -} - -SQLITE_API int sqlite3_os_end(void){ -#if SQLITE_OS_WINRT - if( sleepObj!=NULL ){ - osCloseHandle(sleepObj); - sleepObj = NULL; - } -#endif - return SQLITE_OK; -} - -#endif /* SQLITE_OS_WIN */ - -/************** End of os_win.c **********************************************/ -/************** Begin file bitvec.c ******************************************/ -/* -** 2008 February 16 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file implements an object that represents a fixed-length -** bitmap. Bits are numbered starting with 1. -** -** A bitmap is used to record which pages of a database file have been -** journalled during a transaction, or which pages have the "dont-write" -** property. Usually only a few pages are meet either condition. -** So the bitmap is usually sparse and has low cardinality. -** But sometimes (for example when during a DROP of a large table) most -** or all of the pages in a database can get journalled. In those cases, -** the bitmap becomes dense with high cardinality. The algorithm needs -** to handle both cases well. -** -** The size of the bitmap is fixed when the object is created. -** -** All bits are clear when the bitmap is created. Individual bits -** may be set or cleared one at a time. -** -** Test operations are about 100 times more common that set operations. -** Clear operations are exceedingly rare. There are usually between -** 5 and 500 set operations per Bitvec object, though the number of sets can -** sometimes grow into tens of thousands or larger. The size of the -** Bitvec object is the number of pages in the database file at the -** start of a transaction, and is thus usually less than a few thousand, -** but can be as large as 2 billion for a really big database. -*/ - -/* Size of the Bitvec structure in bytes. */ -#define BITVEC_SZ 512 - -/* Round the union size down to the nearest pointer boundary, since that's how -** it will be aligned within the Bitvec struct. */ -#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) - -/* Type of the array "element" for the bitmap representation. -** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE. -** Setting this to the "natural word" size of your CPU may improve -** performance. */ -#define BITVEC_TELEM u8 -/* Size, in bits, of the bitmap element. */ -#define BITVEC_SZELEM 8 -/* Number of elements in a bitmap array. */ -#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM)) -/* Number of bits in the bitmap array. */ -#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM) - -/* Number of u32 values in hash table. */ -#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32)) -/* Maximum number of entries in hash table before -** sub-dividing and re-hashing. */ -#define BITVEC_MXHASH (BITVEC_NINT/2) -/* Hashing function for the aHash representation. -** Empirical testing showed that the *37 multiplier -** (an arbitrary prime)in the hash function provided -** no fewer collisions than the no-op *1. */ -#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT) - -#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *)) - - -/* -** A bitmap is an instance of the following structure. -** -** This bitmap records the existence of zero or more bits -** with values between 1 and iSize, inclusive. -** -** There are three possible representations of the bitmap. -** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight -** bitmap. The least significant bit is bit 1. -** -** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is -** a hash table that will hold up to BITVEC_MXHASH distinct values. -** -** Otherwise, the value i is redirected into one of BITVEC_NPTR -** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap -** handles up to iDivisor separate values of i. apSub[0] holds -** values between 1 and iDivisor. apSub[1] holds values between -** iDivisor+1 and 2*iDivisor. apSub[N] holds values between -** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized -** to hold deal with values between 1 and iDivisor. -*/ -struct Bitvec { - u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */ - u32 nSet; /* Number of bits that are set - only valid for aHash - ** element. Max is BITVEC_NINT. For BITVEC_SZ of 512, - ** this would be 125. */ - u32 iDivisor; /* Number of bits handled by each apSub[] entry. */ - /* Should >=0 for apSub element. */ - /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */ - /* For a BITVEC_SZ of 512, this would be 34,359,739. */ - union { - BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */ - u32 aHash[BITVEC_NINT]; /* Hash table representation */ - Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ - } u; -}; - -/* -** Create a new bitmap object able to handle bits between 0 and iSize, -** inclusive. Return a pointer to the new object. Return NULL if -** malloc fails. -*/ -SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){ - Bitvec *p; - assert( sizeof(*p)==BITVEC_SZ ); - p = sqlite3MallocZero( sizeof(*p) ); - if( p ){ - p->iSize = iSize; - } - return p; -} - -/* -** Check to see if the i-th bit is set. Return true or false. -** If p is NULL (if the bitmap has not been created) or if -** i is out of range, then return false. -*/ -SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){ - if( p==0 ) return 0; - if( i>p->iSize || i==0 ) return 0; - i--; - while( p->iDivisor ){ - u32 bin = i/p->iDivisor; - i = i%p->iDivisor; - p = p->u.apSub[bin]; - if (!p) { - return 0; - } - } - if( p->iSize<=BITVEC_NBIT ){ - return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0; - } else{ - u32 h = BITVEC_HASH(i++); - while( p->u.aHash[h] ){ - if( p->u.aHash[h]==i ) return 1; - h = (h+1) % BITVEC_NINT; - } - return 0; - } -} - -/* -** Set the i-th bit. Return 0 on success and an error code if -** anything goes wrong. -** -** This routine might cause sub-bitmaps to be allocated. Failing -** to get the memory needed to hold the sub-bitmap is the only -** that can go wrong with an insert, assuming p and i are valid. -** -** The calling function must ensure that p is a valid Bitvec object -** and that the value for "i" is within range of the Bitvec object. -** Otherwise the behavior is undefined. -*/ -SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ - u32 h; - if( p==0 ) return SQLITE_OK; - assert( i>0 ); - assert( i<=p->iSize ); - i--; - while((p->iSize > BITVEC_NBIT) && p->iDivisor) { - u32 bin = i/p->iDivisor; - i = i%p->iDivisor; - if( p->u.apSub[bin]==0 ){ - p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); - if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM; - } - p = p->u.apSub[bin]; - } - if( p->iSize<=BITVEC_NBIT ){ - p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1)); - return SQLITE_OK; - } - h = BITVEC_HASH(i++); - /* if there wasn't a hash collision, and this doesn't */ - /* completely fill the hash, then just add it without */ - /* worring about sub-dividing and re-hashing. */ - if( !p->u.aHash[h] ){ - if (p->nSet<(BITVEC_NINT-1)) { - goto bitvec_set_end; - } else { - goto bitvec_set_rehash; - } - } - /* there was a collision, check to see if it's already */ - /* in hash, if not, try to find a spot for it */ - do { - if( p->u.aHash[h]==i ) return SQLITE_OK; - h++; - if( h>=BITVEC_NINT ) h = 0; - } while( p->u.aHash[h] ); - /* we didn't find it in the hash. h points to the first */ - /* available free spot. check to see if this is going to */ - /* make our hash too "full". */ -bitvec_set_rehash: - if( p->nSet>=BITVEC_MXHASH ){ - unsigned int j; - int rc; - u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash)); - if( aiValues==0 ){ - return SQLITE_NOMEM; - }else{ - memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); - memset(p->u.apSub, 0, sizeof(p->u.apSub)); - p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; - rc = sqlite3BitvecSet(p, i); - for(j=0; jnSet++; - p->u.aHash[h] = i; - return SQLITE_OK; -} - -/* -** Clear the i-th bit. -** -** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage -** that BitvecClear can use to rebuilt its hash table. -*/ -SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){ - if( p==0 ) return; - assert( i>0 ); - i--; - while( p->iDivisor ){ - u32 bin = i/p->iDivisor; - i = i%p->iDivisor; - p = p->u.apSub[bin]; - if (!p) { - return; - } - } - if( p->iSize<=BITVEC_NBIT ){ - p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1))); - }else{ - unsigned int j; - u32 *aiValues = pBuf; - memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash)); - memset(p->u.aHash, 0, sizeof(p->u.aHash)); - p->nSet = 0; - for(j=0; jnSet++; - while( p->u.aHash[h] ){ - h++; - if( h>=BITVEC_NINT ) h = 0; - } - p->u.aHash[h] = aiValues[j]; - } - } - } -} - -/* -** Destroy a bitmap object. Reclaim all memory used. -*/ -SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){ - if( p==0 ) return; - if( p->iDivisor ){ - unsigned int i; - for(i=0; iu.apSub[i]); - } - } - sqlite3_free(p); -} - -/* -** Return the value of the iSize parameter specified when Bitvec *p -** was created. -*/ -SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){ - return p->iSize; -} - -#ifndef SQLITE_OMIT_BUILTIN_TEST -/* -** Let V[] be an array of unsigned characters sufficient to hold -** up to N bits. Let I be an integer between 0 and N. 0<=I>3] |= (1<<(I&7)) -#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7)) -#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 - -/* -** This routine runs an extensive test of the Bitvec code. -** -** The input is an array of integers that acts as a program -** to test the Bitvec. The integers are opcodes followed -** by 0, 1, or 3 operands, depending on the opcode. Another -** opcode follows immediately after the last operand. -** -** There are 6 opcodes numbered from 0 through 5. 0 is the -** "halt" opcode and causes the test to end. -** -** 0 Halt and return the number of errors -** 1 N S X Set N bits beginning with S and incrementing by X -** 2 N S X Clear N bits beginning with S and incrementing by X -** 3 N Set N randomly chosen bits -** 4 N Clear N randomly chosen bits -** 5 N S X Set N bits from S increment X in array only, not in bitvec -** -** The opcodes 1 through 4 perform set and clear operations are performed -** on both a Bitvec object and on a linear array of bits obtained from malloc. -** Opcode 5 works on the linear array only, not on the Bitvec. -** Opcode 5 is used to deliberately induce a fault in order to -** confirm that error detection works. -** -** At the conclusion of the test the linear array is compared -** against the Bitvec object. If there are any differences, -** an error is returned. If they are the same, zero is returned. -** -** If a memory allocation error occurs, return -1. -*/ -SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ - Bitvec *pBitvec = 0; - unsigned char *pV = 0; - int rc = -1; - int i, nx, pc, op; - void *pTmpSpace; - - /* Allocate the Bitvec to be tested and a linear array of - ** bits to act as the reference */ - pBitvec = sqlite3BitvecCreate( sz ); - pV = sqlite3MallocZero( (sz+7)/8 + 1 ); - pTmpSpace = sqlite3_malloc(BITVEC_SZ); - if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; - - /* NULL pBitvec tests */ - sqlite3BitvecSet(0, 1); - sqlite3BitvecClear(0, 1, pTmpSpace); - - /* Run the program */ - pc = 0; - while( (op = aOp[pc])!=0 ){ - switch( op ){ - case 1: - case 2: - case 5: { - nx = 4; - i = aOp[pc+2] - 1; - aOp[pc+2] += aOp[pc+3]; - break; - } - case 3: - case 4: - default: { - nx = 2; - sqlite3_randomness(sizeof(i), &i); - break; - } - } - if( (--aOp[pc+1]) > 0 ) nx = 0; - pc += nx; - i = (i & 0x7fffffff)%sz; - if( (op & 1)!=0 ){ - SETBIT(pV, (i+1)); - if( op!=5 ){ - if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; - } - }else{ - CLEARBIT(pV, (i+1)); - sqlite3BitvecClear(pBitvec, i+1, pTmpSpace); - } - } - - /* Test to make sure the linear array exactly matches the - ** Bitvec object. Start with the assumption that they do - ** match (rc==0). Change rc to non-zero if a discrepancy - ** is found. - */ - rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) - + sqlite3BitvecTest(pBitvec, 0) - + (sqlite3BitvecSize(pBitvec) - sz); - for(i=1; i<=sz; i++){ - if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ - rc = i; - break; - } - } - - /* Free allocated structure */ -bitvec_end: - sqlite3_free(pTmpSpace); - sqlite3_free(pV); - sqlite3BitvecDestroy(pBitvec); - return rc; -} -#endif /* SQLITE_OMIT_BUILTIN_TEST */ - -/************** End of bitvec.c **********************************************/ -/************** Begin file pcache.c ******************************************/ -/* -** 2008 August 05 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file implements that page cache. -*/ - -/* -** A complete page cache is an instance of this structure. -*/ -struct PCache { - PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ - PgHdr *pSynced; /* Last synced page in dirty page list */ - int nRef; /* Number of referenced pages */ - int szCache; /* Configured cache size */ - int szPage; /* Size of every page in this cache */ - int szExtra; /* Size of extra space for each page */ - int bPurgeable; /* True if pages are on backing store */ - int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ - void *pStress; /* Argument to xStress */ - sqlite3_pcache *pCache; /* Pluggable cache module */ - PgHdr *pPage1; /* Reference to page 1 */ -}; - -/* -** Some of the assert() macros in this code are too expensive to run -** even during normal debugging. Use them only rarely on long-running -** tests. Enable the expensive asserts using the -** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option. -*/ -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT -# define expensive_assert(X) assert(X) -#else -# define expensive_assert(X) -#endif - -/********************************** Linked List Management ********************/ - -#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT) -/* -** Check that the pCache->pSynced variable is set correctly. If it -** is not, either fail an assert or return zero. Otherwise, return -** non-zero. This is only used in debugging builds, as follows: -** -** expensive_assert( pcacheCheckSynced(pCache) ); -*/ -static int pcacheCheckSynced(PCache *pCache){ - PgHdr *p; - for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){ - assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) ); - } - return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0); -} -#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */ - -/* -** Remove page pPage from the list of dirty pages. -*/ -static void pcacheRemoveFromDirtyList(PgHdr *pPage){ - PCache *p = pPage->pCache; - - assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); - assert( pPage->pDirtyPrev || pPage==p->pDirty ); - - /* Update the PCache1.pSynced variable if necessary. */ - if( p->pSynced==pPage ){ - PgHdr *pSynced = pPage->pDirtyPrev; - while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ - pSynced = pSynced->pDirtyPrev; - } - p->pSynced = pSynced; - } - - if( pPage->pDirtyNext ){ - pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; - }else{ - assert( pPage==p->pDirtyTail ); - p->pDirtyTail = pPage->pDirtyPrev; - } - if( pPage->pDirtyPrev ){ - pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; - }else{ - assert( pPage==p->pDirty ); - p->pDirty = pPage->pDirtyNext; - } - pPage->pDirtyNext = 0; - pPage->pDirtyPrev = 0; - - expensive_assert( pcacheCheckSynced(p) ); -} - -/* -** Add page pPage to the head of the dirty list (PCache1.pDirty is set to -** pPage). -*/ -static void pcacheAddToDirtyList(PgHdr *pPage){ - PCache *p = pPage->pCache; - - assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); - - pPage->pDirtyNext = p->pDirty; - if( pPage->pDirtyNext ){ - assert( pPage->pDirtyNext->pDirtyPrev==0 ); - pPage->pDirtyNext->pDirtyPrev = pPage; - } - p->pDirty = pPage; - if( !p->pDirtyTail ){ - p->pDirtyTail = pPage; - } - if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ - p->pSynced = pPage; - } - expensive_assert( pcacheCheckSynced(p) ); -} - -/* -** Wrapper around the pluggable caches xUnpin method. If the cache is -** being used for an in-memory database, this function is a no-op. -*/ -static void pcacheUnpin(PgHdr *p){ - PCache *pCache = p->pCache; - if( pCache->bPurgeable ){ - if( p->pgno==1 ){ - pCache->pPage1 = 0; - } - sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0); - } -} - -/*************************************************** General Interfaces ****** -** -** Initialize and shutdown the page cache subsystem. Neither of these -** functions are threadsafe. -*/ -SQLITE_PRIVATE int sqlite3PcacheInitialize(void){ - if( sqlite3GlobalConfig.pcache2.xInit==0 ){ - /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the - ** built-in default page cache is used instead of the application defined - ** page cache. */ - sqlite3PCacheSetDefault(); - } - return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg); -} -SQLITE_PRIVATE void sqlite3PcacheShutdown(void){ - if( sqlite3GlobalConfig.pcache2.xShutdown ){ - /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */ - sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg); - } -} - -/* -** Return the size in bytes of a PCache object. -*/ -SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); } - -/* -** Create a new PCache object. Storage space to hold the object -** has already been allocated and is passed in as the p pointer. -** The caller discovers how much space needs to be allocated by -** calling sqlite3PcacheSize(). -*/ -SQLITE_PRIVATE void sqlite3PcacheOpen( - int szPage, /* Size of every page */ - int szExtra, /* Extra space associated with each page */ - int bPurgeable, /* True if pages are on backing store */ - int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */ - void *pStress, /* Argument to xStress */ - PCache *p /* Preallocated space for the PCache */ -){ - memset(p, 0, sizeof(PCache)); - p->szPage = szPage; - p->szExtra = szExtra; - p->bPurgeable = bPurgeable; - p->xStress = xStress; - p->pStress = pStress; - p->szCache = 100; -} - -/* -** Change the page size for PCache object. The caller must ensure that there -** are no outstanding page references when this function is called. -*/ -SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ - assert( pCache->nRef==0 && pCache->pDirty==0 ); - if( pCache->pCache ){ - sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); - pCache->pCache = 0; - pCache->pPage1 = 0; - } - pCache->szPage = szPage; -} - -/* -** Compute the number of pages of cache requested. -*/ -static int numberOfCachePages(PCache *p){ - if( p->szCache>=0 ){ - return p->szCache; - }else{ - return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); - } -} - -/* -** Try to obtain a page from the cache. -*/ -SQLITE_PRIVATE int sqlite3PcacheFetch( - PCache *pCache, /* Obtain the page from this cache */ - Pgno pgno, /* Page number to obtain */ - int createFlag, /* If true, create page if it does not exist already */ - PgHdr **ppPage /* Write the page here */ -){ - sqlite3_pcache_page *pPage = 0; - PgHdr *pPgHdr = 0; - int eCreate; - - assert( pCache!=0 ); - assert( createFlag==1 || createFlag==0 ); - assert( pgno>0 ); - - /* If the pluggable cache (sqlite3_pcache*) has not been allocated, - ** allocate it now. - */ - if( !pCache->pCache && createFlag ){ - sqlite3_pcache *p; - p = sqlite3GlobalConfig.pcache2.xCreate( - pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable - ); - if( !p ){ - return SQLITE_NOMEM; - } - sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache)); - pCache->pCache = p; - } - - eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty)); - if( pCache->pCache ){ - pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); - } - - if( !pPage && eCreate==1 ){ - PgHdr *pPg; - - /* Find a dirty page to write-out and recycle. First try to find a - ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC - ** cleared), but if that is not possible settle for any other - ** unreferenced dirty page. - */ - expensive_assert( pcacheCheckSynced(pCache) ); - for(pPg=pCache->pSynced; - pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); - pPg=pPg->pDirtyPrev - ); - pCache->pSynced = pPg; - if( !pPg ){ - for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); - } - if( pPg ){ - int rc; -#ifdef SQLITE_LOG_CACHE_SPILL - sqlite3_log(SQLITE_FULL, - "spill page %d making room for %d - cache used: %d/%d", - pPg->pgno, pgno, - sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), - numberOfCachePages(pCache)); -#endif - rc = pCache->xStress(pCache->pStress, pPg); - if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ - return rc; - } - } - - pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2); - } - - if( pPage ){ - pPgHdr = (PgHdr *)pPage->pExtra; - - if( !pPgHdr->pPage ){ - memset(pPgHdr, 0, sizeof(PgHdr)); - pPgHdr->pPage = pPage; - pPgHdr->pData = pPage->pBuf; - pPgHdr->pExtra = (void *)&pPgHdr[1]; - memset(pPgHdr->pExtra, 0, pCache->szExtra); - pPgHdr->pCache = pCache; - pPgHdr->pgno = pgno; - } - assert( pPgHdr->pCache==pCache ); - assert( pPgHdr->pgno==pgno ); - assert( pPgHdr->pData==pPage->pBuf ); - assert( pPgHdr->pExtra==(void *)&pPgHdr[1] ); - - if( 0==pPgHdr->nRef ){ - pCache->nRef++; - } - pPgHdr->nRef++; - if( pgno==1 ){ - pCache->pPage1 = pPgHdr; - } - } - *ppPage = pPgHdr; - return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK; -} - -/* -** Decrement the reference count on a page. If the page is clean and the -** reference count drops to 0, then it is made elible for recycling. -*/ -SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){ - assert( p->nRef>0 ); - p->nRef--; - if( p->nRef==0 ){ - PCache *pCache = p->pCache; - pCache->nRef--; - if( (p->flags&PGHDR_DIRTY)==0 ){ - pcacheUnpin(p); - }else{ - /* Move the page to the head of the dirty list. */ - pcacheRemoveFromDirtyList(p); - pcacheAddToDirtyList(p); - } - } -} - -/* -** Increase the reference count of a supplied page by 1. -*/ -SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ - assert(p->nRef>0); - p->nRef++; -} - -/* -** Drop a page from the cache. There must be exactly one reference to the -** page. This function deletes that reference, so after it returns the -** page pointed to by p is invalid. -*/ -SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ - PCache *pCache; - assert( p->nRef==1 ); - if( p->flags&PGHDR_DIRTY ){ - pcacheRemoveFromDirtyList(p); - } - pCache = p->pCache; - pCache->nRef--; - if( p->pgno==1 ){ - pCache->pPage1 = 0; - } - sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1); -} - -/* -** Make sure the page is marked as dirty. If it isn't dirty already, -** make it so. -*/ -SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ - p->flags &= ~PGHDR_DONT_WRITE; - assert( p->nRef>0 ); - if( 0==(p->flags & PGHDR_DIRTY) ){ - p->flags |= PGHDR_DIRTY; - pcacheAddToDirtyList( p); - } -} - -/* -** Make sure the page is marked as clean. If it isn't clean already, -** make it so. -*/ -SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ - if( (p->flags & PGHDR_DIRTY) ){ - pcacheRemoveFromDirtyList(p); - p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC); - if( p->nRef==0 ){ - pcacheUnpin(p); - } - } -} - -/* -** Make every page in the cache clean. -*/ -SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){ - PgHdr *p; - while( (p = pCache->pDirty)!=0 ){ - sqlite3PcacheMakeClean(p); - } -} - -/* -** Clear the PGHDR_NEED_SYNC flag from all dirty pages. -*/ -SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){ - PgHdr *p; - for(p=pCache->pDirty; p; p=p->pDirtyNext){ - p->flags &= ~PGHDR_NEED_SYNC; - } - pCache->pSynced = pCache->pDirtyTail; -} - -/* -** Change the page number of page p to newPgno. -*/ -SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ - PCache *pCache = p->pCache; - assert( p->nRef>0 ); - assert( newPgno>0 ); - sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); - p->pgno = newPgno; - if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ - pcacheRemoveFromDirtyList(p); - pcacheAddToDirtyList(p); - } -} - -/* -** Drop every cache entry whose page number is greater than "pgno". The -** caller must ensure that there are no outstanding references to any pages -** other than page 1 with a page number greater than pgno. -** -** If there is a reference to page 1 and the pgno parameter passed to this -** function is 0, then the data area associated with page 1 is zeroed, but -** the page object is not dropped. -*/ -SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ - if( pCache->pCache ){ - PgHdr *p; - PgHdr *pNext; - for(p=pCache->pDirty; p; p=pNext){ - pNext = p->pDirtyNext; - /* This routine never gets call with a positive pgno except right - ** after sqlite3PcacheCleanAll(). So if there are dirty pages, - ** it must be that pgno==0. - */ - assert( p->pgno>0 ); - if( ALWAYS(p->pgno>pgno) ){ - assert( p->flags&PGHDR_DIRTY ); - sqlite3PcacheMakeClean(p); - } - } - if( pgno==0 && pCache->pPage1 ){ - memset(pCache->pPage1->pData, 0, pCache->szPage); - pgno = 1; - } - sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1); - } -} - -/* -** Close a cache. -*/ -SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){ - if( pCache->pCache ){ - sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); - } -} - -/* -** Discard the contents of the cache. -*/ -SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){ - sqlite3PcacheTruncate(pCache, 0); -} - -/* -** Merge two lists of pages connected by pDirty and in pgno order. -** Do not both fixing the pDirtyPrev pointers. -*/ -static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ - PgHdr result, *pTail; - pTail = &result; - while( pA && pB ){ - if( pA->pgnopgno ){ - pTail->pDirty = pA; - pTail = pA; - pA = pA->pDirty; - }else{ - pTail->pDirty = pB; - pTail = pB; - pB = pB->pDirty; - } - } - if( pA ){ - pTail->pDirty = pA; - }else if( pB ){ - pTail->pDirty = pB; - }else{ - pTail->pDirty = 0; - } - return result.pDirty; -} - -/* -** Sort the list of pages in accending order by pgno. Pages are -** connected by pDirty pointers. The pDirtyPrev pointers are -** corrupted by this sort. -** -** Since there cannot be more than 2^31 distinct pages in a database, -** there cannot be more than 31 buckets required by the merge sorter. -** One extra bucket is added to catch overflow in case something -** ever changes to make the previous sentence incorrect. -*/ -#define N_SORT_BUCKET 32 -static PgHdr *pcacheSortDirtyList(PgHdr *pIn){ - PgHdr *a[N_SORT_BUCKET], *p; - int i; - memset(a, 0, sizeof(a)); - while( pIn ){ - p = pIn; - pIn = p->pDirty; - p->pDirty = 0; - for(i=0; ALWAYS(ipDirty; p; p=p->pDirtyNext){ - p->pDirty = p->pDirtyNext; - } - return pcacheSortDirtyList(pCache->pDirty); -} - -/* -** Return the total number of referenced pages held by the cache. -*/ -SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){ - return pCache->nRef; -} - -/* -** Return the number of references to the page supplied as an argument. -*/ -SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){ - return p->nRef; -} - -/* -** Return the total number of pages in the cache. -*/ -SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){ - int nPage = 0; - if( pCache->pCache ){ - nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache); - } - return nPage; -} - -#ifdef SQLITE_TEST -/* -** Get the suggested cache-size value. -*/ -SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){ - return numberOfCachePages(pCache); -} -#endif - -/* -** Set the suggested cache-size value. -*/ -SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ - pCache->szCache = mxPage; - if( pCache->pCache ){ - sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache, - numberOfCachePages(pCache)); - } -} - -/* -** Free up as much memory as possible from the page cache. -*/ -SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){ - if( pCache->pCache ){ - sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache); - } -} - -#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) -/* -** For all dirty pages currently in the cache, invoke the specified -** callback. This is only used if the SQLITE_CHECK_PAGES macro is -** defined. -*/ -SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){ - PgHdr *pDirty; - for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){ - xIter(pDirty); - } -} -#endif - -/************** End of pcache.c **********************************************/ -/************** Begin file pcache1.c *****************************************/ -/* -** 2008 November 05 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements the default page cache implementation (the -** sqlite3_pcache interface). It also contains part of the implementation -** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features. -** If the default page cache implementation is overriden, then neither of -** these two features are available. -*/ - - -typedef struct PCache1 PCache1; -typedef struct PgHdr1 PgHdr1; -typedef struct PgFreeslot PgFreeslot; -typedef struct PGroup PGroup; - -/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set -** of one or more PCaches that are able to recycle each others unpinned -** pages when they are under memory pressure. A PGroup is an instance of -** the following object. -** -** This page cache implementation works in one of two modes: -** -** (1) Every PCache is the sole member of its own PGroup. There is -** one PGroup per PCache. -** -** (2) There is a single global PGroup that all PCaches are a member -** of. -** -** Mode 1 uses more memory (since PCache instances are not able to rob -** unused pages from other PCaches) but it also operates without a mutex, -** and is therefore often faster. Mode 2 requires a mutex in order to be -** threadsafe, but recycles pages more efficiently. -** -** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single -** PGroup which is the pcache1.grp global variable and its mutex is -** SQLITE_MUTEX_STATIC_LRU. -*/ -struct PGroup { - sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */ - unsigned int nMaxPage; /* Sum of nMax for purgeable caches */ - unsigned int nMinPage; /* Sum of nMin for purgeable caches */ - unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */ - unsigned int nCurrentPage; /* Number of purgeable pages allocated */ - PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */ -}; - -/* Each page cache is an instance of the following object. Every -** open database file (including each in-memory database and each -** temporary or transient database) has a single page cache which -** is an instance of this object. -** -** Pointers to structures of this type are cast and returned as -** opaque sqlite3_pcache* handles. -*/ -struct PCache1 { - /* Cache configuration parameters. Page size (szPage) and the purgeable - ** flag (bPurgeable) are set when the cache is created. nMax may be - ** modified at any time by a call to the pcache1Cachesize() method. - ** The PGroup mutex must be held when accessing nMax. - */ - PGroup *pGroup; /* PGroup this cache belongs to */ - int szPage; /* Size of allocated pages in bytes */ - int szExtra; /* Size of extra space in bytes */ - int bPurgeable; /* True if cache is purgeable */ - unsigned int nMin; /* Minimum number of pages reserved */ - unsigned int nMax; /* Configured "cache_size" value */ - unsigned int n90pct; /* nMax*9/10 */ - unsigned int iMaxKey; /* Largest key seen since xTruncate() */ - - /* Hash table of all pages. The following variables may only be accessed - ** when the accessor is holding the PGroup mutex. - */ - unsigned int nRecyclable; /* Number of pages in the LRU list */ - unsigned int nPage; /* Total number of pages in apHash */ - unsigned int nHash; /* Number of slots in apHash[] */ - PgHdr1 **apHash; /* Hash table for fast lookup by key */ -}; - -/* -** Each cache entry is represented by an instance of the following -** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of -** PgHdr1.pCache->szPage bytes is allocated directly before this structure -** in memory. -*/ -struct PgHdr1 { - sqlite3_pcache_page page; - unsigned int iKey; /* Key value (page number) */ - PgHdr1 *pNext; /* Next in hash table chain */ - PCache1 *pCache; /* Cache that currently owns this page */ - PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ - PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ -}; - -/* -** Free slots in the allocator used to divide up the buffer provided using -** the SQLITE_CONFIG_PAGECACHE mechanism. -*/ -struct PgFreeslot { - PgFreeslot *pNext; /* Next free slot */ -}; - -/* -** Global data used by this cache. -*/ -static SQLITE_WSD struct PCacheGlobal { - PGroup grp; /* The global PGroup for mode (2) */ - - /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The - ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all - ** fixed at sqlite3_initialize() time and do not require mutex protection. - ** The nFreeSlot and pFree values do require mutex protection. - */ - int isInit; /* True if initialized */ - int szSlot; /* Size of each free slot */ - int nSlot; /* The number of pcache slots */ - int nReserve; /* Try to keep nFreeSlot above this */ - void *pStart, *pEnd; /* Bounds of pagecache malloc range */ - /* Above requires no mutex. Use mutex below for variable that follow. */ - sqlite3_mutex *mutex; /* Mutex for accessing the following: */ - PgFreeslot *pFree; /* Free page blocks */ - int nFreeSlot; /* Number of unused pcache slots */ - /* The following value requires a mutex to change. We skip the mutex on - ** reading because (1) most platforms read a 32-bit integer atomically and - ** (2) even if an incorrect value is read, no great harm is done since this - ** is really just an optimization. */ - int bUnderPressure; /* True if low on PAGECACHE memory */ -} pcache1_g; - -/* -** All code in this file should access the global structure above via the -** alias "pcache1". This ensures that the WSD emulation is used when -** compiling for systems that do not support real WSD. -*/ -#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g)) - -/* -** Macros to enter and leave the PCache LRU mutex. -*/ -#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex) -#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex) - -/******************************************************************************/ -/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/ - -/* -** This function is called during initialization if a static buffer is -** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE -** verb to sqlite3_config(). Parameter pBuf points to an allocation large -** enough to contain 'n' buffers of 'sz' bytes each. -** -** This routine is called from sqlite3_initialize() and so it is guaranteed -** to be serialized already. There is no need for further mutexing. -*/ -SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ - if( pcache1.isInit ){ - PgFreeslot *p; - sz = ROUNDDOWN8(sz); - pcache1.szSlot = sz; - pcache1.nSlot = pcache1.nFreeSlot = n; - pcache1.nReserve = n>90 ? 10 : (n/10 + 1); - pcache1.pStart = pBuf; - pcache1.pFree = 0; - pcache1.bUnderPressure = 0; - while( n-- ){ - p = (PgFreeslot*)pBuf; - p->pNext = pcache1.pFree; - pcache1.pFree = p; - pBuf = (void*)&((char*)pBuf)[sz]; - } - pcache1.pEnd = pBuf; - } -} - -/* -** Malloc function used within this file to allocate space from the buffer -** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no -** such buffer exists or there is no space left in it, this function falls -** back to sqlite3Malloc(). -** -** Multiple threads can run this routine at the same time. Global variables -** in pcache1 need to be protected via mutex. -*/ -static void *pcache1Alloc(int nByte){ - void *p = 0; - assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); - sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); - if( nByte<=pcache1.szSlot ){ - sqlite3_mutex_enter(pcache1.mutex); - p = (PgHdr1 *)pcache1.pFree; - if( p ){ - pcache1.pFree = pcache1.pFree->pNext; - pcache1.nFreeSlot--; - pcache1.bUnderPressure = pcache1.nFreeSlot=0 ); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); - } - sqlite3_mutex_leave(pcache1.mutex); - } - if( p==0 ){ - /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get - ** it from sqlite3Malloc instead. - */ - p = sqlite3Malloc(nByte); -#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS - if( p ){ - int sz = sqlite3MallocSize(p); - sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); - sqlite3_mutex_leave(pcache1.mutex); - } -#endif - sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); - } - return p; -} - -/* -** Free an allocated buffer obtained from pcache1Alloc(). -*/ -static int pcache1Free(void *p){ - int nFreed = 0; - if( p==0 ) return 0; - if( p>=pcache1.pStart && ppNext = pcache1.pFree; - pcache1.pFree = pSlot; - pcache1.nFreeSlot++; - pcache1.bUnderPressure = pcache1.nFreeSlot=pcache1.pStart && ppGroup->mutex) ); - pcache1LeaveMutex(pCache->pGroup); -#ifdef SQLITE_PCACHE_SEPARATE_HEADER - pPg = pcache1Alloc(pCache->szPage); - p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); - if( !pPg || !p ){ - pcache1Free(pPg); - sqlite3_free(p); - pPg = 0; - } -#else - pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra); - p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; -#endif - pcache1EnterMutex(pCache->pGroup); - - if( pPg ){ - p->page.pBuf = pPg; - p->page.pExtra = &p[1]; - if( pCache->bPurgeable ){ - pCache->pGroup->nCurrentPage++; - } - return p; - } - return 0; -} - -/* -** Free a page object allocated by pcache1AllocPage(). -** -** The pointer is allowed to be NULL, which is prudent. But it turns out -** that the current implementation happens to never call this routine -** with a NULL pointer, so we mark the NULL test with ALWAYS(). -*/ -static void pcache1FreePage(PgHdr1 *p){ - if( ALWAYS(p) ){ - PCache1 *pCache = p->pCache; - assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); - pcache1Free(p->page.pBuf); -#ifdef SQLITE_PCACHE_SEPARATE_HEADER - sqlite3_free(p); -#endif - if( pCache->bPurgeable ){ - pCache->pGroup->nCurrentPage--; - } - } -} - -/* -** Malloc function used by SQLite to obtain space from the buffer configured -** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer -** exists, this function falls back to sqlite3Malloc(). -*/ -SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){ - return pcache1Alloc(sz); -} - -/* -** Free an allocated buffer obtained from sqlite3PageMalloc(). -*/ -SQLITE_PRIVATE void sqlite3PageFree(void *p){ - pcache1Free(p); -} - - -/* -** Return true if it desirable to avoid allocating a new page cache -** entry. -** -** If memory was allocated specifically to the page cache using -** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then -** it is desirable to avoid allocating a new page cache entry because -** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient -** for all page cache needs and we should not need to spill the -** allocation onto the heap. -** -** Or, the heap is used for all page cache memory but the heap is -** under memory pressure, then again it is desirable to avoid -** allocating a new page cache entry in order to avoid stressing -** the heap even further. -*/ -static int pcache1UnderMemoryPressure(PCache1 *pCache){ - if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){ - return pcache1.bUnderPressure; - }else{ - return sqlite3HeapNearlyFull(); - } -} - -/******************************************************************************/ -/******** General Implementation Functions ************************************/ - -/* -** This function is used to resize the hash table used by the cache passed -** as the first argument. -** -** The PCache mutex must be held when this function is called. -*/ -static int pcache1ResizeHash(PCache1 *p){ - PgHdr1 **apNew; - unsigned int nNew; - unsigned int i; - - assert( sqlite3_mutex_held(p->pGroup->mutex) ); - - nNew = p->nHash*2; - if( nNew<256 ){ - nNew = 256; - } - - pcache1LeaveMutex(p->pGroup); - if( p->nHash ){ sqlite3BeginBenignMalloc(); } - apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew); - if( p->nHash ){ sqlite3EndBenignMalloc(); } - pcache1EnterMutex(p->pGroup); - if( apNew ){ - for(i=0; inHash; i++){ - PgHdr1 *pPage; - PgHdr1 *pNext = p->apHash[i]; - while( (pPage = pNext)!=0 ){ - unsigned int h = pPage->iKey % nNew; - pNext = pPage->pNext; - pPage->pNext = apNew[h]; - apNew[h] = pPage; - } - } - sqlite3_free(p->apHash); - p->apHash = apNew; - p->nHash = nNew; - } - - return (p->apHash ? SQLITE_OK : SQLITE_NOMEM); -} - -/* -** This function is used internally to remove the page pPage from the -** PGroup LRU list, if is part of it. If pPage is not part of the PGroup -** LRU list, then this function is a no-op. -** -** The PGroup mutex must be held when this function is called. -** -** If pPage is NULL then this routine is a no-op. -*/ -static void pcache1PinPage(PgHdr1 *pPage){ - PCache1 *pCache; - PGroup *pGroup; - - if( pPage==0 ) return; - pCache = pPage->pCache; - pGroup = pCache->pGroup; - assert( sqlite3_mutex_held(pGroup->mutex) ); - if( pPage->pLruNext || pPage==pGroup->pLruTail ){ - if( pPage->pLruPrev ){ - pPage->pLruPrev->pLruNext = pPage->pLruNext; - } - if( pPage->pLruNext ){ - pPage->pLruNext->pLruPrev = pPage->pLruPrev; - } - if( pGroup->pLruHead==pPage ){ - pGroup->pLruHead = pPage->pLruNext; - } - if( pGroup->pLruTail==pPage ){ - pGroup->pLruTail = pPage->pLruPrev; - } - pPage->pLruNext = 0; - pPage->pLruPrev = 0; - pPage->pCache->nRecyclable--; - } -} - - -/* -** Remove the page supplied as an argument from the hash table -** (PCache1.apHash structure) that it is currently stored in. -** -** The PGroup mutex must be held when this function is called. -*/ -static void pcache1RemoveFromHash(PgHdr1 *pPage){ - unsigned int h; - PCache1 *pCache = pPage->pCache; - PgHdr1 **pp; - - assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); - h = pPage->iKey % pCache->nHash; - for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext); - *pp = (*pp)->pNext; - - pCache->nPage--; -} - -/* -** If there are currently more than nMaxPage pages allocated, try -** to recycle pages to reduce the number allocated to nMaxPage. -*/ -static void pcache1EnforceMaxPage(PGroup *pGroup){ - assert( sqlite3_mutex_held(pGroup->mutex) ); - while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){ - PgHdr1 *p = pGroup->pLruTail; - assert( p->pCache->pGroup==pGroup ); - pcache1PinPage(p); - pcache1RemoveFromHash(p); - pcache1FreePage(p); - } -} - -/* -** Discard all pages from cache pCache with a page number (key value) -** greater than or equal to iLimit. Any pinned pages that meet this -** criteria are unpinned before they are discarded. -** -** The PCache mutex must be held when this function is called. -*/ -static void pcache1TruncateUnsafe( - PCache1 *pCache, /* The cache to truncate */ - unsigned int iLimit /* Drop pages with this pgno or larger */ -){ - TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */ - unsigned int h; - assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); - for(h=0; hnHash; h++){ - PgHdr1 **pp = &pCache->apHash[h]; - PgHdr1 *pPage; - while( (pPage = *pp)!=0 ){ - if( pPage->iKey>=iLimit ){ - pCache->nPage--; - *pp = pPage->pNext; - pcache1PinPage(pPage); - pcache1FreePage(pPage); - }else{ - pp = &pPage->pNext; - TESTONLY( nPage++; ) - } - } - } - assert( pCache->nPage==nPage ); -} - -/******************************************************************************/ -/******** sqlite3_pcache Methods **********************************************/ - -/* -** Implementation of the sqlite3_pcache.xInit method. -*/ -static int pcache1Init(void *NotUsed){ - UNUSED_PARAMETER(NotUsed); - assert( pcache1.isInit==0 ); - memset(&pcache1, 0, sizeof(pcache1)); - if( sqlite3GlobalConfig.bCoreMutex ){ - pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); - pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); - } - pcache1.grp.mxPinned = 10; - pcache1.isInit = 1; - return SQLITE_OK; -} - -/* -** Implementation of the sqlite3_pcache.xShutdown method. -** Note that the static mutex allocated in xInit does -** not need to be freed. -*/ -static void pcache1Shutdown(void *NotUsed){ - UNUSED_PARAMETER(NotUsed); - assert( pcache1.isInit!=0 ); - memset(&pcache1, 0, sizeof(pcache1)); -} - -/* -** Implementation of the sqlite3_pcache.xCreate method. -** -** Allocate a new cache. -*/ -static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ - PCache1 *pCache; /* The newly created page cache */ - PGroup *pGroup; /* The group the new page cache will belong to */ - int sz; /* Bytes of memory required to allocate the new cache */ - - /* - ** The seperateCache variable is true if each PCache has its own private - ** PGroup. In other words, separateCache is true for mode (1) where no - ** mutexing is required. - ** - ** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT - ** - ** * Always use a unified cache in single-threaded applications - ** - ** * Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off) - ** use separate caches (mode-1) - */ -#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0 - const int separateCache = 0; -#else - int separateCache = sqlite3GlobalConfig.bCoreMutex>0; -#endif - - assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 ); - assert( szExtra < 300 ); - - sz = sizeof(PCache1) + sizeof(PGroup)*separateCache; - pCache = (PCache1 *)sqlite3MallocZero(sz); - if( pCache ){ - if( separateCache ){ - pGroup = (PGroup*)&pCache[1]; - pGroup->mxPinned = 10; - }else{ - pGroup = &pcache1.grp; - } - pCache->pGroup = pGroup; - pCache->szPage = szPage; - pCache->szExtra = szExtra; - pCache->bPurgeable = (bPurgeable ? 1 : 0); - if( bPurgeable ){ - pCache->nMin = 10; - pcache1EnterMutex(pGroup); - pGroup->nMinPage += pCache->nMin; - pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pcache1LeaveMutex(pGroup); - } - } - return (sqlite3_pcache *)pCache; -} - -/* -** Implementation of the sqlite3_pcache.xCachesize method. -** -** Configure the cache_size limit for a cache. -*/ -static void pcache1Cachesize(sqlite3_pcache *p, int nMax){ - PCache1 *pCache = (PCache1 *)p; - if( pCache->bPurgeable ){ - PGroup *pGroup = pCache->pGroup; - pcache1EnterMutex(pGroup); - pGroup->nMaxPage += (nMax - pCache->nMax); - pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pCache->nMax = nMax; - pCache->n90pct = pCache->nMax*9/10; - pcache1EnforceMaxPage(pGroup); - pcache1LeaveMutex(pGroup); - } -} - -/* -** Implementation of the sqlite3_pcache.xShrink method. -** -** Free up as much memory as possible. -*/ -static void pcache1Shrink(sqlite3_pcache *p){ - PCache1 *pCache = (PCache1*)p; - if( pCache->bPurgeable ){ - PGroup *pGroup = pCache->pGroup; - int savedMaxPage; - pcache1EnterMutex(pGroup); - savedMaxPage = pGroup->nMaxPage; - pGroup->nMaxPage = 0; - pcache1EnforceMaxPage(pGroup); - pGroup->nMaxPage = savedMaxPage; - pcache1LeaveMutex(pGroup); - } -} - -/* -** Implementation of the sqlite3_pcache.xPagecount method. -*/ -static int pcache1Pagecount(sqlite3_pcache *p){ - int n; - PCache1 *pCache = (PCache1*)p; - pcache1EnterMutex(pCache->pGroup); - n = pCache->nPage; - pcache1LeaveMutex(pCache->pGroup); - return n; -} - -/* -** Implementation of the sqlite3_pcache.xFetch method. -** -** Fetch a page by key value. -** -** Whether or not a new page may be allocated by this function depends on -** the value of the createFlag argument. 0 means do not allocate a new -** page. 1 means allocate a new page if space is easily available. 2 -** means to try really hard to allocate a new page. -** -** For a non-purgeable cache (a cache used as the storage for an in-memory -** database) there is really no difference between createFlag 1 and 2. So -** the calling function (pcache.c) will never have a createFlag of 1 on -** a non-purgeable cache. -** -** There are three different approaches to obtaining space for a page, -** depending on the value of parameter createFlag (which may be 0, 1 or 2). -** -** 1. Regardless of the value of createFlag, the cache is searched for a -** copy of the requested page. If one is found, it is returned. -** -** 2. If createFlag==0 and the page is not already in the cache, NULL is -** returned. -** -** 3. If createFlag is 1, and the page is not already in the cache, then -** return NULL (do not allocate a new page) if any of the following -** conditions are true: -** -** (a) the number of pages pinned by the cache is greater than -** PCache1.nMax, or -** -** (b) the number of pages pinned by the cache is greater than -** the sum of nMax for all purgeable caches, less the sum of -** nMin for all other purgeable caches, or -** -** 4. If none of the first three conditions apply and the cache is marked -** as purgeable, and if one of the following is true: -** -** (a) The number of pages allocated for the cache is already -** PCache1.nMax, or -** -** (b) The number of pages allocated for all purgeable caches is -** already equal to or greater than the sum of nMax for all -** purgeable caches, -** -** (c) The system is under memory pressure and wants to avoid -** unnecessary pages cache entry allocations -** -** then attempt to recycle a page from the LRU list. If it is the right -** size, return the recycled buffer. Otherwise, free the buffer and -** proceed to step 5. -** -** 5. Otherwise, allocate and return a new page buffer. -*/ -static sqlite3_pcache_page *pcache1Fetch( - sqlite3_pcache *p, - unsigned int iKey, - int createFlag -){ - unsigned int nPinned; - PCache1 *pCache = (PCache1 *)p; - PGroup *pGroup; - PgHdr1 *pPage = 0; - - assert( pCache->bPurgeable || createFlag!=1 ); - assert( pCache->bPurgeable || pCache->nMin==0 ); - assert( pCache->bPurgeable==0 || pCache->nMin==10 ); - assert( pCache->nMin==0 || pCache->bPurgeable ); - pcache1EnterMutex(pGroup = pCache->pGroup); - - /* Step 1: Search the hash table for an existing entry. */ - if( pCache->nHash>0 ){ - unsigned int h = iKey % pCache->nHash; - for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext); - } - - /* Step 2: Abort if no existing page is found and createFlag is 0 */ - if( pPage || createFlag==0 ){ - pcache1PinPage(pPage); - goto fetch_out; - } - - /* The pGroup local variable will normally be initialized by the - ** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined, - ** then pcache1EnterMutex() is a no-op, so we have to initialize the - ** local variable here. Delaying the initialization of pGroup is an - ** optimization: The common case is to exit the module before reaching - ** this point. - */ -#ifdef SQLITE_MUTEX_OMIT - pGroup = pCache->pGroup; -#endif - - /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ - assert( pCache->nPage >= pCache->nRecyclable ); - nPinned = pCache->nPage - pCache->nRecyclable; - assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); - assert( pCache->n90pct == pCache->nMax*9/10 ); - if( createFlag==1 && ( - nPinned>=pGroup->mxPinned - || nPinned>=pCache->n90pct - || pcache1UnderMemoryPressure(pCache) - )){ - goto fetch_out; - } - - if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){ - goto fetch_out; - } - - /* Step 4. Try to recycle a page. */ - if( pCache->bPurgeable && pGroup->pLruTail && ( - (pCache->nPage+1>=pCache->nMax) - || pGroup->nCurrentPage>=pGroup->nMaxPage - || pcache1UnderMemoryPressure(pCache) - )){ - PCache1 *pOther; - pPage = pGroup->pLruTail; - pcache1RemoveFromHash(pPage); - pcache1PinPage(pPage); - pOther = pPage->pCache; - - /* We want to verify that szPage and szExtra are the same for pOther - ** and pCache. Assert that we can verify this by comparing sums. */ - assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 ); - assert( pCache->szExtra<512 ); - assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 ); - assert( pOther->szExtra<512 ); - - if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){ - pcache1FreePage(pPage); - pPage = 0; - }else{ - pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); - } - } - - /* Step 5. If a usable page buffer has still not been found, - ** attempt to allocate a new one. - */ - if( !pPage ){ - if( createFlag==1 ) sqlite3BeginBenignMalloc(); - pPage = pcache1AllocPage(pCache); - if( createFlag==1 ) sqlite3EndBenignMalloc(); - } - - if( pPage ){ - unsigned int h = iKey % pCache->nHash; - pCache->nPage++; - pPage->iKey = iKey; - pPage->pNext = pCache->apHash[h]; - pPage->pCache = pCache; - pPage->pLruPrev = 0; - pPage->pLruNext = 0; - *(void **)pPage->page.pExtra = 0; - pCache->apHash[h] = pPage; - } - -fetch_out: - if( pPage && iKey>pCache->iMaxKey ){ - pCache->iMaxKey = iKey; - } - pcache1LeaveMutex(pGroup); - return &pPage->page; -} - - -/* -** Implementation of the sqlite3_pcache.xUnpin method. -** -** Mark a page as unpinned (eligible for asynchronous recycling). -*/ -static void pcache1Unpin( - sqlite3_pcache *p, - sqlite3_pcache_page *pPg, - int reuseUnlikely -){ - PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = (PgHdr1 *)pPg; - PGroup *pGroup = pCache->pGroup; - - assert( pPage->pCache==pCache ); - pcache1EnterMutex(pGroup); - - /* It is an error to call this function if the page is already - ** part of the PGroup LRU list. - */ - assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); - assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage ); - - if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ - pcache1RemoveFromHash(pPage); - pcache1FreePage(pPage); - }else{ - /* Add the page to the PGroup LRU list. */ - if( pGroup->pLruHead ){ - pGroup->pLruHead->pLruPrev = pPage; - pPage->pLruNext = pGroup->pLruHead; - pGroup->pLruHead = pPage; - }else{ - pGroup->pLruTail = pPage; - pGroup->pLruHead = pPage; - } - pCache->nRecyclable++; - } - - pcache1LeaveMutex(pCache->pGroup); -} - -/* -** Implementation of the sqlite3_pcache.xRekey method. -*/ -static void pcache1Rekey( - sqlite3_pcache *p, - sqlite3_pcache_page *pPg, - unsigned int iOld, - unsigned int iNew -){ - PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = (PgHdr1 *)pPg; - PgHdr1 **pp; - unsigned int h; - assert( pPage->iKey==iOld ); - assert( pPage->pCache==pCache ); - - pcache1EnterMutex(pCache->pGroup); - - h = iOld%pCache->nHash; - pp = &pCache->apHash[h]; - while( (*pp)!=pPage ){ - pp = &(*pp)->pNext; - } - *pp = pPage->pNext; - - h = iNew%pCache->nHash; - pPage->iKey = iNew; - pPage->pNext = pCache->apHash[h]; - pCache->apHash[h] = pPage; - if( iNew>pCache->iMaxKey ){ - pCache->iMaxKey = iNew; - } - - pcache1LeaveMutex(pCache->pGroup); -} - -/* -** Implementation of the sqlite3_pcache.xTruncate method. -** -** Discard all unpinned pages in the cache with a page number equal to -** or greater than parameter iLimit. Any pinned pages with a page number -** equal to or greater than iLimit are implicitly unpinned. -*/ -static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){ - PCache1 *pCache = (PCache1 *)p; - pcache1EnterMutex(pCache->pGroup); - if( iLimit<=pCache->iMaxKey ){ - pcache1TruncateUnsafe(pCache, iLimit); - pCache->iMaxKey = iLimit-1; - } - pcache1LeaveMutex(pCache->pGroup); -} - -/* -** Implementation of the sqlite3_pcache.xDestroy method. -** -** Destroy a cache allocated using pcache1Create(). -*/ -static void pcache1Destroy(sqlite3_pcache *p){ - PCache1 *pCache = (PCache1 *)p; - PGroup *pGroup = pCache->pGroup; - assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); - pcache1EnterMutex(pGroup); - pcache1TruncateUnsafe(pCache, 0); - assert( pGroup->nMaxPage >= pCache->nMax ); - pGroup->nMaxPage -= pCache->nMax; - assert( pGroup->nMinPage >= pCache->nMin ); - pGroup->nMinPage -= pCache->nMin; - pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pcache1EnforceMaxPage(pGroup); - pcache1LeaveMutex(pGroup); - sqlite3_free(pCache->apHash); - sqlite3_free(pCache); -} - -/* -** This function is called during initialization (sqlite3_initialize()) to -** install the default pluggable cache module, assuming the user has not -** already provided an alternative. -*/ -SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){ - static const sqlite3_pcache_methods2 defaultMethods = { - 1, /* iVersion */ - 0, /* pArg */ - pcache1Init, /* xInit */ - pcache1Shutdown, /* xShutdown */ - pcache1Create, /* xCreate */ - pcache1Cachesize, /* xCachesize */ - pcache1Pagecount, /* xPagecount */ - pcache1Fetch, /* xFetch */ - pcache1Unpin, /* xUnpin */ - pcache1Rekey, /* xRekey */ - pcache1Truncate, /* xTruncate */ - pcache1Destroy, /* xDestroy */ - pcache1Shrink /* xShrink */ - }; - sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); -} - -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT -/* -** This function is called to free superfluous dynamically allocated memory -** held by the pager system. Memory in use by any SQLite pager allocated -** by the current thread may be sqlite3_free()ed. -** -** nReq is the number of bytes of memory required. Once this much has -** been released, the function returns. The return value is the total number -** of bytes of memory released. -*/ -SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ - int nFree = 0; - assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); - assert( sqlite3_mutex_notheld(pcache1.mutex) ); - if( pcache1.pStart==0 ){ - PgHdr1 *p; - pcache1EnterMutex(&pcache1.grp); - while( (nReq<0 || nFreepage.pBuf); -#ifdef SQLITE_PCACHE_SEPARATE_HEADER - nFree += sqlite3MemSize(p); -#endif - pcache1PinPage(p); - pcache1RemoveFromHash(p); - pcache1FreePage(p); - } - pcache1LeaveMutex(&pcache1.grp); - } - return nFree; -} -#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ - -#ifdef SQLITE_TEST -/* -** This function is used by test procedures to inspect the internal state -** of the global cache. -*/ -SQLITE_PRIVATE void sqlite3PcacheStats( - int *pnCurrent, /* OUT: Total number of pages cached */ - int *pnMax, /* OUT: Global maximum cache size */ - int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */ - int *pnRecyclable /* OUT: Total number of pages available for recycling */ -){ - PgHdr1 *p; - int nRecyclable = 0; - for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){ - nRecyclable++; - } - *pnCurrent = pcache1.grp.nCurrentPage; - *pnMax = (int)pcache1.grp.nMaxPage; - *pnMin = (int)pcache1.grp.nMinPage; - *pnRecyclable = nRecyclable; -} -#endif - -/************** End of pcache1.c *********************************************/ -/************** Begin file rowset.c ******************************************/ -/* -** 2008 December 3 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This module implements an object we call a "RowSet". -** -** The RowSet object is a collection of rowids. Rowids -** are inserted into the RowSet in an arbitrary order. Inserts -** can be intermixed with tests to see if a given rowid has been -** previously inserted into the RowSet. -** -** After all inserts are finished, it is possible to extract the -** elements of the RowSet in sorted order. Once this extraction -** process has started, no new elements may be inserted. -** -** Hence, the primitive operations for a RowSet are: -** -** CREATE -** INSERT -** TEST -** SMALLEST -** DESTROY -** -** The CREATE and DESTROY primitives are the constructor and destructor, -** obviously. The INSERT primitive adds a new element to the RowSet. -** TEST checks to see if an element is already in the RowSet. SMALLEST -** extracts the least value from the RowSet. -** -** The INSERT primitive might allocate additional memory. Memory is -** allocated in chunks so most INSERTs do no allocation. There is an -** upper bound on the size of allocated memory. No memory is freed -** until DESTROY. -** -** The TEST primitive includes a "batch" number. The TEST primitive -** will only see elements that were inserted before the last change -** in the batch number. In other words, if an INSERT occurs between -** two TESTs where the TESTs have the same batch nubmer, then the -** value added by the INSERT will not be visible to the second TEST. -** The initial batch number is zero, so if the very first TEST contains -** a non-zero batch number, it will see all prior INSERTs. -** -** No INSERTs may occurs after a SMALLEST. An assertion will fail if -** that is attempted. -** -** The cost of an INSERT is roughly constant. (Sometime new memory -** has to be allocated on an INSERT.) The cost of a TEST with a new -** batch number is O(NlogN) where N is the number of elements in the RowSet. -** The cost of a TEST using the same batch number is O(logN). The cost -** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST -** primitives are constant time. The cost of DESTROY is O(N). -** -** There is an added cost of O(N) when switching between TEST and -** SMALLEST primitives. -*/ - - -/* -** Target size for allocation chunks. -*/ -#define ROWSET_ALLOCATION_SIZE 1024 - -/* -** The number of rowset entries per allocation chunk. -*/ -#define ROWSET_ENTRY_PER_CHUNK \ - ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry)) - -/* -** Each entry in a RowSet is an instance of the following object. -** -** This same object is reused to store a linked list of trees of RowSetEntry -** objects. In that alternative use, pRight points to the next entry -** in the list, pLeft points to the tree, and v is unused. The -** RowSet.pForest value points to the head of this forest list. -*/ -struct RowSetEntry { - i64 v; /* ROWID value for this entry */ - struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */ - struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */ -}; - -/* -** RowSetEntry objects are allocated in large chunks (instances of the -** following structure) to reduce memory allocation overhead. The -** chunks are kept on a linked list so that they can be deallocated -** when the RowSet is destroyed. -*/ -struct RowSetChunk { - struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */ - struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */ -}; - -/* -** A RowSet in an instance of the following structure. -** -** A typedef of this structure if found in sqliteInt.h. -*/ -struct RowSet { - struct RowSetChunk *pChunk; /* List of all chunk allocations */ - sqlite3 *db; /* The database connection */ - struct RowSetEntry *pEntry; /* List of entries using pRight */ - struct RowSetEntry *pLast; /* Last entry on the pEntry list */ - struct RowSetEntry *pFresh; /* Source of new entry objects */ - struct RowSetEntry *pForest; /* List of binary trees of entries */ - u16 nFresh; /* Number of objects on pFresh */ - u8 rsFlags; /* Various flags */ - u8 iBatch; /* Current insert batch */ -}; - -/* -** Allowed values for RowSet.rsFlags -*/ -#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ -#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ - -/* -** Turn bulk memory into a RowSet object. N bytes of memory -** are available at pSpace. The db pointer is used as a memory context -** for any subsequent allocations that need to occur. -** Return a pointer to the new RowSet object. -** -** It must be the case that N is sufficient to make a Rowset. If not -** an assertion fault occurs. -** -** If N is larger than the minimum, use the surplus as an initial -** allocation of entries available to be filled. -*/ -SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ - RowSet *p; - assert( N >= ROUND8(sizeof(*p)) ); - p = pSpace; - p->pChunk = 0; - p->db = db; - p->pEntry = 0; - p->pLast = 0; - p->pForest = 0; - p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); - p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); - p->rsFlags = ROWSET_SORTED; - p->iBatch = 0; - return p; -} - -/* -** Deallocate all chunks from a RowSet. This frees all memory that -** the RowSet has allocated over its lifetime. This routine is -** the destructor for the RowSet. -*/ -SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ - struct RowSetChunk *pChunk, *pNextChunk; - for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ - pNextChunk = pChunk->pNextChunk; - sqlite3DbFree(p->db, pChunk); - } - p->pChunk = 0; - p->nFresh = 0; - p->pEntry = 0; - p->pLast = 0; - p->pForest = 0; - p->rsFlags = ROWSET_SORTED; -} - -/* -** Allocate a new RowSetEntry object that is associated with the -** given RowSet. Return a pointer to the new and completely uninitialized -** objected. -** -** In an OOM situation, the RowSet.db->mallocFailed flag is set and this -** routine returns NULL. -*/ -static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ - assert( p!=0 ); - if( p->nFresh==0 ){ - struct RowSetChunk *pNew; - pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); - if( pNew==0 ){ - return 0; - } - pNew->pNextChunk = p->pChunk; - p->pChunk = pNew; - p->pFresh = pNew->aEntry; - p->nFresh = ROWSET_ENTRY_PER_CHUNK; - } - p->nFresh--; - return p->pFresh++; -} - -/* -** Insert a new value into a RowSet. -** -** The mallocFailed flag of the database connection is set if a -** memory allocation fails. -*/ -SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){ - struct RowSetEntry *pEntry; /* The new entry */ - struct RowSetEntry *pLast; /* The last prior entry */ - - /* This routine is never called after sqlite3RowSetNext() */ - assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); - - pEntry = rowSetEntryAlloc(p); - if( pEntry==0 ) return; - pEntry->v = rowid; - pEntry->pRight = 0; - pLast = p->pLast; - if( pLast ){ - if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){ - p->rsFlags &= ~ROWSET_SORTED; - } - pLast->pRight = pEntry; - }else{ - p->pEntry = pEntry; - } - p->pLast = pEntry; -} - -/* -** Merge two lists of RowSetEntry objects. Remove duplicates. -** -** The input lists are connected via pRight pointers and are -** assumed to each already be in sorted order. -*/ -static struct RowSetEntry *rowSetEntryMerge( - struct RowSetEntry *pA, /* First sorted list to be merged */ - struct RowSetEntry *pB /* Second sorted list to be merged */ -){ - struct RowSetEntry head; - struct RowSetEntry *pTail; - - pTail = &head; - while( pA && pB ){ - assert( pA->pRight==0 || pA->v<=pA->pRight->v ); - assert( pB->pRight==0 || pB->v<=pB->pRight->v ); - if( pA->vv ){ - pTail->pRight = pA; - pA = pA->pRight; - pTail = pTail->pRight; - }else if( pB->vv ){ - pTail->pRight = pB; - pB = pB->pRight; - pTail = pTail->pRight; - }else{ - pA = pA->pRight; - } - } - if( pA ){ - assert( pA->pRight==0 || pA->v<=pA->pRight->v ); - pTail->pRight = pA; - }else{ - assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v ); - pTail->pRight = pB; - } - return head.pRight; -} - -/* -** Sort all elements on the list of RowSetEntry objects into order of -** increasing v. -*/ -static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ - unsigned int i; - struct RowSetEntry *pNext, *aBucket[40]; - - memset(aBucket, 0, sizeof(aBucket)); - while( pIn ){ - pNext = pIn->pRight; - pIn->pRight = 0; - for(i=0; aBucket[i]; i++){ - pIn = rowSetEntryMerge(aBucket[i], pIn); - aBucket[i] = 0; - } - aBucket[i] = pIn; - pIn = pNext; - } - pIn = 0; - for(i=0; ipLeft ){ - struct RowSetEntry *p; - rowSetTreeToList(pIn->pLeft, ppFirst, &p); - p->pRight = pIn; - }else{ - *ppFirst = pIn; - } - if( pIn->pRight ){ - rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast); - }else{ - *ppLast = pIn; - } - assert( (*ppLast)->pRight==0 ); -} - - -/* -** Convert a sorted list of elements (connected by pRight) into a binary -** tree with depth of iDepth. A depth of 1 means the tree contains a single -** node taken from the head of *ppList. A depth of 2 means a tree with -** three nodes. And so forth. -** -** Use as many entries from the input list as required and update the -** *ppList to point to the unused elements of the list. If the input -** list contains too few elements, then construct an incomplete tree -** and leave *ppList set to NULL. -** -** Return a pointer to the root of the constructed binary tree. -*/ -static struct RowSetEntry *rowSetNDeepTree( - struct RowSetEntry **ppList, - int iDepth -){ - struct RowSetEntry *p; /* Root of the new tree */ - struct RowSetEntry *pLeft; /* Left subtree */ - if( *ppList==0 ){ - return 0; - } - if( iDepth==1 ){ - p = *ppList; - *ppList = p->pRight; - p->pLeft = p->pRight = 0; - return p; - } - pLeft = rowSetNDeepTree(ppList, iDepth-1); - p = *ppList; - if( p==0 ){ - return pLeft; - } - p->pLeft = pLeft; - *ppList = p->pRight; - p->pRight = rowSetNDeepTree(ppList, iDepth-1); - return p; -} - -/* -** Convert a sorted list of elements into a binary tree. Make the tree -** as deep as it needs to be in order to contain the entire list. -*/ -static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){ - int iDepth; /* Depth of the tree so far */ - struct RowSetEntry *p; /* Current tree root */ - struct RowSetEntry *pLeft; /* Left subtree */ - - assert( pList!=0 ); - p = pList; - pList = p->pRight; - p->pLeft = p->pRight = 0; - for(iDepth=1; pList; iDepth++){ - pLeft = p; - p = pList; - pList = p->pRight; - p->pLeft = pLeft; - p->pRight = rowSetNDeepTree(&pList, iDepth); - } - return p; -} - -/* -** Take all the entries on p->pEntry and on the trees in p->pForest and -** sort them all together into one big ordered list on p->pEntry. -** -** This routine should only be called once in the life of a RowSet. -*/ -static void rowSetToList(RowSet *p){ - - /* This routine is called only once */ - assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); - - if( (p->rsFlags & ROWSET_SORTED)==0 ){ - p->pEntry = rowSetEntrySort(p->pEntry); - } - - /* While this module could theoretically support it, sqlite3RowSetNext() - ** is never called after sqlite3RowSetText() for the same RowSet. So - ** there is never a forest to deal with. Should this change, simply - ** remove the assert() and the #if 0. */ - assert( p->pForest==0 ); -#if 0 - while( p->pForest ){ - struct RowSetEntry *pTree = p->pForest->pLeft; - if( pTree ){ - struct RowSetEntry *pHead, *pTail; - rowSetTreeToList(pTree, &pHead, &pTail); - p->pEntry = rowSetEntryMerge(p->pEntry, pHead); - } - p->pForest = p->pForest->pRight; - } -#endif - p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */ -} - -/* -** Extract the smallest element from the RowSet. -** Write the element into *pRowid. Return 1 on success. Return -** 0 if the RowSet is already empty. -** -** After this routine has been called, the sqlite3RowSetInsert() -** routine may not be called again. -*/ -SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ - assert( p!=0 ); - - /* Merge the forest into a single sorted list on first call */ - if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p); - - /* Return the next entry on the list */ - if( p->pEntry ){ - *pRowid = p->pEntry->v; - p->pEntry = p->pEntry->pRight; - if( p->pEntry==0 ){ - sqlite3RowSetClear(p); - } - return 1; - }else{ - return 0; - } -} - -/* -** Check to see if element iRowid was inserted into the rowset as -** part of any insert batch prior to iBatch. Return 1 or 0. -** -** If this is the first test of a new batch and if there exist entires -** on pRowSet->pEntry, then sort those entires into the forest at -** pRowSet->pForest so that they can be tested. -*/ -SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){ - struct RowSetEntry *p, *pTree; - - /* This routine is never called after sqlite3RowSetNext() */ - assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); - - /* Sort entries into the forest on the first test of a new batch - */ - if( iBatch!=pRowSet->iBatch ){ - p = pRowSet->pEntry; - if( p ){ - struct RowSetEntry **ppPrevTree = &pRowSet->pForest; - if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ - p = rowSetEntrySort(p); - } - for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ - ppPrevTree = &pTree->pRight; - if( pTree->pLeft==0 ){ - pTree->pLeft = rowSetListToTree(p); - break; - }else{ - struct RowSetEntry *pAux, *pTail; - rowSetTreeToList(pTree->pLeft, &pAux, &pTail); - pTree->pLeft = 0; - p = rowSetEntryMerge(pAux, p); - } - } - if( pTree==0 ){ - *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet); - if( pTree ){ - pTree->v = 0; - pTree->pRight = 0; - pTree->pLeft = rowSetListToTree(p); - } - } - pRowSet->pEntry = 0; - pRowSet->pLast = 0; - pRowSet->rsFlags |= ROWSET_SORTED; - } - pRowSet->iBatch = iBatch; - } - - /* Test to see if the iRowid value appears anywhere in the forest. - ** Return 1 if it does and 0 if not. - */ - for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ - p = pTree->pLeft; - while( p ){ - if( p->vpRight; - }else if( p->v>iRowid ){ - p = p->pLeft; - }else{ - return 1; - } - } - } - return 0; -} - -/************** End of rowset.c **********************************************/ -/************** Begin file pager.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the implementation of the page cache subsystem or "pager". -** -** The pager is used to access a database disk file. It implements -** atomic commit and rollback through the use of a journal file that -** is separate from the database file. The pager also implements file -** locking to prevent two processes from writing the same database -** file simultaneously, or one process from reading the database while -** another is writing. -*/ -#ifndef SQLITE_OMIT_DISKIO -/************** Include wal.h in the middle of pager.c ***********************/ -/************** Begin file wal.h *********************************************/ -/* -** 2010 February 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface to the write-ahead logging -** system. Refer to the comments below and the header comment attached to -** the implementation of each function in log.c for further details. -*/ - -#ifndef _WAL_H_ -#define _WAL_H_ - - -/* Additional values that can be added to the sync_flags argument of -** sqlite3WalFrames(): -*/ -#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */ -#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ - -#ifdef SQLITE_OMIT_WAL -# define sqlite3WalOpen(x,y,z) 0 -# define sqlite3WalLimit(x,y) -# define sqlite3WalClose(w,x,y,z) 0 -# define sqlite3WalBeginReadTransaction(y,z) 0 -# define sqlite3WalEndReadTransaction(z) -# define sqlite3WalDbsize(y) 0 -# define sqlite3WalBeginWriteTransaction(y) 0 -# define sqlite3WalEndWriteTransaction(x) 0 -# define sqlite3WalUndo(x,y,z) 0 -# define sqlite3WalSavepoint(y,z) -# define sqlite3WalSavepointUndo(y,z) 0 -# define sqlite3WalFrames(u,v,w,x,y,z) 0 -# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 -# define sqlite3WalCallback(z) 0 -# define sqlite3WalExclusiveMode(y,z) 0 -# define sqlite3WalHeapMemory(z) 0 -# define sqlite3WalFramesize(z) 0 -# define sqlite3WalFindFrame(x,y,z) 0 -#else - -#define WAL_SAVEPOINT_NDATA 4 - -/* Connection to a write-ahead log (WAL) file. -** There is one object of this type for each pager. -*/ -typedef struct Wal Wal; - -/* Open and close a connection to a write-ahead log. */ -SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); -SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); - -/* Set the limiting size of a WAL file. */ -SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); - -/* Used by readers to open (lock) and close (unlock) a snapshot. A -** snapshot is like a read-transaction. It is the state of the database -** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and -** preserves the current state even if the other threads or processes -** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the -** transaction and releases the lock. -*/ -SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *); -SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal); - -/* Read a page from the write-ahead log, if it is present. */ -SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *); -SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *); - -/* If the WAL is not empty, return the size of the database. */ -SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal); - -/* Obtain or release the WRITER lock. */ -SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal); -SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal); - -/* Undo any frames written (but not committed) to the log */ -SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx); - -/* Return an integer that records the current (uncommitted) write -** position in the WAL */ -SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData); - -/* Move the write position of the WAL back to iFrame. Called in -** response to a ROLLBACK TO command. */ -SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData); - -/* Write a frame or frames to the log. */ -SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); - -/* Copy pages from the log to the database file */ -SQLITE_PRIVATE int sqlite3WalCheckpoint( - Wal *pWal, /* Write-ahead log connection */ - int eMode, /* One of PASSIVE, FULL and RESTART */ - int (*xBusy)(void*), /* Function to call when busy */ - void *pBusyArg, /* Context argument for xBusyHandler */ - int sync_flags, /* Flags to sync db file with (or 0) */ - int nBuf, /* Size of buffer nBuf */ - u8 *zBuf, /* Temporary buffer to use */ - int *pnLog, /* OUT: Number of frames in WAL */ - int *pnCkpt /* OUT: Number of backfilled frames in WAL */ -); - -/* Return the value to pass to a sqlite3_wal_hook callback, the -** number of frames in the WAL at the point of the last commit since -** sqlite3WalCallback() was called. If no commits have occurred since -** the last call, then return 0. -*/ -SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal); - -/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released) -** by the pager layer on the database file. -*/ -SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op); - -/* Return true if the argument is non-NULL and the WAL module is using -** heap-memory for the wal-index. Otherwise, if the argument is NULL or the -** WAL module is using shared-memory, return false. -*/ -SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); - -#ifdef SQLITE_ENABLE_ZIPVFS -/* If the WAL file is not empty, return the number of bytes of content -** stored in each frame (i.e. the db page-size when the WAL was created). -*/ -SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal); -#endif - -#endif /* ifndef SQLITE_OMIT_WAL */ -#endif /* _WAL_H_ */ - -/************** End of wal.h *************************************************/ -/************** Continuing where we left off in pager.c **********************/ - - -/******************* NOTES ON THE DESIGN OF THE PAGER ************************ -** -** This comment block describes invariants that hold when using a rollback -** journal. These invariants do not apply for journal_mode=WAL, -** journal_mode=MEMORY, or journal_mode=OFF. -** -** Within this comment block, a page is deemed to have been synced -** automatically as soon as it is written when PRAGMA synchronous=OFF. -** Otherwise, the page is not synced until the xSync method of the VFS -** is called successfully on the file containing the page. -** -** Definition: A page of the database file is said to be "overwriteable" if -** one or more of the following are true about the page: -** -** (a) The original content of the page as it was at the beginning of -** the transaction has been written into the rollback journal and -** synced. -** -** (b) The page was a freelist leaf page at the start of the transaction. -** -** (c) The page number is greater than the largest page that existed in -** the database file at the start of the transaction. -** -** (1) A page of the database file is never overwritten unless one of the -** following are true: -** -** (a) The page and all other pages on the same sector are overwriteable. -** -** (b) The atomic page write optimization is enabled, and the entire -** transaction other than the update of the transaction sequence -** number consists of a single page change. -** -** (2) The content of a page written into the rollback journal exactly matches -** both the content in the database when the rollback journal was written -** and the content in the database at the beginning of the current -** transaction. -** -** (3) Writes to the database file are an integer multiple of the page size -** in length and are aligned on a page boundary. -** -** (4) Reads from the database file are either aligned on a page boundary and -** an integer multiple of the page size in length or are taken from the -** first 100 bytes of the database file. -** -** (5) All writes to the database file are synced prior to the rollback journal -** being deleted, truncated, or zeroed. -** -** (6) If a master journal file is used, then all writes to the database file -** are synced prior to the master journal being deleted. -** -** Definition: Two databases (or the same database at two points it time) -** are said to be "logically equivalent" if they give the same answer to -** all queries. Note in particular the content of freelist leaf -** pages can be changed arbitarily without effecting the logical equivalence -** of the database. -** -** (7) At any time, if any subset, including the empty set and the total set, -** of the unsynced changes to a rollback journal are removed and the -** journal is rolled back, the resulting database file will be logical -** equivalent to the database file at the beginning of the transaction. -** -** (8) When a transaction is rolled back, the xTruncate method of the VFS -** is called to restore the database file to the same size it was at -** the beginning of the transaction. (In some VFSes, the xTruncate -** method is a no-op, but that does not change the fact the SQLite will -** invoke it.) -** -** (9) Whenever the database file is modified, at least one bit in the range -** of bytes from 24 through 39 inclusive will be changed prior to releasing -** the EXCLUSIVE lock, thus signaling other connections on the same -** database to flush their caches. -** -** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less -** than one billion transactions. -** -** (11) A database file is well-formed at the beginning and at the conclusion -** of every transaction. -** -** (12) An EXCLUSIVE lock is held on the database file when writing to -** the database file. -** -** (13) A SHARED lock is held on the database file while reading any -** content out of the database file. -** -******************************************************************************/ - -/* -** Macros for troubleshooting. Normally turned off -*/ -#if 0 -int sqlite3PagerTrace=1; /* True to enable tracing */ -#define sqlite3DebugPrintf printf -#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; } -#else -#define PAGERTRACE(X) -#endif - -/* -** The following two macros are used within the PAGERTRACE() macros above -** to print out file-descriptors. -** -** PAGERID() takes a pointer to a Pager struct as its argument. The -** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file -** struct as its argument. -*/ -#define PAGERID(p) ((int)(p->fd)) -#define FILEHANDLEID(fd) ((int)fd) - -/* -** The Pager.eState variable stores the current 'state' of a pager. A -** pager may be in any one of the seven states shown in the following -** state diagram. -** -** OPEN <------+------+ -** | | | -** V | | -** +---------> READER-------+ | -** | | | -** | V | -** |<-------WRITER_LOCKED------> ERROR -** | | ^ -** | V | -** |<------WRITER_CACHEMOD-------->| -** | | | -** | V | -** |<-------WRITER_DBMOD---------->| -** | | | -** | V | -** +<------WRITER_FINISHED-------->+ -** -** -** List of state transitions and the C [function] that performs each: -** -** OPEN -> READER [sqlite3PagerSharedLock] -** READER -> OPEN [pager_unlock] -** -** READER -> WRITER_LOCKED [sqlite3PagerBegin] -** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal] -** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal] -** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne] -** WRITER_*** -> READER [pager_end_transaction] -** -** WRITER_*** -> ERROR [pager_error] -** ERROR -> OPEN [pager_unlock] -** -** -** OPEN: -** -** The pager starts up in this state. Nothing is guaranteed in this -** state - the file may or may not be locked and the database size is -** unknown. The database may not be read or written. -** -** * No read or write transaction is active. -** * Any lock, or no lock at all, may be held on the database file. -** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted. -** -** READER: -** -** In this state all the requirements for reading the database in -** rollback (non-WAL) mode are met. Unless the pager is (or recently -** was) in exclusive-locking mode, a user-level read transaction is -** open. The database size is known in this state. -** -** A connection running with locking_mode=normal enters this state when -** it opens a read-transaction on the database and returns to state -** OPEN after the read-transaction is completed. However a connection -** running in locking_mode=exclusive (including temp databases) remains in -** this state even after the read-transaction is closed. The only way -** a locking_mode=exclusive connection can transition from READER to OPEN -** is via the ERROR state (see below). -** -** * A read transaction may be active (but a write-transaction cannot). -** * A SHARED or greater lock is held on the database file. -** * The dbSize variable may be trusted (even if a user-level read -** transaction is not active). The dbOrigSize and dbFileSize variables -** may not be trusted at this point. -** * If the database is a WAL database, then the WAL connection is open. -** * Even if a read-transaction is not open, it is guaranteed that -** there is no hot-journal in the file-system. -** -** WRITER_LOCKED: -** -** The pager moves to this state from READER when a write-transaction -** is first opened on the database. In WRITER_LOCKED state, all locks -** required to start a write-transaction are held, but no actual -** modifications to the cache or database have taken place. -** -** In rollback mode, a RESERVED or (if the transaction was opened with -** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when -** moving to this state, but the journal file is not written to or opened -** to in this state. If the transaction is committed or rolled back while -** in WRITER_LOCKED state, all that is required is to unlock the database -** file. -** -** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file. -** If the connection is running with locking_mode=exclusive, an attempt -** is made to obtain an EXCLUSIVE lock on the database file. -** -** * A write transaction is active. -** * If the connection is open in rollback-mode, a RESERVED or greater -** lock is held on the database file. -** * If the connection is open in WAL-mode, a WAL write transaction -** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully -** called). -** * The dbSize, dbOrigSize and dbFileSize variables are all valid. -** * The contents of the pager cache have not been modified. -** * The journal file may or may not be open. -** * Nothing (not even the first header) has been written to the journal. -** -** WRITER_CACHEMOD: -** -** A pager moves from WRITER_LOCKED state to this state when a page is -** first modified by the upper layer. In rollback mode the journal file -** is opened (if it is not already open) and a header written to the -** start of it. The database file on disk has not been modified. -** -** * A write transaction is active. -** * A RESERVED or greater lock is held on the database file. -** * The journal file is open and the first header has been written -** to it, but the header has not been synced to disk. -** * The contents of the page cache have been modified. -** -** WRITER_DBMOD: -** -** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state -** when it modifies the contents of the database file. WAL connections -** never enter this state (since they do not modify the database file, -** just the log file). -** -** * A write transaction is active. -** * An EXCLUSIVE or greater lock is held on the database file. -** * The journal file is open and the first header has been written -** and synced to disk. -** * The contents of the page cache have been modified (and possibly -** written to disk). -** -** WRITER_FINISHED: -** -** It is not possible for a WAL connection to enter this state. -** -** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD -** state after the entire transaction has been successfully written into the -** database file. In this state the transaction may be committed simply -** by finalizing the journal file. Once in WRITER_FINISHED state, it is -** not possible to modify the database further. At this point, the upper -** layer must either commit or rollback the transaction. -** -** * A write transaction is active. -** * An EXCLUSIVE or greater lock is held on the database file. -** * All writing and syncing of journal and database data has finished. -** If no error occurred, all that remains is to finalize the journal to -** commit the transaction. If an error did occur, the caller will need -** to rollback the transaction. -** -** ERROR: -** -** The ERROR state is entered when an IO or disk-full error (including -** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it -** difficult to be sure that the in-memory pager state (cache contents, -** db size etc.) are consistent with the contents of the file-system. -** -** Temporary pager files may enter the ERROR state, but in-memory pagers -** cannot. -** -** For example, if an IO error occurs while performing a rollback, -** the contents of the page-cache may be left in an inconsistent state. -** At this point it would be dangerous to change back to READER state -** (as usually happens after a rollback). Any subsequent readers might -** report database corruption (due to the inconsistent cache), and if -** they upgrade to writers, they may inadvertently corrupt the database -** file. To avoid this hazard, the pager switches into the ERROR state -** instead of READER following such an error. -** -** Once it has entered the ERROR state, any attempt to use the pager -** to read or write data returns an error. Eventually, once all -** outstanding transactions have been abandoned, the pager is able to -** transition back to OPEN state, discarding the contents of the -** page-cache and any other in-memory state at the same time. Everything -** is reloaded from disk (and, if necessary, hot-journal rollback peformed) -** when a read-transaction is next opened on the pager (transitioning -** the pager into READER state). At that point the system has recovered -** from the error. -** -** Specifically, the pager jumps into the ERROR state if: -** -** 1. An error occurs while attempting a rollback. This happens in -** function sqlite3PagerRollback(). -** -** 2. An error occurs while attempting to finalize a journal file -** following a commit in function sqlite3PagerCommitPhaseTwo(). -** -** 3. An error occurs while attempting to write to the journal or -** database file in function pagerStress() in order to free up -** memory. -** -** In other cases, the error is returned to the b-tree layer. The b-tree -** layer then attempts a rollback operation. If the error condition -** persists, the pager enters the ERROR state via condition (1) above. -** -** Condition (3) is necessary because it can be triggered by a read-only -** statement executed within a transaction. In this case, if the error -** code were simply returned to the user, the b-tree layer would not -** automatically attempt a rollback, as it assumes that an error in a -** read-only statement cannot leave the pager in an internally inconsistent -** state. -** -** * The Pager.errCode variable is set to something other than SQLITE_OK. -** * There are one or more outstanding references to pages (after the -** last reference is dropped the pager should move back to OPEN state). -** * The pager is not an in-memory pager. -** -** -** Notes: -** -** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the -** connection is open in WAL mode. A WAL connection is always in one -** of the first four states. -** -** * Normally, a connection open in exclusive mode is never in PAGER_OPEN -** state. There are two exceptions: immediately after exclusive-mode has -** been turned on (and before any read or write transactions are -** executed), and when the pager is leaving the "error state". -** -** * See also: assert_pager_state(). -*/ -#define PAGER_OPEN 0 -#define PAGER_READER 1 -#define PAGER_WRITER_LOCKED 2 -#define PAGER_WRITER_CACHEMOD 3 -#define PAGER_WRITER_DBMOD 4 -#define PAGER_WRITER_FINISHED 5 -#define PAGER_ERROR 6 - -/* -** The Pager.eLock variable is almost always set to one of the -** following locking-states, according to the lock currently held on -** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. -** This variable is kept up to date as locks are taken and released by -** the pagerLockDb() and pagerUnlockDb() wrappers. -** -** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY -** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not -** the operation was successful. In these circumstances pagerLockDb() and -** pagerUnlockDb() take a conservative approach - eLock is always updated -** when unlocking the file, and only updated when locking the file if the -** VFS call is successful. This way, the Pager.eLock variable may be set -** to a less exclusive (lower) value than the lock that is actually held -** at the system level, but it is never set to a more exclusive value. -** -** This is usually safe. If an xUnlock fails or appears to fail, there may -** be a few redundant xLock() calls or a lock may be held for longer than -** required, but nothing really goes wrong. -** -** The exception is when the database file is unlocked as the pager moves -** from ERROR to OPEN state. At this point there may be a hot-journal file -** in the file-system that needs to be rolled back (as part of a OPEN->SHARED -** transition, by the same pager or any other). If the call to xUnlock() -** fails at this point and the pager is left holding an EXCLUSIVE lock, this -** can confuse the call to xCheckReservedLock() call made later as part -** of hot-journal detection. -** -** xCheckReservedLock() is defined as returning true "if there is a RESERVED -** lock held by this process or any others". So xCheckReservedLock may -** return true because the caller itself is holding an EXCLUSIVE lock (but -** doesn't know it because of a previous error in xUnlock). If this happens -** a hot-journal may be mistaken for a journal being created by an active -** transaction in another process, causing SQLite to read from the database -** without rolling it back. -** -** To work around this, if a call to xUnlock() fails when unlocking the -** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It -** is only changed back to a real locking state after a successful call -** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition -** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK -** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE -** lock on the database file before attempting to roll it back. See function -** PagerSharedLock() for more detail. -** -** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in -** PAGER_OPEN state. -*/ -#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1) - -/* -** A macro used for invoking the codec if there is one -*/ -#ifdef SQLITE_HAS_CODEC -# define CODEC1(P,D,N,X,E) \ - if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; } -# define CODEC2(P,D,N,X,E,O) \ - if( P->xCodec==0 ){ O=(char*)D; }else \ - if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; } -#else -# define CODEC1(P,D,N,X,E) /* NO-OP */ -# define CODEC2(P,D,N,X,E,O) O=(char*)D -#endif - -/* -** The maximum allowed sector size. 64KiB. If the xSectorsize() method -** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. -** This could conceivably cause corruption following a power failure on -** such a system. This is currently an undocumented limit. -*/ -#define MAX_SECTOR_SIZE 0x10000 - -/* -** An instance of the following structure is allocated for each active -** savepoint and statement transaction in the system. All such structures -** are stored in the Pager.aSavepoint[] array, which is allocated and -** resized using sqlite3Realloc(). -** -** When a savepoint is created, the PagerSavepoint.iHdrOffset field is -** set to 0. If a journal-header is written into the main journal while -** the savepoint is active, then iHdrOffset is set to the byte offset -** immediately following the last journal record written into the main -** journal before the journal-header. This is required during savepoint -** rollback (see pagerPlaybackSavepoint()). -*/ -typedef struct PagerSavepoint PagerSavepoint; -struct PagerSavepoint { - i64 iOffset; /* Starting offset in main journal */ - i64 iHdrOffset; /* See above */ - Bitvec *pInSavepoint; /* Set of pages in this savepoint */ - Pgno nOrig; /* Original number of pages in file */ - Pgno iSubRec; /* Index of first record in sub-journal */ -#ifndef SQLITE_OMIT_WAL - u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */ -#endif -}; - -/* -** A open page cache is an instance of struct Pager. A description of -** some of the more important member variables follows: -** -** eState -** -** The current 'state' of the pager object. See the comment and state -** diagram above for a description of the pager state. -** -** eLock -** -** For a real on-disk database, the current lock held on the database file - -** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK. -** -** For a temporary or in-memory database (neither of which require any -** locks), this variable is always set to EXCLUSIVE_LOCK. Since such -** databases always have Pager.exclusiveMode==1, this tricks the pager -** logic into thinking that it already has all the locks it will ever -** need (and no reason to release them). -** -** In some (obscure) circumstances, this variable may also be set to -** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for -** details. -** -** changeCountDone -** -** This boolean variable is used to make sure that the change-counter -** (the 4-byte header field at byte offset 24 of the database file) is -** not updated more often than necessary. -** -** It is set to true when the change-counter field is updated, which -** can only happen if an exclusive lock is held on the database file. -** It is cleared (set to false) whenever an exclusive lock is -** relinquished on the database file. Each time a transaction is committed, -** The changeCountDone flag is inspected. If it is true, the work of -** updating the change-counter is omitted for the current transaction. -** -** This mechanism means that when running in exclusive mode, a connection -** need only update the change-counter once, for the first transaction -** committed. -** -** setMaster -** -** When PagerCommitPhaseOne() is called to commit a transaction, it may -** (or may not) specify a master-journal name to be written into the -** journal file before it is synced to disk. -** -** Whether or not a journal file contains a master-journal pointer affects -** the way in which the journal file is finalized after the transaction is -** committed or rolled back when running in "journal_mode=PERSIST" mode. -** If a journal file does not contain a master-journal pointer, it is -** finalized by overwriting the first journal header with zeroes. If -** it does contain a master-journal pointer the journal file is finalized -** by truncating it to zero bytes, just as if the connection were -** running in "journal_mode=truncate" mode. -** -** Journal files that contain master journal pointers cannot be finalized -** simply by overwriting the first journal-header with zeroes, as the -** master journal pointer could interfere with hot-journal rollback of any -** subsequently interrupted transaction that reuses the journal file. -** -** The flag is cleared as soon as the journal file is finalized (either -** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the -** journal file from being successfully finalized, the setMaster flag -** is cleared anyway (and the pager will move to ERROR state). -** -** doNotSpill, doNotSyncSpill -** -** These two boolean variables control the behavior of cache-spills -** (calls made by the pcache module to the pagerStress() routine to -** write cached data to the file-system in order to free up memory). -** -** When doNotSpill is non-zero, writing to the database from pagerStress() -** is disabled altogether. This is done in a very obscure case that -** comes up during savepoint rollback that requires the pcache module -** to allocate a new page to prevent the journal file from being written -** while it is being traversed by code in pager_playback(). -** -** If doNotSyncSpill is non-zero, writing to the database from pagerStress() -** is permitted, but syncing the journal file is not. This flag is set -** by sqlite3PagerWrite() when the file-system sector-size is larger than -** the database page-size in order to prevent a journal sync from happening -** in between the journalling of two pages on the same sector. -** -** subjInMemory -** -** This is a boolean variable. If true, then any required sub-journal -** is opened as an in-memory journal file. If false, then in-memory -** sub-journals are only used for in-memory pager files. -** -** This variable is updated by the upper layer each time a new -** write-transaction is opened. -** -** dbSize, dbOrigSize, dbFileSize -** -** Variable dbSize is set to the number of pages in the database file. -** It is valid in PAGER_READER and higher states (all states except for -** OPEN and ERROR). -** -** dbSize is set based on the size of the database file, which may be -** larger than the size of the database (the value stored at offset -** 28 of the database header by the btree). If the size of the file -** is not an integer multiple of the page-size, the value stored in -** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2). -** Except, any file that is greater than 0 bytes in size is considered -** to have at least one page. (i.e. a 1KB file with 2K page-size leads -** to dbSize==1). -** -** During a write-transaction, if pages with page-numbers greater than -** dbSize are modified in the cache, dbSize is updated accordingly. -** Similarly, if the database is truncated using PagerTruncateImage(), -** dbSize is updated. -** -** Variables dbOrigSize and dbFileSize are valid in states -** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize -** variable at the start of the transaction. It is used during rollback, -** and to determine whether or not pages need to be journalled before -** being modified. -** -** Throughout a write-transaction, dbFileSize contains the size of -** the file on disk in pages. It is set to a copy of dbSize when the -** write-transaction is first opened, and updated when VFS calls are made -** to write or truncate the database file on disk. -** -** The only reason the dbFileSize variable is required is to suppress -** unnecessary calls to xTruncate() after committing a transaction. If, -** when a transaction is committed, the dbFileSize variable indicates -** that the database file is larger than the database image (Pager.dbSize), -** pager_truncate() is called. The pager_truncate() call uses xFilesize() -** to measure the database file on disk, and then truncates it if required. -** dbFileSize is not used when rolling back a transaction. In this case -** pager_truncate() is called unconditionally (which means there may be -** a call to xFilesize() that is not strictly required). In either case, -** pager_truncate() may cause the file to become smaller or larger. -** -** dbHintSize -** -** The dbHintSize variable is used to limit the number of calls made to -** the VFS xFileControl(FCNTL_SIZE_HINT) method. -** -** dbHintSize is set to a copy of the dbSize variable when a -** write-transaction is opened (at the same time as dbFileSize and -** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called, -** dbHintSize is increased to the number of pages that correspond to the -** size-hint passed to the method call. See pager_write_pagelist() for -** details. -** -** errCode -** -** The Pager.errCode variable is only ever used in PAGER_ERROR state. It -** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode -** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX -** sub-codes. -*/ -struct Pager { - sqlite3_vfs *pVfs; /* OS functions to use for IO */ - u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ - u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ - u8 useJournal; /* Use a rollback journal on this file */ - u8 noSync; /* Do not sync the journal if true */ - u8 fullSync; /* Do extra syncs of the journal for robustness */ - u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ - u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ - u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ - u8 tempFile; /* zFilename is a temporary file */ - u8 readOnly; /* True for a read-only database */ - u8 memDb; /* True to inhibit all file I/O */ - - /************************************************************************** - ** The following block contains those class members that change during - ** routine opertion. Class members not in this block are either fixed - ** when the pager is first created or else only change when there is a - ** significant mode change (such as changing the page_size, locking_mode, - ** or the journal_mode). From another view, these class members describe - ** the "state" of the pager, while other class members describe the - ** "configuration" of the pager. - */ - u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */ - u8 eLock; /* Current lock held on database file */ - u8 changeCountDone; /* Set after incrementing the change-counter */ - u8 setMaster; /* True if a m-j name has been written to jrnl */ - u8 doNotSpill; /* Do not spill the cache when non-zero */ - u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */ - u8 subjInMemory; /* True to use in-memory sub-journals */ - Pgno dbSize; /* Number of pages in the database */ - Pgno dbOrigSize; /* dbSize before the current transaction */ - Pgno dbFileSize; /* Number of pages in the database file */ - Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ - int errCode; /* One of several kinds of errors */ - int nRec; /* Pages journalled since last j-header written */ - u32 cksumInit; /* Quasi-random value added to every checksum */ - u32 nSubRec; /* Number of records written to sub-journal */ - Bitvec *pInJournal; /* One bit for each page in the database file */ - sqlite3_file *fd; /* File descriptor for database */ - sqlite3_file *jfd; /* File descriptor for main journal */ - sqlite3_file *sjfd; /* File descriptor for sub-journal */ - i64 journalOff; /* Current write offset in the journal file */ - i64 journalHdr; /* Byte offset to previous journal header */ - sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ - PagerSavepoint *aSavepoint; /* Array of active savepoints */ - int nSavepoint; /* Number of elements in aSavepoint[] */ - char dbFileVers[16]; /* Changes whenever database file changes */ - - u8 bUseFetch; /* True to use xFetch() */ - int nMmapOut; /* Number of mmap pages currently outstanding */ - sqlite3_int64 szMmap; /* Desired maximum mmap size */ - PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ - /* - ** End of the routinely-changing class members - ***************************************************************************/ - - u16 nExtra; /* Add this many bytes to each in-memory page */ - i16 nReserve; /* Number of unused bytes at end of each page */ - u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ - u32 sectorSize; /* Assumed sector size during rollback */ - int pageSize; /* Number of bytes in a page */ - Pgno mxPgno; /* Maximum allowed size of the database */ - i64 journalSizeLimit; /* Size limit for persistent journal files */ - char *zFilename; /* Name of the database file */ - char *zJournal; /* Name of the journal file */ - int (*xBusyHandler)(void*); /* Function to call when busy */ - void *pBusyHandlerArg; /* Context argument for xBusyHandler */ - int aStat[3]; /* Total cache hits, misses and writes */ -#ifdef SQLITE_TEST - int nRead; /* Database pages read */ -#endif - void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ -#ifdef SQLITE_HAS_CODEC - void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ - void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ - void (*xCodecFree)(void*); /* Destructor for the codec */ - void *pCodec; /* First argument to xCodec... methods */ -#endif - char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ - PCache *pPCache; /* Pointer to page cache object */ -#ifndef SQLITE_OMIT_WAL - Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ - char *zWal; /* File name for write-ahead log */ -#endif -}; - -/* -** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains -** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS -** or CACHE_WRITE to sqlite3_db_status(). -*/ -#define PAGER_STAT_HIT 0 -#define PAGER_STAT_MISS 1 -#define PAGER_STAT_WRITE 2 - -/* -** The following global variables hold counters used for -** testing purposes only. These variables do not exist in -** a non-testing build. These variables are not thread-safe. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */ -SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */ -SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */ -# define PAGER_INCR(v) v++ -#else -# define PAGER_INCR(v) -#endif - - - -/* -** Journal files begin with the following magic string. The data -** was obtained from /dev/random. It is used only as a sanity check. -** -** Since version 2.8.0, the journal format contains additional sanity -** checking information. If the power fails while the journal is being -** written, semi-random garbage data might appear in the journal -** file after power is restored. If an attempt is then made -** to roll the journal back, the database could be corrupted. The additional -** sanity checking data is an attempt to discover the garbage in the -** journal and ignore it. -** -** The sanity checking information for the new journal format consists -** of a 32-bit checksum on each page of data. The checksum covers both -** the page number and the pPager->pageSize bytes of data for the page. -** This cksum is initialized to a 32-bit random value that appears in the -** journal file right after the header. The random initializer is important, -** because garbage data that appears at the end of a journal is likely -** data that was once in other files that have now been deleted. If the -** garbage data came from an obsolete journal file, the checksums might -** be correct. But by initializing the checksum to random value which -** is different for every journal, we minimize that risk. -*/ -static const unsigned char aJournalMagic[] = { - 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7, -}; - -/* -** The size of the of each page record in the journal is given by -** the following macro. -*/ -#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8) - -/* -** The journal header size for this pager. This is usually the same -** size as a single disk sector. See also setSectorSize(). -*/ -#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize) - -/* -** The macro MEMDB is true if we are dealing with an in-memory database. -** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set, -** the value of MEMDB will be a constant and the compiler will optimize -** out code that would never execute. -*/ -#ifdef SQLITE_OMIT_MEMORYDB -# define MEMDB 0 -#else -# define MEMDB pPager->memDb -#endif - -/* -** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch -** interfaces to access the database using memory-mapped I/O. -*/ -#if SQLITE_MAX_MMAP_SIZE>0 -# define USEFETCH(x) ((x)->bUseFetch) -#else -# define USEFETCH(x) 0 -#endif - -/* -** The maximum legal page number is (2^31 - 1). -*/ -#define PAGER_MAX_PGNO 2147483647 - -/* -** The argument to this macro is a file descriptor (type sqlite3_file*). -** Return 0 if it is not open, or non-zero (but not 1) if it is. -** -** This is so that expressions can be written as: -** -** if( isOpen(pPager->jfd) ){ ... -** -** instead of -** -** if( pPager->jfd->pMethods ){ ... -*/ -#define isOpen(pFd) ((pFd)->pMethods) - -/* -** Return true if this pager uses a write-ahead log instead of the usual -** rollback journal. Otherwise false. -*/ -#ifndef SQLITE_OMIT_WAL -static int pagerUseWal(Pager *pPager){ - return (pPager->pWal!=0); -} -#else -# define pagerUseWal(x) 0 -# define pagerRollbackWal(x) 0 -# define pagerWalFrames(v,w,x,y) 0 -# define pagerOpenWalIfPresent(z) SQLITE_OK -# define pagerBeginReadTransaction(z) SQLITE_OK -#endif - -#ifndef NDEBUG -/* -** Usage: -** -** assert( assert_pager_state(pPager) ); -** -** This function runs many asserts to try to find inconsistencies in -** the internal state of the Pager object. -*/ -static int assert_pager_state(Pager *p){ - Pager *pPager = p; - - /* State must be valid. */ - assert( p->eState==PAGER_OPEN - || p->eState==PAGER_READER - || p->eState==PAGER_WRITER_LOCKED - || p->eState==PAGER_WRITER_CACHEMOD - || p->eState==PAGER_WRITER_DBMOD - || p->eState==PAGER_WRITER_FINISHED - || p->eState==PAGER_ERROR - ); - - /* Regardless of the current state, a temp-file connection always behaves - ** as if it has an exclusive lock on the database file. It never updates - ** the change-counter field, so the changeCountDone flag is always set. - */ - assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK ); - assert( p->tempFile==0 || pPager->changeCountDone ); - - /* If the useJournal flag is clear, the journal-mode must be "OFF". - ** And if the journal-mode is "OFF", the journal file must not be open. - */ - assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal ); - assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) ); - - /* Check that MEMDB implies noSync. And an in-memory journal. Since - ** this means an in-memory pager performs no IO at all, it cannot encounter - ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing - ** a journal file. (although the in-memory journal implementation may - ** return SQLITE_IOERR_NOMEM while the journal file is being written). It - ** is therefore not possible for an in-memory pager to enter the ERROR - ** state. - */ - if( MEMDB ){ - assert( p->noSync ); - assert( p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_MEMORY - ); - assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN ); - assert( pagerUseWal(p)==0 ); - } - - /* If changeCountDone is set, a RESERVED lock or greater must be held - ** on the file. - */ - assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK ); - assert( p->eLock!=PENDING_LOCK ); - - switch( p->eState ){ - case PAGER_OPEN: - assert( !MEMDB ); - assert( pPager->errCode==SQLITE_OK ); - assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile ); - break; - - case PAGER_READER: - assert( pPager->errCode==SQLITE_OK ); - assert( p->eLock!=UNKNOWN_LOCK ); - assert( p->eLock>=SHARED_LOCK ); - break; - - case PAGER_WRITER_LOCKED: - assert( p->eLock!=UNKNOWN_LOCK ); - assert( pPager->errCode==SQLITE_OK ); - if( !pagerUseWal(pPager) ){ - assert( p->eLock>=RESERVED_LOCK ); - } - assert( pPager->dbSize==pPager->dbOrigSize ); - assert( pPager->dbOrigSize==pPager->dbFileSize ); - assert( pPager->dbOrigSize==pPager->dbHintSize ); - assert( pPager->setMaster==0 ); - break; - - case PAGER_WRITER_CACHEMOD: - assert( p->eLock!=UNKNOWN_LOCK ); - assert( pPager->errCode==SQLITE_OK ); - if( !pagerUseWal(pPager) ){ - /* It is possible that if journal_mode=wal here that neither the - ** journal file nor the WAL file are open. This happens during - ** a rollback transaction that switches from journal_mode=off - ** to journal_mode=wal. - */ - assert( p->eLock>=RESERVED_LOCK ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL - ); - } - assert( pPager->dbOrigSize==pPager->dbFileSize ); - assert( pPager->dbOrigSize==pPager->dbHintSize ); - break; - - case PAGER_WRITER_DBMOD: - assert( p->eLock==EXCLUSIVE_LOCK ); - assert( pPager->errCode==SQLITE_OK ); - assert( !pagerUseWal(pPager) ); - assert( p->eLock>=EXCLUSIVE_LOCK ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL - ); - assert( pPager->dbOrigSize<=pPager->dbHintSize ); - break; - - case PAGER_WRITER_FINISHED: - assert( p->eLock==EXCLUSIVE_LOCK ); - assert( pPager->errCode==SQLITE_OK ); - assert( !pagerUseWal(pPager) ); - assert( isOpen(p->jfd) - || p->journalMode==PAGER_JOURNALMODE_OFF - || p->journalMode==PAGER_JOURNALMODE_WAL - ); - break; - - case PAGER_ERROR: - /* There must be at least one outstanding reference to the pager if - ** in ERROR state. Otherwise the pager should have already dropped - ** back to OPEN state. - */ - assert( pPager->errCode!=SQLITE_OK ); - assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); - break; - } - - return 1; -} -#endif /* ifndef NDEBUG */ - -#ifdef SQLITE_DEBUG -/* -** Return a pointer to a human readable string in a static buffer -** containing the state of the Pager object passed as an argument. This -** is intended to be used within debuggers. For example, as an alternative -** to "print *pPager" in gdb: -** -** (gdb) printf "%s", print_pager_state(pPager) -*/ -static char *print_pager_state(Pager *p){ - static char zRet[1024]; - - sqlite3_snprintf(1024, zRet, - "Filename: %s\n" - "State: %s errCode=%d\n" - "Lock: %s\n" - "Locking mode: locking_mode=%s\n" - "Journal mode: journal_mode=%s\n" - "Backing store: tempFile=%d memDb=%d useJournal=%d\n" - "Journal: journalOff=%lld journalHdr=%lld\n" - "Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n" - , p->zFilename - , p->eState==PAGER_OPEN ? "OPEN" : - p->eState==PAGER_READER ? "READER" : - p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" : - p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" : - p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" : - p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" : - p->eState==PAGER_ERROR ? "ERROR" : "?error?" - , (int)p->errCode - , p->eLock==NO_LOCK ? "NO_LOCK" : - p->eLock==RESERVED_LOCK ? "RESERVED" : - p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" : - p->eLock==SHARED_LOCK ? "SHARED" : - p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?" - , p->exclusiveMode ? "exclusive" : "normal" - , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" : - p->journalMode==PAGER_JOURNALMODE_OFF ? "off" : - p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" : - p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" : - p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" : - p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?" - , (int)p->tempFile, (int)p->memDb, (int)p->useJournal - , p->journalOff, p->journalHdr - , (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize - ); - - return zRet; -} -#endif - -/* -** Return true if it is necessary to write page *pPg into the sub-journal. -** A page needs to be written into the sub-journal if there exists one -** or more open savepoints for which: -** -** * The page-number is less than or equal to PagerSavepoint.nOrig, and -** * The bit corresponding to the page-number is not set in -** PagerSavepoint.pInSavepoint. -*/ -static int subjRequiresPage(PgHdr *pPg){ - Pgno pgno = pPg->pgno; - Pager *pPager = pPg->pPager; - int i; - for(i=0; inSavepoint; i++){ - PagerSavepoint *p = &pPager->aSavepoint[i]; - if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){ - return 1; - } - } - return 0; -} - -/* -** Return true if the page is already in the journal file. -*/ -static int pageInJournal(PgHdr *pPg){ - return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno); -} - -/* -** Read a 32-bit integer from the given file descriptor. Store the integer -** that is read in *pRes. Return SQLITE_OK if everything worked, or an -** error code is something goes wrong. -** -** All values are stored on disk as big-endian. -*/ -static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){ - unsigned char ac[4]; - int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset); - if( rc==SQLITE_OK ){ - *pRes = sqlite3Get4byte(ac); - } - return rc; -} - -/* -** Write a 32-bit integer into a string buffer in big-endian byte order. -*/ -#define put32bits(A,B) sqlite3Put4byte((u8*)A,B) - - -/* -** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK -** on success or an error code is something goes wrong. -*/ -static int write32bits(sqlite3_file *fd, i64 offset, u32 val){ - char ac[4]; - put32bits(ac, val); - return sqlite3OsWrite(fd, ac, 4, offset); -} - -/* -** Unlock the database file to level eLock, which must be either NO_LOCK -** or SHARED_LOCK. Regardless of whether or not the call to xUnlock() -** succeeds, set the Pager.eLock variable to match the (attempted) new lock. -** -** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is -** called, do not modify it. See the comment above the #define of -** UNKNOWN_LOCK for an explanation of this. -*/ -static int pagerUnlockDb(Pager *pPager, int eLock){ - int rc = SQLITE_OK; - - assert( !pPager->exclusiveMode || pPager->eLock==eLock ); - assert( eLock==NO_LOCK || eLock==SHARED_LOCK ); - assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); - if( isOpen(pPager->fd) ){ - assert( pPager->eLock>=eLock ); - rc = sqlite3OsUnlock(pPager->fd, eLock); - if( pPager->eLock!=UNKNOWN_LOCK ){ - pPager->eLock = (u8)eLock; - } - IOTRACE(("UNLOCK %p %d\n", pPager, eLock)) - } - return rc; -} - -/* -** Lock the database file to level eLock, which must be either SHARED_LOCK, -** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the -** Pager.eLock variable to the new locking state. -** -** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is -** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. -** See the comment above the #define of UNKNOWN_LOCK for an explanation -** of this. -*/ -static int pagerLockDb(Pager *pPager, int eLock){ - int rc = SQLITE_OK; - - assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); - if( pPager->eLockeLock==UNKNOWN_LOCK ){ - rc = sqlite3OsLock(pPager->fd, eLock); - if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){ - pPager->eLock = (u8)eLock; - IOTRACE(("LOCK %p %d\n", pPager, eLock)) - } - } - return rc; -} - -/* -** This function determines whether or not the atomic-write optimization -** can be used with this pager. The optimization can be used if: -** -** (a) the value returned by OsDeviceCharacteristics() indicates that -** a database page may be written atomically, and -** (b) the value returned by OsSectorSize() is less than or equal -** to the page size. -** -** The optimization is also always enabled for temporary files. It is -** an error to call this function if pPager is opened on an in-memory -** database. -** -** If the optimization cannot be used, 0 is returned. If it can be used, -** then the value returned is the size of the journal file when it -** contains rollback data for exactly one page. -*/ -#ifdef SQLITE_ENABLE_ATOMIC_WRITE -static int jrnlBufferSize(Pager *pPager){ - assert( !MEMDB ); - if( !pPager->tempFile ){ - int dc; /* Device characteristics */ - int nSector; /* Sector size */ - int szPage; /* Page size */ - - assert( isOpen(pPager->fd) ); - dc = sqlite3OsDeviceCharacteristics(pPager->fd); - nSector = pPager->sectorSize; - szPage = pPager->pageSize; - - assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); - assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); - if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){ - return 0; - } - } - - return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); -} -#endif - -/* -** If SQLITE_CHECK_PAGES is defined then we do some sanity checking -** on the cache using a hash function. This is used for testing -** and debugging only. -*/ -#ifdef SQLITE_CHECK_PAGES -/* -** Return a 32-bit hash of the page data for pPage. -*/ -static u32 pager_datahash(int nByte, unsigned char *pData){ - u32 hash = 0; - int i; - for(i=0; ipPager->pageSize, (unsigned char *)pPage->pData); -} -static void pager_set_pagehash(PgHdr *pPage){ - pPage->pageHash = pager_pagehash(pPage); -} - -/* -** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES -** is defined, and NDEBUG is not defined, an assert() statement checks -** that the page is either dirty or still matches the calculated page-hash. -*/ -#define CHECK_PAGE(x) checkPage(x) -static void checkPage(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - assert( pPager->eState!=PAGER_ERROR ); - assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) ); -} - -#else -#define pager_datahash(X,Y) 0 -#define pager_pagehash(X) 0 -#define pager_set_pagehash(X) -#define CHECK_PAGE(x) -#endif /* SQLITE_CHECK_PAGES */ - -/* -** When this is called the journal file for pager pPager must be open. -** This function attempts to read a master journal file name from the -** end of the file and, if successful, copies it into memory supplied -** by the caller. See comments above writeMasterJournal() for the format -** used to store a master journal file name at the end of a journal file. -** -** zMaster must point to a buffer of at least nMaster bytes allocated by -** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is -** enough space to write the master journal name). If the master journal -** name in the journal is longer than nMaster bytes (including a -** nul-terminator), then this is handled as if no master journal name -** were present in the journal. -** -** If a master journal file name is present at the end of the journal -** file, then it is copied into the buffer pointed to by zMaster. A -** nul-terminator byte is appended to the buffer following the master -** journal file name. -** -** If it is determined that no master journal file name is present -** zMaster[0] is set to 0 and SQLITE_OK returned. -** -** If an error occurs while reading from the journal file, an SQLite -** error code is returned. -*/ -static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){ - int rc; /* Return code */ - u32 len; /* Length in bytes of master journal name */ - i64 szJ; /* Total size in bytes of journal file pJrnl */ - u32 cksum; /* MJ checksum value read from journal */ - u32 u; /* Unsigned loop counter */ - unsigned char aMagic[8]; /* A buffer to hold the magic header */ - zMaster[0] = '\0'; - - if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ)) - || szJ<16 - || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) - || len>=nMaster - || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) - || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) - || memcmp(aMagic, aJournalMagic, 8) - || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len)) - ){ - return rc; - } - - /* See if the checksum matches the master journal name */ - for(u=0; ujournalOff, assuming a sector -** size of pPager->sectorSize bytes. -** -** i.e for a sector size of 512: -** -** Pager.journalOff Return value -** --------------------------------------- -** 0 0 -** 512 512 -** 100 512 -** 2000 2048 -** -*/ -static i64 journalHdrOffset(Pager *pPager){ - i64 offset = 0; - i64 c = pPager->journalOff; - if( c ){ - offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); - } - assert( offset%JOURNAL_HDR_SZ(pPager)==0 ); - assert( offset>=c ); - assert( (offset-c)jfd) ); - if( pPager->journalOff ){ - const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */ - - IOTRACE(("JZEROHDR %p\n", pPager)) - if( doTruncate || iLimit==0 ){ - rc = sqlite3OsTruncate(pPager->jfd, 0); - }else{ - static const char zeroHdr[28] = {0}; - rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); - } - if( rc==SQLITE_OK && !pPager->noSync ){ - rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags); - } - - /* At this point the transaction is committed but the write lock - ** is still held on the file. If there is a size limit configured for - ** the persistent journal and the journal file currently consumes more - ** space than that limit allows for, truncate it now. There is no need - ** to sync the file following this operation. - */ - if( rc==SQLITE_OK && iLimit>0 ){ - i64 sz; - rc = sqlite3OsFileSize(pPager->jfd, &sz); - if( rc==SQLITE_OK && sz>iLimit ){ - rc = sqlite3OsTruncate(pPager->jfd, iLimit); - } - } - } - return rc; -} - -/* -** The journal file must be open when this routine is called. A journal -** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the -** current location. -** -** The format for the journal header is as follows: -** - 8 bytes: Magic identifying journal format. -** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. -** - 4 bytes: Random number used for page hash. -** - 4 bytes: Initial database page count. -** - 4 bytes: Sector size used by the process that wrote this journal. -** - 4 bytes: Database page size. -** -** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space. -*/ -static int writeJournalHdr(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */ - u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */ - u32 nWrite; /* Bytes of header sector written */ - int ii; /* Loop counter */ - - assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ - - if( nHeader>JOURNAL_HDR_SZ(pPager) ){ - nHeader = JOURNAL_HDR_SZ(pPager); - } - - /* If there are active savepoints and any of them were created - ** since the most recent journal header was written, update the - ** PagerSavepoint.iHdrOffset fields now. - */ - for(ii=0; iinSavepoint; ii++){ - if( pPager->aSavepoint[ii].iHdrOffset==0 ){ - pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff; - } - } - - pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager); - - /* - ** Write the nRec Field - the number of page records that follow this - ** journal header. Normally, zero is written to this value at this time. - ** After the records are added to the journal (and the journal synced, - ** if in full-sync mode), the zero is overwritten with the true number - ** of records (see syncJournal()). - ** - ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When - ** reading the journal this value tells SQLite to assume that the - ** rest of the journal file contains valid page records. This assumption - ** is dangerous, as if a failure occurred whilst writing to the journal - ** file it may contain some garbage data. There are two scenarios - ** where this risk can be ignored: - ** - ** * When the pager is in no-sync mode. Corruption can follow a - ** power failure in this case anyway. - ** - ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees - ** that garbage data is never appended to the journal file. - */ - assert( isOpen(pPager->fd) || pPager->noSync ); - if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) - || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) - ){ - memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); - put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); - }else{ - memset(zHeader, 0, sizeof(aJournalMagic)+4); - } - - /* The random check-hash initializer */ - sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); - put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); - /* The initial database size */ - put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize); - /* The assumed sector size for this process */ - put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); - - /* The page size */ - put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize); - - /* Initializing the tail of the buffer is not necessary. Everything - ** works find if the following memset() is omitted. But initializing - ** the memory prevents valgrind from complaining, so we are willing to - ** take the performance hit. - */ - memset(&zHeader[sizeof(aJournalMagic)+20], 0, - nHeader-(sizeof(aJournalMagic)+20)); - - /* In theory, it is only necessary to write the 28 bytes that the - ** journal header consumes to the journal file here. Then increment the - ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next - ** record is written to the following sector (leaving a gap in the file - ** that will be implicitly filled in by the OS). - ** - ** However it has been discovered that on some systems this pattern can - ** be significantly slower than contiguously writing data to the file, - ** even if that means explicitly writing data to the block of - ** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what - ** is done. - ** - ** The loop is required here in case the sector-size is larger than the - ** database page size. Since the zHeader buffer is only Pager.pageSize - ** bytes in size, more than one call to sqlite3OsWrite() may be required - ** to populate the entire journal header sector. - */ - for(nWrite=0; rc==SQLITE_OK&&nWritejournalHdr, nHeader)) - rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff); - assert( pPager->journalHdr <= pPager->journalOff ); - pPager->journalOff += nHeader; - } - - return rc; -} - -/* -** The journal file must be open when this is called. A journal header file -** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal -** file. The current location in the journal file is given by -** pPager->journalOff. See comments above function writeJournalHdr() for -** a description of the journal header format. -** -** If the header is read successfully, *pNRec is set to the number of -** page records following this header and *pDbSize is set to the size of the -** database before the transaction began, in pages. Also, pPager->cksumInit -** is set to the value read from the journal header. SQLITE_OK is returned -** in this case. -** -** If the journal header file appears to be corrupted, SQLITE_DONE is -** returned and *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes -** cannot be read from the journal file an error code is returned. -*/ -static int readJournalHdr( - Pager *pPager, /* Pager object */ - int isHot, - i64 journalSize, /* Size of the open journal file in bytes */ - u32 *pNRec, /* OUT: Value read from the nRec field */ - u32 *pDbSize /* OUT: Value of original database size field */ -){ - int rc; /* Return code */ - unsigned char aMagic[8]; /* A buffer to hold the magic header */ - i64 iHdrOff; /* Offset of journal header being read */ - - assert( isOpen(pPager->jfd) ); /* Journal file must be open. */ - - /* Advance Pager.journalOff to the start of the next sector. If the - ** journal file is too small for there to be a header stored at this - ** point, return SQLITE_DONE. - */ - pPager->journalOff = journalHdrOffset(pPager); - if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ - return SQLITE_DONE; - } - iHdrOff = pPager->journalOff; - - /* Read in the first 8 bytes of the journal header. If they do not match - ** the magic string found at the start of each journal header, return - ** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise, - ** proceed. - */ - if( isHot || iHdrOff!=pPager->journalHdr ){ - rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff); - if( rc ){ - return rc; - } - if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ - return SQLITE_DONE; - } - } - - /* Read the first three 32-bit fields of the journal header: The nRec - ** field, the checksum-initializer and the database size at the start - ** of the transaction. Return an error code if anything goes wrong. - */ - if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec)) - || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit)) - || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize)) - ){ - return rc; - } - - if( pPager->journalOff==0 ){ - u32 iPageSize; /* Page-size field of journal header */ - u32 iSectorSize; /* Sector-size field of journal header */ - - /* Read the page-size and sector-size journal header fields. */ - if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize)) - || SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize)) - ){ - return rc; - } - - /* Versions of SQLite prior to 3.5.8 set the page-size field of the - ** journal header to zero. In this case, assume that the Pager.pageSize - ** variable is already set to the correct page size. - */ - if( iPageSize==0 ){ - iPageSize = pPager->pageSize; - } - - /* Check that the values read from the page-size and sector-size fields - ** are within range. To be 'in range', both values need to be a power - ** of two greater than or equal to 512 or 32, and not greater than their - ** respective compile time maximum limits. - */ - if( iPageSize<512 || iSectorSize<32 - || iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE - || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0 - ){ - /* If the either the page-size or sector-size in the journal-header is - ** invalid, then the process that wrote the journal-header must have - ** crashed before the header was synced. In this case stop reading - ** the journal file here. - */ - return SQLITE_DONE; - } - - /* Update the page-size to match the value read from the journal. - ** Use a testcase() macro to make sure that malloc failure within - ** PagerSetPagesize() is tested. - */ - rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1); - testcase( rc!=SQLITE_OK ); - - /* Update the assumed sector-size to match the value used by - ** the process that created this journal. If this journal was - ** created by a process other than this one, then this routine - ** is being called from within pager_playback(). The local value - ** of Pager.sectorSize is restored at the end of that routine. - */ - pPager->sectorSize = iSectorSize; - } - - pPager->journalOff += JOURNAL_HDR_SZ(pPager); - return rc; -} - - -/* -** Write the supplied master journal name into the journal file for pager -** pPager at the current location. The master journal name must be the last -** thing written to a journal file. If the pager is in full-sync mode, the -** journal file descriptor is advanced to the next sector boundary before -** anything is written. The format is: -** -** + 4 bytes: PAGER_MJ_PGNO. -** + N bytes: Master journal filename in utf-8. -** + 4 bytes: N (length of master journal name in bytes, no nul-terminator). -** + 4 bytes: Master journal name checksum. -** + 8 bytes: aJournalMagic[]. -** -** The master journal page checksum is the sum of the bytes in the master -** journal name, where each byte is interpreted as a signed 8-bit integer. -** -** If zMaster is a NULL pointer (occurs for a single database transaction), -** this call is a no-op. -*/ -static int writeMasterJournal(Pager *pPager, const char *zMaster){ - int rc; /* Return code */ - int nMaster; /* Length of string zMaster */ - i64 iHdrOff; /* Offset of header in journal file */ - i64 jrnlSize; /* Size of journal file on disk */ - u32 cksum = 0; /* Checksum of string zMaster */ - - assert( pPager->setMaster==0 ); - assert( !pagerUseWal(pPager) ); - - if( !zMaster - || pPager->journalMode==PAGER_JOURNALMODE_MEMORY - || pPager->journalMode==PAGER_JOURNALMODE_OFF - ){ - return SQLITE_OK; - } - pPager->setMaster = 1; - assert( isOpen(pPager->jfd) ); - assert( pPager->journalHdr <= pPager->journalOff ); - - /* Calculate the length in bytes and the checksum of zMaster */ - for(nMaster=0; zMaster[nMaster]; nMaster++){ - cksum += zMaster[nMaster]; - } - - /* If in full-sync mode, advance to the next disk sector before writing - ** the master journal name. This is in case the previous page written to - ** the journal has already been synced. - */ - if( pPager->fullSync ){ - pPager->journalOff = journalHdrOffset(pPager); - } - iHdrOff = pPager->journalOff; - - /* Write the master journal data to the end of the journal file. If - ** an error occurs, return the error code to the caller. - */ - if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager)))) - || (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4))) - || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster))) - || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum))) - || (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8, iHdrOff+4+nMaster+8))) - ){ - return rc; - } - pPager->journalOff += (nMaster+20); - - /* If the pager is in peristent-journal mode, then the physical - ** journal-file may extend past the end of the master-journal name - ** and 8 bytes of magic data just written to the file. This is - ** dangerous because the code to rollback a hot-journal file - ** will not be able to find the master-journal name to determine - ** whether or not the journal is hot. - ** - ** Easiest thing to do in this scenario is to truncate the journal - ** file to the required size. - */ - if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize)) - && jrnlSize>pPager->journalOff - ){ - rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff); - } - return rc; -} - -/* -** Find a page in the hash table given its page number. Return -** a pointer to the page or NULL if the requested page is not -** already in memory. -*/ -static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ - PgHdr *p; /* Return value */ - - /* It is not possible for a call to PcacheFetch() with createFlag==0 to - ** fail, since no attempt to allocate dynamic memory will be made. - */ - (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p); - return p; -} - -/* -** Discard the entire contents of the in-memory page-cache. -*/ -static void pager_reset(Pager *pPager){ - sqlite3BackupRestart(pPager->pBackup); - sqlite3PcacheClear(pPager->pPCache); -} - -/* -** Free all structures in the Pager.aSavepoint[] array and set both -** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal -** if it is open and the pager is not in exclusive mode. -*/ -static void releaseAllSavepoints(Pager *pPager){ - int ii; /* Iterator for looping through Pager.aSavepoint */ - for(ii=0; iinSavepoint; ii++){ - sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); - } - if( !pPager->exclusiveMode || sqlite3IsMemJournal(pPager->sjfd) ){ - sqlite3OsClose(pPager->sjfd); - } - sqlite3_free(pPager->aSavepoint); - pPager->aSavepoint = 0; - pPager->nSavepoint = 0; - pPager->nSubRec = 0; -} - -/* -** Set the bit number pgno in the PagerSavepoint.pInSavepoint -** bitvecs of all open savepoints. Return SQLITE_OK if successful -** or SQLITE_NOMEM if a malloc failure occurs. -*/ -static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){ - int ii; /* Loop counter */ - int rc = SQLITE_OK; /* Result code */ - - for(ii=0; iinSavepoint; ii++){ - PagerSavepoint *p = &pPager->aSavepoint[ii]; - if( pgno<=p->nOrig ){ - rc |= sqlite3BitvecSet(p->pInSavepoint, pgno); - testcase( rc==SQLITE_NOMEM ); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - } - } - return rc; -} - -/* -** This function is a no-op if the pager is in exclusive mode and not -** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN -** state. -** -** If the pager is not in exclusive-access mode, the database file is -** completely unlocked. If the file is unlocked and the file-system does -** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is -** closed (if it is open). -** -** If the pager is in ERROR state when this function is called, the -** contents of the pager cache are discarded before switching back to -** the OPEN state. Regardless of whether the pager is in exclusive-mode -** or not, any journal file left in the file-system will be treated -** as a hot-journal and rolled back the next time a read-transaction -** is opened (by this or by any other connection). -*/ -static void pager_unlock(Pager *pPager){ - - assert( pPager->eState==PAGER_READER - || pPager->eState==PAGER_OPEN - || pPager->eState==PAGER_ERROR - ); - - sqlite3BitvecDestroy(pPager->pInJournal); - pPager->pInJournal = 0; - releaseAllSavepoints(pPager); - - if( pagerUseWal(pPager) ){ - assert( !isOpen(pPager->jfd) ); - sqlite3WalEndReadTransaction(pPager->pWal); - pPager->eState = PAGER_OPEN; - }else if( !pPager->exclusiveMode ){ - int rc; /* Error code returned by pagerUnlockDb() */ - int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0; - - /* If the operating system support deletion of open files, then - ** close the journal file when dropping the database lock. Otherwise - ** another connection with journal_mode=delete might delete the file - ** out from under us. - */ - assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 ); - assert( (PAGER_JOURNALMODE_OFF & 5)!=1 ); - assert( (PAGER_JOURNALMODE_WAL & 5)!=1 ); - assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 ); - assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); - assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); - if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN) - || 1!=(pPager->journalMode & 5) - ){ - sqlite3OsClose(pPager->jfd); - } - - /* If the pager is in the ERROR state and the call to unlock the database - ** file fails, set the current lock to UNKNOWN_LOCK. See the comment - ** above the #define for UNKNOWN_LOCK for an explanation of why this - ** is necessary. - */ - rc = pagerUnlockDb(pPager, NO_LOCK); - if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){ - pPager->eLock = UNKNOWN_LOCK; - } - - /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here - ** without clearing the error code. This is intentional - the error - ** code is cleared and the cache reset in the block below. - */ - assert( pPager->errCode || pPager->eState!=PAGER_ERROR ); - pPager->changeCountDone = 0; - pPager->eState = PAGER_OPEN; - } - - /* If Pager.errCode is set, the contents of the pager cache cannot be - ** trusted. Now that there are no outstanding references to the pager, - ** it can safely move back to PAGER_OPEN state. This happens in both - ** normal and exclusive-locking mode. - */ - if( pPager->errCode ){ - assert( !MEMDB ); - pager_reset(pPager); - pPager->changeCountDone = pPager->tempFile; - pPager->eState = PAGER_OPEN; - pPager->errCode = SQLITE_OK; - } - - pPager->journalOff = 0; - pPager->journalHdr = 0; - pPager->setMaster = 0; -} - -/* -** This function is called whenever an IOERR or FULL error that requires -** the pager to transition into the ERROR state may ahve occurred. -** The first argument is a pointer to the pager structure, the second -** the error-code about to be returned by a pager API function. The -** value returned is a copy of the second argument to this function. -** -** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the -** IOERR sub-codes, the pager enters the ERROR state and the error code -** is stored in Pager.errCode. While the pager remains in the ERROR state, -** all major API calls on the Pager will immediately return Pager.errCode. -** -** The ERROR state indicates that the contents of the pager-cache -** cannot be trusted. This state can be cleared by completely discarding -** the contents of the pager-cache. If a transaction was active when -** the persistent error occurred, then the rollback journal may need -** to be replayed to restore the contents of the database file (as if -** it were a hot-journal). -*/ -static int pager_error(Pager *pPager, int rc){ - int rc2 = rc & 0xff; - assert( rc==SQLITE_OK || !MEMDB ); - assert( - pPager->errCode==SQLITE_FULL || - pPager->errCode==SQLITE_OK || - (pPager->errCode & 0xff)==SQLITE_IOERR - ); - if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ - pPager->errCode = rc; - pPager->eState = PAGER_ERROR; - } - return rc; -} - -static int pager_truncate(Pager *pPager, Pgno nPage); - -/* -** This routine ends a transaction. A transaction is usually ended by -** either a COMMIT or a ROLLBACK operation. This routine may be called -** after rollback of a hot-journal, or if an error occurs while opening -** the journal file or writing the very first journal-header of a -** database transaction. -** -** This routine is never called in PAGER_ERROR state. If it is called -** in PAGER_NONE or PAGER_SHARED state and the lock held is less -** exclusive than a RESERVED lock, it is a no-op. -** -** Otherwise, any active savepoints are released. -** -** If the journal file is open, then it is "finalized". Once a journal -** file has been finalized it is not possible to use it to roll back a -** transaction. Nor will it be considered to be a hot-journal by this -** or any other database connection. Exactly how a journal is finalized -** depends on whether or not the pager is running in exclusive mode and -** the current journal-mode (Pager.journalMode value), as follows: -** -** journalMode==MEMORY -** Journal file descriptor is simply closed. This destroys an -** in-memory journal. -** -** journalMode==TRUNCATE -** Journal file is truncated to zero bytes in size. -** -** journalMode==PERSIST -** The first 28 bytes of the journal file are zeroed. This invalidates -** the first journal header in the file, and hence the entire journal -** file. An invalid journal file cannot be rolled back. -** -** journalMode==DELETE -** The journal file is closed and deleted using sqlite3OsDelete(). -** -** If the pager is running in exclusive mode, this method of finalizing -** the journal file is never used. Instead, if the journalMode is -** DELETE and the pager is in exclusive mode, the method described under -** journalMode==PERSIST is used instead. -** -** After the journal is finalized, the pager moves to PAGER_READER state. -** If running in non-exclusive rollback mode, the lock on the file is -** downgraded to a SHARED_LOCK. -** -** SQLITE_OK is returned if no error occurs. If an error occurs during -** any of the IO operations to finalize the journal file or unlock the -** database then the IO error code is returned to the user. If the -** operation to finalize the journal file fails, then the code still -** tries to unlock the database file if not in exclusive mode. If the -** unlock operation fails as well, then the first error code related -** to the first error encountered (the journal finalization one) is -** returned. -*/ -static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ - int rc = SQLITE_OK; /* Error code from journal finalization operation */ - int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ - - /* Do nothing if the pager does not have an open write transaction - ** or at least a RESERVED lock. This function may be called when there - ** is no write-transaction active but a RESERVED or greater lock is - ** held under two circumstances: - ** - ** 1. After a successful hot-journal rollback, it is called with - ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK. - ** - ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE - ** lock switches back to locking_mode=normal and then executes a - ** read-transaction, this function is called with eState==PAGER_READER - ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed. - */ - assert( assert_pager_state(pPager) ); - assert( pPager->eState!=PAGER_ERROR ); - if( pPager->eStateeLockjfd) || pPager->pInJournal==0 ); - if( isOpen(pPager->jfd) ){ - assert( !pagerUseWal(pPager) ); - - /* Finalize the journal file. */ - if( sqlite3IsMemJournal(pPager->jfd) ){ - assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); - sqlite3OsClose(pPager->jfd); - }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){ - if( pPager->journalOff==0 ){ - rc = SQLITE_OK; - }else{ - rc = sqlite3OsTruncate(pPager->jfd, 0); - } - pPager->journalOff = 0; - }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST - || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL) - ){ - rc = zeroJournalHdr(pPager, hasMaster); - pPager->journalOff = 0; - }else{ - /* This branch may be executed with Pager.journalMode==MEMORY if - ** a hot-journal was just rolled back. In this case the journal - ** file should be closed and deleted. If this connection writes to - ** the database file, it will do so using an in-memory journal. - */ - int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd)); - assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE - || pPager->journalMode==PAGER_JOURNALMODE_MEMORY - || pPager->journalMode==PAGER_JOURNALMODE_WAL - ); - sqlite3OsClose(pPager->jfd); - if( bDelete ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); - } - } - } - -#ifdef SQLITE_CHECK_PAGES - sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); - if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ - PgHdr *p = pager_lookup(pPager, 1); - if( p ){ - p->pageHash = 0; - sqlite3PagerUnref(p); - } - } -#endif - - sqlite3BitvecDestroy(pPager->pInJournal); - pPager->pInJournal = 0; - pPager->nRec = 0; - sqlite3PcacheCleanAll(pPager->pPCache); - sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); - - if( pagerUseWal(pPager) ){ - /* Drop the WAL write-lock, if any. Also, if the connection was in - ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE - ** lock held on the database file. - */ - rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); - assert( rc2==SQLITE_OK ); - }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){ - /* This branch is taken when committing a transaction in rollback-journal - ** mode if the database file on disk is larger than the database image. - ** At this point the journal has been finalized and the transaction - ** successfully committed, but the EXCLUSIVE lock is still held on the - ** file. So it is safe to truncate the database file to its minimum - ** required size. */ - assert( pPager->eLock==EXCLUSIVE_LOCK ); - rc = pager_truncate(pPager, pPager->dbSize); - } - - if( !pPager->exclusiveMode - && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) - ){ - rc2 = pagerUnlockDb(pPager, SHARED_LOCK); - pPager->changeCountDone = 0; - } - pPager->eState = PAGER_READER; - pPager->setMaster = 0; - - return (rc==SQLITE_OK?rc2:rc); -} - -/* -** Execute a rollback if a transaction is active and unlock the -** database file. -** -** If the pager has already entered the ERROR state, do not attempt -** the rollback at this time. Instead, pager_unlock() is called. The -** call to pager_unlock() will discard all in-memory pages, unlock -** the database file and move the pager back to OPEN state. If this -** means that there is a hot-journal left in the file-system, the next -** connection to obtain a shared lock on the pager (which may be this one) -** will roll it back. -** -** If the pager has not already entered the ERROR state, but an IO or -** malloc error occurs during a rollback, then this will itself cause -** the pager to enter the ERROR state. Which will be cleared by the -** call to pager_unlock(), as described above. -*/ -static void pagerUnlockAndRollback(Pager *pPager){ - if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){ - assert( assert_pager_state(pPager) ); - if( pPager->eState>=PAGER_WRITER_LOCKED ){ - sqlite3BeginBenignMalloc(); - sqlite3PagerRollback(pPager); - sqlite3EndBenignMalloc(); - }else if( !pPager->exclusiveMode ){ - assert( pPager->eState==PAGER_READER ); - pager_end_transaction(pPager, 0, 0); - } - } - pager_unlock(pPager); -} - -/* -** Parameter aData must point to a buffer of pPager->pageSize bytes -** of data. Compute and return a checksum based ont the contents of the -** page of data and the current value of pPager->cksumInit. -** -** This is not a real checksum. It is really just the sum of the -** random initial value (pPager->cksumInit) and every 200th byte -** of the page data, starting with byte offset (pPager->pageSize%200). -** Each byte is interpreted as an 8-bit unsigned integer. -** -** Changing the formula used to compute this checksum results in an -** incompatible journal file format. -** -** If journal corruption occurs due to a power failure, the most likely -** scenario is that one end or the other of the record will be changed. -** It is much less likely that the two ends of the journal record will be -** correct and the middle be corrupt. Thus, this "checksum" scheme, -** though fast and simple, catches the mostly likely kind of corruption. -*/ -static u32 pager_cksum(Pager *pPager, const u8 *aData){ - u32 cksum = pPager->cksumInit; /* Checksum value to return */ - int i = pPager->pageSize-200; /* Loop counter */ - while( i>0 ){ - cksum += aData[i]; - i -= 200; - } - return cksum; -} - -/* -** Report the current page size and number of reserved bytes back -** to the codec. -*/ -#ifdef SQLITE_HAS_CODEC -static void pagerReportSize(Pager *pPager){ - if( pPager->xCodecSizeChng ){ - pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize, - (int)pPager->nReserve); - } -} -#else -# define pagerReportSize(X) /* No-op if we do not support a codec */ -#endif - -/* -** Read a single page from either the journal file (if isMainJrnl==1) or -** from the sub-journal (if isMainJrnl==0) and playback that page. -** The page begins at offset *pOffset into the file. The *pOffset -** value is increased to the start of the next page in the journal. -** -** The main rollback journal uses checksums - the statement journal does -** not. -** -** If the page number of the page record read from the (sub-)journal file -** is greater than the current value of Pager.dbSize, then playback is -** skipped and SQLITE_OK is returned. -** -** If pDone is not NULL, then it is a record of pages that have already -** been played back. If the page at *pOffset has already been played back -** (if the corresponding pDone bit is set) then skip the playback. -** Make sure the pDone bit corresponding to the *pOffset page is set -** prior to returning. -** -** If the page record is successfully read from the (sub-)journal file -** and played back, then SQLITE_OK is returned. If an IO error occurs -** while reading the record from the (sub-)journal file or while writing -** to the database file, then the IO error code is returned. If data -** is successfully read from the (sub-)journal file but appears to be -** corrupted, SQLITE_DONE is returned. Data is considered corrupted in -** two circumstances: -** -** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or -** * If the record is being rolled back from the main journal file -** and the checksum field does not match the record content. -** -** Neither of these two scenarios are possible during a savepoint rollback. -** -** If this is a savepoint rollback, then memory may have to be dynamically -** allocated by this function. If this is the case and an allocation fails, -** SQLITE_NOMEM is returned. -*/ -static int pager_playback_one_page( - Pager *pPager, /* The pager being played back */ - i64 *pOffset, /* Offset of record to playback */ - Bitvec *pDone, /* Bitvec of pages already played back */ - int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */ - int isSavepnt /* True for a savepoint rollback */ -){ - int rc; - PgHdr *pPg; /* An existing page in the cache */ - Pgno pgno; /* The page number of a page in journal */ - u32 cksum; /* Checksum used for sanity checking */ - char *aData; /* Temporary storage for the page */ - sqlite3_file *jfd; /* The file descriptor for the journal file */ - int isSynced; /* True if journal page is synced */ - - assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */ - assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */ - assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */ - assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */ - - aData = pPager->pTmpSpace; - assert( aData ); /* Temp storage must have already been allocated */ - assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) ); - - /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction - ** or savepoint rollback done at the request of the caller) or this is - ** a hot-journal rollback. If it is a hot-journal rollback, the pager - ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback - ** only reads from the main journal, not the sub-journal. - */ - assert( pPager->eState>=PAGER_WRITER_CACHEMOD - || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK) - ); - assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl ); - - /* Read the page number and page data from the journal or sub-journal - ** file. Return an error code to the caller if an IO error occurs. - */ - jfd = isMainJrnl ? pPager->jfd : pPager->sjfd; - rc = read32bits(jfd, *pOffset, &pgno); - if( rc!=SQLITE_OK ) return rc; - rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4); - if( rc!=SQLITE_OK ) return rc; - *pOffset += pPager->pageSize + 4 + isMainJrnl*4; - - /* Sanity checking on the page. This is more important that I originally - ** thought. If a power failure occurs while the journal is being written, - ** it could cause invalid data to be written into the journal. We need to - ** detect this invalid data (with high probability) and ignore it. - */ - if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ - assert( !isSavepnt ); - return SQLITE_DONE; - } - if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){ - return SQLITE_OK; - } - if( isMainJrnl ){ - rc = read32bits(jfd, (*pOffset)-4, &cksum); - if( rc ) return rc; - if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){ - return SQLITE_DONE; - } - } - - /* If this page has already been played by before during the current - ** rollback, then don't bother to play it back again. - */ - if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){ - return rc; - } - - /* When playing back page 1, restore the nReserve setting - */ - if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){ - pPager->nReserve = ((u8*)aData)[20]; - pagerReportSize(pPager); - } - - /* If the pager is in CACHEMOD state, then there must be a copy of this - ** page in the pager cache. In this case just update the pager cache, - ** not the database file. The page is left marked dirty in this case. - ** - ** An exception to the above rule: If the database is in no-sync mode - ** and a page is moved during an incremental vacuum then the page may - ** not be in the pager cache. Later: if a malloc() or IO error occurs - ** during a Movepage() call, then the page may not be in the cache - ** either. So the condition described in the above paragraph is not - ** assert()able. - ** - ** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the - ** pager cache if it exists and the main file. The page is then marked - ** not dirty. Since this code is only executed in PAGER_OPEN state for - ** a hot-journal rollback, it is guaranteed that the page-cache is empty - ** if the pager is in OPEN state. - ** - ** Ticket #1171: The statement journal might contain page content that is - ** different from the page content at the start of the transaction. - ** This occurs when a page is changed prior to the start of a statement - ** then changed again within the statement. When rolling back such a - ** statement we must not write to the original database unless we know - ** for certain that original page contents are synced into the main rollback - ** journal. Otherwise, a power loss might leave modified data in the - ** database file without an entry in the rollback journal that can - ** restore the database to its original form. Two conditions must be - ** met before writing to the database files. (1) the database must be - ** locked. (2) we know that the original page content is fully synced - ** in the main journal either because the page is not in cache or else - ** the page is marked as needSync==0. - ** - ** 2008-04-14: When attempting to vacuum a corrupt database file, it - ** is possible to fail a statement on a database that does not yet exist. - ** Do not attempt to write if database file has never been opened. - */ - if( pagerUseWal(pPager) ){ - pPg = 0; - }else{ - pPg = pager_lookup(pPager, pgno); - } - assert( pPg || !MEMDB ); - assert( pPager->eState!=PAGER_OPEN || pPg==0 ); - PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n", - PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData), - (isMainJrnl?"main-journal":"sub-journal") - )); - if( isMainJrnl ){ - isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr); - }else{ - isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC)); - } - if( isOpen(pPager->fd) - && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) - && isSynced - ){ - i64 ofst = (pgno-1)*(i64)pPager->pageSize; - testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 ); - assert( !pagerUseWal(pPager) ); - rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst); - if( pgno>pPager->dbFileSize ){ - pPager->dbFileSize = pgno; - } - if( pPager->pBackup ){ - CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM); - sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); - CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData); - } - }else if( !isMainJrnl && pPg==0 ){ - /* If this is a rollback of a savepoint and data was not written to - ** the database and the page is not in-memory, there is a potential - ** problem. When the page is next fetched by the b-tree layer, it - ** will be read from the database file, which may or may not be - ** current. - ** - ** There are a couple of different ways this can happen. All are quite - ** obscure. When running in synchronous mode, this can only happen - ** if the page is on the free-list at the start of the transaction, then - ** populated, then moved using sqlite3PagerMovepage(). - ** - ** The solution is to add an in-memory page to the cache containing - ** the data just read from the sub-journal. Mark the page as dirty - ** and if the pager requires a journal-sync, then mark the page as - ** requiring a journal-sync before it is written. - */ - assert( isSavepnt ); - assert( pPager->doNotSpill==0 ); - pPager->doNotSpill++; - rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1); - assert( pPager->doNotSpill==1 ); - pPager->doNotSpill--; - if( rc!=SQLITE_OK ) return rc; - pPg->flags &= ~PGHDR_NEED_READ; - sqlite3PcacheMakeDirty(pPg); - } - if( pPg ){ - /* No page should ever be explicitly rolled back that is in use, except - ** for page 1 which is held in use in order to keep the lock on the - ** database active. However such a page may be rolled back as a result - ** of an internal error resulting in an automatic call to - ** sqlite3PagerRollback(). - */ - void *pData; - pData = pPg->pData; - memcpy(pData, (u8*)aData, pPager->pageSize); - pPager->xReiniter(pPg); - if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){ - /* If the contents of this page were just restored from the main - ** journal file, then its content must be as they were when the - ** transaction was first opened. In this case we can mark the page - ** as clean, since there will be no need to write it out to the - ** database. - ** - ** There is one exception to this rule. If the page is being rolled - ** back as part of a savepoint (or statement) rollback from an - ** unsynced portion of the main journal file, then it is not safe - ** to mark the page as clean. This is because marking the page as - ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is - ** already in the journal file (recorded in Pager.pInJournal) and - ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to - ** again within this transaction, it will be marked as dirty but - ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially - ** be written out into the database file before its journal file - ** segment is synced. If a crash occurs during or following this, - ** database corruption may ensue. - */ - assert( !pagerUseWal(pPager) ); - sqlite3PcacheMakeClean(pPg); - } - pager_set_pagehash(pPg); - - /* If this was page 1, then restore the value of Pager.dbFileVers. - ** Do this before any decoding. */ - if( pgno==1 ){ - memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); - } - - /* Decode the page just read from disk */ - CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM); - sqlite3PcacheRelease(pPg); - } - return rc; -} - -/* -** Parameter zMaster is the name of a master journal file. A single journal -** file that referred to the master journal file has just been rolled back. -** This routine checks if it is possible to delete the master journal file, -** and does so if it is. -** -** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not -** available for use within this function. -** -** When a master journal file is created, it is populated with the names -** of all of its child journals, one after another, formatted as utf-8 -** encoded text. The end of each child journal file is marked with a -** nul-terminator byte (0x00). i.e. the entire contents of a master journal -** file for a transaction involving two databases might be: -** -** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00" -** -** A master journal file may only be deleted once all of its child -** journals have been rolled back. -** -** This function reads the contents of the master-journal file into -** memory and loops through each of the child journal names. For -** each child journal, it checks if: -** -** * if the child journal exists, and if so -** * if the child journal contains a reference to master journal -** file zMaster -** -** If a child journal can be found that matches both of the criteria -** above, this function returns without doing anything. Otherwise, if -** no such child journal can be found, file zMaster is deleted from -** the file-system using sqlite3OsDelete(). -** -** If an IO error within this function, an error code is returned. This -** function allocates memory by calling sqlite3Malloc(). If an allocation -** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors -** occur, SQLITE_OK is returned. -** -** TODO: This function allocates a single block of memory to load -** the entire contents of the master journal file. This could be -** a couple of kilobytes or so - potentially larger than the page -** size. -*/ -static int pager_delmaster(Pager *pPager, const char *zMaster){ - sqlite3_vfs *pVfs = pPager->pVfs; - int rc; /* Return code */ - sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */ - sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */ - char *zMasterJournal = 0; /* Contents of master journal file */ - i64 nMasterJournal; /* Size of master journal file */ - char *zJournal; /* Pointer to one journal within MJ file */ - char *zMasterPtr; /* Space to hold MJ filename from a journal file */ - int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */ - - /* Allocate space for both the pJournal and pMaster file descriptors. - ** If successful, open the master journal file for reading. - */ - pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2); - pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); - if( !pMaster ){ - rc = SQLITE_NOMEM; - }else{ - const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL); - rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0); - } - if( rc!=SQLITE_OK ) goto delmaster_out; - - /* Load the entire master journal file into space obtained from - ** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain - ** sufficient space (in zMasterPtr) to hold the names of master - ** journal files extracted from regular rollback-journals. - */ - rc = sqlite3OsFileSize(pMaster, &nMasterJournal); - if( rc!=SQLITE_OK ) goto delmaster_out; - nMasterPtr = pVfs->mxPathname+1; - zMasterJournal = sqlite3Malloc((int)nMasterJournal + nMasterPtr + 1); - if( !zMasterJournal ){ - rc = SQLITE_NOMEM; - goto delmaster_out; - } - zMasterPtr = &zMasterJournal[nMasterJournal+1]; - rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0); - if( rc!=SQLITE_OK ) goto delmaster_out; - zMasterJournal[nMasterJournal] = 0; - - zJournal = zMasterJournal; - while( (zJournal-zMasterJournal)pageSize bytes). -** If the file on disk is currently larger than nPage pages, then use the VFS -** xTruncate() method to truncate it. -** -** Or, it might might be the case that the file on disk is smaller than -** nPage pages. Some operating system implementations can get confused if -** you try to truncate a file to some size that is larger than it -** currently is, so detect this case and write a single zero byte to -** the end of the new file instead. -** -** If successful, return SQLITE_OK. If an IO error occurs while modifying -** the database file, return the error code to the caller. -*/ -static int pager_truncate(Pager *pPager, Pgno nPage){ - int rc = SQLITE_OK; - assert( pPager->eState!=PAGER_ERROR ); - assert( pPager->eState!=PAGER_READER ); - - if( isOpen(pPager->fd) - && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) - ){ - i64 currentSize, newSize; - int szPage = pPager->pageSize; - assert( pPager->eLock==EXCLUSIVE_LOCK ); - /* TODO: Is it safe to use Pager.dbFileSize here? */ - rc = sqlite3OsFileSize(pPager->fd, ¤tSize); - newSize = szPage*(i64)nPage; - if( rc==SQLITE_OK && currentSize!=newSize ){ - if( currentSize>newSize ){ - rc = sqlite3OsTruncate(pPager->fd, newSize); - }else if( (currentSize+szPage)<=newSize ){ - char *pTmp = pPager->pTmpSpace; - memset(pTmp, 0, szPage); - testcase( (newSize-szPage) == currentSize ); - testcase( (newSize-szPage) > currentSize ); - rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage); - } - if( rc==SQLITE_OK ){ - pPager->dbFileSize = nPage; - } - } - } - return rc; -} - -/* -** Return a sanitized version of the sector-size of OS file pFile. The -** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE. -*/ -SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){ - int iRet = sqlite3OsSectorSize(pFile); - if( iRet<32 ){ - iRet = 512; - }else if( iRet>MAX_SECTOR_SIZE ){ - assert( MAX_SECTOR_SIZE>=512 ); - iRet = MAX_SECTOR_SIZE; - } - return iRet; -} - -/* -** Set the value of the Pager.sectorSize variable for the given -** pager based on the value returned by the xSectorSize method -** of the open database file. The sector size will be used used -** to determine the size and alignment of journal header and -** master journal pointers within created journal files. -** -** For temporary files the effective sector size is always 512 bytes. -** -** Otherwise, for non-temporary files, the effective sector size is -** the value returned by the xSectorSize() method rounded up to 32 if -** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it -** is greater than MAX_SECTOR_SIZE. -** -** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set -** the effective sector size to its minimum value (512). The purpose of -** pPager->sectorSize is to define the "blast radius" of bytes that -** might change if a crash occurs while writing to a single byte in -** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero -** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector -** size. For backwards compatibility of the rollback journal file format, -** we cannot reduce the effective sector size below 512. -*/ -static void setSectorSize(Pager *pPager){ - assert( isOpen(pPager->fd) || pPager->tempFile ); - - if( pPager->tempFile - || (sqlite3OsDeviceCharacteristics(pPager->fd) & - SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0 - ){ - /* Sector size doesn't matter for temporary files. Also, the file - ** may not have been opened yet, in which case the OsSectorSize() - ** call will segfault. */ - pPager->sectorSize = 512; - }else{ - pPager->sectorSize = sqlite3SectorSize(pPager->fd); - } -} - -/* -** Playback the journal and thus restore the database file to -** the state it was in before we started making changes. -** -** The journal file format is as follows: -** -** (1) 8 byte prefix. A copy of aJournalMagic[]. -** (2) 4 byte big-endian integer which is the number of valid page records -** in the journal. If this value is 0xffffffff, then compute the -** number of page records from the journal size. -** (3) 4 byte big-endian integer which is the initial value for the -** sanity checksum. -** (4) 4 byte integer which is the number of pages to truncate the -** database to during a rollback. -** (5) 4 byte big-endian integer which is the sector size. The header -** is this many bytes in size. -** (6) 4 byte big-endian integer which is the page size. -** (7) zero padding out to the next sector size. -** (8) Zero or more pages instances, each as follows: -** + 4 byte page number. -** + pPager->pageSize bytes of data. -** + 4 byte checksum -** -** When we speak of the journal header, we mean the first 7 items above. -** Each entry in the journal is an instance of the 8th item. -** -** Call the value from the second bullet "nRec". nRec is the number of -** valid page entries in the journal. In most cases, you can compute the -** value of nRec from the size of the journal file. But if a power -** failure occurred while the journal was being written, it could be the -** case that the size of the journal file had already been increased but -** the extra entries had not yet made it safely to disk. In such a case, -** the value of nRec computed from the file size would be too large. For -** that reason, we always use the nRec value in the header. -** -** If the nRec value is 0xffffffff it means that nRec should be computed -** from the file size. This value is used when the user selects the -** no-sync option for the journal. A power failure could lead to corruption -** in this case. But for things like temporary table (which will be -** deleted when the power is restored) we don't care. -** -** If the file opened as the journal file is not a well-formed -** journal file then all pages up to the first corrupted page are rolled -** back (or no pages if the journal header is corrupted). The journal file -** is then deleted and SQLITE_OK returned, just as if no corruption had -** been encountered. -** -** If an I/O or malloc() error occurs, the journal-file is not deleted -** and an error code is returned. -** -** The isHot parameter indicates that we are trying to rollback a journal -** that might be a hot journal. Or, it could be that the journal is -** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE. -** If the journal really is hot, reset the pager cache prior rolling -** back any content. If the journal is merely persistent, no reset is -** needed. -*/ -static int pager_playback(Pager *pPager, int isHot){ - sqlite3_vfs *pVfs = pPager->pVfs; - i64 szJ; /* Size of the journal file in bytes */ - u32 nRec; /* Number of Records in the journal */ - u32 u; /* Unsigned loop counter */ - Pgno mxPg = 0; /* Size of the original file in pages */ - int rc; /* Result code of a subroutine */ - int res = 1; /* Value returned by sqlite3OsAccess() */ - char *zMaster = 0; /* Name of master journal file if any */ - int needPagerReset; /* True to reset page prior to first page rollback */ - int nPlayback = 0; /* Total number of pages restored from journal */ - - /* Figure out how many records are in the journal. Abort early if - ** the journal is empty. - */ - assert( isOpen(pPager->jfd) ); - rc = sqlite3OsFileSize(pPager->jfd, &szJ); - if( rc!=SQLITE_OK ){ - goto end_playback; - } - - /* Read the master journal name from the journal, if it is present. - ** If a master journal file name is specified, but the file is not - ** present on disk, then the journal is not hot and does not need to be - ** played back. - ** - ** TODO: Technically the following is an error because it assumes that - ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that - ** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c, - ** mxPathname is 512, which is the same as the minimum allowable value - ** for pageSize. - */ - zMaster = pPager->pTmpSpace; - rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); - if( rc==SQLITE_OK && zMaster[0] ){ - rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); - } - zMaster = 0; - if( rc!=SQLITE_OK || !res ){ - goto end_playback; - } - pPager->journalOff = 0; - needPagerReset = isHot; - - /* This loop terminates either when a readJournalHdr() or - ** pager_playback_one_page() call returns SQLITE_DONE or an IO error - ** occurs. - */ - while( 1 ){ - /* Read the next journal header from the journal file. If there are - ** not enough bytes left in the journal file for a complete header, or - ** it is corrupted, then a process must have failed while writing it. - ** This indicates nothing more needs to be rolled back. - */ - rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - } - goto end_playback; - } - - /* If nRec is 0xffffffff, then this journal was created by a process - ** working in no-sync mode. This means that the rest of the journal - ** file consists of pages, there are no more journal headers. Compute - ** the value of nRec based on this assumption. - */ - if( nRec==0xffffffff ){ - assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ); - nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager)); - } - - /* If nRec is 0 and this rollback is of a transaction created by this - ** process and if this is the final header in the journal, then it means - ** that this part of the journal was being filled but has not yet been - ** synced to disk. Compute the number of pages based on the remaining - ** size of the file. - ** - ** The third term of the test was added to fix ticket #2565. - ** When rolling back a hot journal, nRec==0 always means that the next - ** chunk of the journal contains zero pages to be rolled back. But - ** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in - ** the journal, it means that the journal might contain additional - ** pages that need to be rolled back and that the number of pages - ** should be computed based on the journal file size. - */ - if( nRec==0 && !isHot && - pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ - nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager)); - } - - /* If this is the first header read from the journal, truncate the - ** database file back to its original size. - */ - if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ - rc = pager_truncate(pPager, mxPg); - if( rc!=SQLITE_OK ){ - goto end_playback; - } - pPager->dbSize = mxPg; - } - - /* Copy original pages out of the journal and back into the - ** database file and/or page cache. - */ - for(u=0; ujournalOff,0,1,0); - if( rc==SQLITE_OK ){ - nPlayback++; - }else{ - if( rc==SQLITE_DONE ){ - pPager->journalOff = szJ; - break; - }else if( rc==SQLITE_IOERR_SHORT_READ ){ - /* If the journal has been truncated, simply stop reading and - ** processing the journal. This might happen if the journal was - ** not completely written and synced prior to a crash. In that - ** case, the database should have never been written in the - ** first place so it is OK to simply abandon the rollback. */ - rc = SQLITE_OK; - goto end_playback; - }else{ - /* If we are unable to rollback, quit and return the error - ** code. This will cause the pager to enter the error state - ** so that no further harm will be done. Perhaps the next - ** process to come along will be able to rollback the database. - */ - goto end_playback; - } - } - } - } - /*NOTREACHED*/ - assert( 0 ); - -end_playback: - /* Following a rollback, the database file should be back in its original - ** state prior to the start of the transaction, so invoke the - ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the - ** assertion that the transaction counter was modified. - */ -#ifdef SQLITE_DEBUG - if( pPager->fd->pMethods ){ - sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); - } -#endif - - /* If this playback is happening automatically as a result of an IO or - ** malloc error that occurred after the change-counter was updated but - ** before the transaction was committed, then the change-counter - ** modification may just have been reverted. If this happens in exclusive - ** mode, then subsequent transactions performed by the connection will not - ** update the change-counter at all. This may lead to cache inconsistency - ** problems for other processes at some point in the future. So, just - ** in case this has happened, clear the changeCountDone flag now. - */ - pPager->changeCountDone = pPager->tempFile; - - if( rc==SQLITE_OK ){ - zMaster = pPager->pTmpSpace; - rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); - testcase( rc!=SQLITE_OK ); - } - if( rc==SQLITE_OK - && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) - ){ - rc = sqlite3PagerSync(pPager); - } - if( rc==SQLITE_OK ){ - rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0); - testcase( rc!=SQLITE_OK ); - } - if( rc==SQLITE_OK && zMaster[0] && res ){ - /* If there was a master journal and this routine will return success, - ** see if it is possible to delete the master journal. - */ - rc = pager_delmaster(pPager, zMaster); - testcase( rc!=SQLITE_OK ); - } - if( isHot && nPlayback ){ - sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s", - nPlayback, pPager->zJournal); - } - - /* The Pager.sectorSize variable may have been updated while rolling - ** back a journal created by a process with a different sector size - ** value. Reset it to the correct value for this process. - */ - setSectorSize(pPager); - return rc; -} - - -/* -** Read the content for page pPg out of the database file and into -** pPg->pData. A shared lock or greater must be held on the database -** file before this function is called. -** -** If page 1 is read, then the value of Pager.dbFileVers[] is set to -** the value read from the database file. -** -** If an IO error occurs, then the IO error is returned to the caller. -** Otherwise, SQLITE_OK is returned. -*/ -static int readDbPage(PgHdr *pPg, u32 iFrame){ - Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */ - Pgno pgno = pPg->pgno; /* Page number to read */ - int rc = SQLITE_OK; /* Return code */ - int pgsz = pPager->pageSize; /* Number of bytes to read */ - - assert( pPager->eState>=PAGER_READER && !MEMDB ); - assert( isOpen(pPager->fd) ); - - if( NEVER(!isOpen(pPager->fd)) ){ - assert( pPager->tempFile ); - memset(pPg->pData, 0, pPager->pageSize); - return SQLITE_OK; - } - -#ifndef SQLITE_OMIT_WAL - if( iFrame ){ - /* Try to pull the page from the write-ahead log. */ - rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData); - }else -#endif - { - i64 iOffset = (pgno-1)*(i64)pPager->pageSize; - rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset); - if( rc==SQLITE_IOERR_SHORT_READ ){ - rc = SQLITE_OK; - } - } - - if( pgno==1 ){ - if( rc ){ - /* If the read is unsuccessful, set the dbFileVers[] to something - ** that will never be a valid file version. dbFileVers[] is a copy - ** of bytes 24..39 of the database. Bytes 28..31 should always be - ** zero or the size of the database in page. Bytes 32..35 and 35..39 - ** should be page numbers which are never 0xffffffff. So filling - ** pPager->dbFileVers[] with all 0xff bytes should suffice. - ** - ** For an encrypted database, the situation is more complex: bytes - ** 24..39 of the database are white noise. But the probability of - ** white noising equaling 16 bytes of 0xff is vanishingly small so - ** we should still be ok. - */ - memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers)); - }else{ - u8 *dbFileVers = &((u8*)pPg->pData)[24]; - memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers)); - } - } - CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM); - - PAGER_INCR(sqlite3_pager_readdb_count); - PAGER_INCR(pPager->nRead); - IOTRACE(("PGIN %p %d\n", pPager, pgno)); - PAGERTRACE(("FETCH %d page %d hash(%08x)\n", - PAGERID(pPager), pgno, pager_pagehash(pPg))); - - return rc; -} - -/* -** Update the value of the change-counter at offsets 24 and 92 in -** the header and the sqlite version number at offset 96. -** -** This is an unconditional update. See also the pager_incr_changecounter() -** routine which only updates the change-counter if the update is actually -** needed, as determined by the pPager->changeCountDone state variable. -*/ -static void pager_write_changecounter(PgHdr *pPg){ - u32 change_counter; - - /* Increment the value just read and write it back to byte 24. */ - change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1; - put32bits(((char*)pPg->pData)+24, change_counter); - - /* Also store the SQLite version number in bytes 96..99 and in - ** bytes 92..95 store the change counter for which the version number - ** is valid. */ - put32bits(((char*)pPg->pData)+92, change_counter); - put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER); -} - -#ifndef SQLITE_OMIT_WAL -/* -** This function is invoked once for each page that has already been -** written into the log file when a WAL transaction is rolled back. -** Parameter iPg is the page number of said page. The pCtx argument -** is actually a pointer to the Pager structure. -** -** If page iPg is present in the cache, and has no outstanding references, -** it is discarded. Otherwise, if there are one or more outstanding -** references, the page content is reloaded from the database. If the -** attempt to reload content from the database is required and fails, -** return an SQLite error code. Otherwise, SQLITE_OK. -*/ -static int pagerUndoCallback(void *pCtx, Pgno iPg){ - int rc = SQLITE_OK; - Pager *pPager = (Pager *)pCtx; - PgHdr *pPg; - - assert( pagerUseWal(pPager) ); - pPg = sqlite3PagerLookup(pPager, iPg); - if( pPg ){ - if( sqlite3PcachePageRefcount(pPg)==1 ){ - sqlite3PcacheDrop(pPg); - }else{ - u32 iFrame = 0; - rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); - if( rc==SQLITE_OK ){ - rc = readDbPage(pPg, iFrame); - } - if( rc==SQLITE_OK ){ - pPager->xReiniter(pPg); - } - sqlite3PagerUnref(pPg); - } - } - - /* Normally, if a transaction is rolled back, any backup processes are - ** updated as data is copied out of the rollback journal and into the - ** database. This is not generally possible with a WAL database, as - ** rollback involves simply truncating the log file. Therefore, if one - ** or more frames have already been written to the log (and therefore - ** also copied into the backup databases) as part of this transaction, - ** the backups must be restarted. - */ - sqlite3BackupRestart(pPager->pBackup); - - return rc; -} - -/* -** This function is called to rollback a transaction on a WAL database. -*/ -static int pagerRollbackWal(Pager *pPager){ - int rc; /* Return Code */ - PgHdr *pList; /* List of dirty pages to revert */ - - /* For all pages in the cache that are currently dirty or have already - ** been written (but not committed) to the log file, do one of the - ** following: - ** - ** + Discard the cached page (if refcount==0), or - ** + Reload page content from the database (if refcount>0). - */ - pPager->dbSize = pPager->dbOrigSize; - rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager); - pList = sqlite3PcacheDirtyList(pPager->pPCache); - while( pList && rc==SQLITE_OK ){ - PgHdr *pNext = pList->pDirty; - rc = pagerUndoCallback((void *)pPager, pList->pgno); - pList = pNext; - } - - return rc; -} - -/* -** This function is a wrapper around sqlite3WalFrames(). As well as logging -** the contents of the list of pages headed by pList (connected by pDirty), -** this function notifies any active backup processes that the pages have -** changed. -** -** The list of pages passed into this routine is always sorted by page number. -** Hence, if page 1 appears anywhere on the list, it will be the first page. -*/ -static int pagerWalFrames( - Pager *pPager, /* Pager object */ - PgHdr *pList, /* List of frames to log */ - Pgno nTruncate, /* Database size after this commit */ - int isCommit /* True if this is a commit */ -){ - int rc; /* Return code */ - int nList; /* Number of pages in pList */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES) - PgHdr *p; /* For looping over pages */ -#endif - - assert( pPager->pWal ); - assert( pList ); -#ifdef SQLITE_DEBUG - /* Verify that the page list is in accending order */ - for(p=pList; p && p->pDirty; p=p->pDirty){ - assert( p->pgno < p->pDirty->pgno ); - } -#endif - - assert( pList->pDirty==0 || isCommit ); - if( isCommit ){ - /* If a WAL transaction is being committed, there is no point in writing - ** any pages with page numbers greater than nTruncate into the WAL file. - ** They will never be read by any client. So remove them from the pDirty - ** list here. */ - PgHdr *p; - PgHdr **ppNext = &pList; - nList = 0; - for(p=pList; (*ppNext = p)!=0; p=p->pDirty){ - if( p->pgno<=nTruncate ){ - ppNext = &p->pDirty; - nList++; - } - } - assert( pList ); - }else{ - nList = 1; - } - pPager->aStat[PAGER_STAT_WRITE] += nList; - - if( pList->pgno==1 ) pager_write_changecounter(pList); - rc = sqlite3WalFrames(pPager->pWal, - pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags - ); - if( rc==SQLITE_OK && pPager->pBackup ){ - PgHdr *p; - for(p=pList; p; p=p->pDirty){ - sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); - } - } - -#ifdef SQLITE_CHECK_PAGES - pList = sqlite3PcacheDirtyList(pPager->pPCache); - for(p=pList; p; p=p->pDirty){ - pager_set_pagehash(p); - } -#endif - - return rc; -} - -/* -** Begin a read transaction on the WAL. -** -** This routine used to be called "pagerOpenSnapshot()" because it essentially -** makes a snapshot of the database at the current point in time and preserves -** that snapshot for use by the reader in spite of concurrently changes by -** other writers or checkpointers. -*/ -static int pagerBeginReadTransaction(Pager *pPager){ - int rc; /* Return code */ - int changed = 0; /* True if cache must be reset */ - - assert( pagerUseWal(pPager) ); - assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); - - /* sqlite3WalEndReadTransaction() was not called for the previous - ** transaction in locking_mode=EXCLUSIVE. So call it now. If we - ** are in locking_mode=NORMAL and EndRead() was previously called, - ** the duplicate call is harmless. - */ - sqlite3WalEndReadTransaction(pPager->pWal); - - rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed); - if( rc!=SQLITE_OK || changed ){ - pager_reset(pPager); - if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); - } - - return rc; -} -#endif - -/* -** This function is called as part of the transition from PAGER_OPEN -** to PAGER_READER state to determine the size of the database file -** in pages (assuming the page size currently stored in Pager.pageSize). -** -** If no error occurs, SQLITE_OK is returned and the size of the database -** in pages is stored in *pnPage. Otherwise, an error code (perhaps -** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified. -*/ -static int pagerPagecount(Pager *pPager, Pgno *pnPage){ - Pgno nPage; /* Value to return via *pnPage */ - - /* Query the WAL sub-system for the database size. The WalDbsize() - ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or - ** if the database size is not available. The database size is not - ** available from the WAL sub-system if the log file is empty or - ** contains no valid committed transactions. - */ - assert( pPager->eState==PAGER_OPEN ); - assert( pPager->eLock>=SHARED_LOCK ); - nPage = sqlite3WalDbsize(pPager->pWal); - - /* If the database size was not available from the WAL sub-system, - ** determine it based on the size of the database file. If the size - ** of the database file is not an integer multiple of the page-size, - ** round down to the nearest page. Except, any file larger than 0 - ** bytes in size is considered to contain at least one page. - */ - if( nPage==0 ){ - i64 n = 0; /* Size of db file in bytes */ - assert( isOpen(pPager->fd) || pPager->tempFile ); - if( isOpen(pPager->fd) ){ - int rc = sqlite3OsFileSize(pPager->fd, &n); - if( rc!=SQLITE_OK ){ - return rc; - } - } - nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize); - } - - /* If the current number of pages in the file is greater than the - ** configured maximum pager number, increase the allowed limit so - ** that the file can be read. - */ - if( nPage>pPager->mxPgno ){ - pPager->mxPgno = (Pgno)nPage; - } - - *pnPage = nPage; - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_WAL -/* -** Check if the *-wal file that corresponds to the database opened by pPager -** exists if the database is not empy, or verify that the *-wal file does -** not exist (by deleting it) if the database file is empty. -** -** If the database is not empty and the *-wal file exists, open the pager -** in WAL mode. If the database is empty or if no *-wal file exists and -** if no error occurs, make sure Pager.journalMode is not set to -** PAGER_JOURNALMODE_WAL. -** -** Return SQLITE_OK or an error code. -** -** The caller must hold a SHARED lock on the database file to call this -** function. Because an EXCLUSIVE lock on the db file is required to delete -** a WAL on a none-empty database, this ensures there is no race condition -** between the xAccess() below and an xDelete() being executed by some -** other connection. -*/ -static int pagerOpenWalIfPresent(Pager *pPager){ - int rc = SQLITE_OK; - assert( pPager->eState==PAGER_OPEN ); - assert( pPager->eLock>=SHARED_LOCK ); - - if( !pPager->tempFile ){ - int isWal; /* True if WAL file exists */ - Pgno nPage; /* Size of the database file */ - - rc = pagerPagecount(pPager, &nPage); - if( rc ) return rc; - if( nPage==0 ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); - if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK; - isWal = 0; - }else{ - rc = sqlite3OsAccess( - pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal - ); - } - if( rc==SQLITE_OK ){ - if( isWal ){ - testcase( sqlite3PcachePagecount(pPager->pPCache)==0 ); - rc = sqlite3PagerOpenWal(pPager, 0); - }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){ - pPager->journalMode = PAGER_JOURNALMODE_DELETE; - } - } - } - return rc; -} -#endif - -/* -** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback -** the entire master journal file. The case pSavepoint==NULL occurs when -** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction -** savepoint. -** -** When pSavepoint is not NULL (meaning a non-transaction savepoint is -** being rolled back), then the rollback consists of up to three stages, -** performed in the order specified: -** -** * Pages are played back from the main journal starting at byte -** offset PagerSavepoint.iOffset and continuing to -** PagerSavepoint.iHdrOffset, or to the end of the main journal -** file if PagerSavepoint.iHdrOffset is zero. -** -** * If PagerSavepoint.iHdrOffset is not zero, then pages are played -** back starting from the journal header immediately following -** PagerSavepoint.iHdrOffset to the end of the main journal file. -** -** * Pages are then played back from the sub-journal file, starting -** with the PagerSavepoint.iSubRec and continuing to the end of -** the journal file. -** -** Throughout the rollback process, each time a page is rolled back, the -** corresponding bit is set in a bitvec structure (variable pDone in the -** implementation below). This is used to ensure that a page is only -** rolled back the first time it is encountered in either journal. -** -** If pSavepoint is NULL, then pages are only played back from the main -** journal file. There is no need for a bitvec in this case. -** -** In either case, before playback commences the Pager.dbSize variable -** is reset to the value that it held at the start of the savepoint -** (or transaction). No page with a page-number greater than this value -** is played back. If one is encountered it is simply skipped. -*/ -static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ - i64 szJ; /* Effective size of the main journal */ - i64 iHdrOff; /* End of first segment of main-journal records */ - int rc = SQLITE_OK; /* Return code */ - Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */ - - assert( pPager->eState!=PAGER_ERROR ); - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - - /* Allocate a bitvec to use to store the set of pages rolled back */ - if( pSavepoint ){ - pDone = sqlite3BitvecCreate(pSavepoint->nOrig); - if( !pDone ){ - return SQLITE_NOMEM; - } - } - - /* Set the database size back to the value it was before the savepoint - ** being reverted was opened. - */ - pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize; - pPager->changeCountDone = pPager->tempFile; - - if( !pSavepoint && pagerUseWal(pPager) ){ - return pagerRollbackWal(pPager); - } - - /* Use pPager->journalOff as the effective size of the main rollback - ** journal. The actual file might be larger than this in - ** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything - ** past pPager->journalOff is off-limits to us. - */ - szJ = pPager->journalOff; - assert( pagerUseWal(pPager)==0 || szJ==0 ); - - /* Begin by rolling back records from the main journal starting at - ** PagerSavepoint.iOffset and continuing to the next journal header. - ** There might be records in the main journal that have a page number - ** greater than the current database size (pPager->dbSize) but those - ** will be skipped automatically. Pages are added to pDone as they - ** are played back. - */ - if( pSavepoint && !pagerUseWal(pPager) ){ - iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ; - pPager->journalOff = pSavepoint->iOffset; - while( rc==SQLITE_OK && pPager->journalOffjournalOff, pDone, 1, 1); - } - assert( rc!=SQLITE_DONE ); - }else{ - pPager->journalOff = 0; - } - - /* Continue rolling back records out of the main journal starting at - ** the first journal header seen and continuing until the effective end - ** of the main journal file. Continue to skip out-of-range pages and - ** continue adding pages rolled back to pDone. - */ - while( rc==SQLITE_OK && pPager->journalOffjournalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff" - ** test is related to ticket #2565. See the discussion in the - ** pager_playback() function for additional information. - */ - if( nJRec==0 - && pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff - ){ - nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager)); - } - for(ii=0; rc==SQLITE_OK && iijournalOffjournalOff, pDone, 1, 1); - } - assert( rc!=SQLITE_DONE ); - } - assert( rc!=SQLITE_OK || pPager->journalOff>=szJ ); - - /* Finally, rollback pages from the sub-journal. Page that were - ** previously rolled back out of the main journal (and are hence in pDone) - ** will be skipped. Out-of-range pages are also skipped. - */ - if( pSavepoint ){ - u32 ii; /* Loop counter */ - i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize); - - if( pagerUseWal(pPager) ){ - rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData); - } - for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && iinSubRec; ii++){ - assert( offset==(i64)ii*(4+pPager->pageSize) ); - rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1); - } - assert( rc!=SQLITE_DONE ); - } - - sqlite3BitvecDestroy(pDone); - if( rc==SQLITE_OK ){ - pPager->journalOff = szJ; - } - - return rc; -} - -/* -** Change the maximum number of in-memory pages that are allowed. -*/ -SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ - sqlite3PcacheSetCachesize(pPager->pPCache, mxPage); -} - -/* -** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap. -*/ -static void pagerFixMaplimit(Pager *pPager){ -#if SQLITE_MAX_MMAP_SIZE>0 - sqlite3_file *fd = pPager->fd; - if( isOpen(fd) ){ - sqlite3_int64 sz; - pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0; - sz = pPager->szMmap; - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz); - } -#endif -} - -/* -** Change the maximum size of any memory mapping made of the database file. -*/ -SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){ - pPager->szMmap = szMmap; - pagerFixMaplimit(pPager); -} - -/* -** Free as much memory as possible from the pager. -*/ -SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){ - sqlite3PcacheShrink(pPager->pPCache); -} - -/* -** Adjust the robustness of the database to damage due to OS crashes -** or power failures by changing the number of syncs()s when writing -** the rollback journal. There are three levels: -** -** OFF sqlite3OsSync() is never called. This is the default -** for temporary and transient files. -** -** NORMAL The journal is synced once before writes begin on the -** database. This is normally adequate protection, but -** it is theoretically possible, though very unlikely, -** that an inopertune power failure could leave the journal -** in a state which would cause damage to the database -** when it is rolled back. -** -** FULL The journal is synced twice before writes begin on the -** database (with some additional information - the nRec field -** of the journal header - being written in between the two -** syncs). If we assume that writing a -** single disk sector is atomic, then this mode provides -** assurance that the journal will not be corrupted to the -** point of causing damage to the database during rollback. -** -** The above is for a rollback-journal mode. For WAL mode, OFF continues -** to mean that no syncs ever occur. NORMAL means that the WAL is synced -** prior to the start of checkpoint and that the database file is synced -** at the conclusion of the checkpoint if the entire content of the WAL -** was written back into the database. But no sync operations occur for -** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL -** file is synced following each commit operation, in addition to the -** syncs associated with NORMAL. -** -** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The -** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync -** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an -** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL -** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the -** synchronous=FULL versus synchronous=NORMAL setting determines when -** the xSync primitive is called and is relevant to all platforms. -** -** Numeric values associated with these states are OFF==1, NORMAL=2, -** and FULL=3. -*/ -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel( - Pager *pPager, /* The pager to set safety level for */ - int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */ - int bFullFsync, /* PRAGMA fullfsync */ - int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */ -){ - assert( level>=1 && level<=3 ); - pPager->noSync = (level==1 || pPager->tempFile) ?1:0; - pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0; - if( pPager->noSync ){ - pPager->syncFlags = 0; - pPager->ckptSyncFlags = 0; - }else if( bFullFsync ){ - pPager->syncFlags = SQLITE_SYNC_FULL; - pPager->ckptSyncFlags = SQLITE_SYNC_FULL; - }else if( bCkptFullFsync ){ - pPager->syncFlags = SQLITE_SYNC_NORMAL; - pPager->ckptSyncFlags = SQLITE_SYNC_FULL; - }else{ - pPager->syncFlags = SQLITE_SYNC_NORMAL; - pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; - } - pPager->walSyncFlags = pPager->syncFlags; - if( pPager->fullSync ){ - pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS; - } -} -#endif - -/* -** The following global variable is incremented whenever the library -** attempts to open a temporary file. This information is used for -** testing and analysis only. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_opentemp_count = 0; -#endif - -/* -** Open a temporary file. -** -** Write the file descriptor into *pFile. Return SQLITE_OK on success -** or some other error code if we fail. The OS will automatically -** delete the temporary file when it is closed. -** -** The flags passed to the VFS layer xOpen() call are those specified -** by parameter vfsFlags ORed with the following: -** -** SQLITE_OPEN_READWRITE -** SQLITE_OPEN_CREATE -** SQLITE_OPEN_EXCLUSIVE -** SQLITE_OPEN_DELETEONCLOSE -*/ -static int pagerOpentemp( - Pager *pPager, /* The pager object */ - sqlite3_file *pFile, /* Write the file descriptor here */ - int vfsFlags /* Flags passed through to the VFS */ -){ - int rc; /* Return code */ - -#ifdef SQLITE_TEST - sqlite3_opentemp_count++; /* Used for testing and analysis only */ -#endif - - vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; - rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0); - assert( rc!=SQLITE_OK || isOpen(pFile) ); - return rc; -} - -/* -** Set the busy handler function. -** -** The pager invokes the busy-handler if sqlite3OsLock() returns -** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock, -** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE -** lock. It does *not* invoke the busy handler when upgrading from -** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE -** (which occurs during hot-journal rollback). Summary: -** -** Transition | Invokes xBusyHandler -** -------------------------------------------------------- -** NO_LOCK -> SHARED_LOCK | Yes -** SHARED_LOCK -> RESERVED_LOCK | No -** SHARED_LOCK -> EXCLUSIVE_LOCK | No -** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes -** -** If the busy-handler callback returns non-zero, the lock is -** retried. If it returns zero, then the SQLITE_BUSY error is -** returned to the caller of the pager API function. -*/ -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler( - Pager *pPager, /* Pager object */ - int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ - void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ -){ - pPager->xBusyHandler = xBusyHandler; - pPager->pBusyHandlerArg = pBusyHandlerArg; - - if( isOpen(pPager->fd) ){ - void **ap = (void **)&pPager->xBusyHandler; - assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); - assert( ap[1]==pBusyHandlerArg ); - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); - } -} - -/* -** Change the page size used by the Pager object. The new page size -** is passed in *pPageSize. -** -** If the pager is in the error state when this function is called, it -** is a no-op. The value returned is the error state error code (i.e. -** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL). -** -** Otherwise, if all of the following are true: -** -** * the new page size (value of *pPageSize) is valid (a power -** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and -** -** * there are no outstanding page references, and -** -** * the database is either not an in-memory database or it is -** an in-memory database that currently consists of zero pages. -** -** then the pager object page size is set to *pPageSize. -** -** If the page size is changed, then this function uses sqlite3PagerMalloc() -** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt -** fails, SQLITE_NOMEM is returned and the page size remains unchanged. -** In all other cases, SQLITE_OK is returned. -** -** If the page size is not changed, either because one of the enumerated -** conditions above is not true, the pager was in error state when this -** function was called, or because the memory allocation attempt failed, -** then *pPageSize is set to the old, retained page size before returning. -*/ -SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){ - int rc = SQLITE_OK; - - /* It is not possible to do a full assert_pager_state() here, as this - ** function may be called from within PagerOpen(), before the state - ** of the Pager object is internally consistent. - ** - ** At one point this function returned an error if the pager was in - ** PAGER_ERROR state. But since PAGER_ERROR state guarantees that - ** there is at least one outstanding page reference, this function - ** is a no-op for that case anyhow. - */ - - u32 pageSize = *pPageSize; - assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); - if( (pPager->memDb==0 || pPager->dbSize==0) - && sqlite3PcacheRefCount(pPager->pPCache)==0 - && pageSize && pageSize!=(u32)pPager->pageSize - ){ - char *pNew = NULL; /* New temp space */ - i64 nByte = 0; - - if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){ - rc = sqlite3OsFileSize(pPager->fd, &nByte); - } - if( rc==SQLITE_OK ){ - pNew = (char *)sqlite3PageMalloc(pageSize); - if( !pNew ) rc = SQLITE_NOMEM; - } - - if( rc==SQLITE_OK ){ - pager_reset(pPager); - pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize); - pPager->pageSize = pageSize; - sqlite3PageFree(pPager->pTmpSpace); - pPager->pTmpSpace = pNew; - sqlite3PcacheSetPageSize(pPager->pPCache, pageSize); - } - } - - *pPageSize = pPager->pageSize; - if( rc==SQLITE_OK ){ - if( nReserve<0 ) nReserve = pPager->nReserve; - assert( nReserve>=0 && nReserve<1000 ); - pPager->nReserve = (i16)nReserve; - pagerReportSize(pPager); - pagerFixMaplimit(pPager); - } - return rc; -} - -/* -** Return a pointer to the "temporary page" buffer held internally -** by the pager. This is a buffer that is big enough to hold the -** entire content of a database page. This buffer is used internally -** during rollback and will be overwritten whenever a rollback -** occurs. But other modules are free to use it too, as long as -** no rollbacks are happening. -*/ -SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){ - return pPager->pTmpSpace; -} - -/* -** Attempt to set the maximum database page count if mxPage is positive. -** Make no changes if mxPage is zero or negative. And never reduce the -** maximum page count below the current size of the database. -** -** Regardless of mxPage, return the current maximum page count. -*/ -SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ - if( mxPage>0 ){ - pPager->mxPgno = mxPage; - } - assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */ - assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */ - return pPager->mxPgno; -} - -/* -** The following set of routines are used to disable the simulated -** I/O error mechanism. These routines are used to avoid simulated -** errors in places where we do not care about errors. -** -** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops -** and generate no code. -*/ -#ifdef SQLITE_TEST -SQLITE_API extern int sqlite3_io_error_pending; -SQLITE_API extern int sqlite3_io_error_hit; -static int saved_cnt; -void disable_simulated_io_errors(void){ - saved_cnt = sqlite3_io_error_pending; - sqlite3_io_error_pending = -1; -} -void enable_simulated_io_errors(void){ - sqlite3_io_error_pending = saved_cnt; -} -#else -# define disable_simulated_io_errors() -# define enable_simulated_io_errors() -#endif - -/* -** Read the first N bytes from the beginning of the file into memory -** that pDest points to. -** -** If the pager was opened on a transient file (zFilename==""), or -** opened on a file less than N bytes in size, the output buffer is -** zeroed and SQLITE_OK returned. The rationale for this is that this -** function is used to read database headers, and a new transient or -** zero sized database has a header than consists entirely of zeroes. -** -** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered, -** the error code is returned to the caller and the contents of the -** output buffer undefined. -*/ -SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ - int rc = SQLITE_OK; - memset(pDest, 0, N); - assert( isOpen(pPager->fd) || pPager->tempFile ); - - /* This routine is only called by btree immediately after creating - ** the Pager object. There has not been an opportunity to transition - ** to WAL mode yet. - */ - assert( !pagerUseWal(pPager) ); - - if( isOpen(pPager->fd) ){ - IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) - rc = sqlite3OsRead(pPager->fd, pDest, N, 0); - if( rc==SQLITE_IOERR_SHORT_READ ){ - rc = SQLITE_OK; - } - } - return rc; -} - -/* -** This function may only be called when a read-transaction is open on -** the pager. It returns the total number of pages in the database. -** -** However, if the file is between 1 and bytes in size, then -** this is considered a 1 page file. -*/ -SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){ - assert( pPager->eState>=PAGER_READER ); - assert( pPager->eState!=PAGER_WRITER_FINISHED ); - *pnPage = (int)pPager->dbSize; -} - - -/* -** Try to obtain a lock of type locktype on the database file. If -** a similar or greater lock is already held, this function is a no-op -** (returning SQLITE_OK immediately). -** -** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke -** the busy callback if the lock is currently not available. Repeat -** until the busy callback returns false or until the attempt to -** obtain the lock succeeds. -** -** Return SQLITE_OK on success and an error code if we cannot obtain -** the lock. If the lock is obtained successfully, set the Pager.state -** variable to locktype before returning. -*/ -static int pager_wait_on_lock(Pager *pPager, int locktype){ - int rc; /* Return code */ - - /* Check that this is either a no-op (because the requested lock is - ** already held, or one of the transistions that the busy-handler - ** may be invoked during, according to the comment above - ** sqlite3PagerSetBusyhandler(). - */ - assert( (pPager->eLock>=locktype) - || (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK) - || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK) - ); - - do { - rc = pagerLockDb(pPager, locktype); - }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) ); - return rc; -} - -/* -** Function assertTruncateConstraint(pPager) checks that one of the -** following is true for all dirty pages currently in the page-cache: -** -** a) The page number is less than or equal to the size of the -** current database image, in pages, OR -** -** b) if the page content were written at this time, it would not -** be necessary to write the current content out to the sub-journal -** (as determined by function subjRequiresPage()). -** -** If the condition asserted by this function were not true, and the -** dirty page were to be discarded from the cache via the pagerStress() -** routine, pagerStress() would not write the current page content to -** the database file. If a savepoint transaction were rolled back after -** this happened, the correct behavior would be to restore the current -** content of the page. However, since this content is not present in either -** the database file or the portion of the rollback journal and -** sub-journal rolled back the content could not be restored and the -** database image would become corrupt. It is therefore fortunate that -** this circumstance cannot arise. -*/ -#if defined(SQLITE_DEBUG) -static void assertTruncateConstraintCb(PgHdr *pPg){ - assert( pPg->flags&PGHDR_DIRTY ); - assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize ); -} -static void assertTruncateConstraint(Pager *pPager){ - sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb); -} -#else -# define assertTruncateConstraint(pPager) -#endif - -/* -** Truncate the in-memory database file image to nPage pages. This -** function does not actually modify the database file on disk. It -** just sets the internal state of the pager object so that the -** truncation will be done when the current transaction is committed. -** -** This function is only called right before committing a transaction. -** Once this function has been called, the transaction must either be -** rolled back or committed. It is not safe to call this function and -** then continue writing to the database. -*/ -SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ - assert( pPager->dbSize>=nPage ); - assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); - pPager->dbSize = nPage; - - /* At one point the code here called assertTruncateConstraint() to - ** ensure that all pages being truncated away by this operation are, - ** if one or more savepoints are open, present in the savepoint - ** journal so that they can be restored if the savepoint is rolled - ** back. This is no longer necessary as this function is now only - ** called right before committing a transaction. So although the - ** Pager object may still have open savepoints (Pager.nSavepoint!=0), - ** they cannot be rolled back. So the assertTruncateConstraint() call - ** is no longer correct. */ -} - - -/* -** This function is called before attempting a hot-journal rollback. It -** syncs the journal file to disk, then sets pPager->journalHdr to the -** size of the journal file so that the pager_playback() routine knows -** that the entire journal file has been synced. -** -** Syncing a hot-journal to disk before attempting to roll it back ensures -** that if a power-failure occurs during the rollback, the process that -** attempts rollback following system recovery sees the same journal -** content as this process. -** -** If everything goes as planned, SQLITE_OK is returned. Otherwise, -** an SQLite error code. -*/ -static int pagerSyncHotJournal(Pager *pPager){ - int rc = SQLITE_OK; - if( !pPager->noSync ){ - rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL); - } - if( rc==SQLITE_OK ){ - rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr); - } - return rc; -} - -/* -** Obtain a reference to a memory mapped page object for page number pgno. -** The new object will use the pointer pData, obtained from xFetch(). -** If successful, set *ppPage to point to the new page reference -** and return SQLITE_OK. Otherwise, return an SQLite error code and set -** *ppPage to zero. -** -** Page references obtained by calling this function should be released -** by calling pagerReleaseMapPage(). -*/ -static int pagerAcquireMapPage( - Pager *pPager, /* Pager object */ - Pgno pgno, /* Page number */ - void *pData, /* xFetch()'d data for this page */ - PgHdr **ppPage /* OUT: Acquired page object */ -){ - PgHdr *p; /* Memory mapped page to return */ - - if( pPager->pMmapFreelist ){ - *ppPage = p = pPager->pMmapFreelist; - pPager->pMmapFreelist = p->pDirty; - p->pDirty = 0; - memset(p->pExtra, 0, pPager->nExtra); - }else{ - *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra); - if( p==0 ){ - sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData); - return SQLITE_NOMEM; - } - p->pExtra = (void *)&p[1]; - p->flags = PGHDR_MMAP; - p->nRef = 1; - p->pPager = pPager; - } - - assert( p->pExtra==(void *)&p[1] ); - assert( p->pPage==0 ); - assert( p->flags==PGHDR_MMAP ); - assert( p->pPager==pPager ); - assert( p->nRef==1 ); - - p->pgno = pgno; - p->pData = pData; - pPager->nMmapOut++; - - return SQLITE_OK; -} - -/* -** Release a reference to page pPg. pPg must have been returned by an -** earlier call to pagerAcquireMapPage(). -*/ -static void pagerReleaseMapPage(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - pPager->nMmapOut--; - pPg->pDirty = pPager->pMmapFreelist; - pPager->pMmapFreelist = pPg; - - assert( pPager->fd->pMethods->iVersion>=3 ); - sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData); -} - -/* -** Free all PgHdr objects stored in the Pager.pMmapFreelist list. -*/ -static void pagerFreeMapHdrs(Pager *pPager){ - PgHdr *p; - PgHdr *pNext; - for(p=pPager->pMmapFreelist; p; p=pNext){ - pNext = p->pDirty; - sqlite3_free(p); - } -} - - -/* -** Shutdown the page cache. Free all memory and close all files. -** -** If a transaction was in progress when this routine is called, that -** transaction is rolled back. All outstanding pages are invalidated -** and their memory is freed. Any attempt to use a page associated -** with this page cache after this function returns will likely -** result in a coredump. -** -** This function always succeeds. If a transaction is active an attempt -** is made to roll it back. If an error occurs during the rollback -** a hot journal may be left in the filesystem but no error is returned -** to the caller. -*/ -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ - u8 *pTmp = (u8 *)pPager->pTmpSpace; - - assert( assert_pager_state(pPager) ); - disable_simulated_io_errors(); - sqlite3BeginBenignMalloc(); - pagerFreeMapHdrs(pPager); - /* pPager->errCode = 0; */ - pPager->exclusiveMode = 0; -#ifndef SQLITE_OMIT_WAL - sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); - pPager->pWal = 0; -#endif - pager_reset(pPager); - if( MEMDB ){ - pager_unlock(pPager); - }else{ - /* If it is open, sync the journal file before calling UnlockAndRollback. - ** If this is not done, then an unsynced portion of the open journal - ** file may be played back into the database. If a power failure occurs - ** while this is happening, the database could become corrupt. - ** - ** If an error occurs while trying to sync the journal, shift the pager - ** into the ERROR state. This causes UnlockAndRollback to unlock the - ** database and close the journal file without attempting to roll it - ** back or finalize it. The next database user will have to do hot-journal - ** rollback before accessing the database file. - */ - if( isOpen(pPager->jfd) ){ - pager_error(pPager, pagerSyncHotJournal(pPager)); - } - pagerUnlockAndRollback(pPager); - } - sqlite3EndBenignMalloc(); - enable_simulated_io_errors(); - PAGERTRACE(("CLOSE %d\n", PAGERID(pPager))); - IOTRACE(("CLOSE %p\n", pPager)) - sqlite3OsClose(pPager->jfd); - sqlite3OsClose(pPager->fd); - sqlite3PageFree(pTmp); - sqlite3PcacheClose(pPager->pPCache); - -#ifdef SQLITE_HAS_CODEC - if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); -#endif - - assert( !pPager->aSavepoint && !pPager->pInJournal ); - assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) ); - - sqlite3_free(pPager); - return SQLITE_OK; -} - -#if !defined(NDEBUG) || defined(SQLITE_TEST) -/* -** Return the page number for page pPg. -*/ -SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){ - return pPg->pgno; -} -#endif - -/* -** Increment the reference count for page pPg. -*/ -SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){ - sqlite3PcacheRef(pPg); -} - -/* -** Sync the journal. In other words, make sure all the pages that have -** been written to the journal have actually reached the surface of the -** disk and can be restored in the event of a hot-journal rollback. -** -** If the Pager.noSync flag is set, then this function is a no-op. -** Otherwise, the actions required depend on the journal-mode and the -** device characteristics of the file-system, as follows: -** -** * If the journal file is an in-memory journal file, no action need -** be taken. -** -** * Otherwise, if the device does not support the SAFE_APPEND property, -** then the nRec field of the most recently written journal header -** is updated to contain the number of journal records that have -** been written following it. If the pager is operating in full-sync -** mode, then the journal file is synced before this field is updated. -** -** * If the device does not support the SEQUENTIAL property, then -** journal file is synced. -** -** Or, in pseudo-code: -** -** if( NOT ){ -** if( NOT SAFE_APPEND ){ -** if( ) xSync(); -** -** } -** if( NOT SEQUENTIAL ) xSync(); -** } -** -** If successful, this routine clears the PGHDR_NEED_SYNC flag of every -** page currently held in memory before returning SQLITE_OK. If an IO -** error is encountered, then the IO error code is returned to the caller. -*/ -static int syncJournal(Pager *pPager, int newHdr){ - int rc; /* Return code */ - - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - ); - assert( assert_pager_state(pPager) ); - assert( !pagerUseWal(pPager) ); - - rc = sqlite3PagerExclusiveLock(pPager); - if( rc!=SQLITE_OK ) return rc; - - if( !pPager->noSync ){ - assert( !pPager->tempFile ); - if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ - const int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); - assert( isOpen(pPager->jfd) ); - - if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ - /* This block deals with an obscure problem. If the last connection - ** that wrote to this database was operating in persistent-journal - ** mode, then the journal file may at this point actually be larger - ** than Pager.journalOff bytes. If the next thing in the journal - ** file happens to be a journal-header (written as part of the - ** previous connection's transaction), and a crash or power-failure - ** occurs after nRec is updated but before this connection writes - ** anything else to the journal file (or commits/rolls back its - ** transaction), then SQLite may become confused when doing the - ** hot-journal rollback following recovery. It may roll back all - ** of this connections data, then proceed to rolling back the old, - ** out-of-date data that follows it. Database corruption. - ** - ** To work around this, if the journal file does appear to contain - ** a valid header following Pager.journalOff, then write a 0x00 - ** byte to the start of it to prevent it from being recognized. - ** - ** Variable iNextHdrOffset is set to the offset at which this - ** problematic header will occur, if it exists. aMagic is used - ** as a temporary buffer to inspect the first couple of bytes of - ** the potential journal header. - */ - i64 iNextHdrOffset; - u8 aMagic[8]; - u8 zHeader[sizeof(aJournalMagic)+4]; - - memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); - put32bits(&zHeader[sizeof(aJournalMagic)], pPager->nRec); - - iNextHdrOffset = journalHdrOffset(pPager); - rc = sqlite3OsRead(pPager->jfd, aMagic, 8, iNextHdrOffset); - if( rc==SQLITE_OK && 0==memcmp(aMagic, aJournalMagic, 8) ){ - static const u8 zerobyte = 0; - rc = sqlite3OsWrite(pPager->jfd, &zerobyte, 1, iNextHdrOffset); - } - if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ - return rc; - } - - /* Write the nRec value into the journal file header. If in - ** full-synchronous mode, sync the journal first. This ensures that - ** all data has really hit the disk before nRec is updated to mark - ** it as a candidate for rollback. - ** - ** This is not required if the persistent media supports the - ** SAFE_APPEND property. Because in this case it is not possible - ** for garbage data to be appended to the file, the nRec field - ** is populated with 0xFFFFFFFF when the journal header is written - ** and never needs to be updated. - */ - if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ - PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); - IOTRACE(("JSYNC %p\n", pPager)) - rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags); - if( rc!=SQLITE_OK ) return rc; - } - IOTRACE(("JHDR %p %lld\n", pPager, pPager->journalHdr)); - rc = sqlite3OsWrite( - pPager->jfd, zHeader, sizeof(zHeader), pPager->journalHdr - ); - if( rc!=SQLITE_OK ) return rc; - } - if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ - PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); - IOTRACE(("JSYNC %p\n", pPager)) - rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags| - (pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) - ); - if( rc!=SQLITE_OK ) return rc; - } - - pPager->journalHdr = pPager->journalOff; - if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ - pPager->nRec = 0; - rc = writeJournalHdr(pPager); - if( rc!=SQLITE_OK ) return rc; - } - }else{ - pPager->journalHdr = pPager->journalOff; - } - } - - /* Unless the pager is in noSync mode, the journal file was just - ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on - ** all pages. - */ - sqlite3PcacheClearSyncFlags(pPager->pPCache); - pPager->eState = PAGER_WRITER_DBMOD; - assert( assert_pager_state(pPager) ); - return SQLITE_OK; -} - -/* -** The argument is the first in a linked list of dirty pages connected -** by the PgHdr.pDirty pointer. This function writes each one of the -** in-memory pages in the list to the database file. The argument may -** be NULL, representing an empty list. In this case this function is -** a no-op. -** -** The pager must hold at least a RESERVED lock when this function -** is called. Before writing anything to the database file, this lock -** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained, -** SQLITE_BUSY is returned and no data is written to the database file. -** -** If the pager is a temp-file pager and the actual file-system file -** is not yet open, it is created and opened before any data is -** written out. -** -** Once the lock has been upgraded and, if necessary, the file opened, -** the pages are written out to the database file in list order. Writing -** a page is skipped if it meets either of the following criteria: -** -** * The page number is greater than Pager.dbSize, or -** * The PGHDR_DONT_WRITE flag is set on the page. -** -** If writing out a page causes the database file to grow, Pager.dbFileSize -** is updated accordingly. If page 1 is written out, then the value cached -** in Pager.dbFileVers[] is updated to match the new value stored in -** the database file. -** -** If everything is successful, SQLITE_OK is returned. If an IO error -** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot -** be obtained, SQLITE_BUSY is returned. -*/ -static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ - int rc = SQLITE_OK; /* Return code */ - - /* This function is only called for rollback pagers in WRITER_DBMOD state. */ - assert( !pagerUseWal(pPager) ); - assert( pPager->eState==PAGER_WRITER_DBMOD ); - assert( pPager->eLock==EXCLUSIVE_LOCK ); - - /* If the file is a temp-file has not yet been opened, open it now. It - ** is not possible for rc to be other than SQLITE_OK if this branch - ** is taken, as pager_wait_on_lock() is a no-op for temp-files. - */ - if( !isOpen(pPager->fd) ){ - assert( pPager->tempFile && rc==SQLITE_OK ); - rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags); - } - - /* Before the first write, give the VFS a hint of what the final - ** file size will be. - */ - assert( rc!=SQLITE_OK || isOpen(pPager->fd) ); - if( rc==SQLITE_OK - && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize - ){ - sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize; - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile); - pPager->dbHintSize = pPager->dbSize; - } - - while( rc==SQLITE_OK && pList ){ - Pgno pgno = pList->pgno; - - /* If there are dirty pages in the page cache with page numbers greater - ** than Pager.dbSize, this means sqlite3PagerTruncateImage() was called to - ** make the file smaller (presumably by auto-vacuum code). Do not write - ** any such pages to the file. - ** - ** Also, do not write out any page that has the PGHDR_DONT_WRITE flag - ** set (set by sqlite3PagerDontWrite()). - */ - if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){ - i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */ - char *pData; /* Data to write */ - - assert( (pList->flags&PGHDR_NEED_SYNC)==0 ); - if( pList->pgno==1 ) pager_write_changecounter(pList); - - /* Encode the database */ - CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData); - - /* Write out the page data. */ - rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); - - /* If page 1 was just written, update Pager.dbFileVers to match - ** the value now stored in the database file. If writing this - ** page caused the database file to grow, update dbFileSize. - */ - if( pgno==1 ){ - memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers)); - } - if( pgno>pPager->dbFileSize ){ - pPager->dbFileSize = pgno; - } - pPager->aStat[PAGER_STAT_WRITE]++; - - /* Update any backup objects copying the contents of this pager. */ - sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData); - - PAGERTRACE(("STORE %d page %d hash(%08x)\n", - PAGERID(pPager), pgno, pager_pagehash(pList))); - IOTRACE(("PGOUT %p %d\n", pPager, pgno)); - PAGER_INCR(sqlite3_pager_writedb_count); - }else{ - PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno)); - } - pager_set_pagehash(pList); - pList = pList->pDirty; - } - - return rc; -} - -/* -** Ensure that the sub-journal file is open. If it is already open, this -** function is a no-op. -** -** SQLITE_OK is returned if everything goes according to plan. An -** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() -** fails. -*/ -static int openSubJournal(Pager *pPager){ - int rc = SQLITE_OK; - if( !isOpen(pPager->sjfd) ){ - if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->subjInMemory ){ - sqlite3MemJournalOpen(pPager->sjfd); - }else{ - rc = pagerOpentemp(pPager, pPager->sjfd, SQLITE_OPEN_SUBJOURNAL); - } - } - return rc; -} - -/* -** Append a record of the current state of page pPg to the sub-journal. -** It is the callers responsibility to use subjRequiresPage() to check -** that it is really required before calling this function. -** -** If successful, set the bit corresponding to pPg->pgno in the bitvecs -** for all open savepoints before returning. -** -** This function returns SQLITE_OK if everything is successful, an IO -** error code if the attempt to write to the sub-journal fails, or -** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint -** bitvec. -*/ -static int subjournalPage(PgHdr *pPg){ - int rc = SQLITE_OK; - Pager *pPager = pPg->pPager; - if( pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ - - /* Open the sub-journal, if it has not already been opened */ - assert( pPager->useJournal ); - assert( isOpen(pPager->jfd) || pagerUseWal(pPager) ); - assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 ); - assert( pagerUseWal(pPager) - || pageInJournal(pPg) - || pPg->pgno>pPager->dbOrigSize - ); - rc = openSubJournal(pPager); - - /* If the sub-journal was opened successfully (or was already open), - ** write the journal record into the file. */ - if( rc==SQLITE_OK ){ - void *pData = pPg->pData; - i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize); - char *pData2; - - CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); - PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno)); - rc = write32bits(pPager->sjfd, offset, pPg->pgno); - if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4); - } - } - } - if( rc==SQLITE_OK ){ - pPager->nSubRec++; - assert( pPager->nSavepoint>0 ); - rc = addToSavepointBitvecs(pPager, pPg->pgno); - } - return rc; -} - -/* -** This function is called by the pcache layer when it has reached some -** soft memory limit. The first argument is a pointer to a Pager object -** (cast as a void*). The pager is always 'purgeable' (not an in-memory -** database). The second argument is a reference to a page that is -** currently dirty but has no outstanding references. The page -** is always associated with the Pager object passed as the first -** argument. -** -** The job of this function is to make pPg clean by writing its contents -** out to the database file, if possible. This may involve syncing the -** journal file. -** -** If successful, sqlite3PcacheMakeClean() is called on the page and -** SQLITE_OK returned. If an IO error occurs while trying to make the -** page clean, the IO error code is returned. If the page cannot be -** made clean for some other reason, but no error occurs, then SQLITE_OK -** is returned by sqlite3PcacheMakeClean() is not called. -*/ -static int pagerStress(void *p, PgHdr *pPg){ - Pager *pPager = (Pager *)p; - int rc = SQLITE_OK; - - assert( pPg->pPager==pPager ); - assert( pPg->flags&PGHDR_DIRTY ); - - /* The doNotSyncSpill flag is set during times when doing a sync of - ** journal (and adding a new header) is not allowed. This occurs - ** during calls to sqlite3PagerWrite() while trying to journal multiple - ** pages belonging to the same sector. - ** - ** The doNotSpill flag inhibits all cache spilling regardless of whether - ** or not a sync is required. This is set during a rollback. - ** - ** Spilling is also prohibited when in an error state since that could - ** lead to database corruption. In the current implementaton it - ** is impossible for sqlite3PcacheFetch() to be called with createFlag==1 - ** while in the error state, hence it is impossible for this routine to - ** be called in the error state. Nevertheless, we include a NEVER() - ** test for the error state as a safeguard against future changes. - */ - if( NEVER(pPager->errCode) ) return SQLITE_OK; - if( pPager->doNotSpill ) return SQLITE_OK; - if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){ - return SQLITE_OK; - } - - pPg->pDirty = 0; - if( pagerUseWal(pPager) ){ - /* Write a single frame for this page to the log. */ - if( subjRequiresPage(pPg) ){ - rc = subjournalPage(pPg); - } - if( rc==SQLITE_OK ){ - rc = pagerWalFrames(pPager, pPg, 0, 0); - } - }else{ - - /* Sync the journal file if required. */ - if( pPg->flags&PGHDR_NEED_SYNC - || pPager->eState==PAGER_WRITER_CACHEMOD - ){ - rc = syncJournal(pPager, 1); - } - - /* If the page number of this page is larger than the current size of - ** the database image, it may need to be written to the sub-journal. - ** This is because the call to pager_write_pagelist() below will not - ** actually write data to the file in this case. - ** - ** Consider the following sequence of events: - ** - ** BEGIN; - ** - ** - ** SAVEPOINT sp; - ** - ** pagerStress(page X) - ** ROLLBACK TO sp; - ** - ** If (X>Y), then when pagerStress is called page X will not be written - ** out to the database file, but will be dropped from the cache. Then, - ** following the "ROLLBACK TO sp" statement, reading page X will read - ** data from the database file. This will be the copy of page X as it - ** was when the transaction started, not as it was when "SAVEPOINT sp" - ** was executed. - ** - ** The solution is to write the current data for page X into the - ** sub-journal file now (if it is not already there), so that it will - ** be restored to its current value when the "ROLLBACK TO sp" is - ** executed. - */ - if( NEVER( - rc==SQLITE_OK && pPg->pgno>pPager->dbSize && subjRequiresPage(pPg) - ) ){ - rc = subjournalPage(pPg); - } - - /* Write the contents of the page out to the database file. */ - if( rc==SQLITE_OK ){ - assert( (pPg->flags&PGHDR_NEED_SYNC)==0 ); - rc = pager_write_pagelist(pPager, pPg); - } - } - - /* Mark the page as clean. */ - if( rc==SQLITE_OK ){ - PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); - sqlite3PcacheMakeClean(pPg); - } - - return pager_error(pPager, rc); -} - - -/* -** Allocate and initialize a new Pager object and put a pointer to it -** in *ppPager. The pager should eventually be freed by passing it -** to sqlite3PagerClose(). -** -** The zFilename argument is the path to the database file to open. -** If zFilename is NULL then a randomly-named temporary file is created -** and used as the file to be cached. Temporary files are be deleted -** automatically when they are closed. If zFilename is ":memory:" then -** all information is held in cache. It is never written to disk. -** This can be used to implement an in-memory database. -** -** The nExtra parameter specifies the number of bytes of space allocated -** along with each page reference. This space is available to the user -** via the sqlite3PagerGetExtra() API. -** -** The flags argument is used to specify properties that affect the -** operation of the pager. It should be passed some bitwise combination -** of the PAGER_* flags. -** -** The vfsFlags parameter is a bitmask to pass to the flags parameter -** of the xOpen() method of the supplied VFS when opening files. -** -** If the pager object is allocated and the specified file opened -** successfully, SQLITE_OK is returned and *ppPager set to point to -** the new pager object. If an error occurs, *ppPager is set to NULL -** and error code returned. This function may return SQLITE_NOMEM -** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or -** various SQLITE_IO_XXX errors. -*/ -SQLITE_PRIVATE int sqlite3PagerOpen( - sqlite3_vfs *pVfs, /* The virtual file system to use */ - Pager **ppPager, /* OUT: Return the Pager structure here */ - const char *zFilename, /* Name of the database file to open */ - int nExtra, /* Extra bytes append to each in-memory page */ - int flags, /* flags controlling this file */ - int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */ - void (*xReinit)(DbPage*) /* Function to reinitialize pages */ -){ - u8 *pPtr; - Pager *pPager = 0; /* Pager object to allocate and return */ - int rc = SQLITE_OK; /* Return code */ - int tempFile = 0; /* True for temp files (incl. in-memory files) */ - int memDb = 0; /* True if this is an in-memory file */ - int readOnly = 0; /* True if this is a read-only file */ - int journalFileSize; /* Bytes to allocate for each journal fd */ - char *zPathname = 0; /* Full path to database file */ - int nPathname = 0; /* Number of bytes in zPathname */ - int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */ - int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */ - u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */ - const char *zUri = 0; /* URI args to copy */ - int nUri = 0; /* Number of bytes of URI args at *zUri */ - - /* Figure out how much space is required for each journal file-handle - ** (there are two of them, the main journal and the sub-journal). This - ** is the maximum space required for an in-memory journal file handle - ** and a regular journal file-handle. Note that a "regular journal-handle" - ** may be a wrapper capable of caching the first portion of the journal - ** file in memory to implement the atomic-write optimization (see - ** source file journal.c). - */ - if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){ - journalFileSize = ROUND8(sqlite3JournalSize(pVfs)); - }else{ - journalFileSize = ROUND8(sqlite3MemJournalSize()); - } - - /* Set the output variable to NULL in case an error occurs. */ - *ppPager = 0; - -#ifndef SQLITE_OMIT_MEMORYDB - if( flags & PAGER_MEMORY ){ - memDb = 1; - if( zFilename && zFilename[0] ){ - zPathname = sqlite3DbStrDup(0, zFilename); - if( zPathname==0 ) return SQLITE_NOMEM; - nPathname = sqlite3Strlen30(zPathname); - zFilename = 0; - } - } -#endif - - /* Compute and store the full pathname in an allocated buffer pointed - ** to by zPathname, length nPathname. Or, if this is a temporary file, - ** leave both nPathname and zPathname set to 0. - */ - if( zFilename && zFilename[0] ){ - const char *z; - nPathname = pVfs->mxPathname+1; - zPathname = sqlite3DbMallocRaw(0, nPathname*2); - if( zPathname==0 ){ - return SQLITE_NOMEM; - } - zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */ - rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); - nPathname = sqlite3Strlen30(zPathname); - z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1]; - while( *z ){ - z += sqlite3Strlen30(z)+1; - z += sqlite3Strlen30(z)+1; - } - nUri = (int)(&z[1] - zUri); - assert( nUri>=0 ); - if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){ - /* This branch is taken when the journal path required by - ** the database being opened will be more than pVfs->mxPathname - ** bytes in length. This means the database cannot be opened, - ** as it will not be possible to open the journal file or even - ** check for a hot-journal before reading. - */ - rc = SQLITE_CANTOPEN_BKPT; - } - if( rc!=SQLITE_OK ){ - sqlite3DbFree(0, zPathname); - return rc; - } - } - - /* Allocate memory for the Pager structure, PCache object, the - ** three file descriptors, the database file name and the journal - ** file name. The layout in memory is as follows: - ** - ** Pager object (sizeof(Pager) bytes) - ** PCache object (sqlite3PcacheSize() bytes) - ** Database file handle (pVfs->szOsFile bytes) - ** Sub-journal file handle (journalFileSize bytes) - ** Main journal file handle (journalFileSize bytes) - ** Database file name (nPathname+1 bytes) - ** Journal file name (nPathname+8+1 bytes) - */ - pPtr = (u8 *)sqlite3MallocZero( - ROUND8(sizeof(*pPager)) + /* Pager structure */ - ROUND8(pcacheSize) + /* PCache object */ - ROUND8(pVfs->szOsFile) + /* The main db file */ - journalFileSize * 2 + /* The two journal files */ - nPathname + 1 + nUri + /* zFilename */ - nPathname + 8 + 2 /* zJournal */ -#ifndef SQLITE_OMIT_WAL - + nPathname + 4 + 2 /* zWal */ -#endif - ); - assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); - if( !pPtr ){ - sqlite3DbFree(0, zPathname); - return SQLITE_NOMEM; - } - pPager = (Pager*)(pPtr); - pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager))); - pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize)); - pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile)); - pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize); - pPager->zFilename = (char*)(pPtr += journalFileSize); - assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); - - /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */ - if( zPathname ){ - assert( nPathname>0 ); - pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri); - memcpy(pPager->zFilename, zPathname, nPathname); - if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri); - memcpy(pPager->zJournal, zPathname, nPathname); - memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2); - sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal); -#ifndef SQLITE_OMIT_WAL - pPager->zWal = &pPager->zJournal[nPathname+8+1]; - memcpy(pPager->zWal, zPathname, nPathname); - memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1); - sqlite3FileSuffix3(pPager->zFilename, pPager->zWal); -#endif - sqlite3DbFree(0, zPathname); - } - pPager->pVfs = pVfs; - pPager->vfsFlags = vfsFlags; - - /* Open the pager file. - */ - if( zFilename && zFilename[0] ){ - int fout = 0; /* VFS flags returned by xOpen() */ - rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); - assert( !memDb ); - readOnly = (fout&SQLITE_OPEN_READONLY); - - /* If the file was successfully opened for read/write access, - ** choose a default page size in case we have to create the - ** database file. The default page size is the maximum of: - ** - ** + SQLITE_DEFAULT_PAGE_SIZE, - ** + The value returned by sqlite3OsSectorSize() - ** + The largest page size that can be written atomically. - */ - if( rc==SQLITE_OK && !readOnly ){ - setSectorSize(pPager); - assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE); - if( szPageDfltsectorSize ){ - if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ - szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; - }else{ - szPageDflt = (u32)pPager->sectorSize; - } - } -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - { - int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); - int ii; - assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); - assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); - assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536); - for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){ - if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){ - szPageDflt = ii; - } - } - } -#endif - } - }else{ - /* If a temporary file is requested, it is not opened immediately. - ** In this case we accept the default page size and delay actually - ** opening the file until the first call to OsWrite(). - ** - ** This branch is also run for an in-memory database. An in-memory - ** database is the same as a temp-file that is never written out to - ** disk and uses an in-memory rollback journal. - */ - tempFile = 1; - pPager->eState = PAGER_READER; - pPager->eLock = EXCLUSIVE_LOCK; - readOnly = (vfsFlags&SQLITE_OPEN_READONLY); - } - - /* The following call to PagerSetPagesize() serves to set the value of - ** Pager.pageSize and to allocate the Pager.pTmpSpace buffer. - */ - if( rc==SQLITE_OK ){ - assert( pPager->memDb==0 ); - rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1); - testcase( rc!=SQLITE_OK ); - } - - /* If an error occurred in either of the blocks above, free the - ** Pager structure and close the file. - */ - if( rc!=SQLITE_OK ){ - assert( !pPager->pTmpSpace ); - sqlite3OsClose(pPager->fd); - sqlite3_free(pPager); - return rc; - } - - /* Initialize the PCache object. */ - assert( nExtra<1000 ); - nExtra = ROUND8(nExtra); - sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, - !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); - - PAGERTRACE(("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename)); - IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) - - pPager->useJournal = (u8)useJournal; - /* pPager->stmtOpen = 0; */ - /* pPager->stmtInUse = 0; */ - /* pPager->nRef = 0; */ - /* pPager->stmtSize = 0; */ - /* pPager->stmtJSize = 0; */ - /* pPager->nPage = 0; */ - pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; - /* pPager->state = PAGER_UNLOCK; */ -#if 0 - assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) ); -#endif - /* pPager->errMask = 0; */ - pPager->tempFile = (u8)tempFile; - assert( tempFile==PAGER_LOCKINGMODE_NORMAL - || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); - assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); - pPager->exclusiveMode = (u8)tempFile; - pPager->changeCountDone = pPager->tempFile; - pPager->memDb = (u8)memDb; - pPager->readOnly = (u8)readOnly; - assert( useJournal || pPager->tempFile ); - pPager->noSync = pPager->tempFile; - if( pPager->noSync ){ - assert( pPager->fullSync==0 ); - assert( pPager->syncFlags==0 ); - assert( pPager->walSyncFlags==0 ); - assert( pPager->ckptSyncFlags==0 ); - }else{ - pPager->fullSync = 1; - pPager->syncFlags = SQLITE_SYNC_NORMAL; - pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; - pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; - } - /* pPager->pFirst = 0; */ - /* pPager->pFirstSynced = 0; */ - /* pPager->pLast = 0; */ - pPager->nExtra = (u16)nExtra; - pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; - assert( isOpen(pPager->fd) || tempFile ); - setSectorSize(pPager); - if( !useJournal ){ - pPager->journalMode = PAGER_JOURNALMODE_OFF; - }else if( memDb ){ - pPager->journalMode = PAGER_JOURNALMODE_MEMORY; - } - /* pPager->xBusyHandler = 0; */ - /* pPager->pBusyHandlerArg = 0; */ - pPager->xReiniter = xReinit; - /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ - /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */ - - *ppPager = pPager; - return SQLITE_OK; -} - - - -/* -** This function is called after transitioning from PAGER_UNLOCK to -** PAGER_SHARED state. It tests if there is a hot journal present in -** the file-system for the given pager. A hot journal is one that -** needs to be played back. According to this function, a hot-journal -** file exists if the following criteria are met: -** -** * The journal file exists in the file system, and -** * No process holds a RESERVED or greater lock on the database file, and -** * The database file itself is greater than 0 bytes in size, and -** * The first byte of the journal file exists and is not 0x00. -** -** If the current size of the database file is 0 but a journal file -** exists, that is probably an old journal left over from a prior -** database with the same name. In this case the journal file is -** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK -** is returned. -** -** This routine does not check if there is a master journal filename -** at the end of the file. If there is, and that master journal file -** does not exist, then the journal file is not really hot. In this -** case this routine will return a false-positive. The pager_playback() -** routine will discover that the journal file is not really hot and -** will not roll it back. -** -** If a hot-journal file is found to exist, *pExists is set to 1 and -** SQLITE_OK returned. If no hot-journal file is present, *pExists is -** set to 0 and SQLITE_OK returned. If an IO error occurs while trying -** to determine whether or not a hot-journal file exists, the IO error -** code is returned and the value of *pExists is undefined. -*/ -static int hasHotJournal(Pager *pPager, int *pExists){ - sqlite3_vfs * const pVfs = pPager->pVfs; - int rc = SQLITE_OK; /* Return code */ - int exists = 1; /* True if a journal file is present */ - int jrnlOpen = !!isOpen(pPager->jfd); - - assert( pPager->useJournal ); - assert( isOpen(pPager->fd) ); - assert( pPager->eState==PAGER_OPEN ); - - assert( jrnlOpen==0 || ( sqlite3OsDeviceCharacteristics(pPager->jfd) & - SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN - )); - - *pExists = 0; - if( !jrnlOpen ){ - rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists); - } - if( rc==SQLITE_OK && exists ){ - int locked = 0; /* True if some process holds a RESERVED lock */ - - /* Race condition here: Another process might have been holding the - ** the RESERVED lock and have a journal open at the sqlite3OsAccess() - ** call above, but then delete the journal and drop the lock before - ** we get to the following sqlite3OsCheckReservedLock() call. If that - ** is the case, this routine might think there is a hot journal when - ** in fact there is none. This results in a false-positive which will - ** be dealt with by the playback routine. Ticket #3883. - */ - rc = sqlite3OsCheckReservedLock(pPager->fd, &locked); - if( rc==SQLITE_OK && !locked ){ - Pgno nPage; /* Number of pages in database file */ - - /* Check the size of the database file. If it consists of 0 pages, - ** then delete the journal file. See the header comment above for - ** the reasoning here. Delete the obsolete journal file under - ** a RESERVED lock to avoid race conditions and to avoid violating - ** [H33020]. - */ - rc = pagerPagecount(pPager, &nPage); - if( rc==SQLITE_OK ){ - if( nPage==0 ){ - sqlite3BeginBenignMalloc(); - if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){ - sqlite3OsDelete(pVfs, pPager->zJournal, 0); - if( !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); - } - sqlite3EndBenignMalloc(); - }else{ - /* The journal file exists and no other connection has a reserved - ** or greater lock on the database file. Now check that there is - ** at least one non-zero bytes at the start of the journal file. - ** If there is, then we consider this journal to be hot. If not, - ** it can be ignored. - */ - if( !jrnlOpen ){ - int f = SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL; - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &f); - } - if( rc==SQLITE_OK ){ - u8 first = 0; - rc = sqlite3OsRead(pPager->jfd, (void *)&first, 1, 0); - if( rc==SQLITE_IOERR_SHORT_READ ){ - rc = SQLITE_OK; - } - if( !jrnlOpen ){ - sqlite3OsClose(pPager->jfd); - } - *pExists = (first!=0); - }else if( rc==SQLITE_CANTOPEN ){ - /* If we cannot open the rollback journal file in order to see if - ** its has a zero header, that might be due to an I/O error, or - ** it might be due to the race condition described above and in - ** ticket #3883. Either way, assume that the journal is hot. - ** This might be a false positive. But if it is, then the - ** automatic journal playback and recovery mechanism will deal - ** with it under an EXCLUSIVE lock where we do not need to - ** worry so much with race conditions. - */ - *pExists = 1; - rc = SQLITE_OK; - } - } - } - } - } - - return rc; -} - -/* -** This function is called to obtain a shared lock on the database file. -** It is illegal to call sqlite3PagerAcquire() until after this function -** has been successfully called. If a shared-lock is already held when -** this function is called, it is a no-op. -** -** The following operations are also performed by this function. -** -** 1) If the pager is currently in PAGER_OPEN state (no lock held -** on the database file), then an attempt is made to obtain a -** SHARED lock on the database file. Immediately after obtaining -** the SHARED lock, the file-system is checked for a hot-journal, -** which is played back if present. Following any hot-journal -** rollback, the contents of the cache are validated by checking -** the 'change-counter' field of the database file header and -** discarded if they are found to be invalid. -** -** 2) If the pager is running in exclusive-mode, and there are currently -** no outstanding references to any pages, and is in the error state, -** then an attempt is made to clear the error state by discarding -** the contents of the page cache and rolling back any open journal -** file. -** -** If everything is successful, SQLITE_OK is returned. If an IO error -** occurs while locking the database, checking for a hot-journal file or -** rolling back a journal file, the IO error code is returned. -*/ -SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - - /* This routine is only called from b-tree and only when there are no - ** outstanding pages. This implies that the pager state should either - ** be OPEN or READER. READER is only possible if the pager is or was in - ** exclusive access mode. - */ - assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); - assert( assert_pager_state(pPager) ); - assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER ); - if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } - - if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){ - int bHotJournal = 1; /* True if there exists a hot journal-file */ - - assert( !MEMDB ); - - rc = pager_wait_on_lock(pPager, SHARED_LOCK); - if( rc!=SQLITE_OK ){ - assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK ); - goto failed; - } - - /* If a journal file exists, and there is no RESERVED lock on the - ** database file, then it either needs to be played back or deleted. - */ - if( pPager->eLock<=SHARED_LOCK ){ - rc = hasHotJournal(pPager, &bHotJournal); - } - if( rc!=SQLITE_OK ){ - goto failed; - } - if( bHotJournal ){ - if( pPager->readOnly ){ - rc = SQLITE_READONLY_ROLLBACK; - goto failed; - } - - /* Get an EXCLUSIVE lock on the database file. At this point it is - ** important that a RESERVED lock is not obtained on the way to the - ** EXCLUSIVE lock. If it were, another process might open the - ** database file, detect the RESERVED lock, and conclude that the - ** database is safe to read while this process is still rolling the - ** hot-journal back. - ** - ** Because the intermediate RESERVED lock is not requested, any - ** other process attempting to access the database file will get to - ** this point in the code and fail to obtain its own EXCLUSIVE lock - ** on the database file. - ** - ** Unless the pager is in locking_mode=exclusive mode, the lock is - ** downgraded to SHARED_LOCK before this function returns. - */ - rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); - if( rc!=SQLITE_OK ){ - goto failed; - } - - /* If it is not already open and the file exists on disk, open the - ** journal for read/write access. Write access is required because - ** in exclusive-access mode the file descriptor will be kept open - ** and possibly used for a transaction later on. Also, write-access - ** is usually required to finalize the journal in journal_mode=persist - ** mode (and also for journal_mode=truncate on some systems). - ** - ** If the journal does not exist, it usually means that some - ** other connection managed to get in and roll it back before - ** this connection obtained the exclusive lock above. Or, it - ** may mean that the pager was in the error-state when this - ** function was called and the journal file does not exist. - */ - if( !isOpen(pPager->jfd) ){ - sqlite3_vfs * const pVfs = pPager->pVfs; - int bExists; /* True if journal file exists */ - rc = sqlite3OsAccess( - pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &bExists); - if( rc==SQLITE_OK && bExists ){ - int fout = 0; - int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; - assert( !pPager->tempFile ); - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); - assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); - if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){ - rc = SQLITE_CANTOPEN_BKPT; - sqlite3OsClose(pPager->jfd); - } - } - } - - /* Playback and delete the journal. Drop the database write - ** lock and reacquire the read lock. Purge the cache before - ** playing back the hot-journal so that we don't end up with - ** an inconsistent cache. Sync the hot journal before playing - ** it back since the process that crashed and left the hot journal - ** probably did not sync it and we are required to always sync - ** the journal before playing it back. - */ - if( isOpen(pPager->jfd) ){ - assert( rc==SQLITE_OK ); - rc = pagerSyncHotJournal(pPager); - if( rc==SQLITE_OK ){ - rc = pager_playback(pPager, 1); - pPager->eState = PAGER_OPEN; - } - }else if( !pPager->exclusiveMode ){ - pagerUnlockDb(pPager, SHARED_LOCK); - } - - if( rc!=SQLITE_OK ){ - /* This branch is taken if an error occurs while trying to open - ** or roll back a hot-journal while holding an EXCLUSIVE lock. The - ** pager_unlock() routine will be called before returning to unlock - ** the file. If the unlock attempt fails, then Pager.eLock must be - ** set to UNKNOWN_LOCK (see the comment above the #define for - ** UNKNOWN_LOCK above for an explanation). - ** - ** In order to get pager_unlock() to do this, set Pager.eState to - ** PAGER_ERROR now. This is not actually counted as a transition - ** to ERROR state in the state diagram at the top of this file, - ** since we know that the same call to pager_unlock() will very - ** shortly transition the pager object to the OPEN state. Calling - ** assert_pager_state() would fail now, as it should not be possible - ** to be in ERROR state when there are zero outstanding page - ** references. - */ - pager_error(pPager, rc); - goto failed; - } - - assert( pPager->eState==PAGER_OPEN ); - assert( (pPager->eLock==SHARED_LOCK) - || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) - ); - } - - if( !pPager->tempFile && ( - pPager->pBackup - || sqlite3PcachePagecount(pPager->pPCache)>0 - || USEFETCH(pPager) - )){ - /* The shared-lock has just been acquired on the database file - ** and there are already pages in the cache (from a previous - ** read or write transaction). Check to see if the database - ** has been modified. If the database has changed, flush the - ** cache. - ** - ** Database changes is detected by looking at 15 bytes beginning - ** at offset 24 into the file. The first 4 of these 16 bytes are - ** a 32-bit counter that is incremented with each change. The - ** other bytes change randomly with each file change when - ** a codec is in use. - ** - ** There is a vanishingly small chance that a change will not be - ** detected. The chance of an undetected change is so small that - ** it can be neglected. - */ - Pgno nPage = 0; - char dbFileVers[sizeof(pPager->dbFileVers)]; - - rc = pagerPagecount(pPager, &nPage); - if( rc ) goto failed; - - if( nPage>0 ){ - IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); - rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); - if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ - goto failed; - } - }else{ - memset(dbFileVers, 0, sizeof(dbFileVers)); - } - - if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ - pager_reset(pPager); - - /* Unmap the database file. It is possible that external processes - ** may have truncated the database file and then extended it back - ** to its original size while this process was not holding a lock. - ** In this case there may exist a Pager.pMap mapping that appears - ** to be the right size but is not actually valid. Avoid this - ** possibility by unmapping the db here. */ - if( USEFETCH(pPager) ){ - sqlite3OsUnfetch(pPager->fd, 0, 0); - } - } - } - - /* If there is a WAL file in the file-system, open this database in WAL - ** mode. Otherwise, the following function call is a no-op. - */ - rc = pagerOpenWalIfPresent(pPager); -#ifndef SQLITE_OMIT_WAL - assert( pPager->pWal==0 || rc==SQLITE_OK ); -#endif - } - - if( pagerUseWal(pPager) ){ - assert( rc==SQLITE_OK ); - rc = pagerBeginReadTransaction(pPager); - } - - if( pPager->eState==PAGER_OPEN && rc==SQLITE_OK ){ - rc = pagerPagecount(pPager, &pPager->dbSize); - } - - failed: - if( rc!=SQLITE_OK ){ - assert( !MEMDB ); - pager_unlock(pPager); - assert( pPager->eState==PAGER_OPEN ); - }else{ - pPager->eState = PAGER_READER; - } - return rc; -} - -/* -** If the reference count has reached zero, rollback any active -** transaction and unlock the pager. -** -** Except, in locking_mode=EXCLUSIVE when there is nothing to in -** the rollback journal, the unlock is not performed and there is -** nothing to rollback, so this routine is a no-op. -*/ -static void pagerUnlockIfUnused(Pager *pPager){ - if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){ - pagerUnlockAndRollback(pPager); - } -} - -/* -** Acquire a reference to page number pgno in pager pPager (a page -** reference has type DbPage*). If the requested reference is -** successfully obtained, it is copied to *ppPage and SQLITE_OK returned. -** -** If the requested page is already in the cache, it is returned. -** Otherwise, a new page object is allocated and populated with data -** read from the database file. In some cases, the pcache module may -** choose not to allocate a new page object and may reuse an existing -** object with no outstanding references. -** -** The extra data appended to a page is always initialized to zeros the -** first time a page is loaded into memory. If the page requested is -** already in the cache when this function is called, then the extra -** data is left as it was when the page object was last used. -** -** If the database image is smaller than the requested page or if a -** non-zero value is passed as the noContent parameter and the -** requested page is not already stored in the cache, then no -** actual disk read occurs. In this case the memory image of the -** page is initialized to all zeros. -** -** If noContent is true, it means that we do not care about the contents -** of the page. This occurs in two seperate scenarios: -** -** a) When reading a free-list leaf page from the database, and -** -** b) When a savepoint is being rolled back and we need to load -** a new page into the cache to be filled with the data read -** from the savepoint journal. -** -** If noContent is true, then the data returned is zeroed instead of -** being read from the database. Additionally, the bits corresponding -** to pgno in Pager.pInJournal (bitvec of pages already written to the -** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open -** savepoints are set. This means if the page is made writable at any -** point in the future, using a call to sqlite3PagerWrite(), its contents -** will not be journaled. This saves IO. -** -** The acquisition might fail for several reasons. In all cases, -** an appropriate error code is returned and *ppPage is set to NULL. -** -** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt -** to find a page in the in-memory cache first. If the page is not already -** in memory, this routine goes to disk to read it in whereas Lookup() -** just returns 0. This routine acquires a read-lock the first time it -** has to go to disk, and could also playback an old journal if necessary. -** Since Lookup() never goes to disk, it never has to deal with locks -** or journal files. -*/ -SQLITE_PRIVATE int sqlite3PagerAcquire( - Pager *pPager, /* The pager open on the database file */ - Pgno pgno, /* Page number to fetch */ - DbPage **ppPage, /* Write a pointer to the page here */ - int flags /* PAGER_ACQUIRE_XXX flags */ -){ - int rc = SQLITE_OK; - PgHdr *pPg = 0; - u32 iFrame = 0; /* Frame to read from WAL file */ - const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT); - - /* It is acceptable to use a read-only (mmap) page for any page except - ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY - ** flag was specified by the caller. And so long as the db is not a - ** temporary or in-memory database. */ - const int bMmapOk = (pgno!=1 && USEFETCH(pPager) - && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY)) -#ifdef SQLITE_HAS_CODEC - && pPager->xCodec==0 -#endif - ); - - assert( pPager->eState>=PAGER_READER ); - assert( assert_pager_state(pPager) ); - assert( noContent==0 || bMmapOk==0 ); - - if( pgno==0 ){ - return SQLITE_CORRUPT_BKPT; - } - - /* If the pager is in the error state, return an error immediately. - ** Otherwise, request the page from the PCache layer. */ - if( pPager->errCode!=SQLITE_OK ){ - rc = pPager->errCode; - }else{ - - if( bMmapOk && pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); - if( rc!=SQLITE_OK ) goto pager_acquire_err; - } - - if( iFrame==0 && bMmapOk ){ - void *pData = 0; - - rc = sqlite3OsFetch(pPager->fd, - (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData - ); - - if( rc==SQLITE_OK && pData ){ - if( pPager->eState>PAGER_READER ){ - (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); - } - if( pPg==0 ){ - rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); - }else{ - sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); - } - if( pPg ){ - assert( rc==SQLITE_OK ); - *ppPage = pPg; - return SQLITE_OK; - } - } - if( rc!=SQLITE_OK ){ - goto pager_acquire_err; - } - } - - rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage); - } - - if( rc!=SQLITE_OK ){ - /* Either the call to sqlite3PcacheFetch() returned an error or the - ** pager was already in the error-state when this function was called. - ** Set pPg to 0 and jump to the exception handler. */ - pPg = 0; - goto pager_acquire_err; - } - assert( (*ppPage)->pgno==pgno ); - assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 ); - - if( (*ppPage)->pPager && !noContent ){ - /* In this case the pcache already contains an initialized copy of - ** the page. Return without further ado. */ - assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); - pPager->aStat[PAGER_STAT_HIT]++; - return SQLITE_OK; - - }else{ - /* The pager cache has created a new page. Its content needs to - ** be initialized. */ - - pPg = *ppPage; - pPg->pPager = pPager; - - /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page - ** number greater than this, or the unused locking-page, is requested. */ - if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ - rc = SQLITE_CORRUPT_BKPT; - goto pager_acquire_err; - } - - if( MEMDB || pPager->dbSizefd) ){ - if( pgno>pPager->mxPgno ){ - rc = SQLITE_FULL; - goto pager_acquire_err; - } - if( noContent ){ - /* Failure to set the bits in the InJournal bit-vectors is benign. - ** It merely means that we might do some extra work to journal a - ** page that does not need to be journaled. Nevertheless, be sure - ** to test the case where a malloc error occurs while trying to set - ** a bit in a bit vector. - */ - sqlite3BeginBenignMalloc(); - if( pgno<=pPager->dbOrigSize ){ - TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno); - testcase( rc==SQLITE_NOMEM ); - } - TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); - testcase( rc==SQLITE_NOMEM ); - sqlite3EndBenignMalloc(); - } - memset(pPg->pData, 0, pPager->pageSize); - IOTRACE(("ZERO %p %d\n", pPager, pgno)); - }else{ - if( pagerUseWal(pPager) && bMmapOk==0 ){ - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); - if( rc!=SQLITE_OK ) goto pager_acquire_err; - } - assert( pPg->pPager==pPager ); - pPager->aStat[PAGER_STAT_MISS]++; - rc = readDbPage(pPg, iFrame); - if( rc!=SQLITE_OK ){ - goto pager_acquire_err; - } - } - pager_set_pagehash(pPg); - } - - return SQLITE_OK; - -pager_acquire_err: - assert( rc!=SQLITE_OK ); - if( pPg ){ - sqlite3PcacheDrop(pPg); - } - pagerUnlockIfUnused(pPager); - - *ppPage = 0; - return rc; -} - -/* -** Acquire a page if it is already in the in-memory cache. Do -** not read the page from disk. Return a pointer to the page, -** or 0 if the page is not in cache. -** -** See also sqlite3PagerGet(). The difference between this routine -** and sqlite3PagerGet() is that _get() will go to the disk and read -** in the page if the page is not already in cache. This routine -** returns NULL if the page is not in cache or if a disk I/O error -** has ever happened. -*/ -SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ - PgHdr *pPg = 0; - assert( pPager!=0 ); - assert( pgno!=0 ); - assert( pPager->pPCache!=0 ); - assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR ); - sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); - return pPg; -} - -/* -** Release a page reference. -** -** If the number of references to the page drop to zero, then the -** page is added to the LRU list. When all references to all pages -** are released, a rollback occurs and the lock on the database is -** removed. -*/ -SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ - if( pPg ){ - Pager *pPager = pPg->pPager; - if( pPg->flags & PGHDR_MMAP ){ - pagerReleaseMapPage(pPg); - }else{ - sqlite3PcacheRelease(pPg); - } - pagerUnlockIfUnused(pPager); - } -} - -/* -** This function is called at the start of every write transaction. -** There must already be a RESERVED or EXCLUSIVE lock on the database -** file when this routine is called. -** -** Open the journal file for pager pPager and write a journal header -** to the start of it. If there are active savepoints, open the sub-journal -** as well. This function is only used when the journal file is being -** opened to write a rollback log for a transaction. It is not used -** when opening a hot journal file to roll it back. -** -** If the journal file is already open (as it may be in exclusive mode), -** then this function just writes a journal header to the start of the -** already open file. -** -** Whether or not the journal file is opened by this function, the -** Pager.pInJournal bitvec structure is allocated. -** -** Return SQLITE_OK if everything is successful. Otherwise, return -** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or -** an IO error code if opening or writing the journal file fails. -*/ -static int pager_open_journal(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */ - - assert( pPager->eState==PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - assert( pPager->pInJournal==0 ); - - /* If already in the error state, this function is a no-op. But on - ** the other hand, this routine is never called if we are already in - ** an error state. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - - if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ - pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); - if( pPager->pInJournal==0 ){ - return SQLITE_NOMEM; - } - - /* Open the journal file if it is not already open. */ - if( !isOpen(pPager->jfd) ){ - if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ - sqlite3MemJournalOpen(pPager->jfd); - }else{ - const int flags = /* VFS flags to open journal file */ - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| - (pPager->tempFile ? - (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL): - (SQLITE_OPEN_MAIN_JOURNAL) - ); - #ifdef SQLITE_ENABLE_ATOMIC_WRITE - rc = sqlite3JournalOpen( - pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) - ); - #else - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); - #endif - } - assert( rc!=SQLITE_OK || isOpen(pPager->jfd) ); - } - - - /* Write the first journal header to the journal file and open - ** the sub-journal if necessary. - */ - if( rc==SQLITE_OK ){ - /* TODO: Check if all of these are really required. */ - pPager->nRec = 0; - pPager->journalOff = 0; - pPager->setMaster = 0; - pPager->journalHdr = 0; - rc = writeJournalHdr(pPager); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3BitvecDestroy(pPager->pInJournal); - pPager->pInJournal = 0; - }else{ - assert( pPager->eState==PAGER_WRITER_LOCKED ); - pPager->eState = PAGER_WRITER_CACHEMOD; - } - - return rc; -} - -/* -** Begin a write-transaction on the specified pager object. If a -** write-transaction has already been opened, this function is a no-op. -** -** If the exFlag argument is false, then acquire at least a RESERVED -** lock on the database file. If exFlag is true, then acquire at least -** an EXCLUSIVE lock. If such a lock is already held, no locking -** functions need be called. -** -** If the subjInMemory argument is non-zero, then any sub-journal opened -** within this transaction will be opened as an in-memory file. This -** has no effect if the sub-journal is already opened (as it may be when -** running in exclusive mode) or if the transaction does not require a -** sub-journal. If the subjInMemory argument is zero, then any required -** sub-journal is implemented in-memory if pPager is an in-memory database, -** or using a temporary file otherwise. -*/ -SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ - int rc = SQLITE_OK; - - if( pPager->errCode ) return pPager->errCode; - assert( pPager->eState>=PAGER_READER && pPager->eStatesubjInMemory = (u8)subjInMemory; - - if( ALWAYS(pPager->eState==PAGER_READER) ){ - assert( pPager->pInJournal==0 ); - - if( pagerUseWal(pPager) ){ - /* If the pager is configured to use locking_mode=exclusive, and an - ** exclusive lock on the database is not already held, obtain it now. - */ - if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){ - rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); - if( rc!=SQLITE_OK ){ - return rc; - } - sqlite3WalExclusiveMode(pPager->pWal, 1); - } - - /* Grab the write lock on the log file. If successful, upgrade to - ** PAGER_RESERVED state. Otherwise, return an error code to the caller. - ** The busy-handler is not invoked if another connection already - ** holds the write-lock. If possible, the upper layer will call it. - */ - rc = sqlite3WalBeginWriteTransaction(pPager->pWal); - }else{ - /* Obtain a RESERVED lock on the database file. If the exFlag parameter - ** is true, then immediately upgrade this to an EXCLUSIVE lock. The - ** busy-handler callback can be used when upgrading to the EXCLUSIVE - ** lock, but not when obtaining the RESERVED lock. - */ - rc = pagerLockDb(pPager, RESERVED_LOCK); - if( rc==SQLITE_OK && exFlag ){ - rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); - } - } - - if( rc==SQLITE_OK ){ - /* Change to WRITER_LOCKED state. - ** - ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD - ** when it has an open transaction, but never to DBMOD or FINISHED. - ** This is because in those states the code to roll back savepoint - ** transactions may copy data from the sub-journal into the database - ** file as well as into the page cache. Which would be incorrect in - ** WAL mode. - */ - pPager->eState = PAGER_WRITER_LOCKED; - pPager->dbHintSize = pPager->dbSize; - pPager->dbFileSize = pPager->dbSize; - pPager->dbOrigSize = pPager->dbSize; - pPager->journalOff = 0; - } - - assert( rc==SQLITE_OK || pPager->eState==PAGER_READER ); - assert( rc!=SQLITE_OK || pPager->eState==PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - } - - PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager))); - return rc; -} - -/* -** Mark a single data page as writeable. The page is written into the -** main journal or sub-journal as required. If the page is written into -** one of the journals, the corresponding bit is set in the -** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs -** of any open savepoints as appropriate. -*/ -static int pager_write(PgHdr *pPg){ - void *pData = pPg->pData; - Pager *pPager = pPg->pPager; - int rc = SQLITE_OK; - - /* This routine is not called unless a write-transaction has already - ** been started. The journal file may or may not be open at this point. - ** It is never called in the ERROR state. - */ - assert( pPager->eState==PAGER_WRITER_LOCKED - || pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - ); - assert( assert_pager_state(pPager) ); - - /* If an error has been previously detected, report the same error - ** again. This should not happen, but the check provides robustness. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - - /* Higher-level routines never call this function if database is not - ** writable. But check anyway, just for robustness. */ - if( NEVER(pPager->readOnly) ) return SQLITE_PERM; - - CHECK_PAGE(pPg); - - /* The journal file needs to be opened. Higher level routines have already - ** obtained the necessary locks to begin the write-transaction, but the - ** rollback journal might not yet be open. Open it now if this is the case. - ** - ** This is done before calling sqlite3PcacheMakeDirty() on the page. - ** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then - ** an error might occur and the pager would end up in WRITER_LOCKED state - ** with pages marked as dirty in the cache. - */ - if( pPager->eState==PAGER_WRITER_LOCKED ){ - rc = pager_open_journal(pPager); - if( rc!=SQLITE_OK ) return rc; - } - assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); - assert( assert_pager_state(pPager) ); - - /* Mark the page as dirty. If the page has already been written - ** to the journal then we can return right away. - */ - sqlite3PcacheMakeDirty(pPg); - if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){ - assert( !pagerUseWal(pPager) ); - }else{ - - /* The transaction journal now exists and we have a RESERVED or an - ** EXCLUSIVE lock on the main database file. Write the current page to - ** the transaction journal if it is not there already. - */ - if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){ - assert( pagerUseWal(pPager)==0 ); - if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){ - u32 cksum; - char *pData2; - i64 iOff = pPager->journalOff; - - /* We should never write to the journal file the page that - ** contains the database locks. The following assert verifies - ** that we do not. */ - assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); - - assert( pPager->journalHdr<=pPager->journalOff ); - CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2); - cksum = pager_cksum(pPager, (u8*)pData2); - - /* Even if an IO or diskfull error occurs while journalling the - ** page in the block above, set the need-sync flag for the page. - ** Otherwise, when the transaction is rolled back, the logic in - ** playback_one_page() will think that the page needs to be restored - ** in the database file. And if an IO error occurs while doing so, - ** then corruption may follow. - */ - pPg->flags |= PGHDR_NEED_SYNC; - - rc = write32bits(pPager->jfd, iOff, pPg->pgno); - if( rc!=SQLITE_OK ) return rc; - rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4); - if( rc!=SQLITE_OK ) return rc; - rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum); - if( rc!=SQLITE_OK ) return rc; - - IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, - pPager->journalOff, pPager->pageSize)); - PAGER_INCR(sqlite3_pager_writej_count); - PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n", - PAGERID(pPager), pPg->pgno, - ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg))); - - pPager->journalOff += 8 + pPager->pageSize; - pPager->nRec++; - assert( pPager->pInJournal!=0 ); - rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); - testcase( rc==SQLITE_NOMEM ); - assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); - rc |= addToSavepointBitvecs(pPager, pPg->pgno); - if( rc!=SQLITE_OK ){ - assert( rc==SQLITE_NOMEM ); - return rc; - } - }else{ - if( pPager->eState!=PAGER_WRITER_DBMOD ){ - pPg->flags |= PGHDR_NEED_SYNC; - } - PAGERTRACE(("APPEND %d page %d needSync=%d\n", - PAGERID(pPager), pPg->pgno, - ((pPg->flags&PGHDR_NEED_SYNC)?1:0))); - } - } - - /* If the statement journal is open and the page is not in it, - ** then write the current page to the statement journal. Note that - ** the statement journal format differs from the standard journal format - ** in that it omits the checksums and the header. - */ - if( subjRequiresPage(pPg) ){ - rc = subjournalPage(pPg); - } - } - - /* Update the database size and return. - */ - if( pPager->dbSizepgno ){ - pPager->dbSize = pPg->pgno; - } - return rc; -} - -/* -** Mark a data page as writeable. This routine must be called before -** making changes to a page. The caller must check the return value -** of this function and be careful not to change any page data unless -** this routine returns SQLITE_OK. -** -** The difference between this function and pager_write() is that this -** function also deals with the special case where 2 or more pages -** fit on a single disk sector. In this case all co-resident pages -** must have been written to the journal file before returning. -** -** If an error occurs, SQLITE_NOMEM or an IO error code is returned -** as appropriate. Otherwise, SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ - int rc = SQLITE_OK; - - PgHdr *pPg = pDbPage; - Pager *pPager = pPg->pPager; - Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); - - assert( (pPg->flags & PGHDR_MMAP)==0 ); - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - assert( pPager->eState!=PAGER_ERROR ); - assert( assert_pager_state(pPager) ); - - if( nPagePerSector>1 ){ - Pgno nPageCount; /* Total number of pages in database file */ - Pgno pg1; /* First page of the sector pPg is located on. */ - int nPage = 0; /* Number of pages starting at pg1 to journal */ - int ii; /* Loop counter */ - int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ - - /* Set the doNotSyncSpill flag to 1. This is because we cannot allow - ** a journal header to be written between the pages journaled by - ** this function. - */ - assert( !MEMDB ); - assert( pPager->doNotSyncSpill==0 ); - pPager->doNotSyncSpill++; - - /* This trick assumes that both the page-size and sector-size are - ** an integer power of 2. It sets variable pg1 to the identifier - ** of the first page of the sector pPg is located on. - */ - pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; - - nPageCount = pPager->dbSize; - if( pPg->pgno>nPageCount ){ - nPage = (pPg->pgno - pg1)+1; - }else if( (pg1+nPagePerSector-1)>nPageCount ){ - nPage = nPageCount+1-pg1; - }else{ - nPage = nPagePerSector; - } - assert(nPage>0); - assert(pg1<=pPg->pgno); - assert((pg1+nPage)>pPg->pgno); - - for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ - if( pg!=PAGER_MJ_PGNO(pPager) ){ - rc = sqlite3PagerGet(pPager, pg, &pPage); - if( rc==SQLITE_OK ){ - rc = pager_write(pPage); - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnref(pPage); - } - } - }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnref(pPage); - } - } - - /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages - ** starting at pg1, then it needs to be set for all of them. Because - ** writing to any of these nPage pages may damage the others, the - ** journal file must contain sync()ed copies of all of them - ** before any of them can be written out to the database file. - */ - if( rc==SQLITE_OK && needSync ){ - assert( !MEMDB ); - for(ii=0; iiflags |= PGHDR_NEED_SYNC; - sqlite3PagerUnref(pPage); - } - } - } - - assert( pPager->doNotSyncSpill==1 ); - pPager->doNotSyncSpill--; - }else{ - rc = pager_write(pDbPage); - } - return rc; -} - -/* -** Return TRUE if the page given in the argument was previously passed -** to sqlite3PagerWrite(). In other words, return TRUE if it is ok -** to change the content of the page. -*/ -#ifndef NDEBUG -SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ - return pPg->flags&PGHDR_DIRTY; -} -#endif - -/* -** A call to this routine tells the pager that it is not necessary to -** write the information on page pPg back to the disk, even though -** that page might be marked as dirty. This happens, for example, when -** the page has been added as a leaf of the freelist and so its -** content no longer matters. -** -** The overlying software layer calls this routine when all of the data -** on the given page is unused. The pager marks the page as clean so -** that it does not get written to disk. -** -** Tests show that this optimization can quadruple the speed of large -** DELETE operations. -*/ -SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){ - Pager *pPager = pPg->pPager; - if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ - PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); - IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) - pPg->flags |= PGHDR_DONT_WRITE; - pager_set_pagehash(pPg); - } -} - -/* -** This routine is called to increment the value of the database file -** change-counter, stored as a 4-byte big-endian integer starting at -** byte offset 24 of the pager file. The secondary change counter at -** 92 is also updated, as is the SQLite version number at offset 96. -** -** But this only happens if the pPager->changeCountDone flag is false. -** To avoid excess churning of page 1, the update only happens once. -** See also the pager_write_changecounter() routine that does an -** unconditional update of the change counters. -** -** If the isDirectMode flag is zero, then this is done by calling -** sqlite3PagerWrite() on page 1, then modifying the contents of the -** page data. In this case the file will be updated when the current -** transaction is committed. -** -** The isDirectMode flag may only be non-zero if the library was compiled -** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case, -** if isDirect is non-zero, then the database file is updated directly -** by writing an updated version of page 1 using a call to the -** sqlite3OsWrite() function. -*/ -static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ - int rc = SQLITE_OK; - - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - ); - assert( assert_pager_state(pPager) ); - - /* Declare and initialize constant integer 'isDirect'. If the - ** atomic-write optimization is enabled in this build, then isDirect - ** is initialized to the value passed as the isDirectMode parameter - ** to this function. Otherwise, it is always set to zero. - ** - ** The idea is that if the atomic-write optimization is not - ** enabled at compile time, the compiler can omit the tests of - ** 'isDirect' below, as well as the block enclosed in the - ** "if( isDirect )" condition. - */ -#ifndef SQLITE_ENABLE_ATOMIC_WRITE -# define DIRECT_MODE 0 - assert( isDirectMode==0 ); - UNUSED_PARAMETER(isDirectMode); -#else -# define DIRECT_MODE isDirectMode -#endif - - if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){ - PgHdr *pPgHdr; /* Reference to page 1 */ - - assert( !pPager->tempFile && isOpen(pPager->fd) ); - - /* Open page 1 of the file for writing. */ - rc = sqlite3PagerGet(pPager, 1, &pPgHdr); - assert( pPgHdr==0 || rc==SQLITE_OK ); - - /* If page one was fetched successfully, and this function is not - ** operating in direct-mode, make page 1 writable. When not in - ** direct mode, page 1 is always held in cache and hence the PagerGet() - ** above is always successful - hence the ALWAYS on rc==SQLITE_OK. - */ - if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){ - rc = sqlite3PagerWrite(pPgHdr); - } - - if( rc==SQLITE_OK ){ - /* Actually do the update of the change counter */ - pager_write_changecounter(pPgHdr); - - /* If running in direct mode, write the contents of page 1 to the file. */ - if( DIRECT_MODE ){ - const void *zBuf; - assert( pPager->dbFileSize>0 ); - CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf); - if( rc==SQLITE_OK ){ - rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); - pPager->aStat[PAGER_STAT_WRITE]++; - } - if( rc==SQLITE_OK ){ - /* Update the pager's copy of the change-counter. Otherwise, the - ** next time a read transaction is opened the cache will be - ** flushed (as the change-counter values will not match). */ - const void *pCopy = (const void *)&((const char *)zBuf)[24]; - memcpy(&pPager->dbFileVers, pCopy, sizeof(pPager->dbFileVers)); - pPager->changeCountDone = 1; - } - }else{ - pPager->changeCountDone = 1; - } - } - - /* Release the page reference. */ - sqlite3PagerUnref(pPgHdr); - } - return rc; -} - -/* -** Sync the database file to disk. This is a no-op for in-memory databases -** or pages with the Pager.noSync flag set. -** -** If successful, or if called on a pager for which it is a no-op, this -** function returns SQLITE_OK. Otherwise, an IO error code is returned. -*/ -SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){ - int rc = SQLITE_OK; - if( !pPager->noSync ){ - assert( !MEMDB ); - rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); - }else if( isOpen(pPager->fd) ){ - assert( !MEMDB ); - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0); - if( rc==SQLITE_NOTFOUND ){ - rc = SQLITE_OK; - } - } - return rc; -} - -/* -** This function may only be called while a write-transaction is active in -** rollback. If the connection is in WAL mode, this call is a no-op. -** Otherwise, if the connection does not already have an EXCLUSIVE lock on -** the database file, an attempt is made to obtain one. -** -** If the EXCLUSIVE lock is already held or the attempt to obtain it is -** successful, or the connection is in WAL mode, SQLITE_OK is returned. -** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is -** returned. -*/ -SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){ - int rc = SQLITE_OK; - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - || pPager->eState==PAGER_WRITER_LOCKED - ); - assert( assert_pager_state(pPager) ); - if( 0==pagerUseWal(pPager) ){ - rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); - } - return rc; -} - -/* -** Sync the database file for the pager pPager. zMaster points to the name -** of a master journal file that should be written into the individual -** journal file. zMaster may be NULL, which is interpreted as no master -** journal (a single database transaction). -** -** This routine ensures that: -** -** * The database file change-counter is updated, -** * the journal is synced (unless the atomic-write optimization is used), -** * all dirty pages are written to the database file, -** * the database file is truncated (if required), and -** * the database file synced. -** -** The only thing that remains to commit the transaction is to finalize -** (delete, truncate or zero the first part of) the journal file (or -** delete the master journal file if specified). -** -** Note that if zMaster==NULL, this does not overwrite a previous value -** passed to an sqlite3PagerCommitPhaseOne() call. -** -** If the final parameter - noSync - is true, then the database file itself -** is not synced. The caller must call sqlite3PagerSync() directly to -** sync the database file before calling CommitPhaseTwo() to delete the -** journal file in this case. -*/ -SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( - Pager *pPager, /* Pager object */ - const char *zMaster, /* If not NULL, the master journal name */ - int noSync /* True to omit the xSync on the db file */ -){ - int rc = SQLITE_OK; /* Return code */ - - assert( pPager->eState==PAGER_WRITER_LOCKED - || pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - || pPager->eState==PAGER_ERROR - ); - assert( assert_pager_state(pPager) ); - - /* If a prior error occurred, report that error again. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - - PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", - pPager->zFilename, zMaster, pPager->dbSize)); - - /* If no database changes have been made, return early. */ - if( pPager->eStatepBackup); - }else{ - if( pagerUseWal(pPager) ){ - PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); - PgHdr *pPageOne = 0; - if( pList==0 ){ - /* Must have at least one page for the WAL commit flag. - ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ - rc = sqlite3PagerGet(pPager, 1, &pPageOne); - pList = pPageOne; - pList->pDirty = 0; - } - assert( rc==SQLITE_OK ); - if( ALWAYS(pList) ){ - rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1); - } - sqlite3PagerUnref(pPageOne); - if( rc==SQLITE_OK ){ - sqlite3PcacheCleanAll(pPager->pPCache); - } - }else{ - /* The following block updates the change-counter. Exactly how it - ** does this depends on whether or not the atomic-update optimization - ** was enabled at compile time, and if this transaction meets the - ** runtime criteria to use the operation: - ** - ** * The file-system supports the atomic-write property for - ** blocks of size page-size, and - ** * This commit is not part of a multi-file transaction, and - ** * Exactly one page has been modified and store in the journal file. - ** - ** If the optimization was not enabled at compile time, then the - ** pager_incr_changecounter() function is called to update the change - ** counter in 'indirect-mode'. If the optimization is compiled in but - ** is not applicable to this transaction, call sqlite3JournalCreate() - ** to make sure the journal file has actually been created, then call - ** pager_incr_changecounter() to update the change-counter in indirect - ** mode. - ** - ** Otherwise, if the optimization is both enabled and applicable, - ** then call pager_incr_changecounter() to update the change-counter - ** in 'direct' mode. In this case the journal file will never be - ** created for this transaction. - */ - #ifdef SQLITE_ENABLE_ATOMIC_WRITE - PgHdr *pPg; - assert( isOpen(pPager->jfd) - || pPager->journalMode==PAGER_JOURNALMODE_OFF - || pPager->journalMode==PAGER_JOURNALMODE_WAL - ); - if( !zMaster && isOpen(pPager->jfd) - && pPager->journalOff==jrnlBufferSize(pPager) - && pPager->dbSize>=pPager->dbOrigSize - && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) - ){ - /* Update the db file change counter via the direct-write method. The - ** following call will modify the in-memory representation of page 1 - ** to include the updated change counter and then write page 1 - ** directly to the database file. Because of the atomic-write - ** property of the host file-system, this is safe. - */ - rc = pager_incr_changecounter(pPager, 1); - }else{ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc==SQLITE_OK ){ - rc = pager_incr_changecounter(pPager, 0); - } - } - #else - rc = pager_incr_changecounter(pPager, 0); - #endif - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - /* Write the master journal name into the journal file. If a master - ** journal file name has already been written to the journal file, - ** or if zMaster is NULL (no master journal), then this call is a no-op. - */ - rc = writeMasterJournal(pPager, zMaster); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - /* Sync the journal file and write all dirty pages to the database. - ** If the atomic-update optimization is being used, this sync will not - ** create the journal file or perform any real IO. - ** - ** Because the change-counter page was just modified, unless the - ** atomic-update optimization is used it is almost certain that the - ** journal requires a sync here. However, in locking_mode=exclusive - ** on a system under memory pressure it is just possible that this is - ** not the case. In this case it is likely enough that the redundant - ** xSync() call will be changed to a no-op by the OS anyhow. - */ - rc = syncJournal(pPager, 0); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - - rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); - if( rc!=SQLITE_OK ){ - assert( rc!=SQLITE_IOERR_BLOCKED ); - goto commit_phase_one_exit; - } - sqlite3PcacheCleanAll(pPager->pPCache); - - /* If the file on disk is smaller than the database image, use - ** pager_truncate to grow the file here. This can happen if the database - ** image was extended as part of the current transaction and then the - ** last page in the db image moved to the free-list. In this case the - ** last page is never written out to disk, leaving the database file - ** undersized. Fix this now if it is the case. */ - if( pPager->dbSize>pPager->dbFileSize ){ - Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); - assert( pPager->eState==PAGER_WRITER_DBMOD ); - rc = pager_truncate(pPager, nNew); - if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - } - - /* Finally, sync the database file. */ - if( !noSync ){ - rc = sqlite3PagerSync(pPager); - } - IOTRACE(("DBSYNC %p\n", pPager)) - } - } - -commit_phase_one_exit: - if( rc==SQLITE_OK && !pagerUseWal(pPager) ){ - pPager->eState = PAGER_WRITER_FINISHED; - } - return rc; -} - - -/* -** When this function is called, the database file has been completely -** updated to reflect the changes made by the current transaction and -** synced to disk. The journal file still exists in the file-system -** though, and if a failure occurs at this point it will eventually -** be used as a hot-journal and the current transaction rolled back. -** -** This function finalizes the journal file, either by deleting, -** truncating or partially zeroing it, so that it cannot be used -** for hot-journal rollback. Once this is done the transaction is -** irrevocably committed. -** -** If an error occurs, an IO error code is returned and the pager -** moves into the error state. Otherwise, SQLITE_OK is returned. -*/ -SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - - /* This routine should not be called if a prior error has occurred. - ** But if (due to a coding error elsewhere in the system) it does get - ** called, just return the same error code without doing anything. */ - if( NEVER(pPager->errCode) ) return pPager->errCode; - - assert( pPager->eState==PAGER_WRITER_LOCKED - || pPager->eState==PAGER_WRITER_FINISHED - || (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD) - ); - assert( assert_pager_state(pPager) ); - - /* An optimization. If the database was not actually modified during - ** this transaction, the pager is running in exclusive-mode and is - ** using persistent journals, then this function is a no-op. - ** - ** The start of the journal file currently contains a single journal - ** header with the nRec field set to 0. If such a journal is used as - ** a hot-journal during hot-journal rollback, 0 changes will be made - ** to the database file. So there is no need to zero the journal - ** header. Since the pager is in exclusive mode, there is no need - ** to drop any locks either. - */ - if( pPager->eState==PAGER_WRITER_LOCKED - && pPager->exclusiveMode - && pPager->journalMode==PAGER_JOURNALMODE_PERSIST - ){ - assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); - pPager->eState = PAGER_READER; - return SQLITE_OK; - } - - PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); - rc = pager_end_transaction(pPager, pPager->setMaster, 1); - return pager_error(pPager, rc); -} - -/* -** If a write transaction is open, then all changes made within the -** transaction are reverted and the current write-transaction is closed. -** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR -** state if an error occurs. -** -** If the pager is already in PAGER_ERROR state when this function is called, -** it returns Pager.errCode immediately. No work is performed in this case. -** -** Otherwise, in rollback mode, this function performs two functions: -** -** 1) It rolls back the journal file, restoring all database file and -** in-memory cache pages to the state they were in when the transaction -** was opened, and -** -** 2) It finalizes the journal file, so that it is not used for hot -** rollback at any point in the future. -** -** Finalization of the journal file (task 2) is only performed if the -** rollback is successful. -** -** In WAL mode, all cache-entries containing data modified within the -** current transaction are either expelled from the cache or reverted to -** their pre-transaction state by re-reading data from the database or -** WAL files. The WAL transaction is then closed. -*/ -SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ - int rc = SQLITE_OK; /* Return code */ - PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager))); - - /* PagerRollback() is a no-op if called in READER or OPEN state. If - ** the pager is already in the ERROR state, the rollback is not - ** attempted here. Instead, the error code is returned to the caller. - */ - assert( assert_pager_state(pPager) ); - if( pPager->eState==PAGER_ERROR ) return pPager->errCode; - if( pPager->eState<=PAGER_READER ) return SQLITE_OK; - - if( pagerUseWal(pPager) ){ - int rc2; - rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); - rc2 = pager_end_transaction(pPager, pPager->setMaster, 0); - if( rc==SQLITE_OK ) rc = rc2; - }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ - int eState = pPager->eState; - rc = pager_end_transaction(pPager, 0, 0); - if( !MEMDB && eState>PAGER_WRITER_LOCKED ){ - /* This can happen using journal_mode=off. Move the pager to the error - ** state to indicate that the contents of the cache may not be trusted. - ** Any active readers will get SQLITE_ABORT. - */ - pPager->errCode = SQLITE_ABORT; - pPager->eState = PAGER_ERROR; - return rc; - } - }else{ - rc = pager_playback(pPager, 0); - } - - assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); - assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT - || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR ); - - /* If an error occurs during a ROLLBACK, we can no longer trust the pager - ** cache. So call pager_error() on the way out to make any error persistent. - */ - return pager_error(pPager, rc); -} - -/* -** Return TRUE if the database file is opened read-only. Return FALSE -** if the database is (in theory) writable. -*/ -SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){ - return pPager->readOnly; -} - -/* -** Return the number of references to the pager. -*/ -SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){ - return sqlite3PcacheRefCount(pPager->pPCache); -} - -/* -** Return the approximate number of bytes of memory currently -** used by the pager and its associated cache. -*/ -SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager *pPager){ - int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr) - + 5*sizeof(void*); - return perPageSize*sqlite3PcachePagecount(pPager->pPCache) - + sqlite3MallocSize(pPager) - + pPager->pageSize; -} - -/* -** Return the number of references to the specified page. -*/ -SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){ - return sqlite3PcachePageRefcount(pPage); -} - -#ifdef SQLITE_TEST -/* -** This routine is used for testing and analysis only. -*/ -SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ - static int a[11]; - a[0] = sqlite3PcacheRefCount(pPager->pPCache); - a[1] = sqlite3PcachePagecount(pPager->pPCache); - a[2] = sqlite3PcacheGetCachesize(pPager->pPCache); - a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; - a[4] = pPager->eState; - a[5] = pPager->errCode; - a[6] = pPager->aStat[PAGER_STAT_HIT]; - a[7] = pPager->aStat[PAGER_STAT_MISS]; - a[8] = 0; /* Used to be pPager->nOvfl */ - a[9] = pPager->nRead; - a[10] = pPager->aStat[PAGER_STAT_WRITE]; - return a; -} -#endif - -/* -** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or -** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the -** current cache hit or miss count, according to the value of eStat. If the -** reset parameter is non-zero, the cache hit or miss count is zeroed before -** returning. -*/ -SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){ - - assert( eStat==SQLITE_DBSTATUS_CACHE_HIT - || eStat==SQLITE_DBSTATUS_CACHE_MISS - || eStat==SQLITE_DBSTATUS_CACHE_WRITE - ); - - assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); - assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); - assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 ); - - *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT]; - if( reset ){ - pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0; - } -} - -/* -** Return true if this is an in-memory pager. -*/ -SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){ - return MEMDB; -} - -/* -** Check that there are at least nSavepoint savepoints open. If there are -** currently less than nSavepoints open, then open one or more savepoints -** to make up the difference. If the number of savepoints is already -** equal to nSavepoint, then this function is a no-op. -** -** If a memory allocation fails, SQLITE_NOMEM is returned. If an error -** occurs while opening the sub-journal file, then an IO error code is -** returned. Otherwise, SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ - int rc = SQLITE_OK; /* Return code */ - int nCurrent = pPager->nSavepoint; /* Current number of savepoints */ - - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - assert( assert_pager_state(pPager) ); - - if( nSavepoint>nCurrent && pPager->useJournal ){ - int ii; /* Iterator variable */ - PagerSavepoint *aNew; /* New Pager.aSavepoint array */ - - /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM - ** if the allocation fails. Otherwise, zero the new portion in case a - ** malloc failure occurs while populating it in the for(...) loop below. - */ - aNew = (PagerSavepoint *)sqlite3Realloc( - pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint - ); - if( !aNew ){ - return SQLITE_NOMEM; - } - memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); - pPager->aSavepoint = aNew; - - /* Populate the PagerSavepoint structures just allocated. */ - for(ii=nCurrent; iidbSize; - if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ - aNew[ii].iOffset = pPager->journalOff; - }else{ - aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); - } - aNew[ii].iSubRec = pPager->nSubRec; - aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); - if( !aNew[ii].pInSavepoint ){ - return SQLITE_NOMEM; - } - if( pagerUseWal(pPager) ){ - sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); - } - pPager->nSavepoint = ii+1; - } - assert( pPager->nSavepoint==nSavepoint ); - assertTruncateConstraint(pPager); - } - - return rc; -} - -/* -** This function is called to rollback or release (commit) a savepoint. -** The savepoint to release or rollback need not be the most recently -** created savepoint. -** -** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE. -** If it is SAVEPOINT_RELEASE, then release and destroy the savepoint with -** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes -** that have occurred since the specified savepoint was created. -** -** The savepoint to rollback or release is identified by parameter -** iSavepoint. A value of 0 means to operate on the outermost savepoint -** (the first created). A value of (Pager.nSavepoint-1) means operate -** on the most recently created savepoint. If iSavepoint is greater than -** (Pager.nSavepoint-1), then this function is a no-op. -** -** If a negative value is passed to this function, then the current -** transaction is rolled back. This is different to calling -** sqlite3PagerRollback() because this function does not terminate -** the transaction or unlock the database, it just restores the -** contents of the database to its original state. -** -** In any case, all savepoints with an index greater than iSavepoint -** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE), -** then savepoint iSavepoint is also destroyed. -** -** This function may return SQLITE_NOMEM if a memory allocation fails, -** or an IO error code if an IO error occurs while rolling back a -** savepoint. If no errors occur, SQLITE_OK is returned. -*/ -SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ - int rc = pPager->errCode; /* Return code */ - - assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); - assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK ); - - if( rc==SQLITE_OK && iSavepointnSavepoint ){ - int ii; /* Iterator variable */ - int nNew; /* Number of remaining savepoints after this op. */ - - /* Figure out how many savepoints will still be active after this - ** operation. Store this value in nNew. Then free resources associated - ** with any savepoints that are destroyed by this operation. - */ - nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1); - for(ii=nNew; iinSavepoint; ii++){ - sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); - } - pPager->nSavepoint = nNew; - - /* If this is a release of the outermost savepoint, truncate - ** the sub-journal to zero bytes in size. */ - if( op==SAVEPOINT_RELEASE ){ - if( nNew==0 && isOpen(pPager->sjfd) ){ - /* Only truncate if it is an in-memory sub-journal. */ - if( sqlite3IsMemJournal(pPager->sjfd) ){ - rc = sqlite3OsTruncate(pPager->sjfd, 0); - assert( rc==SQLITE_OK ); - } - pPager->nSubRec = 0; - } - } - /* Else this is a rollback operation, playback the specified savepoint. - ** If this is a temp-file, it is possible that the journal file has - ** not yet been opened. In this case there have been no changes to - ** the database file, so the playback operation can be skipped. - */ - else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){ - PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; - rc = pagerPlaybackSavepoint(pPager, pSavepoint); - assert(rc!=SQLITE_DONE); - } - } - - return rc; -} - -/* -** Return the full pathname of the database file. -** -** Except, if the pager is in-memory only, then return an empty string if -** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when -** used to report the filename to the user, for compatibility with legacy -** behavior. But when the Btree needs to know the filename for matching to -** shared cache, it uses nullIfMemDb==0 so that in-memory databases can -** participate in shared-cache. -*/ -SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){ - return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename; -} - -/* -** Return the VFS structure for the pager. -*/ -SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ - return pPager->pVfs; -} - -/* -** Return the file handle for the database file associated -** with the pager. This might return NULL if the file has -** not yet been opened. -*/ -SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){ - return pPager->fd; -} - -/* -** Return the full pathname of the journal file. -*/ -SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){ - return pPager->zJournal; -} - -/* -** Return true if fsync() calls are disabled for this pager. Return FALSE -** if fsync()s are executed normally. -*/ -SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){ - return pPager->noSync; -} - -#ifdef SQLITE_HAS_CODEC -/* -** Set or retrieve the codec for this pager -*/ -SQLITE_PRIVATE void sqlite3PagerSetCodec( - Pager *pPager, - void *(*xCodec)(void*,void*,Pgno,int), - void (*xCodecSizeChng)(void*,int,int), - void (*xCodecFree)(void*), - void *pCodec -){ - if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); - pPager->xCodec = pPager->memDb ? 0 : xCodec; - pPager->xCodecSizeChng = xCodecSizeChng; - pPager->xCodecFree = xCodecFree; - pPager->pCodec = pCodec; - pagerReportSize(pPager); -} -SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){ - return pPager->pCodec; -} -#endif - -#ifndef SQLITE_OMIT_AUTOVACUUM -/* -** Move the page pPg to location pgno in the file. -** -** There must be no references to the page previously located at -** pgno (which we call pPgOld) though that page is allowed to be -** in cache. If the page previously located at pgno is not already -** in the rollback journal, it is not put there by by this routine. -** -** References to the page pPg remain valid. Updating any -** meta-data associated with pPg (i.e. data stored in the nExtra bytes -** allocated along with the page) is the responsibility of the caller. -** -** A transaction must be active when this routine is called. It used to be -** required that a statement transaction was not active, but this restriction -** has been removed (CREATE INDEX needs to move a page when a statement -** transaction is active). -** -** If the fourth argument, isCommit, is non-zero, then this page is being -** moved as part of a database reorganization just before the transaction -** is being committed. In this case, it is guaranteed that the database page -** pPg refers to will not be written to again within this transaction. -** -** This function may return SQLITE_NOMEM or an IO error code if an error -** occurs. Otherwise, it returns SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ - PgHdr *pPgOld; /* The page being overwritten. */ - Pgno needSyncPgno = 0; /* Old value of pPg->pgno, if sync is required */ - int rc; /* Return code */ - Pgno origPgno; /* The original page number */ - - assert( pPg->nRef>0 ); - assert( pPager->eState==PAGER_WRITER_CACHEMOD - || pPager->eState==PAGER_WRITER_DBMOD - ); - assert( assert_pager_state(pPager) ); - - /* In order to be able to rollback, an in-memory database must journal - ** the page we are moving from. - */ - if( MEMDB ){ - rc = sqlite3PagerWrite(pPg); - if( rc ) return rc; - } - - /* If the page being moved is dirty and has not been saved by the latest - ** savepoint, then save the current contents of the page into the - ** sub-journal now. This is required to handle the following scenario: - ** - ** BEGIN; - ** - ** SAVEPOINT one; - ** - ** ROLLBACK TO one; - ** - ** If page X were not written to the sub-journal here, it would not - ** be possible to restore its contents when the "ROLLBACK TO one" - ** statement were is processed. - ** - ** subjournalPage() may need to allocate space to store pPg->pgno into - ** one or more savepoint bitvecs. This is the reason this function - ** may return SQLITE_NOMEM. - */ - if( pPg->flags&PGHDR_DIRTY - && subjRequiresPage(pPg) - && SQLITE_OK!=(rc = subjournalPage(pPg)) - ){ - return rc; - } - - PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n", - PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno)); - IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) - - /* If the journal needs to be sync()ed before page pPg->pgno can - ** be written to, store pPg->pgno in local variable needSyncPgno. - ** - ** If the isCommit flag is set, there is no need to remember that - ** the journal needs to be sync()ed before database page pPg->pgno - ** can be written to. The caller has already promised not to write to it. - */ - if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ - needSyncPgno = pPg->pgno; - assert( pPager->journalMode==PAGER_JOURNALMODE_OFF || - pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize ); - assert( pPg->flags&PGHDR_DIRTY ); - } - - /* If the cache contains a page with page-number pgno, remove it - ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for - ** page pgno before the 'move' operation, it needs to be retained - ** for the page moved there. - */ - pPg->flags &= ~PGHDR_NEED_SYNC; - pPgOld = pager_lookup(pPager, pgno); - assert( !pPgOld || pPgOld->nRef==1 ); - if( pPgOld ){ - pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); - if( MEMDB ){ - /* Do not discard pages from an in-memory database since we might - ** need to rollback later. Just move the page out of the way. */ - sqlite3PcacheMove(pPgOld, pPager->dbSize+1); - }else{ - sqlite3PcacheDrop(pPgOld); - } - } - - origPgno = pPg->pgno; - sqlite3PcacheMove(pPg, pgno); - sqlite3PcacheMakeDirty(pPg); - - /* For an in-memory database, make sure the original page continues - ** to exist, in case the transaction needs to roll back. Use pPgOld - ** as the original page since it has already been allocated. - */ - if( MEMDB ){ - assert( pPgOld ); - sqlite3PcacheMove(pPgOld, origPgno); - sqlite3PagerUnref(pPgOld); - } - - if( needSyncPgno ){ - /* If needSyncPgno is non-zero, then the journal file needs to be - ** sync()ed before any data is written to database file page needSyncPgno. - ** Currently, no such page exists in the page-cache and the - ** "is journaled" bitvec flag has been set. This needs to be remedied by - ** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC - ** flag. - ** - ** If the attempt to load the page into the page-cache fails, (due - ** to a malloc() or IO failure), clear the bit in the pInJournal[] - ** array. Otherwise, if the page is loaded and written again in - ** this transaction, it may be written to the database file before - ** it is synced into the journal file. This way, it may end up in - ** the journal file twice, but that is not a problem. - */ - PgHdr *pPgHdr; - rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); - if( rc!=SQLITE_OK ){ - if( needSyncPgno<=pPager->dbOrigSize ){ - assert( pPager->pTmpSpace!=0 ); - sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace); - } - return rc; - } - pPgHdr->flags |= PGHDR_NEED_SYNC; - sqlite3PcacheMakeDirty(pPgHdr); - sqlite3PagerUnref(pPgHdr); - } - - return SQLITE_OK; -} -#endif - -/* -** Return a pointer to the data for the specified page. -*/ -SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){ - assert( pPg->nRef>0 || pPg->pPager->memDb ); - return pPg->pData; -} - -/* -** Return a pointer to the Pager.nExtra bytes of "extra" space -** allocated along with the specified page. -*/ -SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){ - return pPg->pExtra; -} - -/* -** Get/set the locking-mode for this pager. Parameter eMode must be one -** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or -** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then -** the locking-mode is set to the value specified. -** -** The returned value is either PAGER_LOCKINGMODE_NORMAL or -** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) -** locking-mode. -*/ -SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){ - assert( eMode==PAGER_LOCKINGMODE_QUERY - || eMode==PAGER_LOCKINGMODE_NORMAL - || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); - assert( PAGER_LOCKINGMODE_QUERY<0 ); - assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 ); - assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) ); - if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){ - pPager->exclusiveMode = (u8)eMode; - } - return (int)pPager->exclusiveMode; -} - -/* -** Set the journal-mode for this pager. Parameter eMode must be one of: -** -** PAGER_JOURNALMODE_DELETE -** PAGER_JOURNALMODE_TRUNCATE -** PAGER_JOURNALMODE_PERSIST -** PAGER_JOURNALMODE_OFF -** PAGER_JOURNALMODE_MEMORY -** PAGER_JOURNALMODE_WAL -** -** The journalmode is set to the value specified if the change is allowed. -** The change may be disallowed for the following reasons: -** -** * An in-memory database can only have its journal_mode set to _OFF -** or _MEMORY. -** -** * Temporary databases cannot have _WAL journalmode. -** -** The returned indicate the current (possibly updated) journal-mode. -*/ -SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ - u8 eOld = pPager->journalMode; /* Prior journalmode */ - -#ifdef SQLITE_DEBUG - /* The print_pager_state() routine is intended to be used by the debugger - ** only. We invoke it once here to suppress a compiler warning. */ - print_pager_state(pPager); -#endif - - - /* The eMode parameter is always valid */ - assert( eMode==PAGER_JOURNALMODE_DELETE - || eMode==PAGER_JOURNALMODE_TRUNCATE - || eMode==PAGER_JOURNALMODE_PERSIST - || eMode==PAGER_JOURNALMODE_OFF - || eMode==PAGER_JOURNALMODE_WAL - || eMode==PAGER_JOURNALMODE_MEMORY ); - - /* This routine is only called from the OP_JournalMode opcode, and - ** the logic there will never allow a temporary file to be changed - ** to WAL mode. - */ - assert( pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL ); - - /* Do allow the journalmode of an in-memory database to be set to - ** anything other than MEMORY or OFF - */ - if( MEMDB ){ - assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF ); - if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){ - eMode = eOld; - } - } - - if( eMode!=eOld ){ - - /* Change the journal mode. */ - assert( pPager->eState!=PAGER_ERROR ); - pPager->journalMode = (u8)eMode; - - /* When transistioning from TRUNCATE or PERSIST to any other journal - ** mode except WAL, unless the pager is in locking_mode=exclusive mode, - ** delete the journal file. - */ - assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); - assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); - assert( (PAGER_JOURNALMODE_DELETE & 5)==0 ); - assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 ); - assert( (PAGER_JOURNALMODE_OFF & 5)==0 ); - assert( (PAGER_JOURNALMODE_WAL & 5)==5 ); - - assert( isOpen(pPager->fd) || pPager->exclusiveMode ); - if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){ - - /* In this case we would like to delete the journal file. If it is - ** not possible, then that is not a problem. Deleting the journal file - ** here is an optimization only. - ** - ** Before deleting the journal file, obtain a RESERVED lock on the - ** database file. This ensures that the journal file is not deleted - ** while it is in use by some other client. - */ - sqlite3OsClose(pPager->jfd); - if( pPager->eLock>=RESERVED_LOCK ){ - sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); - }else{ - int rc = SQLITE_OK; - int state = pPager->eState; - assert( state==PAGER_OPEN || state==PAGER_READER ); - if( state==PAGER_OPEN ){ - rc = sqlite3PagerSharedLock(pPager); - } - if( pPager->eState==PAGER_READER ){ - assert( rc==SQLITE_OK ); - rc = pagerLockDb(pPager, RESERVED_LOCK); - } - if( rc==SQLITE_OK ){ - sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); - } - if( rc==SQLITE_OK && state==PAGER_READER ){ - pagerUnlockDb(pPager, SHARED_LOCK); - }else if( state==PAGER_OPEN ){ - pager_unlock(pPager); - } - assert( state==pPager->eState ); - } - } - } - - /* Return the new journal mode */ - return (int)pPager->journalMode; -} - -/* -** Return the current journal mode. -*/ -SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){ - return (int)pPager->journalMode; -} - -/* -** Return TRUE if the pager is in a state where it is OK to change the -** journalmode. Journalmode changes can only happen when the database -** is unmodified. -*/ -SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ - assert( assert_pager_state(pPager) ); - if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; - if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; - return 1; -} - -/* -** Get/set the size-limit used for persistent journal files. -** -** Setting the size limit to -1 means no limit is enforced. -** An attempt to set a limit smaller than -1 is a no-op. -*/ -SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ - if( iLimit>=-1 ){ - pPager->journalSizeLimit = iLimit; - sqlite3WalLimit(pPager->pWal, iLimit); - } - return pPager->journalSizeLimit; -} - -/* -** Return a pointer to the pPager->pBackup variable. The backup module -** in backup.c maintains the content of this variable. This module -** uses it opaquely as an argument to sqlite3BackupRestart() and -** sqlite3BackupUpdate() only. -*/ -SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){ - return &pPager->pBackup; -} - -#ifndef SQLITE_OMIT_VACUUM -/* -** Unless this is an in-memory or temporary database, clear the pager cache. -*/ -SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){ - if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager); -} -#endif - -#ifndef SQLITE_OMIT_WAL -/* -** This function is called when the user invokes "PRAGMA wal_checkpoint", -** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() -** or wal_blocking_checkpoint() API functions. -** -** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. -*/ -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ - int rc = SQLITE_OK; - if( pPager->pWal ){ - rc = sqlite3WalCheckpoint(pPager->pWal, eMode, - pPager->xBusyHandler, pPager->pBusyHandlerArg, - pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, - pnLog, pnCkpt - ); - } - return rc; -} - -SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager){ - return sqlite3WalCallback(pPager->pWal); -} - -/* -** Return true if the underlying VFS for the given pager supports the -** primitives necessary for write-ahead logging. -*/ -SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ - const sqlite3_io_methods *pMethods = pPager->fd->pMethods; - return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap); -} - -/* -** Attempt to take an exclusive lock on the database file. If a PENDING lock -** is obtained instead, immediately release it. -*/ -static int pagerExclusiveLock(Pager *pPager){ - int rc; /* Return code */ - - assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); - rc = pagerLockDb(pPager, EXCLUSIVE_LOCK); - if( rc!=SQLITE_OK ){ - /* If the attempt to grab the exclusive lock failed, release the - ** pending lock that may have been obtained instead. */ - pagerUnlockDb(pPager, SHARED_LOCK); - } - - return rc; -} - -/* -** Call sqlite3WalOpen() to open the WAL handle. If the pager is in -** exclusive-locking mode when this function is called, take an EXCLUSIVE -** lock on the database file and use heap-memory to store the wal-index -** in. Otherwise, use the normal shared-memory. -*/ -static int pagerOpenWal(Pager *pPager){ - int rc = SQLITE_OK; - - assert( pPager->pWal==0 && pPager->tempFile==0 ); - assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); - - /* If the pager is already in exclusive-mode, the WAL module will use - ** heap-memory for the wal-index instead of the VFS shared-memory - ** implementation. Take the exclusive lock now, before opening the WAL - ** file, to make sure this is safe. - */ - if( pPager->exclusiveMode ){ - rc = pagerExclusiveLock(pPager); - } - - /* Open the connection to the log file. If this operation fails, - ** (e.g. due to malloc() failure), return an error code. - */ - if( rc==SQLITE_OK ){ - rc = sqlite3WalOpen(pPager->pVfs, - pPager->fd, pPager->zWal, pPager->exclusiveMode, - pPager->journalSizeLimit, &pPager->pWal - ); - } - pagerFixMaplimit(pPager); - - return rc; -} - - -/* -** The caller must be holding a SHARED lock on the database file to call -** this function. -** -** If the pager passed as the first argument is open on a real database -** file (not a temp file or an in-memory database), and the WAL file -** is not already open, make an attempt to open it now. If successful, -** return SQLITE_OK. If an error occurs or the VFS used by the pager does -** not support the xShmXXX() methods, return an error code. *pbOpen is -** not modified in either case. -** -** If the pager is open on a temp-file (or in-memory database), or if -** the WAL file is already open, set *pbOpen to 1 and return SQLITE_OK -** without doing anything. -*/ -SQLITE_PRIVATE int sqlite3PagerOpenWal( - Pager *pPager, /* Pager object */ - int *pbOpen /* OUT: Set to true if call is a no-op */ -){ - int rc = SQLITE_OK; /* Return code */ - - assert( assert_pager_state(pPager) ); - assert( pPager->eState==PAGER_OPEN || pbOpen ); - assert( pPager->eState==PAGER_READER || !pbOpen ); - assert( pbOpen==0 || *pbOpen==0 ); - assert( pbOpen!=0 || (!pPager->tempFile && !pPager->pWal) ); - - if( !pPager->tempFile && !pPager->pWal ){ - if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; - - /* Close any rollback journal previously open */ - sqlite3OsClose(pPager->jfd); - - rc = pagerOpenWal(pPager); - if( rc==SQLITE_OK ){ - pPager->journalMode = PAGER_JOURNALMODE_WAL; - pPager->eState = PAGER_OPEN; - } - }else{ - *pbOpen = 1; - } - - return rc; -} - -/* -** This function is called to close the connection to the log file prior -** to switching from WAL to rollback mode. -** -** Before closing the log file, this function attempts to take an -** EXCLUSIVE lock on the database file. If this cannot be obtained, an -** error (SQLITE_BUSY) is returned and the log connection is not closed. -** If successful, the EXCLUSIVE lock is not released before returning. -*/ -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ - int rc = SQLITE_OK; - - assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); - - /* If the log file is not already open, but does exist in the file-system, - ** it may need to be checkpointed before the connection can switch to - ** rollback mode. Open it now so this can happen. - */ - if( !pPager->pWal ){ - int logexists = 0; - rc = pagerLockDb(pPager, SHARED_LOCK); - if( rc==SQLITE_OK ){ - rc = sqlite3OsAccess( - pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists - ); - } - if( rc==SQLITE_OK && logexists ){ - rc = pagerOpenWal(pPager); - } - } - - /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on - ** the database file, the log and log-summary files will be deleted. - */ - if( rc==SQLITE_OK && pPager->pWal ){ - rc = pagerExclusiveLock(pPager); - if( rc==SQLITE_OK ){ - rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, - pPager->pageSize, (u8*)pPager->pTmpSpace); - pPager->pWal = 0; - pagerFixMaplimit(pPager); - } - } - return rc; -} - -#endif /* !SQLITE_OMIT_WAL */ - -#ifdef SQLITE_ENABLE_ZIPVFS -/* -** A read-lock must be held on the pager when this function is called. If -** the pager is in WAL mode and the WAL file currently contains one or more -** frames, return the size in bytes of the page images stored within the -** WAL frames. Otherwise, if this is not a WAL database or the WAL file -** is empty, return 0. -*/ -SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ - assert( pPager->eState==PAGER_READER ); - return sqlite3WalFramesize(pPager->pWal); -} -#endif - -#ifdef SQLITE_HAS_CODEC -/* -** This function is called by the wal module when writing page content -** into the log file. -** -** This function returns a pointer to a buffer containing the encrypted -** page content. If a malloc fails, this function may return NULL. -*/ -SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){ - void *aData = 0; - CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData); - return aData; -} -#endif /* SQLITE_HAS_CODEC */ - -#endif /* SQLITE_OMIT_DISKIO */ - -/************** End of pager.c ***********************************************/ -/************** Begin file wal.c *********************************************/ -/* -** 2010 February 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains the implementation of a write-ahead log (WAL) used in -** "journal_mode=WAL" mode. -** -** WRITE-AHEAD LOG (WAL) FILE FORMAT -** -** A WAL file consists of a header followed by zero or more "frames". -** Each frame records the revised content of a single page from the -** database file. All changes to the database are recorded by writing -** frames into the WAL. Transactions commit when a frame is written that -** contains a commit marker. A single WAL can and usually does record -** multiple transactions. Periodically, the content of the WAL is -** transferred back into the database file in an operation called a -** "checkpoint". -** -** A single WAL file can be used multiple times. In other words, the -** WAL can fill up with frames and then be checkpointed and then new -** frames can overwrite the old ones. A WAL always grows from beginning -** toward the end. Checksums and counters attached to each frame are -** used to determine which frames within the WAL are valid and which -** are leftovers from prior checkpoints. -** -** The WAL header is 32 bytes in size and consists of the following eight -** big-endian 32-bit unsigned integer values: -** -** 0: Magic number. 0x377f0682 or 0x377f0683 -** 4: File format version. Currently 3007000 -** 8: Database page size. Example: 1024 -** 12: Checkpoint sequence number -** 16: Salt-1, random integer incremented with each checkpoint -** 20: Salt-2, a different random integer changing with each ckpt -** 24: Checksum-1 (first part of checksum for first 24 bytes of header). -** 28: Checksum-2 (second part of checksum for first 24 bytes of header). -** -** Immediately following the wal-header are zero or more frames. Each -** frame consists of a 24-byte frame-header followed by a bytes -** of page data. The frame-header is six big-endian 32-bit unsigned -** integer values, as follows: -** -** 0: Page number. -** 4: For commit records, the size of the database image in pages -** after the commit. For all other records, zero. -** 8: Salt-1 (copied from the header) -** 12: Salt-2 (copied from the header) -** 16: Checksum-1. -** 20: Checksum-2. -** -** A frame is considered valid if and only if the following conditions are -** true: -** -** (1) The salt-1 and salt-2 values in the frame-header match -** salt values in the wal-header -** -** (2) The checksum values in the final 8 bytes of the frame-header -** exactly match the checksum computed consecutively on the -** WAL header and the first 8 bytes and the content of all frames -** up to and including the current frame. -** -** The checksum is computed using 32-bit big-endian integers if the -** magic number in the first 4 bytes of the WAL is 0x377f0683 and it -** is computed using little-endian if the magic number is 0x377f0682. -** The checksum values are always stored in the frame header in a -** big-endian format regardless of which byte order is used to compute -** the checksum. The checksum is computed by interpreting the input as -** an even number of unsigned 32-bit integers: x[0] through x[N]. The -** algorithm used for the checksum is as follows: -** -** for i from 0 to n-1 step 2: -** s0 += x[i] + s1; -** s1 += x[i+1] + s0; -** endfor -** -** Note that s0 and s1 are both weighted checksums using fibonacci weights -** in reverse order (the largest fibonacci weight occurs on the first element -** of the sequence being summed.) The s1 value spans all 32-bit -** terms of the sequence whereas s0 omits the final term. -** -** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the -** WAL is transferred into the database, then the database is VFS.xSync-ed. -** The VFS.xSync operations serve as write barriers - all writes launched -** before the xSync must complete before any write that launches after the -** xSync begins. -** -** After each checkpoint, the salt-1 value is incremented and the salt-2 -** value is randomized. This prevents old and new frames in the WAL from -** being considered valid at the same time and being checkpointing together -** following a crash. -** -** READER ALGORITHM -** -** To read a page from the database (call it page number P), a reader -** first checks the WAL to see if it contains page P. If so, then the -** last valid instance of page P that is a followed by a commit frame -** or is a commit frame itself becomes the value read. If the WAL -** contains no copies of page P that are valid and which are a commit -** frame or are followed by a commit frame, then page P is read from -** the database file. -** -** To start a read transaction, the reader records the index of the last -** valid frame in the WAL. The reader uses this recorded "mxFrame" value -** for all subsequent read operations. New transactions can be appended -** to the WAL, but as long as the reader uses its original mxFrame value -** and ignores the newly appended content, it will see a consistent snapshot -** of the database from a single point in time. This technique allows -** multiple concurrent readers to view different versions of the database -** content simultaneously. -** -** The reader algorithm in the previous paragraphs works correctly, but -** because frames for page P can appear anywhere within the WAL, the -** reader has to scan the entire WAL looking for page P frames. If the -** WAL is large (multiple megabytes is typical) that scan can be slow, -** and read performance suffers. To overcome this problem, a separate -** data structure called the wal-index is maintained to expedite the -** search for frames of a particular page. -** -** WAL-INDEX FORMAT -** -** Conceptually, the wal-index is shared memory, though VFS implementations -** might choose to implement the wal-index using a mmapped file. Because -** the wal-index is shared memory, SQLite does not support journal_mode=WAL -** on a network filesystem. All users of the database must be able to -** share memory. -** -** The wal-index is transient. After a crash, the wal-index can (and should -** be) reconstructed from the original WAL file. In fact, the VFS is required -** to either truncate or zero the header of the wal-index when the last -** connection to it closes. Because the wal-index is transient, it can -** use an architecture-specific format; it does not have to be cross-platform. -** Hence, unlike the database and WAL file formats which store all values -** as big endian, the wal-index can store multi-byte values in the native -** byte order of the host computer. -** -** The purpose of the wal-index is to answer this question quickly: Given -** a page number P and a maximum frame index M, return the index of the -** last frame in the wal before frame M for page P in the WAL, or return -** NULL if there are no frames for page P in the WAL prior to M. -** -** The wal-index consists of a header region, followed by an one or -** more index blocks. -** -** The wal-index header contains the total number of frames within the WAL -** in the mxFrame field. -** -** Each index block except for the first contains information on -** HASHTABLE_NPAGE frames. The first index block contains information on -** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and -** HASHTABLE_NPAGE are selected so that together the wal-index header and -** first index block are the same size as all other index blocks in the -** wal-index. -** -** Each index block contains two sections, a page-mapping that contains the -** database page number associated with each wal frame, and a hash-table -** that allows readers to query an index block for a specific page number. -** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE -** for the first index block) 32-bit page numbers. The first entry in the -** first index-block contains the database page number corresponding to the -** first frame in the WAL file. The first entry in the second index block -** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in -** the log, and so on. -** -** The last index block in a wal-index usually contains less than the full -** complement of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE) page-numbers, -** depending on the contents of the WAL file. This does not change the -** allocated size of the page-mapping array - the page-mapping array merely -** contains unused entries. -** -** Even without using the hash table, the last frame for page P -** can be found by scanning the page-mapping sections of each index block -** starting with the last index block and moving toward the first, and -** within each index block, starting at the end and moving toward the -** beginning. The first entry that equals P corresponds to the frame -** holding the content for that page. -** -** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers. -** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the -** hash table for each page number in the mapping section, so the hash -** table is never more than half full. The expected number of collisions -** prior to finding a match is 1. Each entry of the hash table is an -** 1-based index of an entry in the mapping section of the same -** index block. Let K be the 1-based index of the largest entry in -** the mapping section. (For index blocks other than the last, K will -** always be exactly HASHTABLE_NPAGE (4096) and for the last index block -** K will be (mxFrame%HASHTABLE_NPAGE).) Unused slots of the hash table -** contain a value of 0. -** -** To look for page P in the hash table, first compute a hash iKey on -** P as follows: -** -** iKey = (P * 383) % HASHTABLE_NSLOT -** -** Then start scanning entries of the hash table, starting with iKey -** (wrapping around to the beginning when the end of the hash table is -** reached) until an unused hash slot is found. Let the first unused slot -** be at index iUnused. (iUnused might be less than iKey if there was -** wrap-around.) Because the hash table is never more than half full, -** the search is guaranteed to eventually hit an unused entry. Let -** iMax be the value between iKey and iUnused, closest to iUnused, -** where aHash[iMax]==P. If there is no iMax entry (if there exists -** no hash slot such that aHash[i]==p) then page P is not in the -** current index block. Otherwise the iMax-th mapping entry of the -** current index block corresponds to the last entry that references -** page P. -** -** A hash search begins with the last index block and moves toward the -** first index block, looking for entries corresponding to page P. On -** average, only two or three slots in each index block need to be -** examined in order to either find the last entry for page P, or to -** establish that no such entry exists in the block. Each index block -** holds over 4000 entries. So two or three index blocks are sufficient -** to cover a typical 10 megabyte WAL file, assuming 1K pages. 8 or 10 -** comparisons (on average) suffice to either locate a frame in the -** WAL or to establish that the frame does not exist in the WAL. This -** is much faster than scanning the entire 10MB WAL. -** -** Note that entries are added in order of increasing K. Hence, one -** reader might be using some value K0 and a second reader that started -** at a later time (after additional transactions were added to the WAL -** and to the wal-index) might be using a different value K1, where K1>K0. -** Both readers can use the same hash table and mapping section to get -** the correct result. There may be entries in the hash table with -** K>K0 but to the first reader, those entries will appear to be unused -** slots in the hash table and so the first reader will get an answer as -** if no values greater than K0 had ever been inserted into the hash table -** in the first place - which is what reader one wants. Meanwhile, the -** second reader using K1 will see additional values that were inserted -** later, which is exactly what reader two wants. -** -** When a rollback occurs, the value of K is decreased. Hash table entries -** that correspond to frames greater than the new K value are removed -** from the hash table at this point. -*/ -#ifndef SQLITE_OMIT_WAL - - -/* -** Trace output macros -*/ -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) -SQLITE_PRIVATE int sqlite3WalTrace = 0; -# define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X -#else -# define WALTRACE(X) -#endif - -/* -** The maximum (and only) versions of the wal and wal-index formats -** that may be interpreted by this version of SQLite. -** -** If a client begins recovering a WAL file and finds that (a) the checksum -** values in the wal-header are correct and (b) the version field is not -** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN. -** -** Similarly, if a client successfully reads a wal-index header (i.e. the -** checksum test is successful) and finds that the version field is not -** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite -** returns SQLITE_CANTOPEN. -*/ -#define WAL_MAX_VERSION 3007000 -#define WALINDEX_MAX_VERSION 3007000 - -/* -** Indices of various locking bytes. WAL_NREADER is the number -** of available reader locks and should be at least 3. -*/ -#define WAL_WRITE_LOCK 0 -#define WAL_ALL_BUT_WRITE 1 -#define WAL_CKPT_LOCK 1 -#define WAL_RECOVER_LOCK 2 -#define WAL_READ_LOCK(I) (3+(I)) -#define WAL_NREADER (SQLITE_SHM_NLOCK-3) - - -/* Object declarations */ -typedef struct WalIndexHdr WalIndexHdr; -typedef struct WalIterator WalIterator; -typedef struct WalCkptInfo WalCkptInfo; - - -/* -** The following object holds a copy of the wal-index header content. -** -** The actual header in the wal-index consists of two copies of this -** object. -** -** The szPage value can be any power of 2 between 512 and 32768, inclusive. -** Or it can be 1 to represent a 65536-byte page. The latter case was -** added in 3.7.1 when support for 64K pages was added. -*/ -struct WalIndexHdr { - u32 iVersion; /* Wal-index version */ - u32 unused; /* Unused (padding) field */ - u32 iChange; /* Counter incremented each transaction */ - u8 isInit; /* 1 when initialized */ - u8 bigEndCksum; /* True if checksums in WAL are big-endian */ - u16 szPage; /* Database page size in bytes. 1==64K */ - u32 mxFrame; /* Index of last valid frame in the WAL */ - u32 nPage; /* Size of database in pages */ - u32 aFrameCksum[2]; /* Checksum of last frame in log */ - u32 aSalt[2]; /* Two salt values copied from WAL header */ - u32 aCksum[2]; /* Checksum over all prior fields */ -}; - -/* -** A copy of the following object occurs in the wal-index immediately -** following the second copy of the WalIndexHdr. This object stores -** information used by checkpoint. -** -** nBackfill is the number of frames in the WAL that have been written -** back into the database. (We call the act of moving content from WAL to -** database "backfilling".) The nBackfill number is never greater than -** WalIndexHdr.mxFrame. nBackfill can only be increased by threads -** holding the WAL_CKPT_LOCK lock (which includes a recovery thread). -** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from -** mxFrame back to zero when the WAL is reset. -** -** There is one entry in aReadMark[] for each reader lock. If a reader -** holds read-lock K, then the value in aReadMark[K] is no greater than -** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff) -** for any aReadMark[] means that entry is unused. aReadMark[0] is -** a special case; its value is never used and it exists as a place-holder -** to avoid having to offset aReadMark[] indexs by one. Readers holding -** WAL_READ_LOCK(0) always ignore the entire WAL and read all content -** directly from the database. -** -** The value of aReadMark[K] may only be changed by a thread that -** is holding an exclusive lock on WAL_READ_LOCK(K). Thus, the value of -** aReadMark[K] cannot changed while there is a reader is using that mark -** since the reader will be holding a shared lock on WAL_READ_LOCK(K). -** -** The checkpointer may only transfer frames from WAL to database where -** the frame numbers are less than or equal to every aReadMark[] that is -** in use (that is, every aReadMark[j] for which there is a corresponding -** WAL_READ_LOCK(j)). New readers (usually) pick the aReadMark[] with the -** largest value and will increase an unused aReadMark[] to mxFrame if there -** is not already an aReadMark[] equal to mxFrame. The exception to the -** previous sentence is when nBackfill equals mxFrame (meaning that everything -** in the WAL has been backfilled into the database) then new readers -** will choose aReadMark[0] which has value 0 and hence such reader will -** get all their all content directly from the database file and ignore -** the WAL. -** -** Writers normally append new frames to the end of the WAL. However, -** if nBackfill equals mxFrame (meaning that all WAL content has been -** written back into the database) and if no readers are using the WAL -** (in other words, if there are no WAL_READ_LOCK(i) where i>0) then -** the writer will first "reset" the WAL back to the beginning and start -** writing new content beginning at frame 1. -** -** We assume that 32-bit loads are atomic and so no locks are needed in -** order to read from any aReadMark[] entries. -*/ -struct WalCkptInfo { - u32 nBackfill; /* Number of WAL frames backfilled into DB */ - u32 aReadMark[WAL_NREADER]; /* Reader marks */ -}; -#define READMARK_NOT_USED 0xffffffff - - -/* A block of WALINDEX_LOCK_RESERVED bytes beginning at -** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems -** only support mandatory file-locks, we do not read or write data -** from the region of the file on which locks are applied. -*/ -#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo)) -#define WALINDEX_LOCK_RESERVED 16 -#define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED) - -/* Size of header before each frame in wal */ -#define WAL_FRAME_HDRSIZE 24 - -/* Size of write ahead log header, including checksum. */ -/* #define WAL_HDRSIZE 24 */ -#define WAL_HDRSIZE 32 - -/* WAL magic value. Either this value, or the same value with the least -** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit -** big-endian format in the first 4 bytes of a WAL file. -** -** If the LSB is set, then the checksums for each frame within the WAL -** file are calculated by treating all data as an array of 32-bit -** big-endian words. Otherwise, they are calculated by interpreting -** all data as 32-bit little-endian words. -*/ -#define WAL_MAGIC 0x377f0682 - -/* -** Return the offset of frame iFrame in the write-ahead log file, -** assuming a database page size of szPage bytes. The offset returned -** is to the start of the write-ahead log frame-header. -*/ -#define walFrameOffset(iFrame, szPage) ( \ - WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \ -) - -/* -** An open write-ahead log file is represented by an instance of the -** following object. -*/ -struct Wal { - sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */ - sqlite3_file *pDbFd; /* File handle for the database file */ - sqlite3_file *pWalFd; /* File handle for WAL file */ - u32 iCallback; /* Value to pass to log callback (or 0) */ - i64 mxWalSize; /* Truncate WAL to this size upon reset */ - int nWiData; /* Size of array apWiData */ - int szFirstBlock; /* Size of first block written to WAL file */ - volatile u32 **apWiData; /* Pointer to wal-index content in memory */ - u32 szPage; /* Database page size */ - i16 readLock; /* Which read lock is being held. -1 for none */ - u8 syncFlags; /* Flags to use to sync header writes */ - u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */ - u8 writeLock; /* True if in a write transaction */ - u8 ckptLock; /* True if holding a checkpoint lock */ - u8 readOnly; /* WAL_RDWR, WAL_RDONLY, or WAL_SHM_RDONLY */ - u8 truncateOnCommit; /* True to truncate WAL file on commit */ - u8 syncHeader; /* Fsync the WAL header if true */ - u8 padToSectorBoundary; /* Pad transactions out to the next sector */ - WalIndexHdr hdr; /* Wal-index header for current transaction */ - const char *zWalName; /* Name of WAL file */ - u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ -#ifdef SQLITE_DEBUG - u8 lockError; /* True if a locking error has occurred */ -#endif -}; - -/* -** Candidate values for Wal.exclusiveMode. -*/ -#define WAL_NORMAL_MODE 0 -#define WAL_EXCLUSIVE_MODE 1 -#define WAL_HEAPMEMORY_MODE 2 - -/* -** Possible values for WAL.readOnly -*/ -#define WAL_RDWR 0 /* Normal read/write connection */ -#define WAL_RDONLY 1 /* The WAL file is readonly */ -#define WAL_SHM_RDONLY 2 /* The SHM file is readonly */ - -/* -** Each page of the wal-index mapping contains a hash-table made up of -** an array of HASHTABLE_NSLOT elements of the following type. -*/ -typedef u16 ht_slot; - -/* -** This structure is used to implement an iterator that loops through -** all frames in the WAL in database page order. Where two or more frames -** correspond to the same database page, the iterator visits only the -** frame most recently written to the WAL (in other words, the frame with -** the largest index). -** -** The internals of this structure are only accessed by: -** -** walIteratorInit() - Create a new iterator, -** walIteratorNext() - Step an iterator, -** walIteratorFree() - Free an iterator. -** -** This functionality is used by the checkpoint code (see walCheckpoint()). -*/ -struct WalIterator { - int iPrior; /* Last result returned from the iterator */ - int nSegment; /* Number of entries in aSegment[] */ - struct WalSegment { - int iNext; /* Next slot in aIndex[] not yet returned */ - ht_slot *aIndex; /* i0, i1, i2... such that aPgno[iN] ascend */ - u32 *aPgno; /* Array of page numbers. */ - int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */ - int iZero; /* Frame number associated with aPgno[0] */ - } aSegment[1]; /* One for every 32KB page in the wal-index */ -}; - -/* -** Define the parameters of the hash tables in the wal-index file. There -** is a hash-table following every HASHTABLE_NPAGE page numbers in the -** wal-index. -** -** Changing any of these constants will alter the wal-index format and -** create incompatibilities. -*/ -#define HASHTABLE_NPAGE 4096 /* Must be power of 2 */ -#define HASHTABLE_HASH_1 383 /* Should be prime */ -#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */ - -/* -** The block of page numbers associated with the first hash-table in a -** wal-index is smaller than usual. This is so that there is a complete -** hash-table on each aligned 32KB page of the wal-index. -*/ -#define HASHTABLE_NPAGE_ONE (HASHTABLE_NPAGE - (WALINDEX_HDR_SIZE/sizeof(u32))) - -/* The wal-index is divided into pages of WALINDEX_PGSZ bytes each. */ -#define WALINDEX_PGSZ ( \ - sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ -) - -/* -** Obtain a pointer to the iPage'th page of the wal-index. The wal-index -** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are -** numbered from zero. -** -** If this call is successful, *ppPage is set to point to the wal-index -** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs, -** then an SQLite error code is returned and *ppPage is set to 0. -*/ -static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ - int rc = SQLITE_OK; - - /* Enlarge the pWal->apWiData[] array if required */ - if( pWal->nWiData<=iPage ){ - int nByte = sizeof(u32*)*(iPage+1); - volatile u32 **apNew; - apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte); - if( !apNew ){ - *ppPage = 0; - return SQLITE_NOMEM; - } - memset((void*)&apNew[pWal->nWiData], 0, - sizeof(u32*)*(iPage+1-pWal->nWiData)); - pWal->apWiData = apNew; - pWal->nWiData = iPage+1; - } - - /* Request a pointer to the required page from the VFS */ - if( pWal->apWiData[iPage]==0 ){ - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ - pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); - if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM; - }else{ - rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, - pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] - ); - if( rc==SQLITE_READONLY ){ - pWal->readOnly |= WAL_SHM_RDONLY; - rc = SQLITE_OK; - } - } - } - - *ppPage = pWal->apWiData[iPage]; - assert( iPage==0 || *ppPage || rc!=SQLITE_OK ); - return rc; -} - -/* -** Return a pointer to the WalCkptInfo structure in the wal-index. -*/ -static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ - assert( pWal->nWiData>0 && pWal->apWiData[0] ); - return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); -} - -/* -** Return a pointer to the WalIndexHdr structure in the wal-index. -*/ -static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ - assert( pWal->nWiData>0 && pWal->apWiData[0] ); - return (volatile WalIndexHdr*)pWal->apWiData[0]; -} - -/* -** The argument to this macro must be of type u32. On a little-endian -** architecture, it returns the u32 value that results from interpreting -** the 4 bytes as a big-endian value. On a big-endian architecture, it -** returns the value that would be produced by intepreting the 4 bytes -** of the input value as a little-endian integer. -*/ -#define BYTESWAP32(x) ( \ - (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8) \ - + (((x)&0x00FF0000)>>8) + (((x)&0xFF000000)>>24) \ -) - -/* -** Generate or extend an 8 byte checksum based on the data in -** array aByte[] and the initial values of aIn[0] and aIn[1] (or -** initial values of 0 and 0 if aIn==NULL). -** -** The checksum is written back into aOut[] before returning. -** -** nByte must be a positive multiple of 8. -*/ -static void walChecksumBytes( - int nativeCksum, /* True for native byte-order, false for non-native */ - u8 *a, /* Content to be checksummed */ - int nByte, /* Bytes of content in a[]. Must be a multiple of 8. */ - const u32 *aIn, /* Initial checksum value input */ - u32 *aOut /* OUT: Final checksum value output */ -){ - u32 s1, s2; - u32 *aData = (u32 *)a; - u32 *aEnd = (u32 *)&a[nByte]; - - if( aIn ){ - s1 = aIn[0]; - s2 = aIn[1]; - }else{ - s1 = s2 = 0; - } - - assert( nByte>=8 ); - assert( (nByte&0x00000007)==0 ); - - if( nativeCksum ){ - do { - s1 += *aData++ + s2; - s2 += *aData++ + s1; - }while( aDataexclusiveMode!=WAL_HEAPMEMORY_MODE ){ - sqlite3OsShmBarrier(pWal->pDbFd); - } -} - -/* -** Write the header information in pWal->hdr into the wal-index. -** -** The checksum on pWal->hdr is updated before it is written. -*/ -static void walIndexWriteHdr(Wal *pWal){ - volatile WalIndexHdr *aHdr = walIndexHdr(pWal); - const int nCksum = offsetof(WalIndexHdr, aCksum); - - assert( pWal->writeLock ); - pWal->hdr.isInit = 1; - pWal->hdr.iVersion = WALINDEX_MAX_VERSION; - walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); - memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr)); - walShmBarrier(pWal); - memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr)); -} - -/* -** This function encodes a single frame header and writes it to a buffer -** supplied by the caller. A frame-header is made up of a series of -** 4-byte big-endian integers, as follows: -** -** 0: Page number. -** 4: For commit records, the size of the database image in pages -** after the commit. For all other records, zero. -** 8: Salt-1 (copied from the wal-header) -** 12: Salt-2 (copied from the wal-header) -** 16: Checksum-1. -** 20: Checksum-2. -*/ -static void walEncodeFrame( - Wal *pWal, /* The write-ahead log */ - u32 iPage, /* Database page number for frame */ - u32 nTruncate, /* New db size (or 0 for non-commit frames) */ - u8 *aData, /* Pointer to page data */ - u8 *aFrame /* OUT: Write encoded frame here */ -){ - int nativeCksum; /* True for native byte-order checksums */ - u32 *aCksum = pWal->hdr.aFrameCksum; - assert( WAL_FRAME_HDRSIZE==24 ); - sqlite3Put4byte(&aFrame[0], iPage); - sqlite3Put4byte(&aFrame[4], nTruncate); - memcpy(&aFrame[8], pWal->hdr.aSalt, 8); - - nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); - walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); - walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); - - sqlite3Put4byte(&aFrame[16], aCksum[0]); - sqlite3Put4byte(&aFrame[20], aCksum[1]); -} - -/* -** Check to see if the frame with header in aFrame[] and content -** in aData[] is valid. If it is a valid frame, fill *piPage and -** *pnTruncate and return true. Return if the frame is not valid. -*/ -static int walDecodeFrame( - Wal *pWal, /* The write-ahead log */ - u32 *piPage, /* OUT: Database page number for frame */ - u32 *pnTruncate, /* OUT: New db size (or 0 if not commit) */ - u8 *aData, /* Pointer to page data (for checksum) */ - u8 *aFrame /* Frame data */ -){ - int nativeCksum; /* True for native byte-order checksums */ - u32 *aCksum = pWal->hdr.aFrameCksum; - u32 pgno; /* Page number of the frame */ - assert( WAL_FRAME_HDRSIZE==24 ); - - /* A frame is only valid if the salt values in the frame-header - ** match the salt values in the wal-header. - */ - if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){ - return 0; - } - - /* A frame is only valid if the page number is creater than zero. - */ - pgno = sqlite3Get4byte(&aFrame[0]); - if( pgno==0 ){ - return 0; - } - - /* A frame is only valid if a checksum of the WAL header, - ** all prior frams, the first 16 bytes of this frame-header, - ** and the frame-data matches the checksum in the last 8 - ** bytes of this frame-header. - */ - nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); - walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); - walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); - if( aCksum[0]!=sqlite3Get4byte(&aFrame[16]) - || aCksum[1]!=sqlite3Get4byte(&aFrame[20]) - ){ - /* Checksum failed. */ - return 0; - } - - /* If we reach this point, the frame is valid. Return the page number - ** and the new database size. - */ - *piPage = pgno; - *pnTruncate = sqlite3Get4byte(&aFrame[4]); - return 1; -} - - -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) -/* -** Names of locks. This routine is used to provide debugging output and is not -** a part of an ordinary build. -*/ -static const char *walLockName(int lockIdx){ - if( lockIdx==WAL_WRITE_LOCK ){ - return "WRITE-LOCK"; - }else if( lockIdx==WAL_CKPT_LOCK ){ - return "CKPT-LOCK"; - }else if( lockIdx==WAL_RECOVER_LOCK ){ - return "RECOVER-LOCK"; - }else{ - static char zName[15]; - sqlite3_snprintf(sizeof(zName), zName, "READ-LOCK[%d]", - lockIdx-WAL_READ_LOCK(0)); - return zName; - } -} -#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */ - - -/* -** Set or release locks on the WAL. Locks are either shared or exclusive. -** A lock cannot be moved directly between shared and exclusive - it must go -** through the unlocked state first. -** -** In locking_mode=EXCLUSIVE, all of these routines become no-ops. -*/ -static int walLockShared(Wal *pWal, int lockIdx){ - int rc; - if( pWal->exclusiveMode ) return SQLITE_OK; - rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, - SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); - WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, - walLockName(lockIdx), rc ? "failed" : "ok")); - VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) - return rc; -} -static void walUnlockShared(Wal *pWal, int lockIdx){ - if( pWal->exclusiveMode ) return; - (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, - SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); - WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); -} -static int walLockExclusive(Wal *pWal, int lockIdx, int n){ - int rc; - if( pWal->exclusiveMode ) return SQLITE_OK; - rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, - SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); - WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, - walLockName(lockIdx), n, rc ? "failed" : "ok")); - VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) - return rc; -} -static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ - if( pWal->exclusiveMode ) return; - (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, - SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); - WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal, - walLockName(lockIdx), n)); -} - -/* -** Compute a hash on a page number. The resulting hash value must land -** between 0 and (HASHTABLE_NSLOT-1). The walHashNext() function advances -** the hash to the next value in the event of a collision. -*/ -static int walHash(u32 iPage){ - assert( iPage>0 ); - assert( (HASHTABLE_NSLOT & (HASHTABLE_NSLOT-1))==0 ); - return (iPage*HASHTABLE_HASH_1) & (HASHTABLE_NSLOT-1); -} -static int walNextHash(int iPriorHash){ - return (iPriorHash+1)&(HASHTABLE_NSLOT-1); -} - -/* -** Return pointers to the hash table and page number array stored on -** page iHash of the wal-index. The wal-index is broken into 32KB pages -** numbered starting from 0. -** -** Set output variable *paHash to point to the start of the hash table -** in the wal-index file. Set *piZero to one less than the frame -** number of the first frame indexed by this hash table. If a -** slot in the hash table is set to N, it refers to frame number -** (*piZero+N) in the log. -** -** Finally, set *paPgno so that *paPgno[1] is the page number of the -** first frame indexed by the hash table, frame (*piZero+1). -*/ -static int walHashGet( - Wal *pWal, /* WAL handle */ - int iHash, /* Find the iHash'th table */ - volatile ht_slot **paHash, /* OUT: Pointer to hash index */ - volatile u32 **paPgno, /* OUT: Pointer to page number array */ - u32 *piZero /* OUT: Frame associated with *paPgno[0] */ -){ - int rc; /* Return code */ - volatile u32 *aPgno; - - rc = walIndexPage(pWal, iHash, &aPgno); - assert( rc==SQLITE_OK || iHash>0 ); - - if( rc==SQLITE_OK ){ - u32 iZero; - volatile ht_slot *aHash; - - aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE]; - if( iHash==0 ){ - aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; - iZero = 0; - }else{ - iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; - } - - *paPgno = &aPgno[-1]; - *paHash = aHash; - *piZero = iZero; - } - return rc; -} - -/* -** Return the number of the wal-index page that contains the hash-table -** and page-number array that contain entries corresponding to WAL frame -** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages -** are numbered starting from 0. -*/ -static int walFramePage(u32 iFrame){ - int iHash = (iFrame+HASHTABLE_NPAGE-HASHTABLE_NPAGE_ONE-1) / HASHTABLE_NPAGE; - assert( (iHash==0 || iFrame>HASHTABLE_NPAGE_ONE) - && (iHash>=1 || iFrame<=HASHTABLE_NPAGE_ONE) - && (iHash<=1 || iFrame>(HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE)) - && (iHash>=2 || iFrame<=HASHTABLE_NPAGE_ONE+HASHTABLE_NPAGE) - && (iHash<=2 || iFrame>(HASHTABLE_NPAGE_ONE+2*HASHTABLE_NPAGE)) - ); - return iHash; -} - -/* -** Return the page number associated with frame iFrame in this WAL. -*/ -static u32 walFramePgno(Wal *pWal, u32 iFrame){ - int iHash = walFramePage(iFrame); - if( iHash==0 ){ - return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; - } - return pWal->apWiData[iHash][(iFrame-1-HASHTABLE_NPAGE_ONE)%HASHTABLE_NPAGE]; -} - -/* -** Remove entries from the hash table that point to WAL slots greater -** than pWal->hdr.mxFrame. -** -** This function is called whenever pWal->hdr.mxFrame is decreased due -** to a rollback or savepoint. -** -** At most only the hash table containing pWal->hdr.mxFrame needs to be -** updated. Any later hash tables will be automatically cleared when -** pWal->hdr.mxFrame advances to the point where those hash tables are -** actually needed. -*/ -static void walCleanupHash(Wal *pWal){ - volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */ - volatile u32 *aPgno = 0; /* Page number array for hash table */ - u32 iZero = 0; /* frame == (aHash[x]+iZero) */ - int iLimit = 0; /* Zero values greater than this */ - int nByte; /* Number of bytes to zero in aPgno[] */ - int i; /* Used to iterate through aHash[] */ - - assert( pWal->writeLock ); - testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 ); - testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE ); - testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 ); - - if( pWal->hdr.mxFrame==0 ) return; - - /* Obtain pointers to the hash-table and page-number array containing - ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed - ** that the page said hash-table and array reside on is already mapped. - */ - assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) ); - assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] ); - walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero); - - /* Zero all hash-table entries that correspond to frame numbers greater - ** than pWal->hdr.mxFrame. - */ - iLimit = pWal->hdr.mxFrame - iZero; - assert( iLimit>0 ); - for(i=0; iiLimit ){ - aHash[i] = 0; - } - } - - /* Zero the entries in the aPgno array that correspond to frames with - ** frame numbers greater than pWal->hdr.mxFrame. - */ - nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]); - memset((void *)&aPgno[iLimit+1], 0, nByte); - -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - /* Verify that the every entry in the mapping region is still reachable - ** via the hash table even after the cleanup. - */ - if( iLimit ){ - int i; /* Loop counter */ - int iKey; /* Hash key */ - for(i=1; i<=iLimit; i++){ - for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){ - if( aHash[iKey]==i ) break; - } - assert( aHash[iKey]==i ); - } - } -#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ -} - - -/* -** Set an entry in the wal-index that will map database page number -** pPage into WAL frame iFrame. -*/ -static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ - int rc; /* Return code */ - u32 iZero = 0; /* One less than frame number of aPgno[1] */ - volatile u32 *aPgno = 0; /* Page number array */ - volatile ht_slot *aHash = 0; /* Hash table */ - - rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero); - - /* Assuming the wal-index file was successfully mapped, populate the - ** page number array and hash table entry. - */ - if( rc==SQLITE_OK ){ - int iKey; /* Hash table key */ - int idx; /* Value to write to hash-table slot */ - int nCollide; /* Number of hash collisions */ - - idx = iFrame - iZero; - assert( idx <= HASHTABLE_NSLOT/2 + 1 ); - - /* If this is the first entry to be added to this hash-table, zero the - ** entire hash table and aPgno[] array before proceding. - */ - if( idx==1 ){ - int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]); - memset((void*)&aPgno[1], 0, nByte); - } - - /* If the entry in aPgno[] is already set, then the previous writer - ** must have exited unexpectedly in the middle of a transaction (after - ** writing one or more dirty pages to the WAL to free up memory). - ** Remove the remnants of that writers uncommitted transaction from - ** the hash-table before writing any new entries. - */ - if( aPgno[idx] ){ - walCleanupHash(pWal); - assert( !aPgno[idx] ); - } - - /* Write the aPgno[] array entry and the hash-table slot. */ - nCollide = idx; - for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ - if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT; - } - aPgno[idx] = iPage; - aHash[iKey] = (ht_slot)idx; - -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - /* Verify that the number of entries in the hash table exactly equals - ** the number of entries in the mapping region. - */ - { - int i; /* Loop counter */ - int nEntry = 0; /* Number of entries in the hash table */ - for(i=0; ickptLock==1 || pWal->ckptLock==0 ); - assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 ); - assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE ); - assert( pWal->writeLock ); - iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; - nLock = SQLITE_SHM_NLOCK - iLock; - rc = walLockExclusive(pWal, iLock, nLock); - if( rc ){ - return rc; - } - WALTRACE(("WAL%p: recovery begin...\n", pWal)); - - memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); - - rc = sqlite3OsFileSize(pWal->pWalFd, &nSize); - if( rc!=SQLITE_OK ){ - goto recovery_error; - } - - if( nSize>WAL_HDRSIZE ){ - u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */ - u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ - int szFrame; /* Number of bytes in buffer aFrame[] */ - u8 *aData; /* Pointer to data part of aFrame buffer */ - int iFrame; /* Index of last frame read */ - i64 iOffset; /* Next offset to read from log file */ - int szPage; /* Page size according to the log */ - u32 magic; /* Magic value read from WAL header */ - u32 version; /* Magic value read from WAL header */ - int isValid; /* True if this frame is valid */ - - /* Read in the WAL header. */ - rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); - if( rc!=SQLITE_OK ){ - goto recovery_error; - } - - /* If the database page size is not a power of two, or is greater than - ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid - ** data. Similarly, if the 'magic' value is invalid, ignore the whole - ** WAL file. - */ - magic = sqlite3Get4byte(&aBuf[0]); - szPage = sqlite3Get4byte(&aBuf[8]); - if( (magic&0xFFFFFFFE)!=WAL_MAGIC - || szPage&(szPage-1) - || szPage>SQLITE_MAX_PAGE_SIZE - || szPage<512 - ){ - goto finished; - } - pWal->hdr.bigEndCksum = (u8)(magic&0x00000001); - pWal->szPage = szPage; - pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); - memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); - - /* Verify that the WAL header checksum is correct */ - walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, - aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum - ); - if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24]) - || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28]) - ){ - goto finished; - } - - /* Verify that the version number on the WAL format is one that - ** are able to understand */ - version = sqlite3Get4byte(&aBuf[4]); - if( version!=WAL_MAX_VERSION ){ - rc = SQLITE_CANTOPEN_BKPT; - goto finished; - } - - /* Malloc a buffer to read frames into. */ - szFrame = szPage + WAL_FRAME_HDRSIZE; - aFrame = (u8 *)sqlite3_malloc(szFrame); - if( !aFrame ){ - rc = SQLITE_NOMEM; - goto recovery_error; - } - aData = &aFrame[WAL_FRAME_HDRSIZE]; - - /* Read all frames from the log file. */ - iFrame = 0; - for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){ - u32 pgno; /* Database page number for frame */ - u32 nTruncate; /* dbsize field from frame header */ - - /* Read and decode the next log frame. */ - iFrame++; - rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset); - if( rc!=SQLITE_OK ) break; - isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame); - if( !isValid ) break; - rc = walIndexAppend(pWal, iFrame, pgno); - if( rc!=SQLITE_OK ) break; - - /* If nTruncate is non-zero, this is a commit record. */ - if( nTruncate ){ - pWal->hdr.mxFrame = iFrame; - pWal->hdr.nPage = nTruncate; - pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); - testcase( szPage<=32768 ); - testcase( szPage>=65536 ); - aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; - aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; - } - } - - sqlite3_free(aFrame); - } - -finished: - if( rc==SQLITE_OK ){ - volatile WalCkptInfo *pInfo; - int i; - pWal->hdr.aFrameCksum[0] = aFrameCksum[0]; - pWal->hdr.aFrameCksum[1] = aFrameCksum[1]; - walIndexWriteHdr(pWal); - - /* Reset the checkpoint-header. This is safe because this thread is - ** currently holding locks that exclude all other readers, writers and - ** checkpointers. - */ - pInfo = walCkptInfo(pWal); - pInfo->nBackfill = 0; - pInfo->aReadMark[0] = 0; - for(i=1; iaReadMark[i] = READMARK_NOT_USED; - if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame; - - /* If more than one frame was recovered from the log file, report an - ** event via sqlite3_log(). This is to help with identifying performance - ** problems caused by applications routinely shutting down without - ** checkpointing the log file. - */ - if( pWal->hdr.nPage ){ - sqlite3_log(SQLITE_NOTICE_RECOVER_WAL, - "recovered %d frames from WAL file %s", - pWal->hdr.mxFrame, pWal->zWalName - ); - } - } - -recovery_error: - WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok")); - walUnlockExclusive(pWal, iLock, nLock); - return rc; -} - -/* -** Close an open wal-index. -*/ -static void walIndexClose(Wal *pWal, int isDelete){ - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ - int i; - for(i=0; inWiData; i++){ - sqlite3_free((void *)pWal->apWiData[i]); - pWal->apWiData[i] = 0; - } - }else{ - sqlite3OsShmUnmap(pWal->pDbFd, isDelete); - } -} - -/* -** Open a connection to the WAL file zWalName. The database file must -** already be opened on connection pDbFd. The buffer that zWalName points -** to must remain valid for the lifetime of the returned Wal* handle. -** -** A SHARED lock should be held on the database file when this function -** is called. The purpose of this SHARED lock is to prevent any other -** client from unlinking the WAL or wal-index file. If another process -** were to do this just after this client opened one of these files, the -** system would be badly broken. -** -** If the log file is successfully opened, SQLITE_OK is returned and -** *ppWal is set to point to a new WAL handle. If an error occurs, -** an SQLite error code is returned and *ppWal is left unmodified. -*/ -SQLITE_PRIVATE int sqlite3WalOpen( - sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ - sqlite3_file *pDbFd, /* The open database file */ - const char *zWalName, /* Name of the WAL file */ - int bNoShm, /* True to run in heap-memory mode */ - i64 mxWalSize, /* Truncate WAL to this size on reset */ - Wal **ppWal /* OUT: Allocated Wal handle */ -){ - int rc; /* Return Code */ - Wal *pRet; /* Object to allocate and return */ - int flags; /* Flags passed to OsOpen() */ - - assert( zWalName && zWalName[0] ); - assert( pDbFd ); - - /* In the amalgamation, the os_unix.c and os_win.c source files come before - ** this source file. Verify that the #defines of the locking byte offsets - ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value. - */ -#ifdef WIN_SHM_BASE - assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET ); -#endif -#ifdef UNIX_SHM_BASE - assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET ); -#endif - - - /* Allocate an instance of struct Wal to return. */ - *ppWal = 0; - pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile); - if( !pRet ){ - return SQLITE_NOMEM; - } - - pRet->pVfs = pVfs; - pRet->pWalFd = (sqlite3_file *)&pRet[1]; - pRet->pDbFd = pDbFd; - pRet->readLock = -1; - pRet->mxWalSize = mxWalSize; - pRet->zWalName = zWalName; - pRet->syncHeader = 1; - pRet->padToSectorBoundary = 1; - pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE); - - /* Open file handle on the write-ahead log file. */ - flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL); - rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags); - if( rc==SQLITE_OK && flags&SQLITE_OPEN_READONLY ){ - pRet->readOnly = WAL_RDONLY; - } - - if( rc!=SQLITE_OK ){ - walIndexClose(pRet, 0); - sqlite3OsClose(pRet->pWalFd); - sqlite3_free(pRet); - }else{ - int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd); - if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; } - if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){ - pRet->padToSectorBoundary = 0; - } - *ppWal = pRet; - WALTRACE(("WAL%d: opened\n", pRet)); - } - return rc; -} - -/* -** Change the size to which the WAL file is trucated on each reset. -*/ -SQLITE_PRIVATE void sqlite3WalLimit(Wal *pWal, i64 iLimit){ - if( pWal ) pWal->mxWalSize = iLimit; -} - -/* -** Find the smallest page number out of all pages held in the WAL that -** has not been returned by any prior invocation of this method on the -** same WalIterator object. Write into *piFrame the frame index where -** that page was last written into the WAL. Write into *piPage the page -** number. -** -** Return 0 on success. If there are no pages in the WAL with a page -** number larger than *piPage, then return 1. -*/ -static int walIteratorNext( - WalIterator *p, /* Iterator */ - u32 *piPage, /* OUT: The page number of the next page */ - u32 *piFrame /* OUT: Wal frame index of next page */ -){ - u32 iMin; /* Result pgno must be greater than iMin */ - u32 iRet = 0xFFFFFFFF; /* 0xffffffff is never a valid page number */ - int i; /* For looping through segments */ - - iMin = p->iPrior; - assert( iMin<0xffffffff ); - for(i=p->nSegment-1; i>=0; i--){ - struct WalSegment *pSegment = &p->aSegment[i]; - while( pSegment->iNextnEntry ){ - u32 iPg = pSegment->aPgno[pSegment->aIndex[pSegment->iNext]]; - if( iPg>iMin ){ - if( iPgiZero + pSegment->aIndex[pSegment->iNext]; - } - break; - } - pSegment->iNext++; - } - } - - *piPage = p->iPrior = iRet; - return (iRet==0xFFFFFFFF); -} - -/* -** This function merges two sorted lists into a single sorted list. -** -** aLeft[] and aRight[] are arrays of indices. The sort key is -** aContent[aLeft[]] and aContent[aRight[]]. Upon entry, the following -** is guaranteed for all J0 && nRight>0 ); - while( iRight=nRight || aContent[aLeft[iLeft]]=nLeft || aContent[aLeft[iLeft]]>dbpage ); - assert( iRight>=nRight || aContent[aRight[iRight]]>dbpage ); - } - - *paRight = aLeft; - *pnRight = iOut; - memcpy(aLeft, aTmp, sizeof(aTmp[0])*iOut); -} - -/* -** Sort the elements in list aList using aContent[] as the sort key. -** Remove elements with duplicate keys, preferring to keep the -** larger aList[] values. -** -** The aList[] entries are indices into aContent[]. The values in -** aList[] are to be sorted so that for all J0 ); - assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) ); - - for(iList=0; iListaList && p->nList<=(1<aList==&aList[iList&~((2<aList, p->nList, &aMerge, &nMerge, aBuffer); - } - aSub[iSub].aList = aMerge; - aSub[iSub].nList = nMerge; - } - - for(iSub++; iSubnList<=(1<aList==&aList[nList&~((2<aList, p->nList, &aMerge, &nMerge, aBuffer); - } - } - assert( aMerge==aList ); - *pnList = nMerge; - -#ifdef SQLITE_DEBUG - { - int i; - for(i=1; i<*pnList; i++){ - assert( aContent[aList[i]] > aContent[aList[i-1]] ); - } - } -#endif -} - -/* -** Free an iterator allocated by walIteratorInit(). -*/ -static void walIteratorFree(WalIterator *p){ - sqlite3ScratchFree(p); -} - -/* -** Construct a WalInterator object that can be used to loop over all -** pages in the WAL in ascending order. The caller must hold the checkpoint -** lock. -** -** On success, make *pp point to the newly allocated WalInterator object -** return SQLITE_OK. Otherwise, return an error code. If this routine -** returns an error, the value of *pp is undefined. -** -** The calling routine should invoke walIteratorFree() to destroy the -** WalIterator object when it has finished with it. -*/ -static int walIteratorInit(Wal *pWal, WalIterator **pp){ - WalIterator *p; /* Return value */ - int nSegment; /* Number of segments to merge */ - u32 iLast; /* Last frame in log */ - int nByte; /* Number of bytes to allocate */ - int i; /* Iterator variable */ - ht_slot *aTmp; /* Temp space used by merge-sort */ - int rc = SQLITE_OK; /* Return Code */ - - /* This routine only runs while holding the checkpoint lock. And - ** it only runs if there is actually content in the log (mxFrame>0). - */ - assert( pWal->ckptLock && pWal->hdr.mxFrame>0 ); - iLast = pWal->hdr.mxFrame; - - /* Allocate space for the WalIterator object. */ - nSegment = walFramePage(iLast) + 1; - nByte = sizeof(WalIterator) - + (nSegment-1)*sizeof(struct WalSegment) - + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3ScratchMalloc(nByte); - if( !p ){ - return SQLITE_NOMEM; - } - memset(p, 0, nByte); - p->nSegment = nSegment; - - /* Allocate temporary space used by the merge-sort routine. This block - ** of memory will be freed before this function returns. - */ - aTmp = (ht_slot *)sqlite3ScratchMalloc( - sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) - ); - if( !aTmp ){ - rc = SQLITE_NOMEM; - } - - for(i=0; rc==SQLITE_OK && iaSegment[p->nSegment])[iZero]; - iZero++; - - for(j=0; jaSegment[i].iZero = iZero; - p->aSegment[i].nEntry = nEntry; - p->aSegment[i].aIndex = aIndex; - p->aSegment[i].aPgno = (u32 *)aPgno; - } - } - sqlite3ScratchFree(aTmp); - - if( rc!=SQLITE_OK ){ - walIteratorFree(p); - } - *pp = p; - return rc; -} - -/* -** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and -** n. If the attempt fails and parameter xBusy is not NULL, then it is a -** busy-handler function. Invoke it and retry the lock until either the -** lock is successfully obtained or the busy-handler returns 0. -*/ -static int walBusyLock( - Wal *pWal, /* WAL connection */ - int (*xBusy)(void*), /* Function to call when busy */ - void *pBusyArg, /* Context argument for xBusyHandler */ - int lockIdx, /* Offset of first byte to lock */ - int n /* Number of bytes to lock */ -){ - int rc; - do { - rc = walLockExclusive(pWal, lockIdx, n); - }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) ); - return rc; -} - -/* -** The cache of the wal-index header must be valid to call this function. -** Return the page-size in bytes used by the database. -*/ -static int walPagesize(Wal *pWal){ - return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); -} - -/* -** Copy as much content as we can from the WAL back into the database file -** in response to an sqlite3_wal_checkpoint() request or the equivalent. -** -** The amount of information copies from WAL to database might be limited -** by active readers. This routine will never overwrite a database page -** that a concurrent reader might be using. -** -** All I/O barrier operations (a.k.a fsyncs) occur in this routine when -** SQLite is in WAL-mode in synchronous=NORMAL. That means that if -** checkpoints are always run by a background thread or background -** process, foreground threads will never block on a lengthy fsync call. -** -** Fsync is called on the WAL before writing content out of the WAL and -** into the database. This ensures that if the new content is persistent -** in the WAL and can be recovered following a power-loss or hard reset. -** -** Fsync is also called on the database file if (and only if) the entire -** WAL content is copied into the database file. This second fsync makes -** it safe to delete the WAL since the new content will persist in the -** database file. -** -** This routine uses and updates the nBackfill field of the wal-index header. -** This is the only routine tha will increase the value of nBackfill. -** (A WAL reset or recovery will revert nBackfill to zero, but not increase -** its value.) -** -** The caller must be holding sufficient locks to ensure that no other -** checkpoint is running (in any other thread or process) at the same -** time. -*/ -static int walCheckpoint( - Wal *pWal, /* Wal connection */ - int eMode, /* One of PASSIVE, FULL or RESTART */ - int (*xBusyCall)(void*), /* Function to call when busy */ - void *pBusyArg, /* Context argument for xBusyHandler */ - int sync_flags, /* Flags for OsSync() (or 0) */ - u8 *zBuf /* Temporary buffer to use */ -){ - int rc; /* Return code */ - int szPage; /* Database page-size */ - WalIterator *pIter = 0; /* Wal iterator context */ - u32 iDbpage = 0; /* Next database page to write */ - u32 iFrame = 0; /* Wal frame containing data for iDbpage */ - u32 mxSafeFrame; /* Max frame that can be backfilled */ - u32 mxPage; /* Max database page to write */ - int i; /* Loop counter */ - volatile WalCkptInfo *pInfo; /* The checkpoint status information */ - int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */ - - szPage = walPagesize(pWal); - testcase( szPage<=32768 ); - testcase( szPage>=65536 ); - pInfo = walCkptInfo(pWal); - if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK; - - /* Allocate the iterator */ - rc = walIteratorInit(pWal, &pIter); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pIter ); - - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall; - - /* Compute in mxSafeFrame the index of the last frame of the WAL that is - ** safe to write into the database. Frames beyond mxSafeFrame might - ** overwrite database pages that are in use by active readers and thus - ** cannot be backfilled from the WAL. - */ - mxSafeFrame = pWal->hdr.mxFrame; - mxPage = pWal->hdr.nPage; - for(i=1; iaReadMark[i]; - if( mxSafeFrame>y ){ - assert( y<=pWal->hdr.mxFrame ); - rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); - if( rc==SQLITE_OK ){ - pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED); - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - }else if( rc==SQLITE_BUSY ){ - mxSafeFrame = y; - xBusy = 0; - }else{ - goto walcheckpoint_out; - } - } - } - - if( pInfo->nBackfillnBackfill; - - /* Sync the WAL to disk */ - if( sync_flags ){ - rc = sqlite3OsSync(pWal->pWalFd, sync_flags); - } - - /* If the database may grow as a result of this checkpoint, hint - ** about the eventual size of the db file to the VFS layer. - */ - if( rc==SQLITE_OK ){ - i64 nReq = ((i64)mxPage * szPage); - rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); - if( rc==SQLITE_OK && nSizepDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); - } - } - - - /* Iterate through the contents of the WAL, copying data to the db file. */ - while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ - i64 iOffset; - assert( walFramePgno(pWal, iFrame)==iDbpage ); - if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue; - iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; - /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ - rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - iOffset = (iDbpage-1)*(i64)szPage; - testcase( IS_BIG_INT(iOffset) ); - rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset); - if( rc!=SQLITE_OK ) break; - } - - /* If work was actually accomplished... */ - if( rc==SQLITE_OK ){ - if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){ - i64 szDb = pWal->hdr.nPage*(i64)szPage; - testcase( IS_BIG_INT(szDb) ); - rc = sqlite3OsTruncate(pWal->pDbFd, szDb); - if( rc==SQLITE_OK && sync_flags ){ - rc = sqlite3OsSync(pWal->pDbFd, sync_flags); - } - } - if( rc==SQLITE_OK ){ - pInfo->nBackfill = mxSafeFrame; - } - } - - /* Release the reader lock held while backfilling */ - walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1); - } - - if( rc==SQLITE_BUSY ){ - /* Reset the return code so as not to report a checkpoint failure - ** just because there are active readers. */ - rc = SQLITE_OK; - } - - /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal - ** file has been copied into the database file, then block until all - ** readers have finished using the wal file. This ensures that the next - ** process to write to the database restarts the wal file. - */ - if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ - assert( pWal->writeLock ); - if( pInfo->nBackfillhdr.mxFrame ){ - rc = SQLITE_BUSY; - }else if( eMode==SQLITE_CHECKPOINT_RESTART ){ - assert( mxSafeFrame==pWal->hdr.mxFrame ); - rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); - if( rc==SQLITE_OK ){ - walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); - } - } - } - - walcheckpoint_out: - walIteratorFree(pIter); - return rc; -} - -/* -** If the WAL file is currently larger than nMax bytes in size, truncate -** it to exactly nMax bytes. If an error occurs while doing so, ignore it. -*/ -static void walLimitSize(Wal *pWal, i64 nMax){ - i64 sz; - int rx; - sqlite3BeginBenignMalloc(); - rx = sqlite3OsFileSize(pWal->pWalFd, &sz); - if( rx==SQLITE_OK && (sz > nMax ) ){ - rx = sqlite3OsTruncate(pWal->pWalFd, nMax); - } - sqlite3EndBenignMalloc(); - if( rx ){ - sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName); - } -} - -/* -** Close a connection to a log file. -*/ -SQLITE_PRIVATE int sqlite3WalClose( - Wal *pWal, /* Wal to close */ - int sync_flags, /* Flags to pass to OsSync() (or 0) */ - int nBuf, - u8 *zBuf /* Buffer of at least nBuf bytes */ -){ - int rc = SQLITE_OK; - if( pWal ){ - int isDelete = 0; /* True to unlink wal and wal-index files */ - - /* If an EXCLUSIVE lock can be obtained on the database file (using the - ** ordinary, rollback-mode locking methods, this guarantees that the - ** connection associated with this log file is the only connection to - ** the database. In this case checkpoint the database and unlink both - ** the wal and wal-index files. - ** - ** The EXCLUSIVE lock is not released before returning. - */ - rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); - if( rc==SQLITE_OK ){ - if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ - pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; - } - rc = sqlite3WalCheckpoint( - pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 - ); - if( rc==SQLITE_OK ){ - int bPersist = -1; - sqlite3OsFileControlHint( - pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist - ); - if( bPersist!=1 ){ - /* Try to delete the WAL file if the checkpoint completed and - ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal - ** mode (!bPersist) */ - isDelete = 1; - }else if( pWal->mxWalSize>=0 ){ - /* Try to truncate the WAL file to zero bytes if the checkpoint - ** completed and fsynced (rc==SQLITE_OK) and we are in persistent - ** WAL mode (bPersist) and if the PRAGMA journal_size_limit is a - ** non-negative value (pWal->mxWalSize>=0). Note that we truncate - ** to zero bytes as truncating to the journal_size_limit might - ** leave a corrupt WAL file on disk. */ - walLimitSize(pWal, 0); - } - } - } - - walIndexClose(pWal, isDelete); - sqlite3OsClose(pWal->pWalFd); - if( isDelete ){ - sqlite3BeginBenignMalloc(); - sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0); - sqlite3EndBenignMalloc(); - } - WALTRACE(("WAL%p: closed\n", pWal)); - sqlite3_free((void *)pWal->apWiData); - sqlite3_free(pWal); - } - return rc; -} - -/* -** Try to read the wal-index header. Return 0 on success and 1 if -** there is a problem. -** -** The wal-index is in shared memory. Another thread or process might -** be writing the header at the same time this procedure is trying to -** read it, which might result in inconsistency. A dirty read is detected -** by verifying that both copies of the header are the same and also by -** a checksum on the header. -** -** If and only if the read is consistent and the header is different from -** pWal->hdr, then pWal->hdr is updated to the content of the new header -** and *pChanged is set to 1. -** -** If the checksum cannot be verified return non-zero. If the header -** is read successfully and the checksum verified, return zero. -*/ -static int walIndexTryHdr(Wal *pWal, int *pChanged){ - u32 aCksum[2]; /* Checksum on the header content */ - WalIndexHdr h1, h2; /* Two copies of the header content */ - WalIndexHdr volatile *aHdr; /* Header in shared memory */ - - /* The first page of the wal-index must be mapped at this point. */ - assert( pWal->nWiData>0 && pWal->apWiData[0] ); - - /* Read the header. This might happen concurrently with a write to the - ** same area of shared memory on a different CPU in a SMP, - ** meaning it is possible that an inconsistent snapshot is read - ** from the file. If this happens, return non-zero. - ** - ** There are two copies of the header at the beginning of the wal-index. - ** When reading, read [0] first then [1]. Writes are in the reverse order. - ** Memory barriers are used to prevent the compiler or the hardware from - ** reordering the reads and writes. - */ - aHdr = walIndexHdr(pWal); - memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); - walShmBarrier(pWal); - memcpy(&h2, (void *)&aHdr[1], sizeof(h2)); - - if( memcmp(&h1, &h2, sizeof(h1))!=0 ){ - return 1; /* Dirty read */ - } - if( h1.isInit==0 ){ - return 1; /* Malformed header - probably all zeros */ - } - walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum); - if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){ - return 1; /* Checksum does not match */ - } - - if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){ - *pChanged = 1; - memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr)); - pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); - testcase( pWal->szPage<=32768 ); - testcase( pWal->szPage>=65536 ); - } - - /* The header was successfully read. Return zero. */ - return 0; -} - -/* -** Read the wal-index header from the wal-index and into pWal->hdr. -** If the wal-header appears to be corrupt, try to reconstruct the -** wal-index from the WAL before returning. -** -** Set *pChanged to 1 if the wal-index header value in pWal->hdr is -** changed by this opertion. If pWal->hdr is unchanged, set *pChanged -** to 0. -** -** If the wal-index header is successfully read, return SQLITE_OK. -** Otherwise an SQLite error code. -*/ -static int walIndexReadHdr(Wal *pWal, int *pChanged){ - int rc; /* Return code */ - int badHdr; /* True if a header read failed */ - volatile u32 *page0; /* Chunk of wal-index containing header */ - - /* Ensure that page 0 of the wal-index (the page that contains the - ** wal-index header) is mapped. Return early if an error occurs here. - */ - assert( pChanged ); - rc = walIndexPage(pWal, 0, &page0); - if( rc!=SQLITE_OK ){ - return rc; - }; - assert( page0 || pWal->writeLock==0 ); - - /* If the first page of the wal-index has been mapped, try to read the - ** wal-index header immediately, without holding any lock. This usually - ** works, but may fail if the wal-index header is corrupt or currently - ** being modified by another thread or process. - */ - badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1); - - /* If the first attempt failed, it might have been due to a race - ** with a writer. So get a WRITE lock and try again. - */ - assert( badHdr==0 || pWal->writeLock==0 ); - if( badHdr ){ - if( pWal->readOnly & WAL_SHM_RDONLY ){ - if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){ - walUnlockShared(pWal, WAL_WRITE_LOCK); - rc = SQLITE_READONLY_RECOVERY; - } - }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){ - pWal->writeLock = 1; - if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ - badHdr = walIndexTryHdr(pWal, pChanged); - if( badHdr ){ - /* If the wal-index header is still malformed even while holding - ** a WRITE lock, it can only mean that the header is corrupted and - ** needs to be reconstructed. So run recovery to do exactly that. - */ - rc = walIndexRecover(pWal); - *pChanged = 1; - } - } - pWal->writeLock = 0; - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - } - } - - /* If the header is read successfully, check the version number to make - ** sure the wal-index was not constructed with some future format that - ** this version of SQLite cannot understand. - */ - if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){ - rc = SQLITE_CANTOPEN_BKPT; - } - - return rc; -} - -/* -** This is the value that walTryBeginRead returns when it needs to -** be retried. -*/ -#define WAL_RETRY (-1) - -/* -** Attempt to start a read transaction. This might fail due to a race or -** other transient condition. When that happens, it returns WAL_RETRY to -** indicate to the caller that it is safe to retry immediately. -** -** On success return SQLITE_OK. On a permanent failure (such an -** I/O error or an SQLITE_BUSY because another process is running -** recovery) return a positive error code. -** -** The useWal parameter is true to force the use of the WAL and disable -** the case where the WAL is bypassed because it has been completely -** checkpointed. If useWal==0 then this routine calls walIndexReadHdr() -** to make a copy of the wal-index header into pWal->hdr. If the -** wal-index header has changed, *pChanged is set to 1 (as an indication -** to the caller that the local paget cache is obsolete and needs to be -** flushed.) When useWal==1, the wal-index header is assumed to already -** be loaded and the pChanged parameter is unused. -** -** The caller must set the cnt parameter to the number of prior calls to -** this routine during the current read attempt that returned WAL_RETRY. -** This routine will start taking more aggressive measures to clear the -** race conditions after multiple WAL_RETRY returns, and after an excessive -** number of errors will ultimately return SQLITE_PROTOCOL. The -** SQLITE_PROTOCOL return indicates that some other process has gone rogue -** and is not honoring the locking protocol. There is a vanishingly small -** chance that SQLITE_PROTOCOL could be returned because of a run of really -** bad luck when there is lots of contention for the wal-index, but that -** possibility is so small that it can be safely neglected, we believe. -** -** On success, this routine obtains a read lock on -** WAL_READ_LOCK(pWal->readLock). The pWal->readLock integer is -** in the range 0 <= pWal->readLock < WAL_NREADER. If pWal->readLock==(-1) -** that means the Wal does not hold any read lock. The reader must not -** access any database page that is modified by a WAL frame up to and -** including frame number aReadMark[pWal->readLock]. The reader will -** use WAL frames up to and including pWal->hdr.mxFrame if pWal->readLock>0 -** Or if pWal->readLock==0, then the reader will ignore the WAL -** completely and get all content directly from the database file. -** If the useWal parameter is 1 then the WAL will never be ignored and -** this routine will always set pWal->readLock>0 on success. -** When the read transaction is completed, the caller must release the -** lock on WAL_READ_LOCK(pWal->readLock) and set pWal->readLock to -1. -** -** This routine uses the nBackfill and aReadMark[] fields of the header -** to select a particular WAL_READ_LOCK() that strives to let the -** checkpoint process do as much work as possible. This routine might -** update values of the aReadMark[] array in the header, but if it does -** so it takes care to hold an exclusive lock on the corresponding -** WAL_READ_LOCK() while changing values. -*/ -static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ - volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */ - u32 mxReadMark; /* Largest aReadMark[] value */ - int mxI; /* Index of largest aReadMark[] value */ - int i; /* Loop counter */ - int rc = SQLITE_OK; /* Return code */ - - assert( pWal->readLock<0 ); /* Not currently locked */ - - /* Take steps to avoid spinning forever if there is a protocol error. - ** - ** Circumstances that cause a RETRY should only last for the briefest - ** instances of time. No I/O or other system calls are done while the - ** locks are held, so the locks should not be held for very long. But - ** if we are unlucky, another process that is holding a lock might get - ** paged out or take a page-fault that is time-consuming to resolve, - ** during the few nanoseconds that it is holding the lock. In that case, - ** it might take longer than normal for the lock to free. - ** - ** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few - ** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this - ** is more of a scheduler yield than an actual delay. But on the 10th - ** an subsequent retries, the delays start becoming longer and longer, - ** so that on the 100th (and last) RETRY we delay for 21 milliseconds. - ** The total delay time before giving up is less than 1 second. - */ - if( cnt>5 ){ - int nDelay = 1; /* Pause time in microseconds */ - if( cnt>100 ){ - VVA_ONLY( pWal->lockError = 1; ) - return SQLITE_PROTOCOL; - } - if( cnt>=10 ) nDelay = (cnt-9)*238; /* Max delay 21ms. Total delay 996ms */ - sqlite3OsSleep(pWal->pVfs, nDelay); - } - - if( !useWal ){ - rc = walIndexReadHdr(pWal, pChanged); - if( rc==SQLITE_BUSY ){ - /* If there is not a recovery running in another thread or process - ** then convert BUSY errors to WAL_RETRY. If recovery is known to - ** be running, convert BUSY to BUSY_RECOVERY. There is a race here - ** which might cause WAL_RETRY to be returned even if BUSY_RECOVERY - ** would be technically correct. But the race is benign since with - ** WAL_RETRY this routine will be called again and will probably be - ** right on the second iteration. - */ - if( pWal->apWiData[0]==0 ){ - /* This branch is taken when the xShmMap() method returns SQLITE_BUSY. - ** We assume this is a transient condition, so return WAL_RETRY. The - ** xShmMap() implementation used by the default unix and win32 VFS - ** modules may return SQLITE_BUSY due to a race condition in the - ** code that determines whether or not the shared-memory region - ** must be zeroed before the requested page is returned. - */ - rc = WAL_RETRY; - }else if( SQLITE_OK==(rc = walLockShared(pWal, WAL_RECOVER_LOCK)) ){ - walUnlockShared(pWal, WAL_RECOVER_LOCK); - rc = WAL_RETRY; - }else if( rc==SQLITE_BUSY ){ - rc = SQLITE_BUSY_RECOVERY; - } - } - if( rc!=SQLITE_OK ){ - return rc; - } - } - - pInfo = walCkptInfo(pWal); - if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){ - /* The WAL has been completely backfilled (or it is empty). - ** and can be safely ignored. - */ - rc = walLockShared(pWal, WAL_READ_LOCK(0)); - walShmBarrier(pWal); - if( rc==SQLITE_OK ){ - if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){ - /* It is not safe to allow the reader to continue here if frames - ** may have been appended to the log before READ_LOCK(0) was obtained. - ** When holding READ_LOCK(0), the reader ignores the entire log file, - ** which implies that the database file contains a trustworthy - ** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from - ** happening, this is usually correct. - ** - ** However, if frames have been appended to the log (or if the log - ** is wrapped and written for that matter) before the READ_LOCK(0) - ** is obtained, that is not necessarily true. A checkpointer may - ** have started to backfill the appended frames but crashed before - ** it finished. Leaving a corrupt image in the database file. - */ - walUnlockShared(pWal, WAL_READ_LOCK(0)); - return WAL_RETRY; - } - pWal->readLock = 0; - return SQLITE_OK; - }else if( rc!=SQLITE_BUSY ){ - return rc; - } - } - - /* If we get this far, it means that the reader will want to use - ** the WAL to get at content from recent commits. The job now is - ** to select one of the aReadMark[] entries that is closest to - ** but not exceeding pWal->hdr.mxFrame and lock that entry. - */ - mxReadMark = 0; - mxI = 0; - for(i=1; iaReadMark[i]; - if( mxReadMark<=thisMark && thisMark<=pWal->hdr.mxFrame ){ - assert( thisMark!=READMARK_NOT_USED ); - mxReadMark = thisMark; - mxI = i; - } - } - /* There was once an "if" here. The extra "{" is to preserve indentation. */ - { - if( (pWal->readOnly & WAL_SHM_RDONLY)==0 - && (mxReadMarkhdr.mxFrame || mxI==0) - ){ - for(i=1; iaReadMark[i] = pWal->hdr.mxFrame; - mxI = i; - walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); - break; - }else if( rc!=SQLITE_BUSY ){ - return rc; - } - } - } - if( mxI==0 ){ - assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); - return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK; - } - - rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); - if( rc ){ - return rc==SQLITE_BUSY ? WAL_RETRY : rc; - } - /* Now that the read-lock has been obtained, check that neither the - ** value in the aReadMark[] array or the contents of the wal-index - ** header have changed. - ** - ** It is necessary to check that the wal-index header did not change - ** between the time it was read and when the shared-lock was obtained - ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility - ** that the log file may have been wrapped by a writer, or that frames - ** that occur later in the log than pWal->hdr.mxFrame may have been - ** copied into the database by a checkpointer. If either of these things - ** happened, then reading the database with the current value of - ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry - ** instead. - ** - ** This does not guarantee that the copy of the wal-index header is up to - ** date before proceeding. That would not be possible without somehow - ** blocking writers. It only guarantees that a dangerous checkpoint or - ** log-wrap (either of which would require an exclusive lock on - ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid. - */ - walShmBarrier(pWal); - if( pInfo->aReadMark[mxI]!=mxReadMark - || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) - ){ - walUnlockShared(pWal, WAL_READ_LOCK(mxI)); - return WAL_RETRY; - }else{ - assert( mxReadMark<=pWal->hdr.mxFrame ); - pWal->readLock = (i16)mxI; - } - } - return rc; -} - -/* -** Begin a read transaction on the database. -** -** This routine used to be called sqlite3OpenSnapshot() and with good reason: -** it takes a snapshot of the state of the WAL and wal-index for the current -** instant in time. The current thread will continue to use this snapshot. -** Other threads might append new content to the WAL and wal-index but -** that extra content is ignored by the current thread. -** -** If the database contents have changes since the previous read -** transaction, then *pChanged is set to 1 before returning. The -** Pager layer will use this to know that is cache is stale and -** needs to be flushed. -*/ -SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ - int rc; /* Return code */ - int cnt = 0; /* Number of TryBeginRead attempts */ - - do{ - rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); - }while( rc==WAL_RETRY ); - testcase( (rc&0xff)==SQLITE_BUSY ); - testcase( (rc&0xff)==SQLITE_IOERR ); - testcase( rc==SQLITE_PROTOCOL ); - testcase( rc==SQLITE_OK ); - return rc; -} - -/* -** Finish with a read transaction. All this does is release the -** read-lock. -*/ -SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ - sqlite3WalEndWriteTransaction(pWal); - if( pWal->readLock>=0 ){ - walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); - pWal->readLock = -1; - } -} - -/* -** Search the wal file for page pgno. If found, set *piRead to the frame that -** contains the page. Otherwise, if pgno is not in the wal file, set *piRead -** to zero. -** -** Return SQLITE_OK if successful, or an error code if an error occurs. If an -** error does occur, the final value of *piRead is undefined. -*/ -SQLITE_PRIVATE int sqlite3WalFindFrame( - Wal *pWal, /* WAL handle */ - Pgno pgno, /* Database page number to read data for */ - u32 *piRead /* OUT: Frame number (or zero) */ -){ - u32 iRead = 0; /* If !=0, WAL frame to return data from */ - u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */ - int iHash; /* Used to loop through N hash tables */ - - /* This routine is only be called from within a read transaction. */ - assert( pWal->readLock>=0 || pWal->lockError ); - - /* If the "last page" field of the wal-index header snapshot is 0, then - ** no data will be read from the wal under any circumstances. Return early - ** in this case as an optimization. Likewise, if pWal->readLock==0, - ** then the WAL is ignored by the reader so return early, as if the - ** WAL were empty. - */ - if( iLast==0 || pWal->readLock==0 ){ - *piRead = 0; - return SQLITE_OK; - } - - /* Search the hash table or tables for an entry matching page number - ** pgno. Each iteration of the following for() loop searches one - ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames). - ** - ** This code might run concurrently to the code in walIndexAppend() - ** that adds entries to the wal-index (and possibly to this hash - ** table). This means the value just read from the hash - ** slot (aHash[iKey]) may have been added before or after the - ** current read transaction was opened. Values added after the - ** read transaction was opened may have been written incorrectly - - ** i.e. these slots may contain garbage data. However, we assume - ** that any slots written before the current read transaction was - ** opened remain unmodified. - ** - ** For the reasons above, the if(...) condition featured in the inner - ** loop of the following block is more stringent that would be required - ** if we had exclusive access to the hash-table: - ** - ** (aPgno[iFrame]==pgno): - ** This condition filters out normal hash-table collisions. - ** - ** (iFrame<=iLast): - ** This condition filters out entries that were added to the hash - ** table after the current read-transaction had started. - */ - for(iHash=walFramePage(iLast); iHash>=0 && iRead==0; iHash--){ - volatile ht_slot *aHash; /* Pointer to hash table */ - volatile u32 *aPgno; /* Pointer to array of page numbers */ - u32 iZero; /* Frame number corresponding to aPgno[0] */ - int iKey; /* Hash slot index */ - int nCollide; /* Number of hash collisions remaining */ - int rc; /* Error code */ - - rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero); - if( rc!=SQLITE_OK ){ - return rc; - } - nCollide = HASHTABLE_NSLOT; - for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ - u32 iFrame = aHash[iKey] + iZero; - if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ - /* assert( iFrame>iRead ); -- not true if there is corruption */ - iRead = iFrame; - } - if( (nCollide--)==0 ){ - return SQLITE_CORRUPT_BKPT; - } - } - } - -#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT - /* If expensive assert() statements are available, do a linear search - ** of the wal-index file content. Make sure the results agree with the - ** result obtained using the hash indexes above. */ - { - u32 iRead2 = 0; - u32 iTest; - for(iTest=iLast; iTest>0; iTest--){ - if( walFramePgno(pWal, iTest)==pgno ){ - iRead2 = iTest; - break; - } - } - assert( iRead==iRead2 ); - } -#endif - - *piRead = iRead; - return SQLITE_OK; -} - -/* -** Read the contents of frame iRead from the wal file into buffer pOut -** (which is nOut bytes in size). Return SQLITE_OK if successful, or an -** error code otherwise. -*/ -SQLITE_PRIVATE int sqlite3WalReadFrame( - Wal *pWal, /* WAL handle */ - u32 iRead, /* Frame to read */ - int nOut, /* Size of buffer pOut in bytes */ - u8 *pOut /* Buffer to write page data to */ -){ - int sz; - i64 iOffset; - sz = pWal->hdr.szPage; - sz = (sz&0xfe00) + ((sz&0x0001)<<16); - testcase( sz<=32768 ); - testcase( sz>=65536 ); - iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; - /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ - return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset); -} - -/* -** Return the size of the database in pages (or zero, if unknown). -*/ -SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){ - if( pWal && ALWAYS(pWal->readLock>=0) ){ - return pWal->hdr.nPage; - } - return 0; -} - - -/* -** This function starts a write transaction on the WAL. -** -** A read transaction must have already been started by a prior call -** to sqlite3WalBeginReadTransaction(). -** -** If another thread or process has written into the database since -** the read transaction was started, then it is not possible for this -** thread to write as doing so would cause a fork. So this routine -** returns SQLITE_BUSY in that case and no write transaction is started. -** -** There can only be a single writer active at a time. -*/ -SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){ - int rc; - - /* Cannot start a write transaction without first holding a read - ** transaction. */ - assert( pWal->readLock>=0 ); - - if( pWal->readOnly ){ - return SQLITE_READONLY; - } - - /* Only one writer allowed at a time. Get the write lock. Return - ** SQLITE_BUSY if unable. - */ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - if( rc ){ - return rc; - } - pWal->writeLock = 1; - - /* If another connection has written to the database file since the - ** time the read transaction on this connection was started, then - ** the write is disallowed. - */ - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; - rc = SQLITE_BUSY; - } - - return rc; -} - -/* -** End a write transaction. The commit has already been done. This -** routine merely releases the lock. -*/ -SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){ - if( pWal->writeLock ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; - pWal->truncateOnCommit = 0; - } - return SQLITE_OK; -} - -/* -** If any data has been written (but not committed) to the log file, this -** function moves the write-pointer back to the start of the transaction. -** -** Additionally, the callback function is invoked for each frame written -** to the WAL since the start of the transaction. If the callback returns -** other than SQLITE_OK, it is not invoked again and the error code is -** returned to the caller. -** -** Otherwise, if the callback function does not return an error, this -** function returns SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ - int rc = SQLITE_OK; - if( ALWAYS(pWal->writeLock) ){ - Pgno iMax = pWal->hdr.mxFrame; - Pgno iFrame; - - /* Restore the clients cache of the wal-index header to the state it - ** was in before the client began writing to the database. - */ - memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); - - for(iFrame=pWal->hdr.mxFrame+1; - ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; - iFrame++ - ){ - /* This call cannot fail. Unless the page for which the page number - ** is passed as the second argument is (a) in the cache and - ** (b) has an outstanding reference, then xUndo is either a no-op - ** (if (a) is false) or simply expels the page from the cache (if (b) - ** is false). - ** - ** If the upper layer is doing a rollback, it is guaranteed that there - ** are no outstanding references to any page other than page 1. And - ** page 1 is never written to the log until the transaction is - ** committed. As a result, the call to xUndo may not fail. - */ - assert( walFramePgno(pWal, iFrame)!=1 ); - rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); - } - if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); - } - assert( rc==SQLITE_OK ); - return rc; -} - -/* -** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 -** values. This function populates the array with values required to -** "rollback" the write position of the WAL handle back to the current -** point in the event of a savepoint rollback (via WalSavepointUndo()). -*/ -SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){ - assert( pWal->writeLock ); - aWalData[0] = pWal->hdr.mxFrame; - aWalData[1] = pWal->hdr.aFrameCksum[0]; - aWalData[2] = pWal->hdr.aFrameCksum[1]; - aWalData[3] = pWal->nCkpt; -} - -/* -** Move the write position of the WAL back to the point identified by -** the values in the aWalData[] array. aWalData must point to an array -** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated -** by a call to WalSavepoint(). -*/ -SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ - int rc = SQLITE_OK; - - assert( pWal->writeLock ); - assert( aWalData[3]!=pWal->nCkpt || aWalData[0]<=pWal->hdr.mxFrame ); - - if( aWalData[3]!=pWal->nCkpt ){ - /* This savepoint was opened immediately after the write-transaction - ** was started. Right after that, the writer decided to wrap around - ** to the start of the log. Update the savepoint values to match. - */ - aWalData[0] = 0; - aWalData[3] = pWal->nCkpt; - } - - if( aWalData[0]hdr.mxFrame ){ - pWal->hdr.mxFrame = aWalData[0]; - pWal->hdr.aFrameCksum[0] = aWalData[1]; - pWal->hdr.aFrameCksum[1] = aWalData[2]; - walCleanupHash(pWal); - } - - return rc; -} - - -/* -** This function is called just before writing a set of frames to the log -** file (see sqlite3WalFrames()). It checks to see if, instead of appending -** to the current log file, it is possible to overwrite the start of the -** existing log file with the new frames (i.e. "reset" the log). If so, -** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left -** unchanged. -** -** SQLITE_OK is returned if no error is encountered (regardless of whether -** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned -** if an error occurs. -*/ -static int walRestartLog(Wal *pWal){ - int rc = SQLITE_OK; - int cnt; - - if( pWal->readLock==0 ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - assert( pInfo->nBackfill==pWal->hdr.mxFrame ); - if( pInfo->nBackfill>0 ){ - u32 salt1; - sqlite3_randomness(4, &salt1); - rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); - if( rc==SQLITE_OK ){ - /* If all readers are using WAL_READ_LOCK(0) (in other words if no - ** readers are currently using the WAL), then the transactions - ** frames will overwrite the start of the existing log. Update the - ** wal-index header to reflect this. - ** - ** In theory it would be Ok to update the cache of the header only - ** at this point. But updating the actual wal-index header is also - ** safe and means there is no special case for sqlite3WalUndo() - ** to handle if this transaction is rolled back. - */ - int i; /* Loop counter */ - u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ - - pWal->nCkpt++; - pWal->hdr.mxFrame = 0; - sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); - aSalt[1] = salt1; - walIndexWriteHdr(pWal); - pInfo->nBackfill = 0; - pInfo->aReadMark[1] = 0; - for(i=2; iaReadMark[i] = READMARK_NOT_USED; - assert( pInfo->aReadMark[0]==0 ); - walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); - }else if( rc!=SQLITE_BUSY ){ - return rc; - } - } - walUnlockShared(pWal, WAL_READ_LOCK(0)); - pWal->readLock = -1; - cnt = 0; - do{ - int notUsed; - rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt); - }while( rc==WAL_RETRY ); - assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */ - testcase( (rc&0xff)==SQLITE_IOERR ); - testcase( rc==SQLITE_PROTOCOL ); - testcase( rc==SQLITE_OK ); - } - return rc; -} - -/* -** Information about the current state of the WAL file and where -** the next fsync should occur - passed from sqlite3WalFrames() into -** walWriteToLog(). -*/ -typedef struct WalWriter { - Wal *pWal; /* The complete WAL information */ - sqlite3_file *pFd; /* The WAL file to which we write */ - sqlite3_int64 iSyncPoint; /* Fsync at this offset */ - int syncFlags; /* Flags for the fsync */ - int szPage; /* Size of one page */ -} WalWriter; - -/* -** Write iAmt bytes of content into the WAL file beginning at iOffset. -** Do a sync when crossing the p->iSyncPoint boundary. -** -** In other words, if iSyncPoint is in between iOffset and iOffset+iAmt, -** first write the part before iSyncPoint, then sync, then write the -** rest. -*/ -static int walWriteToLog( - WalWriter *p, /* WAL to write to */ - void *pContent, /* Content to be written */ - int iAmt, /* Number of bytes to write */ - sqlite3_int64 iOffset /* Start writing at this offset */ -){ - int rc; - if( iOffsetiSyncPoint && iOffset+iAmt>=p->iSyncPoint ){ - int iFirstAmt = (int)(p->iSyncPoint - iOffset); - rc = sqlite3OsWrite(p->pFd, pContent, iFirstAmt, iOffset); - if( rc ) return rc; - iOffset += iFirstAmt; - iAmt -= iFirstAmt; - pContent = (void*)(iFirstAmt + (char*)pContent); - assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) ); - rc = sqlite3OsSync(p->pFd, p->syncFlags); - if( iAmt==0 || rc ) return rc; - } - rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset); - return rc; -} - -/* -** Write out a single frame of the WAL -*/ -static int walWriteOneFrame( - WalWriter *p, /* Where to write the frame */ - PgHdr *pPage, /* The page of the frame to be written */ - int nTruncate, /* The commit flag. Usually 0. >0 for commit */ - sqlite3_int64 iOffset /* Byte offset at which to write */ -){ - int rc; /* Result code from subfunctions */ - void *pData; /* Data actually written */ - u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ -#if defined(SQLITE_HAS_CODEC) - if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM; -#else - pData = pPage->pData; -#endif - walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame); - rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset); - if( rc ) return rc; - /* Write the page data */ - rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame)); - return rc; -} - -/* -** Write a set of frames to the log. The caller must hold the write-lock -** on the log file (obtained using sqlite3WalBeginWriteTransaction()). -*/ -SQLITE_PRIVATE int sqlite3WalFrames( - Wal *pWal, /* Wal handle to write to */ - int szPage, /* Database page-size in bytes */ - PgHdr *pList, /* List of dirty pages to write */ - Pgno nTruncate, /* Database size after this commit */ - int isCommit, /* True if this is a commit */ - int sync_flags /* Flags to pass to OsSync() (or 0) */ -){ - int rc; /* Used to catch return codes */ - u32 iFrame; /* Next frame address */ - PgHdr *p; /* Iterator to run through pList with. */ - PgHdr *pLast = 0; /* Last frame in list */ - int nExtra = 0; /* Number of extra copies of last page */ - int szFrame; /* The size of a single frame */ - i64 iOffset; /* Next byte to write in WAL file */ - WalWriter w; /* The writer */ - - assert( pList ); - assert( pWal->writeLock ); - - /* If this frame set completes a transaction, then nTruncate>0. If - ** nTruncate==0 then this frame set does not complete the transaction. */ - assert( (isCommit!=0)==(nTruncate!=0) ); - -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) - { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){} - WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n", - pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill")); - } -#endif - - /* See if it is possible to write these frames into the start of the - ** log file, instead of appending to it at pWal->hdr.mxFrame. - */ - if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){ - return rc; - } - - /* If this is the first frame written into the log, write the WAL - ** header to the start of the WAL file. See comments at the top of - ** this source file for a description of the WAL header format. - */ - iFrame = pWal->hdr.mxFrame; - if( iFrame==0 ){ - u8 aWalHdr[WAL_HDRSIZE]; /* Buffer to assemble wal-header in */ - u32 aCksum[2]; /* Checksum for wal-header */ - - sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN)); - sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION); - sqlite3Put4byte(&aWalHdr[8], szPage); - sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt); - if( pWal->nCkpt==0 ) sqlite3_randomness(8, pWal->hdr.aSalt); - memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8); - walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum); - sqlite3Put4byte(&aWalHdr[24], aCksum[0]); - sqlite3Put4byte(&aWalHdr[28], aCksum[1]); - - pWal->szPage = szPage; - pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN; - pWal->hdr.aFrameCksum[0] = aCksum[0]; - pWal->hdr.aFrameCksum[1] = aCksum[1]; - pWal->truncateOnCommit = 1; - - rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0); - WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok")); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Sync the header (unless SQLITE_IOCAP_SEQUENTIAL is true or unless - ** all syncing is turned off by PRAGMA synchronous=OFF). Otherwise - ** an out-of-order write following a WAL restart could result in - ** database corruption. See the ticket: - ** - ** http://localhost:591/sqlite/info/ff5be73dee - */ - if( pWal->syncHeader && sync_flags ){ - rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK); - if( rc ) return rc; - } - } - assert( (int)pWal->szPage==szPage ); - - /* Setup information needed to write frames into the WAL */ - w.pWal = pWal; - w.pFd = pWal->pWalFd; - w.iSyncPoint = 0; - w.syncFlags = sync_flags; - w.szPage = szPage; - iOffset = walFrameOffset(iFrame+1, szPage); - szFrame = szPage + WAL_FRAME_HDRSIZE; - - /* Write all frames into the log file exactly once */ - for(p=pList; p; p=p->pDirty){ - int nDbSize; /* 0 normally. Positive == commit flag */ - iFrame++; - assert( iOffset==walFrameOffset(iFrame, szPage) ); - nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0; - rc = walWriteOneFrame(&w, p, nDbSize, iOffset); - if( rc ) return rc; - pLast = p; - iOffset += szFrame; - } - - /* If this is the end of a transaction, then we might need to pad - ** the transaction and/or sync the WAL file. - ** - ** Padding and syncing only occur if this set of frames complete a - ** transaction and if PRAGMA synchronous=FULL. If synchronous==NORMAL - ** or synchonous==OFF, then no padding or syncing are needed. - ** - ** If SQLITE_IOCAP_POWERSAFE_OVERWRITE is defined, then padding is not - ** needed and only the sync is done. If padding is needed, then the - ** final frame is repeated (with its commit mark) until the next sector - ** boundary is crossed. Only the part of the WAL prior to the last - ** sector boundary is synced; the part of the last frame that extends - ** past the sector boundary is written after the sync. - */ - if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){ - if( pWal->padToSectorBoundary ){ - int sectorSize = sqlite3SectorSize(pWal->pWalFd); - w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize; - while( iOffsettruncateOnCommit && pWal->mxWalSize>=0 ){ - i64 sz = pWal->mxWalSize; - if( walFrameOffset(iFrame+nExtra+1, szPage)>pWal->mxWalSize ){ - sz = walFrameOffset(iFrame+nExtra+1, szPage); - } - walLimitSize(pWal, sz); - pWal->truncateOnCommit = 0; - } - - /* Append data to the wal-index. It is not necessary to lock the - ** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index - ** guarantees that there are no other writers, and no data that may - ** be in use by existing readers is being overwritten. - */ - iFrame = pWal->hdr.mxFrame; - for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){ - iFrame++; - rc = walIndexAppend(pWal, iFrame, p->pgno); - } - while( rc==SQLITE_OK && nExtra>0 ){ - iFrame++; - nExtra--; - rc = walIndexAppend(pWal, iFrame, pLast->pgno); - } - - if( rc==SQLITE_OK ){ - /* Update the private copy of the header. */ - pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16)); - testcase( szPage<=32768 ); - testcase( szPage>=65536 ); - pWal->hdr.mxFrame = iFrame; - if( isCommit ){ - pWal->hdr.iChange++; - pWal->hdr.nPage = nTruncate; - } - /* If this is a commit, update the wal-index header too. */ - if( isCommit ){ - walIndexWriteHdr(pWal); - pWal->iCallback = iFrame; - } - } - - WALTRACE(("WAL%p: frame write %s\n", pWal, rc ? "failed" : "ok")); - return rc; -} - -/* -** This routine is called to implement sqlite3_wal_checkpoint() and -** related interfaces. -** -** Obtain a CHECKPOINT lock and then backfill as much information as -** we can from WAL into the database. -** -** If parameter xBusy is not NULL, it is a pointer to a busy-handler -** callback. In this case this function runs a blocking checkpoint. -*/ -SQLITE_PRIVATE int sqlite3WalCheckpoint( - Wal *pWal, /* Wal connection */ - int eMode, /* PASSIVE, FULL or RESTART */ - int (*xBusy)(void*), /* Function to call when busy */ - void *pBusyArg, /* Context argument for xBusyHandler */ - int sync_flags, /* Flags to sync db file with (or 0) */ - int nBuf, /* Size of temporary buffer */ - u8 *zBuf, /* Temporary buffer to use */ - int *pnLog, /* OUT: Number of frames in WAL */ - int *pnCkpt /* OUT: Number of backfilled frames in WAL */ -){ - int rc; /* Return code */ - int isChanged = 0; /* True if a new wal-index header is loaded */ - int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ - - assert( pWal->ckptLock==0 ); - assert( pWal->writeLock==0 ); - - if( pWal->readOnly ) return SQLITE_READONLY; - WALTRACE(("WAL%p: checkpoint begins\n", pWal)); - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); - if( rc ){ - /* Usually this is SQLITE_BUSY meaning that another thread or process - ** is already running a checkpoint, or maybe a recovery. But it might - ** also be SQLITE_IOERR. */ - return rc; - } - pWal->ckptLock = 1; - - /* If this is a blocking-checkpoint, then obtain the write-lock as well - ** to prevent any writers from running while the checkpoint is underway. - ** This has to be done before the call to walIndexReadHdr() below. - ** - ** If the writer lock cannot be obtained, then a passive checkpoint is - ** run instead. Since the checkpointer is not holding the writer lock, - ** there is no point in blocking waiting for any readers. Assuming no - ** other error occurs, this function will return SQLITE_BUSY to the caller. - */ - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ - rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - }else if( rc==SQLITE_BUSY ){ - eMode2 = SQLITE_CHECKPOINT_PASSIVE; - rc = SQLITE_OK; - } - } - - /* Read the wal-index header. */ - if( rc==SQLITE_OK ){ - rc = walIndexReadHdr(pWal, &isChanged); - if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ - sqlite3OsUnfetch(pWal->pDbFd, 0, 0); - } - } - - /* Copy data from the log to the database file. */ - if( rc==SQLITE_OK ){ - if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf); - } - - /* If no error occurred, set the output variables. */ - if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ - if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; - if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); - } - } - - if( isChanged ){ - /* If a new wal-index header was loaded before the checkpoint was - ** performed, then the pager-cache associated with pWal is now - ** out of date. So zero the cached wal-index header to ensure that - ** next time the pager opens a snapshot on this database it knows that - ** the cache needs to be reset. - */ - memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); - } - - /* Release the locks. */ - sqlite3WalEndWriteTransaction(pWal); - walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); - pWal->ckptLock = 0; - WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); - return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); -} - -/* Return the value to pass to a sqlite3_wal_hook callback, the -** number of frames in the WAL at the point of the last commit since -** sqlite3WalCallback() was called. If no commits have occurred since -** the last call, then return 0. -*/ -SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal){ - u32 ret = 0; - if( pWal ){ - ret = pWal->iCallback; - pWal->iCallback = 0; - } - return (int)ret; -} - -/* -** This function is called to change the WAL subsystem into or out -** of locking_mode=EXCLUSIVE. -** -** If op is zero, then attempt to change from locking_mode=EXCLUSIVE -** into locking_mode=NORMAL. This means that we must acquire a lock -** on the pWal->readLock byte. If the WAL is already in locking_mode=NORMAL -** or if the acquisition of the lock fails, then return 0. If the -** transition out of exclusive-mode is successful, return 1. This -** operation must occur while the pager is still holding the exclusive -** lock on the main database file. -** -** If op is one, then change from locking_mode=NORMAL into -** locking_mode=EXCLUSIVE. This means that the pWal->readLock must -** be released. Return 1 if the transition is made and 0 if the -** WAL is already in exclusive-locking mode - meaning that this -** routine is a no-op. The pager must already hold the exclusive lock -** on the main database file before invoking this operation. -** -** If op is negative, then do a dry-run of the op==1 case but do -** not actually change anything. The pager uses this to see if it -** should acquire the database exclusive lock prior to invoking -** the op==1 case. -*/ -SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){ - int rc; - assert( pWal->writeLock==0 ); - assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 ); - - /* pWal->readLock is usually set, but might be -1 if there was a - ** prior error while attempting to acquire are read-lock. This cannot - ** happen if the connection is actually in exclusive mode (as no xShmLock - ** locks are taken in this case). Nor should the pager attempt to - ** upgrade to exclusive-mode following such an error. - */ - assert( pWal->readLock>=0 || pWal->lockError ); - assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); - - if( op==0 ){ - if( pWal->exclusiveMode ){ - pWal->exclusiveMode = 0; - if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){ - pWal->exclusiveMode = 1; - } - rc = pWal->exclusiveMode==0; - }else{ - /* Already in locking_mode=NORMAL */ - rc = 0; - } - }else if( op>0 ){ - assert( pWal->exclusiveMode==0 ); - assert( pWal->readLock>=0 ); - walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); - pWal->exclusiveMode = 1; - rc = 1; - }else{ - rc = pWal->exclusiveMode==0; - } - return rc; -} - -/* -** Return true if the argument is non-NULL and the WAL module is using -** heap-memory for the wal-index. Otherwise, if the argument is NULL or the -** WAL module is using shared-memory, return false. -*/ -SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ - return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); -} - -#ifdef SQLITE_ENABLE_ZIPVFS -/* -** If the argument is not NULL, it points to a Wal object that holds a -** read-lock. This function returns the database page-size if it is known, -** or zero if it is not (or if pWal is NULL). -*/ -SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){ - assert( pWal==0 || pWal->readLock>=0 ); - return (pWal ? pWal->szPage : 0); -} -#endif - -#endif /* #ifndef SQLITE_OMIT_WAL */ - -/************** End of wal.c *************************************************/ -/************** Begin file btmutex.c *****************************************/ -/* -** 2007 August 27 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code used to implement mutexes on Btree objects. -** This code really belongs in btree.c. But btree.c is getting too -** big and we want to break it down some. This packaged seemed like -** a good breakout. -*/ -/************** Include btreeInt.h in the middle of btmutex.c ****************/ -/************** Begin file btreeInt.h ****************************************/ -/* -** 2004 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file implements a external (disk-based) database using BTrees. -** For a detailed discussion of BTrees, refer to -** -** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: -** "Sorting And Searching", pages 473-480. Addison-Wesley -** Publishing Company, Reading, Massachusetts. -** -** The basic idea is that each page of the file contains N database -** entries and N+1 pointers to subpages. -** -** ---------------------------------------------------------------- -** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) | -** ---------------------------------------------------------------- -** -** All of the keys on the page that Ptr(0) points to have values less -** than Key(0). All of the keys on page Ptr(1) and its subpages have -** values greater than Key(0) and less than Key(1). All of the keys -** on Ptr(N) and its subpages have values greater than Key(N-1). And -** so forth. -** -** Finding a particular key requires reading O(log(M)) pages from the -** disk where M is the number of entries in the tree. -** -** In this implementation, a single file can hold one or more separate -** BTrees. Each BTree is identified by the index of its root page. The -** key and data for any entry are combined to form the "payload". A -** fixed amount of payload can be carried directly on the database -** page. If the payload is larger than the preset amount then surplus -** bytes are stored on overflow pages. The payload for an entry -** and the preceding pointer are combined to form a "Cell". Each -** page has a small header which contains the Ptr(N) pointer and other -** information such as the size of key and data. -** -** FORMAT DETAILS -** -** The file is divided into pages. The first page is called page 1, -** the second is page 2, and so forth. A page number of zero indicates -** "no such page". The page size can be any power of 2 between 512 and 65536. -** Each page can be either a btree page, a freelist page, an overflow -** page, or a pointer-map page. -** -** The first page is always a btree page. The first 100 bytes of the first -** page contain a special header (the "file header") that describes the file. -** The format of the file header is as follows: -** -** OFFSET SIZE DESCRIPTION -** 0 16 Header string: "SQLite format 3\000" -** 16 2 Page size in bytes. -** 18 1 File format write version -** 19 1 File format read version -** 20 1 Bytes of unused space at the end of each page -** 21 1 Max embedded payload fraction -** 22 1 Min embedded payload fraction -** 23 1 Min leaf payload fraction -** 24 4 File change counter -** 28 4 Reserved for future use -** 32 4 First freelist page -** 36 4 Number of freelist pages in the file -** 40 60 15 4-byte meta values passed to higher layers -** -** 40 4 Schema cookie -** 44 4 File format of schema layer -** 48 4 Size of page cache -** 52 4 Largest root-page (auto/incr_vacuum) -** 56 4 1=UTF-8 2=UTF16le 3=UTF16be -** 60 4 User version -** 64 4 Incremental vacuum mode -** 68 4 unused -** 72 4 unused -** 76 4 unused -** -** All of the integer values are big-endian (most significant byte first). -** -** The file change counter is incremented when the database is changed -** This counter allows other processes to know when the file has changed -** and thus when they need to flush their cache. -** -** The max embedded payload fraction is the amount of the total usable -** space in a page that can be consumed by a single cell for standard -** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default -** is to limit the maximum cell size so that at least 4 cells will fit -** on one page. Thus the default max embedded payload fraction is 64. -** -** If the payload for a cell is larger than the max payload, then extra -** payload is spilled to overflow pages. Once an overflow page is allocated, -** as many bytes as possible are moved into the overflow pages without letting -** the cell size drop below the min embedded payload fraction. -** -** The min leaf payload fraction is like the min embedded payload fraction -** except that it applies to leaf nodes in a LEAFDATA tree. The maximum -** payload fraction for a LEAFDATA tree is always 100% (or 255) and it -** not specified in the header. -** -** Each btree pages is divided into three sections: The header, the -** cell pointer array, and the cell content area. Page 1 also has a 100-byte -** file header that occurs before the page header. -** -** |----------------| -** | file header | 100 bytes. Page 1 only. -** |----------------| -** | page header | 8 bytes for leaves. 12 bytes for interior nodes -** |----------------| -** | cell pointer | | 2 bytes per cell. Sorted order. -** | array | | Grows downward -** | | v -** |----------------| -** | unallocated | -** | space | -** |----------------| ^ Grows upwards -** | cell content | | Arbitrary order interspersed with freeblocks. -** | area | | and free space fragments. -** |----------------| -** -** The page headers looks like this: -** -** OFFSET SIZE DESCRIPTION -** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf -** 1 2 byte offset to the first freeblock -** 3 2 number of cells on this page -** 5 2 first byte of the cell content area -** 7 1 number of fragmented free bytes -** 8 4 Right child (the Ptr(N) value). Omitted on leaves. -** -** The flags define the format of this btree page. The leaf flag means that -** this page has no children. The zerodata flag means that this page carries -** only keys and no data. The intkey flag means that the key is a integer -** which is stored in the key size entry of the cell header rather than in -** the payload area. -** -** The cell pointer array begins on the first byte after the page header. -** The cell pointer array contains zero or more 2-byte numbers which are -** offsets from the beginning of the page to the cell content in the cell -** content area. The cell pointers occur in sorted order. The system strives -** to keep free space after the last cell pointer so that new cells can -** be easily added without having to defragment the page. -** -** Cell content is stored at the very end of the page and grows toward the -** beginning of the page. -** -** Unused space within the cell content area is collected into a linked list of -** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset -** to the first freeblock is given in the header. Freeblocks occur in -** increasing order. Because a freeblock must be at least 4 bytes in size, -** any group of 3 or fewer unused bytes in the cell content area cannot -** exist on the freeblock chain. A group of 3 or fewer free bytes is called -** a fragment. The total number of bytes in all fragments is recorded. -** in the page header at offset 7. -** -** SIZE DESCRIPTION -** 2 Byte offset of the next freeblock -** 2 Bytes in this freeblock -** -** Cells are of variable length. Cells are stored in the cell content area at -** the end of the page. Pointers to the cells are in the cell pointer array -** that immediately follows the page header. Cells is not necessarily -** contiguous or in order, but cell pointers are contiguous and in order. -** -** Cell content makes use of variable length integers. A variable -** length integer is 1 to 9 bytes where the lower 7 bits of each -** byte are used. The integer consists of all bytes that have bit 8 set and -** the first byte with bit 8 clear. The most significant byte of the integer -** appears first. A variable-length integer may not be more than 9 bytes long. -** As a special case, all 8 bytes of the 9th byte are used as data. This -** allows a 64-bit integer to be encoded in 9 bytes. -** -** 0x00 becomes 0x00000000 -** 0x7f becomes 0x0000007f -** 0x81 0x00 becomes 0x00000080 -** 0x82 0x00 becomes 0x00000100 -** 0x80 0x7f becomes 0x0000007f -** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 -** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081 -** -** Variable length integers are used for rowids and to hold the number of -** bytes of key and data in a btree cell. -** -** The content of a cell looks like this: -** -** SIZE DESCRIPTION -** 4 Page number of the left child. Omitted if leaf flag is set. -** var Number of bytes of data. Omitted if the zerodata flag is set. -** var Number of bytes of key. Or the key itself if intkey flag is set. -** * Payload -** 4 First page of the overflow chain. Omitted if no overflow -** -** Overflow pages form a linked list. Each page except the last is completely -** filled with data (pagesize - 4 bytes). The last page can have as little -** as 1 byte of data. -** -** SIZE DESCRIPTION -** 4 Page number of next overflow page -** * Data -** -** Freelist pages come in two subtypes: trunk pages and leaf pages. The -** file header points to the first in a linked list of trunk page. Each trunk -** page points to multiple leaf pages. The content of a leaf page is -** unspecified. A trunk page looks like this: -** -** SIZE DESCRIPTION -** 4 Page number of next trunk page -** 4 Number of leaf pointers on this page -** * zero or more pages numbers of leaves -*/ - - -/* The following value is the maximum cell size assuming a maximum page -** size give above. -*/ -#define MX_CELL_SIZE(pBt) ((int)(pBt->pageSize-8)) - -/* The maximum number of cells on a single page of the database. This -** assumes a minimum cell size of 6 bytes (4 bytes for the cell itself -** plus 2 bytes for the index to the cell in the page header). Such -** small cells will be rare, but they are possible. -*/ -#define MX_CELL(pBt) ((pBt->pageSize-8)/6) - -/* Forward declarations */ -typedef struct MemPage MemPage; -typedef struct BtLock BtLock; - -/* -** This is a magic string that appears at the beginning of every -** SQLite database in order to identify the file as a real database. -** -** You can change this value at compile-time by specifying a -** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The -** header must be exactly 16 bytes including the zero-terminator so -** the string itself should be 15 characters long. If you change -** the header, then your custom library will not be able to read -** databases generated by the standard tools and the standard tools -** will not be able to read databases created by your custom library. -*/ -#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */ -# define SQLITE_FILE_HEADER "SQLite format 3" -#endif - -/* -** Page type flags. An ORed combination of these flags appear as the -** first byte of on-disk image of every BTree page. -*/ -#define PTF_INTKEY 0x01 -#define PTF_ZERODATA 0x02 -#define PTF_LEAFDATA 0x04 -#define PTF_LEAF 0x08 - -/* -** As each page of the file is loaded into memory, an instance of the following -** structure is appended and initialized to zero. This structure stores -** information about the page that is decoded from the raw file page. -** -** The pParent field points back to the parent page. This allows us to -** walk up the BTree from any leaf to the root. Care must be taken to -** unref() the parent page pointer when this page is no longer referenced. -** The pageDestructor() routine handles that chore. -** -** Access to all fields of this structure is controlled by the mutex -** stored in MemPage.pBt->mutex. -*/ -struct MemPage { - u8 isInit; /* True if previously initialized. MUST BE FIRST! */ - u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ - u8 intKey; /* True if intkey flag is set */ - u8 leaf; /* True if leaf flag is set */ - u8 hasData; /* True if this page stores data */ - u8 hdrOffset; /* 100 for page 1. 0 otherwise */ - u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ - u8 max1bytePayload; /* min(maxLocal,127) */ - u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ - u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ - u16 cellOffset; /* Index in aData of first cell pointer */ - u16 nFree; /* Number of free bytes on the page */ - u16 nCell; /* Number of cells on this page, local and ovfl */ - u16 maskPage; /* Mask for page offset */ - u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th - ** non-overflow cell */ - u8 *apOvfl[5]; /* Pointers to the body of overflow cells */ - BtShared *pBt; /* Pointer to BtShared that this page is part of */ - u8 *aData; /* Pointer to disk image of the page data */ - u8 *aDataEnd; /* One byte past the end of usable data */ - u8 *aCellIdx; /* The cell index area */ - DbPage *pDbPage; /* Pager page handle */ - Pgno pgno; /* Page number for this page */ -}; - -/* -** The in-memory image of a disk page has the auxiliary information appended -** to the end. EXTRA_SIZE is the number of bytes of space needed to hold -** that extra information. -*/ -#define EXTRA_SIZE sizeof(MemPage) - -/* -** A linked list of the following structures is stored at BtShared.pLock. -** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor -** is opened on the table with root page BtShared.iTable. Locks are removed -** from this list when a transaction is committed or rolled back, or when -** a btree handle is closed. -*/ -struct BtLock { - Btree *pBtree; /* Btree handle holding this lock */ - Pgno iTable; /* Root page of table */ - u8 eLock; /* READ_LOCK or WRITE_LOCK */ - BtLock *pNext; /* Next in BtShared.pLock list */ -}; - -/* Candidate values for BtLock.eLock */ -#define READ_LOCK 1 -#define WRITE_LOCK 2 - -/* A Btree handle -** -** A database connection contains a pointer to an instance of -** this object for every database file that it has open. This structure -** is opaque to the database connection. The database connection cannot -** see the internals of this structure and only deals with pointers to -** this structure. -** -** For some database files, the same underlying database cache might be -** shared between multiple connections. In that case, each connection -** has it own instance of this object. But each instance of this object -** points to the same BtShared object. The database cache and the -** schema associated with the database file are all contained within -** the BtShared object. -** -** All fields in this structure are accessed under sqlite3.mutex. -** The pBt pointer itself may not be changed while there exists cursors -** in the referenced BtShared that point back to this Btree since those -** cursors have to go through this Btree to find their BtShared and -** they often do so without holding sqlite3.mutex. -*/ -struct Btree { - sqlite3 *db; /* The database connection holding this btree */ - BtShared *pBt; /* Sharable content of this btree */ - u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ - u8 sharable; /* True if we can share pBt with another db */ - u8 locked; /* True if db currently has pBt locked */ - int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ - int nBackup; /* Number of backup operations reading this btree */ - Btree *pNext; /* List of other sharable Btrees from the same db */ - Btree *pPrev; /* Back pointer of the same list */ -#ifndef SQLITE_OMIT_SHARED_CACHE - BtLock lock; /* Object used to lock page 1 */ -#endif -}; - -/* -** Btree.inTrans may take one of the following values. -** -** If the shared-data extension is enabled, there may be multiple users -** of the Btree structure. At most one of these may open a write transaction, -** but any number may have active read transactions. -*/ -#define TRANS_NONE 0 -#define TRANS_READ 1 -#define TRANS_WRITE 2 - -/* -** An instance of this object represents a single database file. -** -** A single database file can be in use at the same time by two -** or more database connections. When two or more connections are -** sharing the same database file, each connection has it own -** private Btree object for the file and each of those Btrees points -** to this one BtShared object. BtShared.nRef is the number of -** connections currently sharing this database file. -** -** Fields in this structure are accessed under the BtShared.mutex -** mutex, except for nRef and pNext which are accessed under the -** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field -** may not be modified once it is initially set as long as nRef>0. -** The pSchema field may be set once under BtShared.mutex and -** thereafter is unchanged as long as nRef>0. -** -** isPending: -** -** If a BtShared client fails to obtain a write-lock on a database -** table (because there exists one or more read-locks on the table), -** the shared-cache enters 'pending-lock' state and isPending is -** set to true. -** -** The shared-cache leaves the 'pending lock' state when either of -** the following occur: -** -** 1) The current writer (BtShared.pWriter) concludes its transaction, OR -** 2) The number of locks held by other connections drops to zero. -** -** while in the 'pending-lock' state, no connection may start a new -** transaction. -** -** This feature is included to help prevent writer-starvation. -*/ -struct BtShared { - Pager *pPager; /* The page cache */ - sqlite3 *db; /* Database connection currently using this Btree */ - BtCursor *pCursor; /* A list of all open cursors */ - MemPage *pPage1; /* First page of the database */ - u8 openFlags; /* Flags to sqlite3BtreeOpen() */ -#ifndef SQLITE_OMIT_AUTOVACUUM - u8 autoVacuum; /* True if auto-vacuum is enabled */ - u8 incrVacuum; /* True if incr-vacuum is enabled */ - u8 bDoTruncate; /* True to truncate db on commit */ -#endif - u8 inTransaction; /* Transaction state */ - u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ - u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ - u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ - u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ - u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */ - u16 minLeaf; /* Minimum local payload in a LEAFDATA table */ - u32 pageSize; /* Total number of bytes on a page */ - u32 usableSize; /* Number of usable bytes on each page */ - int nTransaction; /* Number of open transactions (read + write) */ - u32 nPage; /* Number of pages in the database */ - void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ - void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ - sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */ - Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */ -#ifndef SQLITE_OMIT_SHARED_CACHE - int nRef; /* Number of references to this structure */ - BtShared *pNext; /* Next on a list of sharable BtShared structs */ - BtLock *pLock; /* List of locks held on this shared-btree struct */ - Btree *pWriter; /* Btree with currently open write transaction */ -#endif - u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */ -}; - -/* -** Allowed values for BtShared.btsFlags -*/ -#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */ -#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */ -#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */ -#define BTS_INITIALLY_EMPTY 0x0008 /* Database was empty at trans start */ -#define BTS_NO_WAL 0x0010 /* Do not open write-ahead-log files */ -#define BTS_EXCLUSIVE 0x0020 /* pWriter has an exclusive lock */ -#define BTS_PENDING 0x0040 /* Waiting for read-locks to clear */ - -/* -** An instance of the following structure is used to hold information -** about a cell. The parseCellPtr() function fills in this structure -** based on information extract from the raw disk page. -*/ -typedef struct CellInfo CellInfo; -struct CellInfo { - i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ - u8 *pCell; /* Pointer to the start of cell content */ - u32 nData; /* Number of bytes of data */ - u32 nPayload; /* Total amount of payload */ - u16 nHeader; /* Size of the cell content header in bytes */ - u16 nLocal; /* Amount of payload held locally */ - u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */ - u16 nSize; /* Size of the cell content on the main b-tree page */ -}; - -/* -** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than -** this will be declared corrupt. This value is calculated based on a -** maximum database size of 2^31 pages a minimum fanout of 2 for a -** root-node and 3 for all other internal nodes. -** -** If a tree that appears to be taller than this is encountered, it is -** assumed that the database is corrupt. -*/ -#define BTCURSOR_MAX_DEPTH 20 - -/* -** A cursor is a pointer to a particular entry within a particular -** b-tree within a database file. -** -** The entry is identified by its MemPage and the index in -** MemPage.aCell[] of the entry. -** -** A single database file can be shared by two more database connections, -** but cursors cannot be shared. Each cursor is associated with a -** particular database connection identified BtCursor.pBtree.db. -** -** Fields in this structure are accessed under the BtShared.mutex -** found at self->pBt->mutex. -*/ -struct BtCursor { - Btree *pBtree; /* The Btree to which this cursor belongs */ - BtShared *pBt; /* The BtShared this cursor points to */ - BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ - struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ -#ifndef SQLITE_OMIT_INCRBLOB - Pgno *aOverflow; /* Cache of overflow page locations */ -#endif - Pgno pgnoRoot; /* The root page of this tree */ - sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */ - CellInfo info; /* A parse of the cell we are pointing at */ - i64 nKey; /* Size of pKey, or last integer key */ - void *pKey; /* Saved key that was cursor's last known position */ - int skipNext; /* Prev() is noop if negative. Next() is noop if positive */ - u8 wrFlag; /* True if writable */ - u8 atLast; /* Cursor pointing to the last entry */ - u8 validNKey; /* True if info.nKey is valid */ - u8 eState; /* One of the CURSOR_XXX constants (see below) */ -#ifndef SQLITE_OMIT_INCRBLOB - u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ -#endif - u8 hints; /* As configured by CursorSetHints() */ - i16 iPage; /* Index of current page in apPage */ - u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ - MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ -}; - -/* -** Potential values for BtCursor.eState. -** -** CURSOR_VALID: -** Cursor points to a valid entry. getPayload() etc. may be called. -** -** CURSOR_INVALID: -** Cursor does not point to a valid entry. This can happen (for example) -** because the table is empty or because BtreeCursorFirst() has not been -** called. -** -** CURSOR_REQUIRESEEK: -** The table that this cursor was opened on still exists, but has been -** modified since the cursor was last used. The cursor position is saved -** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in -** this state, restoreCursorPosition() can be called to attempt to -** seek the cursor to the saved position. -** -** CURSOR_FAULT: -** A unrecoverable error (an I/O error or a malloc failure) has occurred -** on a different connection that shares the BtShared cache with this -** cursor. The error has left the cache in an inconsistent state. -** Do nothing else with this cursor. Any attempt to use the cursor -** should return the error code stored in BtCursor.skip -*/ -#define CURSOR_INVALID 0 -#define CURSOR_VALID 1 -#define CURSOR_REQUIRESEEK 2 -#define CURSOR_FAULT 3 - -/* -** The database page the PENDING_BYTE occupies. This page is never used. -*/ -# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt) - -/* -** These macros define the location of the pointer-map entry for a -** database page. The first argument to each is the number of usable -** bytes on each page of the database (often 1024). The second is the -** page number to look up in the pointer map. -** -** PTRMAP_PAGENO returns the database page number of the pointer-map -** page that stores the required pointer. PTRMAP_PTROFFSET returns -** the offset of the requested map entry. -** -** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page, -** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be -** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements -** this test. -*/ -#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno) -#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1)) -#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno)) - -/* -** The pointer map is a lookup table that identifies the parent page for -** each child page in the database file. The parent page is the page that -** contains a pointer to the child. Every page in the database contains -** 0 or 1 parent pages. (In this context 'database page' refers -** to any page that is not part of the pointer map itself.) Each pointer map -** entry consists of a single byte 'type' and a 4 byte parent page number. -** The PTRMAP_XXX identifiers below are the valid types. -** -** The purpose of the pointer map is to facility moving pages from one -** position in the file to another as part of autovacuum. When a page -** is moved, the pointer in its parent must be updated to point to the -** new location. The pointer map is used to locate the parent page quickly. -** -** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not -** used in this case. -** -** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number -** is not used in this case. -** -** PTRMAP_OVERFLOW1: The database page is the first page in a list of -** overflow pages. The page number identifies the page that -** contains the cell with a pointer to this overflow page. -** -** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of -** overflow pages. The page-number identifies the previous -** page in the overflow page list. -** -** PTRMAP_BTREE: The database page is a non-root btree page. The page number -** identifies the parent page in the btree. -*/ -#define PTRMAP_ROOTPAGE 1 -#define PTRMAP_FREEPAGE 2 -#define PTRMAP_OVERFLOW1 3 -#define PTRMAP_OVERFLOW2 4 -#define PTRMAP_BTREE 5 - -/* A bunch of assert() statements to check the transaction state variables -** of handle p (type Btree*) are internally consistent. -*/ -#define btreeIntegrity(p) \ - assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \ - assert( p->pBt->inTransaction>=p->inTrans ); - - -/* -** The ISAUTOVACUUM macro is used within balance_nonroot() to determine -** if the database supports auto-vacuum or not. Because it is used -** within an expression that is an argument to another macro -** (sqliteMallocRaw), it is not possible to use conditional compilation. -** So, this macro is defined instead. -*/ -#ifndef SQLITE_OMIT_AUTOVACUUM -#define ISAUTOVACUUM (pBt->autoVacuum) -#else -#define ISAUTOVACUUM 0 -#endif - - -/* -** This structure is passed around through all the sanity checking routines -** in order to keep track of some global state information. -** -** The aRef[] array is allocated so that there is 1 bit for each page in -** the database. As the integrity-check proceeds, for each page used in -** the database the corresponding bit is set. This allows integrity-check to -** detect pages that are used twice and orphaned pages (both of which -** indicate corruption). -*/ -typedef struct IntegrityCk IntegrityCk; -struct IntegrityCk { - BtShared *pBt; /* The tree being checked out */ - Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ - u8 *aPgRef; /* 1 bit per page in the db (see above) */ - Pgno nPage; /* Number of pages in the database */ - int mxErr; /* Stop accumulating errors when this reaches zero */ - int nErr; /* Number of messages written to zErrMsg so far */ - int mallocFailed; /* A memory allocation error has occurred */ - StrAccum errMsg; /* Accumulate the error message text here */ -}; - -/* -** Routines to read or write a two- and four-byte big-endian integer values. -*/ -#define get2byte(x) ((x)[0]<<8 | (x)[1]) -#define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v)) -#define get4byte sqlite3Get4byte -#define put4byte sqlite3Put4byte - -/************** End of btreeInt.h ********************************************/ -/************** Continuing where we left off in btmutex.c ********************/ -#ifndef SQLITE_OMIT_SHARED_CACHE -#if SQLITE_THREADSAFE - -/* -** Obtain the BtShared mutex associated with B-Tree handle p. Also, -** set BtShared.db to the database handle associated with p and the -** p->locked boolean to true. -*/ -static void lockBtreeMutex(Btree *p){ - assert( p->locked==0 ); - assert( sqlite3_mutex_notheld(p->pBt->mutex) ); - assert( sqlite3_mutex_held(p->db->mutex) ); - - sqlite3_mutex_enter(p->pBt->mutex); - p->pBt->db = p->db; - p->locked = 1; -} - -/* -** Release the BtShared mutex associated with B-Tree handle p and -** clear the p->locked boolean. -*/ -static void unlockBtreeMutex(Btree *p){ - BtShared *pBt = p->pBt; - assert( p->locked==1 ); - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( sqlite3_mutex_held(p->db->mutex) ); - assert( p->db==pBt->db ); - - sqlite3_mutex_leave(pBt->mutex); - p->locked = 0; -} - -/* -** Enter a mutex on the given BTree object. -** -** If the object is not sharable, then no mutex is ever required -** and this routine is a no-op. The underlying mutex is non-recursive. -** But we keep a reference count in Btree.wantToLock so the behavior -** of this interface is recursive. -** -** To avoid deadlocks, multiple Btrees are locked in the same order -** by all database connections. The p->pNext is a list of other -** Btrees belonging to the same database connection as the p Btree -** which need to be locked after p. If we cannot get a lock on -** p, then first unlock all of the others on p->pNext, then wait -** for the lock to become available on p, then relock all of the -** subsequent Btrees that desire a lock. -*/ -SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ - Btree *pLater; - - /* Some basic sanity checking on the Btree. The list of Btrees - ** connected by pNext and pPrev should be in sorted order by - ** Btree.pBt value. All elements of the list should belong to - ** the same connection. Only shared Btrees are on the list. */ - assert( p->pNext==0 || p->pNext->pBt>p->pBt ); - assert( p->pPrev==0 || p->pPrev->pBtpBt ); - assert( p->pNext==0 || p->pNext->db==p->db ); - assert( p->pPrev==0 || p->pPrev->db==p->db ); - assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); - - /* Check for locking consistency */ - assert( !p->locked || p->wantToLock>0 ); - assert( p->sharable || p->wantToLock==0 ); - - /* We should already hold a lock on the database connection */ - assert( sqlite3_mutex_held(p->db->mutex) ); - - /* Unless the database is sharable and unlocked, then BtShared.db - ** should already be set correctly. */ - assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db ); - - if( !p->sharable ) return; - p->wantToLock++; - if( p->locked ) return; - - /* In most cases, we should be able to acquire the lock we - ** want without having to go throught the ascending lock - ** procedure that follows. Just be sure not to block. - */ - if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ - p->pBt->db = p->db; - p->locked = 1; - return; - } - - /* To avoid deadlock, first release all locks with a larger - ** BtShared address. Then acquire our lock. Then reacquire - ** the other BtShared locks that we used to hold in ascending - ** order. - */ - for(pLater=p->pNext; pLater; pLater=pLater->pNext){ - assert( pLater->sharable ); - assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); - assert( !pLater->locked || pLater->wantToLock>0 ); - if( pLater->locked ){ - unlockBtreeMutex(pLater); - } - } - lockBtreeMutex(p); - for(pLater=p->pNext; pLater; pLater=pLater->pNext){ - if( pLater->wantToLock ){ - lockBtreeMutex(pLater); - } - } -} - -/* -** Exit the recursive mutex on a Btree. -*/ -SQLITE_PRIVATE void sqlite3BtreeLeave(Btree *p){ - if( p->sharable ){ - assert( p->wantToLock>0 ); - p->wantToLock--; - if( p->wantToLock==0 ){ - unlockBtreeMutex(p); - } - } -} - -#ifndef NDEBUG -/* -** Return true if the BtShared mutex is held on the btree, or if the -** B-Tree is not marked as sharable. -** -** This routine is used only from within assert() statements. -*/ -SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){ - assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 ); - assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db ); - assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) ); - assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) ); - - return (p->sharable==0 || p->locked); -} -#endif - - -#ifndef SQLITE_OMIT_INCRBLOB -/* -** Enter and leave a mutex on a Btree given a cursor owned by that -** Btree. These entry points are used by incremental I/O and can be -** omitted if that module is not used. -*/ -SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){ - sqlite3BtreeEnter(pCur->pBtree); -} -SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){ - sqlite3BtreeLeave(pCur->pBtree); -} -#endif /* SQLITE_OMIT_INCRBLOB */ - - -/* -** Enter the mutex on every Btree associated with a database -** connection. This is needed (for example) prior to parsing -** a statement since we will be comparing table and column names -** against all schemas and we do not want those schemas being -** reset out from under us. -** -** There is a corresponding leave-all procedures. -** -** Enter the mutexes in accending order by BtShared pointer address -** to avoid the possibility of deadlock when two threads with -** two or more btrees in common both try to lock all their btrees -** at the same instant. -*/ -SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ - int i; - Btree *p; - assert( sqlite3_mutex_held(db->mutex) ); - for(i=0; inDb; i++){ - p = db->aDb[i].pBt; - if( p ) sqlite3BtreeEnter(p); - } -} -SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ - int i; - Btree *p; - assert( sqlite3_mutex_held(db->mutex) ); - for(i=0; inDb; i++){ - p = db->aDb[i].pBt; - if( p ) sqlite3BtreeLeave(p); - } -} - -/* -** Return true if a particular Btree requires a lock. Return FALSE if -** no lock is ever required since it is not sharable. -*/ -SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){ - return p->sharable; -} - -#ifndef NDEBUG -/* -** Return true if the current thread holds the database connection -** mutex and all required BtShared mutexes. -** -** This routine is used inside assert() statements only. -*/ -SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ - int i; - if( !sqlite3_mutex_held(db->mutex) ){ - return 0; - } - for(i=0; inDb; i++){ - Btree *p; - p = db->aDb[i].pBt; - if( p && p->sharable && - (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){ - return 0; - } - } - return 1; -} -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* -** Return true if the correct mutexes are held for accessing the -** db->aDb[iDb].pSchema structure. The mutexes required for schema -** access are: -** -** (1) The mutex on db -** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt. -** -** If pSchema is not NULL, then iDb is computed from pSchema and -** db using sqlite3SchemaToIndex(). -*/ -SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ - Btree *p; - assert( db!=0 ); - if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema); - assert( iDb>=0 && iDbnDb ); - if( !sqlite3_mutex_held(db->mutex) ) return 0; - if( iDb==1 ) return 1; - p = db->aDb[iDb].pBt; - assert( p!=0 ); - return p->sharable==0 || p->locked==1; -} -#endif /* NDEBUG */ - -#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */ -/* -** The following are special cases for mutex enter routines for use -** in single threaded applications that use shared cache. Except for -** these two routines, all mutex operations are no-ops in that case and -** are null #defines in btree.h. -** -** If shared cache is disabled, then all btree mutex routines, including -** the ones below, are no-ops and are null #defines in btree.h. -*/ - -SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ - p->pBt->db = p->db; -} -SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ - int i; - for(i=0; inDb; i++){ - Btree *p = db->aDb[i].pBt; - if( p ){ - p->pBt->db = p->db; - } - } -} -#endif /* if SQLITE_THREADSAFE */ -#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ - -/************** End of btmutex.c *********************************************/ -/************** Begin file btree.c *******************************************/ -/* -** 2004 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file implements a external (disk-based) database using BTrees. -** See the header comment on "btreeInt.h" for additional information. -** Including a description of file format and an overview of operation. -*/ - -/* -** The header string that appears at the beginning of every -** SQLite database. -*/ -static const char zMagicHeader[] = SQLITE_FILE_HEADER; - -/* -** Set this global variable to 1 to enable tracing using the TRACE -** macro. -*/ -#if 0 -int sqlite3BtreeTrace=1; /* True to enable tracing */ -# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);} -#else -# define TRACE(X) -#endif - -/* -** Extract a 2-byte big-endian integer from an array of unsigned bytes. -** But if the value is zero, make it 65536. -** -** This routine is used to extract the "offset to cell content area" value -** from the header of a btree page. If the page size is 65536 and the page -** is empty, the offset should be 65536, but the 2-byte value stores zero. -** This routine makes the necessary adjustment to 65536. -*/ -#define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1) - -/* -** Values passed as the 5th argument to allocateBtreePage() -*/ -#define BTALLOC_ANY 0 /* Allocate any page */ -#define BTALLOC_EXACT 1 /* Allocate exact page if possible */ -#define BTALLOC_LE 2 /* Allocate any page <= the parameter */ - -/* -** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not -** defined, or 0 if it is. For example: -** -** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum); -*/ -#ifndef SQLITE_OMIT_AUTOVACUUM -#define IfNotOmitAV(expr) (expr) -#else -#define IfNotOmitAV(expr) 0 -#endif - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** A list of BtShared objects that are eligible for participation -** in shared cache. This variable has file scope during normal builds, -** but the test harness needs to access it so we make it global for -** test builds. -** -** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER. -*/ -#ifdef SQLITE_TEST -SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; -#else -static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0; -#endif -#endif /* SQLITE_OMIT_SHARED_CACHE */ - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** Enable or disable the shared pager and schema features. -** -** This routine has no effect on existing database connections. -** The shared cache setting effects only future calls to -** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). -*/ -SQLITE_API int sqlite3_enable_shared_cache(int enable){ - sqlite3GlobalConfig.sharedCacheEnabled = enable; - return SQLITE_OK; -} -#endif - - - -#ifdef SQLITE_OMIT_SHARED_CACHE - /* - ** The functions querySharedCacheTableLock(), setSharedCacheTableLock(), - ** and clearAllSharedCacheTableLocks() - ** manipulate entries in the BtShared.pLock linked list used to store - ** shared-cache table level locks. If the library is compiled with the - ** shared-cache feature disabled, then there is only ever one user - ** of each BtShared structure and so this locking is not necessary. - ** So define the lock related functions as no-ops. - */ - #define querySharedCacheTableLock(a,b,c) SQLITE_OK - #define setSharedCacheTableLock(a,b,c) SQLITE_OK - #define clearAllSharedCacheTableLocks(a) - #define downgradeAllSharedCacheTableLocks(a) - #define hasSharedCacheTableLock(a,b,c,d) 1 - #define hasReadConflicts(a, b) 0 -#endif - -#ifndef SQLITE_OMIT_SHARED_CACHE - -#ifdef SQLITE_DEBUG -/* -**** This function is only used as part of an assert() statement. *** -** -** Check to see if pBtree holds the required locks to read or write to the -** table with root page iRoot. Return 1 if it does and 0 if not. -** -** For example, when writing to a table with root-page iRoot via -** Btree connection pBtree: -** -** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) ); -** -** When writing to an index that resides in a sharable database, the -** caller should have first obtained a lock specifying the root page of -** the corresponding table. This makes things a bit more complicated, -** as this module treats each table as a separate structure. To determine -** the table corresponding to the index being written, this -** function has to search through the database schema. -** -** Instead of a lock on the table/index rooted at page iRoot, the caller may -** hold a write-lock on the schema table (root page 1). This is also -** acceptable. -*/ -static int hasSharedCacheTableLock( - Btree *pBtree, /* Handle that must hold lock */ - Pgno iRoot, /* Root page of b-tree */ - int isIndex, /* True if iRoot is the root of an index b-tree */ - int eLockType /* Required lock type (READ_LOCK or WRITE_LOCK) */ -){ - Schema *pSchema = (Schema *)pBtree->pBt->pSchema; - Pgno iTab = 0; - BtLock *pLock; - - /* If this database is not shareable, or if the client is reading - ** and has the read-uncommitted flag set, then no lock is required. - ** Return true immediately. - */ - if( (pBtree->sharable==0) - || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted)) - ){ - return 1; - } - - /* If the client is reading or writing an index and the schema is - ** not loaded, then it is too difficult to actually check to see if - ** the correct locks are held. So do not bother - just return true. - ** This case does not come up very often anyhow. - */ - if( isIndex && (!pSchema || (pSchema->flags&DB_SchemaLoaded)==0) ){ - return 1; - } - - /* Figure out the root-page that the lock should be held on. For table - ** b-trees, this is just the root page of the b-tree being read or - ** written. For index b-trees, it is the root page of the associated - ** table. */ - if( isIndex ){ - HashElem *p; - for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ - Index *pIdx = (Index *)sqliteHashData(p); - if( pIdx->tnum==(int)iRoot ){ - iTab = pIdx->pTable->tnum; - } - } - }else{ - iTab = iRoot; - } - - /* Search for the required lock. Either a write-lock on root-page iTab, a - ** write-lock on the schema table, or (if the client is reading) a - ** read-lock on iTab will suffice. Return 1 if any of these are found. */ - for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){ - if( pLock->pBtree==pBtree - && (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1)) - && pLock->eLock>=eLockType - ){ - return 1; - } - } - - /* Failed to find the required lock. */ - return 0; -} -#endif /* SQLITE_DEBUG */ - -#ifdef SQLITE_DEBUG -/* -**** This function may be used as part of assert() statements only. **** -** -** Return true if it would be illegal for pBtree to write into the -** table or index rooted at iRoot because other shared connections are -** simultaneously reading that same table or index. -** -** It is illegal for pBtree to write if some other Btree object that -** shares the same BtShared object is currently reading or writing -** the iRoot table. Except, if the other Btree object has the -** read-uncommitted flag set, then it is OK for the other object to -** have a read cursor. -** -** For example, before writing to any part of the table or index -** rooted at page iRoot, one should call: -** -** assert( !hasReadConflicts(pBtree, iRoot) ); -*/ -static int hasReadConflicts(Btree *pBtree, Pgno iRoot){ - BtCursor *p; - for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - if( p->pgnoRoot==iRoot - && p->pBtree!=pBtree - && 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted) - ){ - return 1; - } - } - return 0; -} -#endif /* #ifdef SQLITE_DEBUG */ - -/* -** Query to see if Btree handle p may obtain a lock of type eLock -** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return -** SQLITE_OK if the lock may be obtained (by calling -** setSharedCacheTableLock()), or SQLITE_LOCKED if not. -*/ -static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){ - BtShared *pBt = p->pBt; - BtLock *pIter; - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); - assert( p->db!=0 ); - assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 ); - - /* If requesting a write-lock, then the Btree must have an open write - ** transaction on this file. And, obviously, for this to be so there - ** must be an open write transaction on the file itself. - */ - assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) ); - assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE ); - - /* This routine is a no-op if the shared-cache is not enabled */ - if( !p->sharable ){ - return SQLITE_OK; - } - - /* If some other connection is holding an exclusive lock, the - ** requested lock may not be obtained. - */ - if( pBt->pWriter!=p && (pBt->btsFlags & BTS_EXCLUSIVE)!=0 ){ - sqlite3ConnectionBlocked(p->db, pBt->pWriter->db); - return SQLITE_LOCKED_SHAREDCACHE; - } - - for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ - /* The condition (pIter->eLock!=eLock) in the following if(...) - ** statement is a simplification of: - ** - ** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK) - ** - ** since we know that if eLock==WRITE_LOCK, then no other connection - ** may hold a WRITE_LOCK on any table in this file (since there can - ** only be a single writer). - */ - assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK ); - assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK); - if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){ - sqlite3ConnectionBlocked(p->db, pIter->pBtree->db); - if( eLock==WRITE_LOCK ){ - assert( p==pBt->pWriter ); - pBt->btsFlags |= BTS_PENDING; - } - return SQLITE_LOCKED_SHAREDCACHE; - } - } - return SQLITE_OK; -} -#endif /* !SQLITE_OMIT_SHARED_CACHE */ - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** Add a lock on the table with root-page iTable to the shared-btree used -** by Btree handle p. Parameter eLock must be either READ_LOCK or -** WRITE_LOCK. -** -** This function assumes the following: -** -** (a) The specified Btree object p is connected to a sharable -** database (one with the BtShared.sharable flag set), and -** -** (b) No other Btree objects hold a lock that conflicts -** with the requested lock (i.e. querySharedCacheTableLock() has -** already been called and returned SQLITE_OK). -** -** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM -** is returned if a malloc attempt fails. -*/ -static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ - BtShared *pBt = p->pBt; - BtLock *pLock = 0; - BtLock *pIter; - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); - assert( p->db!=0 ); - - /* A connection with the read-uncommitted flag set will never try to - ** obtain a read-lock using this function. The only read-lock obtained - ** by a connection in read-uncommitted mode is on the sqlite_master - ** table, and that lock is obtained in BtreeBeginTrans(). */ - assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK ); - - /* This function should only be called on a sharable b-tree after it - ** has been determined that no other b-tree holds a conflicting lock. */ - assert( p->sharable ); - assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) ); - - /* First search the list for an existing lock on this table. */ - for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ - if( pIter->iTable==iTable && pIter->pBtree==p ){ - pLock = pIter; - break; - } - } - - /* If the above search did not find a BtLock struct associating Btree p - ** with table iTable, allocate one and link it into the list. - */ - if( !pLock ){ - pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock)); - if( !pLock ){ - return SQLITE_NOMEM; - } - pLock->iTable = iTable; - pLock->pBtree = p; - pLock->pNext = pBt->pLock; - pBt->pLock = pLock; - } - - /* Set the BtLock.eLock variable to the maximum of the current lock - ** and the requested lock. This means if a write-lock was already held - ** and a read-lock requested, we don't incorrectly downgrade the lock. - */ - assert( WRITE_LOCK>READ_LOCK ); - if( eLock>pLock->eLock ){ - pLock->eLock = eLock; - } - - return SQLITE_OK; -} -#endif /* !SQLITE_OMIT_SHARED_CACHE */ - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** Release all the table locks (locks obtained via calls to -** the setSharedCacheTableLock() procedure) held by Btree object p. -** -** This function assumes that Btree p has an open read or write -** transaction. If it does not, then the BTS_PENDING flag -** may be incorrectly cleared. -*/ -static void clearAllSharedCacheTableLocks(Btree *p){ - BtShared *pBt = p->pBt; - BtLock **ppIter = &pBt->pLock; - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( p->sharable || 0==*ppIter ); - assert( p->inTrans>0 ); - - while( *ppIter ){ - BtLock *pLock = *ppIter; - assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree ); - assert( pLock->pBtree->inTrans>=pLock->eLock ); - if( pLock->pBtree==p ){ - *ppIter = pLock->pNext; - assert( pLock->iTable!=1 || pLock==&p->lock ); - if( pLock->iTable!=1 ){ - sqlite3_free(pLock); - } - }else{ - ppIter = &pLock->pNext; - } - } - - assert( (pBt->btsFlags & BTS_PENDING)==0 || pBt->pWriter ); - if( pBt->pWriter==p ){ - pBt->pWriter = 0; - pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING); - }else if( pBt->nTransaction==2 ){ - /* This function is called when Btree p is concluding its - ** transaction. If there currently exists a writer, and p is not - ** that writer, then the number of locks held by connections other - ** than the writer must be about to drop to zero. In this case - ** set the BTS_PENDING flag to 0. - ** - ** If there is not currently a writer, then BTS_PENDING must - ** be zero already. So this next line is harmless in that case. - */ - pBt->btsFlags &= ~BTS_PENDING; - } -} - -/* -** This function changes all write-locks held by Btree p into read-locks. -*/ -static void downgradeAllSharedCacheTableLocks(Btree *p){ - BtShared *pBt = p->pBt; - if( pBt->pWriter==p ){ - BtLock *pLock; - pBt->pWriter = 0; - pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING); - for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){ - assert( pLock->eLock==READ_LOCK || pLock->pBtree==p ); - pLock->eLock = READ_LOCK; - } - } -} - -#endif /* SQLITE_OMIT_SHARED_CACHE */ - -static void releasePage(MemPage *pPage); /* Forward reference */ - -/* -***** This routine is used inside of assert() only **** -** -** Verify that the cursor holds the mutex on its BtShared -*/ -#ifdef SQLITE_DEBUG -static int cursorHoldsMutex(BtCursor *p){ - return sqlite3_mutex_held(p->pBt->mutex); -} -#endif - - -#ifndef SQLITE_OMIT_INCRBLOB -/* -** Invalidate the overflow page-list cache for cursor pCur, if any. -*/ -static void invalidateOverflowCache(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - sqlite3_free(pCur->aOverflow); - pCur->aOverflow = 0; -} - -/* -** Invalidate the overflow page-list cache for all cursors opened -** on the shared btree structure pBt. -*/ -static void invalidateAllOverflowCache(BtShared *pBt){ - BtCursor *p; - assert( sqlite3_mutex_held(pBt->mutex) ); - for(p=pBt->pCursor; p; p=p->pNext){ - invalidateOverflowCache(p); - } -} - -/* -** This function is called before modifying the contents of a table -** to invalidate any incrblob cursors that are open on the -** row or one of the rows being modified. -** -** If argument isClearTable is true, then the entire contents of the -** table is about to be deleted. In this case invalidate all incrblob -** cursors open on any row within the table with root-page pgnoRoot. -** -** Otherwise, if argument isClearTable is false, then the row with -** rowid iRow is being replaced or deleted. In this case invalidate -** only those incrblob cursors open on that specific row. -*/ -static void invalidateIncrblobCursors( - Btree *pBtree, /* The database file to check */ - i64 iRow, /* The rowid that might be changing */ - int isClearTable /* True if all rows are being deleted */ -){ - BtCursor *p; - BtShared *pBt = pBtree->pBt; - assert( sqlite3BtreeHoldsMutex(pBtree) ); - for(p=pBt->pCursor; p; p=p->pNext){ - if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){ - p->eState = CURSOR_INVALID; - } - } -} - -#else - /* Stub functions when INCRBLOB is omitted */ - #define invalidateOverflowCache(x) - #define invalidateAllOverflowCache(x) - #define invalidateIncrblobCursors(x,y,z) -#endif /* SQLITE_OMIT_INCRBLOB */ - -/* -** Set bit pgno of the BtShared.pHasContent bitvec. This is called -** when a page that previously contained data becomes a free-list leaf -** page. -** -** The BtShared.pHasContent bitvec exists to work around an obscure -** bug caused by the interaction of two useful IO optimizations surrounding -** free-list leaf pages: -** -** 1) When all data is deleted from a page and the page becomes -** a free-list leaf page, the page is not written to the database -** (as free-list leaf pages contain no meaningful data). Sometimes -** such a page is not even journalled (as it will not be modified, -** why bother journalling it?). -** -** 2) When a free-list leaf page is reused, its content is not read -** from the database or written to the journal file (why should it -** be, if it is not at all meaningful?). -** -** By themselves, these optimizations work fine and provide a handy -** performance boost to bulk delete or insert operations. However, if -** a page is moved to the free-list and then reused within the same -** transaction, a problem comes up. If the page is not journalled when -** it is moved to the free-list and it is also not journalled when it -** is extracted from the free-list and reused, then the original data -** may be lost. In the event of a rollback, it may not be possible -** to restore the database to its original configuration. -** -** The solution is the BtShared.pHasContent bitvec. Whenever a page is -** moved to become a free-list leaf page, the corresponding bit is -** set in the bitvec. Whenever a leaf page is extracted from the free-list, -** optimization 2 above is omitted if the corresponding bit is already -** set in BtShared.pHasContent. The contents of the bitvec are cleared -** at the end of every transaction. -*/ -static int btreeSetHasContent(BtShared *pBt, Pgno pgno){ - int rc = SQLITE_OK; - if( !pBt->pHasContent ){ - assert( pgno<=pBt->nPage ); - pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage); - if( !pBt->pHasContent ){ - rc = SQLITE_NOMEM; - } - } - if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){ - rc = sqlite3BitvecSet(pBt->pHasContent, pgno); - } - return rc; -} - -/* -** Query the BtShared.pHasContent vector. -** -** This function is called when a free-list leaf page is removed from the -** free-list for reuse. It returns false if it is safe to retrieve the -** page from the pager layer with the 'no-content' flag set. True otherwise. -*/ -static int btreeGetHasContent(BtShared *pBt, Pgno pgno){ - Bitvec *p = pBt->pHasContent; - return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno))); -} - -/* -** Clear (destroy) the BtShared.pHasContent bitvec. This should be -** invoked at the conclusion of each write-transaction. -*/ -static void btreeClearHasContent(BtShared *pBt){ - sqlite3BitvecDestroy(pBt->pHasContent); - pBt->pHasContent = 0; -} - -/* -** Release all of the apPage[] pages for a cursor. -*/ -static void btreeReleaseAllCursorPages(BtCursor *pCur){ - int i; - for(i=0; i<=pCur->iPage; i++){ - releasePage(pCur->apPage[i]); - pCur->apPage[i] = 0; - } - pCur->iPage = -1; -} - - -/* -** Save the current cursor position in the variables BtCursor.nKey -** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. -** -** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) -** prior to calling this routine. -*/ -static int saveCursorPosition(BtCursor *pCur){ - int rc; - - assert( CURSOR_VALID==pCur->eState ); - assert( 0==pCur->pKey ); - assert( cursorHoldsMutex(pCur) ); - - rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); - assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ - - /* If this is an intKey table, then the above call to BtreeKeySize() - ** stores the integer key in pCur->nKey. In this case this value is - ** all that is required. Otherwise, if pCur is not open on an intKey - ** table, then malloc space for and store the pCur->nKey bytes of key - ** data. - */ - if( 0==pCur->apPage[0]->intKey ){ - void *pKey = sqlite3Malloc( (int)pCur->nKey ); - if( pKey ){ - rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); - if( rc==SQLITE_OK ){ - pCur->pKey = pKey; - }else{ - sqlite3_free(pKey); - } - }else{ - rc = SQLITE_NOMEM; - } - } - assert( !pCur->apPage[0]->intKey || !pCur->pKey ); - - if( rc==SQLITE_OK ){ - btreeReleaseAllCursorPages(pCur); - pCur->eState = CURSOR_REQUIRESEEK; - } - - invalidateOverflowCache(pCur); - return rc; -} - -/* -** Save the positions of all cursors (except pExcept) that are open on -** the table with root-page iRoot. Usually, this is called just before cursor -** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). -*/ -static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ - BtCursor *p; - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pExcept==0 || pExcept->pBt==pBt ); - for(p=pBt->pCursor; p; p=p->pNext){ - if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ - if( p->eState==CURSOR_VALID ){ - int rc = saveCursorPosition(p); - if( SQLITE_OK!=rc ){ - return rc; - } - }else{ - testcase( p->iPage>0 ); - btreeReleaseAllCursorPages(p); - } - } - } - return SQLITE_OK; -} - -/* -** Clear the current cursor position. -*/ -SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - sqlite3_free(pCur->pKey); - pCur->pKey = 0; - pCur->eState = CURSOR_INVALID; -} - -/* -** In this version of BtreeMoveto, pKey is a packed index record -** such as is generated by the OP_MakeRecord opcode. Unpack the -** record and then call BtreeMovetoUnpacked() to do the work. -*/ -static int btreeMoveto( - BtCursor *pCur, /* Cursor open on the btree to be searched */ - const void *pKey, /* Packed key if the btree is an index */ - i64 nKey, /* Integer key for tables. Size of pKey for indices */ - int bias, /* Bias search to the high end */ - int *pRes /* Write search results here */ -){ - int rc; /* Status code */ - UnpackedRecord *pIdxKey; /* Unpacked index key */ - char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */ - char *pFree = 0; - - if( pKey ){ - assert( nKey==(i64)(int)nKey ); - pIdxKey = sqlite3VdbeAllocUnpackedRecord( - pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree - ); - if( pIdxKey==0 ) return SQLITE_NOMEM; - sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey); - }else{ - pIdxKey = 0; - } - rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes); - if( pFree ){ - sqlite3DbFree(pCur->pKeyInfo->db, pFree); - } - return rc; -} - -/* -** Restore the cursor to the position it was in (or as close to as possible) -** when saveCursorPosition() was called. Note that this call deletes the -** saved position info stored by saveCursorPosition(), so there can be -** at most one effective restoreCursorPosition() call after each -** saveCursorPosition(). -*/ -static int btreeRestoreCursorPosition(BtCursor *pCur){ - int rc; - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState>=CURSOR_REQUIRESEEK ); - if( pCur->eState==CURSOR_FAULT ){ - return pCur->skipNext; - } - pCur->eState = CURSOR_INVALID; - rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext); - if( rc==SQLITE_OK ){ - sqlite3_free(pCur->pKey); - pCur->pKey = 0; - assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); - } - return rc; -} - -#define restoreCursorPosition(p) \ - (p->eState>=CURSOR_REQUIRESEEK ? \ - btreeRestoreCursorPosition(p) : \ - SQLITE_OK) - -/* -** Determine whether or not a cursor has moved from the position it -** was last placed at. Cursors can move when the row they are pointing -** at is deleted out from under them. -** -** This routine returns an error code if something goes wrong. The -** integer *pHasMoved is set to one if the cursor has moved and 0 if not. -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){ - int rc; - - rc = restoreCursorPosition(pCur); - if( rc ){ - *pHasMoved = 1; - return rc; - } - if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){ - *pHasMoved = 1; - }else{ - *pHasMoved = 0; - } - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_AUTOVACUUM -/* -** Given a page number of a regular database page, return the page -** number for the pointer-map page that contains the entry for the -** input page number. -** -** Return 0 (not a valid page) for pgno==1 since there is -** no pointer map associated with page 1. The integrity_check logic -** requires that ptrmapPageno(*,1)!=1. -*/ -static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ - int nPagesPerMapPage; - Pgno iPtrMap, ret; - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pgno<2 ) return 0; - nPagesPerMapPage = (pBt->usableSize/5)+1; - iPtrMap = (pgno-2)/nPagesPerMapPage; - ret = (iPtrMap*nPagesPerMapPage) + 2; - if( ret==PENDING_BYTE_PAGE(pBt) ){ - ret++; - } - return ret; -} - -/* -** Write an entry into the pointer map. -** -** This routine updates the pointer map entry for page number 'key' -** so that it maps to type 'eType' and parent page number 'pgno'. -** -** If *pRC is initially non-zero (non-SQLITE_OK) then this routine is -** a no-op. If an error occurs, the appropriate error code is written -** into *pRC. -*/ -static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ - DbPage *pDbPage; /* The pointer map page */ - u8 *pPtrmap; /* The pointer map data */ - Pgno iPtrmap; /* The pointer map page number */ - int offset; /* Offset in pointer map page */ - int rc; /* Return code from subfunctions */ - - if( *pRC ) return; - - assert( sqlite3_mutex_held(pBt->mutex) ); - /* The master-journal page number must never be used as a pointer map page */ - assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); - - assert( pBt->autoVacuum ); - if( key==0 ){ - *pRC = SQLITE_CORRUPT_BKPT; - return; - } - iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); - if( rc!=SQLITE_OK ){ - *pRC = rc; - return; - } - offset = PTRMAP_PTROFFSET(iPtrmap, key); - if( offset<0 ){ - *pRC = SQLITE_CORRUPT_BKPT; - goto ptrmap_exit; - } - assert( offset <= (int)pBt->usableSize-5 ); - pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); - - if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ - TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); - *pRC= rc = sqlite3PagerWrite(pDbPage); - if( rc==SQLITE_OK ){ - pPtrmap[offset] = eType; - put4byte(&pPtrmap[offset+1], parent); - } - } - -ptrmap_exit: - sqlite3PagerUnref(pDbPage); -} - -/* -** Read an entry from the pointer map. -** -** This routine retrieves the pointer map entry for page 'key', writing -** the type and parent page number to *pEType and *pPgno respectively. -** An error code is returned if something goes wrong, otherwise SQLITE_OK. -*/ -static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ - DbPage *pDbPage; /* The pointer map page */ - int iPtrmap; /* Pointer map page index */ - u8 *pPtrmap; /* Pointer map page data */ - int offset; /* Offset of entry in pointer map */ - int rc; - - assert( sqlite3_mutex_held(pBt->mutex) ); - - iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); - if( rc!=0 ){ - return rc; - } - pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); - - offset = PTRMAP_PTROFFSET(iPtrmap, key); - if( offset<0 ){ - sqlite3PagerUnref(pDbPage); - return SQLITE_CORRUPT_BKPT; - } - assert( offset <= (int)pBt->usableSize-5 ); - assert( pEType!=0 ); - *pEType = pPtrmap[offset]; - if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); - - sqlite3PagerUnref(pDbPage); - if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; - return SQLITE_OK; -} - -#else /* if defined SQLITE_OMIT_AUTOVACUUM */ - #define ptrmapPut(w,x,y,z,rc) - #define ptrmapGet(w,x,y,z) SQLITE_OK - #define ptrmapPutOvflPtr(x, y, rc) -#endif - -/* -** Given a btree page and a cell index (0 means the first cell on -** the page, 1 means the second cell, and so forth) return a pointer -** to the cell content. -** -** This routine works only for pages that do not contain overflow cells. -*/ -#define findCell(P,I) \ - ((P)->aData + ((P)->maskPage & get2byte(&(P)->aCellIdx[2*(I)]))) -#define findCellv2(D,M,O,I) (D+(M&get2byte(D+(O+2*(I))))) - - -/* -** This a more complex version of findCell() that works for -** pages that do contain overflow cells. -*/ -static u8 *findOverflowCell(MemPage *pPage, int iCell){ - int i; - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - for(i=pPage->nOverflow-1; i>=0; i--){ - int k; - k = pPage->aiOvfl[i]; - if( k<=iCell ){ - if( k==iCell ){ - return pPage->apOvfl[i]; - } - iCell--; - } - } - return findCell(pPage, iCell); -} - -/* -** Parse a cell content block and fill in the CellInfo structure. There -** are two versions of this function. btreeParseCell() takes a -** cell index as the second argument and btreeParseCellPtr() -** takes a pointer to the body of the cell as its second argument. -** -** Within this file, the parseCell() macro can be called instead of -** btreeParseCellPtr(). Using some compilers, this will be faster. -*/ -static void btreeParseCellPtr( - MemPage *pPage, /* Page containing the cell */ - u8 *pCell, /* Pointer to the cell text. */ - CellInfo *pInfo /* Fill in this structure */ -){ - u16 n; /* Number bytes in cell content header */ - u32 nPayload; /* Number of bytes of cell payload */ - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - - pInfo->pCell = pCell; - assert( pPage->leaf==0 || pPage->leaf==1 ); - n = pPage->childPtrSize; - assert( n==4-4*pPage->leaf ); - if( pPage->intKey ){ - if( pPage->hasData ){ - n += getVarint32(&pCell[n], nPayload); - }else{ - nPayload = 0; - } - n += getVarint(&pCell[n], (u64*)&pInfo->nKey); - pInfo->nData = nPayload; - }else{ - pInfo->nData = 0; - n += getVarint32(&pCell[n], nPayload); - pInfo->nKey = nPayload; - } - pInfo->nPayload = nPayload; - pInfo->nHeader = n; - testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==pPage->maxLocal+1 ); - if( likely(nPayload<=pPage->maxLocal) ){ - /* This is the (easy) common case where the entire payload fits - ** on the local page. No overflow is required. - */ - if( (pInfo->nSize = (u16)(n+nPayload))<4 ) pInfo->nSize = 4; - pInfo->nLocal = (u16)nPayload; - pInfo->iOverflow = 0; - }else{ - /* If the payload will not fit completely on the local page, we have - ** to decide how much to store locally and how much to spill onto - ** overflow pages. The strategy is to minimize the amount of unused - ** space on overflow pages while keeping the amount of local storage - ** in between minLocal and maxLocal. - ** - ** Warning: changing the way overflow payload is distributed in any - ** way will result in an incompatible file format. - */ - int minLocal; /* Minimum amount of payload held locally */ - int maxLocal; /* Maximum amount of payload held locally */ - int surplus; /* Overflow payload available for local storage */ - - minLocal = pPage->minLocal; - maxLocal = pPage->maxLocal; - surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4); - testcase( surplus==maxLocal ); - testcase( surplus==maxLocal+1 ); - if( surplus <= maxLocal ){ - pInfo->nLocal = (u16)surplus; - }else{ - pInfo->nLocal = (u16)minLocal; - } - pInfo->iOverflow = (u16)(pInfo->nLocal + n); - pInfo->nSize = pInfo->iOverflow + 4; - } -} -#define parseCell(pPage, iCell, pInfo) \ - btreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo)) -static void btreeParseCell( - MemPage *pPage, /* Page containing the cell */ - int iCell, /* The cell index. First cell is 0 */ - CellInfo *pInfo /* Fill in this structure */ -){ - parseCell(pPage, iCell, pInfo); -} - -/* -** Compute the total number of bytes that a Cell needs in the cell -** data area of the btree-page. The return number includes the cell -** data header and the local payload, but not any overflow page or -** the space used by the cell pointer. -*/ -static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ - u8 *pIter = &pCell[pPage->childPtrSize]; - u32 nSize; - -#ifdef SQLITE_DEBUG - /* The value returned by this function should always be the same as - ** the (CellInfo.nSize) value found by doing a full parse of the - ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of - ** this function verifies that this invariant is not violated. */ - CellInfo debuginfo; - btreeParseCellPtr(pPage, pCell, &debuginfo); -#endif - - if( pPage->intKey ){ - u8 *pEnd; - if( pPage->hasData ){ - pIter += getVarint32(pIter, nSize); - }else{ - nSize = 0; - } - - /* pIter now points at the 64-bit integer key value, a variable length - ** integer. The following block moves pIter to point at the first byte - ** past the end of the key value. */ - pEnd = &pIter[9]; - while( (*pIter++)&0x80 && pItermaxLocal ); - testcase( nSize==pPage->maxLocal+1 ); - if( nSize>pPage->maxLocal ){ - int minLocal = pPage->minLocal; - nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); - testcase( nSize==pPage->maxLocal ); - testcase( nSize==pPage->maxLocal+1 ); - if( nSize>pPage->maxLocal ){ - nSize = minLocal; - } - nSize += 4; - } - nSize += (u32)(pIter - pCell); - - /* The minimum size of any cell is 4 bytes. */ - if( nSize<4 ){ - nSize = 4; - } - - assert( nSize==debuginfo.nSize ); - return (u16)nSize; -} - -#ifdef SQLITE_DEBUG -/* This variation on cellSizePtr() is used inside of assert() statements -** only. */ -static u16 cellSize(MemPage *pPage, int iCell){ - return cellSizePtr(pPage, findCell(pPage, iCell)); -} -#endif - -#ifndef SQLITE_OMIT_AUTOVACUUM -/* -** If the cell pCell, part of page pPage contains a pointer -** to an overflow page, insert an entry into the pointer-map -** for the overflow page. -*/ -static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){ - CellInfo info; - if( *pRC ) return; - assert( pCell!=0 ); - btreeParseCellPtr(pPage, pCell, &info); - assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); - if( info.iOverflow ){ - Pgno ovfl = get4byte(&pCell[info.iOverflow]); - ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC); - } -} -#endif - - -/* -** Defragment the page given. All Cells are moved to the -** end of the page and all free space is collected into one -** big FreeBlk that occurs in between the header and cell -** pointer array and the cell content area. -*/ -static int defragmentPage(MemPage *pPage){ - int i; /* Loop counter */ - int pc; /* Address of a i-th cell */ - int hdr; /* Offset to the page header */ - int size; /* Size of a cell */ - int usableSize; /* Number of usable bytes on a page */ - int cellOffset; /* Offset to the cell pointer array */ - int cbrk; /* Offset to the cell content area */ - int nCell; /* Number of cells on the page */ - unsigned char *data; /* The page data */ - unsigned char *temp; /* Temp area for cell content */ - int iCellFirst; /* First allowable cell index */ - int iCellLast; /* Last possible cell index */ - - - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( pPage->pBt!=0 ); - assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); - assert( pPage->nOverflow==0 ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - temp = sqlite3PagerTempSpace(pPage->pBt->pPager); - data = pPage->aData; - hdr = pPage->hdrOffset; - cellOffset = pPage->cellOffset; - nCell = pPage->nCell; - assert( nCell==get2byte(&data[hdr+3]) ); - usableSize = pPage->pBt->usableSize; - cbrk = get2byte(&data[hdr+5]); - memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk); - cbrk = usableSize; - iCellFirst = cellOffset + 2*nCell; - iCellLast = usableSize - 4; - for(i=0; iiCellLast ){ - return SQLITE_CORRUPT_BKPT; - } -#endif - assert( pc>=iCellFirst && pc<=iCellLast ); - size = cellSizePtr(pPage, &temp[pc]); - cbrk -= size; -#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) - if( cbrkusableSize ){ - return SQLITE_CORRUPT_BKPT; - } -#endif - assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); - testcase( cbrk+size==usableSize ); - testcase( pc+size==usableSize ); - memcpy(&data[cbrk], &temp[pc], size); - put2byte(pAddr, cbrk); - } - assert( cbrk>=iCellFirst ); - put2byte(&data[hdr+5], cbrk); - data[hdr+1] = 0; - data[hdr+2] = 0; - data[hdr+7] = 0; - memset(&data[iCellFirst], 0, cbrk-iCellFirst); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - if( cbrk-iCellFirst!=pPage->nFree ){ - return SQLITE_CORRUPT_BKPT; - } - return SQLITE_OK; -} - -/* -** Allocate nByte bytes of space from within the B-Tree page passed -** as the first argument. Write into *pIdx the index into pPage->aData[] -** of the first byte of allocated space. Return either SQLITE_OK or -** an error code (usually SQLITE_CORRUPT). -** -** The caller guarantees that there is sufficient space to make the -** allocation. This routine might need to defragment in order to bring -** all the space together, however. This routine will avoid using -** the first two bytes past the cell pointer area since presumably this -** allocation is being made in order to insert a new cell, so we will -** also end up needing a new cell pointer. -*/ -static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ - const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ - u8 * const data = pPage->aData; /* Local cache of pPage->aData */ - int nFrag; /* Number of fragmented bytes on pPage */ - int top; /* First byte of cell content area */ - int gap; /* First byte of gap between cell pointers and cell content */ - int rc; /* Integer return code */ - int usableSize; /* Usable size of the page */ - - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( pPage->pBt ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( nByte>=0 ); /* Minimum cell size is 4 */ - assert( pPage->nFree>=nByte ); - assert( pPage->nOverflow==0 ); - usableSize = pPage->pBt->usableSize; - assert( nByte < usableSize-8 ); - - nFrag = data[hdr+7]; - assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf ); - gap = pPage->cellOffset + 2*pPage->nCell; - top = get2byteNotZero(&data[hdr+5]); - if( gap>top ) return SQLITE_CORRUPT_BKPT; - testcase( gap+2==top ); - testcase( gap+1==top ); - testcase( gap==top ); - - if( nFrag>=60 ){ - /* Always defragment highly fragmented pages */ - rc = defragmentPage(pPage); - if( rc ) return rc; - top = get2byteNotZero(&data[hdr+5]); - }else if( gap+2<=top ){ - /* Search the freelist looking for a free slot big enough to satisfy - ** the request. The allocation is made from the first free slot in - ** the list that is large enough to accomadate it. - */ - int pc, addr; - for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){ - int size; /* Size of the free slot */ - if( pc>usableSize-4 || pc=nByte ){ - int x = size - nByte; - testcase( x==4 ); - testcase( x==3 ); - if( x<4 ){ - /* Remove the slot from the free-list. Update the number of - ** fragmented bytes within the page. */ - memcpy(&data[addr], &data[pc], 2); - data[hdr+7] = (u8)(nFrag + x); - }else if( size+pc > usableSize ){ - return SQLITE_CORRUPT_BKPT; - }else{ - /* The slot remains on the free-list. Reduce its size to account - ** for the portion used by the new allocation. */ - put2byte(&data[pc+2], x); - } - *pIdx = pc + x; - return SQLITE_OK; - } - } - } - - /* Check to make sure there is enough space in the gap to satisfy - ** the allocation. If not, defragment. - */ - testcase( gap+2+nByte==top ); - if( gap+2+nByte>top ){ - rc = defragmentPage(pPage); - if( rc ) return rc; - top = get2byteNotZero(&data[hdr+5]); - assert( gap+nByte<=top ); - } - - - /* Allocate memory from the gap in between the cell pointer array - ** and the cell content area. The btreeInitPage() call has already - ** validated the freelist. Given that the freelist is valid, there - ** is no way that the allocation can extend off the end of the page. - ** The assert() below verifies the previous sentence. - */ - top -= nByte; - put2byte(&data[hdr+5], top); - assert( top+nByte <= (int)pPage->pBt->usableSize ); - *pIdx = top; - return SQLITE_OK; -} - -/* -** Return a section of the pPage->aData to the freelist. -** The first byte of the new free block is pPage->aDisk[start] -** and the size of the block is "size" bytes. -** -** Most of the effort here is involved in coalesing adjacent -** free blocks into a single big free block. -*/ -static int freeSpace(MemPage *pPage, int start, int size){ - int addr, pbegin, hdr; - int iLast; /* Largest possible freeblock offset */ - unsigned char *data = pPage->aData; - - assert( pPage->pBt!=0 ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( start>=pPage->hdrOffset+6+pPage->childPtrSize ); - assert( (start + size) <= (int)pPage->pBt->usableSize ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( size>=0 ); /* Minimum cell size is 4 */ - - if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){ - /* Overwrite deleted information with zeros when the secure_delete - ** option is enabled */ - memset(&data[start], 0, size); - } - - /* Add the space back into the linked list of freeblocks. Note that - ** even though the freeblock list was checked by btreeInitPage(), - ** btreeInitPage() did not detect overlapping cells or - ** freeblocks that overlapped cells. Nor does it detect when the - ** cell content area exceeds the value in the page header. If these - ** situations arise, then subsequent insert operations might corrupt - ** the freelist. So we do need to check for corruption while scanning - ** the freelist. - */ - hdr = pPage->hdrOffset; - addr = hdr + 1; - iLast = pPage->pBt->usableSize - 4; - assert( start<=iLast ); - while( (pbegin = get2byte(&data[addr]))0 ){ - if( pbeginiLast ){ - return SQLITE_CORRUPT_BKPT; - } - assert( pbegin>addr || pbegin==0 ); - put2byte(&data[addr], start); - put2byte(&data[start], pbegin); - put2byte(&data[start+2], size); - pPage->nFree = pPage->nFree + (u16)size; - - /* Coalesce adjacent free blocks */ - addr = hdr + 1; - while( (pbegin = get2byte(&data[addr]))>0 ){ - int pnext, psize, x; - assert( pbegin>addr ); - assert( pbegin <= (int)pPage->pBt->usableSize-4 ); - pnext = get2byte(&data[pbegin]); - psize = get2byte(&data[pbegin+2]); - if( pbegin + psize + 3 >= pnext && pnext>0 ){ - int frag = pnext - (pbegin+psize); - if( (frag<0) || (frag>(int)data[hdr+7]) ){ - return SQLITE_CORRUPT_BKPT; - } - data[hdr+7] -= (u8)frag; - x = get2byte(&data[pnext]); - put2byte(&data[pbegin], x); - x = pnext + get2byte(&data[pnext+2]) - pbegin; - put2byte(&data[pbegin+2], x); - }else{ - addr = pbegin; - } - } - - /* If the cell content area begins with a freeblock, remove it. */ - if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){ - int top; - pbegin = get2byte(&data[hdr+1]); - memcpy(&data[hdr+1], &data[pbegin], 2); - top = get2byte(&data[hdr+5]) + get2byte(&data[pbegin+2]); - put2byte(&data[hdr+5], top); - } - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - return SQLITE_OK; -} - -/* -** Decode the flags byte (the first byte of the header) for a page -** and initialize fields of the MemPage structure accordingly. -** -** Only the following combinations are supported. Anything different -** indicates a corrupt database files: -** -** PTF_ZERODATA -** PTF_ZERODATA | PTF_LEAF -** PTF_LEAFDATA | PTF_INTKEY -** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF -*/ -static int decodeFlags(MemPage *pPage, int flagByte){ - BtShared *pBt; /* A copy of pPage->pBt */ - - assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 ); - flagByte &= ~PTF_LEAF; - pPage->childPtrSize = 4-4*pPage->leaf; - pBt = pPage->pBt; - if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ - pPage->intKey = 1; - pPage->hasData = pPage->leaf; - pPage->maxLocal = pBt->maxLeaf; - pPage->minLocal = pBt->minLeaf; - }else if( flagByte==PTF_ZERODATA ){ - pPage->intKey = 0; - pPage->hasData = 0; - pPage->maxLocal = pBt->maxLocal; - pPage->minLocal = pBt->minLocal; - }else{ - return SQLITE_CORRUPT_BKPT; - } - pPage->max1bytePayload = pBt->max1bytePayload; - return SQLITE_OK; -} - -/* -** Initialize the auxiliary information for a disk block. -** -** Return SQLITE_OK on success. If we see that the page does -** not contain a well-formed database page, then return -** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not -** guarantee that the page is well-formed. It only shows that -** we failed to detect any corruption. -*/ -static int btreeInitPage(MemPage *pPage){ - - assert( pPage->pBt!=0 ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); - assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); - assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); - - if( !pPage->isInit ){ - u16 pc; /* Address of a freeblock within pPage->aData[] */ - u8 hdr; /* Offset to beginning of page header */ - u8 *data; /* Equal to pPage->aData */ - BtShared *pBt; /* The main btree structure */ - int usableSize; /* Amount of usable space on each page */ - u16 cellOffset; /* Offset from start of page to first cell pointer */ - int nFree; /* Number of unused bytes on the page */ - int top; /* First byte of the cell content area */ - int iCellFirst; /* First allowable cell or freeblock offset */ - int iCellLast; /* Last possible cell or freeblock offset */ - - pBt = pPage->pBt; - - hdr = pPage->hdrOffset; - data = pPage->aData; - if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT; - assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); - pPage->maskPage = (u16)(pBt->pageSize - 1); - pPage->nOverflow = 0; - usableSize = pBt->usableSize; - pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; - pPage->aDataEnd = &data[usableSize]; - pPage->aCellIdx = &data[cellOffset]; - top = get2byteNotZero(&data[hdr+5]); - pPage->nCell = get2byte(&data[hdr+3]); - if( pPage->nCell>MX_CELL(pBt) ){ - /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_BKPT; - } - testcase( pPage->nCell==MX_CELL(pBt) ); - - /* A malformed database page might cause us to read past the end - ** of page when parsing a cell. - ** - ** The following block of code checks early to see if a cell extends - ** past the end of a page boundary and causes SQLITE_CORRUPT to be - ** returned if it does. - */ - iCellFirst = cellOffset + 2*pPage->nCell; - iCellLast = usableSize - 4; -#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK) - { - int i; /* Index into the cell pointer array */ - int sz; /* Size of a cell */ - - if( !pPage->leaf ) iCellLast--; - for(i=0; inCell; i++){ - pc = get2byte(&data[cellOffset+i*2]); - testcase( pc==iCellFirst ); - testcase( pc==iCellLast ); - if( pciCellLast ){ - return SQLITE_CORRUPT_BKPT; - } - sz = cellSizePtr(pPage, &data[pc]); - testcase( pc+sz==usableSize ); - if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_BKPT; - } - } - if( !pPage->leaf ) iCellLast++; - } -#endif - - /* Compute the total free space on the page */ - pc = get2byte(&data[hdr+1]); - nFree = data[hdr+7] + top; - while( pc>0 ){ - u16 next, size; - if( pciCellLast ){ - /* Start of free block is off the page */ - return SQLITE_CORRUPT_BKPT; - } - next = get2byte(&data[pc]); - size = get2byte(&data[pc+2]); - if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){ - /* Free blocks must be in ascending order. And the last byte of - ** the free-block must lie on the database page. */ - return SQLITE_CORRUPT_BKPT; - } - nFree = nFree + size; - pc = next; - } - - /* At this point, nFree contains the sum of the offset to the start - ** of the cell-content area plus the number of free bytes within - ** the cell-content area. If this is greater than the usable-size - ** of the page, then the page must be corrupted. This check also - ** serves to verify that the offset to the start of the cell-content - ** area, according to the page header, lies within the page. - */ - if( nFree>usableSize ){ - return SQLITE_CORRUPT_BKPT; - } - pPage->nFree = (u16)(nFree - iCellFirst); - pPage->isInit = 1; - } - return SQLITE_OK; -} - -/* -** Set up a raw page so that it looks like a database page holding -** no entries. -*/ -static void zeroPage(MemPage *pPage, int flags){ - unsigned char *data = pPage->aData; - BtShared *pBt = pPage->pBt; - u8 hdr = pPage->hdrOffset; - u16 first; - - assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); - assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); - assert( sqlite3PagerGetData(pPage->pDbPage) == data ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pBt->btsFlags & BTS_SECURE_DELETE ){ - memset(&data[hdr], 0, pBt->usableSize - hdr); - } - data[hdr] = (char)flags; - first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0); - memset(&data[hdr+1], 0, 4); - data[hdr+7] = 0; - put2byte(&data[hdr+5], pBt->usableSize); - pPage->nFree = (u16)(pBt->usableSize - first); - decodeFlags(pPage, flags); - pPage->hdrOffset = hdr; - pPage->cellOffset = first; - pPage->aDataEnd = &data[pBt->usableSize]; - pPage->aCellIdx = &data[first]; - pPage->nOverflow = 0; - assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); - pPage->maskPage = (u16)(pBt->pageSize - 1); - pPage->nCell = 0; - pPage->isInit = 1; -} - - -/* -** Convert a DbPage obtained from the pager into a MemPage used by -** the btree layer. -*/ -static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){ - MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); - pPage->aData = sqlite3PagerGetData(pDbPage); - pPage->pDbPage = pDbPage; - pPage->pBt = pBt; - pPage->pgno = pgno; - pPage->hdrOffset = pPage->pgno==1 ? 100 : 0; - return pPage; -} - -/* -** Get a page from the pager. Initialize the MemPage.pBt and -** MemPage.aData elements if needed. -** -** If the noContent flag is set, it means that we do not care about -** the content of the page at this time. So do not go to the disk -** to fetch the content. Just fill in the content with zeros for now. -** If in the future we call sqlite3PagerWrite() on this page, that -** means we have started to be concerned about content and the disk -** read should occur at that point. -*/ -static int btreeGetPage( - BtShared *pBt, /* The btree */ - Pgno pgno, /* Number of the page to fetch */ - MemPage **ppPage, /* Return the page in this parameter */ - int noContent, /* Do not load page content if true */ - int bReadonly /* True if a read-only (mmap) page is ok */ -){ - int rc; - DbPage *pDbPage; - int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0) - | (bReadonly ? PAGER_ACQUIRE_READONLY : 0); - - assert( noContent==0 || bReadonly==0 ); - assert( sqlite3_mutex_held(pBt->mutex) ); - rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags); - if( rc ) return rc; - *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); - return SQLITE_OK; -} - -/* -** Retrieve a page from the pager cache. If the requested page is not -** already in the pager cache return NULL. Initialize the MemPage.pBt and -** MemPage.aData elements if needed. -*/ -static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){ - DbPage *pDbPage; - assert( sqlite3_mutex_held(pBt->mutex) ); - pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); - if( pDbPage ){ - return btreePageFromDbPage(pDbPage, pgno, pBt); - } - return 0; -} - -/* -** Return the size of the database file in pages. If there is any kind of -** error, return ((unsigned int)-1). -*/ -static Pgno btreePagecount(BtShared *pBt){ - return pBt->nPage; -} -SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){ - assert( sqlite3BtreeHoldsMutex(p) ); - assert( ((p->pBt->nPage)&0x8000000)==0 ); - return (int)btreePagecount(p->pBt); -} - -/* -** Get a page from the pager and initialize it. This routine is just a -** convenience wrapper around separate calls to btreeGetPage() and -** btreeInitPage(). -** -** If an error occurs, then the value *ppPage is set to is undefined. It -** may remain unchanged, or it may be set to an invalid value. -*/ -static int getAndInitPage( - BtShared *pBt, /* The database file */ - Pgno pgno, /* Number of the page to get */ - MemPage **ppPage, /* Write the page pointer here */ - int bReadonly /* True if a read-only (mmap) page is ok */ -){ - int rc; - assert( sqlite3_mutex_held(pBt->mutex) ); - - if( pgno>btreePagecount(pBt) ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = btreeGetPage(pBt, pgno, ppPage, 0, bReadonly); - if( rc==SQLITE_OK ){ - rc = btreeInitPage(*ppPage); - if( rc!=SQLITE_OK ){ - releasePage(*ppPage); - } - } - } - - testcase( pgno==0 ); - assert( pgno!=0 || rc==SQLITE_CORRUPT ); - return rc; -} - -/* -** Release a MemPage. This should be called once for each prior -** call to btreeGetPage. -*/ -static void releasePage(MemPage *pPage){ - if( pPage ){ - assert( pPage->aData ); - assert( pPage->pBt ); - assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); - assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - sqlite3PagerUnref(pPage->pDbPage); - } -} - -/* -** During a rollback, when the pager reloads information into the cache -** so that the cache is restored to its original state at the start of -** the transaction, for each page restored this routine is called. -** -** This routine needs to reset the extra data section at the end of the -** page to agree with the restored data. -*/ -static void pageReinit(DbPage *pData){ - MemPage *pPage; - pPage = (MemPage *)sqlite3PagerGetExtra(pData); - assert( sqlite3PagerPageRefcount(pData)>0 ); - if( pPage->isInit ){ - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pPage->isInit = 0; - if( sqlite3PagerPageRefcount(pData)>1 ){ - /* pPage might not be a btree page; it might be an overflow page - ** or ptrmap page or a free page. In those cases, the following - ** call to btreeInitPage() will likely return SQLITE_CORRUPT. - ** But no harm is done by this. And it is very important that - ** btreeInitPage() be called on every btree page so we make - ** the call for every page that comes in for re-initing. */ - btreeInitPage(pPage); - } - } -} - -/* -** Invoke the busy handler for a btree. -*/ -static int btreeInvokeBusyHandler(void *pArg){ - BtShared *pBt = (BtShared*)pArg; - assert( pBt->db ); - assert( sqlite3_mutex_held(pBt->db->mutex) ); - return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); -} - -/* -** Open a database file. -** -** zFilename is the name of the database file. If zFilename is NULL -** then an ephemeral database is created. The ephemeral database might -** be exclusively in memory, or it might use a disk-based memory cache. -** Either way, the ephemeral database will be automatically deleted -** when sqlite3BtreeClose() is called. -** -** If zFilename is ":memory:" then an in-memory database is created -** that is automatically destroyed when it is closed. -** -** The "flags" parameter is a bitmask that might contain bits like -** BTREE_OMIT_JOURNAL and/or BTREE_MEMORY. -** -** If the database is already opened in the same database connection -** and we are in shared cache mode, then the open will fail with an -** SQLITE_CONSTRAINT error. We cannot allow two or more BtShared -** objects in the same database connection since doing so will lead -** to problems with locking. -*/ -SQLITE_PRIVATE int sqlite3BtreeOpen( - sqlite3_vfs *pVfs, /* VFS to use for this b-tree */ - const char *zFilename, /* Name of the file containing the BTree database */ - sqlite3 *db, /* Associated database handle */ - Btree **ppBtree, /* Pointer to new Btree object written here */ - int flags, /* Options */ - int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */ -){ - BtShared *pBt = 0; /* Shared part of btree structure */ - Btree *p; /* Handle to return */ - sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */ - int rc = SQLITE_OK; /* Result code from this function */ - u8 nReserve; /* Byte of unused space on each page */ - unsigned char zDbHeader[100]; /* Database header content */ - - /* True if opening an ephemeral, temporary database */ - const int isTempDb = zFilename==0 || zFilename[0]==0; - - /* Set the variable isMemdb to true for an in-memory database, or - ** false for a file-based database. - */ -#ifdef SQLITE_OMIT_MEMORYDB - const int isMemdb = 0; -#else - const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0) - || (isTempDb && sqlite3TempInMemory(db)) - || (vfsFlags & SQLITE_OPEN_MEMORY)!=0; -#endif - - assert( db!=0 ); - assert( pVfs!=0 ); - assert( sqlite3_mutex_held(db->mutex) ); - assert( (flags&0xff)==flags ); /* flags fit in 8 bits */ - - /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */ - assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 ); - - /* A BTREE_SINGLE database is always a temporary and/or ephemeral */ - assert( (flags & BTREE_SINGLE)==0 || isTempDb ); - - if( isMemdb ){ - flags |= BTREE_MEMORY; - } - if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){ - vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; - } - p = sqlite3MallocZero(sizeof(Btree)); - if( !p ){ - return SQLITE_NOMEM; - } - p->inTrans = TRANS_NONE; - p->db = db; -#ifndef SQLITE_OMIT_SHARED_CACHE - p->lock.pBtree = p; - p->lock.iTable = 1; -#endif - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) - /* - ** If this Btree is a candidate for shared cache, try to find an - ** existing BtShared object that we can share with - */ - if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){ - if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ - int nFullPathname = pVfs->mxPathname+1; - char *zFullPathname = sqlite3Malloc(nFullPathname); - MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) - p->sharable = 1; - if( !zFullPathname ){ - sqlite3_free(p); - return SQLITE_NOMEM; - } - if( isMemdb ){ - memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1); - }else{ - rc = sqlite3OsFullPathname(pVfs, zFilename, - nFullPathname, zFullPathname); - if( rc ){ - sqlite3_free(zFullPathname); - sqlite3_free(p); - return rc; - } - } -#if SQLITE_THREADSAFE - mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN); - sqlite3_mutex_enter(mutexOpen); - mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); - sqlite3_mutex_enter(mutexShared); -#endif - for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){ - assert( pBt->nRef>0 ); - if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0)) - && sqlite3PagerVfs(pBt->pPager)==pVfs ){ - int iDb; - for(iDb=db->nDb-1; iDb>=0; iDb--){ - Btree *pExisting = db->aDb[iDb].pBt; - if( pExisting && pExisting->pBt==pBt ){ - sqlite3_mutex_leave(mutexShared); - sqlite3_mutex_leave(mutexOpen); - sqlite3_free(zFullPathname); - sqlite3_free(p); - return SQLITE_CONSTRAINT; - } - } - p->pBt = pBt; - pBt->nRef++; - break; - } - } - sqlite3_mutex_leave(mutexShared); - sqlite3_free(zFullPathname); - } -#ifdef SQLITE_DEBUG - else{ - /* In debug mode, we mark all persistent databases as sharable - ** even when they are not. This exercises the locking code and - ** gives more opportunity for asserts(sqlite3_mutex_held()) - ** statements to find locking problems. - */ - p->sharable = 1; - } -#endif - } -#endif - if( pBt==0 ){ - /* - ** The following asserts make sure that structures used by the btree are - ** the right size. This is to guard against size changes that result - ** when compiling on a different architecture. - */ - assert( sizeof(i64)==8 || sizeof(i64)==4 ); - assert( sizeof(u64)==8 || sizeof(u64)==4 ); - assert( sizeof(u32)==4 ); - assert( sizeof(u16)==2 ); - assert( sizeof(Pgno)==4 ); - - pBt = sqlite3MallocZero( sizeof(*pBt) ); - if( pBt==0 ){ - rc = SQLITE_NOMEM; - goto btree_open_out; - } - rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, - EXTRA_SIZE, flags, vfsFlags, pageReinit); - if( rc==SQLITE_OK ){ - sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); - rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); - } - if( rc!=SQLITE_OK ){ - goto btree_open_out; - } - pBt->openFlags = (u8)flags; - pBt->db = db; - sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); - p->pBt = pBt; - - pBt->pCursor = 0; - pBt->pPage1 = 0; - if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY; -#ifdef SQLITE_SECURE_DELETE - pBt->btsFlags |= BTS_SECURE_DELETE; -#endif - pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16); - if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE - || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ - pBt->pageSize = 0; -#ifndef SQLITE_OMIT_AUTOVACUUM - /* If the magic name ":memory:" will create an in-memory database, then - ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if - ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if - ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a - ** regular file-name. In this case the auto-vacuum applies as per normal. - */ - if( zFilename && !isMemdb ){ - pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0); - pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0); - } -#endif - nReserve = 0; - }else{ - nReserve = zDbHeader[20]; - pBt->btsFlags |= BTS_PAGESIZE_FIXED; -#ifndef SQLITE_OMIT_AUTOVACUUM - pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0); - pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0); -#endif - } - rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); - if( rc ) goto btree_open_out; - pBt->usableSize = pBt->pageSize - nReserve; - assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) - /* Add the new BtShared object to the linked list sharable BtShareds. - */ - if( p->sharable ){ - MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) - pBt->nRef = 1; - MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);) - if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){ - pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); - if( pBt->mutex==0 ){ - rc = SQLITE_NOMEM; - db->mallocFailed = 0; - goto btree_open_out; - } - } - sqlite3_mutex_enter(mutexShared); - pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList); - GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt; - sqlite3_mutex_leave(mutexShared); - } -#endif - } - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) - /* If the new Btree uses a sharable pBtShared, then link the new - ** Btree into the list of all sharable Btrees for the same connection. - ** The list is kept in ascending order by pBt address. - */ - if( p->sharable ){ - int i; - Btree *pSib; - for(i=0; inDb; i++){ - if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){ - while( pSib->pPrev ){ pSib = pSib->pPrev; } - if( p->pBtpBt ){ - p->pNext = pSib; - p->pPrev = 0; - pSib->pPrev = p; - }else{ - while( pSib->pNext && pSib->pNext->pBtpBt ){ - pSib = pSib->pNext; - } - p->pNext = pSib->pNext; - p->pPrev = pSib; - if( p->pNext ){ - p->pNext->pPrev = p; - } - pSib->pNext = p; - } - break; - } - } - } -#endif - *ppBtree = p; - -btree_open_out: - if( rc!=SQLITE_OK ){ - if( pBt && pBt->pPager ){ - sqlite3PagerClose(pBt->pPager); - } - sqlite3_free(pBt); - sqlite3_free(p); - *ppBtree = 0; - }else{ - /* If the B-Tree was successfully opened, set the pager-cache size to the - ** default value. Except, when opening on an existing shared pager-cache, - ** do not change the pager-cache size. - */ - if( sqlite3BtreeSchema(p, 0, 0)==0 ){ - sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); - } - } - if( mutexOpen ){ - assert( sqlite3_mutex_held(mutexOpen) ); - sqlite3_mutex_leave(mutexOpen); - } - return rc; -} - -/* -** Decrement the BtShared.nRef counter. When it reaches zero, -** remove the BtShared structure from the sharing list. Return -** true if the BtShared.nRef counter reaches zero and return -** false if it is still positive. -*/ -static int removeFromSharingList(BtShared *pBt){ -#ifndef SQLITE_OMIT_SHARED_CACHE - MUTEX_LOGIC( sqlite3_mutex *pMaster; ) - BtShared *pList; - int removed = 0; - - assert( sqlite3_mutex_notheld(pBt->mutex) ); - MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) - sqlite3_mutex_enter(pMaster); - pBt->nRef--; - if( pBt->nRef<=0 ){ - if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){ - GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext; - }else{ - pList = GLOBAL(BtShared*,sqlite3SharedCacheList); - while( ALWAYS(pList) && pList->pNext!=pBt ){ - pList=pList->pNext; - } - if( ALWAYS(pList) ){ - pList->pNext = pBt->pNext; - } - } - if( SQLITE_THREADSAFE ){ - sqlite3_mutex_free(pBt->mutex); - } - removed = 1; - } - sqlite3_mutex_leave(pMaster); - return removed; -#else - return 1; -#endif -} - -/* -** Make sure pBt->pTmpSpace points to an allocation of -** MX_CELL_SIZE(pBt) bytes. -*/ -static void allocateTempSpace(BtShared *pBt){ - if( !pBt->pTmpSpace ){ - pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); - } -} - -/* -** Free the pBt->pTmpSpace allocation -*/ -static void freeTempSpace(BtShared *pBt){ - sqlite3PageFree( pBt->pTmpSpace); - pBt->pTmpSpace = 0; -} - -/* -** Close an open database and invalidate all cursors. -*/ -SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ - BtShared *pBt = p->pBt; - BtCursor *pCur; - - /* Close all cursors opened via this handle. */ - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - pCur = pBt->pCursor; - while( pCur ){ - BtCursor *pTmp = pCur; - pCur = pCur->pNext; - if( pTmp->pBtree==p ){ - sqlite3BtreeCloseCursor(pTmp); - } - } - - /* Rollback any active transaction and free the handle structure. - ** The call to sqlite3BtreeRollback() drops any table-locks held by - ** this handle. - */ - sqlite3BtreeRollback(p, SQLITE_OK); - sqlite3BtreeLeave(p); - - /* If there are still other outstanding references to the shared-btree - ** structure, return now. The remainder of this procedure cleans - ** up the shared-btree. - */ - assert( p->wantToLock==0 && p->locked==0 ); - if( !p->sharable || removeFromSharingList(pBt) ){ - /* The pBt is no longer on the sharing list, so we can access - ** it without having to hold the mutex. - ** - ** Clean out and delete the BtShared object. - */ - assert( !pBt->pCursor ); - sqlite3PagerClose(pBt->pPager); - if( pBt->xFreeSchema && pBt->pSchema ){ - pBt->xFreeSchema(pBt->pSchema); - } - sqlite3DbFree(0, pBt->pSchema); - freeTempSpace(pBt); - sqlite3_free(pBt); - } - -#ifndef SQLITE_OMIT_SHARED_CACHE - assert( p->wantToLock==0 ); - assert( p->locked==0 ); - if( p->pPrev ) p->pPrev->pNext = p->pNext; - if( p->pNext ) p->pNext->pPrev = p->pPrev; -#endif - - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Change the limit on the number of pages allowed in the cache. -** -** The maximum number of cache pages is set to the absolute -** value of mxPage. If mxPage is negative, the pager will -** operate asynchronously - it will not stop to do fsync()s -** to insure data is written to the disk surface before -** continuing. Transactions still work if synchronous is off, -** and the database cannot be corrupted if this program -** crashes. But if the operating system crashes or there is -** an abrupt power failure when synchronous is off, the database -** could be left in an inconsistent and unrecoverable state. -** Synchronous is on by default so database corruption is not -** normally a worry. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ - BtShared *pBt = p->pBt; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - sqlite3PagerSetCachesize(pBt->pPager, mxPage); - sqlite3BtreeLeave(p); - return SQLITE_OK; -} - -/* -** Change the limit on the amount of the database file that may be -** memory mapped. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){ - BtShared *pBt = p->pBt; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - sqlite3PagerSetMmapLimit(pBt->pPager, szMmap); - sqlite3BtreeLeave(p); - return SQLITE_OK; -} - -/* -** Change the way data is synced to disk in order to increase or decrease -** how well the database resists damage due to OS crashes and power -** failures. Level 1 is the same as asynchronous (no syncs() occur and -** there is a high probability of damage) Level 2 is the default. There -** is a very low but non-zero probability of damage. Level 3 reduces the -** probability of damage to near zero but with a write performance reduction. -*/ -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel( - Btree *p, /* The btree to set the safety level on */ - int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */ - int fullSync, /* PRAGMA fullfsync. */ - int ckptFullSync /* PRAGMA checkpoint_fullfync */ -){ - BtShared *pBt = p->pBt; - assert( sqlite3_mutex_held(p->db->mutex) ); - assert( level>=1 && level<=3 ); - sqlite3BtreeEnter(p); - sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync); - sqlite3BtreeLeave(p); - return SQLITE_OK; -} -#endif - -/* -** Return TRUE if the given btree is set to safety level 1. In other -** words, return TRUE if no sync() occurs on the disk files. -*/ -SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree *p){ - BtShared *pBt = p->pBt; - int rc; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - assert( pBt && pBt->pPager ); - rc = sqlite3PagerNosync(pBt->pPager); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Change the default pages size and the number of reserved bytes per page. -** Or, if the page size has already been fixed, return SQLITE_READONLY -** without changing anything. -** -** The page size must be a power of 2 between 512 and 65536. If the page -** size supplied does not meet this constraint then the page size is not -** changed. -** -** Page sizes are constrained to be a power of two so that the region -** of the database file used for locking (beginning at PENDING_BYTE, -** the first byte past the 1GB boundary, 0x40000000) needs to occur -** at the beginning of a page. -** -** If parameter nReserve is less than zero, then the number of reserved -** bytes per page is left unchanged. -** -** If the iFix!=0 then the BTS_PAGESIZE_FIXED flag is set so that the page size -** and autovacuum mode can no longer be changed. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){ - int rc = SQLITE_OK; - BtShared *pBt = p->pBt; - assert( nReserve>=-1 && nReserve<=255 ); - sqlite3BtreeEnter(p); - if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ - sqlite3BtreeLeave(p); - return SQLITE_READONLY; - } - if( nReserve<0 ){ - nReserve = pBt->pageSize - pBt->usableSize; - } - assert( nReserve>=0 && nReserve<=255 ); - if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && - ((pageSize-1)&pageSize)==0 ){ - assert( (pageSize & 7)==0 ); - assert( !pBt->pPage1 && !pBt->pCursor ); - pBt->pageSize = (u32)pageSize; - freeTempSpace(pBt); - } - rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve); - pBt->usableSize = pBt->pageSize - (u16)nReserve; - if( iFix ) pBt->btsFlags |= BTS_PAGESIZE_FIXED; - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Return the currently defined page size -*/ -SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){ - return p->pBt->pageSize; -} - -#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG) -/* -** This function is similar to sqlite3BtreeGetReserve(), except that it -** may only be called if it is guaranteed that the b-tree mutex is already -** held. -** -** This is useful in one special case in the backup API code where it is -** known that the shared b-tree mutex is held, but the mutex on the -** database handle that owns *p is not. In this case if sqlite3BtreeEnter() -** were to be called, it might collide with some other operation on the -** database handle that owns *p, causing undefined behavior. -*/ -SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ - assert( sqlite3_mutex_held(p->pBt->mutex) ); - return p->pBt->pageSize - p->pBt->usableSize; -} -#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */ - -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) -/* -** Return the number of bytes of space at the end of every page that -** are intentually left unused. This is the "reserved" space that is -** sometimes used by extensions. -*/ -SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree *p){ - int n; - sqlite3BtreeEnter(p); - n = p->pBt->pageSize - p->pBt->usableSize; - sqlite3BtreeLeave(p); - return n; -} - -/* -** Set the maximum page count for a database if mxPage is positive. -** No changes are made if mxPage is 0 or negative. -** Regardless of the value of mxPage, return the maximum page count. -*/ -SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){ - int n; - sqlite3BtreeEnter(p); - n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); - sqlite3BtreeLeave(p); - return n; -} - -/* -** Set the BTS_SECURE_DELETE flag if newFlag is 0 or 1. If newFlag is -1, -** then make no changes. Always return the value of the BTS_SECURE_DELETE -** setting after the change. -*/ -SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ - int b; - if( p==0 ) return 0; - sqlite3BtreeEnter(p); - if( newFlag>=0 ){ - p->pBt->btsFlags &= ~BTS_SECURE_DELETE; - if( newFlag ) p->pBt->btsFlags |= BTS_SECURE_DELETE; - } - b = (p->pBt->btsFlags & BTS_SECURE_DELETE)!=0; - sqlite3BtreeLeave(p); - return b; -} -#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ - -/* -** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' -** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it -** is disabled. The default value for the auto-vacuum property is -** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ -#ifdef SQLITE_OMIT_AUTOVACUUM - return SQLITE_READONLY; -#else - BtShared *pBt = p->pBt; - int rc = SQLITE_OK; - u8 av = (u8)autoVacuum; - - sqlite3BtreeEnter(p); - if( (pBt->btsFlags & BTS_PAGESIZE_FIXED)!=0 && (av ?1:0)!=pBt->autoVacuum ){ - rc = SQLITE_READONLY; - }else{ - pBt->autoVacuum = av ?1:0; - pBt->incrVacuum = av==2 ?1:0; - } - sqlite3BtreeLeave(p); - return rc; -#endif -} - -/* -** Return the value of the 'auto-vacuum' property. If auto-vacuum is -** enabled 1 is returned. Otherwise 0. -*/ -SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){ -#ifdef SQLITE_OMIT_AUTOVACUUM - return BTREE_AUTOVACUUM_NONE; -#else - int rc; - sqlite3BtreeEnter(p); - rc = ( - (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE: - (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL: - BTREE_AUTOVACUUM_INCR - ); - sqlite3BtreeLeave(p); - return rc; -#endif -} - - -/* -** Get a reference to pPage1 of the database file. This will -** also acquire a readlock on that file. -** -** SQLITE_OK is returned on success. If the file is not a -** well-formed database file, then SQLITE_CORRUPT is returned. -** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM -** is returned if we run out of memory. -*/ -static int lockBtree(BtShared *pBt){ - int rc; /* Result code from subfunctions */ - MemPage *pPage1; /* Page 1 of the database file */ - int nPage; /* Number of pages in the database */ - int nPageFile = 0; /* Number of pages in the database file */ - int nPageHeader; /* Number of pages in the database according to hdr */ - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pBt->pPage1==0 ); - rc = sqlite3PagerSharedLock(pBt->pPager); - if( rc!=SQLITE_OK ) return rc; - rc = btreeGetPage(pBt, 1, &pPage1, 0, 0); - if( rc!=SQLITE_OK ) return rc; - - /* Do some checking to help insure the file we opened really is - ** a valid database file. - */ - nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData); - sqlite3PagerPagecount(pBt->pPager, &nPageFile); - if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ - nPage = nPageFile; - } - if( nPage>0 ){ - u32 pageSize; - u32 usableSize; - u8 *page1 = pPage1->aData; - rc = SQLITE_NOTADB; - if( memcmp(page1, zMagicHeader, 16)!=0 ){ - goto page1_init_failed; - } - -#ifdef SQLITE_OMIT_WAL - if( page1[18]>1 ){ - pBt->btsFlags |= BTS_READ_ONLY; - } - if( page1[19]>1 ){ - goto page1_init_failed; - } -#else - if( page1[18]>2 ){ - pBt->btsFlags |= BTS_READ_ONLY; - } - if( page1[19]>2 ){ - goto page1_init_failed; - } - - /* If the write version is set to 2, this database should be accessed - ** in WAL mode. If the log is not already open, open it now. Then - ** return SQLITE_OK and return without populating BtShared.pPage1. - ** The caller detects this and calls this function again. This is - ** required as the version of page 1 currently in the page1 buffer - ** may not be the latest version - there may be a newer one in the log - ** file. - */ - if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){ - int isOpen = 0; - rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen); - if( rc!=SQLITE_OK ){ - goto page1_init_failed; - }else if( isOpen==0 ){ - releasePage(pPage1); - return SQLITE_OK; - } - rc = SQLITE_NOTADB; - } -#endif - - /* The maximum embedded fraction must be exactly 25%. And the minimum - ** embedded fraction must be 12.5% for both leaf-data and non-leaf-data. - ** The original design allowed these amounts to vary, but as of - ** version 3.6.0, we require them to be fixed. - */ - if( memcmp(&page1[21], "\100\040\040",3)!=0 ){ - goto page1_init_failed; - } - pageSize = (page1[16]<<8) | (page1[17]<<16); - if( ((pageSize-1)&pageSize)!=0 - || pageSize>SQLITE_MAX_PAGE_SIZE - || pageSize<=256 - ){ - goto page1_init_failed; - } - assert( (pageSize & 7)==0 ); - usableSize = pageSize - page1[20]; - if( (u32)pageSize!=pBt->pageSize ){ - /* After reading the first page of the database assuming a page size - ** of BtShared.pageSize, we have discovered that the page-size is - ** actually pageSize. Unlock the database, leave pBt->pPage1 at - ** zero and return SQLITE_OK. The caller will call this function - ** again with the correct page-size. - */ - releasePage(pPage1); - pBt->usableSize = usableSize; - pBt->pageSize = pageSize; - freeTempSpace(pBt); - rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, - pageSize-usableSize); - return rc; - } - if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){ - rc = SQLITE_CORRUPT_BKPT; - goto page1_init_failed; - } - if( usableSize<480 ){ - goto page1_init_failed; - } - pBt->pageSize = pageSize; - pBt->usableSize = usableSize; -#ifndef SQLITE_OMIT_AUTOVACUUM - pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); - pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); -#endif - } - - /* maxLocal is the maximum amount of payload to store locally for - ** a cell. Make sure it is small enough so that at least minFanout - ** cells can will fit on one page. We assume a 10-byte page header. - ** Besides the payload, the cell must store: - ** 2-byte pointer to the cell - ** 4-byte child pointer - ** 9-byte nKey value - ** 4-byte nData value - ** 4-byte overflow page pointer - ** So a cell consists of a 2-byte pointer, a header which is as much as - ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow - ** page pointer. - */ - pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23); - pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23); - pBt->maxLeaf = (u16)(pBt->usableSize - 35); - pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23); - if( pBt->maxLocal>127 ){ - pBt->max1bytePayload = 127; - }else{ - pBt->max1bytePayload = (u8)pBt->maxLocal; - } - assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); - pBt->pPage1 = pPage1; - pBt->nPage = nPage; - return SQLITE_OK; - -page1_init_failed: - releasePage(pPage1); - pBt->pPage1 = 0; - return rc; -} - -#ifndef NDEBUG -/* -** Return the number of cursors open on pBt. This is for use -** in assert() expressions, so it is only compiled if NDEBUG is not -** defined. -** -** Only write cursors are counted if wrOnly is true. If wrOnly is -** false then all cursors are counted. -** -** For the purposes of this routine, a cursor is any cursor that -** is capable of reading or writing to the databse. Cursors that -** have been tripped into the CURSOR_FAULT state are not counted. -*/ -static int countValidCursors(BtShared *pBt, int wrOnly){ - BtCursor *pCur; - int r = 0; - for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; - } - return r; -} -#endif - -/* -** If there are no outstanding cursors and we are not in the middle -** of a transaction but there is a read lock on the database, then -** this routine unrefs the first page of the database file which -** has the effect of releasing the read lock. -** -** If there is a transaction in progress, this routine is a no-op. -*/ -static void unlockBtreeIfUnused(BtShared *pBt){ - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE ); - if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){ - assert( pBt->pPage1->aData ); - assert( sqlite3PagerRefcount(pBt->pPager)==1 ); - assert( pBt->pPage1->aData ); - releasePage(pBt->pPage1); - pBt->pPage1 = 0; - } -} - -/* -** If pBt points to an empty file then convert that empty file -** into a new empty database by initializing the first page of -** the database. -*/ -static int newDatabase(BtShared *pBt){ - MemPage *pP1; - unsigned char *data; - int rc; - - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pBt->nPage>0 ){ - return SQLITE_OK; - } - pP1 = pBt->pPage1; - assert( pP1!=0 ); - data = pP1->aData; - rc = sqlite3PagerWrite(pP1->pDbPage); - if( rc ) return rc; - memcpy(data, zMagicHeader, sizeof(zMagicHeader)); - assert( sizeof(zMagicHeader)==16 ); - data[16] = (u8)((pBt->pageSize>>8)&0xff); - data[17] = (u8)((pBt->pageSize>>16)&0xff); - data[18] = 1; - data[19] = 1; - assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize); - data[20] = (u8)(pBt->pageSize - pBt->usableSize); - data[21] = 64; - data[22] = 32; - data[23] = 32; - memset(&data[24], 0, 100-24); - zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA ); - pBt->btsFlags |= BTS_PAGESIZE_FIXED; -#ifndef SQLITE_OMIT_AUTOVACUUM - assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 ); - assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 ); - put4byte(&data[36 + 4*4], pBt->autoVacuum); - put4byte(&data[36 + 7*4], pBt->incrVacuum); -#endif - pBt->nPage = 1; - data[31] = 1; - return SQLITE_OK; -} - -/* -** Initialize the first page of the database file (creating a database -** consisting of a single page and no schema objects). Return SQLITE_OK -** if successful, or an SQLite error code otherwise. -*/ -SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){ - int rc; - sqlite3BtreeEnter(p); - p->pBt->nPage = 0; - rc = newDatabase(p->pBt); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Attempt to start a new transaction. A write-transaction -** is started if the second argument is nonzero, otherwise a read- -** transaction. If the second argument is 2 or more and exclusive -** transaction is started, meaning that no other process is allowed -** to access the database. A preexisting transaction may not be -** upgraded to exclusive by calling this routine a second time - the -** exclusivity flag only works for a new transaction. -** -** A write-transaction must be started before attempting any -** changes to the database. None of the following routines -** will work unless a transaction is started first: -** -** sqlite3BtreeCreateTable() -** sqlite3BtreeCreateIndex() -** sqlite3BtreeClearTable() -** sqlite3BtreeDropTable() -** sqlite3BtreeInsert() -** sqlite3BtreeDelete() -** sqlite3BtreeUpdateMeta() -** -** If an initial attempt to acquire the lock fails because of lock contention -** and the database was previously unlocked, then invoke the busy handler -** if there is one. But if there was previously a read-lock, do not -** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is -** returned when there is already a read-lock in order to avoid a deadlock. -** -** Suppose there are two processes A and B. A has a read lock and B has -** a reserved lock. B tries to promote to exclusive but is blocked because -** of A's read lock. A tries to promote to reserved but is blocked by B. -** One or the other of the two processes must give way or there can be -** no progress. By returning SQLITE_BUSY and not invoking the busy callback -** when A already has a read lock, we encourage A to give up and let B -** proceed. -*/ -SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ - sqlite3 *pBlock = 0; - BtShared *pBt = p->pBt; - int rc = SQLITE_OK; - - sqlite3BtreeEnter(p); - btreeIntegrity(p); - - /* If the btree is already in a write-transaction, or it - ** is already in a read-transaction and a read-transaction - ** is requested, this is a no-op. - */ - if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ - goto trans_begun; - } - assert( IfNotOmitAV(pBt->bDoTruncate)==0 ); - - /* Write transactions are not possible on a read-only database */ - if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ - rc = SQLITE_READONLY; - goto trans_begun; - } - -#ifndef SQLITE_OMIT_SHARED_CACHE - /* If another database handle has already opened a write transaction - ** on this shared-btree structure and a second write transaction is - ** requested, return SQLITE_LOCKED. - */ - if( (wrflag && pBt->inTransaction==TRANS_WRITE) - || (pBt->btsFlags & BTS_PENDING)!=0 - ){ - pBlock = pBt->pWriter->db; - }else if( wrflag>1 ){ - BtLock *pIter; - for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ - if( pIter->pBtree!=p ){ - pBlock = pIter->pBtree->db; - break; - } - } - } - if( pBlock ){ - sqlite3ConnectionBlocked(p->db, pBlock); - rc = SQLITE_LOCKED_SHAREDCACHE; - goto trans_begun; - } -#endif - - /* Any read-only or read-write transaction implies a read-lock on - ** page 1. So if some other shared-cache client already has a write-lock - ** on page 1, the transaction cannot be opened. */ - rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); - if( SQLITE_OK!=rc ) goto trans_begun; - - pBt->btsFlags &= ~BTS_INITIALLY_EMPTY; - if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY; - do { - /* Call lockBtree() until either pBt->pPage1 is populated or - ** lockBtree() returns something other than SQLITE_OK. lockBtree() - ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after - ** reading page 1 it discovers that the page-size of the database - ** file is not pBt->pageSize. In this case lockBtree() will update - ** pBt->pageSize to the page-size of the file on disk. - */ - while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) ); - - if( rc==SQLITE_OK && wrflag ){ - if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){ - rc = SQLITE_READONLY; - }else{ - rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db)); - if( rc==SQLITE_OK ){ - rc = newDatabase(pBt); - } - } - } - - if( rc!=SQLITE_OK ){ - unlockBtreeIfUnused(pBt); - } - }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && - btreeInvokeBusyHandler(pBt) ); - - if( rc==SQLITE_OK ){ - if( p->inTrans==TRANS_NONE ){ - pBt->nTransaction++; -#ifndef SQLITE_OMIT_SHARED_CACHE - if( p->sharable ){ - assert( p->lock.pBtree==p && p->lock.iTable==1 ); - p->lock.eLock = READ_LOCK; - p->lock.pNext = pBt->pLock; - pBt->pLock = &p->lock; - } -#endif - } - p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); - if( p->inTrans>pBt->inTransaction ){ - pBt->inTransaction = p->inTrans; - } - if( wrflag ){ - MemPage *pPage1 = pBt->pPage1; -#ifndef SQLITE_OMIT_SHARED_CACHE - assert( !pBt->pWriter ); - pBt->pWriter = p; - pBt->btsFlags &= ~BTS_EXCLUSIVE; - if( wrflag>1 ) pBt->btsFlags |= BTS_EXCLUSIVE; -#endif - - /* If the db-size header field is incorrect (as it may be if an old - ** client has been writing the database file), update it now. Doing - ** this sooner rather than later means the database size can safely - ** re-read the database size from page 1 if a savepoint or transaction - ** rollback occurs within the transaction. - */ - if( pBt->nPage!=get4byte(&pPage1->aData[28]) ){ - rc = sqlite3PagerWrite(pPage1->pDbPage); - if( rc==SQLITE_OK ){ - put4byte(&pPage1->aData[28], pBt->nPage); - } - } - } - } - - -trans_begun: - if( rc==SQLITE_OK && wrflag ){ - /* This call makes sure that the pager has the correct number of - ** open savepoints. If the second parameter is greater than 0 and - ** the sub-journal is not already open, then it will be opened here. - */ - rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); - } - - btreeIntegrity(p); - sqlite3BtreeLeave(p); - return rc; -} - -#ifndef SQLITE_OMIT_AUTOVACUUM - -/* -** Set the pointer-map entries for all children of page pPage. Also, if -** pPage contains cells that point to overflow pages, set the pointer -** map entries for the overflow pages as well. -*/ -static int setChildPtrmaps(MemPage *pPage){ - int i; /* Counter variable */ - int nCell; /* Number of cells in page pPage */ - int rc; /* Return code */ - BtShared *pBt = pPage->pBt; - u8 isInitOrig = pPage->isInit; - Pgno pgno = pPage->pgno; - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - rc = btreeInitPage(pPage); - if( rc!=SQLITE_OK ){ - goto set_child_ptrmaps_out; - } - nCell = pPage->nCell; - - for(i=0; ileaf ){ - Pgno childPgno = get4byte(pCell); - ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); - } - } - - if( !pPage->leaf ){ - Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); - } - -set_child_ptrmaps_out: - pPage->isInit = isInitOrig; - return rc; -} - -/* -** Somewhere on pPage is a pointer to page iFrom. Modify this pointer so -** that it points to iTo. Parameter eType describes the type of pointer to -** be modified, as follows: -** -** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child -** page of pPage. -** -** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow -** page pointed to by one of the cells on pPage. -** -** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next -** overflow page in the list. -*/ -static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - if( eType==PTRMAP_OVERFLOW2 ){ - /* The pointer is always the first 4 bytes of the page in this case. */ - if( get4byte(pPage->aData)!=iFrom ){ - return SQLITE_CORRUPT_BKPT; - } - put4byte(pPage->aData, iTo); - }else{ - u8 isInitOrig = pPage->isInit; - int i; - int nCell; - - btreeInitPage(pPage); - nCell = pPage->nCell; - - for(i=0; iaData+pPage->maskPage - && iFrom==get4byte(&pCell[info.iOverflow]) - ){ - put4byte(&pCell[info.iOverflow], iTo); - break; - } - }else{ - if( get4byte(pCell)==iFrom ){ - put4byte(pCell, iTo); - break; - } - } - } - - if( i==nCell ){ - if( eType!=PTRMAP_BTREE || - get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - return SQLITE_CORRUPT_BKPT; - } - put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); - } - - pPage->isInit = isInitOrig; - } - return SQLITE_OK; -} - - -/* -** Move the open database page pDbPage to location iFreePage in the -** database. The pDbPage reference remains valid. -** -** The isCommit flag indicates that there is no need to remember that -** the journal needs to be sync()ed before database page pDbPage->pgno -** can be written to. The caller has already promised not to write to that -** page. -*/ -static int relocatePage( - BtShared *pBt, /* Btree */ - MemPage *pDbPage, /* Open page to move */ - u8 eType, /* Pointer map 'type' entry for pDbPage */ - Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */ - Pgno iFreePage, /* The location to move pDbPage to */ - int isCommit /* isCommit flag passed to sqlite3PagerMovepage */ -){ - MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ - Pgno iDbPage = pDbPage->pgno; - Pager *pPager = pBt->pPager; - int rc; - - assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || - eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pDbPage->pBt==pBt ); - - /* Move page iDbPage from its current location to page number iFreePage */ - TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", - iDbPage, iFreePage, iPtrPage, eType)); - rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit); - if( rc!=SQLITE_OK ){ - return rc; - } - pDbPage->pgno = iFreePage; - - /* If pDbPage was a btree-page, then it may have child pages and/or cells - ** that point to overflow pages. The pointer map entries for all these - ** pages need to be changed. - ** - ** If pDbPage is an overflow page, then the first 4 bytes may store a - ** pointer to a subsequent overflow page. If this is the case, then - ** the pointer map needs to be updated for the subsequent overflow page. - */ - if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){ - rc = setChildPtrmaps(pDbPage); - if( rc!=SQLITE_OK ){ - return rc; - } - }else{ - Pgno nextOvfl = get4byte(pDbPage->aData); - if( nextOvfl!=0 ){ - ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage, &rc); - if( rc!=SQLITE_OK ){ - return rc; - } - } - } - - /* Fix the database pointer on page iPtrPage that pointed at iDbPage so - ** that it points at iFreePage. Also fix the pointer map entry for - ** iPtrPage. - */ - if( eType!=PTRMAP_ROOTPAGE ){ - rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = sqlite3PagerWrite(pPtrPage->pDbPage); - if( rc!=SQLITE_OK ){ - releasePage(pPtrPage); - return rc; - } - rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType); - releasePage(pPtrPage); - if( rc==SQLITE_OK ){ - ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc); - } - } - return rc; -} - -/* Forward declaration required by incrVacuumStep(). */ -static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); - -/* -** Perform a single step of an incremental-vacuum. If successful, return -** SQLITE_OK. If there is no work to do (and therefore no point in -** calling this function again), return SQLITE_DONE. Or, if an error -** occurs, return some other error code. -** -** More specificly, this function attempts to re-organize the database so -** that the last page of the file currently in use is no longer in use. -** -** Parameter nFin is the number of pages that this database would contain -** were this function called until it returns SQLITE_DONE. -** -** If the bCommit parameter is non-zero, this function assumes that the -** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE -** or an error. bCommit is passed true for an auto-vacuum-on-commmit -** operation, or false for an incremental vacuum. -*/ -static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ - Pgno nFreeList; /* Number of pages still on the free-list */ - int rc; - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( iLastPg>nFin ); - - if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ - u8 eType; - Pgno iPtrPage; - - nFreeList = get4byte(&pBt->pPage1->aData[36]); - if( nFreeList==0 ){ - return SQLITE_DONE; - } - - rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage); - if( rc!=SQLITE_OK ){ - return rc; - } - if( eType==PTRMAP_ROOTPAGE ){ - return SQLITE_CORRUPT_BKPT; - } - - if( eType==PTRMAP_FREEPAGE ){ - if( bCommit==0 ){ - /* Remove the page from the files free-list. This is not required - ** if bCommit is non-zero. In that case, the free-list will be - ** truncated to zero after this function returns, so it doesn't - ** matter if it still contains some garbage entries. - */ - Pgno iFreePg; - MemPage *pFreePg; - rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( iFreePg==iLastPg ); - releasePage(pFreePg); - } - } else { - Pgno iFreePg; /* Index of free page to move pLastPg to */ - MemPage *pLastPg; - u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */ - Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */ - - rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* If bCommit is zero, this loop runs exactly once and page pLastPg - ** is swapped with the first free page pulled off the free list. - ** - ** On the other hand, if bCommit is greater than zero, then keep - ** looping until a free-page located within the first nFin pages - ** of the file is found. - */ - if( bCommit==0 ){ - eMode = BTALLOC_LE; - iNear = nFin; - } - do { - MemPage *pFreePg; - rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode); - if( rc!=SQLITE_OK ){ - releasePage(pLastPg); - return rc; - } - releasePage(pFreePg); - }while( bCommit && iFreePg>nFin ); - assert( iFreePgbDoTruncate = 1; - pBt->nPage = iLastPg; - } - return SQLITE_OK; -} - -/* -** The database opened by the first argument is an auto-vacuum database -** nOrig pages in size containing nFree free pages. Return the expected -** size of the database in pages following an auto-vacuum operation. -*/ -static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){ - int nEntry; /* Number of entries on one ptrmap page */ - Pgno nPtrmap; /* Number of PtrMap pages to be freed */ - Pgno nFin; /* Return value */ - - nEntry = pBt->usableSize/5; - nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; - nFin = nOrig - nFree - nPtrmap; - if( nOrig>PENDING_BYTE_PAGE(pBt) && nFinpBt; - - sqlite3BtreeEnter(p); - assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); - if( !pBt->autoVacuum ){ - rc = SQLITE_DONE; - }else{ - Pgno nOrig = btreePagecount(pBt); - Pgno nFree = get4byte(&pBt->pPage1->aData[36]); - Pgno nFin = finalDbSize(pBt, nOrig, nFree); - - if( nOrig0 ){ - rc = saveAllCursors(pBt, 0, 0); - if( rc==SQLITE_OK ){ - invalidateAllOverflowCache(pBt); - rc = incrVacuumStep(pBt, nFin, nOrig, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - put4byte(&pBt->pPage1->aData[28], pBt->nPage); - } - }else{ - rc = SQLITE_DONE; - } - } - sqlite3BtreeLeave(p); - return rc; -} - -/* -** This routine is called prior to sqlite3PagerCommit when a transaction -** is commited for an auto-vacuum database. -** -** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages -** the database file should be truncated to during the commit process. -** i.e. the database has been reorganized so that only the first *pnTrunc -** pages are in use. -*/ -static int autoVacuumCommit(BtShared *pBt){ - int rc = SQLITE_OK; - Pager *pPager = pBt->pPager; - VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager) ); - - assert( sqlite3_mutex_held(pBt->mutex) ); - invalidateAllOverflowCache(pBt); - assert(pBt->autoVacuum); - if( !pBt->incrVacuum ){ - Pgno nFin; /* Number of pages in database after autovacuuming */ - Pgno nFree; /* Number of pages on the freelist initially */ - Pgno iFree; /* The next page to be freed */ - Pgno nOrig; /* Database size before freeing */ - - nOrig = btreePagecount(pBt); - if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ - /* It is not possible to create a database for which the final page - ** is either a pointer-map page or the pending-byte page. If one - ** is encountered, this indicates corruption. - */ - return SQLITE_CORRUPT_BKPT; - } - - nFree = get4byte(&pBt->pPage1->aData[36]); - nFin = finalDbSize(pBt, nOrig, nFree); - if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; - if( nFinnFin && rc==SQLITE_OK; iFree--){ - rc = incrVacuumStep(pBt, nFin, iFree, 1); - } - if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - put4byte(&pBt->pPage1->aData[32], 0); - put4byte(&pBt->pPage1->aData[36], 0); - put4byte(&pBt->pPage1->aData[28], nFin); - pBt->bDoTruncate = 1; - pBt->nPage = nFin; - } - if( rc!=SQLITE_OK ){ - sqlite3PagerRollback(pPager); - } - } - - assert( nRef>=sqlite3PagerRefcount(pPager) ); - return rc; -} - -#else /* ifndef SQLITE_OMIT_AUTOVACUUM */ -# define setChildPtrmaps(x) SQLITE_OK -#endif - -/* -** This routine does the first phase of a two-phase commit. This routine -** causes a rollback journal to be created (if it does not already exist) -** and populated with enough information so that if a power loss occurs -** the database can be restored to its original state by playing back -** the journal. Then the contents of the journal are flushed out to -** the disk. After the journal is safely on oxide, the changes to the -** database are written into the database file and flushed to oxide. -** At the end of this call, the rollback journal still exists on the -** disk and we are still holding all locks, so the transaction has not -** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the -** commit process. -** -** This call is a no-op if no write-transaction is currently active on pBt. -** -** Otherwise, sync the database file for the btree pBt. zMaster points to -** the name of a master journal file that should be written into the -** individual journal file, or is NULL, indicating no master journal file -** (single database transaction). -** -** When this is called, the master journal should already have been -** created, populated with this journal pointer and synced to disk. -** -** Once this is routine has returned, the only thing required to commit -** the write-transaction for this database file is to delete the journal. -*/ -SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ - int rc = SQLITE_OK; - if( p->inTrans==TRANS_WRITE ){ - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - rc = autoVacuumCommit(pBt); - if( rc!=SQLITE_OK ){ - sqlite3BtreeLeave(p); - return rc; - } - } - if( pBt->bDoTruncate ){ - sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage); - } -#endif - rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0); - sqlite3BtreeLeave(p); - } - return rc; -} - -/* -** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() -** at the conclusion of a transaction. -*/ -static void btreeEndTransaction(Btree *p){ - BtShared *pBt = p->pBt; - assert( sqlite3BtreeHoldsMutex(p) ); - -#ifndef SQLITE_OMIT_AUTOVACUUM - pBt->bDoTruncate = 0; -#endif - if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){ - /* If there are other active statements that belong to this database - ** handle, downgrade to a read-only transaction. The other statements - ** may still be reading from the database. */ - downgradeAllSharedCacheTableLocks(p); - p->inTrans = TRANS_READ; - }else{ - /* If the handle had any kind of transaction open, decrement the - ** transaction count of the shared btree. If the transaction count - ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused() - ** call below will unlock the pager. */ - if( p->inTrans!=TRANS_NONE ){ - clearAllSharedCacheTableLocks(p); - pBt->nTransaction--; - if( 0==pBt->nTransaction ){ - pBt->inTransaction = TRANS_NONE; - } - } - - /* Set the current transaction state to TRANS_NONE and unlock the - ** pager if this call closed the only read or write transaction. */ - p->inTrans = TRANS_NONE; - unlockBtreeIfUnused(pBt); - } - - btreeIntegrity(p); -} - -/* -** Commit the transaction currently in progress. -** -** This routine implements the second phase of a 2-phase commit. The -** sqlite3BtreeCommitPhaseOne() routine does the first phase and should -** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne() -** routine did all the work of writing information out to disk and flushing the -** contents so that they are written onto the disk platter. All this -** routine has to do is delete or truncate or zero the header in the -** the rollback journal (which causes the transaction to commit) and -** drop locks. -** -** Normally, if an error occurs while the pager layer is attempting to -** finalize the underlying journal file, this function returns an error and -** the upper layer will attempt a rollback. However, if the second argument -** is non-zero then this b-tree transaction is part of a multi-file -** transaction. In this case, the transaction has already been committed -** (by deleting a master journal file) and the caller will ignore this -** functions return code. So, even if an error occurs in the pager layer, -** reset the b-tree objects internal state to indicate that the write -** transaction has been closed. This is quite safe, as the pager will have -** transitioned to the error state. -** -** This will release the write lock on the database file. If there -** are no active cursors, it also releases the read lock. -*/ -SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){ - - if( p->inTrans==TRANS_NONE ) return SQLITE_OK; - sqlite3BtreeEnter(p); - btreeIntegrity(p); - - /* If the handle has a write-transaction open, commit the shared-btrees - ** transaction and set the shared state to TRANS_READ. - */ - if( p->inTrans==TRANS_WRITE ){ - int rc; - BtShared *pBt = p->pBt; - assert( pBt->inTransaction==TRANS_WRITE ); - assert( pBt->nTransaction>0 ); - rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); - if( rc!=SQLITE_OK && bCleanup==0 ){ - sqlite3BtreeLeave(p); - return rc; - } - pBt->inTransaction = TRANS_READ; - btreeClearHasContent(pBt); - } - - btreeEndTransaction(p); - sqlite3BtreeLeave(p); - return SQLITE_OK; -} - -/* -** Do both phases of a commit. -*/ -SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){ - int rc; - sqlite3BtreeEnter(p); - rc = sqlite3BtreeCommitPhaseOne(p, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeCommitPhaseTwo(p, 0); - } - sqlite3BtreeLeave(p); - return rc; -} - -/* -** This routine sets the state to CURSOR_FAULT and the error -** code to errCode for every cursor on BtShared that pBtree -** references. -** -** Every cursor is tripped, including cursors that belong -** to other database connections that happen to be sharing -** the cache with pBtree. -** -** This routine gets called when a rollback occurs. -** All cursors using the same cache must be tripped -** to prevent them from trying to use the btree after -** the rollback. The rollback may have deleted tables -** or moved root pages, so it is not sufficient to -** save the state of the cursor. The cursor must be -** invalidated. -*/ -SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ - BtCursor *p; - if( pBtree==0 ) return; - sqlite3BtreeEnter(pBtree); - for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - int i; - sqlite3BtreeClearCursor(p); - p->eState = CURSOR_FAULT; - p->skipNext = errCode; - for(i=0; i<=p->iPage; i++){ - releasePage(p->apPage[i]); - p->apPage[i] = 0; - } - } - sqlite3BtreeLeave(pBtree); -} - -/* -** Rollback the transaction in progress. All cursors will be -** invalided by this operation. Any attempt to use a cursor -** that was open at the beginning of this operation will result -** in an error. -** -** This will release the write lock on the database file. If there -** are no active cursors, it also releases the read lock. -*/ -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){ - int rc; - BtShared *pBt = p->pBt; - MemPage *pPage1; - - sqlite3BtreeEnter(p); - if( tripCode==SQLITE_OK ){ - rc = tripCode = saveAllCursors(pBt, 0, 0); - }else{ - rc = SQLITE_OK; - } - if( tripCode ){ - sqlite3BtreeTripAllCursors(p, tripCode); - } - btreeIntegrity(p); - - if( p->inTrans==TRANS_WRITE ){ - int rc2; - - assert( TRANS_WRITE==pBt->inTransaction ); - rc2 = sqlite3PagerRollback(pBt->pPager); - if( rc2!=SQLITE_OK ){ - rc = rc2; - } - - /* The rollback may have destroyed the pPage1->aData value. So - ** call btreeGetPage() on page 1 again to make - ** sure pPage1->aData is set correctly. */ - if( btreeGetPage(pBt, 1, &pPage1, 0, 0)==SQLITE_OK ){ - int nPage = get4byte(28+(u8*)pPage1->aData); - testcase( nPage==0 ); - if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); - testcase( pBt->nPage!=nPage ); - pBt->nPage = nPage; - releasePage(pPage1); - } - assert( countValidCursors(pBt, 1)==0 ); - pBt->inTransaction = TRANS_READ; - btreeClearHasContent(pBt); - } - - btreeEndTransaction(p); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Start a statement subtransaction. The subtransaction can can be rolled -** back independently of the main transaction. You must start a transaction -** before starting a subtransaction. The subtransaction is ended automatically -** if the main transaction commits or rolls back. -** -** Statement subtransactions are used around individual SQL statements -** that are contained within a BEGIN...COMMIT block. If a constraint -** error occurs within the statement, the effect of that one statement -** can be rolled back without having to rollback the entire transaction. -** -** A statement sub-transaction is implemented as an anonymous savepoint. The -** value passed as the second parameter is the total number of savepoints, -** including the new anonymous savepoint, open on the B-Tree. i.e. if there -** are no active savepoints and no other statement-transactions open, -** iStatement is 1. This anonymous savepoint can be released or rolled back -** using the sqlite3BtreeSavepoint() function. -*/ -SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree *p, int iStatement){ - int rc; - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); - assert( p->inTrans==TRANS_WRITE ); - assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); - assert( iStatement>0 ); - assert( iStatement>p->db->nSavepoint ); - assert( pBt->inTransaction==TRANS_WRITE ); - /* At the pager level, a statement transaction is a savepoint with - ** an index greater than all savepoints created explicitly using - ** SQL statements. It is illegal to open, release or rollback any - ** such savepoints while the statement transaction savepoint is active. - */ - rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** The second argument to this function, op, is always SAVEPOINT_ROLLBACK -** or SAVEPOINT_RELEASE. This function either releases or rolls back the -** savepoint identified by parameter iSavepoint, depending on the value -** of op. -** -** Normally, iSavepoint is greater than or equal to zero. However, if op is -** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the -** contents of the entire transaction are rolled back. This is different -** from a normal transaction rollback, as no locks are released and the -** transaction remains open. -*/ -SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){ - int rc = SQLITE_OK; - if( p && p->inTrans==TRANS_WRITE ){ - BtShared *pBt = p->pBt; - assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); - assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) ); - sqlite3BtreeEnter(p); - rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint); - if( rc==SQLITE_OK ){ - if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){ - pBt->nPage = 0; - } - rc = newDatabase(pBt); - pBt->nPage = get4byte(28 + pBt->pPage1->aData); - - /* The database size was written into the offset 28 of the header - ** when the transaction started, so we know that the value at offset - ** 28 is nonzero. */ - assert( pBt->nPage>0 ); - } - sqlite3BtreeLeave(p); - } - return rc; -} - -/* -** Create a new cursor for the BTree whose root is on the page -** iTable. If a read-only cursor is requested, it is assumed that -** the caller already has at least a read-only transaction open -** on the database already. If a write-cursor is requested, then -** the caller is assumed to have an open write transaction. -** -** If wrFlag==0, then the cursor can only be used for reading. -** If wrFlag==1, then the cursor can be used for reading or for -** writing if other conditions for writing are also met. These -** are the conditions that must be met in order for writing to -** be allowed: -** -** 1: The cursor must have been opened with wrFlag==1 -** -** 2: Other database connections that share the same pager cache -** but which are not in the READ_UNCOMMITTED state may not have -** cursors open with wrFlag==0 on the same table. Otherwise -** the changes made by this write cursor would be visible to -** the read cursors in the other database connection. -** -** 3: The database must be writable (not on read-only media) -** -** 4: There must be an active transaction. -** -** No checking is done to make sure that page iTable really is the -** root page of a b-tree. If it is not, then the cursor acquired -** will not work correctly. -** -** It is assumed that the sqlite3BtreeCursorZero() has been called -** on pCur to initialize the memory space prior to invoking this routine. -*/ -static int btreeCursor( - Btree *p, /* The btree */ - int iTable, /* Root page of table to open */ - int wrFlag, /* 1 to write. 0 read-only */ - struct KeyInfo *pKeyInfo, /* First arg to comparison function */ - BtCursor *pCur /* Space for new cursor */ -){ - BtShared *pBt = p->pBt; /* Shared b-tree handle */ - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( wrFlag==0 || wrFlag==1 ); - - /* The following assert statements verify that if this is a sharable - ** b-tree database, the connection is holding the required table locks, - ** and that no other connection has any open cursor that conflicts with - ** this lock. */ - assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) ); - assert( wrFlag==0 || !hasReadConflicts(p, iTable) ); - - /* Assert that the caller has opened the required transaction. */ - assert( p->inTrans>TRANS_NONE ); - assert( wrFlag==0 || p->inTrans==TRANS_WRITE ); - assert( pBt->pPage1 && pBt->pPage1->aData ); - - if( NEVER(wrFlag && (pBt->btsFlags & BTS_READ_ONLY)!=0) ){ - return SQLITE_READONLY; - } - if( iTable==1 && btreePagecount(pBt)==0 ){ - assert( wrFlag==0 ); - iTable = 0; - } - - /* Now that no other errors can occur, finish filling in the BtCursor - ** variables and link the cursor into the BtShared list. */ - pCur->pgnoRoot = (Pgno)iTable; - pCur->iPage = -1; - pCur->pKeyInfo = pKeyInfo; - pCur->pBtree = p; - pCur->pBt = pBt; - pCur->wrFlag = (u8)wrFlag; - pCur->pNext = pBt->pCursor; - if( pCur->pNext ){ - pCur->pNext->pPrev = pCur; - } - pBt->pCursor = pCur; - pCur->eState = CURSOR_INVALID; - pCur->cachedRowid = 0; - return SQLITE_OK; -} -SQLITE_PRIVATE int sqlite3BtreeCursor( - Btree *p, /* The btree */ - int iTable, /* Root page of table to open */ - int wrFlag, /* 1 to write. 0 read-only */ - struct KeyInfo *pKeyInfo, /* First arg to xCompare() */ - BtCursor *pCur /* Write new cursor here */ -){ - int rc; - sqlite3BtreeEnter(p); - rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Return the size of a BtCursor object in bytes. -** -** This interfaces is needed so that users of cursors can preallocate -** sufficient storage to hold a cursor. The BtCursor object is opaque -** to users so they cannot do the sizeof() themselves - they must call -** this routine. -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){ - return ROUND8(sizeof(BtCursor)); -} - -/* -** Initialize memory that will be converted into a BtCursor object. -** -** The simple approach here would be to memset() the entire object -** to zero. But it turns out that the apPage[] and aiIdx[] arrays -** do not need to be zeroed and they are large, so we can save a lot -** of run-time by skipping the initialization of those elements. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ - memset(p, 0, offsetof(BtCursor, iPage)); -} - -/* -** Set the cached rowid value of every cursor in the same database file -** as pCur and having the same root page number as pCur. The value is -** set to iRowid. -** -** Only positive rowid values are considered valid for this cache. -** The cache is initialized to zero, indicating an invalid cache. -** A btree will work fine with zero or negative rowids. We just cannot -** cache zero or negative rowids, which means tables that use zero or -** negative rowids might run a little slower. But in practice, zero -** or negative rowids are very uncommon so this should not be a problem. -*/ -SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor *pCur, sqlite3_int64 iRowid){ - BtCursor *p; - for(p=pCur->pBt->pCursor; p; p=p->pNext){ - if( p->pgnoRoot==pCur->pgnoRoot ) p->cachedRowid = iRowid; - } - assert( pCur->cachedRowid==iRowid ); -} - -/* -** Return the cached rowid for the given cursor. A negative or zero -** return value indicates that the rowid cache is invalid and should be -** ignored. If the rowid cache has never before been set, then a -** zero is returned. -*/ -SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor *pCur){ - return pCur->cachedRowid; -} - -/* -** Close a cursor. The read lock on the database file is released -** when the last cursor is closed. -*/ -SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ - Btree *pBtree = pCur->pBtree; - if( pBtree ){ - int i; - BtShared *pBt = pCur->pBt; - sqlite3BtreeEnter(pBtree); - sqlite3BtreeClearCursor(pCur); - if( pCur->pPrev ){ - pCur->pPrev->pNext = pCur->pNext; - }else{ - pBt->pCursor = pCur->pNext; - } - if( pCur->pNext ){ - pCur->pNext->pPrev = pCur->pPrev; - } - for(i=0; i<=pCur->iPage; i++){ - releasePage(pCur->apPage[i]); - } - unlockBtreeIfUnused(pBt); - invalidateOverflowCache(pCur); - /* sqlite3_free(pCur); */ - sqlite3BtreeLeave(pBtree); - } - return SQLITE_OK; -} - -/* -** Make sure the BtCursor* given in the argument has a valid -** BtCursor.info structure. If it is not already valid, call -** btreeParseCell() to fill it in. -** -** BtCursor.info is a cache of the information in the current cell. -** Using this cache reduces the number of calls to btreeParseCell(). -** -** 2007-06-25: There is a bug in some versions of MSVC that cause the -** compiler to crash when getCellInfo() is implemented as a macro. -** But there is a measureable speed advantage to using the macro on gcc -** (when less compiler optimizations like -Os or -O0 are used and the -** compiler is not doing agressive inlining.) So we use a real function -** for MSVC and a macro for everything else. Ticket #2457. -*/ -#ifndef NDEBUG - static void assertCellInfo(BtCursor *pCur){ - CellInfo info; - int iPage = pCur->iPage; - memset(&info, 0, sizeof(info)); - btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); - assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); - } -#else - #define assertCellInfo(x) -#endif -#ifdef _MSC_VER - /* Use a real function in MSVC to work around bugs in that compiler. */ - static void getCellInfo(BtCursor *pCur){ - if( pCur->info.nSize==0 ){ - int iPage = pCur->iPage; - btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); - pCur->validNKey = 1; - }else{ - assertCellInfo(pCur); - } - } -#else /* if not _MSC_VER */ - /* Use a macro in all other compilers so that the function is inlined */ -#define getCellInfo(pCur) \ - if( pCur->info.nSize==0 ){ \ - int iPage = pCur->iPage; \ - btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \ - pCur->validNKey = 1; \ - }else{ \ - assertCellInfo(pCur); \ - } -#endif /* _MSC_VER */ - -#ifndef NDEBUG /* The next routine used only within assert() statements */ -/* -** Return true if the given BtCursor is valid. A valid cursor is one -** that is currently pointing to a row in a (non-empty) table. -** This is a verification routine is used only within assert() statements. -*/ -SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ - return pCur && pCur->eState==CURSOR_VALID; -} -#endif /* NDEBUG */ - -/* -** Set *pSize to the size of the buffer needed to hold the value of -** the key for the current entry. If the cursor is not pointing -** to a valid entry, *pSize is set to 0. -** -** For a table with the INTKEY flag set, this routine returns the key -** itself, not the number of bytes in the key. -** -** The caller must position the cursor prior to invoking this routine. -** -** This routine cannot fail. It always returns SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); - if( pCur->eState!=CURSOR_VALID ){ - *pSize = 0; - }else{ - getCellInfo(pCur); - *pSize = pCur->info.nKey; - } - return SQLITE_OK; -} - -/* -** Set *pSize to the number of bytes of data in the entry the -** cursor currently points to. -** -** The caller must guarantee that the cursor is pointing to a non-NULL -** valid entry. In other words, the calling procedure must guarantee -** that the cursor has Cursor.eState==CURSOR_VALID. -** -** Failure is not possible. This function always returns SQLITE_OK. -** It might just as well be a procedure (returning void) but we continue -** to return an integer result code for historical reasons. -*/ -SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - getCellInfo(pCur); - *pSize = pCur->info.nData; - return SQLITE_OK; -} - -/* -** Given the page number of an overflow page in the database (parameter -** ovfl), this function finds the page number of the next page in the -** linked list of overflow pages. If possible, it uses the auto-vacuum -** pointer-map data instead of reading the content of page ovfl to do so. -** -** If an error occurs an SQLite error code is returned. Otherwise: -** -** The page number of the next overflow page in the linked list is -** written to *pPgnoNext. If page ovfl is the last page in its linked -** list, *pPgnoNext is set to zero. -** -** If ppPage is not NULL, and a reference to the MemPage object corresponding -** to page number pOvfl was obtained, then *ppPage is set to point to that -** reference. It is the responsibility of the caller to call releasePage() -** on *ppPage to free the reference. In no reference was obtained (because -** the pointer-map was used to obtain the value for *pPgnoNext), then -** *ppPage is set to zero. -*/ -static int getOverflowPage( - BtShared *pBt, /* The database file */ - Pgno ovfl, /* Current overflow page number */ - MemPage **ppPage, /* OUT: MemPage handle (may be NULL) */ - Pgno *pPgnoNext /* OUT: Next overflow page number */ -){ - Pgno next = 0; - MemPage *pPage = 0; - int rc = SQLITE_OK; - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert(pPgnoNext); - -#ifndef SQLITE_OMIT_AUTOVACUUM - /* Try to find the next page in the overflow list using the - ** autovacuum pointer-map pages. Guess that the next page in - ** the overflow list is page number (ovfl+1). If that guess turns - ** out to be wrong, fall back to loading the data of page - ** number ovfl to determine the next page number. - */ - if( pBt->autoVacuum ){ - Pgno pgno; - Pgno iGuess = ovfl+1; - u8 eType; - - while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){ - iGuess++; - } - - if( iGuess<=btreePagecount(pBt) ){ - rc = ptrmapGet(pBt, iGuess, &eType, &pgno); - if( rc==SQLITE_OK && eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){ - next = iGuess; - rc = SQLITE_DONE; - } - } - } -#endif - - assert( next==0 || rc==SQLITE_DONE ); - if( rc==SQLITE_OK ){ - rc = btreeGetPage(pBt, ovfl, &pPage, 0, (ppPage==0)); - assert( rc==SQLITE_OK || pPage==0 ); - if( rc==SQLITE_OK ){ - next = get4byte(pPage->aData); - } - } - - *pPgnoNext = next; - if( ppPage ){ - *ppPage = pPage; - }else{ - releasePage(pPage); - } - return (rc==SQLITE_DONE ? SQLITE_OK : rc); -} - -/* -** Copy data from a buffer to a page, or from a page to a buffer. -** -** pPayload is a pointer to data stored on database page pDbPage. -** If argument eOp is false, then nByte bytes of data are copied -** from pPayload to the buffer pointed at by pBuf. If eOp is true, -** then sqlite3PagerWrite() is called on pDbPage and nByte bytes -** of data are copied from the buffer pBuf to pPayload. -** -** SQLITE_OK is returned on success, otherwise an error code. -*/ -static int copyPayload( - void *pPayload, /* Pointer to page data */ - void *pBuf, /* Pointer to buffer */ - int nByte, /* Number of bytes to copy */ - int eOp, /* 0 -> copy from page, 1 -> copy to page */ - DbPage *pDbPage /* Page containing pPayload */ -){ - if( eOp ){ - /* Copy data from buffer to page (a write operation) */ - int rc = sqlite3PagerWrite(pDbPage); - if( rc!=SQLITE_OK ){ - return rc; - } - memcpy(pPayload, pBuf, nByte); - }else{ - /* Copy data from page to buffer (a read operation) */ - memcpy(pBuf, pPayload, nByte); - } - return SQLITE_OK; -} - -/* -** This function is used to read or overwrite payload information -** for the entry that the pCur cursor is pointing to. If the eOp -** parameter is 0, this is a read operation (data copied into -** buffer pBuf). If it is non-zero, a write (data copied from -** buffer pBuf). -** -** A total of "amt" bytes are read or written beginning at "offset". -** Data is read to or from the buffer pBuf. -** -** The content being read or written might appear on the main page -** or be scattered out on multiple overflow pages. -** -** If the BtCursor.isIncrblobHandle flag is set, and the current -** cursor entry uses one or more overflow pages, this function -** allocates space for and lazily popluates the overflow page-list -** cache array (BtCursor.aOverflow). Subsequent calls use this -** cache to make seeking to the supplied offset more efficient. -** -** Once an overflow page-list cache has been allocated, it may be -** invalidated if some other cursor writes to the same table, or if -** the cursor is moved to a different row. Additionally, in auto-vacuum -** mode, the following events may invalidate an overflow page-list cache. -** -** * An incremental vacuum, -** * A commit in auto_vacuum="full" mode, -** * Creating a table (may require moving an overflow page). -*/ -static int accessPayload( - BtCursor *pCur, /* Cursor pointing to entry to read from */ - u32 offset, /* Begin reading this far into payload */ - u32 amt, /* Read this many bytes */ - unsigned char *pBuf, /* Write the bytes into this buffer */ - int eOp /* zero to read. non-zero to write. */ -){ - unsigned char *aPayload; - int rc = SQLITE_OK; - u32 nKey; - int iIdx = 0; - MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ - BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ - - assert( pPage ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->aiIdx[pCur->iPage]nCell ); - assert( cursorHoldsMutex(pCur) ); - - getCellInfo(pCur); - aPayload = pCur->info.pCell + pCur->info.nHeader; - nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey); - - if( NEVER(offset+amt > nKey+pCur->info.nData) - || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] - ){ - /* Trying to read or write past the end of the data is an error */ - return SQLITE_CORRUPT_BKPT; - } - - /* Check if data must be read/written to/from the btree page itself. */ - if( offsetinfo.nLocal ){ - int a = amt; - if( a+offset>pCur->info.nLocal ){ - a = pCur->info.nLocal - offset; - } - rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage); - offset = 0; - pBuf += a; - amt -= a; - }else{ - offset -= pCur->info.nLocal; - } - - if( rc==SQLITE_OK && amt>0 ){ - const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ - Pgno nextPage; - - nextPage = get4byte(&aPayload[pCur->info.nLocal]); - -#ifndef SQLITE_OMIT_INCRBLOB - /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[] - ** has not been allocated, allocate it now. The array is sized at - ** one entry for each overflow page in the overflow chain. The - ** page number of the first overflow page is stored in aOverflow[0], - ** etc. A value of 0 in the aOverflow[] array means "not yet known" - ** (the cache is lazily populated). - */ - if( pCur->isIncrblobHandle && !pCur->aOverflow ){ - int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; - pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl); - /* nOvfl is always positive. If it were zero, fetchPayload would have - ** been used instead of this routine. */ - if( ALWAYS(nOvfl) && !pCur->aOverflow ){ - rc = SQLITE_NOMEM; - } - } - - /* If the overflow page-list cache has been allocated and the - ** entry for the first required overflow page is valid, skip - ** directly to it. - */ - if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){ - iIdx = (offset/ovflSize); - nextPage = pCur->aOverflow[iIdx]; - offset = (offset%ovflSize); - } -#endif - - for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ - -#ifndef SQLITE_OMIT_INCRBLOB - /* If required, populate the overflow page-list cache. */ - if( pCur->aOverflow ){ - assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); - pCur->aOverflow[iIdx] = nextPage; - } -#endif - - if( offset>=ovflSize ){ - /* The only reason to read this page is to obtain the page - ** number for the next page in the overflow chain. The page - ** data is not required. So first try to lookup the overflow - ** page-list cache, if any, then fall back to the getOverflowPage() - ** function. - */ -#ifndef SQLITE_OMIT_INCRBLOB - if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){ - nextPage = pCur->aOverflow[iIdx+1]; - } else -#endif - rc = getOverflowPage(pBt, nextPage, 0, &nextPage); - offset -= ovflSize; - }else{ - /* Need to read this page properly. It contains some of the - ** range of data that is being read (eOp==0) or written (eOp!=0). - */ -#ifdef SQLITE_DIRECT_OVERFLOW_READ - sqlite3_file *fd; -#endif - int a = amt; - if( a + offset > ovflSize ){ - a = ovflSize - offset; - } - -#ifdef SQLITE_DIRECT_OVERFLOW_READ - /* If all the following are true: - ** - ** 1) this is a read operation, and - ** 2) data is required from the start of this overflow page, and - ** 3) the database is file-backed, and - ** 4) there is no open write-transaction, and - ** 5) the database is not a WAL database, - ** - ** then data can be read directly from the database file into the - ** output buffer, bypassing the page-cache altogether. This speeds - ** up loading large records that span many overflow pages. - */ - if( eOp==0 /* (1) */ - && offset==0 /* (2) */ - && pBt->inTransaction==TRANS_READ /* (4) */ - && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ - && pBt->pPage1->aData[19]==0x01 /* (5) */ - ){ - u8 aSave[4]; - u8 *aWrite = &pBuf[-4]; - memcpy(aSave, aWrite, 4); - rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); - nextPage = get4byte(aWrite); - memcpy(aWrite, aSave, 4); - }else -#endif - - { - DbPage *pDbPage; - rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage, - (eOp==0 ? PAGER_ACQUIRE_READONLY : 0) - ); - if( rc==SQLITE_OK ){ - aPayload = sqlite3PagerGetData(pDbPage); - nextPage = get4byte(aPayload); - rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); - sqlite3PagerUnref(pDbPage); - offset = 0; - } - } - amt -= a; - pBuf += a; - } - } - } - - if( rc==SQLITE_OK && amt>0 ){ - return SQLITE_CORRUPT_BKPT; - } - return rc; -} - -/* -** Read part of the key associated with cursor pCur. Exactly -** "amt" bytes will be transfered into pBuf[]. The transfer -** begins at "offset". -** -** The caller must ensure that pCur is pointing to a valid row -** in the table. -** -** Return SQLITE_OK on success or an error code if anything goes -** wrong. An error is returned if "offset+amt" is larger than -** the available payload. -*/ -SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); - assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); - return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); -} - -/* -** Read part of the data associated with cursor pCur. Exactly -** "amt" bytes will be transfered into pBuf[]. The transfer -** begins at "offset". -** -** Return SQLITE_OK on success or an error code if anything goes -** wrong. An error is returned if "offset+amt" is larger than -** the available payload. -*/ -SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - int rc; - -#ifndef SQLITE_OMIT_INCRBLOB - if ( pCur->eState==CURSOR_INVALID ){ - return SQLITE_ABORT; - } -#endif - - assert( cursorHoldsMutex(pCur) ); - rc = restoreCursorPosition(pCur); - if( rc==SQLITE_OK ){ - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); - assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); - rc = accessPayload(pCur, offset, amt, pBuf, 0); - } - return rc; -} - -/* -** Return a pointer to payload information from the entry that the -** pCur cursor is pointing to. The pointer is to the beginning of -** the key if skipKey==0 and it points to the beginning of data if -** skipKey==1. The number of bytes of available key/data is written -** into *pAmt. If *pAmt==0, then the value returned will not be -** a valid pointer. -** -** This routine is an optimization. It is common for the entire key -** and data to fit on the local page and for there to be no overflow -** pages. When that is so, this routine can be used to access the -** key and data without making a copy. If the key and/or data spills -** onto overflow pages, then accessPayload() must be used to reassemble -** the key/data and copy it into a preallocated buffer. -** -** The pointer returned by this routine looks directly into the cached -** page of the database. The data might change or move the next time -** any btree routine is called. -*/ -static const unsigned char *fetchPayload( - BtCursor *pCur, /* Cursor pointing to entry to read from */ - int *pAmt, /* Write the number of available bytes here */ - int skipKey /* read beginning at data if this is true */ -){ - unsigned char *aPayload; - MemPage *pPage; - u32 nKey; - u32 nLocal; - - assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); - assert( pCur->eState==CURSOR_VALID ); - assert( cursorHoldsMutex(pCur) ); - pPage = pCur->apPage[pCur->iPage]; - assert( pCur->aiIdx[pCur->iPage]nCell ); - if( NEVER(pCur->info.nSize==0) ){ - btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage], - &pCur->info); - } - aPayload = pCur->info.pCell; - aPayload += pCur->info.nHeader; - if( pPage->intKey ){ - nKey = 0; - }else{ - nKey = (int)pCur->info.nKey; - } - if( skipKey ){ - aPayload += nKey; - nLocal = pCur->info.nLocal - nKey; - }else{ - nLocal = pCur->info.nLocal; - assert( nLocal<=nKey ); - } - *pAmt = nLocal; - return aPayload; -} - - -/* -** For the entry that cursor pCur is point to, return as -** many bytes of the key or data as are available on the local -** b-tree page. Write the number of available bytes into *pAmt. -** -** The pointer returned is ephemeral. The key/data may move -** or be destroyed on the next call to any Btree routine, -** including calls from other threads against the same cache. -** Hence, a mutex on the BtShared should be held prior to calling -** this routine. -** -** These routines is used to get quick access to key and data -** in the common case where no overflow pages are used. -*/ -SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ - const void *p = 0; - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( cursorHoldsMutex(pCur) ); - if( ALWAYS(pCur->eState==CURSOR_VALID) ){ - p = (const void*)fetchPayload(pCur, pAmt, 0); - } - return p; -} -SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ - const void *p = 0; - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( cursorHoldsMutex(pCur) ); - if( ALWAYS(pCur->eState==CURSOR_VALID) ){ - p = (const void*)fetchPayload(pCur, pAmt, 1); - } - return p; -} - - -/* -** Move the cursor down to a new child page. The newPgno argument is the -** page number of the child page to move to. -** -** This function returns SQLITE_CORRUPT if the page-header flags field of -** the new child page does not match the flags field of the parent (i.e. -** if an intkey page appears to be the parent of a non-intkey page, or -** vice-versa). -*/ -static int moveToChild(BtCursor *pCur, u32 newPgno){ - int rc; - int i = pCur->iPage; - MemPage *pNewPage; - BtShared *pBt = pCur->pBt; - - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPageiPage>=0 ); - if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ - return SQLITE_CORRUPT_BKPT; - } - rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->wrFlag==0)); - if( rc ) return rc; - pCur->apPage[i+1] = pNewPage; - pCur->aiIdx[i+1] = 0; - pCur->iPage++; - - pCur->info.nSize = 0; - pCur->validNKey = 0; - if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){ - return SQLITE_CORRUPT_BKPT; - } - return SQLITE_OK; -} - -#if 0 -/* -** Page pParent is an internal (non-leaf) tree page. This function -** asserts that page number iChild is the left-child if the iIdx'th -** cell in page pParent. Or, if iIdx is equal to the total number of -** cells in pParent, that page number iChild is the right-child of -** the page. -*/ -static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){ - assert( iIdx<=pParent->nCell ); - if( iIdx==pParent->nCell ){ - assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild ); - }else{ - assert( get4byte(findCell(pParent, iIdx))==iChild ); - } -} -#else -# define assertParentIndex(x,y,z) -#endif - -/* -** Move the cursor up to the parent page. -** -** pCur->idx is set to the cell index that contains the pointer -** to the page we are coming from. If we are coming from the -** right-most child page then pCur->idx is set to one more than -** the largest cell index. -*/ -static void moveToParent(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>0 ); - assert( pCur->apPage[pCur->iPage] ); - - /* UPDATE: It is actually possible for the condition tested by the assert - ** below to be untrue if the database file is corrupt. This can occur if - ** one cursor has modified page pParent while a reference to it is held - ** by a second cursor. Which can only happen if a single page is linked - ** into more than one b-tree structure in a corrupt database. */ -#if 0 - assertParentIndex( - pCur->apPage[pCur->iPage-1], - pCur->aiIdx[pCur->iPage-1], - pCur->apPage[pCur->iPage]->pgno - ); -#endif - testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); - - releasePage(pCur->apPage[pCur->iPage]); - pCur->iPage--; - pCur->info.nSize = 0; - pCur->validNKey = 0; -} - -/* -** Move the cursor to point to the root page of its b-tree structure. -** -** If the table has a virtual root page, then the cursor is moved to point -** to the virtual root page instead of the actual root page. A table has a -** virtual root page when the actual root page contains no cells and a -** single child page. This can only happen with the table rooted at page 1. -** -** If the b-tree structure is empty, the cursor state is set to -** CURSOR_INVALID. Otherwise, the cursor is set to point to the first -** cell located on the root (or virtual root) page and the cursor state -** is set to CURSOR_VALID. -** -** If this function returns successfully, it may be assumed that the -** page-header flags indicate that the [virtual] root-page is the expected -** kind of b-tree page (i.e. if when opening the cursor the caller did not -** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D, -** indicating a table b-tree, or if the caller did specify a KeyInfo -** structure the flags byte is set to 0x02 or 0x0A, indicating an index -** b-tree). -*/ -static int moveToRoot(BtCursor *pCur){ - MemPage *pRoot; - int rc = SQLITE_OK; - Btree *p = pCur->pBtree; - BtShared *pBt = p->pBt; - - assert( cursorHoldsMutex(pCur) ); - assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); - assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); - assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); - if( pCur->eState>=CURSOR_REQUIRESEEK ){ - if( pCur->eState==CURSOR_FAULT ){ - assert( pCur->skipNext!=SQLITE_OK ); - return pCur->skipNext; - } - sqlite3BtreeClearCursor(pCur); - } - - if( pCur->iPage>=0 ){ - int i; - for(i=1; i<=pCur->iPage; i++){ - releasePage(pCur->apPage[i]); - } - pCur->iPage = 0; - }else if( pCur->pgnoRoot==0 ){ - pCur->eState = CURSOR_INVALID; - return SQLITE_OK; - }else{ - rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0); - if( rc!=SQLITE_OK ){ - pCur->eState = CURSOR_INVALID; - return rc; - } - pCur->iPage = 0; - - /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor - ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is - ** NULL, the caller expects a table b-tree. If this is not the case, - ** return an SQLITE_CORRUPT error. */ - assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 ); - if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){ - return SQLITE_CORRUPT_BKPT; - } - } - - /* Assert that the root page is of the correct type. This must be the - ** case as the call to this function that loaded the root-page (either - ** this call or a previous invocation) would have detected corruption - ** if the assumption were not true, and it is not possible for the flags - ** byte to have been modified while this cursor is holding a reference - ** to the page. */ - pRoot = pCur->apPage[0]; - assert( pRoot->pgno==pCur->pgnoRoot ); - assert( pRoot->isInit && (pCur->pKeyInfo==0)==pRoot->intKey ); - - pCur->aiIdx[0] = 0; - pCur->info.nSize = 0; - pCur->atLast = 0; - pCur->validNKey = 0; - - if( pRoot->nCell==0 && !pRoot->leaf ){ - Pgno subpage; - if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; - subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); - pCur->eState = CURSOR_VALID; - rc = moveToChild(pCur, subpage); - }else{ - pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID); - } - return rc; -} - -/* -** Move the cursor down to the left-most leaf entry beneath the -** entry to which it is currently pointing. -** -** The left-most leaf is the one with the smallest key - the first -** in ascending order. -*/ -static int moveToLeftmost(BtCursor *pCur){ - Pgno pgno; - int rc = SQLITE_OK; - MemPage *pPage; - - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ - assert( pCur->aiIdx[pCur->iPage]nCell ); - pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage])); - rc = moveToChild(pCur, pgno); - } - return rc; -} - -/* -** Move the cursor down to the right-most leaf entry beneath the -** page to which it is currently pointing. Notice the difference -** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() -** finds the left-most entry beneath the *entry* whereas moveToRightmost() -** finds the right-most entry beneath the *page*. -** -** The right-most entry is the one with the largest key - the last -** key in ascending order. -*/ -static int moveToRightmost(BtCursor *pCur){ - Pgno pgno; - int rc = SQLITE_OK; - MemPage *pPage = 0; - - assert( cursorHoldsMutex(pCur) ); - assert( pCur->eState==CURSOR_VALID ); - while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ - pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - pCur->aiIdx[pCur->iPage] = pPage->nCell; - rc = moveToChild(pCur, pgno); - } - if( rc==SQLITE_OK ){ - pCur->aiIdx[pCur->iPage] = pPage->nCell-1; - pCur->info.nSize = 0; - pCur->validNKey = 0; - } - return rc; -} - -/* Move the cursor to the first entry in the table. Return SQLITE_OK -** on success. Set *pRes to 0 if the cursor actually points to something -** or set *pRes to 1 if the table is empty. -*/ -SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ - int rc; - - assert( cursorHoldsMutex(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - rc = moveToRoot(pCur); - if( rc==SQLITE_OK ){ - if( pCur->eState==CURSOR_INVALID ){ - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); - *pRes = 1; - }else{ - assert( pCur->apPage[pCur->iPage]->nCell>0 ); - *pRes = 0; - rc = moveToLeftmost(pCur); - } - } - return rc; -} - -/* Move the cursor to the last entry in the table. Return SQLITE_OK -** on success. Set *pRes to 0 if the cursor actually points to something -** or set *pRes to 1 if the table is empty. -*/ -SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ - int rc; - - assert( cursorHoldsMutex(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - - /* If the cursor already points to the last entry, this is a no-op. */ - if( CURSOR_VALID==pCur->eState && pCur->atLast ){ -#ifdef SQLITE_DEBUG - /* This block serves to assert() that the cursor really does point - ** to the last entry in the b-tree. */ - int ii; - for(ii=0; iiiPage; ii++){ - assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); - } - assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 ); - assert( pCur->apPage[pCur->iPage]->leaf ); -#endif - return SQLITE_OK; - } - - rc = moveToRoot(pCur); - if( rc==SQLITE_OK ){ - if( CURSOR_INVALID==pCur->eState ){ - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); - *pRes = 1; - }else{ - assert( pCur->eState==CURSOR_VALID ); - *pRes = 0; - rc = moveToRightmost(pCur); - pCur->atLast = rc==SQLITE_OK ?1:0; - } - } - return rc; -} - -/* Move the cursor so that it points to an entry near the key -** specified by pIdxKey or intKey. Return a success code. -** -** For INTKEY tables, the intKey parameter is used. pIdxKey -** must be NULL. For index tables, pIdxKey is used and intKey -** is ignored. -** -** If an exact match is not found, then the cursor is always -** left pointing at a leaf page which would hold the entry if it -** were present. The cursor might point to an entry that comes -** before or after the key. -** -** An integer is written into *pRes which is the result of -** comparing the key with the entry to which the cursor is -** pointing. The meaning of the integer written into -** *pRes is as follows: -** -** *pRes<0 The cursor is left pointing at an entry that -** is smaller than intKey/pIdxKey or if the table is empty -** and the cursor is therefore left point to nothing. -** -** *pRes==0 The cursor is left pointing at an entry that -** exactly matches intKey/pIdxKey. -** -** *pRes>0 The cursor is left pointing at an entry that -** is larger than intKey/pIdxKey. -** -*/ -SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( - BtCursor *pCur, /* The cursor to be moved */ - UnpackedRecord *pIdxKey, /* Unpacked index key */ - i64 intKey, /* The table key */ - int biasRight, /* If true, bias the search to the high end */ - int *pRes /* Write search results here */ -){ - int rc; - - assert( cursorHoldsMutex(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - assert( pRes ); - assert( (pIdxKey==0)==(pCur->pKeyInfo==0) ); - - /* If the cursor is already positioned at the point we are trying - ** to move to, then just return without doing any work */ - if( pCur->eState==CURSOR_VALID && pCur->validNKey - && pCur->apPage[0]->intKey - ){ - if( pCur->info.nKey==intKey ){ - *pRes = 0; - return SQLITE_OK; - } - if( pCur->atLast && pCur->info.nKeypgnoRoot==0 || pCur->apPage[pCur->iPage] ); - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit ); - assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 ); - if( pCur->eState==CURSOR_INVALID ){ - *pRes = -1; - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); - return SQLITE_OK; - } - assert( pCur->apPage[0]->intKey || pIdxKey ); - for(;;){ - int lwr, upr, idx; - Pgno chldPg; - MemPage *pPage = pCur->apPage[pCur->iPage]; - int c; - - /* pPage->nCell must be greater than zero. If this is the root-page - ** the cursor would have been INVALID above and this for(;;) loop - ** not run. If this is not the root-page, then the moveToChild() routine - ** would have already detected db corruption. Similarly, pPage must - ** be the right kind (index or table) of b-tree page. Otherwise - ** a moveToChild() or moveToRoot() call would have detected corruption. */ - assert( pPage->nCell>0 ); - assert( pPage->intKey==(pIdxKey==0) ); - lwr = 0; - upr = pPage->nCell-1; - if( biasRight ){ - pCur->aiIdx[pCur->iPage] = (u16)(idx = upr); - }else{ - pCur->aiIdx[pCur->iPage] = (u16)(idx = (upr+lwr)/2); - } - for(;;){ - u8 *pCell; /* Pointer to current cell in pPage */ - - assert( idx==pCur->aiIdx[pCur->iPage] ); - pCur->info.nSize = 0; - pCell = findCell(pPage, idx) + pPage->childPtrSize; - if( pPage->intKey ){ - i64 nCellKey; - if( pPage->hasData ){ - u32 dummy; - pCell += getVarint32(pCell, dummy); - } - getVarint(pCell, (u64*)&nCellKey); - if( nCellKey==intKey ){ - c = 0; - }else if( nCellKeyintKey ); - c = +1; - } - pCur->validNKey = 1; - pCur->info.nKey = nCellKey; - }else{ - /* The maximum supported page-size is 65536 bytes. This means that - ** the maximum number of record bytes stored on an index B-Tree - ** page is less than 16384 bytes and may be stored as a 2-byte - ** varint. This information is used to attempt to avoid parsing - ** the entire cell by checking for the cases where the record is - ** stored entirely within the b-tree page by inspecting the first - ** 2 bytes of the cell. - */ - int nCell = pCell[0]; - if( nCell<=pPage->max1bytePayload - /* && (pCell+nCell)aDataEnd */ - ){ - /* This branch runs if the record-size field of the cell is a - ** single byte varint and the record fits entirely on the main - ** b-tree page. */ - testcase( pCell+nCell+1==pPage->aDataEnd ); - c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey); - }else if( !(pCell[1] & 0x80) - && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal - /* && (pCell+nCell+2)<=pPage->aDataEnd */ - ){ - /* The record-size field is a 2 byte varint and the record - ** fits entirely on the main b-tree page. */ - testcase( pCell+nCell+2==pPage->aDataEnd ); - c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey); - }else{ - /* The record flows over onto one or more overflow pages. In - ** this case the whole cell needs to be parsed, a buffer allocated - ** and accessPayload() used to retrieve the record into the - ** buffer before VdbeRecordCompare() can be called. */ - void *pCellKey; - u8 * const pCellBody = pCell - pPage->childPtrSize; - btreeParseCellPtr(pPage, pCellBody, &pCur->info); - nCell = (int)pCur->info.nKey; - pCellKey = sqlite3Malloc( nCell ); - if( pCellKey==0 ){ - rc = SQLITE_NOMEM; - goto moveto_finish; - } - rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0); - if( rc ){ - sqlite3_free(pCellKey); - goto moveto_finish; - } - c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); - sqlite3_free(pCellKey); - } - } - if( c==0 ){ - if( pPage->intKey && !pPage->leaf ){ - lwr = idx; - break; - }else{ - *pRes = 0; - rc = SQLITE_OK; - goto moveto_finish; - } - } - if( c<0 ){ - lwr = idx+1; - }else{ - upr = idx-1; - } - if( lwr>upr ){ - break; - } - pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2); - } - assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); - assert( pPage->isInit ); - if( pPage->leaf ){ - chldPg = 0; - }else if( lwr>=pPage->nCell ){ - chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); - }else{ - chldPg = get4byte(findCell(pPage, lwr)); - } - if( chldPg==0 ){ - assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); - *pRes = c; - rc = SQLITE_OK; - goto moveto_finish; - } - pCur->aiIdx[pCur->iPage] = (u16)lwr; - pCur->info.nSize = 0; - pCur->validNKey = 0; - rc = moveToChild(pCur, chldPg); - if( rc ) goto moveto_finish; - } -moveto_finish: - return rc; -} - - -/* -** Return TRUE if the cursor is not pointing at an entry of the table. -** -** TRUE will be returned after a call to sqlite3BtreeNext() moves -** past the last entry in the table or sqlite3BtreePrev() moves past -** the first entry. TRUE is also returned if the table is empty. -*/ -SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){ - /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries - ** have been deleted? This API will need to change to return an error code - ** as well as the boolean result value. - */ - return (CURSOR_VALID!=pCur->eState); -} - -/* -** Advance the cursor to the next entry in the database. If -** successful then set *pRes=0. If the cursor -** was already pointing to the last entry in the database before -** this routine was called, then set *pRes=1. -*/ -SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ - int rc; - int idx; - MemPage *pPage; - - assert( cursorHoldsMutex(pCur) ); - rc = restoreCursorPosition(pCur); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pRes!=0 ); - if( CURSOR_INVALID==pCur->eState ){ - *pRes = 1; - return SQLITE_OK; - } - if( pCur->skipNext>0 ){ - pCur->skipNext = 0; - *pRes = 0; - return SQLITE_OK; - } - pCur->skipNext = 0; - - pPage = pCur->apPage[pCur->iPage]; - idx = ++pCur->aiIdx[pCur->iPage]; - assert( pPage->isInit ); - - /* If the database file is corrupt, it is possible for the value of idx - ** to be invalid here. This can only occur if a second cursor modifies - ** the page while cursor pCur is holding a reference to it. Which can - ** only happen if the database is corrupt in such a way as to link the - ** page into more than one b-tree structure. */ - testcase( idx>pPage->nCell ); - - pCur->info.nSize = 0; - pCur->validNKey = 0; - if( idx>=pPage->nCell ){ - if( !pPage->leaf ){ - rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); - if( rc ) return rc; - rc = moveToLeftmost(pCur); - *pRes = 0; - return rc; - } - do{ - if( pCur->iPage==0 ){ - *pRes = 1; - pCur->eState = CURSOR_INVALID; - return SQLITE_OK; - } - moveToParent(pCur); - pPage = pCur->apPage[pCur->iPage]; - }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell ); - *pRes = 0; - if( pPage->intKey ){ - rc = sqlite3BtreeNext(pCur, pRes); - }else{ - rc = SQLITE_OK; - } - return rc; - } - *pRes = 0; - if( pPage->leaf ){ - return SQLITE_OK; - } - rc = moveToLeftmost(pCur); - return rc; -} - - -/* -** Step the cursor to the back to the previous entry in the database. If -** successful then set *pRes=0. If the cursor -** was already pointing to the first entry in the database before -** this routine was called, then set *pRes=1. -*/ -SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ - int rc; - MemPage *pPage; - - assert( cursorHoldsMutex(pCur) ); - rc = restoreCursorPosition(pCur); - if( rc!=SQLITE_OK ){ - return rc; - } - pCur->atLast = 0; - if( CURSOR_INVALID==pCur->eState ){ - *pRes = 1; - return SQLITE_OK; - } - if( pCur->skipNext<0 ){ - pCur->skipNext = 0; - *pRes = 0; - return SQLITE_OK; - } - pCur->skipNext = 0; - - pPage = pCur->apPage[pCur->iPage]; - assert( pPage->isInit ); - if( !pPage->leaf ){ - int idx = pCur->aiIdx[pCur->iPage]; - rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); - if( rc ){ - return rc; - } - rc = moveToRightmost(pCur); - }else{ - while( pCur->aiIdx[pCur->iPage]==0 ){ - if( pCur->iPage==0 ){ - pCur->eState = CURSOR_INVALID; - *pRes = 1; - return SQLITE_OK; - } - moveToParent(pCur); - } - pCur->info.nSize = 0; - pCur->validNKey = 0; - - pCur->aiIdx[pCur->iPage]--; - pPage = pCur->apPage[pCur->iPage]; - if( pPage->intKey && !pPage->leaf ){ - rc = sqlite3BtreePrevious(pCur, pRes); - }else{ - rc = SQLITE_OK; - } - } - *pRes = 0; - return rc; -} - -/* -** Allocate a new page from the database file. -** -** The new page is marked as dirty. (In other words, sqlite3PagerWrite() -** has already been called on the new page.) The new page has also -** been referenced and the calling routine is responsible for calling -** sqlite3PagerUnref() on the new page when it is done. -** -** SQLITE_OK is returned on success. Any other return value indicates -** an error. *ppPage and *pPgno are undefined in the event of an error. -** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned. -** -** If the "nearby" parameter is not 0, then an effort is made to -** locate a page close to the page number "nearby". This can be used in an -** attempt to keep related pages close to each other in the database file, -** which in turn can make database access faster. -** -** If the eMode parameter is BTALLOC_EXACT and the nearby page exists -** anywhere on the free-list, then it is guaranteed to be returned. If -** eMode is BTALLOC_LT then the page returned will be less than or equal -** to nearby if any such page exists. If eMode is BTALLOC_ANY then there -** are no restrictions on which page is returned. -*/ -static int allocateBtreePage( - BtShared *pBt, /* The btree */ - MemPage **ppPage, /* Store pointer to the allocated page here */ - Pgno *pPgno, /* Store the page number here */ - Pgno nearby, /* Search for a page near this one */ - u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */ -){ - MemPage *pPage1; - int rc; - u32 n; /* Number of pages on the freelist */ - u32 k; /* Number of leaves on the trunk of the freelist */ - MemPage *pTrunk = 0; - MemPage *pPrevTrunk = 0; - Pgno mxPage; /* Total size of the database file */ - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) ); - pPage1 = pBt->pPage1; - mxPage = btreePagecount(pBt); - n = get4byte(&pPage1->aData[36]); - testcase( n==mxPage-1 ); - if( n>=mxPage ){ - return SQLITE_CORRUPT_BKPT; - } - if( n>0 ){ - /* There are pages on the freelist. Reuse one of those pages. */ - Pgno iTrunk; - u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ - - /* If eMode==BTALLOC_EXACT and a query of the pointer-map - ** shows that the page 'nearby' is somewhere on the free-list, then - ** the entire-list will be searched for that page. - */ -#ifndef SQLITE_OMIT_AUTOVACUUM - if( eMode==BTALLOC_EXACT ){ - if( nearby<=mxPage ){ - u8 eType; - assert( nearby>0 ); - assert( pBt->autoVacuum ); - rc = ptrmapGet(pBt, nearby, &eType, 0); - if( rc ) return rc; - if( eType==PTRMAP_FREEPAGE ){ - searchList = 1; - } - } - }else if( eMode==BTALLOC_LE ){ - searchList = 1; - } -#endif - - /* Decrement the free-list count by 1. Set iTrunk to the index of the - ** first free-list trunk page. iPrevTrunk is initially 1. - */ - rc = sqlite3PagerWrite(pPage1->pDbPage); - if( rc ) return rc; - put4byte(&pPage1->aData[36], n-1); - - /* The code within this loop is run only once if the 'searchList' variable - ** is not true. Otherwise, it runs once for each trunk-page on the - ** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT) - ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT) - */ - do { - pPrevTrunk = pTrunk; - if( pPrevTrunk ){ - iTrunk = get4byte(&pPrevTrunk->aData[0]); - }else{ - iTrunk = get4byte(&pPage1->aData[32]); - } - testcase( iTrunk==mxPage ); - if( iTrunk>mxPage ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0); - } - if( rc ){ - pTrunk = 0; - goto end_allocate_page; - } - assert( pTrunk!=0 ); - assert( pTrunk->aData!=0 ); - - k = get4byte(&pTrunk->aData[4]); /* # of leaves on this trunk page */ - if( k==0 && !searchList ){ - /* The trunk has no leaves and the list is not being searched. - ** So extract the trunk page itself and use it as the newly - ** allocated page */ - assert( pPrevTrunk==0 ); - rc = sqlite3PagerWrite(pTrunk->pDbPage); - if( rc ){ - goto end_allocate_page; - } - *pPgno = iTrunk; - memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); - *ppPage = pTrunk; - pTrunk = 0; - TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); - }else if( k>(u32)(pBt->usableSize/4 - 2) ){ - /* Value of k is out of range. Database corruption */ - rc = SQLITE_CORRUPT_BKPT; - goto end_allocate_page; -#ifndef SQLITE_OMIT_AUTOVACUUM - }else if( searchList - && (nearby==iTrunk || (iTrunkpDbPage); - if( rc ){ - goto end_allocate_page; - } - if( k==0 ){ - if( !pPrevTrunk ){ - memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); - }else{ - rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); - if( rc!=SQLITE_OK ){ - goto end_allocate_page; - } - memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); - } - }else{ - /* The trunk page is required by the caller but it contains - ** pointers to free-list leaves. The first leaf becomes a trunk - ** page in this case. - */ - MemPage *pNewTrunk; - Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); - if( iNewTrunk>mxPage ){ - rc = SQLITE_CORRUPT_BKPT; - goto end_allocate_page; - } - testcase( iNewTrunk==mxPage ); - rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0, 0); - if( rc!=SQLITE_OK ){ - goto end_allocate_page; - } - rc = sqlite3PagerWrite(pNewTrunk->pDbPage); - if( rc!=SQLITE_OK ){ - releasePage(pNewTrunk); - goto end_allocate_page; - } - memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4); - put4byte(&pNewTrunk->aData[4], k-1); - memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4); - releasePage(pNewTrunk); - if( !pPrevTrunk ){ - assert( sqlite3PagerIswriteable(pPage1->pDbPage) ); - put4byte(&pPage1->aData[32], iNewTrunk); - }else{ - rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); - if( rc ){ - goto end_allocate_page; - } - put4byte(&pPrevTrunk->aData[0], iNewTrunk); - } - } - pTrunk = 0; - TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); -#endif - }else if( k>0 ){ - /* Extract a leaf from the trunk */ - u32 closest; - Pgno iPage; - unsigned char *aData = pTrunk->aData; - if( nearby>0 ){ - u32 i; - closest = 0; - if( eMode==BTALLOC_LE ){ - for(i=0; imxPage ){ - rc = SQLITE_CORRUPT_BKPT; - goto end_allocate_page; - } - testcase( iPage==mxPage ); - if( !searchList - || (iPage==nearby || (iPagepgno, n-1)); - rc = sqlite3PagerWrite(pTrunk->pDbPage); - if( rc ) goto end_allocate_page; - if( closestpDbPage); - if( rc!=SQLITE_OK ){ - releasePage(*ppPage); - } - } - searchList = 0; - } - } - releasePage(pPrevTrunk); - pPrevTrunk = 0; - }while( searchList ); - }else{ - /* There are no pages on the freelist, so append a new page to the - ** database image. - ** - ** Normally, new pages allocated by this block can be requested from the - ** pager layer with the 'no-content' flag set. This prevents the pager - ** from trying to read the pages content from disk. However, if the - ** current transaction has already run one or more incremental-vacuum - ** steps, then the page we are about to allocate may contain content - ** that is required in the event of a rollback. In this case, do - ** not set the no-content flag. This causes the pager to load and journal - ** the current page content before overwriting it. - ** - ** Note that the pager will not actually attempt to load or journal - ** content for any page that really does lie past the end of the database - ** file on disk. So the effects of disabling the no-content optimization - ** here are confined to those pages that lie between the end of the - ** database image and the end of the database file. - */ - int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate)); - - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - if( rc ) return rc; - pBt->nPage++; - if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; - -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ - /* If *pPgno refers to a pointer-map page, allocate two new pages - ** at the end of the file instead of one. The first allocated page - ** becomes a new pointer-map page, the second is used by the caller. - */ - MemPage *pPg = 0; - TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); - assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pPg->pDbPage); - releasePage(pPg); - } - if( rc ) return rc; - pBt->nPage++; - if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; } - } -#endif - put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage); - *pPgno = pBt->nPage; - - assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent, 0); - if( rc ) return rc; - rc = sqlite3PagerWrite((*ppPage)->pDbPage); - if( rc!=SQLITE_OK ){ - releasePage(*ppPage); - } - TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); - } - - assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - -end_allocate_page: - releasePage(pTrunk); - releasePage(pPrevTrunk); - if( rc==SQLITE_OK ){ - if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ - releasePage(*ppPage); - return SQLITE_CORRUPT_BKPT; - } - (*ppPage)->isInit = 0; - }else{ - *ppPage = 0; - } - assert( rc!=SQLITE_OK || sqlite3PagerIswriteable((*ppPage)->pDbPage) ); - return rc; -} - -/* -** This function is used to add page iPage to the database file free-list. -** It is assumed that the page is not already a part of the free-list. -** -** The value passed as the second argument to this function is optional. -** If the caller happens to have a pointer to the MemPage object -** corresponding to page iPage handy, it may pass it as the second value. -** Otherwise, it may pass NULL. -** -** If a pointer to a MemPage object is passed as the second argument, -** its reference count is not altered by this function. -*/ -static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ - MemPage *pTrunk = 0; /* Free-list trunk page */ - Pgno iTrunk = 0; /* Page number of free-list trunk page */ - MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */ - MemPage *pPage; /* Page being freed. May be NULL. */ - int rc; /* Return Code */ - int nFree; /* Initial number of pages on free-list */ - - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( iPage>1 ); - assert( !pMemPage || pMemPage->pgno==iPage ); - - if( pMemPage ){ - pPage = pMemPage; - sqlite3PagerRef(pPage->pDbPage); - }else{ - pPage = btreePageLookup(pBt, iPage); - } - - /* Increment the free page count on pPage1 */ - rc = sqlite3PagerWrite(pPage1->pDbPage); - if( rc ) goto freepage_out; - nFree = get4byte(&pPage1->aData[36]); - put4byte(&pPage1->aData[36], nFree+1); - - if( pBt->btsFlags & BTS_SECURE_DELETE ){ - /* If the secure_delete option is enabled, then - ** always fully overwrite deleted information with zeros. - */ - if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0, 0))!=0) ) - || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0) - ){ - goto freepage_out; - } - memset(pPage->aData, 0, pPage->pBt->pageSize); - } - - /* If the database supports auto-vacuum, write an entry in the pointer-map - ** to indicate that the page is free. - */ - if( ISAUTOVACUUM ){ - ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc); - if( rc ) goto freepage_out; - } - - /* Now manipulate the actual database free-list structure. There are two - ** possibilities. If the free-list is currently empty, or if the first - ** trunk page in the free-list is full, then this page will become a - ** new free-list trunk page. Otherwise, it will become a leaf of the - ** first trunk page in the current free-list. This block tests if it - ** is possible to add the page as a new free-list leaf. - */ - if( nFree!=0 ){ - u32 nLeaf; /* Initial number of leaf cells on trunk page */ - - iTrunk = get4byte(&pPage1->aData[32]); - rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0); - if( rc!=SQLITE_OK ){ - goto freepage_out; - } - - nLeaf = get4byte(&pTrunk->aData[4]); - assert( pBt->usableSize>32 ); - if( nLeaf > (u32)pBt->usableSize/4 - 2 ){ - rc = SQLITE_CORRUPT_BKPT; - goto freepage_out; - } - if( nLeaf < (u32)pBt->usableSize/4 - 8 ){ - /* In this case there is room on the trunk page to insert the page - ** being freed as a new leaf. - ** - ** Note that the trunk page is not really full until it contains - ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have - ** coded. But due to a coding error in versions of SQLite prior to - ** 3.6.0, databases with freelist trunk pages holding more than - ** usableSize/4 - 8 entries will be reported as corrupt. In order - ** to maintain backwards compatibility with older versions of SQLite, - ** we will continue to restrict the number of entries to usableSize/4 - 8 - ** for now. At some point in the future (once everyone has upgraded - ** to 3.6.0 or later) we should consider fixing the conditional above - ** to read "usableSize/4-2" instead of "usableSize/4-8". - */ - rc = sqlite3PagerWrite(pTrunk->pDbPage); - if( rc==SQLITE_OK ){ - put4byte(&pTrunk->aData[4], nLeaf+1); - put4byte(&pTrunk->aData[8+nLeaf*4], iPage); - if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){ - sqlite3PagerDontWrite(pPage->pDbPage); - } - rc = btreeSetHasContent(pBt, iPage); - } - TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); - goto freepage_out; - } - } - - /* If control flows to this point, then it was not possible to add the - ** the page being freed as a leaf page of the first trunk in the free-list. - ** Possibly because the free-list is empty, or possibly because the - ** first trunk in the free-list is full. Either way, the page being freed - ** will become the new first trunk page in the free-list. - */ - if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0, 0)) ){ - goto freepage_out; - } - rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc!=SQLITE_OK ){ - goto freepage_out; - } - put4byte(pPage->aData, iTrunk); - put4byte(&pPage->aData[4], 0); - put4byte(&pPage1->aData[32], iPage); - TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk)); - -freepage_out: - if( pPage ){ - pPage->isInit = 0; - } - releasePage(pPage); - releasePage(pTrunk); - return rc; -} -static void freePage(MemPage *pPage, int *pRC){ - if( (*pRC)==SQLITE_OK ){ - *pRC = freePage2(pPage->pBt, pPage, pPage->pgno); - } -} - -/* -** Free any overflow pages associated with the given Cell. -*/ -static int clearCell(MemPage *pPage, unsigned char *pCell){ - BtShared *pBt = pPage->pBt; - CellInfo info; - Pgno ovflPgno; - int rc; - int nOvfl; - u32 ovflPageSize; - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - btreeParseCellPtr(pPage, pCell, &info); - if( info.iOverflow==0 ){ - return SQLITE_OK; /* No overflow pages. Return without doing anything */ - } - if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){ - return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */ - } - ovflPgno = get4byte(&pCell[info.iOverflow]); - assert( pBt->usableSize > 4 ); - ovflPageSize = pBt->usableSize - 4; - nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; - assert( ovflPgno==0 || nOvfl>0 ); - while( nOvfl-- ){ - Pgno iNext = 0; - MemPage *pOvfl = 0; - if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){ - /* 0 is not a legal page number and page 1 cannot be an - ** overflow page. Therefore if ovflPgno<2 or past the end of the - ** file the database must be corrupt. */ - return SQLITE_CORRUPT_BKPT; - } - if( nOvfl ){ - rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext); - if( rc ) return rc; - } - - if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) ) - && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1 - ){ - /* There is no reason any cursor should have an outstanding reference - ** to an overflow page belonging to a cell that is being deleted/updated. - ** So if there exists more than one reference to this page, then it - ** must not really be an overflow page and the database must be corrupt. - ** It is helpful to detect this before calling freePage2(), as - ** freePage2() may zero the page contents if secure-delete mode is - ** enabled. If this 'overflow' page happens to be a page that the - ** caller is iterating through or using in some other way, this - ** can be problematic. - */ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = freePage2(pBt, pOvfl, ovflPgno); - } - - if( pOvfl ){ - sqlite3PagerUnref(pOvfl->pDbPage); - } - if( rc ) return rc; - ovflPgno = iNext; - } - return SQLITE_OK; -} - -/* -** Create the byte sequence used to represent a cell on page pPage -** and write that byte sequence into pCell[]. Overflow pages are -** allocated and filled in as necessary. The calling procedure -** is responsible for making sure sufficient space has been allocated -** for pCell[]. -** -** Note that pCell does not necessary need to point to the pPage->aData -** area. pCell might point to some temporary storage. The cell will -** be constructed in this temporary area then copied into pPage->aData -** later. -*/ -static int fillInCell( - MemPage *pPage, /* The page that contains the cell */ - unsigned char *pCell, /* Complete text of the cell */ - const void *pKey, i64 nKey, /* The key */ - const void *pData,int nData, /* The data */ - int nZero, /* Extra zero bytes to append to pData */ - int *pnSize /* Write cell size here */ -){ - int nPayload; - const u8 *pSrc; - int nSrc, n, rc; - int spaceLeft; - MemPage *pOvfl = 0; - MemPage *pToRelease = 0; - unsigned char *pPrior; - unsigned char *pPayload; - BtShared *pBt = pPage->pBt; - Pgno pgnoOvfl = 0; - int nHeader; - CellInfo info; - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - - /* pPage is not necessarily writeable since pCell might be auxiliary - ** buffer space that is separate from the pPage buffer area */ - assert( pCellaData || pCell>=&pPage->aData[pBt->pageSize] - || sqlite3PagerIswriteable(pPage->pDbPage) ); - - /* Fill in the header. */ - nHeader = 0; - if( !pPage->leaf ){ - nHeader += 4; - } - if( pPage->hasData ){ - nHeader += putVarint(&pCell[nHeader], nData+nZero); - }else{ - nData = nZero = 0; - } - nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); - btreeParseCellPtr(pPage, pCell, &info); - assert( info.nHeader==nHeader ); - assert( info.nKey==nKey ); - assert( info.nData==(u32)(nData+nZero) ); - - /* Fill in the payload */ - nPayload = nData + nZero; - if( pPage->intKey ){ - pSrc = pData; - nSrc = nData; - nData = 0; - }else{ - if( NEVER(nKey>0x7fffffff || pKey==0) ){ - return SQLITE_CORRUPT_BKPT; - } - nPayload += (int)nKey; - pSrc = pKey; - nSrc = (int)nKey; - } - *pnSize = info.nSize; - spaceLeft = info.nLocal; - pPayload = &pCell[nHeader]; - pPrior = &pCell[info.iOverflow]; - - while( nPayload>0 ){ - if( spaceLeft==0 ){ -#ifndef SQLITE_OMIT_AUTOVACUUM - Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ - if( pBt->autoVacuum ){ - do{ - pgnoOvfl++; - } while( - PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) - ); - } -#endif - rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0); -#ifndef SQLITE_OMIT_AUTOVACUUM - /* If the database supports auto-vacuum, and the second or subsequent - ** overflow page is being allocated, add an entry to the pointer-map - ** for that page now. - ** - ** If this is the first overflow page, then write a partial entry - ** to the pointer-map. If we write nothing to this pointer-map slot, - ** then the optimistic overflow chain processing in clearCell() - ** may misinterpret the uninitialized values and delete the - ** wrong pages from the database. - */ - if( pBt->autoVacuum && rc==SQLITE_OK ){ - u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); - ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc); - if( rc ){ - releasePage(pOvfl); - } - } -#endif - if( rc ){ - releasePage(pToRelease); - return rc; - } - - /* If pToRelease is not zero than pPrior points into the data area - ** of pToRelease. Make sure pToRelease is still writeable. */ - assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); - - /* If pPrior is part of the data area of pPage, then make sure pPage - ** is still writeable */ - assert( pPrioraData || pPrior>=&pPage->aData[pBt->pageSize] - || sqlite3PagerIswriteable(pPage->pDbPage) ); - - put4byte(pPrior, pgnoOvfl); - releasePage(pToRelease); - pToRelease = pOvfl; - pPrior = pOvfl->aData; - put4byte(pPrior, 0); - pPayload = &pOvfl->aData[4]; - spaceLeft = pBt->usableSize - 4; - } - n = nPayload; - if( n>spaceLeft ) n = spaceLeft; - - /* If pToRelease is not zero than pPayload points into the data area - ** of pToRelease. Make sure pToRelease is still writeable. */ - assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); - - /* If pPayload is part of the data area of pPage, then make sure pPage - ** is still writeable */ - assert( pPayloadaData || pPayload>=&pPage->aData[pBt->pageSize] - || sqlite3PagerIswriteable(pPage->pDbPage) ); - - if( nSrc>0 ){ - if( n>nSrc ) n = nSrc; - assert( pSrc ); - memcpy(pPayload, pSrc, n); - }else{ - memset(pPayload, 0, n); - } - nPayload -= n; - pPayload += n; - pSrc += n; - nSrc -= n; - spaceLeft -= n; - if( nSrc==0 ){ - nSrc = nData; - pSrc = pData; - } - } - releasePage(pToRelease); - return SQLITE_OK; -} - -/* -** Remove the i-th cell from pPage. This routine effects pPage only. -** The cell content is not freed or deallocated. It is assumed that -** the cell content has been copied someplace else. This routine just -** removes the reference to the cell from pPage. -** -** "sz" must be the number of bytes in the cell. -*/ -static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ - u32 pc; /* Offset to cell content of cell being deleted */ - u8 *data; /* pPage->aData */ - u8 *ptr; /* Used to move bytes around within data[] */ - u8 *endPtr; /* End of loop */ - int rc; /* The return code */ - int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ - - if( *pRC ) return; - - assert( idx>=0 && idxnCell ); - assert( sz==cellSize(pPage, idx) ); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - data = pPage->aData; - ptr = &pPage->aCellIdx[2*idx]; - pc = get2byte(ptr); - hdr = pPage->hdrOffset; - testcase( pc==get2byte(&data[hdr+5]) ); - testcase( pc+sz==pPage->pBt->usableSize ); - if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){ - *pRC = SQLITE_CORRUPT_BKPT; - return; - } - rc = freeSpace(pPage, pc, sz); - if( rc ){ - *pRC = rc; - return; - } - endPtr = &pPage->aCellIdx[2*pPage->nCell - 2]; - assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */ - while( ptrnCell--; - put2byte(&data[hdr+3], pPage->nCell); - pPage->nFree += 2; -} - -/* -** Insert a new cell on pPage at cell index "i". pCell points to the -** content of the cell. -** -** If the cell content will fit on the page, then put it there. If it -** will not fit, then make a copy of the cell content into pTemp if -** pTemp is not null. Regardless of pTemp, allocate a new entry -** in pPage->apOvfl[] and make it point to the cell content (either -** in pTemp or the original pCell) and also record its index. -** Allocating a new entry in pPage->aCell[] implies that -** pPage->nOverflow is incremented. -** -** If nSkip is non-zero, then do not copy the first nSkip bytes of the -** cell. The caller will overwrite them after this function returns. If -** nSkip is non-zero, then pCell may not point to an invalid memory location -** (but pCell+nSkip is always valid). -*/ -static void insertCell( - MemPage *pPage, /* Page into which we are copying */ - int i, /* New cell becomes the i-th cell of the page */ - u8 *pCell, /* Content of the new cell */ - int sz, /* Bytes of content in pCell */ - u8 *pTemp, /* Temp storage space for pCell, if needed */ - Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ - int *pRC /* Read and write return code from here */ -){ - int idx = 0; /* Where to write new cell content in data[] */ - int j; /* Loop counter */ - int end; /* First byte past the last cell pointer in data[] */ - int ins; /* Index in data[] where new cell pointer is inserted */ - int cellOffset; /* Address of first cell pointer in data[] */ - u8 *data; /* The content of the whole page */ - u8 *ptr; /* Used for moving information around in data[] */ - u8 *endPtr; /* End of the loop */ - - int nSkip = (iChild ? 4 : 0); - - if( *pRC ) return; - - assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); - assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 ); - assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); - assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - /* The cell should normally be sized correctly. However, when moving a - ** malformed cell from a leaf page to an interior page, if the cell size - ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size - ** might be less than 8 (leaf-size + pointer) on the interior node. Hence - ** the term after the || in the following assert(). */ - assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) ); - if( pPage->nOverflow || sz+2>pPage->nFree ){ - if( pTemp ){ - memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); - pCell = pTemp; - } - if( iChild ){ - put4byte(pCell, iChild); - } - j = pPage->nOverflow++; - assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) ); - pPage->apOvfl[j] = pCell; - pPage->aiOvfl[j] = (u16)i; - }else{ - int rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc!=SQLITE_OK ){ - *pRC = rc; - return; - } - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - data = pPage->aData; - cellOffset = pPage->cellOffset; - end = cellOffset + 2*pPage->nCell; - ins = cellOffset + 2*i; - rc = allocateSpace(pPage, sz, &idx); - if( rc ){ *pRC = rc; return; } - /* The allocateSpace() routine guarantees the following two properties - ** if it returns success */ - assert( idx >= end+2 ); - assert( idx+sz <= (int)pPage->pBt->usableSize ); - pPage->nCell++; - pPage->nFree -= (u16)(2 + sz); - memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip); - if( iChild ){ - put4byte(&data[idx], iChild); - } - ptr = &data[end]; - endPtr = &data[ins]; - assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */ - while( ptr>endPtr ){ - *(u16*)ptr = *(u16*)&ptr[-2]; - ptr -= 2; - } - put2byte(&data[ins], idx); - put2byte(&data[pPage->hdrOffset+3], pPage->nCell); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pPage->pBt->autoVacuum ){ - /* The cell may contain a pointer to an overflow page. If so, write - ** the entry for the overflow page into the pointer map. - */ - ptrmapPutOvflPtr(pPage, pCell, pRC); - } -#endif - } -} - -/* -** Add a list of cells to a page. The page should be initially empty. -** The cells are guaranteed to fit on the page. -*/ -static void assemblePage( - MemPage *pPage, /* The page to be assemblied */ - int nCell, /* The number of cells to add to this page */ - u8 **apCell, /* Pointers to cell bodies */ - u16 *aSize /* Sizes of the cells */ -){ - int i; /* Loop counter */ - u8 *pCellptr; /* Address of next cell pointer */ - int cellbody; /* Address of next cell body */ - u8 * const data = pPage->aData; /* Pointer to data for pPage */ - const int hdr = pPage->hdrOffset; /* Offset of header on pPage */ - const int nUsable = pPage->pBt->usableSize; /* Usable size of page */ - - assert( pPage->nOverflow==0 ); - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( nCell>=0 && nCell<=(int)MX_CELL(pPage->pBt) - && (int)MX_CELL(pPage->pBt)<=10921); - assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - - /* Check that the page has just been zeroed by zeroPage() */ - assert( pPage->nCell==0 ); - assert( get2byteNotZero(&data[hdr+5])==nUsable ); - - pCellptr = &pPage->aCellIdx[nCell*2]; - cellbody = nUsable; - for(i=nCell-1; i>=0; i--){ - u16 sz = aSize[i]; - pCellptr -= 2; - cellbody -= sz; - put2byte(pCellptr, cellbody); - memcpy(&data[cellbody], apCell[i], sz); - } - put2byte(&data[hdr+3], nCell); - put2byte(&data[hdr+5], cellbody); - pPage->nFree -= (nCell*2 + nUsable - cellbody); - pPage->nCell = (u16)nCell; -} - -/* -** The following parameters determine how many adjacent pages get involved -** in a balancing operation. NN is the number of neighbors on either side -** of the page that participate in the balancing operation. NB is the -** total number of pages that participate, including the target page and -** NN neighbors on either side. -** -** The minimum value of NN is 1 (of course). Increasing NN above 1 -** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance -** in exchange for a larger degradation in INSERT and UPDATE performance. -** The value of NN appears to give the best results overall. -*/ -#define NN 1 /* Number of neighbors on either side of pPage */ -#define NB (NN*2+1) /* Total pages involved in the balance */ - - -#ifndef SQLITE_OMIT_QUICKBALANCE -/* -** This version of balance() handles the common special case where -** a new entry is being inserted on the extreme right-end of the -** tree, in other words, when the new entry will become the largest -** entry in the tree. -** -** Instead of trying to balance the 3 right-most leaf pages, just add -** a new page to the right-hand side and put the one new entry in -** that page. This leaves the right side of the tree somewhat -** unbalanced. But odds are that we will be inserting new entries -** at the end soon afterwards so the nearly empty page will quickly -** fill up. On average. -** -** pPage is the leaf page which is the right-most page in the tree. -** pParent is its parent. pPage must have a single overflow entry -** which is also the right-most entry on the page. -** -** The pSpace buffer is used to store a temporary copy of the divider -** cell that will be inserted into pParent. Such a cell consists of a 4 -** byte page number followed by a variable length integer. In other -** words, at most 13 bytes. Hence the pSpace buffer must be at -** least 13 bytes in size. -*/ -static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ - BtShared *const pBt = pPage->pBt; /* B-Tree Database */ - MemPage *pNew; /* Newly allocated page */ - int rc; /* Return Code */ - Pgno pgnoNew; /* Page number of pNew */ - - assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - assert( pPage->nOverflow==1 ); - - /* This error condition is now caught prior to reaching this function */ - if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; - - /* Allocate a new page. This page will become the right-sibling of - ** pPage. Make the parent page writable, so that the new divider cell - ** may be inserted. If both these operations are successful, proceed. - */ - rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); - - if( rc==SQLITE_OK ){ - - u8 *pOut = &pSpace[4]; - u8 *pCell = pPage->apOvfl[0]; - u16 szCell = cellSizePtr(pPage, pCell); - u8 *pStop; - - assert( sqlite3PagerIswriteable(pNew->pDbPage) ); - assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) ); - zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF); - assemblePage(pNew, 1, &pCell, &szCell); - - /* If this is an auto-vacuum database, update the pointer map - ** with entries for the new page, and any pointer from the - ** cell on the page to an overflow page. If either of these - ** operations fails, the return code is set, but the contents - ** of the parent page are still manipulated by thh code below. - ** That is Ok, at this point the parent page is guaranteed to - ** be marked as dirty. Returning an error code will cause a - ** rollback, undoing any changes made to the parent page. - */ - if( ISAUTOVACUUM ){ - ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc); - if( szCell>pNew->minLocal ){ - ptrmapPutOvflPtr(pNew, pCell, &rc); - } - } - - /* Create a divider cell to insert into pParent. The divider cell - ** consists of a 4-byte page number (the page number of pPage) and - ** a variable length key value (which must be the same value as the - ** largest key on pPage). - ** - ** To find the largest key value on pPage, first find the right-most - ** cell on pPage. The first two fields of this cell are the - ** record-length (a variable length integer at most 32-bits in size) - ** and the key value (a variable length integer, may have any value). - ** The first of the while(...) loops below skips over the record-length - ** field. The second while(...) loop copies the key value from the - ** cell on pPage into the pSpace buffer. - */ - pCell = findCell(pPage, pPage->nCell-1); - pStop = &pCell[9]; - while( (*(pCell++)&0x80) && pCellnCell, pSpace, (int)(pOut-pSpace), - 0, pPage->pgno, &rc); - - /* Set the right-child pointer of pParent to point to the new page. */ - put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); - - /* Release the reference to the new page. */ - releasePage(pNew); - } - - return rc; -} -#endif /* SQLITE_OMIT_QUICKBALANCE */ - -#if 0 -/* -** This function does not contribute anything to the operation of SQLite. -** it is sometimes activated temporarily while debugging code responsible -** for setting pointer-map entries. -*/ -static int ptrmapCheckPages(MemPage **apPage, int nPage){ - int i, j; - for(i=0; ipBt; - assert( pPage->isInit ); - - for(j=0; jnCell; j++){ - CellInfo info; - u8 *z; - - z = findCell(pPage, j); - btreeParseCellPtr(pPage, z, &info); - if( info.iOverflow ){ - Pgno ovfl = get4byte(&z[info.iOverflow]); - ptrmapGet(pBt, ovfl, &e, &n); - assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 ); - } - if( !pPage->leaf ){ - Pgno child = get4byte(z); - ptrmapGet(pBt, child, &e, &n); - assert( n==pPage->pgno && e==PTRMAP_BTREE ); - } - } - if( !pPage->leaf ){ - Pgno child = get4byte(&pPage->aData[pPage->hdrOffset+8]); - ptrmapGet(pBt, child, &e, &n); - assert( n==pPage->pgno && e==PTRMAP_BTREE ); - } - } - return 1; -} -#endif - -/* -** This function is used to copy the contents of the b-tree node stored -** on page pFrom to page pTo. If page pFrom was not a leaf page, then -** the pointer-map entries for each child page are updated so that the -** parent page stored in the pointer map is page pTo. If pFrom contained -** any cells with overflow page pointers, then the corresponding pointer -** map entries are also updated so that the parent page is page pTo. -** -** If pFrom is currently carrying any overflow cells (entries in the -** MemPage.apOvfl[] array), they are not copied to pTo. -** -** Before returning, page pTo is reinitialized using btreeInitPage(). -** -** The performance of this function is not critical. It is only used by -** the balance_shallower() and balance_deeper() procedures, neither of -** which are called often under normal circumstances. -*/ -static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){ - if( (*pRC)==SQLITE_OK ){ - BtShared * const pBt = pFrom->pBt; - u8 * const aFrom = pFrom->aData; - u8 * const aTo = pTo->aData; - int const iFromHdr = pFrom->hdrOffset; - int const iToHdr = ((pTo->pgno==1) ? 100 : 0); - int rc; - int iData; - - - assert( pFrom->isInit ); - assert( pFrom->nFree>=iToHdr ); - assert( get2byte(&aFrom[iFromHdr+5]) <= (int)pBt->usableSize ); - - /* Copy the b-tree node content from page pFrom to page pTo. */ - iData = get2byte(&aFrom[iFromHdr+5]); - memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData); - memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell); - - /* Reinitialize page pTo so that the contents of the MemPage structure - ** match the new data. The initialization of pTo can actually fail under - ** fairly obscure circumstances, even though it is a copy of initialized - ** page pFrom. - */ - pTo->isInit = 0; - rc = btreeInitPage(pTo); - if( rc!=SQLITE_OK ){ - *pRC = rc; - return; - } - - /* If this is an auto-vacuum database, update the pointer-map entries - ** for any b-tree or overflow pages that pTo now contains the pointers to. - */ - if( ISAUTOVACUUM ){ - *pRC = setChildPtrmaps(pTo); - } - } -} - -/* -** This routine redistributes cells on the iParentIdx'th child of pParent -** (hereafter "the page") and up to 2 siblings so that all pages have about the -** same amount of free space. Usually a single sibling on either side of the -** page are used in the balancing, though both siblings might come from one -** side if the page is the first or last child of its parent. If the page -** has fewer than 2 siblings (something which can only happen if the page -** is a root page or a child of a root page) then all available siblings -** participate in the balancing. -** -** The number of siblings of the page might be increased or decreased by -** one or two in an effort to keep pages nearly full but not over full. -** -** Note that when this routine is called, some of the cells on the page -** might not actually be stored in MemPage.aData[]. This can happen -** if the page is overfull. This routine ensures that all cells allocated -** to the page and its siblings fit into MemPage.aData[] before returning. -** -** In the course of balancing the page and its siblings, cells may be -** inserted into or removed from the parent page (pParent). Doing so -** may cause the parent page to become overfull or underfull. If this -** happens, it is the responsibility of the caller to invoke the correct -** balancing routine to fix this problem (see the balance() routine). -** -** If this routine fails for any reason, it might leave the database -** in a corrupted state. So if this routine fails, the database should -** be rolled back. -** -** The third argument to this function, aOvflSpace, is a pointer to a -** buffer big enough to hold one page. If while inserting cells into the parent -** page (pParent) the parent page becomes overfull, this buffer is -** used to store the parent's overflow cells. Because this function inserts -** a maximum of four divider cells into the parent page, and the maximum -** size of a cell stored within an internal node is always less than 1/4 -** of the page-size, the aOvflSpace[] buffer is guaranteed to be large -** enough for all overflow cells. -** -** If aOvflSpace is set to a null pointer, this function returns -** SQLITE_NOMEM. -*/ -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) -#pragma optimize("", off) -#endif -static int balance_nonroot( - MemPage *pParent, /* Parent page of siblings being balanced */ - int iParentIdx, /* Index of "the page" in pParent */ - u8 *aOvflSpace, /* page-size bytes of space for parent ovfl */ - int isRoot, /* True if pParent is a root-page */ - int bBulk /* True if this call is part of a bulk load */ -){ - BtShared *pBt; /* The whole database */ - int nCell = 0; /* Number of cells in apCell[] */ - int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ - int nNew = 0; /* Number of pages in apNew[] */ - int nOld; /* Number of pages in apOld[] */ - int i, j, k; /* Loop counters */ - int nxDiv; /* Next divider slot in pParent->aCell[] */ - int rc = SQLITE_OK; /* The return code */ - u16 leafCorrection; /* 4 if pPage is a leaf. 0 if not */ - int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ - int usableSpace; /* Bytes in pPage beyond the header */ - int pageFlags; /* Value of pPage->aData[0] */ - int subtotal; /* Subtotal of bytes in cells on one page */ - int iSpace1 = 0; /* First unused byte of aSpace1[] */ - int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */ - int szScratch; /* Size of scratch memory requested */ - MemPage *apOld[NB]; /* pPage and up to two siblings */ - MemPage *apCopy[NB]; /* Private copies of apOld[] pages */ - MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ - u8 *pRight; /* Location in parent of right-sibling pointer */ - u8 *apDiv[NB-1]; /* Divider cells in pParent */ - int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */ - int szNew[NB+2]; /* Combined size of cells place on i-th page */ - u8 **apCell = 0; /* All cells begin balanced */ - u16 *szCell; /* Local size of all cells in apCell[] */ - u8 *aSpace1; /* Space for copies of dividers cells */ - Pgno pgno; /* Temp var to store a page number in */ - - pBt = pParent->pBt; - assert( sqlite3_mutex_held(pBt->mutex) ); - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - -#if 0 - TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); -#endif - - /* At this point pParent may have at most one overflow cell. And if - ** this overflow cell is present, it must be the cell with - ** index iParentIdx. This scenario comes about when this function - ** is called (indirectly) from sqlite3BtreeDelete(). - */ - assert( pParent->nOverflow==0 || pParent->nOverflow==1 ); - assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx ); - - if( !aOvflSpace ){ - return SQLITE_NOMEM; - } - - /* Find the sibling pages to balance. Also locate the cells in pParent - ** that divide the siblings. An attempt is made to find NN siblings on - ** either side of pPage. More siblings are taken from one side, however, - ** if there are fewer than NN siblings on the other side. If pParent - ** has NB or fewer children then all children of pParent are taken. - ** - ** This loop also drops the divider cells from the parent page. This - ** way, the remainder of the function does not have to deal with any - ** overflow cells in the parent page, since if any existed they will - ** have already been removed. - */ - i = pParent->nOverflow + pParent->nCell; - if( i<2 ){ - nxDiv = 0; - }else{ - assert( bBulk==0 || bBulk==1 ); - if( iParentIdx==0 ){ - nxDiv = 0; - }else if( iParentIdx==i ){ - nxDiv = i-2+bBulk; - }else{ - assert( bBulk==0 ); - nxDiv = iParentIdx-1; - } - i = 2-bBulk; - } - nOld = i+1; - if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){ - pRight = &pParent->aData[pParent->hdrOffset+8]; - }else{ - pRight = findCell(pParent, i+nxDiv-pParent->nOverflow); - } - pgno = get4byte(pRight); - while( 1 ){ - rc = getAndInitPage(pBt, pgno, &apOld[i], 0); - if( rc ){ - memset(apOld, 0, (i+1)*sizeof(MemPage*)); - goto balance_cleanup; - } - nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; - if( (i--)==0 ) break; - - if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){ - apDiv[i] = pParent->apOvfl[0]; - pgno = get4byte(apDiv[i]); - szNew[i] = cellSizePtr(pParent, apDiv[i]); - pParent->nOverflow = 0; - }else{ - apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow); - pgno = get4byte(apDiv[i]); - szNew[i] = cellSizePtr(pParent, apDiv[i]); - - /* Drop the cell from the parent page. apDiv[i] still points to - ** the cell within the parent, even though it has been dropped. - ** This is safe because dropping a cell only overwrites the first - ** four bytes of it, and this function does not need the first - ** four bytes of the divider cell. So the pointer is safe to use - ** later on. - ** - ** But not if we are in secure-delete mode. In secure-delete mode, - ** the dropCell() routine will overwrite the entire cell with zeroes. - ** In this case, temporarily copy the cell into the aOvflSpace[] - ** buffer. It will be copied out again as soon as the aSpace[] buffer - ** is allocated. */ - if( pBt->btsFlags & BTS_SECURE_DELETE ){ - int iOff; - - iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData); - if( (iOff+szNew[i])>(int)pBt->usableSize ){ - rc = SQLITE_CORRUPT_BKPT; - memset(apOld, 0, (i+1)*sizeof(MemPage*)); - goto balance_cleanup; - }else{ - memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]); - apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; - } - } - dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); - } - } - - /* Make nMaxCells a multiple of 4 in order to preserve 8-byte - ** alignment */ - nMaxCells = (nMaxCells + 3)&~3; - - /* - ** Allocate space for memory structures - */ - k = pBt->pageSize + ROUND8(sizeof(MemPage)); - szScratch = - nMaxCells*sizeof(u8*) /* apCell */ - + nMaxCells*sizeof(u16) /* szCell */ - + pBt->pageSize /* aSpace1 */ - + k*nOld; /* Page copies (apCopy) */ - apCell = sqlite3ScratchMalloc( szScratch ); - if( apCell==0 ){ - rc = SQLITE_NOMEM; - goto balance_cleanup; - } - szCell = (u16*)&apCell[nMaxCells]; - aSpace1 = (u8*)&szCell[nMaxCells]; - assert( EIGHT_BYTE_ALIGNMENT(aSpace1) ); - - /* - ** Load pointers to all cells on sibling pages and the divider cells - ** into the local apCell[] array. Make copies of the divider cells - ** into space obtained from aSpace1[] and remove the divider cells - ** from pParent. - ** - ** If the siblings are on leaf pages, then the child pointers of the - ** divider cells are stripped from the cells before they are copied - ** into aSpace1[]. In this way, all cells in apCell[] are without - ** child pointers. If siblings are not leaves, then all cell in - ** apCell[] include child pointers. Either way, all cells in apCell[] - ** are alike. - ** - ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. - ** leafData: 1 if pPage holds key+data and pParent holds only keys. - */ - leafCorrection = apOld[0]->leaf*4; - leafData = apOld[0]->hasData; - for(i=0; ipageSize + k*i]; - memcpy(pOld, apOld[i], sizeof(MemPage)); - pOld->aData = (void*)&pOld[1]; - memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize); - - limit = pOld->nCell+pOld->nOverflow; - if( pOld->nOverflow>0 ){ - for(j=0; jaData; - u16 maskPage = pOld->maskPage; - u16 cellOffset = pOld->cellOffset; - for(j=0; jmaxLocal+23 ); - assert( iSpace1 <= (int)pBt->pageSize ); - memcpy(pTemp, apDiv[i], sz); - apCell[nCell] = pTemp+leafCorrection; - assert( leafCorrection==0 || leafCorrection==4 ); - szCell[nCell] = szCell[nCell] - leafCorrection; - if( !pOld->leaf ){ - assert( leafCorrection==0 ); - assert( pOld->hdrOffset==0 ); - /* The right pointer of the child page pOld becomes the left - ** pointer of the divider cell */ - memcpy(apCell[nCell], &pOld->aData[8], 4); - }else{ - assert( leafCorrection==4 ); - if( szCell[nCell]<4 ){ - /* Do not allow any cells smaller than 4 bytes. */ - szCell[nCell] = 4; - } - } - nCell++; - } - } - - /* - ** Figure out the number of pages needed to hold all nCell cells. - ** Store this number in "k". Also compute szNew[] which is the total - ** size of all cells on the i-th page and cntNew[] which is the index - ** in apCell[] of the cell that divides page i from page i+1. - ** cntNew[k] should equal nCell. - ** - ** Values computed by this block: - ** - ** k: The total number of sibling pages - ** szNew[i]: Spaced used on the i-th sibling page. - ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to - ** the right of the i-th sibling page. - ** usableSpace: Number of bytes of space available on each sibling. - ** - */ - usableSpace = pBt->usableSize - 12 + leafCorrection; - for(subtotal=k=i=0; i usableSpace ){ - szNew[k] = subtotal - szCell[i]; - cntNew[k] = i; - if( leafData ){ i--; } - subtotal = 0; - k++; - if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } - } - } - szNew[k] = subtotal; - cntNew[k] = nCell; - k++; - - /* - ** The packing computed by the previous block is biased toward the siblings - ** on the left side. The left siblings are always nearly full, while the - ** right-most sibling might be nearly empty. This block of code attempts - ** to adjust the packing of siblings to get a better balance. - ** - ** This adjustment is more than an optimization. The packing above might - ** be so out of balance as to be illegal. For example, the right-most - ** sibling might be completely empty. This adjustment is not optional. - */ - for(i=k-1; i>0; i--){ - int szRight = szNew[i]; /* Size of sibling on the right */ - int szLeft = szNew[i-1]; /* Size of sibling on the left */ - int r; /* Index of right-most cell in left sibling */ - int d; /* Index of first cell to the left of right sibling */ - - r = cntNew[i-1] - 1; - d = r + 1 - leafData; - assert( d0) or pPage is - ** a virtual root page. A virtual root page is when the real root - ** page is page 1 and we are the only child of that page. - ** - ** UPDATE: The assert() below is not necessarily true if the database - ** file is corrupt. The corruption will be detected and reported later - ** in this procedure so there is no need to act upon it now. - */ -#if 0 - assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) ); -#endif - - TRACE(("BALANCE: old: %d %d %d ", - apOld[0]->pgno, - nOld>=2 ? apOld[1]->pgno : 0, - nOld>=3 ? apOld[2]->pgno : 0 - )); - - /* - ** Allocate k new pages. Reuse old pages where possible. - */ - if( apOld[0]->pgno<=1 ){ - rc = SQLITE_CORRUPT_BKPT; - goto balance_cleanup; - } - pageFlags = apOld[0]->aData[0]; - for(i=0; ipDbPage); - nNew++; - if( rc ) goto balance_cleanup; - }else{ - assert( i>0 ); - rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0); - if( rc ) goto balance_cleanup; - apNew[i] = pNew; - nNew++; - - /* Set the pointer-map entry for the new sibling page. */ - if( ISAUTOVACUUM ){ - ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc); - if( rc!=SQLITE_OK ){ - goto balance_cleanup; - } - } - } - } - - /* Free any old pages that were not reused as new pages. - */ - while( ipgno; - int minI = i; - for(j=i+1; jpgno<(unsigned)minV ){ - minI = j; - minV = apNew[j]->pgno; - } - } - if( minI>i ){ - MemPage *pT; - pT = apNew[i]; - apNew[i] = apNew[minI]; - apNew[minI] = pT; - } - } - TRACE(("new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n", - apNew[0]->pgno, szNew[0], - nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0, - nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0, - nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0, - nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0)); - - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - put4byte(pRight, apNew[nNew-1]->pgno); - - /* - ** Evenly distribute the data in apCell[] across the new pages. - ** Insert divider cells into pParent as necessary. - */ - j = 0; - for(i=0; inCell>0 || (nNew==1 && cntNew[0]==0) ); - assert( pNew->nOverflow==0 ); - - j = cntNew[i]; - - /* If the sibling page assembled above was not the right-most sibling, - ** insert a divider cell into the parent page. - */ - assert( ileaf ){ - memcpy(&pNew->aData[8], pCell, 4); - }else if( leafData ){ - /* If the tree is a leaf-data tree, and the siblings are leaves, - ** then there is no divider cell in apCell[]. Instead, the divider - ** cell consists of the integer key for the right-most cell of - ** the sibling-page assembled above only. - */ - CellInfo info; - j--; - btreeParseCellPtr(pNew, apCell[j], &info); - pCell = pTemp; - sz = 4 + putVarint(&pCell[4], info.nKey); - pTemp = 0; - }else{ - pCell -= 4; - /* Obscure case for non-leaf-data trees: If the cell at pCell was - ** previously stored on a leaf node, and its reported size was 4 - ** bytes, then it may actually be smaller than this - ** (see btreeParseCellPtr(), 4 bytes is the minimum size of - ** any cell). But it is important to pass the correct size to - ** insertCell(), so reparse the cell now. - ** - ** Note that this can never happen in an SQLite data file, as all - ** cells are at least 4 bytes. It only happens in b-trees used - ** to evaluate "IN (SELECT ...)" and similar clauses. - */ - if( szCell[j]==4 ){ - assert(leafCorrection==4); - sz = cellSizePtr(pParent, pCell); - } - } - iOvflSpace += sz; - assert( sz<=pBt->maxLocal+23 ); - assert( iOvflSpace <= (int)pBt->pageSize ); - insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno, &rc); - if( rc!=SQLITE_OK ) goto balance_cleanup; - assert( sqlite3PagerIswriteable(pParent->pDbPage) ); - - j++; - nxDiv++; - } - } - assert( j==nCell ); - assert( nOld>0 ); - assert( nNew>0 ); - if( (pageFlags & PTF_LEAF)==0 ){ - u8 *zChild = &apCopy[nOld-1]->aData[8]; - memcpy(&apNew[nNew-1]->aData[8], zChild, 4); - } - - if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){ - /* The root page of the b-tree now contains no cells. The only sibling - ** page is the right-child of the parent. Copy the contents of the - ** child page into the parent, decreasing the overall height of the - ** b-tree structure by one. This is described as the "balance-shallower" - ** sub-algorithm in some documentation. - ** - ** If this is an auto-vacuum database, the call to copyNodeContent() - ** sets all pointer-map entries corresponding to database image pages - ** for which the pointer is stored within the content being copied. - ** - ** The second assert below verifies that the child page is defragmented - ** (it must be, as it was just reconstructed using assemblePage()). This - ** is important if the parent page happens to be page 1 of the database - ** image. */ - assert( nNew==1 ); - assert( apNew[0]->nFree == - (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) - ); - copyNodeContent(apNew[0], pParent, &rc); - freePage(apNew[0], &rc); - }else if( ISAUTOVACUUM ){ - /* Fix the pointer-map entries for all the cells that were shifted around. - ** There are several different types of pointer-map entries that need to - ** be dealt with by this routine. Some of these have been set already, but - ** many have not. The following is a summary: - ** - ** 1) The entries associated with new sibling pages that were not - ** siblings when this function was called. These have already - ** been set. We don't need to worry about old siblings that were - ** moved to the free-list - the freePage() code has taken care - ** of those. - ** - ** 2) The pointer-map entries associated with the first overflow - ** page in any overflow chains used by new divider cells. These - ** have also already been taken care of by the insertCell() code. - ** - ** 3) If the sibling pages are not leaves, then the child pages of - ** cells stored on the sibling pages may need to be updated. - ** - ** 4) If the sibling pages are not internal intkey nodes, then any - ** overflow pages used by these cells may need to be updated - ** (internal intkey nodes never contain pointers to overflow pages). - ** - ** 5) If the sibling pages are not leaves, then the pointer-map - ** entries for the right-child pages of each sibling may need - ** to be updated. - ** - ** Cases 1 and 2 are dealt with above by other code. The next - ** block deals with cases 3 and 4 and the one after that, case 5. Since - ** setting a pointer map entry is a relatively expensive operation, this - ** code only sets pointer map entries for child or overflow pages that have - ** actually moved between pages. */ - MemPage *pNew = apNew[0]; - MemPage *pOld = apCopy[0]; - int nOverflow = pOld->nOverflow; - int iNextOld = pOld->nCell + nOverflow; - int iOverflow = (nOverflow ? pOld->aiOvfl[0] : -1); - j = 0; /* Current 'old' sibling page */ - k = 0; /* Current 'new' sibling page */ - for(i=0; inCell + pOld->nOverflow; - if( pOld->nOverflow ){ - nOverflow = pOld->nOverflow; - iOverflow = i + !leafData + pOld->aiOvfl[0]; - } - isDivider = !leafData; - } - - assert(nOverflow>0 || iOverflowaiOvfl[0]==pOld->aiOvfl[1]-1); - assert(nOverflow<3 || pOld->aiOvfl[1]==pOld->aiOvfl[2]-1); - if( i==iOverflow ){ - isDivider = 1; - if( (--nOverflow)>0 ){ - iOverflow++; - } - } - - if( i==cntNew[k] ){ - /* Cell i is the cell immediately following the last cell on new - ** sibling page k. If the siblings are not leaf pages of an - ** intkey b-tree, then cell i is a divider cell. */ - pNew = apNew[++k]; - if( !leafData ) continue; - } - assert( jpgno!=pNew->pgno ){ - if( !leafCorrection ){ - ptrmapPut(pBt, get4byte(apCell[i]), PTRMAP_BTREE, pNew->pgno, &rc); - } - if( szCell[i]>pNew->minLocal ){ - ptrmapPutOvflPtr(pNew, apCell[i], &rc); - } - } - } - - if( !leafCorrection ){ - for(i=0; iaData[8]); - ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); - } - } - -#if 0 - /* The ptrmapCheckPages() contains assert() statements that verify that - ** all pointer map pages are set correctly. This is helpful while - ** debugging. This is usually disabled because a corrupt database may - ** cause an assert() statement to fail. */ - ptrmapCheckPages(apNew, nNew); - ptrmapCheckPages(&pParent, 1); -#endif - } - - assert( pParent->isInit ); - TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", - nOld, nNew, nCell)); - - /* - ** Cleanup before returning. - */ -balance_cleanup: - sqlite3ScratchFree(apCell); - for(i=0; i= 1700 && defined(_M_ARM) -#pragma optimize("", on) -#endif - - -/* -** This function is called when the root page of a b-tree structure is -** overfull (has one or more overflow pages). -** -** A new child page is allocated and the contents of the current root -** page, including overflow cells, are copied into the child. The root -** page is then overwritten to make it an empty page with the right-child -** pointer pointing to the new page. -** -** Before returning, all pointer-map entries corresponding to pages -** that the new child-page now contains pointers to are updated. The -** entry corresponding to the new right-child pointer of the root -** page is also updated. -** -** If successful, *ppChild is set to contain a reference to the child -** page and SQLITE_OK is returned. In this case the caller is required -** to call releasePage() on *ppChild exactly once. If an error occurs, -** an error code is returned and *ppChild is set to 0. -*/ -static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ - int rc; /* Return value from subprocedures */ - MemPage *pChild = 0; /* Pointer to a new child page */ - Pgno pgnoChild = 0; /* Page number of the new child page */ - BtShared *pBt = pRoot->pBt; /* The BTree */ - - assert( pRoot->nOverflow>0 ); - assert( sqlite3_mutex_held(pBt->mutex) ); - - /* Make pRoot, the root page of the b-tree, writable. Allocate a new - ** page that will become the new right-child of pPage. Copy the contents - ** of the node stored on pRoot into the new child page. - */ - rc = sqlite3PagerWrite(pRoot->pDbPage); - if( rc==SQLITE_OK ){ - rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0); - copyNodeContent(pRoot, pChild, &rc); - if( ISAUTOVACUUM ){ - ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc); - } - } - if( rc ){ - *ppChild = 0; - releasePage(pChild); - return rc; - } - assert( sqlite3PagerIswriteable(pChild->pDbPage) ); - assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); - assert( pChild->nCell==pRoot->nCell ); - - TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); - - /* Copy the overflow cells from pRoot to pChild */ - memcpy(pChild->aiOvfl, pRoot->aiOvfl, - pRoot->nOverflow*sizeof(pRoot->aiOvfl[0])); - memcpy(pChild->apOvfl, pRoot->apOvfl, - pRoot->nOverflow*sizeof(pRoot->apOvfl[0])); - pChild->nOverflow = pRoot->nOverflow; - - /* Zero the contents of pRoot. Then install pChild as the right-child. */ - zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF); - put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild); - - *ppChild = pChild; - return SQLITE_OK; -} - -/* -** The page that pCur currently points to has just been modified in -** some way. This function figures out if this modification means the -** tree needs to be balanced, and if so calls the appropriate balancing -** routine. Balancing routines are: -** -** balance_quick() -** balance_deeper() -** balance_nonroot() -*/ -static int balance(BtCursor *pCur){ - int rc = SQLITE_OK; - const int nMin = pCur->pBt->usableSize * 2 / 3; - u8 aBalanceQuickSpace[13]; - u8 *pFree = 0; - - TESTONLY( int balance_quick_called = 0 ); - TESTONLY( int balance_deeper_called = 0 ); - - do { - int iPage = pCur->iPage; - MemPage *pPage = pCur->apPage[iPage]; - - if( iPage==0 ){ - if( pPage->nOverflow ){ - /* The root page of the b-tree is overfull. In this case call the - ** balance_deeper() function to create a new child for the root-page - ** and copy the current contents of the root-page to it. The - ** next iteration of the do-loop will balance the child page. - */ - assert( (balance_deeper_called++)==0 ); - rc = balance_deeper(pPage, &pCur->apPage[1]); - if( rc==SQLITE_OK ){ - pCur->iPage = 1; - pCur->aiIdx[0] = 0; - pCur->aiIdx[1] = 0; - assert( pCur->apPage[1]->nOverflow ); - } - }else{ - break; - } - }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){ - break; - }else{ - MemPage * const pParent = pCur->apPage[iPage-1]; - int const iIdx = pCur->aiIdx[iPage-1]; - - rc = sqlite3PagerWrite(pParent->pDbPage); - if( rc==SQLITE_OK ){ -#ifndef SQLITE_OMIT_QUICKBALANCE - if( pPage->hasData - && pPage->nOverflow==1 - && pPage->aiOvfl[0]==pPage->nCell - && pParent->pgno!=1 - && pParent->nCell==iIdx - ){ - /* Call balance_quick() to create a new sibling of pPage on which - ** to store the overflow cell. balance_quick() inserts a new cell - ** into pParent, which may cause pParent overflow. If this - ** happens, the next interation of the do-loop will balance pParent - ** use either balance_nonroot() or balance_deeper(). Until this - ** happens, the overflow cell is stored in the aBalanceQuickSpace[] - ** buffer. - ** - ** The purpose of the following assert() is to check that only a - ** single call to balance_quick() is made for each call to this - ** function. If this were not verified, a subtle bug involving reuse - ** of the aBalanceQuickSpace[] might sneak in. - */ - assert( (balance_quick_called++)==0 ); - rc = balance_quick(pParent, pPage, aBalanceQuickSpace); - }else -#endif - { - /* In this case, call balance_nonroot() to redistribute cells - ** between pPage and up to 2 of its sibling pages. This involves - ** modifying the contents of pParent, which may cause pParent to - ** become overfull or underfull. The next iteration of the do-loop - ** will balance the parent page to correct this. - ** - ** If the parent page becomes overfull, the overflow cell or cells - ** are stored in the pSpace buffer allocated immediately below. - ** A subsequent iteration of the do-loop will deal with this by - ** calling balance_nonroot() (balance_deeper() may be called first, - ** but it doesn't deal with overflow cells - just moves them to a - ** different page). Once this subsequent call to balance_nonroot() - ** has completed, it is safe to release the pSpace buffer used by - ** the previous call, as the overflow cell data will have been - ** copied either into the body of a database page or into the new - ** pSpace buffer passed to the latter call to balance_nonroot(). - */ - u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); - rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints); - if( pFree ){ - /* If pFree is not NULL, it points to the pSpace buffer used - ** by a previous call to balance_nonroot(). Its contents are - ** now stored either on real database pages or within the - ** new pSpace buffer, so it may be safely freed here. */ - sqlite3PageFree(pFree); - } - - /* The pSpace buffer will be freed after the next call to - ** balance_nonroot(), or just before this function returns, whichever - ** comes first. */ - pFree = pSpace; - } - } - - pPage->nOverflow = 0; - - /* The next iteration of the do-loop balances the parent page. */ - releasePage(pPage); - pCur->iPage--; - } - }while( rc==SQLITE_OK ); - - if( pFree ){ - sqlite3PageFree(pFree); - } - return rc; -} - - -/* -** Insert a new record into the BTree. The key is given by (pKey,nKey) -** and the data is given by (pData,nData). The cursor is used only to -** define what table the record should be inserted into. The cursor -** is left pointing at a random location. -** -** For an INTKEY table, only the nKey value of the key is used. pKey is -** ignored. For a ZERODATA table, the pData and nData are both ignored. -** -** If the seekResult parameter is non-zero, then a successful call to -** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already -** been performed. seekResult is the search result returned (a negative -** number if pCur points at an entry that is smaller than (pKey, nKey), or -** a positive value if pCur points at an etry that is larger than -** (pKey, nKey)). -** -** If the seekResult parameter is non-zero, then the caller guarantees that -** cursor pCur is pointing at the existing copy of a row that is to be -** overwritten. If the seekResult parameter is 0, then cursor pCur may -** point to any entry or to no entry at all and so this function has to seek -** the cursor before the new key can be inserted. -*/ -SQLITE_PRIVATE int sqlite3BtreeInsert( - BtCursor *pCur, /* Insert data into the table of this cursor */ - const void *pKey, i64 nKey, /* The key of the new record */ - const void *pData, int nData, /* The data of the new record */ - int nZero, /* Number of extra 0 bytes to append to data */ - int appendBias, /* True if this is likely an append */ - int seekResult /* Result of prior MovetoUnpacked() call */ -){ - int rc; - int loc = seekResult; /* -1: before desired location +1: after */ - int szNew = 0; - int idx; - MemPage *pPage; - Btree *p = pCur->pBtree; - BtShared *pBt = p->pBt; - unsigned char *oldCell; - unsigned char *newCell = 0; - - if( pCur->eState==CURSOR_FAULT ){ - assert( pCur->skipNext!=SQLITE_OK ); - return pCur->skipNext; - } - - assert( cursorHoldsMutex(pCur) ); - assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE - && (pBt->btsFlags & BTS_READ_ONLY)==0 ); - assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); - - /* Assert that the caller has been consistent. If this cursor was opened - ** expecting an index b-tree, then the caller should be inserting blob - ** keys with no associated data. If the cursor was opened expecting an - ** intkey table, the caller should be inserting integer keys with a - ** blob of associated data. */ - assert( (pKey==0)==(pCur->pKeyInfo==0) ); - - /* Save the positions of any other cursors open on this table. - ** - ** In some cases, the call to btreeMoveto() below is a no-op. For - ** example, when inserting data into a table with auto-generated integer - ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the - ** integer key to use. It then calls this function to actually insert the - ** data into the intkey B-Tree. In this case btreeMoveto() recognizes - ** that the cursor is already where it needs to be and returns without - ** doing any work. To avoid thwarting these optimizations, it is important - ** not to clear the cursor here. - */ - rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); - if( rc ) return rc; - - /* If this is an insert into a table b-tree, invalidate any incrblob - ** cursors open on the row being replaced (assuming this is a replace - ** operation - if it is not, the following is a no-op). */ - if( pCur->pKeyInfo==0 ){ - invalidateIncrblobCursors(p, nKey, 0); - } - - if( !loc ){ - rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc); - if( rc ) return rc; - } - assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); - - pPage = pCur->apPage[pCur->iPage]; - assert( pPage->intKey || nKey>=0 ); - assert( pPage->leaf || !pPage->intKey ); - - TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", - pCur->pgnoRoot, nKey, nData, pPage->pgno, - loc==0 ? "overwrite" : "new entry")); - assert( pPage->isInit ); - allocateTempSpace(pBt); - newCell = pBt->pTmpSpace; - if( newCell==0 ) return SQLITE_NOMEM; - rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); - if( rc ) goto end_insert; - assert( szNew==cellSizePtr(pPage, newCell) ); - assert( szNew <= MX_CELL_SIZE(pBt) ); - idx = pCur->aiIdx[pCur->iPage]; - if( loc==0 ){ - u16 szOld; - assert( idxnCell ); - rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc ){ - goto end_insert; - } - oldCell = findCell(pPage, idx); - if( !pPage->leaf ){ - memcpy(newCell, oldCell, 4); - } - szOld = cellSizePtr(pPage, oldCell); - rc = clearCell(pPage, oldCell); - dropCell(pPage, idx, szOld, &rc); - if( rc ) goto end_insert; - }else if( loc<0 && pPage->nCell>0 ){ - assert( pPage->leaf ); - idx = ++pCur->aiIdx[pCur->iPage]; - }else{ - assert( pPage->leaf ); - } - insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); - assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); - - /* If no error has occurred and pPage has an overflow cell, call balance() - ** to redistribute the cells within the tree. Since balance() may move - ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey - ** variables. - ** - ** Previous versions of SQLite called moveToRoot() to move the cursor - ** back to the root page as balance() used to invalidate the contents - ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that, - ** set the cursor state to "invalid". This makes common insert operations - ** slightly faster. - ** - ** There is a subtle but important optimization here too. When inserting - ** multiple records into an intkey b-tree using a single cursor (as can - ** happen while processing an "INSERT INTO ... SELECT" statement), it - ** is advantageous to leave the cursor pointing to the last entry in - ** the b-tree if possible. If the cursor is left pointing to the last - ** entry in the table, and the next row inserted has an integer key - ** larger than the largest existing key, it is possible to insert the - ** row without seeking the cursor. This can be a big performance boost. - */ - pCur->info.nSize = 0; - pCur->validNKey = 0; - if( rc==SQLITE_OK && pPage->nOverflow ){ - rc = balance(pCur); - - /* Must make sure nOverflow is reset to zero even if the balance() - ** fails. Internal data structure corruption will result otherwise. - ** Also, set the cursor state to invalid. This stops saveCursorPosition() - ** from trying to save the current position of the cursor. */ - pCur->apPage[pCur->iPage]->nOverflow = 0; - pCur->eState = CURSOR_INVALID; - } - assert( pCur->apPage[pCur->iPage]->nOverflow==0 ); - -end_insert: - return rc; -} - -/* -** Delete the entry that the cursor is pointing to. The cursor -** is left pointing at a arbitrary location. -*/ -SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ - Btree *p = pCur->pBtree; - BtShared *pBt = p->pBt; - int rc; /* Return code */ - MemPage *pPage; /* Page to delete cell from */ - unsigned char *pCell; /* Pointer to cell to delete */ - int iCellIdx; /* Index of cell to delete */ - int iCellDepth; /* Depth of node containing pCell */ - - assert( cursorHoldsMutex(pCur) ); - assert( pBt->inTransaction==TRANS_WRITE ); - assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); - assert( pCur->wrFlag ); - assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); - assert( !hasReadConflicts(p, pCur->pgnoRoot) ); - - if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell) - || NEVER(pCur->eState!=CURSOR_VALID) - ){ - return SQLITE_ERROR; /* Something has gone awry. */ - } - - iCellDepth = pCur->iPage; - iCellIdx = pCur->aiIdx[iCellDepth]; - pPage = pCur->apPage[iCellDepth]; - pCell = findCell(pPage, iCellIdx); - - /* If the page containing the entry to delete is not a leaf page, move - ** the cursor to the largest entry in the tree that is smaller than - ** the entry being deleted. This cell will replace the cell being deleted - ** from the internal node. The 'previous' entry is used for this instead - ** of the 'next' entry, as the previous entry is always a part of the - ** sub-tree headed by the child page of the cell being deleted. This makes - ** balancing the tree following the delete operation easier. */ - if( !pPage->leaf ){ - int notUsed; - rc = sqlite3BtreePrevious(pCur, ¬Used); - if( rc ) return rc; - } - - /* Save the positions of any other cursors open on this table before - ** making any modifications. Make the page containing the entry to be - ** deleted writable. Then free any overflow pages associated with the - ** entry and finally remove the cell itself from within the page. - */ - rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); - if( rc ) return rc; - - /* If this is a delete operation to remove a row from a table b-tree, - ** invalidate any incrblob cursors open on the row being deleted. */ - if( pCur->pKeyInfo==0 ){ - invalidateIncrblobCursors(p, pCur->info.nKey, 0); - } - - rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc ) return rc; - rc = clearCell(pPage, pCell); - dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc); - if( rc ) return rc; - - /* If the cell deleted was not located on a leaf page, then the cursor - ** is currently pointing to the largest entry in the sub-tree headed - ** by the child-page of the cell that was just deleted from an internal - ** node. The cell from the leaf node needs to be moved to the internal - ** node to replace the deleted cell. */ - if( !pPage->leaf ){ - MemPage *pLeaf = pCur->apPage[pCur->iPage]; - int nCell; - Pgno n = pCur->apPage[iCellDepth+1]->pgno; - unsigned char *pTmp; - - pCell = findCell(pLeaf, pLeaf->nCell-1); - nCell = cellSizePtr(pLeaf, pCell); - assert( MX_CELL_SIZE(pBt) >= nCell ); - - allocateTempSpace(pBt); - pTmp = pBt->pTmpSpace; - - rc = sqlite3PagerWrite(pLeaf->pDbPage); - insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); - dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); - if( rc ) return rc; - } - - /* Balance the tree. If the entry deleted was located on a leaf page, - ** then the cursor still points to that page. In this case the first - ** call to balance() repairs the tree, and the if(...) condition is - ** never true. - ** - ** Otherwise, if the entry deleted was on an internal node page, then - ** pCur is pointing to the leaf page from which a cell was removed to - ** replace the cell deleted from the internal node. This is slightly - ** tricky as the leaf node may be underfull, and the internal node may - ** be either under or overfull. In this case run the balancing algorithm - ** on the leaf node first. If the balance proceeds far enough up the - ** tree that we can be sure that any problem in the internal node has - ** been corrected, so be it. Otherwise, after balancing the leaf node, - ** walk the cursor up the tree to the internal node and balance it as - ** well. */ - rc = balance(pCur); - if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){ - while( pCur->iPage>iCellDepth ){ - releasePage(pCur->apPage[pCur->iPage--]); - } - rc = balance(pCur); - } - - if( rc==SQLITE_OK ){ - moveToRoot(pCur); - } - return rc; -} - -/* -** Create a new BTree table. Write into *piTable the page -** number for the root page of the new table. -** -** The type of type is determined by the flags parameter. Only the -** following values of flags are currently in use. Other values for -** flags might not work: -** -** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys -** BTREE_ZERODATA Used for SQL indices -*/ -static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){ - BtShared *pBt = p->pBt; - MemPage *pRoot; - Pgno pgnoRoot; - int rc; - int ptfFlags; /* Page-type flage for the root page of new table */ - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( pBt->inTransaction==TRANS_WRITE ); - assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); - -#ifdef SQLITE_OMIT_AUTOVACUUM - rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); - if( rc ){ - return rc; - } -#else - if( pBt->autoVacuum ){ - Pgno pgnoMove; /* Move a page here to make room for the root-page */ - MemPage *pPageMove; /* The page to move to. */ - - /* Creating a new table may probably require moving an existing database - ** to make room for the new tables root page. In case this page turns - ** out to be an overflow page, delete all overflow page-map caches - ** held by open cursors. - */ - invalidateAllOverflowCache(pBt); - - /* Read the value of meta[3] from the database to determine where the - ** root page of the new table should go. meta[3] is the largest root-page - ** created so far, so the new root-page is (meta[3]+1). - */ - sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot); - pgnoRoot++; - - /* The new root-page may not be allocated on a pointer-map page, or the - ** PENDING_BYTE page. - */ - while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || - pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ - pgnoRoot++; - } - assert( pgnoRoot>=3 ); - - /* Allocate a page. The page that currently resides at pgnoRoot will - ** be moved to the allocated page (unless the allocated page happens - ** to reside at pgnoRoot). - */ - rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT); - if( rc!=SQLITE_OK ){ - return rc; - } - - if( pgnoMove!=pgnoRoot ){ - /* pgnoRoot is the page that will be used for the root-page of - ** the new table (assuming an error did not occur). But we were - ** allocated pgnoMove. If required (i.e. if it was not allocated - ** by extending the file), the current page at position pgnoMove - ** is already journaled. - */ - u8 eType = 0; - Pgno iPtrPage = 0; - - /* Save the positions of any open cursors. This is required in - ** case they are holding a reference to an xFetch reference - ** corresponding to page pgnoRoot. */ - rc = saveAllCursors(pBt, 0, 0); - releasePage(pPageMove); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Move the page currently at pgnoRoot to pgnoMove. */ - rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); - if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ - rc = SQLITE_CORRUPT_BKPT; - } - if( rc!=SQLITE_OK ){ - releasePage(pRoot); - return rc; - } - assert( eType!=PTRMAP_ROOTPAGE ); - assert( eType!=PTRMAP_FREEPAGE ); - rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0); - releasePage(pRoot); - - /* Obtain the page at pgnoRoot */ - if( rc!=SQLITE_OK ){ - return rc; - } - rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = sqlite3PagerWrite(pRoot->pDbPage); - if( rc!=SQLITE_OK ){ - releasePage(pRoot); - return rc; - } - }else{ - pRoot = pPageMove; - } - - /* Update the pointer-map and meta-data with the new root-page number. */ - ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc); - if( rc ){ - releasePage(pRoot); - return rc; - } - - /* When the new root page was allocated, page 1 was made writable in - ** order either to increase the database filesize, or to decrement the - ** freelist count. Hence, the sqlite3BtreeUpdateMeta() call cannot fail. - */ - assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) ); - rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); - if( NEVER(rc) ){ - releasePage(pRoot); - return rc; - } - - }else{ - rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); - if( rc ) return rc; - } -#endif - assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); - if( createTabFlags & BTREE_INTKEY ){ - ptfFlags = PTF_INTKEY | PTF_LEAFDATA | PTF_LEAF; - }else{ - ptfFlags = PTF_ZERODATA | PTF_LEAF; - } - zeroPage(pRoot, ptfFlags); - sqlite3PagerUnref(pRoot->pDbPage); - assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 ); - *piTable = (int)pgnoRoot; - return SQLITE_OK; -} -SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ - int rc; - sqlite3BtreeEnter(p); - rc = btreeCreateTable(p, piTable, flags); - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Erase the given database page and all its children. Return -** the page to the freelist. -*/ -static int clearDatabasePage( - BtShared *pBt, /* The BTree that contains the table */ - Pgno pgno, /* Page number to clear */ - int freePageFlag, /* Deallocate page if true */ - int *pnChange /* Add number of Cells freed to this counter */ -){ - MemPage *pPage; - int rc; - unsigned char *pCell; - int i; - - assert( sqlite3_mutex_held(pBt->mutex) ); - if( pgno>btreePagecount(pBt) ){ - return SQLITE_CORRUPT_BKPT; - } - - rc = getAndInitPage(pBt, pgno, &pPage, 0); - if( rc ) return rc; - for(i=0; inCell; i++){ - pCell = findCell(pPage, i); - if( !pPage->leaf ){ - rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); - if( rc ) goto cleardatabasepage_out; - } - rc = clearCell(pPage, pCell); - if( rc ) goto cleardatabasepage_out; - } - if( !pPage->leaf ){ - rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), 1, pnChange); - if( rc ) goto cleardatabasepage_out; - }else if( pnChange ){ - assert( pPage->intKey ); - *pnChange += pPage->nCell; - } - if( freePageFlag ){ - freePage(pPage, &rc); - }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ - zeroPage(pPage, pPage->aData[0] | PTF_LEAF); - } - -cleardatabasepage_out: - releasePage(pPage); - return rc; -} - -/* -** Delete all information from a single table in the database. iTable is -** the page number of the root of the table. After this routine returns, -** the root page is empty, but still exists. -** -** This routine will fail with SQLITE_LOCKED if there are any open -** read cursors on the table. Open write cursors are moved to the -** root of the table. -** -** If pnChange is not NULL, then table iTable must be an intkey table. The -** integer value pointed to by pnChange is incremented by the number of -** entries in the table. -*/ -SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){ - int rc; - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); - assert( p->inTrans==TRANS_WRITE ); - - rc = saveAllCursors(pBt, (Pgno)iTable, 0); - - if( SQLITE_OK==rc ){ - /* Invalidate all incrblob cursors open on table iTable (assuming iTable - ** is the root of a table b-tree - if it is not, the following call is - ** a no-op). */ - invalidateIncrblobCursors(p, 0, 1); - rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange); - } - sqlite3BtreeLeave(p); - return rc; -} - -/* -** Erase all information in a table and add the root of the table to -** the freelist. Except, the root of the principle table (the one on -** page 1) is never added to the freelist. -** -** This routine will fail with SQLITE_LOCKED if there are any open -** cursors on the table. -** -** If AUTOVACUUM is enabled and the page at iTable is not the last -** root page in the database file, then the last root page -** in the database file is moved into the slot formerly occupied by -** iTable and that last slot formerly occupied by the last root page -** is added to the freelist instead of iTable. In this say, all -** root pages are kept at the beginning of the database file, which -** is necessary for AUTOVACUUM to work right. *piMoved is set to the -** page number that used to be the last root page in the file before -** the move. If no page gets moved, *piMoved is set to 0. -** The last root page is recorded in meta[3] and the value of -** meta[3] is updated by this procedure. -*/ -static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ - int rc; - MemPage *pPage = 0; - BtShared *pBt = p->pBt; - - assert( sqlite3BtreeHoldsMutex(p) ); - assert( p->inTrans==TRANS_WRITE ); - - /* It is illegal to drop a table if any cursors are open on the - ** database. This is because in auto-vacuum mode the backend may - ** need to move another root-page to fill a gap left by the deleted - ** root page. If an open cursor was using this page a problem would - ** occur. - ** - ** This error is caught long before control reaches this point. - */ - if( NEVER(pBt->pCursor) ){ - sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db); - return SQLITE_LOCKED_SHAREDCACHE; - } - - rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0, 0); - if( rc ) return rc; - rc = sqlite3BtreeClearTable(p, iTable, 0); - if( rc ){ - releasePage(pPage); - return rc; - } - - *piMoved = 0; - - if( iTable>1 ){ -#ifdef SQLITE_OMIT_AUTOVACUUM - freePage(pPage, &rc); - releasePage(pPage); -#else - if( pBt->autoVacuum ){ - Pgno maxRootPgno; - sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno); - - if( iTable==maxRootPgno ){ - /* If the table being dropped is the table with the largest root-page - ** number in the database, put the root page on the free list. - */ - freePage(pPage, &rc); - releasePage(pPage); - if( rc!=SQLITE_OK ){ - return rc; - } - }else{ - /* The table being dropped does not have the largest root-page - ** number in the database. So move the page that does into the - ** gap left by the deleted root-page. - */ - MemPage *pMove; - releasePage(pPage); - rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0); - releasePage(pMove); - if( rc!=SQLITE_OK ){ - return rc; - } - pMove = 0; - rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0); - freePage(pMove, &rc); - releasePage(pMove); - if( rc!=SQLITE_OK ){ - return rc; - } - *piMoved = maxRootPgno; - } - - /* Set the new 'max-root-page' value in the database header. This - ** is the old value less one, less one more if that happens to - ** be a root-page number, less one again if that is the - ** PENDING_BYTE_PAGE. - */ - maxRootPgno--; - while( maxRootPgno==PENDING_BYTE_PAGE(pBt) - || PTRMAP_ISPAGE(pBt, maxRootPgno) ){ - maxRootPgno--; - } - assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); - - rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); - }else{ - freePage(pPage, &rc); - releasePage(pPage); - } -#endif - }else{ - /* If sqlite3BtreeDropTable was called on page 1. - ** This really never should happen except in a corrupt - ** database. - */ - zeroPage(pPage, PTF_INTKEY|PTF_LEAF ); - releasePage(pPage); - } - return rc; -} -SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ - int rc; - sqlite3BtreeEnter(p); - rc = btreeDropTable(p, iTable, piMoved); - sqlite3BtreeLeave(p); - return rc; -} - - -/* -** This function may only be called if the b-tree connection already -** has a read or write transaction open on the database. -** -** Read the meta-information out of a database file. Meta[0] -** is the number of free pages currently in the database. Meta[1] -** through meta[15] are available for use by higher layers. Meta[0] -** is read-only, the others are read/write. -** -** The schema layer numbers meta values differently. At the schema -** layer (and the SetCookie and ReadCookie opcodes) the number of -** free pages is not visible. So Cookie[0] is the same as Meta[1]. -*/ -SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ - BtShared *pBt = p->pBt; - - sqlite3BtreeEnter(p); - assert( p->inTrans>TRANS_NONE ); - assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); - assert( pBt->pPage1 ); - assert( idx>=0 && idx<=15 ); - - *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); - - /* If auto-vacuum is disabled in this build and this is an auto-vacuum - ** database, mark the database as read-only. */ -#ifdef SQLITE_OMIT_AUTOVACUUM - if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ - pBt->btsFlags |= BTS_READ_ONLY; - } -#endif - - sqlite3BtreeLeave(p); -} - -/* -** Write meta-information back into the database. Meta[0] is -** read-only and may not be written. -*/ -SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ - BtShared *pBt = p->pBt; - unsigned char *pP1; - int rc; - assert( idx>=1 && idx<=15 ); - sqlite3BtreeEnter(p); - assert( p->inTrans==TRANS_WRITE ); - assert( pBt->pPage1!=0 ); - pP1 = pBt->pPage1->aData; - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - if( rc==SQLITE_OK ){ - put4byte(&pP1[36 + idx*4], iMeta); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( idx==BTREE_INCR_VACUUM ){ - assert( pBt->autoVacuum || iMeta==0 ); - assert( iMeta==0 || iMeta==1 ); - pBt->incrVacuum = (u8)iMeta; - } -#endif - } - sqlite3BtreeLeave(p); - return rc; -} - -#ifndef SQLITE_OMIT_BTREECOUNT -/* -** The first argument, pCur, is a cursor opened on some b-tree. Count the -** number of entries in the b-tree and write the result to *pnEntry. -** -** SQLITE_OK is returned if the operation is successfully executed. -** Otherwise, if an error is encountered (i.e. an IO error or database -** corruption) an SQLite error code is returned. -*/ -SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ - i64 nEntry = 0; /* Value to return in *pnEntry */ - int rc; /* Return code */ - - if( pCur->pgnoRoot==0 ){ - *pnEntry = 0; - return SQLITE_OK; - } - rc = moveToRoot(pCur); - - /* Unless an error occurs, the following loop runs one iteration for each - ** page in the B-Tree structure (not including overflow pages). - */ - while( rc==SQLITE_OK ){ - int iIdx; /* Index of child node in parent */ - MemPage *pPage; /* Current page of the b-tree */ - - /* If this is a leaf page or the tree is not an int-key tree, then - ** this page contains countable entries. Increment the entry counter - ** accordingly. - */ - pPage = pCur->apPage[pCur->iPage]; - if( pPage->leaf || !pPage->intKey ){ - nEntry += pPage->nCell; - } - - /* pPage is a leaf node. This loop navigates the cursor so that it - ** points to the first interior cell that it points to the parent of - ** the next page in the tree that has not yet been visited. The - ** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell - ** of the page, or to the number of cells in the page if the next page - ** to visit is the right-child of its parent. - ** - ** If all pages in the tree have been visited, return SQLITE_OK to the - ** caller. - */ - if( pPage->leaf ){ - do { - if( pCur->iPage==0 ){ - /* All pages of the b-tree have been visited. Return successfully. */ - *pnEntry = nEntry; - return SQLITE_OK; - } - moveToParent(pCur); - }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); - - pCur->aiIdx[pCur->iPage]++; - pPage = pCur->apPage[pCur->iPage]; - } - - /* Descend to the child node of the cell that the cursor currently - ** points at. This is the right-child if (iIdx==pPage->nCell). - */ - iIdx = pCur->aiIdx[pCur->iPage]; - if( iIdx==pPage->nCell ){ - rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); - }else{ - rc = moveToChild(pCur, get4byte(findCell(pPage, iIdx))); - } - } - - /* An error has occurred. Return an error code. */ - return rc; -} -#endif - -/* -** Return the pager associated with a BTree. This routine is used for -** testing and debugging only. -*/ -SQLITE_PRIVATE Pager *sqlite3BtreePager(Btree *p){ - return p->pBt->pPager; -} - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* -** Append a message to the error message string. -*/ -static void checkAppendMsg( - IntegrityCk *pCheck, - char *zMsg1, - const char *zFormat, - ... -){ - va_list ap; - if( !pCheck->mxErr ) return; - pCheck->mxErr--; - pCheck->nErr++; - va_start(ap, zFormat); - if( pCheck->errMsg.nChar ){ - sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); - } - if( zMsg1 ){ - sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1); - } - sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap); - va_end(ap); - if( pCheck->errMsg.mallocFailed ){ - pCheck->mallocFailed = 1; - } -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK - -/* -** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that -** corresponds to page iPg is already set. -*/ -static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); - return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); -} - -/* -** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. -*/ -static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ - assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); - pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); -} - - -/* -** Add 1 to the reference count for page iPage. If this is the second -** reference to the page, add an error message to pCheck->zErrMsg. -** Return 1 if there are 2 ore more references to the page and 0 if -** if this is the first reference to the page. -** -** Also check that the page number is in bounds. -*/ -static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){ - if( iPage==0 ) return 1; - if( iPage>pCheck->nPage ){ - checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); - return 1; - } - if( getPageReferenced(pCheck, iPage) ){ - checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); - return 1; - } - setPageReferenced(pCheck, iPage); - return 0; -} - -#ifndef SQLITE_OMIT_AUTOVACUUM -/* -** Check that the entry in the pointer-map for page iChild maps to -** page iParent, pointer type ptrType. If not, append an error message -** to pCheck. -*/ -static void checkPtrmap( - IntegrityCk *pCheck, /* Integrity check context */ - Pgno iChild, /* Child page number */ - u8 eType, /* Expected pointer map type */ - Pgno iParent, /* Expected pointer map parent page number */ - char *zContext /* Context description (used for error msg) */ -){ - int rc; - u8 ePtrmapType; - Pgno iPtrmapParent; - - rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1; - checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild); - return; - } - - if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ - checkAppendMsg(pCheck, zContext, - "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", - iChild, eType, iParent, ePtrmapType, iPtrmapParent); - } -} -#endif - -/* -** Check the integrity of the freelist or of an overflow page list. -** Verify that the number of pages on the list is N. -*/ -static void checkList( - IntegrityCk *pCheck, /* Integrity checking context */ - int isFreeList, /* True for a freelist. False for overflow page list */ - int iPage, /* Page number for first page in the list */ - int N, /* Expected number of pages in the list */ - char *zContext /* Context for error messages */ -){ - int i; - int expected = N; - int iFirst = iPage; - while( N-- > 0 && pCheck->mxErr ){ - DbPage *pOvflPage; - unsigned char *pOvflData; - if( iPage<1 ){ - checkAppendMsg(pCheck, zContext, - "%d of %d pages missing from overflow list starting at %d", - N+1, expected, iFirst); - break; - } - if( checkRef(pCheck, iPage, zContext) ) break; - if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){ - checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage); - break; - } - pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); - if( isFreeList ){ - int n = get4byte(&pOvflData[4]); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pCheck->pBt->autoVacuum ){ - checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext); - } -#endif - if( n>(int)pCheck->pBt->usableSize/4-2 ){ - checkAppendMsg(pCheck, zContext, - "freelist leaf count too big on page %d", iPage); - N--; - }else{ - for(i=0; ipBt->autoVacuum ){ - checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext); - } -#endif - checkRef(pCheck, iFreePage, zContext); - } - N -= n; - } - } -#ifndef SQLITE_OMIT_AUTOVACUUM - else{ - /* If this database supports auto-vacuum and iPage is not the last - ** page in this overflow list, check that the pointer-map entry for - ** the following page matches iPage. - */ - if( pCheck->pBt->autoVacuum && N>0 ){ - i = get4byte(pOvflData); - checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext); - } - } -#endif - iPage = get4byte(pOvflData); - sqlite3PagerUnref(pOvflPage); - } -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* -** Do various sanity checks on a single page of a tree. Return -** the tree depth. Root pages return 0. Parents of root pages -** return 1, and so forth. -** -** These checks are done: -** -** 1. Make sure that cells and freeblocks do not overlap -** but combine to completely cover the page. -** NO 2. Make sure cell keys are in order. -** NO 3. Make sure no key is less than or equal to zLowerBound. -** NO 4. Make sure no key is greater than or equal to zUpperBound. -** 5. Check the integrity of overflow pages. -** 6. Recursively call checkTreePage on all children. -** 7. Verify that the depth of all children is the same. -** 8. Make sure this page is at least 33% full or else it is -** the root of the tree. -*/ -static int checkTreePage( - IntegrityCk *pCheck, /* Context for the sanity check */ - int iPage, /* Page number of the page to check */ - char *zParentContext, /* Parent context */ - i64 *pnParentMinKey, - i64 *pnParentMaxKey -){ - MemPage *pPage; - int i, rc, depth, d2, pgno, cnt; - int hdr, cellStart; - int nCell; - u8 *data; - BtShared *pBt; - int usableSize; - char zContext[100]; - char *hit = 0; - i64 nMinKey = 0; - i64 nMaxKey = 0; - - sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); - - /* Check that the page exists - */ - pBt = pCheck->pBt; - usableSize = pBt->usableSize; - if( iPage==0 ) return 0; - if( checkRef(pCheck, iPage, zParentContext) ) return 0; - if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0, 0))!=0 ){ - checkAppendMsg(pCheck, zContext, - "unable to get the page. error code=%d", rc); - return 0; - } - - /* Clear MemPage.isInit to make sure the corruption detection code in - ** btreeInitPage() is executed. */ - pPage->isInit = 0; - if( (rc = btreeInitPage(pPage))!=0 ){ - assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */ - checkAppendMsg(pCheck, zContext, - "btreeInitPage() returns error code %d", rc); - releasePage(pPage); - return 0; - } - - /* Check out all the cells. - */ - depth = 0; - for(i=0; inCell && pCheck->mxErr; i++){ - u8 *pCell; - u32 sz; - CellInfo info; - - /* Check payload overflow pages - */ - sqlite3_snprintf(sizeof(zContext), zContext, - "On tree page %d cell %d: ", iPage, i); - pCell = findCell(pPage,i); - btreeParseCellPtr(pPage, pCell, &info); - sz = info.nData; - if( !pPage->intKey ) sz += (int)info.nKey; - /* For intKey pages, check that the keys are in order. - */ - else if( i==0 ) nMinKey = nMaxKey = info.nKey; - else{ - if( info.nKey <= nMaxKey ){ - checkAppendMsg(pCheck, zContext, - "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey); - } - nMaxKey = info.nKey; - } - assert( sz==info.nPayload ); - if( (sz>info.nLocal) - && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize]) - ){ - int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); - Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext); - } -#endif - checkList(pCheck, 0, pgnoOvfl, nPage, zContext); - } - - /* Check sanity of left child page. - */ - if( !pPage->leaf ){ - pgno = get4byte(pCell); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); - } -#endif - d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey); - if( i>0 && d2!=depth ){ - checkAppendMsg(pCheck, zContext, "Child page depth differs"); - } - depth = d2; - } - } - - if( !pPage->leaf ){ - pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - sqlite3_snprintf(sizeof(zContext), zContext, - "On page %d at right child: ", iPage); -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); - } -#endif - checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey); - } - - /* For intKey leaf pages, check that the min/max keys are in order - ** with any left/parent/right pages. - */ - if( pPage->leaf && pPage->intKey ){ - /* if we are a left child page */ - if( pnParentMinKey ){ - /* if we are the left most child page */ - if( !pnParentMaxKey ){ - if( nMaxKey > *pnParentMinKey ){ - checkAppendMsg(pCheck, zContext, - "Rowid %lld out of order (max larger than parent min of %lld)", - nMaxKey, *pnParentMinKey); - } - }else{ - if( nMinKey <= *pnParentMinKey ){ - checkAppendMsg(pCheck, zContext, - "Rowid %lld out of order (min less than parent min of %lld)", - nMinKey, *pnParentMinKey); - } - if( nMaxKey > *pnParentMaxKey ){ - checkAppendMsg(pCheck, zContext, - "Rowid %lld out of order (max larger than parent max of %lld)", - nMaxKey, *pnParentMaxKey); - } - *pnParentMinKey = nMaxKey; - } - /* else if we're a right child page */ - } else if( pnParentMaxKey ){ - if( nMinKey <= *pnParentMaxKey ){ - checkAppendMsg(pCheck, zContext, - "Rowid %lld out of order (min less than parent max of %lld)", - nMinKey, *pnParentMaxKey); - } - } - } - - /* Check for complete coverage of the page - */ - data = pPage->aData; - hdr = pPage->hdrOffset; - hit = sqlite3PageMalloc( pBt->pageSize ); - if( hit==0 ){ - pCheck->mallocFailed = 1; - }else{ - int contentOffset = get2byteNotZero(&data[hdr+5]); - assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ - memset(hit+contentOffset, 0, usableSize-contentOffset); - memset(hit, 1, contentOffset); - nCell = get2byte(&data[hdr+3]); - cellStart = hdr + 12 - 4*pPage->leaf; - for(i=0; i=usableSize ){ - checkAppendMsg(pCheck, 0, - "Corruption detected in cell %d on page %d",i,iPage); - }else{ - for(j=pc+size-1; j>=pc; j--) hit[j]++; - } - } - i = get2byte(&data[hdr+1]); - while( i>0 ){ - int size, j; - assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */ - size = get2byte(&data[i+2]); - assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */ - for(j=i+size-1; j>=i; j--) hit[j]++; - j = get2byte(&data[i]); - assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */ - assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */ - i = j; - } - for(i=cnt=0; i1 ){ - checkAppendMsg(pCheck, 0, - "Multiple uses for byte %d of page %d", i, iPage); - break; - } - } - if( cnt!=data[hdr+7] ){ - checkAppendMsg(pCheck, 0, - "Fragmentation of %d bytes reported as %d on page %d", - cnt, data[hdr+7], iPage); - } - } - sqlite3PageFree(hit); - releasePage(pPage); - return depth+1; -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* -** This routine does a complete check of the given BTree file. aRoot[] is -** an array of pages numbers were each page number is the root page of -** a table. nRoot is the number of entries in aRoot. -** -** A read-only or read-write transaction must be opened before calling -** this function. -** -** Write the number of error seen in *pnErr. Except for some memory -** allocation errors, an error message held in memory obtained from -** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is -** returned. If a memory allocation error occurs, NULL is returned. -*/ -SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( - Btree *p, /* The btree to be checked */ - int *aRoot, /* An array of root pages numbers for individual trees */ - int nRoot, /* Number of entries in aRoot[] */ - int mxErr, /* Stop reporting errors after this many */ - int *pnErr /* Write number of errors seen to this variable */ -){ - Pgno i; - int nRef; - IntegrityCk sCheck; - BtShared *pBt = p->pBt; - char zErr[100]; - - sqlite3BtreeEnter(p); - assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); - nRef = sqlite3PagerRefcount(pBt->pPager); - sCheck.pBt = pBt; - sCheck.pPager = pBt->pPager; - sCheck.nPage = btreePagecount(sCheck.pBt); - sCheck.mxErr = mxErr; - sCheck.nErr = 0; - sCheck.mallocFailed = 0; - *pnErr = 0; - if( sCheck.nPage==0 ){ - sqlite3BtreeLeave(p); - return 0; - } - - sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); - if( !sCheck.aPgRef ){ - *pnErr = 1; - sqlite3BtreeLeave(p); - return 0; - } - i = PENDING_BYTE_PAGE(pBt); - if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); - sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); - sCheck.errMsg.useMalloc = 2; - - /* Check the integrity of the freelist - */ - checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), - get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); - - /* Check all the tables. - */ - for(i=0; (int)iautoVacuum && aRoot[i]>1 ){ - checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); - } -#endif - checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL); - } - - /* Make sure every page in the file is referenced - */ - for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ -#ifdef SQLITE_OMIT_AUTOVACUUM - if( getPageReferenced(&sCheck, i)==0 ){ - checkAppendMsg(&sCheck, 0, "Page %d is never used", i); - } -#else - /* If the database supports auto-vacuum, make sure no tables contain - ** references to pointer-map pages. - */ - if( getPageReferenced(&sCheck, i)==0 && - (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, 0, "Page %d is never used", i); - } - if( getPageReferenced(&sCheck, i)!=0 && - (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ - checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); - } -#endif - } - - /* Make sure this analysis did not leave any unref() pages. - ** This is an internal consistency check; an integrity check - ** of the integrity check. - */ - if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){ - checkAppendMsg(&sCheck, 0, - "Outstanding page count goes from %d to %d during this analysis", - nRef, sqlite3PagerRefcount(pBt->pPager) - ); - } - - /* Clean up and report errors. - */ - sqlite3BtreeLeave(p); - sqlite3_free(sCheck.aPgRef); - if( sCheck.mallocFailed ){ - sqlite3StrAccumReset(&sCheck.errMsg); - *pnErr = sCheck.nErr+1; - return 0; - } - *pnErr = sCheck.nErr; - if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); - return sqlite3StrAccumFinish(&sCheck.errMsg); -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -/* -** Return the full pathname of the underlying database file. Return -** an empty string if the database is in-memory or a TEMP database. -** -** The pager filename is invariant as long as the pager is -** open so it is safe to access without the BtShared mutex. -*/ -SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *p){ - assert( p->pBt->pPager!=0 ); - return sqlite3PagerFilename(p->pBt->pPager, 1); -} - -/* -** Return the pathname of the journal file for this database. The return -** value of this routine is the same regardless of whether the journal file -** has been created or not. -** -** The pager journal filename is invariant as long as the pager is -** open so it is safe to access without the BtShared mutex. -*/ -SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *p){ - assert( p->pBt->pPager!=0 ); - return sqlite3PagerJournalname(p->pBt->pPager); -} - -/* -** Return non-zero if a transaction is active. -*/ -SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree *p){ - assert( p==0 || sqlite3_mutex_held(p->db->mutex) ); - return (p && (p->inTrans==TRANS_WRITE)); -} - -#ifndef SQLITE_OMIT_WAL -/* -** Run a checkpoint on the Btree passed as the first argument. -** -** Return SQLITE_LOCKED if this or any other connection has an open -** transaction on the shared-cache the argument Btree is connected to. -** -** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. -*/ -SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){ - int rc = SQLITE_OK; - if( p ){ - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); - if( pBt->inTransaction!=TRANS_NONE ){ - rc = SQLITE_LOCKED; - }else{ - rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); - } - sqlite3BtreeLeave(p); - } - return rc; -} -#endif - -/* -** Return non-zero if a read (or write) transaction is active. -*/ -SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree *p){ - assert( p ); - assert( sqlite3_mutex_held(p->db->mutex) ); - return p->inTrans!=TRANS_NONE; -} - -SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){ - assert( p ); - assert( sqlite3_mutex_held(p->db->mutex) ); - return p->nBackup!=0; -} - -/* -** This function returns a pointer to a blob of memory associated with -** a single shared-btree. The memory is used by client code for its own -** purposes (for example, to store a high-level schema associated with -** the shared-btree). The btree layer manages reference counting issues. -** -** The first time this is called on a shared-btree, nBytes bytes of memory -** are allocated, zeroed, and returned to the caller. For each subsequent -** call the nBytes parameter is ignored and a pointer to the same blob -** of memory returned. -** -** If the nBytes parameter is 0 and the blob of memory has not yet been -** allocated, a null pointer is returned. If the blob has already been -** allocated, it is returned as normal. -** -** Just before the shared-btree is closed, the function passed as the -** xFree argument when the memory allocation was made is invoked on the -** blob of allocated memory. The xFree function should not call sqlite3_free() -** on the memory, the btree layer does that. -*/ -SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ - BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); - if( !pBt->pSchema && nBytes ){ - pBt->pSchema = sqlite3DbMallocZero(0, nBytes); - pBt->xFreeSchema = xFree; - } - sqlite3BtreeLeave(p); - return pBt->pSchema; -} - -/* -** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared -** btree as the argument handle holds an exclusive lock on the -** sqlite_master table. Otherwise SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){ - int rc; - assert( sqlite3_mutex_held(p->db->mutex) ); - sqlite3BtreeEnter(p); - rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); - assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE ); - sqlite3BtreeLeave(p); - return rc; -} - - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** Obtain a lock on the table whose root page is iTab. The -** lock is a write lock if isWritelock is true or a read lock -** if it is false. -*/ -SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ - int rc = SQLITE_OK; - assert( p->inTrans!=TRANS_NONE ); - if( p->sharable ){ - u8 lockType = READ_LOCK + isWriteLock; - assert( READ_LOCK+1==WRITE_LOCK ); - assert( isWriteLock==0 || isWriteLock==1 ); - - sqlite3BtreeEnter(p); - rc = querySharedCacheTableLock(p, iTab, lockType); - if( rc==SQLITE_OK ){ - rc = setSharedCacheTableLock(p, iTab, lockType); - } - sqlite3BtreeLeave(p); - } - return rc; -} -#endif - -#ifndef SQLITE_OMIT_INCRBLOB -/* -** Argument pCsr must be a cursor opened for writing on an -** INTKEY table currently pointing at a valid table entry. -** This function modifies the data stored as part of that entry. -** -** Only the data content may only be modified, it is not possible to -** change the length of the data stored. If this function is called with -** parameters that attempt to write past the end of the existing data, -** no modifications are made and SQLITE_CORRUPT is returned. -*/ -SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ - int rc; - assert( cursorHoldsMutex(pCsr) ); - assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); - assert( pCsr->isIncrblobHandle ); - - rc = restoreCursorPosition(pCsr); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pCsr->eState!=CURSOR_REQUIRESEEK ); - if( pCsr->eState!=CURSOR_VALID ){ - return SQLITE_ABORT; - } - - /* Save the positions of all other cursors open on this table. This is - ** required in case any of them are holding references to an xFetch - ** version of the b-tree page modified by the accessPayload call below. - ** - ** Note that pCsr must be open on a BTREE_INTKEY table and saveCursorPosition() - ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence - ** saveAllCursors can only return SQLITE_OK. - */ - VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr); - assert( rc==SQLITE_OK ); - - /* Check some assumptions: - ** (a) the cursor is open for writing, - ** (b) there is a read/write transaction open, - ** (c) the connection holds a write-lock on the table (if required), - ** (d) there are no conflicting read-locks, and - ** (e) the cursor points at a valid row of an intKey table. - */ - if( !pCsr->wrFlag ){ - return SQLITE_READONLY; - } - assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0 - && pCsr->pBt->inTransaction==TRANS_WRITE ); - assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) ); - assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) ); - assert( pCsr->apPage[pCsr->iPage]->intKey ); - - return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1); -} - -/* -** Set a flag on this cursor to cache the locations of pages from the -** overflow list for the current row. This is used by cursors opened -** for incremental blob IO only. -** -** This function sets a flag only. The actual page location cache -** (stored in BtCursor.aOverflow[]) is allocated and used by function -** accessPayload() (the worker function for sqlite3BtreeData() and -** sqlite3BtreePutData()). -*/ -SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - invalidateOverflowCache(pCur); - pCur->isIncrblobHandle = 1; -} -#endif - -/* -** Set both the "read version" (single byte at byte offset 18) and -** "write version" (single byte at byte offset 19) fields in the database -** header to iVersion. -*/ -SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ - BtShared *pBt = pBtree->pBt; - int rc; /* Return code */ - - assert( iVersion==1 || iVersion==2 ); - - /* If setting the version fields to 1, do not automatically open the - ** WAL connection, even if the version fields are currently set to 2. - */ - pBt->btsFlags &= ~BTS_NO_WAL; - if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL; - - rc = sqlite3BtreeBeginTrans(pBtree, 0); - if( rc==SQLITE_OK ){ - u8 *aData = pBt->pPage1->aData; - if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ - rc = sqlite3BtreeBeginTrans(pBtree, 2); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - if( rc==SQLITE_OK ){ - aData[18] = (u8)iVersion; - aData[19] = (u8)iVersion; - } - } - } - } - - pBt->btsFlags &= ~BTS_NO_WAL; - return rc; -} - -/* -** set the mask of hint flags for cursor pCsr. Currently the only valid -** values are 0 and BTREE_BULKLOAD. -*/ -SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ - assert( mask==BTREE_BULKLOAD || mask==0 ); - pCsr->hints = mask; -} - -/************** End of btree.c ***********************************************/ -/************** Begin file backup.c ******************************************/ -/* -** 2009 January 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the implementation of the sqlite3_backup_XXX() -** API functions and the related features. -*/ - -/* Macro to find the minimum of two numeric values. -*/ -#ifndef MIN -# define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -/* -** Structure allocated for each backup operation. -*/ -struct sqlite3_backup { - sqlite3* pDestDb; /* Destination database handle */ - Btree *pDest; /* Destination b-tree file */ - u32 iDestSchema; /* Original schema cookie in destination */ - int bDestLocked; /* True once a write-transaction is open on pDest */ - - Pgno iNext; /* Page number of the next source page to copy */ - sqlite3* pSrcDb; /* Source database handle */ - Btree *pSrc; /* Source b-tree file */ - - int rc; /* Backup process error code */ - - /* These two variables are set by every call to backup_step(). They are - ** read by calls to backup_remaining() and backup_pagecount(). - */ - Pgno nRemaining; /* Number of pages left to copy */ - Pgno nPagecount; /* Total number of pages to copy */ - - int isAttached; /* True once backup has been registered with pager */ - sqlite3_backup *pNext; /* Next backup associated with source pager */ -}; - -/* -** THREAD SAFETY NOTES: -** -** Once it has been created using backup_init(), a single sqlite3_backup -** structure may be accessed via two groups of thread-safe entry points: -** -** * Via the sqlite3_backup_XXX() API function backup_step() and -** backup_finish(). Both these functions obtain the source database -** handle mutex and the mutex associated with the source BtShared -** structure, in that order. -** -** * Via the BackupUpdate() and BackupRestart() functions, which are -** invoked by the pager layer to report various state changes in -** the page cache associated with the source database. The mutex -** associated with the source database BtShared structure will always -** be held when either of these functions are invoked. -** -** The other sqlite3_backup_XXX() API functions, backup_remaining() and -** backup_pagecount() are not thread-safe functions. If they are called -** while some other thread is calling backup_step() or backup_finish(), -** the values returned may be invalid. There is no way for a call to -** BackupUpdate() or BackupRestart() to interfere with backup_remaining() -** or backup_pagecount(). -** -** Depending on the SQLite configuration, the database handles and/or -** the Btree objects may have their own mutexes that require locking. -** Non-sharable Btrees (in-memory databases for example), do not have -** associated mutexes. -*/ - -/* -** Return a pointer corresponding to database zDb (i.e. "main", "temp") -** in connection handle pDb. If such a database cannot be found, return -** a NULL pointer and write an error message to pErrorDb. -** -** If the "temp" database is requested, it may need to be opened by this -** function. If an error occurs while doing so, return 0 and write an -** error message to pErrorDb. -*/ -static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ - int i = sqlite3FindDbName(pDb, zDb); - - if( i==1 ){ - Parse *pParse; - int rc = 0; - pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); - if( pParse==0 ){ - sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); - rc = SQLITE_NOMEM; - }else{ - pParse->db = pDb; - if( sqlite3OpenTempDatabase(pParse) ){ - sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); - rc = SQLITE_ERROR; - } - sqlite3DbFree(pErrorDb, pParse->zErrMsg); - sqlite3StackFree(pErrorDb, pParse); - } - if( rc ){ - return 0; - } - } - - if( i<0 ){ - sqlite3Error(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); - return 0; - } - - return pDb->aDb[i].pBt; -} - -/* -** Attempt to set the page size of the destination to match the page size -** of the source. -*/ -static int setDestPgsz(sqlite3_backup *p){ - int rc; - rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); - return rc; -} - -/* -** Create an sqlite3_backup process to copy the contents of zSrcDb from -** connection handle pSrcDb to zDestDb in pDestDb. If successful, return -** a pointer to the new sqlite3_backup object. -** -** If an error occurs, NULL is returned and an error code and error message -** stored in database handle pDestDb. -*/ -SQLITE_API sqlite3_backup *sqlite3_backup_init( - sqlite3* pDestDb, /* Database to write to */ - const char *zDestDb, /* Name of database within pDestDb */ - sqlite3* pSrcDb, /* Database connection to read from */ - const char *zSrcDb /* Name of database within pSrcDb */ -){ - sqlite3_backup *p; /* Value to return */ - - /* Lock the source database handle. The destination database - ** handle is not locked in this routine, but it is locked in - ** sqlite3_backup_step(). The user is required to ensure that no - ** other thread accesses the destination handle for the duration - ** of the backup operation. Any attempt to use the destination - ** database connection while a backup is in progress may cause - ** a malfunction or a deadlock. - */ - sqlite3_mutex_enter(pSrcDb->mutex); - sqlite3_mutex_enter(pDestDb->mutex); - - if( pSrcDb==pDestDb ){ - sqlite3Error( - pDestDb, SQLITE_ERROR, "source and destination must be distinct" - ); - p = 0; - }else { - /* Allocate space for a new sqlite3_backup object... - ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a - ** call to sqlite3_backup_init() and is destroyed by a call to - ** sqlite3_backup_finish(). */ - p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); - if( !p ){ - sqlite3Error(pDestDb, SQLITE_NOMEM, 0); - } - } - - /* If the allocation succeeded, populate the new object. */ - if( p ){ - p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); - p->pDest = findBtree(pDestDb, pDestDb, zDestDb); - p->pDestDb = pDestDb; - p->pSrcDb = pSrcDb; - p->iNext = 1; - p->isAttached = 0; - - if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM ){ - /* One (or both) of the named databases did not exist or an OOM - ** error was hit. The error has already been written into the - ** pDestDb handle. All that is left to do here is free the - ** sqlite3_backup structure. - */ - sqlite3_free(p); - p = 0; - } - } - if( p ){ - p->pSrc->nBackup++; - } - - sqlite3_mutex_leave(pDestDb->mutex); - sqlite3_mutex_leave(pSrcDb->mutex); - return p; -} - -/* -** Argument rc is an SQLite error code. Return true if this error is -** considered fatal if encountered during a backup operation. All errors -** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED. -*/ -static int isFatalError(int rc){ - return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED)); -} - -/* -** Parameter zSrcData points to a buffer containing the data for -** page iSrcPg from the source database. Copy this data into the -** destination database. -*/ -static int backupOnePage( - sqlite3_backup *p, /* Backup handle */ - Pgno iSrcPg, /* Source database page to backup */ - const u8 *zSrcData, /* Source database page data */ - int bUpdate /* True for an update, false otherwise */ -){ - Pager * const pDestPager = sqlite3BtreePager(p->pDest); - const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); - int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); - const int nCopy = MIN(nSrcPgsz, nDestPgsz); - const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; -#ifdef SQLITE_HAS_CODEC - /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is - ** guaranteed that the shared-mutex is held by this thread, handle - ** p->pSrc may not actually be the owner. */ - int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); - int nDestReserve = sqlite3BtreeGetReserve(p->pDest); -#endif - int rc = SQLITE_OK; - i64 iOff; - - assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); - assert( p->bDestLocked ); - assert( !isFatalError(p->rc) ); - assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); - assert( zSrcData ); - - /* Catch the case where the destination is an in-memory database and the - ** page sizes of the source and destination differ. - */ - if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){ - rc = SQLITE_READONLY; - } - -#ifdef SQLITE_HAS_CODEC - /* Backup is not possible if the page size of the destination is changing - ** and a codec is in use. - */ - if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){ - rc = SQLITE_READONLY; - } - - /* Backup is not possible if the number of bytes of reserve space differ - ** between source and destination. If there is a difference, try to - ** fix the destination to agree with the source. If that is not possible, - ** then the backup cannot proceed. - */ - if( nSrcReserve!=nDestReserve ){ - u32 newPgsz = nSrcPgsz; - rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve); - if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY; - } -#endif - - /* This loop runs once for each destination page spanned by the source - ** page. For each iteration, variable iOff is set to the byte offset - ** of the destination page. - */ - for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOffpDest->pBt) ) continue; - if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg)) - && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg)) - ){ - const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; - u8 *zDestData = sqlite3PagerGetData(pDestPg); - u8 *zOut = &zDestData[iOff%nDestPgsz]; - - /* Copy the data from the source page into the destination page. - ** Then clear the Btree layer MemPage.isInit flag. Both this module - ** and the pager code use this trick (clearing the first byte - ** of the page 'extra' space to invalidate the Btree layers - ** cached parse of the page). MemPage.isInit is marked - ** "MUST BE FIRST" for this purpose. - */ - memcpy(zOut, zIn, nCopy); - ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; - if( iOff==0 && bUpdate==0 ){ - sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); - } - } - sqlite3PagerUnref(pDestPg); - } - - return rc; -} - -/* -** If pFile is currently larger than iSize bytes, then truncate it to -** exactly iSize bytes. If pFile is not larger than iSize bytes, then -** this function is a no-op. -** -** Return SQLITE_OK if everything is successful, or an SQLite error -** code if an error occurs. -*/ -static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){ - i64 iCurrent; - int rc = sqlite3OsFileSize(pFile, &iCurrent); - if( rc==SQLITE_OK && iCurrent>iSize ){ - rc = sqlite3OsTruncate(pFile, iSize); - } - return rc; -} - -/* -** Register this backup object with the associated source pager for -** callbacks when pages are changed or the cache invalidated. -*/ -static void attachBackupObject(sqlite3_backup *p){ - sqlite3_backup **pp; - assert( sqlite3BtreeHoldsMutex(p->pSrc) ); - pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); - p->pNext = *pp; - *pp = p; - p->isAttached = 1; -} - -/* -** Copy nPage pages from the source b-tree to the destination. -*/ -SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ - int rc; - int destMode; /* Destination journal mode */ - int pgszSrc = 0; /* Source page size */ - int pgszDest = 0; /* Destination page size */ - - sqlite3_mutex_enter(p->pSrcDb->mutex); - sqlite3BtreeEnter(p->pSrc); - if( p->pDestDb ){ - sqlite3_mutex_enter(p->pDestDb->mutex); - } - - rc = p->rc; - if( !isFatalError(rc) ){ - Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */ - Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */ - int ii; /* Iterator variable */ - int nSrcPage = -1; /* Size of source db in pages */ - int bCloseTrans = 0; /* True if src db requires unlocking */ - - /* If the source pager is currently in a write-transaction, return - ** SQLITE_BUSY immediately. - */ - if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){ - rc = SQLITE_BUSY; - }else{ - rc = SQLITE_OK; - } - - /* Lock the destination database, if it is not locked already. */ - if( SQLITE_OK==rc && p->bDestLocked==0 - && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) - ){ - p->bDestLocked = 1; - sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); - } - - /* If there is no open read-transaction on the source database, open - ** one now. If a transaction is opened here, then it will be closed - ** before this function exits. - */ - if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){ - rc = sqlite3BtreeBeginTrans(p->pSrc, 0); - bCloseTrans = 1; - } - - /* Do not allow backup if the destination database is in WAL mode - ** and the page sizes are different between source and destination */ - pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); - pgszDest = sqlite3BtreeGetPageSize(p->pDest); - destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); - if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){ - rc = SQLITE_READONLY; - } - - /* Now that there is a read-lock on the source database, query the - ** source pager for the number of pages in the database. - */ - nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); - assert( nSrcPage>=0 ); - for(ii=0; (nPage<0 || iiiNext<=(Pgno)nSrcPage && !rc; ii++){ - const Pgno iSrcPg = p->iNext; /* Source page number */ - if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ - DbPage *pSrcPg; /* Source page object */ - rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg, - PAGER_ACQUIRE_READONLY); - if( rc==SQLITE_OK ){ - rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); - sqlite3PagerUnref(pSrcPg); - } - } - p->iNext++; - } - if( rc==SQLITE_OK ){ - p->nPagecount = nSrcPage; - p->nRemaining = nSrcPage+1-p->iNext; - if( p->iNext>(Pgno)nSrcPage ){ - rc = SQLITE_DONE; - }else if( !p->isAttached ){ - attachBackupObject(p); - } - } - - /* Update the schema version field in the destination database. This - ** is to make sure that the schema-version really does change in - ** the case where the source and destination databases have the - ** same schema version. - */ - if( rc==SQLITE_DONE ){ - if( nSrcPage==0 ){ - rc = sqlite3BtreeNewDb(p->pDest); - nSrcPage = 1; - } - if( rc==SQLITE_OK || rc==SQLITE_DONE ){ - rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); - } - if( rc==SQLITE_OK ){ - if( p->pDestDb ){ - sqlite3ResetAllSchemasOfConnection(p->pDestDb); - } - if( destMode==PAGER_JOURNALMODE_WAL ){ - rc = sqlite3BtreeSetVersion(p->pDest, 2); - } - } - if( rc==SQLITE_OK ){ - int nDestTruncate; - /* Set nDestTruncate to the final number of pages in the destination - ** database. The complication here is that the destination page - ** size may be different to the source page size. - ** - ** If the source page size is smaller than the destination page size, - ** round up. In this case the call to sqlite3OsTruncate() below will - ** fix the size of the file. However it is important to call - ** sqlite3PagerTruncateImage() here so that any pages in the - ** destination file that lie beyond the nDestTruncate page mark are - ** journalled by PagerCommitPhaseOne() before they are destroyed - ** by the file truncation. - */ - assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); - assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); - if( pgszSrcpDest->pBt) ){ - nDestTruncate--; - } - }else{ - nDestTruncate = nSrcPage * (pgszSrc/pgszDest); - } - assert( nDestTruncate>0 ); - - if( pgszSrc= iSize || ( - nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) - && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest - )); - - /* This block ensures that all data required to recreate the original - ** database has been stored in the journal for pDestPager and the - ** journal synced to disk. So at this point we may safely modify - ** the database file in any way, knowing that if a power failure - ** occurs, the original database will be reconstructed from the - ** journal file. */ - sqlite3PagerPagecount(pDestPager, &nDstPage); - for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ - if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ - DbPage *pPg; - rc = sqlite3PagerGet(pDestPager, iPg, &pPg); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pPg); - sqlite3PagerUnref(pPg); - } - } - } - if( rc==SQLITE_OK ){ - rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); - } - - /* Write the extra pages and truncate the database file as required */ - iEnd = MIN(PENDING_BYTE + pgszDest, iSize); - for( - iOff=PENDING_BYTE+pgszSrc; - rc==SQLITE_OK && iOffpDest, 0)) - ){ - rc = SQLITE_DONE; - } - } - } - - /* If bCloseTrans is true, then this function opened a read transaction - ** on the source database. Close the read transaction here. There is - ** no need to check the return values of the btree methods here, as - ** "committing" a read-only transaction cannot fail. - */ - if( bCloseTrans ){ - TESTONLY( int rc2 ); - TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); - TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); - assert( rc2==SQLITE_OK ); - } - - if( rc==SQLITE_IOERR_NOMEM ){ - rc = SQLITE_NOMEM; - } - p->rc = rc; - } - if( p->pDestDb ){ - sqlite3_mutex_leave(p->pDestDb->mutex); - } - sqlite3BtreeLeave(p->pSrc); - sqlite3_mutex_leave(p->pSrcDb->mutex); - return rc; -} - -/* -** Release all resources associated with an sqlite3_backup* handle. -*/ -SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ - sqlite3_backup **pp; /* Ptr to head of pagers backup list */ - sqlite3 *pSrcDb; /* Source database connection */ - int rc; /* Value to return */ - - /* Enter the mutexes */ - if( p==0 ) return SQLITE_OK; - pSrcDb = p->pSrcDb; - sqlite3_mutex_enter(pSrcDb->mutex); - sqlite3BtreeEnter(p->pSrc); - if( p->pDestDb ){ - sqlite3_mutex_enter(p->pDestDb->mutex); - } - - /* Detach this backup from the source pager. */ - if( p->pDestDb ){ - p->pSrc->nBackup--; - } - if( p->isAttached ){ - pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); - while( *pp!=p ){ - pp = &(*pp)->pNext; - } - *pp = p->pNext; - } - - /* If a transaction is still open on the Btree, roll it back. */ - sqlite3BtreeRollback(p->pDest, SQLITE_OK); - - /* Set the error code of the destination database handle. */ - rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; - sqlite3Error(p->pDestDb, rc, 0); - - /* Exit the mutexes and free the backup context structure. */ - if( p->pDestDb ){ - sqlite3LeaveMutexAndCloseZombie(p->pDestDb); - } - sqlite3BtreeLeave(p->pSrc); - if( p->pDestDb ){ - /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a - ** call to sqlite3_backup_init() and is destroyed by a call to - ** sqlite3_backup_finish(). */ - sqlite3_free(p); - } - sqlite3LeaveMutexAndCloseZombie(pSrcDb); - return rc; -} - -/* -** Return the number of pages still to be backed up as of the most recent -** call to sqlite3_backup_step(). -*/ -SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){ - return p->nRemaining; -} - -/* -** Return the total number of pages in the source database as of the most -** recent call to sqlite3_backup_step(). -*/ -SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){ - return p->nPagecount; -} - -/* -** This function is called after the contents of page iPage of the -** source database have been modified. If page iPage has already been -** copied into the destination database, then the data written to the -** destination is now invalidated. The destination copy of iPage needs -** to be updated with the new data before the backup operation is -** complete. -** -** It is assumed that the mutex associated with the BtShared object -** corresponding to the source database is held when this function is -** called. -*/ -SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ - sqlite3_backup *p; /* Iterator variable */ - for(p=pBackup; p; p=p->pNext){ - assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); - if( !isFatalError(p->rc) && iPageiNext ){ - /* The backup process p has already copied page iPage. But now it - ** has been modified by a transaction on the source pager. Copy - ** the new data into the backup. - */ - int rc; - assert( p->pDestDb ); - sqlite3_mutex_enter(p->pDestDb->mutex); - rc = backupOnePage(p, iPage, aData, 1); - sqlite3_mutex_leave(p->pDestDb->mutex); - assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); - if( rc!=SQLITE_OK ){ - p->rc = rc; - } - } - } -} - -/* -** Restart the backup process. This is called when the pager layer -** detects that the database has been modified by an external database -** connection. In this case there is no way of knowing which of the -** pages that have been copied into the destination database are still -** valid and which are not, so the entire process needs to be restarted. -** -** It is assumed that the mutex associated with the BtShared object -** corresponding to the source database is held when this function is -** called. -*/ -SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *pBackup){ - sqlite3_backup *p; /* Iterator variable */ - for(p=pBackup; p; p=p->pNext){ - assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); - p->iNext = 1; - } -} - -#ifndef SQLITE_OMIT_VACUUM -/* -** Copy the complete content of pBtFrom into pBtTo. A transaction -** must be active for both files. -** -** The size of file pTo may be reduced by this operation. If anything -** goes wrong, the transaction on pTo is rolled back. If successful, the -** transaction is committed before returning. -*/ -SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ - int rc; - sqlite3_file *pFd; /* File descriptor for database pTo */ - sqlite3_backup b; - sqlite3BtreeEnter(pTo); - sqlite3BtreeEnter(pFrom); - - assert( sqlite3BtreeIsInTrans(pTo) ); - pFd = sqlite3PagerFile(sqlite3BtreePager(pTo)); - if( pFd->pMethods ){ - i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom); - rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte); - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; - if( rc ) goto copy_finished; - } - - /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set - ** to 0. This is used by the implementations of sqlite3_backup_step() - ** and sqlite3_backup_finish() to detect that they are being called - ** from this function, not directly by the user. - */ - memset(&b, 0, sizeof(b)); - b.pSrcDb = pFrom->db; - b.pSrc = pFrom; - b.pDest = pTo; - b.iNext = 1; - - /* 0x7FFFFFFF is the hard limit for the number of pages in a database - ** file. By passing this as the number of pages to copy to - ** sqlite3_backup_step(), we can guarantee that the copy finishes - ** within a single call (unless an error occurs). The assert() statement - ** checks this assumption - (p->rc) should be set to either SQLITE_DONE - ** or an error code. - */ - sqlite3_backup_step(&b, 0x7FFFFFFF); - assert( b.rc!=SQLITE_OK ); - rc = sqlite3_backup_finish(&b); - if( rc==SQLITE_OK ){ - pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; - }else{ - sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); - } - - assert( sqlite3BtreeIsInTrans(pTo)==0 ); -copy_finished: - sqlite3BtreeLeave(pFrom); - sqlite3BtreeLeave(pTo); - return rc; -} -#endif /* SQLITE_OMIT_VACUUM */ - -/************** End of backup.c **********************************************/ -/************** Begin file vdbemem.c *****************************************/ -/* -** 2004 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code use to manipulate "Mem" structure. A "Mem" -** stores a single value in the VDBE. Mem is an opaque structure visible -** only within the VDBE. Interface routines refer to a Mem using the -** name sqlite_value -*/ - -/* -** If pMem is an object with a valid string representation, this routine -** ensures the internal encoding for the string representation is -** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE. -** -** If pMem is not a string object, or the encoding of the string -** representation is already stored using the requested encoding, then this -** routine is a no-op. -** -** SQLITE_OK is returned if the conversion is successful (or not required). -** SQLITE_NOMEM may be returned if a malloc() fails during conversion -** between formats. -*/ -SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ -#ifndef SQLITE_OMIT_UTF16 - int rc; -#endif - assert( (pMem->flags&MEM_RowSet)==0 ); - assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE - || desiredEnc==SQLITE_UTF16BE ); - if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ - return SQLITE_OK; - } - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); -#ifdef SQLITE_OMIT_UTF16 - return SQLITE_ERROR; -#else - - /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, - ** then the encoding of the value may not have changed. - */ - rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc); - assert(rc==SQLITE_OK || rc==SQLITE_NOMEM); - assert(rc==SQLITE_OK || pMem->enc!=desiredEnc); - assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc); - return rc; -#endif -} - -/* -** Make sure pMem->z points to a writable allocation of at least -** n bytes. -** -** If the third argument passed to this function is true, then memory -** cell pMem must contain a string or blob. In this case the content is -** preserved. Otherwise, if the third parameter to this function is false, -** any current string or blob value may be discarded. -** -** This function sets the MEM_Dyn flag and clears any xDel callback. -** It also clears MEM_Ephem and MEM_Static. If the preserve flag is -** not set, Mem.n is zeroed. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ - assert( 1 >= - ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) + - (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + - ((pMem->flags&MEM_Ephem) ? 1 : 0) + - ((pMem->flags&MEM_Static) ? 1 : 0) - ); - assert( (pMem->flags&MEM_RowSet)==0 ); - - /* If the preserve flag is set to true, then the memory cell must already - ** contain a valid string or blob value. */ - assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); - - if( n<32 ) n = 32; - if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)z==pMem->zMalloc ){ - pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); - preserve = 0; - }else{ - sqlite3DbFree(pMem->db, pMem->zMalloc); - pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); - } - } - - if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){ - memcpy(pMem->zMalloc, pMem->z, pMem->n); - } - if( pMem->flags&MEM_Dyn && pMem->xDel ){ - assert( pMem->xDel!=SQLITE_DYNAMIC ); - pMem->xDel((void *)(pMem->z)); - } - - pMem->z = pMem->zMalloc; - if( pMem->z==0 ){ - pMem->flags = MEM_Null; - }else{ - pMem->flags &= ~(MEM_Ephem|MEM_Static); - } - pMem->xDel = 0; - return (pMem->z ? SQLITE_OK : SQLITE_NOMEM); -} - -/* -** Make the given Mem object MEM_Dyn. In other words, make it so -** that any TEXT or BLOB content is stored in memory obtained from -** malloc(). In this way, we know that the memory is safe to be -** overwritten or altered. -** -** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ - int f; - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( (pMem->flags&MEM_RowSet)==0 ); - ExpandBlob(pMem); - f = pMem->flags; - if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){ - if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ - return SQLITE_NOMEM; - } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n+1] = 0; - pMem->flags |= MEM_Term; -#ifdef SQLITE_DEBUG - pMem->pScopyFrom = 0; -#endif - } - - return SQLITE_OK; -} - -/* -** If the given Mem* has a zero-filled tail, turn it into an ordinary -** blob stored in dynamically allocated space. -*/ -#ifndef SQLITE_OMIT_INCRBLOB -SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ - if( pMem->flags & MEM_Zero ){ - int nByte; - assert( pMem->flags&MEM_Blob ); - assert( (pMem->flags&MEM_RowSet)==0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - - /* Set nByte to the number of bytes required to store the expanded blob. */ - nByte = pMem->n + pMem->u.nZero; - if( nByte<=0 ){ - nByte = 1; - } - if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ - return SQLITE_NOMEM; - } - - memset(&pMem->z[pMem->n], 0, pMem->u.nZero); - pMem->n += pMem->u.nZero; - pMem->flags &= ~(MEM_Zero|MEM_Term); - } - return SQLITE_OK; -} -#endif - - -/* -** Make sure the given Mem is \u0000 terminated. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){ - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){ - return SQLITE_OK; /* Nothing to do */ - } - if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ - return SQLITE_NOMEM; - } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n+1] = 0; - pMem->flags |= MEM_Term; - return SQLITE_OK; -} - -/* -** Add MEM_Str to the set of representations for the given Mem. Numbers -** are converted using sqlite3_snprintf(). Converting a BLOB to a string -** is a no-op. -** -** Existing representations MEM_Int and MEM_Real are *not* invalidated. -** -** A MEM_Null value will never be passed to this function. This function is -** used for converting values to text for returning to the user (i.e. via -** sqlite3_value_text()), or for ensuring that values to be used as btree -** keys are strings. In the former case a NULL pointer is returned the -** user and the later is an internal programming error. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, int enc){ - int rc = SQLITE_OK; - int fg = pMem->flags; - const int nByte = 32; - - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( !(fg&MEM_Zero) ); - assert( !(fg&(MEM_Str|MEM_Blob)) ); - assert( fg&(MEM_Int|MEM_Real) ); - assert( (pMem->flags&MEM_RowSet)==0 ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - - - if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){ - return SQLITE_NOMEM; - } - - /* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8 - ** string representation of the value. Then, if the required encoding - ** is UTF-16le or UTF-16be do a translation. - ** - ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. - */ - if( fg & MEM_Int ){ - sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i); - }else{ - assert( fg & MEM_Real ); - sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r); - } - pMem->n = sqlite3Strlen30(pMem->z); - pMem->enc = SQLITE_UTF8; - pMem->flags |= MEM_Str|MEM_Term; - sqlite3VdbeChangeEncoding(pMem, enc); - return rc; -} - -/* -** Memory cell pMem contains the context of an aggregate function. -** This routine calls the finalize method for that function. The -** result of the aggregate is stored back into pMem. -** -** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK -** otherwise. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ - int rc = SQLITE_OK; - if( ALWAYS(pFunc && pFunc->xFinalize) ){ - sqlite3_context ctx; - assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - memset(&ctx, 0, sizeof(ctx)); - ctx.s.flags = MEM_Null; - ctx.s.db = pMem->db; - ctx.pMem = pMem; - ctx.pFunc = pFunc; - pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ - assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel ); - sqlite3DbFree(pMem->db, pMem->zMalloc); - memcpy(pMem, &ctx.s, sizeof(ctx.s)); - rc = ctx.isError; - } - return rc; -} - -/* -** If the memory cell contains a string value that must be freed by -** invoking an external callback, free it now. Calling this function -** does not free any Mem.zMalloc buffer. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){ - assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); - if( p->flags&MEM_Agg ){ - sqlite3VdbeMemFinalize(p, p->u.pDef); - assert( (p->flags & MEM_Agg)==0 ); - sqlite3VdbeMemRelease(p); - }else if( p->flags&MEM_Dyn && p->xDel ){ - assert( (p->flags&MEM_RowSet)==0 ); - assert( p->xDel!=SQLITE_DYNAMIC ); - p->xDel((void *)p->z); - p->xDel = 0; - }else if( p->flags&MEM_RowSet ){ - sqlite3RowSetClear(p->u.pRowSet); - }else if( p->flags&MEM_Frame ){ - sqlite3VdbeMemSetNull(p); - } -} - -/* -** Release any memory held by the Mem. This may leave the Mem in an -** inconsistent state, for example with (Mem.z==0) and -** (Mem.type==SQLITE_TEXT). -*/ -SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){ - VdbeMemRelease(p); - sqlite3DbFree(p->db, p->zMalloc); - p->z = 0; - p->zMalloc = 0; - p->xDel = 0; -} - -/* -** Convert a 64-bit IEEE double into a 64-bit signed integer. -** If the double is too large, return 0x8000000000000000. -** -** Most systems appear to do this simply by assigning -** variables and without the extra range tests. But -** there are reports that windows throws an expection -** if the floating point value is out of range. (See ticket #2880.) -** Because we do not completely understand the problem, we will -** take the conservative approach and always do range tests -** before attempting the conversion. -*/ -static i64 doubleToInt64(double r){ -#ifdef SQLITE_OMIT_FLOATING_POINT - /* When floating-point is omitted, double and int64 are the same thing */ - return r; -#else - /* - ** Many compilers we encounter do not define constants for the - ** minimum and maximum 64-bit integers, or they define them - ** inconsistently. And many do not understand the "LL" notation. - ** So we define our own static constants here using nothing - ** larger than a 32-bit integer constant. - */ - static const i64 maxInt = LARGEST_INT64; - static const i64 minInt = SMALLEST_INT64; - - if( r<(double)minInt ){ - return minInt; - }else if( r>(double)maxInt ){ - /* minInt is correct here - not maxInt. It turns out that assigning - ** a very large positive number to an integer results in a very large - ** negative integer. This makes no sense, but it is what x86 hardware - ** does so for compatibility we will do the same in software. */ - return minInt; - }else{ - return (i64)r; - } -#endif -} - -/* -** Return some kind of integer value which is the best we can do -** at representing the value that *pMem describes as an integer. -** If pMem is an integer, then the value is exact. If pMem is -** a floating-point then the value returned is the integer part. -** If pMem is a string or blob, then we make an attempt to convert -** it into a integer and return that. If pMem represents an -** an SQL-NULL value, return 0. -** -** If pMem represents a string value, its encoding might be changed. -*/ -SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){ - int flags; - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - flags = pMem->flags; - if( flags & MEM_Int ){ - return pMem->u.i; - }else if( flags & MEM_Real ){ - return doubleToInt64(pMem->r); - }else if( flags & (MEM_Str|MEM_Blob) ){ - i64 value = 0; - assert( pMem->z || pMem->n==0 ); - testcase( pMem->z==0 ); - sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); - return value; - }else{ - return 0; - } -} - -/* -** Return the best representation of pMem that we can get into a -** double. If pMem is already a double or an integer, return its -** value. If it is a string or blob, try to convert it to a double. -** If it is a NULL, return 0.0. -*/ -SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - if( pMem->flags & MEM_Real ){ - return pMem->r; - }else if( pMem->flags & MEM_Int ){ - return (double)pMem->u.i; - }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - double val = (double)0; - sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc); - return val; - }else{ - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - return (double)0; - } -} - -/* -** The MEM structure is already a MEM_Real. Try to also make it a -** MEM_Int if we can. -*/ -SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ - assert( pMem->flags & MEM_Real ); - assert( (pMem->flags & MEM_RowSet)==0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - - pMem->u.i = doubleToInt64(pMem->r); - - /* Only mark the value as an integer if - ** - ** (1) the round-trip conversion real->int->real is a no-op, and - ** (2) The integer is neither the largest nor the smallest - ** possible integer (ticket #3922) - ** - ** The second and third terms in the following conditional enforces - ** the second condition under the assumption that addition overflow causes - ** values to wrap around. On x86 hardware, the third term is always - ** true and could be omitted. But we leave it in because other - ** architectures might behave differently. - */ - if( pMem->r==(double)pMem->u.i - && pMem->u.i>SMALLEST_INT64 -#if defined(__i486__) || defined(__x86_64__) - && ALWAYS(pMem->u.iu.iflags |= MEM_Int; - } -} - -/* -** Convert pMem to type integer. Invalidate any prior representations. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){ - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( (pMem->flags & MEM_RowSet)==0 ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - - pMem->u.i = sqlite3VdbeIntValue(pMem); - MemSetTypeFlag(pMem, MEM_Int); - return SQLITE_OK; -} - -/* -** Convert pMem so that it is of type MEM_Real. -** Invalidate any prior representations. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){ - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - - pMem->r = sqlite3VdbeRealValue(pMem); - MemSetTypeFlag(pMem, MEM_Real); - return SQLITE_OK; -} - -/* -** Convert pMem so that it has types MEM_Real or MEM_Int or both. -** Invalidate any prior representations. -** -** Every effort is made to force the conversion, even if the input -** is a string that does not look completely like a number. Convert -** as much of the string as we can and ignore the rest. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ - if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ - assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){ - MemSetTypeFlag(pMem, MEM_Int); - }else{ - pMem->r = sqlite3VdbeRealValue(pMem); - MemSetTypeFlag(pMem, MEM_Real); - sqlite3VdbeIntegerAffinity(pMem); - } - } - assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); - pMem->flags &= ~(MEM_Str|MEM_Blob); - return SQLITE_OK; -} - -/* -** Delete any previous value and set the value stored in *pMem to NULL. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){ - if( pMem->flags & MEM_Frame ){ - VdbeFrame *pFrame = pMem->u.pFrame; - pFrame->pParent = pFrame->v->pDelFrame; - pFrame->v->pDelFrame = pFrame; - } - if( pMem->flags & MEM_RowSet ){ - sqlite3RowSetClear(pMem->u.pRowSet); - } - MemSetTypeFlag(pMem, MEM_Null); - pMem->type = SQLITE_NULL; -} - -/* -** Delete any previous value and set the value to be a BLOB of length -** n containing all zeros. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){ - sqlite3VdbeMemRelease(pMem); - pMem->flags = MEM_Blob|MEM_Zero; - pMem->type = SQLITE_BLOB; - pMem->n = 0; - if( n<0 ) n = 0; - pMem->u.nZero = n; - pMem->enc = SQLITE_UTF8; - -#ifdef SQLITE_OMIT_INCRBLOB - sqlite3VdbeMemGrow(pMem, n, 0); - if( pMem->z ){ - pMem->n = n; - memset(pMem->z, 0, n); - } -#endif -} - -/* -** Delete any previous value and set the value stored in *pMem to val, -** manifest type INTEGER. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ - sqlite3VdbeMemRelease(pMem); - pMem->u.i = val; - pMem->flags = MEM_Int; - pMem->type = SQLITE_INTEGER; -} - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** Delete any previous value and set the value stored in *pMem to val, -** manifest type REAL. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ - if( sqlite3IsNaN(val) ){ - sqlite3VdbeMemSetNull(pMem); - }else{ - sqlite3VdbeMemRelease(pMem); - pMem->r = val; - pMem->flags = MEM_Real; - pMem->type = SQLITE_FLOAT; - } -} -#endif - -/* -** Delete any previous value and set the value of pMem to be an -** empty boolean index. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ - sqlite3 *db = pMem->db; - assert( db!=0 ); - assert( (pMem->flags & MEM_RowSet)==0 ); - sqlite3VdbeMemRelease(pMem); - pMem->zMalloc = sqlite3DbMallocRaw(db, 64); - if( db->mallocFailed ){ - pMem->flags = MEM_Null; - }else{ - assert( pMem->zMalloc ); - pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, - sqlite3DbMallocSize(db, pMem->zMalloc)); - assert( pMem->u.pRowSet!=0 ); - pMem->flags = MEM_RowSet; - } -} - -/* -** Return true if the Mem object contains a TEXT or BLOB that is -** too large - whose size exceeds SQLITE_MAX_LENGTH. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){ - assert( p->db!=0 ); - if( p->flags & (MEM_Str|MEM_Blob) ){ - int n = p->n; - if( p->flags & MEM_Zero ){ - n += p->u.nZero; - } - return n>p->db->aLimit[SQLITE_LIMIT_LENGTH]; - } - return 0; -} - -#ifdef SQLITE_DEBUG -/* -** This routine prepares a memory cell for modication by breaking -** its link to a shallow copy and by marking any current shallow -** copies of this cell as invalid. -** -** This is used for testing and debugging only - to make sure shallow -** copies are not misused. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ - int i; - Mem *pX; - for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){ - if( pX->pScopyFrom==pMem ){ - pX->flags |= MEM_Invalid; - pX->pScopyFrom = 0; - } - } - pMem->pScopyFrom = 0; -} -#endif /* SQLITE_DEBUG */ - -/* -** Size of struct Mem not including the Mem.zMalloc member. -*/ -#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc)) - -/* -** Make an shallow copy of pFrom into pTo. Prior contents of -** pTo are freed. The pFrom->z field is not duplicated. If -** pFrom->z is used, then pTo->z points to the same thing as pFrom->z -** and flags gets srcType (either MEM_Ephem or MEM_Static). -*/ -SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ - assert( (pFrom->flags & MEM_RowSet)==0 ); - VdbeMemRelease(pTo); - memcpy(pTo, pFrom, MEMCELLSIZE); - pTo->xDel = 0; - if( (pFrom->flags&MEM_Static)==0 ){ - pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); - assert( srcType==MEM_Ephem || srcType==MEM_Static ); - pTo->flags |= srcType; - } -} - -/* -** Make a full copy of pFrom into pTo. Prior contents of pTo are -** freed before the copy is made. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ - int rc = SQLITE_OK; - - assert( (pFrom->flags & MEM_RowSet)==0 ); - VdbeMemRelease(pTo); - memcpy(pTo, pFrom, MEMCELLSIZE); - pTo->flags &= ~MEM_Dyn; - - if( pTo->flags&(MEM_Str|MEM_Blob) ){ - if( 0==(pFrom->flags&MEM_Static) ){ - pTo->flags |= MEM_Ephem; - rc = sqlite3VdbeMemMakeWriteable(pTo); - } - } - - return rc; -} - -/* -** Transfer the contents of pFrom to pTo. Any existing value in pTo is -** freed. If pFrom contains ephemeral data, a copy is made. -** -** pFrom contains an SQL NULL when this routine returns. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ - assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) ); - assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) ); - assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db ); - - sqlite3VdbeMemRelease(pTo); - memcpy(pTo, pFrom, sizeof(Mem)); - pFrom->flags = MEM_Null; - pFrom->xDel = 0; - pFrom->zMalloc = 0; -} - -/* -** Change the value of a Mem to be a string or a BLOB. -** -** The memory management strategy depends on the value of the xDel -** parameter. If the value passed is SQLITE_TRANSIENT, then the -** string is copied into a (possibly existing) buffer managed by the -** Mem structure. Otherwise, any existing buffer is freed and the -** pointer copied. -** -** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH -** size limit) then no memory allocation occurs. If the string can be -** stored without allocating memory, then it is. If a memory allocation -** is required to store the string, then value of pMem is unchanged. In -** either case, SQLITE_TOOBIG is returned. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemSetStr( - Mem *pMem, /* Memory cell to set to string value */ - const char *z, /* String pointer */ - int n, /* Bytes in string, or negative */ - u8 enc, /* Encoding of z. 0 for BLOBs */ - void (*xDel)(void*) /* Destructor function */ -){ - int nByte = n; /* New value for pMem->n */ - int iLimit; /* Maximum allowed string or blob size */ - u16 flags = 0; /* New value for pMem->flags */ - - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - assert( (pMem->flags & MEM_RowSet)==0 ); - - /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ - if( !z ){ - sqlite3VdbeMemSetNull(pMem); - return SQLITE_OK; - } - - if( pMem->db ){ - iLimit = pMem->db->aLimit[SQLITE_LIMIT_LENGTH]; - }else{ - iLimit = SQLITE_MAX_LENGTH; - } - flags = (enc==0?MEM_Blob:MEM_Str); - if( nByte<0 ){ - assert( enc!=0 ); - if( enc==SQLITE_UTF8 ){ - for(nByte=0; nByte<=iLimit && z[nByte]; nByte++){} - }else{ - for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} - } - flags |= MEM_Term; - } - - /* The following block sets the new values of Mem.z and Mem.xDel. It - ** also sets a flag in local variable "flags" to indicate the memory - ** management (one of MEM_Dyn or MEM_Static). - */ - if( xDel==SQLITE_TRANSIENT ){ - int nAlloc = nByte; - if( flags&MEM_Term ){ - nAlloc += (enc==SQLITE_UTF8?1:2); - } - if( nByte>iLimit ){ - return SQLITE_TOOBIG; - } - if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){ - return SQLITE_NOMEM; - } - memcpy(pMem->z, z, nAlloc); - }else if( xDel==SQLITE_DYNAMIC ){ - sqlite3VdbeMemRelease(pMem); - pMem->zMalloc = pMem->z = (char *)z; - pMem->xDel = 0; - }else{ - sqlite3VdbeMemRelease(pMem); - pMem->z = (char *)z; - pMem->xDel = xDel; - flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); - } - - pMem->n = nByte; - pMem->flags = flags; - pMem->enc = (enc==0 ? SQLITE_UTF8 : enc); - pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT); - -#ifndef SQLITE_OMIT_UTF16 - if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ - return SQLITE_NOMEM; - } -#endif - - if( nByte>iLimit ){ - return SQLITE_TOOBIG; - } - - return SQLITE_OK; -} - -/* -** Compare the values contained by the two memory cells, returning -** negative, zero or positive if pMem1 is less than, equal to, or greater -** than pMem2. Sorting order is NULL's first, followed by numbers (integers -** and reals) sorted numerically, followed by text ordered by the collating -** sequence pColl and finally blob's ordered by memcmp(). -** -** Two NULL values are considered equal by this function. -*/ -SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ - int rc; - int f1, f2; - int combined_flags; - - f1 = pMem1->flags; - f2 = pMem2->flags; - combined_flags = f1|f2; - assert( (combined_flags & MEM_RowSet)==0 ); - - /* If one value is NULL, it is less than the other. If both values - ** are NULL, return 0. - */ - if( combined_flags&MEM_Null ){ - return (f2&MEM_Null) - (f1&MEM_Null); - } - - /* If one value is a number and the other is not, the number is less. - ** If both are numbers, compare as reals if one is a real, or as integers - ** if both values are integers. - */ - if( combined_flags&(MEM_Int|MEM_Real) ){ - if( !(f1&(MEM_Int|MEM_Real)) ){ - return 1; - } - if( !(f2&(MEM_Int|MEM_Real)) ){ - return -1; - } - if( (f1 & f2 & MEM_Int)==0 ){ - double r1, r2; - if( (f1&MEM_Real)==0 ){ - r1 = (double)pMem1->u.i; - }else{ - r1 = pMem1->r; - } - if( (f2&MEM_Real)==0 ){ - r2 = (double)pMem2->u.i; - }else{ - r2 = pMem2->r; - } - if( r1r2 ) return 1; - return 0; - }else{ - assert( f1&MEM_Int ); - assert( f2&MEM_Int ); - if( pMem1->u.i < pMem2->u.i ) return -1; - if( pMem1->u.i > pMem2->u.i ) return 1; - return 0; - } - } - - /* If one value is a string and the other is a blob, the string is less. - ** If both are strings, compare using the collating functions. - */ - if( combined_flags&MEM_Str ){ - if( (f1 & MEM_Str)==0 ){ - return 1; - } - if( (f2 & MEM_Str)==0 ){ - return -1; - } - - assert( pMem1->enc==pMem2->enc ); - assert( pMem1->enc==SQLITE_UTF8 || - pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE ); - - /* The collation sequence must be defined at this point, even if - ** the user deletes the collation sequence after the vdbe program is - ** compiled (this was not always the case). - */ - assert( !pColl || pColl->xCmp ); - - if( pColl ){ - if( pMem1->enc==pColl->enc ){ - /* The strings are already in the correct encoding. Call the - ** comparison function directly */ - return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); - }else{ - const void *v1, *v2; - int n1, n2; - Mem c1; - Mem c2; - memset(&c1, 0, sizeof(c1)); - memset(&c2, 0, sizeof(c2)); - sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); - sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); - v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); - n1 = v1==0 ? 0 : c1.n; - v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); - n2 = v2==0 ? 0 : c2.n; - rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); - sqlite3VdbeMemRelease(&c1); - sqlite3VdbeMemRelease(&c2); - return rc; - } - } - /* If a NULL pointer was passed as the collate function, fall through - ** to the blob case and use memcmp(). */ - } - - /* Both values must be blobs. Compare using memcmp(). */ - rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); - if( rc==0 ){ - rc = pMem1->n - pMem2->n; - } - return rc; -} - -/* -** Move data out of a btree key or data field and into a Mem structure. -** The data or key is taken from the entry that pCur is currently pointing -** to. offset and amt determine what portion of the data or key to retrieve. -** key is true to get the key or false to get data. The result is written -** into the pMem element. -** -** The pMem structure is assumed to be uninitialized. Any prior content -** is overwritten without being freed. -** -** If this routine fails for any reason (malloc returns NULL or unable -** to read from the disk) then the pMem is left in an inconsistent state. -*/ -SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( - BtCursor *pCur, /* Cursor pointing at record to retrieve. */ - int offset, /* Offset from the start of data to return bytes from. */ - int amt, /* Number of bytes to return. */ - int key, /* If true, retrieve from the btree key, not data. */ - Mem *pMem /* OUT: Return data in this Mem structure. */ -){ - char *zData; /* Data from the btree layer */ - int available = 0; /* Number of bytes available on the local btree page */ - int rc = SQLITE_OK; /* Return code */ - - assert( sqlite3BtreeCursorIsValid(pCur) ); - - /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() - ** that both the BtShared and database handle mutexes are held. */ - assert( (pMem->flags & MEM_RowSet)==0 ); - if( key ){ - zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); - }else{ - zData = (char *)sqlite3BtreeDataFetch(pCur, &available); - } - assert( zData!=0 ); - - if( offset+amt<=available && (pMem->flags&MEM_Dyn)==0 ){ - sqlite3VdbeMemRelease(pMem); - pMem->z = &zData[offset]; - pMem->flags = MEM_Blob|MEM_Ephem; - }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ - pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; - pMem->enc = 0; - pMem->type = SQLITE_BLOB; - if( key ){ - rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); - }else{ - rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); - } - pMem->z[amt] = 0; - pMem->z[amt+1] = 0; - if( rc!=SQLITE_OK ){ - sqlite3VdbeMemRelease(pMem); - } - } - pMem->n = amt; - - return rc; -} - -/* This function is only available internally, it is not part of the -** external API. It works in a similar way to sqlite3_value_text(), -** except the data returned is in the encoding specified by the second -** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or -** SQLITE_UTF8. -** -** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED. -** If that is the case, then the result must be aligned on an even byte -** boundary. -*/ -SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ - if( !pVal ) return 0; - - assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); - assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); - assert( (pVal->flags & MEM_RowSet)==0 ); - - if( pVal->flags&MEM_Null ){ - return 0; - } - assert( (MEM_Blob>>3) == MEM_Str ); - pVal->flags |= (pVal->flags & MEM_Blob)>>3; - ExpandBlob(pVal); - if( pVal->flags&MEM_Str ){ - sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); - if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){ - assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); - if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ - return 0; - } - } - sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */ - }else{ - assert( (pVal->flags&MEM_Blob)==0 ); - sqlite3VdbeMemStringify(pVal, enc); - assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); - } - assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 - || pVal->db->mallocFailed ); - if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ - return pVal->z; - }else{ - return 0; - } -} - -/* -** Create a new sqlite3_value object. -*/ -SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){ - Mem *p = sqlite3DbMallocZero(db, sizeof(*p)); - if( p ){ - p->flags = MEM_Null; - p->type = SQLITE_NULL; - p->db = db; - } - return p; -} - -/* -** Create a new sqlite3_value object, containing the value of pExpr. -** -** This only works for very simple expressions that consist of one constant -** token (i.e. "5", "5.1", "'a string'"). If the expression can -** be converted directly into a value, then the value is allocated and -** a pointer written to *ppVal. The caller is responsible for deallocating -** the value by passing it to sqlite3ValueFree() later on. If the expression -** cannot be converted to a value, then *ppVal is set to NULL. -*/ -SQLITE_PRIVATE int sqlite3ValueFromExpr( - sqlite3 *db, /* The database connection */ - Expr *pExpr, /* The expression to evaluate */ - u8 enc, /* Encoding to use */ - u8 affinity, /* Affinity to use */ - sqlite3_value **ppVal /* Write the new value here */ -){ - int op; - char *zVal = 0; - sqlite3_value *pVal = 0; - int negInt = 1; - const char *zNeg = ""; - - if( !pExpr ){ - *ppVal = 0; - return SQLITE_OK; - } - op = pExpr->op; - - /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3. - ** The ifdef here is to enable us to achieve 100% branch test coverage even - ** when SQLITE_ENABLE_STAT3 is omitted. - */ -#ifdef SQLITE_ENABLE_STAT3 - if( op==TK_REGISTER ) op = pExpr->op2; -#else - if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; -#endif - - /* Handle negative integers in a single step. This is needed in the - ** case when the value is -9223372036854775808. - */ - if( op==TK_UMINUS - && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){ - pExpr = pExpr->pLeft; - op = pExpr->op; - negInt = -1; - zNeg = "-"; - } - - if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ - pVal = sqlite3ValueNew(db); - if( pVal==0 ) goto no_mem; - if( ExprHasProperty(pExpr, EP_IntValue) ){ - sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt); - }else{ - zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken); - if( zVal==0 ) goto no_mem; - sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); - if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT; - } - if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ - sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); - }else{ - sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); - } - if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str; - if( enc!=SQLITE_UTF8 ){ - sqlite3VdbeChangeEncoding(pVal, enc); - } - }else if( op==TK_UMINUS ) { - /* This branch happens for multiple negative signs. Ex: -(-5) */ - if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){ - sqlite3VdbeMemNumerify(pVal); - if( pVal->u.i==SMALLEST_INT64 ){ - pVal->flags &= MEM_Int; - pVal->flags |= MEM_Real; - pVal->r = (double)LARGEST_INT64; - }else{ - pVal->u.i = -pVal->u.i; - } - pVal->r = -pVal->r; - sqlite3ValueApplyAffinity(pVal, affinity, enc); - } - }else if( op==TK_NULL ){ - pVal = sqlite3ValueNew(db); - if( pVal==0 ) goto no_mem; - } -#ifndef SQLITE_OMIT_BLOB_LITERAL - else if( op==TK_BLOB ){ - int nVal; - assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); - assert( pExpr->u.zToken[1]=='\'' ); - pVal = sqlite3ValueNew(db); - if( !pVal ) goto no_mem; - zVal = &pExpr->u.zToken[2]; - nVal = sqlite3Strlen30(zVal)-1; - assert( zVal[nVal]=='\'' ); - sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, - 0, SQLITE_DYNAMIC); - } -#endif - - if( pVal ){ - sqlite3VdbeMemStoreType(pVal); - } - *ppVal = pVal; - return SQLITE_OK; - -no_mem: - db->mallocFailed = 1; - sqlite3DbFree(db, zVal); - sqlite3ValueFree(pVal); - *ppVal = 0; - return SQLITE_NOMEM; -} - -/* -** Change the string value of an sqlite3_value object -*/ -SQLITE_PRIVATE void sqlite3ValueSetStr( - sqlite3_value *v, /* Value to be set */ - int n, /* Length of string z */ - const void *z, /* Text of the new string */ - u8 enc, /* Encoding to use */ - void (*xDel)(void*) /* Destructor for the string */ -){ - if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel); -} - -/* -** Free an sqlite3_value object -*/ -SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){ - if( !v ) return; - sqlite3VdbeMemRelease((Mem *)v); - sqlite3DbFree(((Mem*)v)->db, v); -} - -/* -** Return the number of bytes in the sqlite3_value object assuming -** that it uses the encoding "enc" -*/ -SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ - Mem *p = (Mem*)pVal; - if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){ - if( p->flags & MEM_Zero ){ - return p->n + p->u.nZero; - }else{ - return p->n; - } - } - return 0; -} - -/************** End of vdbemem.c *********************************************/ -/************** Begin file vdbeaux.c *****************************************/ -/* -** 2003 September 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used for creating, destroying, and populating -** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior -** to version 2.8.7, all this code was combined into the vdbe.c source file. -** But that file was getting too big so this subroutines were split out. -*/ - -/* -** Create a new virtual database engine. -*/ -SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){ - Vdbe *p; - p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); - if( p==0 ) return 0; - p->db = db; - if( db->pVdbe ){ - db->pVdbe->pPrev = p; - } - p->pNext = db->pVdbe; - p->pPrev = 0; - db->pVdbe = p; - p->magic = VDBE_MAGIC_INIT; - return p; -} - -/* -** Remember the SQL string for a prepared statement. -*/ -SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ - assert( isPrepareV2==1 || isPrepareV2==0 ); - if( p==0 ) return; -#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) - if( !isPrepareV2 ) return; -#endif - assert( p->zSql==0 ); - p->zSql = sqlite3DbStrNDup(p->db, z, n); - p->isPrepareV2 = (u8)isPrepareV2; -} - -/* -** Return the SQL associated with a prepared statement -*/ -SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe *)pStmt; - return (p && p->isPrepareV2) ? p->zSql : 0; -} - -/* -** Swap all content between two VDBE structures. -*/ -SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ - Vdbe tmp, *pTmp; - char *zTmp; - tmp = *pA; - *pA = *pB; - *pB = tmp; - pTmp = pA->pNext; - pA->pNext = pB->pNext; - pB->pNext = pTmp; - pTmp = pA->pPrev; - pA->pPrev = pB->pPrev; - pB->pPrev = pTmp; - zTmp = pA->zSql; - pA->zSql = pB->zSql; - pB->zSql = zTmp; - pB->isPrepareV2 = pA->isPrepareV2; -} - -#ifdef SQLITE_DEBUG -/* -** Turn tracing on or off -*/ -SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ - p->trace = trace; -} -#endif - -/* -** Resize the Vdbe.aOp array so that it is at least one op larger than -** it was. -** -** If an out-of-memory error occurs while resizing the array, return -** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain -** unchanged (this is so that any opcodes already allocated can be -** correctly deallocated along with the rest of the Vdbe). -*/ -static int growOpArray(Vdbe *p){ - VdbeOp *pNew; - int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op))); - pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op)); - if( pNew ){ - p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op); - p->aOp = pNew; - } - return (pNew ? SQLITE_OK : SQLITE_NOMEM); -} - -/* -** Add a new instruction to the list of instructions current in the -** VDBE. Return the address of the new instruction. -** -** Parameters: -** -** p Pointer to the VDBE -** -** op The opcode for this instruction -** -** p1, p2, p3 Operands -** -** Use the sqlite3VdbeResolveLabel() function to fix an address and -** the sqlite3VdbeChangeP4() function to change the value of the P4 -** operand. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ - int i; - VdbeOp *pOp; - - i = p->nOp; - assert( p->magic==VDBE_MAGIC_INIT ); - assert( op>0 && op<0xff ); - if( p->nOpAlloc<=i ){ - if( growOpArray(p) ){ - return 1; - } - } - p->nOp++; - pOp = &p->aOp[i]; - pOp->opcode = (u8)op; - pOp->p5 = 0; - pOp->p1 = p1; - pOp->p2 = p2; - pOp->p3 = p3; - pOp->p4.p = 0; - pOp->p4type = P4_NOTUSED; -#ifdef SQLITE_DEBUG - pOp->zComment = 0; - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - sqlite3VdbePrintOp(0, i, &p->aOp[i]); - } -#endif -#ifdef VDBE_PROFILE - pOp->cycles = 0; - pOp->cnt = 0; -#endif - return i; -} -SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){ - return sqlite3VdbeAddOp3(p, op, 0, 0, 0); -} -SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe *p, int op, int p1){ - return sqlite3VdbeAddOp3(p, op, p1, 0, 0); -} -SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe *p, int op, int p1, int p2){ - return sqlite3VdbeAddOp3(p, op, p1, p2, 0); -} - - -/* -** Add an opcode that includes the p4 value as a pointer. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOp4( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - const char *zP4, /* The P4 operand */ - int p4type /* P4 operand type */ -){ - int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); - sqlite3VdbeChangeP4(p, addr, zP4, p4type); - return addr; -} - -/* -** Add an OP_ParseSchema opcode. This routine is broken out from -** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees -** as having been used. -** -** The zWhere string must have been obtained from sqlite3_malloc(). -** This routine will take ownership of the allocated memory. -*/ -SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){ - int j; - int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0); - sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC); - for(j=0; jdb->nDb; j++) sqlite3VdbeUsesBtree(p, j); -} - -/* -** Add an opcode that includes the p4 value as an integer. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( - Vdbe *p, /* Add the opcode to this VM */ - int op, /* The new opcode */ - int p1, /* The P1 operand */ - int p2, /* The P2 operand */ - int p3, /* The P3 operand */ - int p4 /* The P4 operand as an integer */ -){ - int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); - sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32); - return addr; -} - -/* -** Create a new symbolic label for an instruction that has yet to be -** coded. The symbolic label is really just a negative number. The -** label can be used as the P2 value of an operation. Later, when -** the label is resolved to a specific address, the VDBE will scan -** through its operation list and change all values of P2 which match -** the label into the resolved address. -** -** The VDBE knows that a P2 value is a label because labels are -** always negative and P2 values are suppose to be non-negative. -** Hence, a negative P2 value is a label that has yet to be resolved. -** -** Zero is returned if a malloc() fails. -*/ -SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){ - int i = p->nLabel++; - assert( p->magic==VDBE_MAGIC_INIT ); - if( (i & (i-1))==0 ){ - p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, - (i*2+1)*sizeof(p->aLabel[0])); - } - if( p->aLabel ){ - p->aLabel[i] = -1; - } - return -1-i; -} - -/* -** Resolve label "x" to be the address of the next instruction to -** be inserted. The parameter "x" must have been obtained from -** a prior call to sqlite3VdbeMakeLabel(). -*/ -SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *p, int x){ - int j = -1-x; - assert( p->magic==VDBE_MAGIC_INIT ); - assert( j>=0 && jnLabel ); - if( p->aLabel ){ - p->aLabel[j] = p->nOp; - } -} - -/* -** Mark the VDBE as one that can only be run one time. -*/ -SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){ - p->runOnlyOnce = 1; -} - -#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ - -/* -** The following type and function are used to iterate through all opcodes -** in a Vdbe main program and each of the sub-programs (triggers) it may -** invoke directly or indirectly. It should be used as follows: -** -** Op *pOp; -** VdbeOpIter sIter; -** -** memset(&sIter, 0, sizeof(sIter)); -** sIter.v = v; // v is of type Vdbe* -** while( (pOp = opIterNext(&sIter)) ){ -** // Do something with pOp -** } -** sqlite3DbFree(v->db, sIter.apSub); -** -*/ -typedef struct VdbeOpIter VdbeOpIter; -struct VdbeOpIter { - Vdbe *v; /* Vdbe to iterate through the opcodes of */ - SubProgram **apSub; /* Array of subprograms */ - int nSub; /* Number of entries in apSub */ - int iAddr; /* Address of next instruction to return */ - int iSub; /* 0 = main program, 1 = first sub-program etc. */ -}; -static Op *opIterNext(VdbeOpIter *p){ - Vdbe *v = p->v; - Op *pRet = 0; - Op *aOp; - int nOp; - - if( p->iSub<=p->nSub ){ - - if( p->iSub==0 ){ - aOp = v->aOp; - nOp = v->nOp; - }else{ - aOp = p->apSub[p->iSub-1]->aOp; - nOp = p->apSub[p->iSub-1]->nOp; - } - assert( p->iAddriAddr]; - p->iAddr++; - if( p->iAddr==nOp ){ - p->iSub++; - p->iAddr = 0; - } - - if( pRet->p4type==P4_SUBPROGRAM ){ - int nByte = (p->nSub+1)*sizeof(SubProgram*); - int j; - for(j=0; jnSub; j++){ - if( p->apSub[j]==pRet->p4.pProgram ) break; - } - if( j==p->nSub ){ - p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte); - if( !p->apSub ){ - pRet = 0; - }else{ - p->apSub[p->nSub++] = pRet->p4.pProgram; - } - } - } - } - - return pRet; -} - -/* -** Check if the program stored in the VM associated with pParse may -** throw an ABORT exception (causing the statement, but not entire transaction -** to be rolled back). This condition is true if the main program or any -** sub-programs contains any of the following: -** -** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort. -** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort. -** * OP_Destroy -** * OP_VUpdate -** * OP_VRename -** * OP_FkCounter with P2==0 (immediate foreign key constraint) -** -** Then check that the value of Parse.mayAbort is true if an -** ABORT may be thrown, or false otherwise. Return true if it does -** match, or false otherwise. This function is intended to be used as -** part of an assert statement in the compiler. Similar to: -** -** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); -*/ -SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ - int hasAbort = 0; - Op *pOp; - VdbeOpIter sIter; - memset(&sIter, 0, sizeof(sIter)); - sIter.v = v; - - while( (pOp = opIterNext(&sIter))!=0 ){ - int opcode = pOp->opcode; - if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename -#ifndef SQLITE_OMIT_FOREIGN_KEY - || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) -#endif - || ((opcode==OP_Halt || opcode==OP_HaltIfNull) - && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) - ){ - hasAbort = 1; - break; - } - } - sqlite3DbFree(v->db, sIter.apSub); - - /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. - ** If malloc failed, then the while() loop above may not have iterated - ** through all opcodes and hasAbort may be set incorrectly. Return - ** true for this case to prevent the assert() in the callers frame - ** from failing. */ - return ( v->db->mallocFailed || hasAbort==mayAbort ); -} -#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ - -/* -** Loop through the program looking for P2 values that are negative -** on jump instructions. Each such value is a label. Resolve the -** label by setting the P2 value to its correct non-zero value. -** -** This routine is called once after all opcodes have been inserted. -** -** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument -** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by -** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array. -** -** The Op.opflags field is set on all opcodes. -*/ -static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ - int i; - int nMaxArgs = *pMaxFuncArgs; - Op *pOp; - int *aLabel = p->aLabel; - p->readOnly = 1; - for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ - u8 opcode = pOp->opcode; - - pOp->opflags = sqlite3OpcodeProperty[opcode]; - if( opcode==OP_Function || opcode==OP_AggStep ){ - if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; - }else if( (opcode==OP_Transaction && pOp->p2!=0) || opcode==OP_Vacuum ){ - p->readOnly = 0; -#ifndef SQLITE_OMIT_VIRTUALTABLE - }else if( opcode==OP_VUpdate ){ - if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; - }else if( opcode==OP_VFilter ){ - int n; - assert( p->nOp - i >= 3 ); - assert( pOp[-1].opcode==OP_Integer ); - n = pOp[-1].p1; - if( n>nMaxArgs ) nMaxArgs = n; -#endif - }else if( opcode==OP_Next || opcode==OP_SorterNext ){ - pOp->p4.xAdvance = sqlite3BtreeNext; - pOp->p4type = P4_ADVANCE; - }else if( opcode==OP_Prev ){ - pOp->p4.xAdvance = sqlite3BtreePrevious; - pOp->p4type = P4_ADVANCE; - } - - if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ - assert( -1-pOp->p2nLabel ); - pOp->p2 = aLabel[-1-pOp->p2]; - } - } - sqlite3DbFree(p->db, p->aLabel); - p->aLabel = 0; - - *pMaxFuncArgs = nMaxArgs; -} - -/* -** Return the address of the next instruction to be inserted. -*/ -SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){ - assert( p->magic==VDBE_MAGIC_INIT ); - return p->nOp; -} - -/* -** This function returns a pointer to the array of opcodes associated with -** the Vdbe passed as the first argument. It is the callers responsibility -** to arrange for the returned array to be eventually freed using the -** vdbeFreeOpArray() function. -** -** Before returning, *pnOp is set to the number of entries in the returned -** array. Also, *pnMaxArg is set to the larger of its current value and -** the number of entries in the Vdbe.apArg[] array required to execute the -** returned program. -*/ -SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ - VdbeOp *aOp = p->aOp; - assert( aOp && !p->db->mallocFailed ); - - /* Check that sqlite3VdbeUsesBtree() was not called on this VM */ - assert( p->btreeMask==0 ); - - resolveP2Values(p, pnMaxArg); - *pnOp = p->nOp; - p->aOp = 0; - return aOp; -} - -/* -** Add a whole list of operations to the operation stack. Return the -** address of the first operation added. -*/ -SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ - int addr; - assert( p->magic==VDBE_MAGIC_INIT ); - if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){ - return 0; - } - addr = p->nOp; - if( ALWAYS(nOp>0) ){ - int i; - VdbeOpList const *pIn = aOp; - for(i=0; ip2; - VdbeOp *pOut = &p->aOp[i+addr]; - pOut->opcode = pIn->opcode; - pOut->p1 = pIn->p1; - if( p2<0 && (sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP)!=0 ){ - pOut->p2 = addr + ADDR(p2); - }else{ - pOut->p2 = p2; - } - pOut->p3 = pIn->p3; - pOut->p4type = P4_NOTUSED; - pOut->p4.p = 0; - pOut->p5 = 0; -#ifdef SQLITE_DEBUG - pOut->zComment = 0; - if( p->db->flags & SQLITE_VdbeAddopTrace ){ - sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); - } -#endif - } - p->nOp += nOp; - } - return addr; -} - -/* -** Change the value of the P1 operand for a specific instruction. -** This routine is useful when a large program is loaded from a -** static array using sqlite3VdbeAddOpList but we want to make a -** few minor changes to the program. -*/ -SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){ - assert( p!=0 ); - if( ((u32)p->nOp)>addr ){ - p->aOp[addr].p1 = val; - } -} - -/* -** Change the value of the P2 operand for a specific instruction. -** This routine is useful for setting a jump destination. -*/ -SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){ - assert( p!=0 ); - if( ((u32)p->nOp)>addr ){ - p->aOp[addr].p2 = val; - } -} - -/* -** Change the value of the P3 operand for a specific instruction. -*/ -SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ - assert( p!=0 ); - if( ((u32)p->nOp)>addr ){ - p->aOp[addr].p3 = val; - } -} - -/* -** Change the value of the P5 operand for the most recently -** added operation. -*/ -SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){ - assert( p!=0 ); - if( p->aOp ){ - assert( p->nOp>0 ); - p->aOp[p->nOp-1].p5 = val; - } -} - -/* -** Change the P2 operand of instruction addr so that it points to -** the address of the next instruction to be coded. -*/ -SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ - assert( addr>=0 || p->db->mallocFailed ); - if( addr>=0 ) sqlite3VdbeChangeP2(p, addr, p->nOp); -} - - -/* -** If the input FuncDef structure is ephemeral, then free it. If -** the FuncDef is not ephermal, then do nothing. -*/ -static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ - if( ALWAYS(pDef) && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){ - sqlite3DbFree(db, pDef); - } -} - -static void vdbeFreeOpArray(sqlite3 *, Op *, int); - -/* -** Delete a P4 value if necessary. -*/ -static void freeP4(sqlite3 *db, int p4type, void *p4){ - if( p4 ){ - assert( db ); - switch( p4type ){ - case P4_REAL: - case P4_INT64: - case P4_DYNAMIC: - case P4_KEYINFO: - case P4_INTARRAY: - case P4_KEYINFO_HANDOFF: { - sqlite3DbFree(db, p4); - break; - } - case P4_MPRINTF: { - if( db->pnBytesFreed==0 ) sqlite3_free(p4); - break; - } - case P4_VDBEFUNC: { - VdbeFunc *pVdbeFunc = (VdbeFunc *)p4; - freeEphemeralFunction(db, pVdbeFunc->pFunc); - if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); - sqlite3DbFree(db, pVdbeFunc); - break; - } - case P4_FUNCDEF: { - freeEphemeralFunction(db, (FuncDef*)p4); - break; - } - case P4_MEM: { - if( db->pnBytesFreed==0 ){ - sqlite3ValueFree((sqlite3_value*)p4); - }else{ - Mem *p = (Mem*)p4; - sqlite3DbFree(db, p->zMalloc); - sqlite3DbFree(db, p); - } - break; - } - case P4_VTAB : { - if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); - break; - } - } - } -} - -/* -** Free the space allocated for aOp and any p4 values allocated for the -** opcodes contained within. If aOp is not NULL it is assumed to contain -** nOp entries. -*/ -static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ - if( aOp ){ - Op *pOp; - for(pOp=aOp; pOp<&aOp[nOp]; pOp++){ - freeP4(db, pOp->p4type, pOp->p4.p); -#ifdef SQLITE_DEBUG - sqlite3DbFree(db, pOp->zComment); -#endif - } - } - sqlite3DbFree(db, aOp); -} - -/* -** Link the SubProgram object passed as the second argument into the linked -** list at Vdbe.pSubProgram. This list is used to delete all sub-program -** objects when the VM is no longer required. -*/ -SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){ - p->pNext = pVdbe->pProgram; - pVdbe->pProgram = p; -} - -/* -** Change the opcode at addr into OP_Noop -*/ -SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ - if( p->aOp ){ - VdbeOp *pOp = &p->aOp[addr]; - sqlite3 *db = p->db; - freeP4(db, pOp->p4type, pOp->p4.p); - memset(pOp, 0, sizeof(pOp[0])); - pOp->opcode = OP_Noop; - } -} - -/* -** Change the value of the P4 operand for a specific instruction. -** This routine is useful when a large program is loaded from a -** static array using sqlite3VdbeAddOpList but we want to make a -** few minor changes to the program. -** -** If n>=0 then the P4 operand is dynamic, meaning that a copy of -** the string is made into memory obtained from sqlite3_malloc(). -** A value of n==0 means copy bytes of zP4 up to and including the -** first null byte. If n>0 then copy n+1 bytes of zP4. -** -** If n==P4_KEYINFO it means that zP4 is a pointer to a KeyInfo structure. -** A copy is made of the KeyInfo structure into memory obtained from -** sqlite3_malloc, to be freed when the Vdbe is finalized. -** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure -** stored in memory that the caller has obtained from sqlite3_malloc. The -** caller should not free the allocation, it will be freed when the Vdbe is -** finalized. -** -** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points -** to a string or structure that is guaranteed to exist for the lifetime of -** the Vdbe. In these cases we can just copy the pointer. -** -** If addr<0 then change P4 on the most recently inserted instruction. -*/ -SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){ - Op *pOp; - sqlite3 *db; - assert( p!=0 ); - db = p->db; - assert( p->magic==VDBE_MAGIC_INIT ); - if( p->aOp==0 || db->mallocFailed ){ - if ( n!=P4_KEYINFO && n!=P4_VTAB ) { - freeP4(db, n, (void*)*(char**)&zP4); - } - return; - } - assert( p->nOp>0 ); - assert( addrnOp ); - if( addr<0 ){ - addr = p->nOp - 1; - } - pOp = &p->aOp[addr]; - assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 ); - freeP4(db, pOp->p4type, pOp->p4.p); - pOp->p4.p = 0; - if( n==P4_INT32 ){ - /* Note: this cast is safe, because the origin data point was an int - ** that was cast to a (const char *). */ - pOp->p4.i = SQLITE_PTR_TO_INT(zP4); - pOp->p4type = P4_INT32; - }else if( zP4==0 ){ - pOp->p4.p = 0; - pOp->p4type = P4_NOTUSED; - }else if( n==P4_KEYINFO ){ - KeyInfo *pKeyInfo; - int nField, nByte; - - nField = ((KeyInfo*)zP4)->nField; - nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField; - pKeyInfo = sqlite3DbMallocRaw(0, nByte); - pOp->p4.pKeyInfo = pKeyInfo; - if( pKeyInfo ){ - u8 *aSortOrder; - memcpy((char*)pKeyInfo, zP4, nByte - nField); - aSortOrder = pKeyInfo->aSortOrder; - assert( aSortOrder!=0 ); - pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField]; - memcpy(pKeyInfo->aSortOrder, aSortOrder, nField); - pOp->p4type = P4_KEYINFO; - }else{ - p->db->mallocFailed = 1; - pOp->p4type = P4_NOTUSED; - } - }else if( n==P4_KEYINFO_HANDOFF ){ - pOp->p4.p = (void*)zP4; - pOp->p4type = P4_KEYINFO; - }else if( n==P4_VTAB ){ - pOp->p4.p = (void*)zP4; - pOp->p4type = P4_VTAB; - sqlite3VtabLock((VTable *)zP4); - assert( ((VTable *)zP4)->db==p->db ); - }else if( n<0 ){ - pOp->p4.p = (void*)zP4; - pOp->p4type = (signed char)n; - }else{ - if( n==0 ) n = sqlite3Strlen30(zP4); - pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n); - pOp->p4type = P4_DYNAMIC; - } -} - -#ifndef NDEBUG -/* -** Change the comment on the most recently coded instruction. Or -** insert a No-op and add the comment to that new instruction. This -** makes the code easier to read during debugging. None of this happens -** in a production build. -*/ -static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){ - assert( p->nOp>0 || p->aOp==0 ); - assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); - if( p->nOp ){ - assert( p->aOp ); - sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment); - p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap); - } -} -SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ - va_list ap; - if( p ){ - va_start(ap, zFormat); - vdbeVComment(p, zFormat, ap); - va_end(ap); - } -} -SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ - va_list ap; - if( p ){ - sqlite3VdbeAddOp0(p, OP_Noop); - va_start(ap, zFormat); - vdbeVComment(p, zFormat, ap); - va_end(ap); - } -} -#endif /* NDEBUG */ - -/* -** Return the opcode for a given address. If the address is -1, then -** return the most recently inserted opcode. -** -** If a memory allocation error has occurred prior to the calling of this -** routine, then a pointer to a dummy VdbeOp will be returned. That opcode -** is readable but not writable, though it is cast to a writable value. -** The return of a dummy opcode allows the call to continue functioning -** after a OOM fault without having to check to see if the return from -** this routine is a valid pointer. But because the dummy.opcode is 0, -** dummy will never be written to. This is verified by code inspection and -** by running with Valgrind. -** -** About the #ifdef SQLITE_OMIT_TRACE: Normally, this routine is never called -** unless p->nOp>0. This is because in the absense of SQLITE_OMIT_TRACE, -** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as -** a new VDBE is created. So we are free to set addr to p->nOp-1 without -** having to double-check to make sure that the result is non-negative. But -** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to -** check the value of p->nOp-1 before continuing. -*/ -SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ - /* C89 specifies that the constant "dummy" will be initialized to all - ** zeros, which is correct. MSVC generates a warning, nevertheless. */ - static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */ - assert( p->magic==VDBE_MAGIC_INIT ); - if( addr<0 ){ -#ifdef SQLITE_OMIT_TRACE - if( p->nOp==0 ) return (VdbeOp*)&dummy; -#endif - addr = p->nOp - 1; - } - assert( (addr>=0 && addrnOp) || p->db->mallocFailed ); - if( p->db->mallocFailed ){ - return (VdbeOp*)&dummy; - }else{ - return &p->aOp[addr]; - } -} - -#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ - || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) -/* -** Compute a string that describes the P4 parameter for an opcode. -** Use zTemp for any required temporary buffer space. -*/ -static char *displayP4(Op *pOp, char *zTemp, int nTemp){ - char *zP4 = zTemp; - assert( nTemp>=20 ); - switch( pOp->p4type ){ - case P4_KEYINFO_STATIC: - case P4_KEYINFO: { - int i, j; - KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; - assert( pKeyInfo->aSortOrder!=0 ); - sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); - i = sqlite3Strlen30(zTemp); - for(j=0; jnField; j++){ - CollSeq *pColl = pKeyInfo->aColl[j]; - const char *zColl = pColl ? pColl->zName : "nil"; - int n = sqlite3Strlen30(zColl); - if( i+n>nTemp-6 ){ - memcpy(&zTemp[i],",...",4); - break; - } - zTemp[i++] = ','; - if( pKeyInfo->aSortOrder[j] ){ - zTemp[i++] = '-'; - } - memcpy(&zTemp[i], zColl, n+1); - i += n; - } - zTemp[i++] = ')'; - zTemp[i] = 0; - assert( ip4.pColl; - sqlite3_snprintf(nTemp, zTemp, "collseq(%.20s)", pColl->zName); - break; - } - case P4_FUNCDEF: { - FuncDef *pDef = pOp->p4.pFunc; - sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); - break; - } - case P4_INT64: { - sqlite3_snprintf(nTemp, zTemp, "%lld", *pOp->p4.pI64); - break; - } - case P4_INT32: { - sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p4.i); - break; - } - case P4_REAL: { - sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal); - break; - } - case P4_MEM: { - Mem *pMem = pOp->p4.pMem; - if( pMem->flags & MEM_Str ){ - zP4 = pMem->z; - }else if( pMem->flags & MEM_Int ){ - sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); - }else if( pMem->flags & MEM_Real ){ - sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r); - }else if( pMem->flags & MEM_Null ){ - sqlite3_snprintf(nTemp, zTemp, "NULL"); - }else{ - assert( pMem->flags & MEM_Blob ); - zP4 = "(blob)"; - } - break; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - case P4_VTAB: { - sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; - sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); - break; - } -#endif - case P4_INTARRAY: { - sqlite3_snprintf(nTemp, zTemp, "intarray"); - break; - } - case P4_SUBPROGRAM: { - sqlite3_snprintf(nTemp, zTemp, "program"); - break; - } - case P4_ADVANCE: { - zTemp[0] = 0; - break; - } - default: { - zP4 = pOp->p4.z; - if( zP4==0 ){ - zP4 = zTemp; - zTemp[0] = 0; - } - } - } - assert( zP4!=0 ); - return zP4; -} -#endif - -/* -** Declare to the Vdbe that the BTree object at db->aDb[i] is used. -** -** The prepared statements need to know in advance the complete set of -** attached databases that will be use. A mask of these databases -** is maintained in p->btreeMask. The p->lockMask value is the subset of -** p->btreeMask of databases that will require a lock. -*/ -SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){ - assert( i>=0 && idb->nDb && i<(int)sizeof(yDbMask)*8 ); - assert( i<(int)sizeof(p->btreeMask)*8 ); - p->btreeMask |= ((yDbMask)1)<db->aDb[i].pBt) ){ - p->lockMask |= ((yDbMask)1)<0 -/* -** If SQLite is compiled to support shared-cache mode and to be threadsafe, -** this routine obtains the mutex associated with each BtShared structure -** that may be accessed by the VM passed as an argument. In doing so it also -** sets the BtShared.db member of each of the BtShared structures, ensuring -** that the correct busy-handler callback is invoked if required. -** -** If SQLite is not threadsafe but does support shared-cache mode, then -** sqlite3BtreeEnter() is invoked to set the BtShared.db variables -** of all of BtShared structures accessible via the database handle -** associated with the VM. -** -** If SQLite is not threadsafe and does not support shared-cache mode, this -** function is a no-op. -** -** The p->btreeMask field is a bitmask of all btrees that the prepared -** statement p will ever use. Let N be the number of bits in p->btreeMask -** corresponding to btrees that use shared cache. Then the runtime of -** this routine is N*N. But as N is rarely more than 1, this should not -** be a problem. -*/ -SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe *p){ - int i; - yDbMask mask; - sqlite3 *db; - Db *aDb; - int nDb; - if( p->lockMask==0 ) return; /* The common case */ - db = p->db; - aDb = db->aDb; - nDb = db->nDb; - for(i=0, mask=1; ilockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ - sqlite3BtreeEnter(aDb[i].pBt); - } - } -} -#endif - -#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0 -/* -** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter(). -*/ -SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){ - int i; - yDbMask mask; - sqlite3 *db; - Db *aDb; - int nDb; - if( p->lockMask==0 ) return; /* The common case */ - db = p->db; - aDb = db->aDb; - nDb = db->nDb; - for(i=0, mask=1; ilockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ - sqlite3BtreeLeave(aDb[i].pBt); - } - } -} -#endif - -#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) -/* -** Print a single opcode. This routine is used for debugging only. -*/ -SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ - char *zP4; - char zPtr[50]; - static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n"; - if( pOut==0 ) pOut = stdout; - zP4 = displayP4(pOp, zPtr, sizeof(zPtr)); - fprintf(pOut, zFormat1, pc, - sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5, -#ifdef SQLITE_DEBUG - pOp->zComment ? pOp->zComment : "" -#else - "" -#endif - ); - fflush(pOut); -} -#endif - -/* -** Release an array of N Mem elements -*/ -static void releaseMemArray(Mem *p, int N){ - if( p && N ){ - Mem *pEnd; - sqlite3 *db = p->db; - u8 malloc_failed = db->mallocFailed; - if( db->pnBytesFreed ){ - for(pEnd=&p[N]; pzMalloc); - } - return; - } - for(pEnd=&p[N]; pflags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ - sqlite3VdbeMemRelease(p); - }else if( p->zMalloc ){ - sqlite3DbFree(db, p->zMalloc); - p->zMalloc = 0; - } - - p->flags = MEM_Invalid; - } - db->mallocFailed = malloc_failed; - } -} - -/* -** Delete a VdbeFrame object and its contents. VdbeFrame objects are -** allocated by the OP_Program opcode in sqlite3VdbeExec(). -*/ -SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){ - int i; - Mem *aMem = VdbeFrameMem(p); - VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; - for(i=0; inChildCsr; i++){ - sqlite3VdbeFreeCursor(p->v, apCsr[i]); - } - releaseMemArray(aMem, p->nChildMem); - sqlite3DbFree(p->v->db, p); -} - -#ifndef SQLITE_OMIT_EXPLAIN -/* -** Give a listing of the program in the virtual machine. -** -** The interface is the same as sqlite3VdbeExec(). But instead of -** running the code, it invokes the callback once for each instruction. -** This feature is used to implement "EXPLAIN". -** -** When p->explain==1, each instruction is listed. When -** p->explain==2, only OP_Explain instructions are listed and these -** are shown in a different format. p->explain==2 is used to implement -** EXPLAIN QUERY PLAN. -** -** When p->explain==1, first the main program is listed, then each of -** the trigger subprograms are listed one by one. -*/ -SQLITE_PRIVATE int sqlite3VdbeList( - Vdbe *p /* The VDBE */ -){ - int nRow; /* Stop when row count reaches this */ - int nSub = 0; /* Number of sub-vdbes seen so far */ - SubProgram **apSub = 0; /* Array of sub-vdbes */ - Mem *pSub = 0; /* Memory cell hold array of subprogs */ - sqlite3 *db = p->db; /* The database connection */ - int i; /* Loop counter */ - int rc = SQLITE_OK; /* Return code */ - Mem *pMem = &p->aMem[1]; /* First Mem of result set */ - - assert( p->explain ); - assert( p->magic==VDBE_MAGIC_RUN ); - assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); - - /* Even though this opcode does not use dynamic strings for - ** the result, result columns may become dynamic if the user calls - ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. - */ - releaseMemArray(pMem, 8); - p->pResultSet = 0; - - if( p->rc==SQLITE_NOMEM ){ - /* This happens if a malloc() inside a call to sqlite3_column_text() or - ** sqlite3_column_text16() failed. */ - db->mallocFailed = 1; - return SQLITE_ERROR; - } - - /* When the number of output rows reaches nRow, that means the - ** listing has finished and sqlite3_step() should return SQLITE_DONE. - ** nRow is the sum of the number of rows in the main program, plus - ** the sum of the number of rows in all trigger subprograms encountered - ** so far. The nRow value will increase as new trigger subprograms are - ** encountered, but p->pc will eventually catch up to nRow. - */ - nRow = p->nOp; - if( p->explain==1 ){ - /* The first 8 memory cells are used for the result set. So we will - ** commandeer the 9th cell to use as storage for an array of pointers - ** to trigger subprograms. The VDBE is guaranteed to have at least 9 - ** cells. */ - assert( p->nMem>9 ); - pSub = &p->aMem[9]; - if( pSub->flags&MEM_Blob ){ - /* On the first call to sqlite3_step(), pSub will hold a NULL. It is - ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */ - nSub = pSub->n/sizeof(Vdbe*); - apSub = (SubProgram **)pSub->z; - } - for(i=0; inOp; - } - } - - do{ - i = p->pc++; - }while( iexplain==2 && p->aOp[i].opcode!=OP_Explain ); - if( i>=nRow ){ - p->rc = SQLITE_OK; - rc = SQLITE_DONE; - }else if( db->u1.isInterrupted ){ - p->rc = SQLITE_INTERRUPT; - rc = SQLITE_ERROR; - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc)); - }else{ - char *z; - Op *pOp; - if( inOp ){ - /* The output line number is small enough that we are still in the - ** main program. */ - pOp = &p->aOp[i]; - }else{ - /* We are currently listing subprograms. Figure out which one and - ** pick up the appropriate opcode. */ - int j; - i -= p->nOp; - for(j=0; i>=apSub[j]->nOp; j++){ - i -= apSub[j]->nOp; - } - pOp = &apSub[j]->aOp[i]; - } - if( p->explain==1 ){ - pMem->flags = MEM_Int; - pMem->type = SQLITE_INTEGER; - pMem->u.i = i; /* Program counter */ - pMem++; - - pMem->flags = MEM_Static|MEM_Str|MEM_Term; - pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ - assert( pMem->z!=0 ); - pMem->n = sqlite3Strlen30(pMem->z); - pMem->type = SQLITE_TEXT; - pMem->enc = SQLITE_UTF8; - pMem++; - - /* When an OP_Program opcode is encounter (the only opcode that has - ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms - ** kept in p->aMem[9].z to hold the new program - assuming this subprogram - ** has not already been seen. - */ - if( pOp->p4type==P4_SUBPROGRAM ){ - int nByte = (nSub+1)*sizeof(SubProgram*); - int j; - for(j=0; jp4.pProgram ) break; - } - if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){ - apSub = (SubProgram **)pSub->z; - apSub[nSub++] = pOp->p4.pProgram; - pSub->flags |= MEM_Blob; - pSub->n = nSub*sizeof(SubProgram*); - } - } - } - - pMem->flags = MEM_Int; - pMem->u.i = pOp->p1; /* P1 */ - pMem->type = SQLITE_INTEGER; - pMem++; - - pMem->flags = MEM_Int; - pMem->u.i = pOp->p2; /* P2 */ - pMem->type = SQLITE_INTEGER; - pMem++; - - pMem->flags = MEM_Int; - pMem->u.i = pOp->p3; /* P3 */ - pMem->type = SQLITE_INTEGER; - pMem++; - - if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */ - assert( p->db->mallocFailed ); - return SQLITE_ERROR; - } - pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; - z = displayP4(pOp, pMem->z, 32); - if( z!=pMem->z ){ - sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0); - }else{ - assert( pMem->z!=0 ); - pMem->n = sqlite3Strlen30(pMem->z); - pMem->enc = SQLITE_UTF8; - } - pMem->type = SQLITE_TEXT; - pMem++; - - if( p->explain==1 ){ - if( sqlite3VdbeMemGrow(pMem, 4, 0) ){ - assert( p->db->mallocFailed ); - return SQLITE_ERROR; - } - pMem->flags = MEM_Dyn|MEM_Str|MEM_Term; - pMem->n = 2; - sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ - pMem->type = SQLITE_TEXT; - pMem->enc = SQLITE_UTF8; - pMem++; - -#ifdef SQLITE_DEBUG - if( pOp->zComment ){ - pMem->flags = MEM_Str|MEM_Term; - pMem->z = pOp->zComment; - pMem->n = sqlite3Strlen30(pMem->z); - pMem->enc = SQLITE_UTF8; - pMem->type = SQLITE_TEXT; - }else -#endif - { - pMem->flags = MEM_Null; /* Comment */ - pMem->type = SQLITE_NULL; - } - } - - p->nResColumn = 8 - 4*(p->explain-1); - p->pResultSet = &p->aMem[1]; - p->rc = SQLITE_OK; - rc = SQLITE_ROW; - } - return rc; -} -#endif /* SQLITE_OMIT_EXPLAIN */ - -#ifdef SQLITE_DEBUG -/* -** Print the SQL that was used to generate a VDBE program. -*/ -SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){ - int nOp = p->nOp; - VdbeOp *pOp; - if( nOp<1 ) return; - pOp = &p->aOp[0]; - if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){ - const char *z = pOp->p4.z; - while( sqlite3Isspace(*z) ) z++; - printf("SQL: [%s]\n", z); - } -} -#endif - -#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) -/* -** Print an IOTRACE message showing SQL content. -*/ -SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){ - int nOp = p->nOp; - VdbeOp *pOp; - if( sqlite3IoTrace==0 ) return; - if( nOp<1 ) return; - pOp = &p->aOp[0]; - if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){ - int i, j; - char z[1000]; - sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z); - for(i=0; sqlite3Isspace(z[i]); i++){} - for(j=0; z[i]; i++){ - if( sqlite3Isspace(z[i]) ){ - if( z[i-1]!=' ' ){ - z[j++] = ' '; - } - }else{ - z[j++] = z[i]; - } - } - z[j] = 0; - sqlite3IoTrace("SQL %s\n", z); - } -} -#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ - -/* -** Allocate space from a fixed size buffer and return a pointer to -** that space. If insufficient space is available, return NULL. -** -** The pBuf parameter is the initial value of a pointer which will -** receive the new memory. pBuf is normally NULL. If pBuf is not -** NULL, it means that memory space has already been allocated and that -** this routine should not allocate any new memory. When pBuf is not -** NULL simply return pBuf. Only allocate new memory space when pBuf -** is NULL. -** -** nByte is the number of bytes of space needed. -** -** *ppFrom points to available space and pEnd points to the end of the -** available space. When space is allocated, *ppFrom is advanced past -** the end of the allocated space. -** -** *pnByte is a counter of the number of bytes of space that have failed -** to allocate. If there is insufficient space in *ppFrom to satisfy the -** request, then increment *pnByte by the amount of the request. -*/ -static void *allocSpace( - void *pBuf, /* Where return pointer will be stored */ - int nByte, /* Number of bytes to allocate */ - u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */ - u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */ - int *pnByte /* If allocation cannot be made, increment *pnByte */ -){ - assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) ); - if( pBuf ) return pBuf; - nByte = ROUND8(nByte); - if( &(*ppFrom)[nByte] <= pEnd ){ - pBuf = (void*)*ppFrom; - *ppFrom += nByte; - }else{ - *pnByte += nByte; - } - return pBuf; -} - -/* -** Rewind the VDBE back to the beginning in preparation for -** running it. -*/ -SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ -#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) - int i; -#endif - assert( p!=0 ); - assert( p->magic==VDBE_MAGIC_INIT ); - - /* There should be at least one opcode. - */ - assert( p->nOp>0 ); - - /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */ - p->magic = VDBE_MAGIC_RUN; - -#ifdef SQLITE_DEBUG - for(i=1; inMem; i++){ - assert( p->aMem[i].db==p->db ); - } -#endif - p->pc = -1; - p->rc = SQLITE_OK; - p->errorAction = OE_Abort; - p->magic = VDBE_MAGIC_RUN; - p->nChange = 0; - p->cacheCtr = 1; - p->minWriteFileFormat = 255; - p->iStatement = 0; - p->nFkConstraint = 0; -#ifdef VDBE_PROFILE - for(i=0; inOp; i++){ - p->aOp[i].cnt = 0; - p->aOp[i].cycles = 0; - } -#endif -} - -/* -** Prepare a virtual machine for execution for the first time after -** creating the virtual machine. This involves things such -** as allocating stack space and initializing the program counter. -** After the VDBE has be prepped, it can be executed by one or more -** calls to sqlite3VdbeExec(). -** -** This function may be called exact once on a each virtual machine. -** After this routine is called the VM has been "packaged" and is ready -** to run. After this routine is called, futher calls to -** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects -** the Vdbe from the Parse object that helped generate it so that the -** the Vdbe becomes an independent entity and the Parse object can be -** destroyed. -** -** Use the sqlite3VdbeRewind() procedure to restore a virtual machine back -** to its initial state after it has been run. -*/ -SQLITE_PRIVATE void sqlite3VdbeMakeReady( - Vdbe *p, /* The VDBE */ - Parse *pParse /* Parsing context */ -){ - sqlite3 *db; /* The database connection */ - int nVar; /* Number of parameters */ - int nMem; /* Number of VM memory registers */ - int nCursor; /* Number of cursors required */ - int nArg; /* Number of arguments in subprograms */ - int nOnce; /* Number of OP_Once instructions */ - int n; /* Loop counter */ - u8 *zCsr; /* Memory available for allocation */ - u8 *zEnd; /* First byte past allocated memory */ - int nByte; /* How much extra memory is needed */ - - assert( p!=0 ); - assert( p->nOp>0 ); - assert( pParse!=0 ); - assert( p->magic==VDBE_MAGIC_INIT ); - db = p->db; - assert( db->mallocFailed==0 ); - nVar = pParse->nVar; - nMem = pParse->nMem; - nCursor = pParse->nTab; - nArg = pParse->nMaxArg; - nOnce = pParse->nOnce; - if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */ - - /* For each cursor required, also allocate a memory cell. Memory - ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by - ** the vdbe program. Instead they are used to allocate space for - ** VdbeCursor/BtCursor structures. The blob of memory associated with - ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) - ** stores the blob of memory associated with cursor 1, etc. - ** - ** See also: allocateCursor(). - */ - nMem += nCursor; - - /* Allocate space for memory registers, SQL variables, VDBE cursors and - ** an array to marshal SQL function arguments in. - */ - zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */ - zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past end of zCsr[] */ - - resolveP2Values(p, &nArg); - p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); - if( pParse->explain && nMem<10 ){ - nMem = 10; - } - memset(zCsr, 0, zEnd-zCsr); - zCsr += (zCsr - (u8*)0)&7; - assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); - p->expired = 0; - - /* Memory for registers, parameters, cursor, etc, is allocated in two - ** passes. On the first pass, we try to reuse unused space at the - ** end of the opcode array. If we are unable to satisfy all memory - ** requirements by reusing the opcode array tail, then the second - ** pass will fill in the rest using a fresh allocation. - ** - ** This two-pass approach that reuses as much memory as possible from - ** the leftover space at the end of the opcode array can significantly - ** reduce the amount of memory held by a prepared statement. - */ - do { - nByte = 0; - p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte); - p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte); - p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte); - p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte); - p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*), - &zCsr, zEnd, &nByte); - p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte); - if( nByte ){ - p->pFree = sqlite3DbMallocZero(db, nByte); - } - zCsr = p->pFree; - zEnd = &zCsr[nByte]; - }while( nByte && !db->mallocFailed ); - - p->nCursor = nCursor; - p->nOnceFlag = nOnce; - if( p->aVar ){ - p->nVar = (ynVar)nVar; - for(n=0; naVar[n].flags = MEM_Null; - p->aVar[n].db = db; - } - } - if( p->azVar ){ - p->nzVar = pParse->nzVar; - memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0])); - memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0])); - } - if( p->aMem ){ - p->aMem--; /* aMem[] goes from 1..nMem */ - p->nMem = nMem; /* not from 0..nMem-1 */ - for(n=1; n<=nMem; n++){ - p->aMem[n].flags = MEM_Invalid; - p->aMem[n].db = db; - } - } - p->explain = pParse->explain; - sqlite3VdbeRewind(p); -} - -/* -** Close a VDBE cursor and release all the resources that cursor -** happens to hold. -*/ -SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ - if( pCx==0 ){ - return; - } - sqlite3VdbeSorterClose(p->db, pCx); - if( pCx->pBt ){ - sqlite3BtreeClose(pCx->pBt); - /* The pCx->pCursor will be close automatically, if it exists, by - ** the call above. */ - }else if( pCx->pCursor ){ - sqlite3BtreeCloseCursor(pCx->pCursor); - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( pCx->pVtabCursor ){ - sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; - const sqlite3_module *pModule = pCx->pModule; - p->inVtabMethod = 1; - pModule->xClose(pVtabCursor); - p->inVtabMethod = 0; - } -#endif -} - -/* -** Copy the values stored in the VdbeFrame structure to its Vdbe. This -** is used, for example, when a trigger sub-program is halted to restore -** control to the main program. -*/ -SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ - Vdbe *v = pFrame->v; - v->aOnceFlag = pFrame->aOnceFlag; - v->nOnceFlag = pFrame->nOnceFlag; - v->aOp = pFrame->aOp; - v->nOp = pFrame->nOp; - v->aMem = pFrame->aMem; - v->nMem = pFrame->nMem; - v->apCsr = pFrame->apCsr; - v->nCursor = pFrame->nCursor; - v->db->lastRowid = pFrame->lastRowid; - v->nChange = pFrame->nChange; - return pFrame->pc; -} - -/* -** Close all cursors. -** -** Also release any dynamic memory held by the VM in the Vdbe.aMem memory -** cell array. This is necessary as the memory cell array may contain -** pointers to VdbeFrame objects, which may in turn contain pointers to -** open cursors. -*/ -static void closeAllCursors(Vdbe *p){ - if( p->pFrame ){ - VdbeFrame *pFrame; - for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); - sqlite3VdbeFrameRestore(pFrame); - } - p->pFrame = 0; - p->nFrame = 0; - - if( p->apCsr ){ - int i; - for(i=0; inCursor; i++){ - VdbeCursor *pC = p->apCsr[i]; - if( pC ){ - sqlite3VdbeFreeCursor(p, pC); - p->apCsr[i] = 0; - } - } - } - if( p->aMem ){ - releaseMemArray(&p->aMem[1], p->nMem); - } - while( p->pDelFrame ){ - VdbeFrame *pDel = p->pDelFrame; - p->pDelFrame = pDel->pParent; - sqlite3VdbeFrameDelete(pDel); - } -} - -/* -** Clean up the VM after execution. -** -** This routine will automatically close any cursors, lists, and/or -** sorters that were left open. It also deletes the values of -** variables in the aVar[] array. -*/ -static void Cleanup(Vdbe *p){ - sqlite3 *db = p->db; - -#ifdef SQLITE_DEBUG - /* Execute assert() statements to ensure that the Vdbe.apCsr[] and - ** Vdbe.aMem[] arrays have already been cleaned up. */ - int i; - if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 ); - if( p->aMem ){ - for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid ); - } -#endif - - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; - p->pResultSet = 0; -} - -/* -** Set the number of result columns that will be returned by this SQL -** statement. This is now set at compile time, rather than during -** execution of the vdbe program so that sqlite3_column_count() can -** be called on an SQL statement before sqlite3_step(). -*/ -SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ - Mem *pColName; - int n; - sqlite3 *db = p->db; - - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); - sqlite3DbFree(db, p->aColName); - n = nResColumn*COLNAME_N; - p->nResColumn = (u16)nResColumn; - p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); - if( p->aColName==0 ) return; - while( n-- > 0 ){ - pColName->flags = MEM_Null; - pColName->db = p->db; - pColName++; - } -} - -/* -** Set the name of the idx'th column to be returned by the SQL statement. -** zName must be a pointer to a nul terminated string. -** -** This call must be made after a call to sqlite3VdbeSetNumCols(). -** -** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC -** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed -** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed. -*/ -SQLITE_PRIVATE int sqlite3VdbeSetColName( - Vdbe *p, /* Vdbe being configured */ - int idx, /* Index of column zName applies to */ - int var, /* One of the COLNAME_* constants */ - const char *zName, /* Pointer to buffer containing name */ - void (*xDel)(void*) /* Memory management strategy for zName */ -){ - int rc; - Mem *pColName; - assert( idxnResColumn ); - assert( vardb->mallocFailed ){ - assert( !zName || xDel!=SQLITE_DYNAMIC ); - return SQLITE_NOMEM; - } - assert( p->aColName!=0 ); - pColName = &(p->aColName[idx+var*p->nResColumn]); - rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); - assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); - return rc; -} - -/* -** A read or write transaction may or may not be active on database handle -** db. If a transaction is active, commit it. If there is a -** write-transaction spanning more than one database file, this routine -** takes care of the master journal trickery. -*/ -static int vdbeCommit(sqlite3 *db, Vdbe *p){ - int i; - int nTrans = 0; /* Number of databases with an active write-transaction */ - int rc = SQLITE_OK; - int needXcommit = 0; - -#ifdef SQLITE_OMIT_VIRTUALTABLE - /* With this option, sqlite3VtabSync() is defined to be simply - ** SQLITE_OK so p is not used. - */ - UNUSED_PARAMETER(p); -#endif - - /* Before doing anything else, call the xSync() callback for any - ** virtual module tables written in this transaction. This has to - ** be done before determining whether a master journal file is - ** required, as an xSync() callback may add an attached database - ** to the transaction. - */ - rc = sqlite3VtabSync(db, &p->zErrMsg); - - /* This loop determines (a) if the commit hook should be invoked and - ** (b) how many database files have open write transactions, not - ** including the temp database. (b) is important because if more than - ** one database file has an open write transaction, a master journal - ** file is required for an atomic commit. - */ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( sqlite3BtreeIsInTrans(pBt) ){ - needXcommit = 1; - if( i!=1 ) nTrans++; - sqlite3BtreeEnter(pBt); - rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt)); - sqlite3BtreeLeave(pBt); - } - } - if( rc!=SQLITE_OK ){ - return rc; - } - - /* If there are any write-transactions at all, invoke the commit hook */ - if( needXcommit && db->xCommitCallback ){ - rc = db->xCommitCallback(db->pCommitArg); - if( rc ){ - return SQLITE_CONSTRAINT_COMMITHOOK; - } - } - - /* The simple case - no more than one database file (not counting the - ** TEMP database) has a transaction active. There is no need for the - ** master-journal. - ** - ** If the return value of sqlite3BtreeGetFilename() is a zero length - ** string, it means the main database is :memory: or a temp file. In - ** that case we do not support atomic multi-file commits, so use the - ** simple case then too. - */ - if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt)) - || nTrans<=1 - ){ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = sqlite3BtreeCommitPhaseOne(pBt, 0); - } - } - - /* Do the commit only if all databases successfully complete phase 1. - ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an - ** IO error while deleting or truncating a journal file. It is unlikely, - ** but could happen. In this case abandon processing and return the error. - */ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = sqlite3BtreeCommitPhaseTwo(pBt, 0); - } - } - if( rc==SQLITE_OK ){ - sqlite3VtabCommit(db); - } - } - - /* The complex case - There is a multi-file write-transaction active. - ** This requires a master journal file to ensure the transaction is - ** committed atomicly. - */ -#ifndef SQLITE_OMIT_DISKIO - else{ - sqlite3_vfs *pVfs = db->pVfs; - int needSync = 0; - char *zMaster = 0; /* File-name for the master journal */ - char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt); - sqlite3_file *pMaster = 0; - i64 offset = 0; - int res; - int retryCount = 0; - int nMainFile; - - /* Select a master journal file name */ - nMainFile = sqlite3Strlen30(zMainFile); - zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile); - if( zMaster==0 ) return SQLITE_NOMEM; - do { - u32 iRandom; - if( retryCount ){ - if( retryCount>100 ){ - sqlite3_log(SQLITE_FULL, "MJ delete: %s", zMaster); - sqlite3OsDelete(pVfs, zMaster, 0); - break; - }else if( retryCount==1 ){ - sqlite3_log(SQLITE_FULL, "MJ collide: %s", zMaster); - } - } - retryCount++; - sqlite3_randomness(sizeof(iRandom), &iRandom); - sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X", - (iRandom>>8)&0xffffff, iRandom&0xff); - /* The antipenultimate character of the master journal name must - ** be "9" to avoid name collisions when using 8+3 filenames. */ - assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' ); - sqlite3FileSuffix3(zMainFile, zMaster); - rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res); - }while( rc==SQLITE_OK && res ); - if( rc==SQLITE_OK ){ - /* Open the master journal. */ - rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster, - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| - SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0 - ); - } - if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, zMaster); - return rc; - } - - /* Write the name of each database file in the transaction into the new - ** master journal file. If an error occurs at this point close - ** and delete the master journal file. All the individual journal files - ** still have 'null' as the master journal pointer, so they will roll - ** back independently if a failure occurs. - */ - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( sqlite3BtreeIsInTrans(pBt) ){ - char const *zFile = sqlite3BtreeGetJournalname(pBt); - if( zFile==0 ){ - continue; /* Ignore TEMP and :memory: databases */ - } - assert( zFile[0]!=0 ); - if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ - needSync = 1; - } - rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset); - offset += sqlite3Strlen30(zFile)+1; - if( rc!=SQLITE_OK ){ - sqlite3OsCloseFree(pMaster); - sqlite3OsDelete(pVfs, zMaster, 0); - sqlite3DbFree(db, zMaster); - return rc; - } - } - } - - /* Sync the master journal file. If the IOCAP_SEQUENTIAL device - ** flag is set this is not required. - */ - if( needSync - && 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL) - && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL)) - ){ - sqlite3OsCloseFree(pMaster); - sqlite3OsDelete(pVfs, zMaster, 0); - sqlite3DbFree(db, zMaster); - return rc; - } - - /* Sync all the db files involved in the transaction. The same call - ** sets the master journal pointer in each individual journal. If - ** an error occurs here, do not delete the master journal file. - ** - ** If the error occurs during the first call to - ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the - ** master journal file will be orphaned. But we cannot delete it, - ** in case the master journal file name was written into the journal - ** file before the failure occurred. - */ - for(i=0; rc==SQLITE_OK && inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster); - } - } - sqlite3OsCloseFree(pMaster); - assert( rc!=SQLITE_BUSY ); - if( rc!=SQLITE_OK ){ - sqlite3DbFree(db, zMaster); - return rc; - } - - /* Delete the master journal file. This commits the transaction. After - ** doing this the directory is synced again before any individual - ** transaction files are deleted. - */ - rc = sqlite3OsDelete(pVfs, zMaster, 1); - sqlite3DbFree(db, zMaster); - zMaster = 0; - if( rc ){ - return rc; - } - - /* All files and directories have already been synced, so the following - ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and - ** deleting or truncating journals. If something goes wrong while - ** this is happening we don't really care. The integrity of the - ** transaction is already guaranteed, but some stray 'cold' journals - ** may be lying around. Returning an error code won't help matters. - */ - disable_simulated_io_errors(); - sqlite3BeginBenignMalloc(); - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - sqlite3BtreeCommitPhaseTwo(pBt, 1); - } - } - sqlite3EndBenignMalloc(); - enable_simulated_io_errors(); - - sqlite3VtabCommit(db); - } -#endif - - return rc; -} - -/* -** This routine checks that the sqlite3.activeVdbeCnt count variable -** matches the number of vdbe's in the list sqlite3.pVdbe that are -** currently active. An assertion fails if the two counts do not match. -** This is an internal self-check only - it is not an essential processing -** step. -** -** This is a no-op if NDEBUG is defined. -*/ -#ifndef NDEBUG -static void checkActiveVdbeCnt(sqlite3 *db){ - Vdbe *p; - int cnt = 0; - int nWrite = 0; - p = db->pVdbe; - while( p ){ - if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){ - cnt++; - if( p->readOnly==0 ) nWrite++; - } - p = p->pNext; - } - assert( cnt==db->activeVdbeCnt ); - assert( nWrite==db->writeVdbeCnt ); -} -#else -#define checkActiveVdbeCnt(x) -#endif - -/* -** If the Vdbe passed as the first argument opened a statement-transaction, -** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or -** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement -** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the -** statement transaction is commtted. -** -** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned. -** Otherwise SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ - sqlite3 *const db = p->db; - int rc = SQLITE_OK; - - /* If p->iStatement is greater than zero, then this Vdbe opened a - ** statement transaction that should be closed here. The only exception - ** is that an IO error may have occurred, causing an emergency rollback. - ** In this case (db->nStatement==0), and there is nothing to do. - */ - if( db->nStatement && p->iStatement ){ - int i; - const int iSavepoint = p->iStatement-1; - - assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); - assert( db->nStatement>0 ); - assert( p->iStatement==(db->nStatement+db->nSavepoint) ); - - for(i=0; inDb; i++){ - int rc2 = SQLITE_OK; - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - if( eOp==SAVEPOINT_ROLLBACK ){ - rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint); - } - if( rc2==SQLITE_OK ){ - rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint); - } - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - db->nStatement--; - p->iStatement = 0; - - if( rc==SQLITE_OK ){ - if( eOp==SAVEPOINT_ROLLBACK ){ - rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint); - } - if( rc==SQLITE_OK ){ - rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint); - } - } - - /* If the statement transaction is being rolled back, also restore the - ** database handles deferred constraint counter to the value it had when - ** the statement transaction was opened. */ - if( eOp==SAVEPOINT_ROLLBACK ){ - db->nDeferredCons = p->nStmtDefCons; - } - } - return rc; -} - -/* -** This function is called when a transaction opened by the database -** handle associated with the VM passed as an argument is about to be -** committed. If there are outstanding deferred foreign key constraint -** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK. -** -** If there are outstanding FK violations and this function returns -** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY -** and write an error message to it. Then return SQLITE_ERROR. -*/ -#ifndef SQLITE_OMIT_FOREIGN_KEY -SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ - sqlite3 *db = p->db; - if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){ - p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; - p->errorAction = OE_Abort; - sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed"); - return SQLITE_ERROR; - } - return SQLITE_OK; -} -#endif - -/* -** This routine is called the when a VDBE tries to halt. If the VDBE -** has made changes and is in autocommit mode, then commit those -** changes. If a rollback is needed, then do the rollback. -** -** This routine is the only way to move the state of a VM from -** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to -** call this on a VM that is in the SQLITE_MAGIC_HALT state. -** -** Return an error code. If the commit could not complete because of -** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it -** means the close did not happen and needs to be repeated. -*/ -SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ - int rc; /* Used to store transient return codes */ - sqlite3 *db = p->db; - - /* This function contains the logic that determines if a statement or - ** transaction will be committed or rolled back as a result of the - ** execution of this virtual machine. - ** - ** If any of the following errors occur: - ** - ** SQLITE_NOMEM - ** SQLITE_IOERR - ** SQLITE_FULL - ** SQLITE_INTERRUPT - ** - ** Then the internal cache might have been left in an inconsistent - ** state. We need to rollback the statement transaction, if there is - ** one, or the complete transaction if there is no statement transaction. - */ - - if( p->db->mallocFailed ){ - p->rc = SQLITE_NOMEM; - } - if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); - closeAllCursors(p); - if( p->magic!=VDBE_MAGIC_RUN ){ - return SQLITE_OK; - } - checkActiveVdbeCnt(db); - - /* No commit or rollback needed if the program never started */ - if( p->pc>=0 ){ - int mrc; /* Primary error code from p->rc */ - int eStatementOp = 0; - int isSpecialError; /* Set to true if a 'special' error */ - - /* Lock all btrees used by the statement */ - sqlite3VdbeEnter(p); - - /* Check for one of the special errors */ - mrc = p->rc & 0xff; - assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */ - isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR - || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL; - if( isSpecialError ){ - /* If the query was read-only and the error code is SQLITE_INTERRUPT, - ** no rollback is necessary. Otherwise, at least a savepoint - ** transaction must be rolled back to restore the database to a - ** consistent state. - ** - ** Even if the statement is read-only, it is important to perform - ** a statement or transaction rollback operation. If the error - ** occurred while writing to the journal, sub-journal or database - ** file as part of an effort to free up cache space (see function - ** pagerStress() in pager.c), the rollback is required to restore - ** the pager to a consistent state. - */ - if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ - if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){ - eStatementOp = SAVEPOINT_ROLLBACK; - }else{ - /* We are forced to roll back the active transaction. Before doing - ** so, abort any other statements this handle currently has active. - */ - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; - } - } - } - - /* Check for immediate foreign key violations. */ - if( p->rc==SQLITE_OK ){ - sqlite3VdbeCheckFk(p, 0); - } - - /* If the auto-commit flag is set and this is the only active writer - ** VM, then we do either a commit or rollback of the current transaction. - ** - ** Note: This block also runs if one of the special errors handled - ** above has occurred. - */ - if( !sqlite3VtabInSync(db) - && db->autoCommit - && db->writeVdbeCnt==(p->readOnly==0) - ){ - if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ - rc = sqlite3VdbeCheckFk(p, 1); - if( rc!=SQLITE_OK ){ - if( NEVER(p->readOnly) ){ - sqlite3VdbeLeave(p); - return SQLITE_ERROR; - } - rc = SQLITE_CONSTRAINT_FOREIGNKEY; - }else{ - /* The auto-commit flag is true, the vdbe program was successful - ** or hit an 'OR FAIL' constraint and there are no deferred foreign - ** key constraints to hold up the transaction. This means a commit - ** is required. */ - rc = vdbeCommit(db, p); - } - if( rc==SQLITE_BUSY && p->readOnly ){ - sqlite3VdbeLeave(p); - return SQLITE_BUSY; - }else if( rc!=SQLITE_OK ){ - p->rc = rc; - sqlite3RollbackAll(db, SQLITE_OK); - }else{ - db->nDeferredCons = 0; - sqlite3CommitInternalChanges(db); - } - }else{ - sqlite3RollbackAll(db, SQLITE_OK); - } - db->nStatement = 0; - }else if( eStatementOp==0 ){ - if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ - eStatementOp = SAVEPOINT_RELEASE; - }else if( p->errorAction==OE_Abort ){ - eStatementOp = SAVEPOINT_ROLLBACK; - }else{ - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; - } - } - - /* If eStatementOp is non-zero, then a statement transaction needs to - ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to - ** do so. If this operation returns an error, and the current statement - ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the - ** current statement error code. - */ - if( eStatementOp ){ - rc = sqlite3VdbeCloseStatement(p, eStatementOp); - if( rc ){ - if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){ - p->rc = rc; - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; - } - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - sqlite3CloseSavepoints(db); - db->autoCommit = 1; - } - } - - /* If this was an INSERT, UPDATE or DELETE and no statement transaction - ** has been rolled back, update the database connection change-counter. - */ - if( p->changeCntOn ){ - if( eStatementOp!=SAVEPOINT_ROLLBACK ){ - sqlite3VdbeSetChanges(db, p->nChange); - }else{ - sqlite3VdbeSetChanges(db, 0); - } - p->nChange = 0; - } - - /* Release the locks */ - sqlite3VdbeLeave(p); - } - - /* We have successfully halted and closed the VM. Record this fact. */ - if( p->pc>=0 ){ - db->activeVdbeCnt--; - if( !p->readOnly ){ - db->writeVdbeCnt--; - } - assert( db->activeVdbeCnt>=db->writeVdbeCnt ); - } - p->magic = VDBE_MAGIC_HALT; - checkActiveVdbeCnt(db); - if( p->db->mallocFailed ){ - p->rc = SQLITE_NOMEM; - } - - /* If the auto-commit flag is set to true, then any locks that were held - ** by connection db have now been released. Call sqlite3ConnectionUnlocked() - ** to invoke any required unlock-notify callbacks. - */ - if( db->autoCommit ){ - sqlite3ConnectionUnlocked(db); - } - - assert( db->activeVdbeCnt>0 || db->autoCommit==0 || db->nStatement==0 ); - return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK); -} - - -/* -** Each VDBE holds the result of the most recent sqlite3_step() call -** in p->rc. This routine sets that result back to SQLITE_OK. -*/ -SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){ - p->rc = SQLITE_OK; -} - -/* -** Copy the error code and error message belonging to the VDBE passed -** as the first argument to its database handle (so that they will be -** returned by calls to sqlite3_errcode() and sqlite3_errmsg()). -** -** This function does not clear the VDBE error code or message, just -** copies them to the database handle. -*/ -SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ - sqlite3 *db = p->db; - int rc = p->rc; - if( p->zErrMsg ){ - u8 mallocFailed = db->mallocFailed; - sqlite3BeginBenignMalloc(); - sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); - sqlite3EndBenignMalloc(); - db->mallocFailed = mallocFailed; - db->errCode = rc; - }else{ - sqlite3Error(db, rc, 0); - } - return rc; -} - -#ifdef SQLITE_ENABLE_SQLLOG -/* -** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, -** invoke it. -*/ -static void vdbeInvokeSqllog(Vdbe *v){ - if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){ - char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql); - assert( v->db->init.busy==0 ); - if( zExpanded ){ - sqlite3GlobalConfig.xSqllog( - sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1 - ); - sqlite3DbFree(v->db, zExpanded); - } - } -} -#else -# define vdbeInvokeSqllog(x) -#endif - -/* -** Clean up a VDBE after execution but do not delete the VDBE just yet. -** Write any error messages into *pzErrMsg. Return the result code. -** -** After this routine is run, the VDBE should be ready to be executed -** again. -** -** To look at it another way, this routine resets the state of the -** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to -** VDBE_MAGIC_INIT. -*/ -SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ - sqlite3 *db; - db = p->db; - - /* If the VM did not run to completion or if it encountered an - ** error, then it might not have been halted properly. So halt - ** it now. - */ - sqlite3VdbeHalt(p); - - /* If the VDBE has be run even partially, then transfer the error code - ** and error message from the VDBE into the main database structure. But - ** if the VDBE has just been set to run but has not actually executed any - ** instructions yet, leave the main database error information unchanged. - */ - if( p->pc>=0 ){ - vdbeInvokeSqllog(p); - sqlite3VdbeTransferError(p); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; - if( p->runOnlyOnce ) p->expired = 1; - }else if( p->rc && p->expired ){ - /* The expired flag was set on the VDBE before the first call - ** to sqlite3_step(). For consistency (since sqlite3_step() was - ** called), set the database error in this case as well. - */ - sqlite3Error(db, p->rc, 0); - sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; - } - - /* Reclaim all memory used by the VDBE - */ - Cleanup(p); - - /* Save profiling information from this VDBE run. - */ -#ifdef VDBE_PROFILE - { - FILE *out = fopen("vdbe_profile.out", "a"); - if( out ){ - int i; - fprintf(out, "---- "); - for(i=0; inOp; i++){ - fprintf(out, "%02x", p->aOp[i].opcode); - } - fprintf(out, "\n"); - for(i=0; inOp; i++){ - fprintf(out, "%6d %10lld %8lld ", - p->aOp[i].cnt, - p->aOp[i].cycles, - p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 - ); - sqlite3VdbePrintOp(out, i, &p->aOp[i]); - } - fclose(out); - } - } -#endif - p->magic = VDBE_MAGIC_INIT; - return p->rc & db->errMask; -} - -/* -** Clean up and delete a VDBE after execution. Return an integer which is -** the result code. Write any error message text into *pzErrMsg. -*/ -SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){ - int rc = SQLITE_OK; - if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){ - rc = sqlite3VdbeReset(p); - assert( (rc & p->db->errMask)==rc ); - } - sqlite3VdbeDelete(p); - return rc; -} - -/* -** Call the destructor for each auxdata entry in pVdbeFunc for which -** the corresponding bit in mask is clear. Auxdata entries beyond 31 -** are always destroyed. To destroy all auxdata entries, call this -** routine with mask==0. -*/ -SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){ - int i; - for(i=0; inAux; i++){ - struct AuxData *pAux = &pVdbeFunc->apAux[i]; - if( (i>31 || !(mask&(((u32)1)<pAux ){ - if( pAux->xDelete ){ - pAux->xDelete(pAux->pAux); - } - pAux->pAux = 0; - } - } -} - -/* -** Free all memory associated with the Vdbe passed as the second argument, -** except for object itself, which is preserved. -** -** The difference between this function and sqlite3VdbeDelete() is that -** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with -** the database connection and frees the object itself. -*/ -SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ - SubProgram *pSub, *pNext; - int i; - assert( p->db==0 || p->db==db ); - releaseMemArray(p->aVar, p->nVar); - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); - for(pSub=p->pProgram; pSub; pSub=pNext){ - pNext = pSub->pNext; - vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); - sqlite3DbFree(db, pSub); - } - for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); - vdbeFreeOpArray(db, p->aOp, p->nOp); - sqlite3DbFree(db, p->aLabel); - sqlite3DbFree(db, p->aColName); - sqlite3DbFree(db, p->zSql); - sqlite3DbFree(db, p->pFree); -#if defined(SQLITE_ENABLE_TREE_EXPLAIN) - sqlite3DbFree(db, p->zExplain); - sqlite3DbFree(db, p->pExplain); -#endif -} - -/* -** Delete an entire VDBE. -*/ -SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ - sqlite3 *db; - - if( NEVER(p==0) ) return; - db = p->db; - assert( sqlite3_mutex_held(db->mutex) ); - sqlite3VdbeClearObject(db, p); - if( p->pPrev ){ - p->pPrev->pNext = p->pNext; - }else{ - assert( db->pVdbe==p ); - db->pVdbe = p->pNext; - } - if( p->pNext ){ - p->pNext->pPrev = p->pPrev; - } - p->magic = VDBE_MAGIC_DEAD; - p->db = 0; - sqlite3DbFree(db, p); -} - -/* -** Make sure the cursor p is ready to read or write the row to which it -** was last positioned. Return an error code if an OOM fault or I/O error -** prevents us from positioning the cursor to its correct position. -** -** If a MoveTo operation is pending on the given cursor, then do that -** MoveTo now. If no move is pending, check to see if the row has been -** deleted out from under the cursor and if it has, mark the row as -** a NULL row. -** -** If the cursor is already pointing to the correct row and that row has -** not been deleted out from under the cursor, then this routine is a no-op. -*/ -SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ - if( p->deferredMoveto ){ - int res, rc; -#ifdef SQLITE_TEST - extern int sqlite3_search_count; -#endif - assert( p->isTable ); - rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); - if( rc ) return rc; - p->lastRowid = p->movetoTarget; - if( res!=0 ) return SQLITE_CORRUPT_BKPT; - p->rowidIsValid = 1; -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - p->deferredMoveto = 0; - p->cacheStatus = CACHE_STALE; - }else if( ALWAYS(p->pCursor) ){ - int hasMoved; - int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved); - if( rc ) return rc; - if( hasMoved ){ - p->cacheStatus = CACHE_STALE; - p->nullRow = 1; - } - } - return SQLITE_OK; -} - -/* -** The following functions: -** -** sqlite3VdbeSerialType() -** sqlite3VdbeSerialTypeLen() -** sqlite3VdbeSerialLen() -** sqlite3VdbeSerialPut() -** sqlite3VdbeSerialGet() -** -** encapsulate the code that serializes values for storage in SQLite -** data and index records. Each serialized value consists of a -** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned -** integer, stored as a varint. -** -** In an SQLite index record, the serial type is stored directly before -** the blob of data that it corresponds to. In a table record, all serial -** types are stored at the start of the record, and the blobs of data at -** the end. Hence these functions allow the caller to handle the -** serial-type and data blob separately. -** -** The following table describes the various storage classes for data: -** -** serial type bytes of data type -** -------------- --------------- --------------- -** 0 0 NULL -** 1 1 signed integer -** 2 2 signed integer -** 3 3 signed integer -** 4 4 signed integer -** 5 6 signed integer -** 6 8 signed integer -** 7 8 IEEE float -** 8 0 Integer constant 0 -** 9 0 Integer constant 1 -** 10,11 reserved for expansion -** N>=12 and even (N-12)/2 BLOB -** N>=13 and odd (N-13)/2 text -** -** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions -** of SQLite will not understand those serial types. -*/ - -/* -** Return the serial-type for the value stored in pMem. -*/ -SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){ - int flags = pMem->flags; - int n; - - if( flags&MEM_Null ){ - return 0; - } - if( flags&MEM_Int ){ - /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ -# define MAX_6BYTE ((((i64)0x00008000)<<32)-1) - i64 i = pMem->u.i; - u64 u; - if( i<0 ){ - if( i<(-MAX_6BYTE) ) return 6; - /* Previous test prevents: u = -(-9223372036854775808) */ - u = -i; - }else{ - u = i; - } - if( u<=127 ){ - return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1; - } - if( u<=32767 ) return 2; - if( u<=8388607 ) return 3; - if( u<=2147483647 ) return 4; - if( u<=MAX_6BYTE ) return 5; - return 6; - } - if( flags&MEM_Real ){ - return 7; - } - assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) ); - n = pMem->n; - if( flags & MEM_Zero ){ - n += pMem->u.nZero; - } - assert( n>=0 ); - return ((n*2) + 12 + ((flags&MEM_Str)!=0)); -} - -/* -** Return the length of the data corresponding to the supplied serial-type. -*/ -SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32 serial_type){ - if( serial_type>=12 ){ - return (serial_type-12)/2; - }else{ - static const u8 aSize[] = { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 }; - return aSize[serial_type]; - } -} - -/* -** If we are on an architecture with mixed-endian floating -** points (ex: ARM7) then swap the lower 4 bytes with the -** upper 4 bytes. Return the result. -** -** For most architectures, this is a no-op. -** -** (later): It is reported to me that the mixed-endian problem -** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems -** that early versions of GCC stored the two words of a 64-bit -** float in the wrong order. And that error has been propagated -** ever since. The blame is not necessarily with GCC, though. -** GCC might have just copying the problem from a prior compiler. -** I am also told that newer versions of GCC that follow a different -** ABI get the byte order right. -** -** Developers using SQLite on an ARM7 should compile and run their -** application using -DSQLITE_DEBUG=1 at least once. With DEBUG -** enabled, some asserts below will ensure that the byte order of -** floating point values is correct. -** -** (2007-08-30) Frank van Vugt has studied this problem closely -** and has send his findings to the SQLite developers. Frank -** writes that some Linux kernels offer floating point hardware -** emulation that uses only 32-bit mantissas instead of a full -** 48-bits as required by the IEEE standard. (This is the -** CONFIG_FPE_FASTFPE option.) On such systems, floating point -** byte swapping becomes very complicated. To avoid problems, -** the necessary byte swapping is carried out using a 64-bit integer -** rather than a 64-bit float. Frank assures us that the code here -** works for him. We, the developers, have no way to independently -** verify this, but Frank seems to know what he is talking about -** so we trust him. -*/ -#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT -static u64 floatSwap(u64 in){ - union { - u64 r; - u32 i[2]; - } u; - u32 t; - - u.r = in; - t = u.i[0]; - u.i[0] = u.i[1]; - u.i[1] = t; - return u.r; -} -# define swapMixedEndianFloat(X) X = floatSwap(X) -#else -# define swapMixedEndianFloat(X) -#endif - -/* -** Write the serialized data blob for the value stored in pMem into -** buf. It is assumed that the caller has allocated sufficient space. -** Return the number of bytes written. -** -** nBuf is the amount of space left in buf[]. nBuf must always be -** large enough to hold the entire field. Except, if the field is -** a blob with a zero-filled tail, then buf[] might be just the right -** size to hold everything except for the zero-filled tail. If buf[] -** is only big enough to hold the non-zero prefix, then only write that -** prefix into buf[]. But if buf[] is large enough to hold both the -** prefix and the tail then write the prefix and set the tail to all -** zeros. -** -** Return the number of bytes actually written into buf[]. The number -** of bytes in the zero-filled tail is included in the return value only -** if those bytes were zeroed in buf[]. -*/ -SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){ - u32 serial_type = sqlite3VdbeSerialType(pMem, file_format); - u32 len; - - /* Integer and Real */ - if( serial_type<=7 && serial_type>0 ){ - u64 v; - u32 i; - if( serial_type==7 ){ - assert( sizeof(v)==sizeof(pMem->r) ); - memcpy(&v, &pMem->r, sizeof(v)); - swapMixedEndianFloat(v); - }else{ - v = pMem->u.i; - } - len = i = sqlite3VdbeSerialTypeLen(serial_type); - assert( len<=(u32)nBuf ); - while( i-- ){ - buf[i] = (u8)(v&0xFF); - v >>= 8; - } - return len; - } - - /* String or blob */ - if( serial_type>=12 ){ - assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) - == (int)sqlite3VdbeSerialTypeLen(serial_type) ); - assert( pMem->n<=nBuf ); - len = pMem->n; - memcpy(buf, pMem->z, len); - if( pMem->flags & MEM_Zero ){ - len += pMem->u.nZero; - assert( nBuf>=0 ); - if( len > (u32)nBuf ){ - len = (u32)nBuf; - } - memset(&buf[pMem->n], 0, len-pMem->n); - } - return len; - } - - /* NULL or constants 0 or 1 */ - return 0; -} - -/* -** Deserialize the data blob pointed to by buf as serial type serial_type -** and store the result in pMem. Return the number of bytes read. -*/ -SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( - const unsigned char *buf, /* Buffer to deserialize from */ - u32 serial_type, /* Serial type to deserialize */ - Mem *pMem /* Memory cell to write value into */ -){ - switch( serial_type ){ - case 10: /* Reserved for future use */ - case 11: /* Reserved for future use */ - case 0: { /* NULL */ - pMem->flags = MEM_Null; - break; - } - case 1: { /* 1-byte signed integer */ - pMem->u.i = (signed char)buf[0]; - pMem->flags = MEM_Int; - return 1; - } - case 2: { /* 2-byte signed integer */ - pMem->u.i = (((signed char)buf[0])<<8) | buf[1]; - pMem->flags = MEM_Int; - return 2; - } - case 3: { /* 3-byte signed integer */ - pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2]; - pMem->flags = MEM_Int; - return 3; - } - case 4: { /* 4-byte signed integer */ - pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; - pMem->flags = MEM_Int; - return 4; - } - case 5: { /* 6-byte signed integer */ - u64 x = (((signed char)buf[0])<<8) | buf[1]; - u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5]; - x = (x<<32) | y; - pMem->u.i = *(i64*)&x; - pMem->flags = MEM_Int; - return 6; - } - case 6: /* 8-byte signed integer */ - case 7: { /* IEEE floating point */ - u64 x; - u32 y; -#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) - /* Verify that integers and floating point values use the same - ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is - ** defined that 64-bit floating point values really are mixed - ** endian. - */ - static const u64 t1 = ((u64)0x3ff00000)<<32; - static const double r1 = 1.0; - u64 t2 = t1; - swapMixedEndianFloat(t2); - assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); -#endif - - x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; - y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7]; - x = (x<<32) | y; - if( serial_type==6 ){ - pMem->u.i = *(i64*)&x; - pMem->flags = MEM_Int; - }else{ - assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->r, &x, sizeof(x)); - pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; - } - return 8; - } - case 8: /* Integer 0 */ - case 9: { /* Integer 1 */ - pMem->u.i = serial_type-8; - pMem->flags = MEM_Int; - return 0; - } - default: { - u32 len = (serial_type-12)/2; - pMem->z = (char *)buf; - pMem->n = len; - pMem->xDel = 0; - if( serial_type&0x01 ){ - pMem->flags = MEM_Str | MEM_Ephem; - }else{ - pMem->flags = MEM_Blob | MEM_Ephem; - } - return len; - } - } - return 0; -} - -/* -** This routine is used to allocate sufficient space for an UnpackedRecord -** structure large enough to be used with sqlite3VdbeRecordUnpack() if -** the first argument is a pointer to KeyInfo structure pKeyInfo. -** -** The space is either allocated using sqlite3DbMallocRaw() or from within -** the unaligned buffer passed via the second and third arguments (presumably -** stack space). If the former, then *ppFree is set to a pointer that should -** be eventually freed by the caller using sqlite3DbFree(). Or, if the -** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL -** before returning. -** -** If an OOM error occurs, NULL is returned. -*/ -SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( - KeyInfo *pKeyInfo, /* Description of the record */ - char *pSpace, /* Unaligned space available */ - int szSpace, /* Size of pSpace[] in bytes */ - char **ppFree /* OUT: Caller should free this pointer */ -){ - UnpackedRecord *p; /* Unpacked record to return */ - int nOff; /* Increment pSpace by nOff to align it */ - int nByte; /* Number of bytes required for *p */ - - /* We want to shift the pointer pSpace up such that it is 8-byte aligned. - ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift - ** it by. If pSpace is already 8-byte aligned, nOff should be zero. - */ - nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7; - nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); - if( nByte>szSpace+nOff ){ - p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); - *ppFree = (char *)p; - if( !p ) return 0; - }else{ - p = (UnpackedRecord*)&pSpace[nOff]; - *ppFree = 0; - } - - p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; - assert( pKeyInfo->aSortOrder!=0 ); - p->pKeyInfo = pKeyInfo; - p->nField = pKeyInfo->nField + 1; - return p; -} - -/* -** Given the nKey-byte encoding of a record in pKey[], populate the -** UnpackedRecord structure indicated by the fourth argument with the -** contents of the decoded record. -*/ -SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( - KeyInfo *pKeyInfo, /* Information about the record format */ - int nKey, /* Size of the binary record */ - const void *pKey, /* The binary record */ - UnpackedRecord *p /* Populate this structure before returning. */ -){ - const unsigned char *aKey = (const unsigned char *)pKey; - int d; - u32 idx; /* Offset in aKey[] to read from */ - u16 u; /* Unsigned loop counter */ - u32 szHdr; - Mem *pMem = p->aMem; - - p->flags = 0; - assert( EIGHT_BYTE_ALIGNMENT(pMem) ); - idx = getVarint32(aKey, szHdr); - d = szHdr; - u = 0; - while( idxnField && d<=nKey ){ - u32 serial_type; - - idx += getVarint32(&aKey[idx], serial_type); - pMem->enc = pKeyInfo->enc; - pMem->db = pKeyInfo->db; - /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ - pMem->zMalloc = 0; - d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); - pMem++; - u++; - } - assert( u<=pKeyInfo->nField + 1 ); - p->nField = u; -} - -/* -** This function compares the two table rows or index records -** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero -** or positive integer if key1 is less than, equal to or -** greater than key2. The {nKey1, pKey1} key must be a blob -** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 -** key must be a parsed key such as obtained from -** sqlite3VdbeParseRecord. -** -** Key1 and Key2 do not have to contain the same number of fields. -** The key with fewer fields is usually compares less than the -** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set -** and the common prefixes are equal, then key1 is less than key2. -** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are -** equal, then the keys are considered to be equal and -** the parts beyond the common prefix are ignored. -*/ -SQLITE_PRIVATE int sqlite3VdbeRecordCompare( - int nKey1, const void *pKey1, /* Left key */ - UnpackedRecord *pPKey2 /* Right key */ -){ - int d1; /* Offset into aKey[] of next data element */ - u32 idx1; /* Offset into aKey[] of next header element */ - u32 szHdr1; /* Number of bytes in header */ - int i = 0; - int nField; - int rc = 0; - const unsigned char *aKey1 = (const unsigned char *)pKey1; - KeyInfo *pKeyInfo; - Mem mem1; - - pKeyInfo = pPKey2->pKeyInfo; - mem1.enc = pKeyInfo->enc; - mem1.db = pKeyInfo->db; - /* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */ - VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */ - - /* Compilers may complain that mem1.u.i is potentially uninitialized. - ** We could initialize it, as shown here, to silence those complaints. - ** But in fact, mem1.u.i will never actually be used uninitialized, and doing - ** the unnecessary initialization has a measurable negative performance - ** impact, since this routine is a very high runner. And so, we choose - ** to ignore the compiler warnings and leave this variable uninitialized. - */ - /* mem1.u.i = 0; // not needed, here to silence compiler warning */ - - idx1 = getVarint32(aKey1, szHdr1); - d1 = szHdr1; - nField = pKeyInfo->nField; - assert( pKeyInfo->aSortOrder!=0 ); - while( idx1nField ){ - u32 serial_type1; - - /* Read the serial types for the next element in each key. */ - idx1 += getVarint32( aKey1+idx1, serial_type1 ); - if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; - - /* Extract the values to be compared. - */ - d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); - - /* Do the comparison - */ - rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], - iaColl[i] : 0); - if( rc!=0 ){ - assert( mem1.zMalloc==0 ); /* See comment below */ - - /* Invert the result if we are using DESC sort order. */ - if( iaSortOrder[i] ){ - rc = -rc; - } - - /* If the PREFIX_SEARCH flag is set and all fields except the final - ** rowid field were equal, then clear the PREFIX_SEARCH flag and set - ** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1). - ** This is used by the OP_IsUnique opcode. - */ - if( (pPKey2->flags & UNPACKED_PREFIX_SEARCH) && i==(pPKey2->nField-1) ){ - assert( idx1==szHdr1 && rc ); - assert( mem1.flags & MEM_Int ); - pPKey2->flags &= ~UNPACKED_PREFIX_SEARCH; - pPKey2->rowid = mem1.u.i; - } - - return rc; - } - i++; - } - - /* No memory allocation is ever used on mem1. Prove this using - ** the following assert(). If the assert() fails, it indicates a - ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). - */ - assert( mem1.zMalloc==0 ); - - /* rc==0 here means that one of the keys ran out of fields and - ** all the fields up to that point were equal. If the UNPACKED_INCRKEY - ** flag is set, then break the tie by treating key2 as larger. - ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes - ** are considered to be equal. Otherwise, the longer key is the - ** larger. As it happens, the pPKey2 will always be the longer - ** if there is a difference. - */ - assert( rc==0 ); - if( pPKey2->flags & UNPACKED_INCRKEY ){ - rc = -1; - }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){ - /* Leave rc==0 */ - }else if( idx1m.n) ){ - goto idx_rowid_corruption; - } - - /* The last field of the index should be an integer - the ROWID. - ** Verify that the last entry really is an integer. */ - (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid); - testcase( typeRowid==1 ); - testcase( typeRowid==2 ); - testcase( typeRowid==3 ); - testcase( typeRowid==4 ); - testcase( typeRowid==5 ); - testcase( typeRowid==6 ); - testcase( typeRowid==8 ); - testcase( typeRowid==9 ); - if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){ - goto idx_rowid_corruption; - } - lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); - testcase( (u32)m.n==szHdr+lenRowid ); - if( unlikely((u32)m.npCursor; - Mem m; - - assert( sqlite3BtreeCursorIsValid(pCur) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); - assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ - /* nCellKey will always be between 0 and 0xffffffff because of the say - ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ - if( nCellKey<=0 || nCellKey>0x7fffffff ){ - *res = 0; - return SQLITE_CORRUPT_BKPT; - } - memset(&m, 0, sizeof(m)); - rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m); - if( rc ){ - return rc; - } - assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH ); - *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); - sqlite3VdbeMemRelease(&m); - return SQLITE_OK; -} - -/* -** This routine sets the value to be returned by subsequent calls to -** sqlite3_changes() on the database handle 'db'. -*/ -SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){ - assert( sqlite3_mutex_held(db->mutex) ); - db->nChange = nChange; - db->nTotalChange += nChange; -} - -/* -** Set a flag in the vdbe to update the change counter when it is finalised -** or reset. -*/ -SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){ - v->changeCntOn = 1; -} - -/* -** Mark every prepared statement associated with a database connection -** as expired. -** -** An expired statement means that recompilation of the statement is -** recommend. Statements expire when things happen that make their -** programs obsolete. Removing user-defined functions or collating -** sequences, or changing an authorization function are the types of -** things that make prepared statements obsolete. -*/ -SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db){ - Vdbe *p; - for(p = db->pVdbe; p; p=p->pNext){ - p->expired = 1; - } -} - -/* -** Return the database associated with the Vdbe. -*/ -SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){ - return v->db; -} - -/* -** Return a pointer to an sqlite3_value structure containing the value bound -** parameter iVar of VM v. Except, if the value is an SQL NULL, return -** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_* -** constants) to the value before returning it. -** -** The returned value must be freed by the caller using sqlite3ValueFree(). -*/ -SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe *v, int iVar, u8 aff){ - assert( iVar>0 ); - if( v ){ - Mem *pMem = &v->aVar[iVar-1]; - if( 0==(pMem->flags & MEM_Null) ){ - sqlite3_value *pRet = sqlite3ValueNew(v->db); - if( pRet ){ - sqlite3VdbeMemCopy((Mem *)pRet, pMem); - sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8); - sqlite3VdbeMemStoreType((Mem *)pRet); - } - return pRet; - } - } - return 0; -} - -/* -** Configure SQL variable iVar so that binding a new value to it signals -** to sqlite3_reoptimize() that re-preparing the statement may result -** in a better query plan. -*/ -SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ - assert( iVar>0 ); - if( iVar>32 ){ - v->expmask = 0xffffffff; - }else{ - v->expmask |= ((u32)1 << (iVar-1)); - } -} - -/************** End of vdbeaux.c *********************************************/ -/************** Begin file vdbeapi.c *****************************************/ -/* -** 2004 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code use to implement APIs that are part of the -** VDBE. -*/ - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Return TRUE (non-zero) of the statement supplied as an argument needs -** to be recompiled. A statement needs to be recompiled whenever the -** execution environment changes in a way that would alter the program -** that sqlite3_prepare() generates. For example, if new functions or -** collating sequences are registered or if an authorizer function is -** added or changed. -*/ -SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe*)pStmt; - return p==0 || p->expired; -} -#endif - -/* -** Check on a Vdbe to make sure it has not been finalized. Log -** an error and return true if it has been finalized (or is otherwise -** invalid). Return false if it is ok. -*/ -static int vdbeSafety(Vdbe *p){ - if( p->db==0 ){ - sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement"); - return 1; - }else{ - return 0; - } -} -static int vdbeSafetyNotNull(Vdbe *p){ - if( p==0 ){ - sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement"); - return 1; - }else{ - return vdbeSafety(p); - } -} - -/* -** The following routine destroys a virtual machine that is created by -** the sqlite3_compile() routine. The integer returned is an SQLITE_ -** success/failure code that describes the result of executing the virtual -** machine. -** -** This routine sets the error code and string returned by -** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). -*/ -SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ - int rc; - if( pStmt==0 ){ - /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL - ** pointer is a harmless no-op. */ - rc = SQLITE_OK; - }else{ - Vdbe *v = (Vdbe*)pStmt; - sqlite3 *db = v->db; - if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; - sqlite3_mutex_enter(db->mutex); - rc = sqlite3VdbeFinalize(v); - rc = sqlite3ApiExit(db, rc); - sqlite3LeaveMutexAndCloseZombie(db); - } - return rc; -} - -/* -** Terminate the current execution of an SQL statement and reset it -** back to its starting state so that it can be reused. A success code from -** the prior execution is returned. -** -** This routine sets the error code and string returned by -** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). -*/ -SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ - int rc; - if( pStmt==0 ){ - rc = SQLITE_OK; - }else{ - Vdbe *v = (Vdbe*)pStmt; - sqlite3_mutex_enter(v->db->mutex); - rc = sqlite3VdbeReset(v); - sqlite3VdbeRewind(v); - assert( (rc & (v->db->errMask))==rc ); - rc = sqlite3ApiExit(v->db, rc); - sqlite3_mutex_leave(v->db->mutex); - } - return rc; -} - -/* -** Set all the parameters in the compiled SQL statement to NULL. -*/ -SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ - int i; - int rc = SQLITE_OK; - Vdbe *p = (Vdbe*)pStmt; -#if SQLITE_THREADSAFE - sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; -#endif - sqlite3_mutex_enter(mutex); - for(i=0; inVar; i++){ - sqlite3VdbeMemRelease(&p->aVar[i]); - p->aVar[i].flags = MEM_Null; - } - if( p->isPrepareV2 && p->expmask ){ - p->expired = 1; - } - sqlite3_mutex_leave(mutex); - return rc; -} - - -/**************************** sqlite3_value_ ******************************* -** The following routines extract information from a Mem or sqlite3_value -** structure. -*/ -SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){ - Mem *p = (Mem*)pVal; - if( p->flags & (MEM_Blob|MEM_Str) ){ - sqlite3VdbeMemExpandBlob(p); - p->flags &= ~MEM_Str; - p->flags |= MEM_Blob; - return p->n ? p->z : 0; - }else{ - return sqlite3_value_text(pVal); - } -} -SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){ - return sqlite3ValueBytes(pVal, SQLITE_UTF8); -} -SQLITE_API int sqlite3_value_bytes16(sqlite3_value *pVal){ - return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE); -} -SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){ - return sqlite3VdbeRealValue((Mem*)pVal); -} -SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){ - return (int)sqlite3VdbeIntValue((Mem*)pVal); -} -SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ - return sqlite3VdbeIntValue((Mem*)pVal); -} -SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ - return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_value_text16(sqlite3_value* pVal){ - return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); -} -SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *pVal){ - return sqlite3ValueText(pVal, SQLITE_UTF16BE); -} -SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){ - return sqlite3ValueText(pVal, SQLITE_UTF16LE); -} -#endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ - return pVal->type; -} - -/**************************** sqlite3_result_ ******************************* -** The following routines are used by user-defined functions to specify -** the function result. -** -** The setStrOrError() funtion calls sqlite3VdbeMemSetStr() to store the -** result as a string or blob but if the string or blob is too large, it -** then sets the error code to SQLITE_TOOBIG -*/ -static void setResultStrOrError( - sqlite3_context *pCtx, /* Function context */ - const char *z, /* String pointer */ - int n, /* Bytes in string, or negative */ - u8 enc, /* Encoding of z. 0 for BLOBs */ - void (*xDel)(void*) /* Destructor function */ -){ - if( sqlite3VdbeMemSetStr(&pCtx->s, z, n, enc, xDel)==SQLITE_TOOBIG ){ - sqlite3_result_error_toobig(pCtx); - } -} -SQLITE_API void sqlite3_result_blob( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( n>=0 ); - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - setResultStrOrError(pCtx, z, n, 0, xDel); -} -SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetDouble(&pCtx->s, rVal); -} -SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - pCtx->isError = SQLITE_ERROR; - sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - pCtx->isError = SQLITE_ERROR; - sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); -} -#endif -SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal); -} -SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetInt64(&pCtx->s, iVal); -} -SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetNull(&pCtx->s); -} -SQLITE_API void sqlite3_result_text( - sqlite3_context *pCtx, - const char *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API void sqlite3_result_text16( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); -} -SQLITE_API void sqlite3_result_text16be( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); -} -SQLITE_API void sqlite3_result_text16le( - sqlite3_context *pCtx, - const void *z, - int n, - void (*xDel)(void *) -){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); -} -#endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemCopy(&pCtx->s, pValue); -} -SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetZeroBlob(&pCtx->s, n); -} -SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ - pCtx->isError = errCode; - if( pCtx->s.flags & MEM_Null ){ - sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1, - SQLITE_UTF8, SQLITE_STATIC); - } -} - -/* Force an SQLITE_TOOBIG error. */ -SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - pCtx->isError = SQLITE_TOOBIG; - sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, - SQLITE_UTF8, SQLITE_STATIC); -} - -/* An SQLITE_NOMEM error. */ -SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetNull(&pCtx->s); - pCtx->isError = SQLITE_NOMEM; - pCtx->s.db->mallocFailed = 1; -} - -/* -** This function is called after a transaction has been committed. It -** invokes callbacks registered with sqlite3_wal_hook() as required. -*/ -static int doWalCallbacks(sqlite3 *db){ - int rc = SQLITE_OK; -#ifndef SQLITE_OMIT_WAL - int i; - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); - if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ - rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); - } - } - } -#endif - return rc; -} - -/* -** Execute the statement pStmt, either until a row of data is ready, the -** statement is completely executed or an error occurs. -** -** This routine implements the bulk of the logic behind the sqlite_step() -** API. The only thing omitted is the automatic recompile if a -** schema change has occurred. That detail is handled by the -** outer sqlite3_step() wrapper procedure. -*/ -static int sqlite3Step(Vdbe *p){ - sqlite3 *db; - int rc; - - assert(p); - if( p->magic!=VDBE_MAGIC_RUN ){ - /* We used to require that sqlite3_reset() be called before retrying - ** sqlite3_step() after any error or after SQLITE_DONE. But beginning - ** with version 3.7.0, we changed this so that sqlite3_reset() would - ** be called automatically instead of throwing the SQLITE_MISUSE error. - ** This "automatic-reset" change is not technically an incompatibility, - ** since any application that receives an SQLITE_MISUSE is broken by - ** definition. - ** - ** Nevertheless, some published applications that were originally written - ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE - ** returns, and those were broken by the automatic-reset change. As a - ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the - ** legacy behavior of returning SQLITE_MISUSE for cases where the - ** previous sqlite3_step() returned something other than a SQLITE_LOCKED - ** or SQLITE_BUSY error. - */ -#ifdef SQLITE_OMIT_AUTORESET - if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){ - sqlite3_reset((sqlite3_stmt*)p); - }else{ - return SQLITE_MISUSE_BKPT; - } -#else - sqlite3_reset((sqlite3_stmt*)p); -#endif - } - - /* Check that malloc() has not failed. If it has, return early. */ - db = p->db; - if( db->mallocFailed ){ - p->rc = SQLITE_NOMEM; - return SQLITE_NOMEM; - } - - if( p->pc<=0 && p->expired ){ - p->rc = SQLITE_SCHEMA; - rc = SQLITE_ERROR; - goto end_of_step; - } - if( p->pc<0 ){ - /* If there are no other statements currently running, then - ** reset the interrupt flag. This prevents a call to sqlite3_interrupt - ** from interrupting a statement that has not yet started. - */ - if( db->activeVdbeCnt==0 ){ - db->u1.isInterrupted = 0; - } - - assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 ); - -#ifndef SQLITE_OMIT_TRACE - if( db->xProfile && !db->init.busy ){ - sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); - } -#endif - - db->activeVdbeCnt++; - if( p->readOnly==0 ) db->writeVdbeCnt++; - p->pc = 0; - } -#ifndef SQLITE_OMIT_EXPLAIN - if( p->explain ){ - rc = sqlite3VdbeList(p); - }else -#endif /* SQLITE_OMIT_EXPLAIN */ - { - db->vdbeExecCnt++; - rc = sqlite3VdbeExec(p); - db->vdbeExecCnt--; - } - -#ifndef SQLITE_OMIT_TRACE - /* Invoke the profile callback if there is one - */ - if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ - sqlite3_int64 iNow; - sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); - db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000); - } -#endif - - if( rc==SQLITE_DONE ){ - assert( p->rc==SQLITE_OK ); - p->rc = doWalCallbacks(db); - if( p->rc!=SQLITE_OK ){ - rc = SQLITE_ERROR; - } - } - - db->errCode = rc; - if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){ - p->rc = SQLITE_NOMEM; - } -end_of_step: - /* At this point local variable rc holds the value that should be - ** returned if this statement was compiled using the legacy - ** sqlite3_prepare() interface. According to the docs, this can only - ** be one of the values in the first assert() below. Variable p->rc - ** contains the value that would be returned if sqlite3_finalize() - ** were called on statement p. - */ - assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR - || rc==SQLITE_BUSY || rc==SQLITE_MISUSE - ); - assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE ); - if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ - /* If this statement was prepared using sqlite3_prepare_v2(), and an - ** error has occurred, then return the error code in p->rc to the - ** caller. Set the error code in the database handle to the same value. - */ - rc = sqlite3VdbeTransferError(p); - } - return (rc&db->errMask); -} - -/* -** This is the top-level implementation of sqlite3_step(). Call -** sqlite3Step() to do most of the work. If a schema error occurs, -** call sqlite3Reprepare() and try again. -*/ -SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ - int rc = SQLITE_OK; /* Result from sqlite3Step() */ - int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ - Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ - int cnt = 0; /* Counter to prevent infinite loop of reprepares */ - sqlite3 *db; /* The database connection */ - - if( vdbeSafetyNotNull(v) ){ - return SQLITE_MISUSE_BKPT; - } - db = v->db; - sqlite3_mutex_enter(db->mutex); - v->doingRerun = 0; - while( (rc = sqlite3Step(v))==SQLITE_SCHEMA - && cnt++ < SQLITE_MAX_SCHEMA_RETRY - && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ - sqlite3_reset(pStmt); - v->doingRerun = 1; - assert( v->expired==0 ); - } - if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){ - /* This case occurs after failing to recompile an sql statement. - ** The error message from the SQL compiler has already been loaded - ** into the database handle. This block copies the error message - ** from the database handle into the statement and sets the statement - ** program counter to 0 to ensure that when the statement is - ** finalized or reset the parser error message is available via - ** sqlite3_errmsg() and sqlite3_errcode(). - */ - const char *zErr = (const char *)sqlite3_value_text(db->pErr); - sqlite3DbFree(db, v->zErrMsg); - if( !db->mallocFailed ){ - v->zErrMsg = sqlite3DbStrDup(db, zErr); - v->rc = rc2; - } else { - v->zErrMsg = 0; - v->rc = rc = SQLITE_NOMEM; - } - } - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Extract the user data from a sqlite3_context structure and return a -** pointer to it. -*/ -SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ - assert( p && p->pFunc ); - return p->pFunc->pUserData; -} - -/* -** Extract the user data from a sqlite3_context structure and return a -** pointer to it. -** -** IMPLEMENTATION-OF: R-46798-50301 The sqlite3_context_db_handle() interface -** returns a copy of the pointer to the database connection (the 1st -** parameter) of the sqlite3_create_function() and -** sqlite3_create_function16() routines that originally registered the -** application defined function. -*/ -SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ - assert( p && p->pFunc ); - return p->s.db; -} - -/* -** The following is the implementation of an SQL function that always -** fails with an error message stating that the function is used in the -** wrong context. The sqlite3_overload_function() API might construct -** SQL function that use this routine so that the functions will exist -** for name resolution but are actually overloaded by the xFindFunction -** method of virtual tables. -*/ -SQLITE_PRIVATE void sqlite3InvalidFunction( - sqlite3_context *context, /* The function calling context */ - int NotUsed, /* Number of arguments to the function */ - sqlite3_value **NotUsed2 /* Value of each argument */ -){ - const char *zName = context->pFunc->zName; - char *zErr; - UNUSED_PARAMETER2(NotUsed, NotUsed2); - zErr = sqlite3_mprintf( - "unable to use function %s in the requested context", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); -} - -/* -** Allocate or return the aggregate context for a user function. A new -** context is allocated on the first call. Subsequent calls return the -** same context that was returned on prior calls. -*/ -SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ - Mem *pMem; - assert( p && p->pFunc && p->pFunc->xStep ); - assert( sqlite3_mutex_held(p->s.db->mutex) ); - pMem = p->pMem; - testcase( nByte<0 ); - if( (pMem->flags & MEM_Agg)==0 ){ - if( nByte<=0 ){ - sqlite3VdbeMemReleaseExternal(pMem); - pMem->flags = MEM_Null; - pMem->z = 0; - }else{ - sqlite3VdbeMemGrow(pMem, nByte, 0); - pMem->flags = MEM_Agg; - pMem->u.pDef = p->pFunc; - if( pMem->z ){ - memset(pMem->z, 0, nByte); - } - } - } - return (void*)pMem->z; -} - -/* -** Return the auxilary data pointer, if any, for the iArg'th argument to -** the user-function defined by pCtx. -*/ -SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ - VdbeFunc *pVdbeFunc; - - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - pVdbeFunc = pCtx->pVdbeFunc; - if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){ - return 0; - } - return pVdbeFunc->apAux[iArg].pAux; -} - -/* -** Set the auxilary data pointer and delete function, for the iArg'th -** argument to the user-function defined by pCtx. Any previous value is -** deleted by calling the delete function specified when it was set. -*/ -SQLITE_API void sqlite3_set_auxdata( - sqlite3_context *pCtx, - int iArg, - void *pAux, - void (*xDelete)(void*) -){ - struct AuxData *pAuxData; - VdbeFunc *pVdbeFunc; - if( iArg<0 ) goto failed; - - assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - pVdbeFunc = pCtx->pVdbeFunc; - if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){ - int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0); - int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg; - pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc); - if( !pVdbeFunc ){ - goto failed; - } - pCtx->pVdbeFunc = pVdbeFunc; - memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux)); - pVdbeFunc->nAux = iArg+1; - pVdbeFunc->pFunc = pCtx->pFunc; - } - - pAuxData = &pVdbeFunc->apAux[iArg]; - if( pAuxData->pAux && pAuxData->xDelete ){ - pAuxData->xDelete(pAuxData->pAux); - } - pAuxData->pAux = pAux; - pAuxData->xDelete = xDelete; - return; - -failed: - if( xDelete ){ - xDelete(pAux); - } -} - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Return the number of times the Step function of a aggregate has been -** called. -** -** This function is deprecated. Do not use it for new code. It is -** provide only to avoid breaking legacy code. New aggregate function -** implementations should keep their own counts within their aggregate -** context. -*/ -SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ - assert( p && p->pMem && p->pFunc && p->pFunc->xStep ); - return p->pMem->n; -} -#endif - -/* -** Return the number of columns in the result set for the statement pStmt. -*/ -SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ - Vdbe *pVm = (Vdbe *)pStmt; - return pVm ? pVm->nResColumn : 0; -} - -/* -** Return the number of values available from the current row of the -** currently executing statement pStmt. -*/ -SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ - Vdbe *pVm = (Vdbe *)pStmt; - if( pVm==0 || pVm->pResultSet==0 ) return 0; - return pVm->nResColumn; -} - - -/* -** Check to see if column iCol of the given statement is valid. If -** it is, return a pointer to the Mem for the value of that column. -** If iCol is not valid, return a pointer to a Mem which has a value -** of NULL. -*/ -static Mem *columnMem(sqlite3_stmt *pStmt, int i){ - Vdbe *pVm; - Mem *pOut; - - pVm = (Vdbe *)pStmt; - if( pVm && pVm->pResultSet!=0 && inResColumn && i>=0 ){ - sqlite3_mutex_enter(pVm->db->mutex); - pOut = &pVm->pResultSet[i]; - }else{ - /* If the value passed as the second argument is out of range, return - ** a pointer to the following static Mem object which contains the - ** value SQL NULL. Even though the Mem structure contains an element - ** of type i64, on certain architectures (x86) with certain compiler - ** switches (-Os), gcc may align this Mem object on a 4-byte boundary - ** instead of an 8-byte one. This all works fine, except that when - ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s - ** that a Mem structure is located on an 8-byte boundary. To prevent - ** these assert()s from failing, when building with SQLITE_DEBUG defined - ** using gcc, we force nullMem to be 8-byte aligned using the magical - ** __attribute__((aligned(8))) macro. */ - static const Mem nullMem -#if defined(SQLITE_DEBUG) && defined(__GNUC__) - __attribute__((aligned(8))) -#endif - = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0, -#ifdef SQLITE_DEBUG - 0, 0, /* pScopyFrom, pFiller */ -#endif - 0, 0 }; - - if( pVm && ALWAYS(pVm->db) ){ - sqlite3_mutex_enter(pVm->db->mutex); - sqlite3Error(pVm->db, SQLITE_RANGE, 0); - } - pOut = (Mem*)&nullMem; - } - return pOut; -} - -/* -** This function is called after invoking an sqlite3_value_XXX function on a -** column value (i.e. a value returned by evaluating an SQL expression in the -** select list of a SELECT statement) that may cause a malloc() failure. If -** malloc() has failed, the threads mallocFailed flag is cleared and the result -** code of statement pStmt set to SQLITE_NOMEM. -** -** Specifically, this is called from within: -** -** sqlite3_column_int() -** sqlite3_column_int64() -** sqlite3_column_text() -** sqlite3_column_text16() -** sqlite3_column_real() -** sqlite3_column_bytes() -** sqlite3_column_bytes16() -** sqiite3_column_blob() -*/ -static void columnMallocFailure(sqlite3_stmt *pStmt) -{ - /* If malloc() failed during an encoding conversion within an - ** sqlite3_column_XXX API, then set the return code of the statement to - ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR - ** and _finalize() will return NOMEM. - */ - Vdbe *p = (Vdbe *)pStmt; - if( p ){ - p->rc = sqlite3ApiExit(p->db, p->rc); - sqlite3_mutex_leave(p->db->mutex); - } -} - -/**************************** sqlite3_column_ ******************************* -** The following routines are used to access elements of the current row -** in the result set. -*/ -SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ - const void *val; - val = sqlite3_value_blob( columnMem(pStmt,i) ); - /* Even though there is no encoding conversion, value_blob() might - ** need to call malloc() to expand the result of a zeroblob() - ** expression. - */ - columnMallocFailure(pStmt); - return val; -} -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ - int val = sqlite3_value_bytes( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ - int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ - double val = sqlite3_value_double( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ - int val = sqlite3_value_int( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ - sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ - const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ - Mem *pOut = columnMem(pStmt, i); - if( pOut->flags&MEM_Static ){ - pOut->flags &= ~MEM_Static; - pOut->flags |= MEM_Ephem; - } - columnMallocFailure(pStmt); - return (sqlite3_value *)pOut; -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ - const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return val; -} -#endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ - int iType = sqlite3_value_type( columnMem(pStmt,i) ); - columnMallocFailure(pStmt); - return iType; -} - -/* The following function is experimental and subject to change or -** removal */ -/*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){ -** return sqlite3_value_numeric_type( columnMem(pStmt,i) ); -**} -*/ - -/* -** Convert the N-th element of pStmt->pColName[] into a string using -** xFunc() then return that string. If N is out of range, return 0. -** -** There are up to 5 names for each column. useType determines which -** name is returned. Here are the names: -** -** 0 The column name as it should be displayed for output -** 1 The datatype name for the column -** 2 The name of the database that the column derives from -** 3 The name of the table that the column derives from -** 4 The name of the table column that the result column derives from -** -** If the result is not a simple column reference (if it is an expression -** or a constant) then useTypes 2, 3, and 4 return NULL. -*/ -static const void *columnName( - sqlite3_stmt *pStmt, - int N, - const void *(*xFunc)(Mem*), - int useType -){ - const void *ret = 0; - Vdbe *p = (Vdbe *)pStmt; - int n; - sqlite3 *db = p->db; - - assert( db!=0 ); - n = sqlite3_column_count(pStmt); - if( N=0 ){ - N += useType*n; - sqlite3_mutex_enter(db->mutex); - assert( db->mallocFailed==0 ); - ret = xFunc(&p->aColName[N]); - /* A malloc may have failed inside of the xFunc() call. If this - ** is the case, clear the mallocFailed flag and return NULL. - */ - if( db->mallocFailed ){ - db->mallocFailed = 0; - ret = 0; - } - sqlite3_mutex_leave(db->mutex); - } - return ret; -} - -/* -** Return the name of the Nth column of the result set returned by SQL -** statement pStmt. -*/ -SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); -} -#endif - -/* -** Constraint: If you have ENABLE_COLUMN_METADATA then you must -** not define OMIT_DECLTYPE. -*/ -#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA) -# error "Must not define both SQLITE_OMIT_DECLTYPE \ - and SQLITE_ENABLE_COLUMN_METADATA" -#endif - -#ifndef SQLITE_OMIT_DECLTYPE -/* -** Return the column declaration type (if applicable) of the 'i'th column -** of the result set of SQL statement pStmt. -*/ -SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); -} -#endif /* SQLITE_OMIT_UTF16 */ -#endif /* SQLITE_OMIT_DECLTYPE */ - -#ifdef SQLITE_ENABLE_COLUMN_METADATA -/* -** Return the name of the database from which a result column derives. -** NULL is returned if the result column is an expression or constant or -** anything else which is not an unabiguous reference to a database column. -*/ -SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Return the name of the table from which a result column derives. -** NULL is returned if the result column is an expression or constant or -** anything else which is not an unabiguous reference to a database column. -*/ -SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Return the name of the table column from which a result column derives. -** NULL is returned if the result column is an expression or constant or -** anything else which is not an unabiguous reference to a database column. -*/ -SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); -} -#endif /* SQLITE_OMIT_UTF16 */ -#endif /* SQLITE_ENABLE_COLUMN_METADATA */ - - -/******************************* sqlite3_bind_ *************************** -** -** Routines used to attach values to wildcards in a compiled SQL statement. -*/ -/* -** Unbind the value bound to variable i in virtual machine p. This is the -** the same as binding a NULL value to the column. If the "i" parameter is -** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. -** -** A successful evaluation of this routine acquires the mutex on p. -** the mutex is released if any kind of error occurs. -** -** The error code stored in database p->db is overwritten with the return -** value in any case. -*/ -static int vdbeUnbind(Vdbe *p, int i){ - Mem *pVar; - if( vdbeSafetyNotNull(p) ){ - return SQLITE_MISUSE_BKPT; - } - sqlite3_mutex_enter(p->db->mutex); - if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ - sqlite3Error(p->db, SQLITE_MISUSE, 0); - sqlite3_mutex_leave(p->db->mutex); - sqlite3_log(SQLITE_MISUSE, - "bind on a busy prepared statement: [%s]", p->zSql); - return SQLITE_MISUSE_BKPT; - } - if( i<1 || i>p->nVar ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); - sqlite3_mutex_leave(p->db->mutex); - return SQLITE_RANGE; - } - i--; - pVar = &p->aVar[i]; - sqlite3VdbeMemRelease(pVar); - pVar->flags = MEM_Null; - sqlite3Error(p->db, SQLITE_OK, 0); - - /* If the bit corresponding to this variable in Vdbe.expmask is set, then - ** binding a new value to this variable invalidates the current query plan. - ** - ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host - ** parameter in the WHERE clause might influence the choice of query plan - ** for a statement, then the statement will be automatically recompiled, - ** as if there had been a schema change, on the first sqlite3_step() call - ** following any change to the bindings of that parameter. - */ - if( p->isPrepareV2 && - ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) - ){ - p->expired = 1; - } - return SQLITE_OK; -} - -/* -** Bind a text or BLOB value. -*/ -static int bindText( - sqlite3_stmt *pStmt, /* The statement to bind against */ - int i, /* Index of the parameter to bind */ - const void *zData, /* Pointer to the data to be bound */ - int nData, /* Number of bytes of data to be bound */ - void (*xDel)(void*), /* Destructor for the data */ - u8 encoding /* Encoding for the data */ -){ - Vdbe *p = (Vdbe *)pStmt; - Mem *pVar; - int rc; - - rc = vdbeUnbind(p, i); - if( rc==SQLITE_OK ){ - if( zData!=0 ){ - pVar = &p->aVar[i-1]; - rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); - if( rc==SQLITE_OK && encoding!=0 ){ - rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); - } - sqlite3Error(p->db, rc, 0); - rc = sqlite3ApiExit(p->db, rc); - } - sqlite3_mutex_leave(p->db->mutex); - }else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){ - xDel((void*)zData); - } - return rc; -} - - -/* -** Bind a blob value to an SQL statement variable. -*/ -SQLITE_API int sqlite3_bind_blob( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int nData, - void (*xDel)(void*) -){ - return bindText(pStmt, i, zData, nData, xDel, 0); -} -SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ - int rc; - Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, i); - if( rc==SQLITE_OK ){ - sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); - sqlite3_mutex_leave(p->db->mutex); - } - return rc; -} -SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ - return sqlite3_bind_int64(p, i, (i64)iValue); -} -SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ - int rc; - Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, i); - if( rc==SQLITE_OK ){ - sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); - sqlite3_mutex_leave(p->db->mutex); - } - return rc; -} -SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ - int rc; - Vdbe *p = (Vdbe*)pStmt; - rc = vdbeUnbind(p, i); - if( rc==SQLITE_OK ){ - sqlite3_mutex_leave(p->db->mutex); - } - return rc; -} -SQLITE_API int sqlite3_bind_text( - sqlite3_stmt *pStmt, - int i, - const char *zData, - int nData, - void (*xDel)(void*) -){ - return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8); -} -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API int sqlite3_bind_text16( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int nData, - void (*xDel)(void*) -){ - return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); -} -#endif /* SQLITE_OMIT_UTF16 */ -SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ - int rc; - switch( pValue->type ){ - case SQLITE_INTEGER: { - rc = sqlite3_bind_int64(pStmt, i, pValue->u.i); - break; - } - case SQLITE_FLOAT: { - rc = sqlite3_bind_double(pStmt, i, pValue->r); - break; - } - case SQLITE_BLOB: { - if( pValue->flags & MEM_Zero ){ - rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero); - }else{ - rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT); - } - break; - } - case SQLITE_TEXT: { - rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT, - pValue->enc); - break; - } - default: { - rc = sqlite3_bind_null(pStmt, i); - break; - } - } - return rc; -} -SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ - int rc; - Vdbe *p = (Vdbe *)pStmt; - rc = vdbeUnbind(p, i); - if( rc==SQLITE_OK ){ - sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); - sqlite3_mutex_leave(p->db->mutex); - } - return rc; -} - -/* -** Return the number of wildcards that can be potentially bound to. -** This routine is added to support DBD::SQLite. -*/ -SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe*)pStmt; - return p ? p->nVar : 0; -} - -/* -** Return the name of a wildcard parameter. Return NULL if the index -** is out of range or if the wildcard is unnamed. -** -** The result is always UTF-8. -*/ -SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ - Vdbe *p = (Vdbe*)pStmt; - if( p==0 || i<1 || i>p->nzVar ){ - return 0; - } - return p->azVar[i-1]; -} - -/* -** Given a wildcard parameter name, return the index of the variable -** with that name. If there is no variable with the given name, -** return 0. -*/ -SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){ - int i; - if( p==0 ){ - return 0; - } - if( zName ){ - for(i=0; inzVar; i++){ - const char *z = p->azVar[i]; - if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){ - return i+1; - } - } - } - return 0; -} -SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ - return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); -} - -/* -** Transfer all bindings from the first statement over to the second. -*/ -SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ - Vdbe *pFrom = (Vdbe*)pFromStmt; - Vdbe *pTo = (Vdbe*)pToStmt; - int i; - assert( pTo->db==pFrom->db ); - assert( pTo->nVar==pFrom->nVar ); - sqlite3_mutex_enter(pTo->db->mutex); - for(i=0; inVar; i++){ - sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]); - } - sqlite3_mutex_leave(pTo->db->mutex); - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** Deprecated external interface. Internal/core SQLite code -** should call sqlite3TransferBindings. -** -** Is is misuse to call this routine with statements from different -** database connections. But as this is a deprecated interface, we -** will not bother to check for that condition. -** -** If the two statements contain a different number of bindings, then -** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise -** SQLITE_OK is returned. -*/ -SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){ - Vdbe *pFrom = (Vdbe*)pFromStmt; - Vdbe *pTo = (Vdbe*)pToStmt; - if( pFrom->nVar!=pTo->nVar ){ - return SQLITE_ERROR; - } - if( pTo->isPrepareV2 && pTo->expmask ){ - pTo->expired = 1; - } - if( pFrom->isPrepareV2 && pFrom->expmask ){ - pFrom->expired = 1; - } - return sqlite3TransferBindings(pFromStmt, pToStmt); -} -#endif - -/* -** Return the sqlite3* database handle to which the prepared statement given -** in the argument belongs. This is the same database handle that was -** the first argument to the sqlite3_prepare() that was used to create -** the statement in the first place. -*/ -SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ - return pStmt ? ((Vdbe*)pStmt)->db : 0; -} - -/* -** Return true if the prepared statement is guaranteed to not modify the -** database. -*/ -SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ - return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; -} - -/* -** Return true if the prepared statement is in need of being reset. -*/ -SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ - Vdbe *v = (Vdbe*)pStmt; - return v!=0 && v->pc>0 && v->magic==VDBE_MAGIC_RUN; -} - -/* -** Return a pointer to the next prepared statement after pStmt associated -** with database connection pDb. If pStmt is NULL, return the first -** prepared statement for the database connection. Return NULL if there -** are no more. -*/ -SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ - sqlite3_stmt *pNext; - sqlite3_mutex_enter(pDb->mutex); - if( pStmt==0 ){ - pNext = (sqlite3_stmt*)pDb->pVdbe; - }else{ - pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext; - } - sqlite3_mutex_leave(pDb->mutex); - return pNext; -} - -/* -** Return the value of a status counter for a prepared statement -*/ -SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ - Vdbe *pVdbe = (Vdbe*)pStmt; - int v = pVdbe->aCounter[op-1]; - if( resetFlag ) pVdbe->aCounter[op-1] = 0; - return v; -} - -/************** End of vdbeapi.c *********************************************/ -/************** Begin file vdbetrace.c ***************************************/ -/* -** 2009 November 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code used to insert the values of host parameters -** (aka "wildcards") into the SQL text output by sqlite3_trace(). -** -** The Vdbe parse-tree explainer is also found here. -*/ - -#ifndef SQLITE_OMIT_TRACE - -/* -** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of -** bytes in this text up to but excluding the first character in -** a host parameter. If the text contains no host parameters, return -** the total number of bytes in the text. -*/ -static int findNextHostParameter(const char *zSql, int *pnToken){ - int tokenType; - int nTotal = 0; - int n; - - *pnToken = 0; - while( zSql[0] ){ - n = sqlite3GetToken((u8*)zSql, &tokenType); - assert( n>0 && tokenType!=TK_ILLEGAL ); - if( tokenType==TK_VARIABLE ){ - *pnToken = n; - break; - } - nTotal += n; - zSql += n; - } - return nTotal; -} - -/* -** This function returns a pointer to a nul-terminated string in memory -** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the -** string contains a copy of zRawSql but with host parameters expanded to -** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, -** then the returned string holds a copy of zRawSql with "-- " prepended -** to each line of text. -** -** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then -** then long strings and blobs are truncated to that many bytes. This -** can be used to prevent unreasonably large trace strings when dealing -** with large (multi-megabyte) strings and blobs. -** -** The calling function is responsible for making sure the memory returned -** is eventually freed. -** -** ALGORITHM: Scan the input string looking for host parameters in any of -** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within -** string literals, quoted identifier names, and comments. For text forms, -** the host parameter index is found by scanning the perpared -** statement for the corresponding OP_Variable opcode. Once the host -** parameter index is known, locate the value in p->aVar[]. Then render -** the value as a literal in place of the host parameter name. -*/ -SQLITE_PRIVATE char *sqlite3VdbeExpandSql( - Vdbe *p, /* The prepared statement being evaluated */ - const char *zRawSql /* Raw text of the SQL statement */ -){ - sqlite3 *db; /* The database connection */ - int idx = 0; /* Index of a host parameter */ - int nextIndex = 1; /* Index of next ? host parameter */ - int n; /* Length of a token prefix */ - int nToken; /* Length of the parameter token */ - int i; /* Loop counter */ - Mem *pVar; /* Value of a host parameter */ - StrAccum out; /* Accumulate the output here */ - char zBase[100]; /* Initial working space */ - - db = p->db; - sqlite3StrAccumInit(&out, zBase, sizeof(zBase), - db->aLimit[SQLITE_LIMIT_LENGTH]); - out.db = db; - if( db->vdbeExecCnt>1 ){ - while( *zRawSql ){ - const char *zStart = zRawSql; - while( *(zRawSql++)!='\n' && *zRawSql ); - sqlite3StrAccumAppend(&out, "-- ", 3); - sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); - } - }else{ - while( zRawSql[0] ){ - n = findNextHostParameter(zRawSql, &nToken); - assert( n>0 ); - sqlite3StrAccumAppend(&out, zRawSql, n); - zRawSql += n; - assert( zRawSql[0] || nToken==0 ); - if( nToken==0 ) break; - if( zRawSql[0]=='?' ){ - if( nToken>1 ){ - assert( sqlite3Isdigit(zRawSql[1]) ); - sqlite3GetInt32(&zRawSql[1], &idx); - }else{ - idx = nextIndex; - } - }else{ - assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); - testcase( zRawSql[0]==':' ); - testcase( zRawSql[0]=='$' ); - testcase( zRawSql[0]=='@' ); - idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); - assert( idx>0 ); - } - zRawSql += nToken; - nextIndex = idx + 1; - assert( idx>0 && idx<=p->nVar ); - pVar = &p->aVar[idx-1]; - if( pVar->flags & MEM_Null ){ - sqlite3StrAccumAppend(&out, "NULL", 4); - }else if( pVar->flags & MEM_Int ){ - sqlite3XPrintf(&out, "%lld", pVar->u.i); - }else if( pVar->flags & MEM_Real ){ - sqlite3XPrintf(&out, "%!.15g", pVar->r); - }else if( pVar->flags & MEM_Str ){ - int nOut; /* Number of bytes of the string text to include in output */ -#ifndef SQLITE_OMIT_UTF16 - u8 enc = ENC(db); - Mem utf8; - if( enc!=SQLITE_UTF8 ){ - memset(&utf8, 0, sizeof(utf8)); - utf8.db = db; - sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); - sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); - pVar = &utf8; - } -#endif - nOut = pVar->n; -#ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOut>SQLITE_TRACE_SIZE_LIMIT ){ - nOut = SQLITE_TRACE_SIZE_LIMIT; - while( nOutn && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } - } -#endif - sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); -#ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOutn ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); -#endif -#ifndef SQLITE_OMIT_UTF16 - if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); -#endif - }else if( pVar->flags & MEM_Zero ){ - sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); - }else{ - int nOut; /* Number of bytes of the blob to include in output */ - assert( pVar->flags & MEM_Blob ); - sqlite3StrAccumAppend(&out, "x'", 2); - nOut = pVar->n; -#ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; -#endif - for(i=0; iz[i]&0xff); - } - sqlite3StrAccumAppend(&out, "'", 1); -#ifdef SQLITE_TRACE_SIZE_LIMIT - if( nOutn ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); -#endif - } - } - } - return sqlite3StrAccumFinish(&out); -} - -#endif /* #ifndef SQLITE_OMIT_TRACE */ - -/***************************************************************************** -** The following code implements the data-structure explaining logic -** for the Vdbe. -*/ - -#if defined(SQLITE_ENABLE_TREE_EXPLAIN) - -/* -** Allocate a new Explain object -*/ -SQLITE_PRIVATE void sqlite3ExplainBegin(Vdbe *pVdbe){ - if( pVdbe ){ - Explain *p; - sqlite3BeginBenignMalloc(); - p = (Explain *)sqlite3MallocZero( sizeof(Explain) ); - if( p ){ - p->pVdbe = pVdbe; - sqlite3_free(pVdbe->pExplain); - pVdbe->pExplain = p; - sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase), - SQLITE_MAX_LENGTH); - p->str.useMalloc = 2; - }else{ - sqlite3EndBenignMalloc(); - } - } -} - -/* -** Return true if the Explain ends with a new-line. -*/ -static int endsWithNL(Explain *p){ - return p && p->str.zText && p->str.nChar - && p->str.zText[p->str.nChar-1]=='\n'; -} - -/* -** Append text to the indentation -*/ -SQLITE_PRIVATE void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){ - Explain *p; - if( pVdbe && (p = pVdbe->pExplain)!=0 ){ - va_list ap; - if( p->nIndent && endsWithNL(p) ){ - int n = p->nIndent; - if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent); - sqlite3AppendSpace(&p->str, p->aIndent[n-1]); - } - va_start(ap, zFormat); - sqlite3VXPrintf(&p->str, 1, zFormat, ap); - va_end(ap); - } -} - -/* -** Append a '\n' if there is not already one. -*/ -SQLITE_PRIVATE void sqlite3ExplainNL(Vdbe *pVdbe){ - Explain *p; - if( pVdbe && (p = pVdbe->pExplain)!=0 && !endsWithNL(p) ){ - sqlite3StrAccumAppend(&p->str, "\n", 1); - } -} - -/* -** Push a new indentation level. Subsequent lines will be indented -** so that they begin at the current cursor position. -*/ -SQLITE_PRIVATE void sqlite3ExplainPush(Vdbe *pVdbe){ - Explain *p; - if( pVdbe && (p = pVdbe->pExplain)!=0 ){ - if( p->str.zText && p->nIndentaIndent) ){ - const char *z = p->str.zText; - int i = p->str.nChar-1; - int x; - while( i>=0 && z[i]!='\n' ){ i--; } - x = (p->str.nChar - 1) - i; - if( p->nIndent && xaIndent[p->nIndent-1] ){ - x = p->aIndent[p->nIndent-1]; - } - p->aIndent[p->nIndent] = x; - } - p->nIndent++; - } -} - -/* -** Pop the indentation stack by one level. -*/ -SQLITE_PRIVATE void sqlite3ExplainPop(Vdbe *p){ - if( p && p->pExplain ) p->pExplain->nIndent--; -} - -/* -** Free the indentation structure -*/ -SQLITE_PRIVATE void sqlite3ExplainFinish(Vdbe *pVdbe){ - if( pVdbe && pVdbe->pExplain ){ - sqlite3_free(pVdbe->zExplain); - sqlite3ExplainNL(pVdbe); - pVdbe->zExplain = sqlite3StrAccumFinish(&pVdbe->pExplain->str); - sqlite3_free(pVdbe->pExplain); - pVdbe->pExplain = 0; - sqlite3EndBenignMalloc(); - } -} - -/* -** Return the explanation of a virtual machine. -*/ -SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){ - return (pVdbe && pVdbe->zExplain) ? pVdbe->zExplain : 0; -} -#endif /* defined(SQLITE_DEBUG) */ - -/************** End of vdbetrace.c *******************************************/ -/************** Begin file vdbe.c ********************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** The code in this file implements execution method of the -** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c") -** handles housekeeping details such as creating and deleting -** VDBE instances. This file is solely interested in executing -** the VDBE program. -** -** In the external interface, an "sqlite3_stmt*" is an opaque pointer -** to a VDBE. -** -** The SQL parser generates a program which is then executed by -** the VDBE to do the work of the SQL statement. VDBE programs are -** similar in form to assembly language. The program consists of -** a linear sequence of operations. Each operation has an opcode -** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4 -** is a null-terminated string. Operand P5 is an unsigned character. -** Few opcodes use all 5 operands. -** -** Computation results are stored on a set of registers numbered beginning -** with 1 and going up to Vdbe.nMem. Each register can store -** either an integer, a null-terminated string, a floating point -** number, or the SQL "NULL" value. An implicit conversion from one -** type to the other occurs as necessary. -** -** Most of the code in this file is taken up by the sqlite3VdbeExec() -** function which does the work of interpreting a VDBE program. -** But other routines are also provided to help in building up -** a program instruction by instruction. -** -** Various scripts scan this source file in order to generate HTML -** documentation, headers files, or other derived files. The formatting -** of the code in this file is, therefore, important. See other comments -** in this file for details. If in doubt, do not deviate from existing -** commenting and indentation practices when changing or adding code. -*/ - -/* -** Invoke this macro on memory cells just prior to changing the -** value of the cell. This macro verifies that shallow copies are -** not misused. -*/ -#ifdef SQLITE_DEBUG -# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) -#else -# define memAboutToChange(P,M) -#endif - -/* -** The following global variable is incremented every time a cursor -** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test -** procedures use this information to make sure that indices are -** working correctly. This variable has no function other than to -** help verify the correct operation of the library. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_search_count = 0; -#endif - -/* -** When this global variable is positive, it gets decremented once before -** each instruction in the VDBE. When it reaches zero, the u1.isInterrupted -** field of the sqlite3 structure is set in order to simulate an interrupt. -** -** This facility is used for testing purposes only. It does not function -** in an ordinary build. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_interrupt_count = 0; -#endif - -/* -** The next global variable is incremented each type the OP_Sort opcode -** is executed. The test procedures use this information to make sure that -** sorting is occurring or not occurring at appropriate times. This variable -** has no function other than to help verify the correct operation of the -** library. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_sort_count = 0; -#endif - -/* -** The next global variable records the size of the largest MEM_Blob -** or MEM_Str that has been used by a VDBE opcode. The test procedures -** use this information to make sure that the zero-blob functionality -** is working correctly. This variable has no function other than to -** help verify the correct operation of the library. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_max_blobsize = 0; -static void updateMaxBlobsize(Mem *p){ - if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){ - sqlite3_max_blobsize = p->n; - } -} -#endif - -/* -** The next global variable is incremented each type the OP_Found opcode -** is executed. This is used to test whether or not the foreign key -** operation implemented using OP_FkIsZero is working. This variable -** has no function other than to help verify the correct operation of the -** library. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_found_count = 0; -#endif - -/* -** Test a register to see if it exceeds the current maximum blob size. -** If it does, record the new maximum blob size. -*/ -#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST) -# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) -#else -# define UPDATE_MAX_BLOBSIZE(P) -#endif - -/* -** Convert the given register into a string if it isn't one -** already. Return non-zero if a malloc() fails. -*/ -#define Stringify(P, enc) \ - if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ - { goto no_mem; } - -/* -** An ephemeral string value (signified by the MEM_Ephem flag) contains -** a pointer to a dynamically allocated string where some other entity -** is responsible for deallocating that string. Because the register -** does not control the string, it might be deleted without the register -** knowing it. -** -** This routine converts an ephemeral string into a dynamically allocated -** string that the register itself controls. In other words, it -** converts an MEM_Ephem string into an MEM_Dyn string. -*/ -#define Deephemeralize(P) \ - if( ((P)->flags&MEM_Ephem)!=0 \ - && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} - -/* Return true if the cursor was opened using the OP_OpenSorter opcode. */ -# define isSorter(x) ((x)->pSorter!=0) - -/* -** Argument pMem points at a register that will be passed to a -** user-defined function or returned to the user as the result of a query. -** This routine sets the pMem->type variable used by the sqlite3_value_*() -** routines. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){ - int flags = pMem->flags; - if( flags & MEM_Null ){ - pMem->type = SQLITE_NULL; - } - else if( flags & MEM_Int ){ - pMem->type = SQLITE_INTEGER; - } - else if( flags & MEM_Real ){ - pMem->type = SQLITE_FLOAT; - } - else if( flags & MEM_Str ){ - pMem->type = SQLITE_TEXT; - }else{ - pMem->type = SQLITE_BLOB; - } -} - -/* -** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL -** if we run out of memory. -*/ -static VdbeCursor *allocateCursor( - Vdbe *p, /* The virtual machine */ - int iCur, /* Index of the new VdbeCursor */ - int nField, /* Number of fields in the table or index */ - int iDb, /* Database the cursor belongs to, or -1 */ - int isBtreeCursor /* True for B-Tree. False for pseudo-table or vtab */ -){ - /* Find the memory cell that will be used to store the blob of memory - ** required for this VdbeCursor structure. It is convenient to use a - ** vdbe memory cell to manage the memory allocation required for a - ** VdbeCursor structure for the following reasons: - ** - ** * Sometimes cursor numbers are used for a couple of different - ** purposes in a vdbe program. The different uses might require - ** different sized allocations. Memory cells provide growable - ** allocations. - ** - ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can - ** be freed lazily via the sqlite3_release_memory() API. This - ** minimizes the number of malloc calls made by the system. - ** - ** Memory cells for cursors are allocated at the top of the address - ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for - ** cursor 1 is managed by memory cell (p->nMem-1), etc. - */ - Mem *pMem = &p->aMem[p->nMem-iCur]; - - int nByte; - VdbeCursor *pCx = 0; - nByte = - ROUND8(sizeof(VdbeCursor)) + - (isBtreeCursor?sqlite3BtreeCursorSize():0) + - 2*nField*sizeof(u32); - - assert( iCurnCursor ); - if( p->apCsr[iCur] ){ - sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); - p->apCsr[iCur] = 0; - } - if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){ - p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z; - memset(pCx, 0, sizeof(VdbeCursor)); - pCx->iDb = iDb; - pCx->nField = nField; - if( nField ){ - pCx->aType = (u32 *)&pMem->z[ROUND8(sizeof(VdbeCursor))]; - } - if( isBtreeCursor ){ - pCx->pCursor = (BtCursor*) - &pMem->z[ROUND8(sizeof(VdbeCursor))+2*nField*sizeof(u32)]; - sqlite3BtreeCursorZero(pCx->pCursor); - } - } - return pCx; -} - -/* -** Try to convert a value into a numeric representation if we can -** do so without loss of information. In other words, if the string -** looks like a number, convert it into a number. If it does not -** look like a number, leave it alone. -*/ -static void applyNumericAffinity(Mem *pRec){ - if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){ - double rValue; - i64 iValue; - u8 enc = pRec->enc; - if( (pRec->flags&MEM_Str)==0 ) return; - if( sqlite3AtoF(pRec->z, &rValue, pRec->n, enc)==0 ) return; - if( 0==sqlite3Atoi64(pRec->z, &iValue, pRec->n, enc) ){ - pRec->u.i = iValue; - pRec->flags |= MEM_Int; - }else{ - pRec->r = rValue; - pRec->flags |= MEM_Real; - } - } -} - -/* -** Processing is determine by the affinity parameter: -** -** SQLITE_AFF_INTEGER: -** SQLITE_AFF_REAL: -** SQLITE_AFF_NUMERIC: -** Try to convert pRec to an integer representation or a -** floating-point representation if an integer representation -** is not possible. Note that the integer representation is -** always preferred, even if the affinity is REAL, because -** an integer representation is more space efficient on disk. -** -** SQLITE_AFF_TEXT: -** Convert pRec to a text representation. -** -** SQLITE_AFF_NONE: -** No-op. pRec is unchanged. -*/ -static void applyAffinity( - Mem *pRec, /* The value to apply affinity to */ - char affinity, /* The affinity to be applied */ - u8 enc /* Use this text encoding */ -){ - if( affinity==SQLITE_AFF_TEXT ){ - /* Only attempt the conversion to TEXT if there is an integer or real - ** representation (blob and NULL do not get converted) but no string - ** representation. - */ - if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ - sqlite3VdbeMemStringify(pRec, enc); - } - pRec->flags &= ~(MEM_Real|MEM_Int); - }else if( affinity!=SQLITE_AFF_NONE ){ - assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL - || affinity==SQLITE_AFF_NUMERIC ); - applyNumericAffinity(pRec); - if( pRec->flags & MEM_Real ){ - sqlite3VdbeIntegerAffinity(pRec); - } - } -} - -/* -** Try to convert the type of a function argument or a result column -** into a numeric representation. Use either INTEGER or REAL whichever -** is appropriate. But only do the conversion if it is possible without -** loss of information and return the revised type of the argument. -*/ -SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ - Mem *pMem = (Mem*)pVal; - if( pMem->type==SQLITE_TEXT ){ - applyNumericAffinity(pMem); - sqlite3VdbeMemStoreType(pMem); - } - return pMem->type; -} - -/* -** Exported version of applyAffinity(). This one works on sqlite3_value*, -** not the internal Mem* type. -*/ -SQLITE_PRIVATE void sqlite3ValueApplyAffinity( - sqlite3_value *pVal, - u8 affinity, - u8 enc -){ - applyAffinity((Mem *)pVal, affinity, enc); -} - -#ifdef SQLITE_DEBUG -/* -** Write a nice string representation of the contents of cell pMem -** into buffer zBuf, length nBuf. -*/ -SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ - char *zCsr = zBuf; - int f = pMem->flags; - - static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"}; - - if( f&MEM_Blob ){ - int i; - char c; - if( f & MEM_Dyn ){ - c = 'z'; - assert( (f & (MEM_Static|MEM_Ephem))==0 ); - }else if( f & MEM_Static ){ - c = 't'; - assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); - }else if( f & MEM_Ephem ){ - c = 'e'; - assert( (f & (MEM_Static|MEM_Dyn))==0 ); - }else{ - c = 's'; - } - - sqlite3_snprintf(100, zCsr, "%c", c); - zCsr += sqlite3Strlen30(zCsr); - sqlite3_snprintf(100, zCsr, "%d[", pMem->n); - zCsr += sqlite3Strlen30(zCsr); - for(i=0; i<16 && in; i++){ - sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF)); - zCsr += sqlite3Strlen30(zCsr); - } - for(i=0; i<16 && in; i++){ - char z = pMem->z[i]; - if( z<32 || z>126 ) *zCsr++ = '.'; - else *zCsr++ = z; - } - - sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]); - zCsr += sqlite3Strlen30(zCsr); - if( f & MEM_Zero ){ - sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero); - zCsr += sqlite3Strlen30(zCsr); - } - *zCsr = '\0'; - }else if( f & MEM_Str ){ - int j, k; - zBuf[0] = ' '; - if( f & MEM_Dyn ){ - zBuf[1] = 'z'; - assert( (f & (MEM_Static|MEM_Ephem))==0 ); - }else if( f & MEM_Static ){ - zBuf[1] = 't'; - assert( (f & (MEM_Dyn|MEM_Ephem))==0 ); - }else if( f & MEM_Ephem ){ - zBuf[1] = 'e'; - assert( (f & (MEM_Static|MEM_Dyn))==0 ); - }else{ - zBuf[1] = 's'; - } - k = 2; - sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n); - k += sqlite3Strlen30(&zBuf[k]); - zBuf[k++] = '['; - for(j=0; j<15 && jn; j++){ - u8 c = pMem->z[j]; - if( c>=0x20 && c<0x7f ){ - zBuf[k++] = c; - }else{ - zBuf[k++] = '.'; - } - } - zBuf[k++] = ']'; - sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]); - k += sqlite3Strlen30(&zBuf[k]); - zBuf[k++] = 0; - } -} -#endif - -#ifdef SQLITE_DEBUG -/* -** Print the value of a register for tracing purposes: -*/ -static void memTracePrint(FILE *out, Mem *p){ - if( p->flags & MEM_Invalid ){ - fprintf(out, " undefined"); - }else if( p->flags & MEM_Null ){ - fprintf(out, " NULL"); - }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ - fprintf(out, " si:%lld", p->u.i); - }else if( p->flags & MEM_Int ){ - fprintf(out, " i:%lld", p->u.i); -#ifndef SQLITE_OMIT_FLOATING_POINT - }else if( p->flags & MEM_Real ){ - fprintf(out, " r:%g", p->r); -#endif - }else if( p->flags & MEM_RowSet ){ - fprintf(out, " (rowset)"); - }else{ - char zBuf[200]; - sqlite3VdbeMemPrettyPrint(p, zBuf); - fprintf(out, " "); - fprintf(out, "%s", zBuf); - } -} -static void registerTrace(FILE *out, int iReg, Mem *p){ - fprintf(out, "REG[%d] = ", iReg); - memTracePrint(out, p); - fprintf(out, "\n"); -} -#endif - -#ifdef SQLITE_DEBUG -# define REGISTER_TRACE(R,M) if(p->trace)registerTrace(p->trace,R,M) -#else -# define REGISTER_TRACE(R,M) -#endif - - -#ifdef VDBE_PROFILE - -/* -** hwtime.h contains inline assembler code for implementing -** high-performance timing routines. -*/ -/************** Include hwtime.h in the middle of vdbe.c *********************/ -/************** Begin file hwtime.h ******************************************/ -/* -** 2008 May 27 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains inline asm code for retrieving "high-performance" -** counters for x86 class CPUs. -*/ -#ifndef _HWTIME_H_ -#define _HWTIME_H_ - -/* -** The following routine only works on pentium-class (or newer) processors. -** It uses the RDTSC opcode to read the cycle count value out of the -** processor and returns that value. This can be used for high-res -** profiling. -*/ -#if (defined(__GNUC__) || defined(_MSC_VER)) && \ - (defined(i386) || defined(__i386__) || defined(_M_IX86)) - - #if defined(__GNUC__) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned int lo, hi; - __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); - return (sqlite_uint64)hi << 32 | lo; - } - - #elif defined(_MSC_VER) - - __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ - __asm { - rdtsc - ret ; return value at EDX:EAX - } - } - - #endif - -#elif (defined(__GNUC__) && defined(__x86_64__)) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned long val; - __asm__ __volatile__ ("rdtsc" : "=A" (val)); - return val; - } - -#elif (defined(__GNUC__) && defined(__ppc__)) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - unsigned long long retval; - unsigned long junk; - __asm__ __volatile__ ("\n\ - 1: mftbu %1\n\ - mftb %L0\n\ - mftbu %0\n\ - cmpw %0,%1\n\ - bne 1b" - : "=r" (retval), "=r" (junk)); - return retval; - } - -#else - - #error Need implementation of sqlite3Hwtime() for your platform. - - /* - ** To compile without implementing sqlite3Hwtime() for your platform, - ** you can remove the above #error and use the following - ** stub function. You will lose timing support for many - ** of the debugging and testing utilities, but it should at - ** least compile and run. - */ -SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } - -#endif - -#endif /* !defined(_HWTIME_H_) */ - -/************** End of hwtime.h **********************************************/ -/************** Continuing where we left off in vdbe.c ***********************/ - -#endif - -/* -** The CHECK_FOR_INTERRUPT macro defined here looks to see if the -** sqlite3_interrupt() routine has been called. If it has been, then -** processing of the VDBE program is interrupted. -** -** This macro added to every instruction that does a jump in order to -** implement a loop. This test used to be on every single instruction, -** but that meant we more testing than we needed. By only testing the -** flag on jump instructions, we get a (small) speed improvement. -*/ -#define CHECK_FOR_INTERRUPT \ - if( db->u1.isInterrupted ) goto abort_due_to_interrupt; - - -#ifndef NDEBUG -/* -** This function is only called from within an assert() expression. It -** checks that the sqlite3.nTransaction variable is correctly set to -** the number of non-transaction savepoints currently in the -** linked list starting at sqlite3.pSavepoint. -** -** Usage: -** -** assert( checkSavepointCount(db) ); -*/ -static int checkSavepointCount(sqlite3 *db){ - int n = 0; - Savepoint *p; - for(p=db->pSavepoint; p; p=p->pNext) n++; - assert( n==(db->nSavepoint + db->isTransactionSavepoint) ); - return 1; -} -#endif - -/* -** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored -** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored -** in memory obtained from sqlite3DbMalloc). -*/ -static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){ - sqlite3 *db = p->db; - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg); - sqlite3_free(pVtab->zErrMsg); - pVtab->zErrMsg = 0; -} - - -/* -** Execute as much of a VDBE program as we can then return. -** -** sqlite3VdbeMakeReady() must be called before this routine in order to -** close the program with a final OP_Halt and to set up the callbacks -** and the error message pointer. -** -** Whenever a row or result data is available, this routine will either -** invoke the result callback (if there is one) or return with -** SQLITE_ROW. -** -** If an attempt is made to open a locked database, then this routine -** will either invoke the busy callback (if there is one) or it will -** return SQLITE_BUSY. -** -** If an error occurs, an error message is written to memory obtained -** from sqlite3_malloc() and p->zErrMsg is made to point to that memory. -** The error code is stored in p->rc and this routine returns SQLITE_ERROR. -** -** If the callback ever returns non-zero, then the program exits -** immediately. There will be no error message but the p->rc field is -** set to SQLITE_ABORT and this routine will return SQLITE_ERROR. -** -** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this -** routine to return SQLITE_ERROR. -** -** Other fatal errors return SQLITE_ERROR. -** -** After this routine has finished, sqlite3VdbeFinalize() should be -** used to clean up the mess that was left behind. -*/ -SQLITE_PRIVATE int sqlite3VdbeExec( - Vdbe *p /* The VDBE */ -){ - int pc=0; /* The program counter */ - Op *aOp = p->aOp; /* Copy of p->aOp */ - Op *pOp; /* Current operation */ - int rc = SQLITE_OK; /* Value to return */ - sqlite3 *db = p->db; /* The database */ - u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ - u8 encoding = ENC(db); /* The database encoding */ -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - int checkProgress; /* True if progress callbacks are enabled */ - int nProgressOps = 0; /* Opcodes executed since progress callback. */ -#endif - Mem *aMem = p->aMem; /* Copy of p->aMem */ - Mem *pIn1 = 0; /* 1st input operand */ - Mem *pIn2 = 0; /* 2nd input operand */ - Mem *pIn3 = 0; /* 3rd input operand */ - Mem *pOut = 0; /* Output operand */ - int iCompare = 0; /* Result of last OP_Compare operation */ - int *aPermute = 0; /* Permutation of columns for OP_Compare */ - i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ -#ifdef VDBE_PROFILE - u64 start; /* CPU clock count at start of opcode */ - int origPc; /* Program counter at start of opcode */ -#endif - /******************************************************************** - ** Automatically generated code - ** - ** The following union is automatically generated by the - ** vdbe-compress.tcl script. The purpose of this union is to - ** reduce the amount of stack space required by this function. - ** See comments in the vdbe-compress.tcl script for details. - */ - union vdbeExecUnion { - struct OP_Yield_stack_vars { - int pcDest; - } aa; - struct OP_Null_stack_vars { - int cnt; - u16 nullFlag; - } ab; - struct OP_Variable_stack_vars { - Mem *pVar; /* Value being transferred */ - } ac; - struct OP_Move_stack_vars { - char *zMalloc; /* Holding variable for allocated memory */ - int n; /* Number of registers left to copy */ - int p1; /* Register to copy from */ - int p2; /* Register to copy to */ - } ad; - struct OP_Copy_stack_vars { - int n; - } ae; - struct OP_ResultRow_stack_vars { - Mem *pMem; - int i; - } af; - struct OP_Concat_stack_vars { - i64 nByte; - } ag; - struct OP_Remainder_stack_vars { - char bIntint; /* Started out as two integer operands */ - int flags; /* Combined MEM_* flags from both inputs */ - i64 iA; /* Integer value of left operand */ - i64 iB; /* Integer value of right operand */ - double rA; /* Real value of left operand */ - double rB; /* Real value of right operand */ - } ah; - struct OP_Function_stack_vars { - int i; - Mem *pArg; - sqlite3_context ctx; - sqlite3_value **apVal; - int n; - } ai; - struct OP_ShiftRight_stack_vars { - i64 iA; - u64 uA; - i64 iB; - u8 op; - } aj; - struct OP_Ge_stack_vars { - int res; /* Result of the comparison of pIn1 against pIn3 */ - char affinity; /* Affinity to use for comparison */ - u16 flags1; /* Copy of initial value of pIn1->flags */ - u16 flags3; /* Copy of initial value of pIn3->flags */ - } ak; - struct OP_Compare_stack_vars { - int n; - int i; - int p1; - int p2; - const KeyInfo *pKeyInfo; - int idx; - CollSeq *pColl; /* Collating sequence to use on this term */ - int bRev; /* True for DESCENDING sort order */ - } al; - struct OP_Or_stack_vars { - int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - } am; - struct OP_IfNot_stack_vars { - int c; - } an; - struct OP_Column_stack_vars { - u32 payloadSize; /* Number of bytes in the record */ - i64 payloadSize64; /* Number of bytes in the record */ - int p1; /* P1 value of the opcode */ - int p2; /* column number to retrieve */ - VdbeCursor *pC; /* The VDBE cursor */ - char *zRec; /* Pointer to complete record-data */ - BtCursor *pCrsr; /* The BTree cursor */ - u32 *aType; /* aType[i] holds the numeric type of the i-th column */ - u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ - int nField; /* number of fields in the record */ - int len; /* The length of the serialized data for the column */ - int i; /* Loop counter */ - char *zData; /* Part of the record being decoded */ - Mem *pDest; /* Where to write the extracted value */ - Mem sMem; /* For storing the record being decoded */ - u8 *zIdx; /* Index into header */ - u8 *zEndHdr; /* Pointer to first byte after the header */ - u32 offset; /* Offset into the data */ - u32 szField; /* Number of bytes in the content of a field */ - int szHdr; /* Size of the header size field at start of record */ - int avail; /* Number of bytes of available data */ - u32 t; /* A type code from the record header */ - Mem *pReg; /* PseudoTable input register */ - } ao; - struct OP_Affinity_stack_vars { - const char *zAffinity; /* The affinity to be applied */ - char cAff; /* A single character of affinity */ - } ap; - struct OP_MakeRecord_stack_vars { - u8 *zNewRecord; /* A buffer to hold the data for the new record */ - Mem *pRec; /* The new record */ - u64 nData; /* Number of bytes of data space */ - int nHdr; /* Number of bytes of header space */ - i64 nByte; /* Data space required for this record */ - int nZero; /* Number of zero bytes at the end of the record */ - int nVarint; /* Number of bytes in a varint */ - u32 serial_type; /* Type field */ - Mem *pData0; /* First field to be combined into the record */ - Mem *pLast; /* Last field of the record */ - int nField; /* Number of fields in the record */ - char *zAffinity; /* The affinity string for the record */ - int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] */ - int len; /* Length of a field */ - } aq; - struct OP_Count_stack_vars { - i64 nEntry; - BtCursor *pCrsr; - } ar; - struct OP_Savepoint_stack_vars { - int p1; /* Value of P1 operand */ - char *zName; /* Name of savepoint */ - int nName; - Savepoint *pNew; - Savepoint *pSavepoint; - Savepoint *pTmp; - int iSavepoint; - int ii; - } as; - struct OP_AutoCommit_stack_vars { - int desiredAutoCommit; - int iRollback; - int turnOnAC; - } at; - struct OP_Transaction_stack_vars { - Btree *pBt; - } au; - struct OP_ReadCookie_stack_vars { - int iMeta; - int iDb; - int iCookie; - } av; - struct OP_SetCookie_stack_vars { - Db *pDb; - } aw; - struct OP_VerifyCookie_stack_vars { - int iMeta; - int iGen; - Btree *pBt; - } ax; - struct OP_OpenWrite_stack_vars { - int nField; - KeyInfo *pKeyInfo; - int p2; - int iDb; - int wrFlag; - Btree *pX; - VdbeCursor *pCur; - Db *pDb; - } ay; - struct OP_OpenEphemeral_stack_vars { - VdbeCursor *pCx; - } az; - struct OP_SorterOpen_stack_vars { - VdbeCursor *pCx; - } ba; - struct OP_OpenPseudo_stack_vars { - VdbeCursor *pCx; - } bb; - struct OP_SeekGt_stack_vars { - int res; - int oc; - VdbeCursor *pC; - UnpackedRecord r; - int nField; - i64 iKey; /* The rowid we are to seek to */ - } bc; - struct OP_Seek_stack_vars { - VdbeCursor *pC; - } bd; - struct OP_Found_stack_vars { - int alreadyExists; - VdbeCursor *pC; - int res; - char *pFree; - UnpackedRecord *pIdxKey; - UnpackedRecord r; - char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; - } be; - struct OP_IsUnique_stack_vars { - u16 ii; - VdbeCursor *pCx; - BtCursor *pCrsr; - u16 nField; - Mem *aMx; - UnpackedRecord r; /* B-Tree index search key */ - i64 R; /* Rowid stored in register P3 */ - } bf; - struct OP_NotExists_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - u64 iKey; - } bg; - struct OP_NewRowid_stack_vars { - i64 v; /* The new rowid */ - VdbeCursor *pC; /* Cursor of table to get the new rowid */ - int res; /* Result of an sqlite3BtreeLast() */ - int cnt; /* Counter to limit the number of searches */ - Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ - VdbeFrame *pFrame; /* Root frame of VDBE */ - } bh; - struct OP_InsertInt_stack_vars { - Mem *pData; /* MEM cell holding data for the record to be inserted */ - Mem *pKey; /* MEM cell holding key for the record */ - i64 iKey; /* The integer ROWID or key for the record to be inserted */ - VdbeCursor *pC; /* Cursor to table into which insert is written */ - int nZero; /* Number of zero-bytes to append */ - int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ - const char *zDb; /* database name - used by the update hook */ - const char *zTbl; /* Table name - used by the opdate hook */ - int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ - } bi; - struct OP_Delete_stack_vars { - i64 iKey; - VdbeCursor *pC; - } bj; - struct OP_SorterCompare_stack_vars { - VdbeCursor *pC; - int res; - } bk; - struct OP_SorterData_stack_vars { - VdbeCursor *pC; - } bl; - struct OP_RowData_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - u32 n; - i64 n64; - } bm; - struct OP_Rowid_stack_vars { - VdbeCursor *pC; - i64 v; - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - } bn; - struct OP_NullRow_stack_vars { - VdbeCursor *pC; - } bo; - struct OP_Last_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - } bp; - struct OP_Rewind_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - } bq; - struct OP_Next_stack_vars { - VdbeCursor *pC; - int res; - } br; - struct OP_IdxInsert_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int nKey; - const char *zKey; - } bs; - struct OP_IdxDelete_stack_vars { - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - UnpackedRecord r; - } bt; - struct OP_IdxRowid_stack_vars { - BtCursor *pCrsr; - VdbeCursor *pC; - i64 rowid; - } bu; - struct OP_IdxGE_stack_vars { - VdbeCursor *pC; - int res; - UnpackedRecord r; - } bv; - struct OP_Destroy_stack_vars { - int iMoved; - int iCnt; - Vdbe *pVdbe; - int iDb; - } bw; - struct OP_Clear_stack_vars { - int nChange; - } bx; - struct OP_CreateTable_stack_vars { - int pgno; - int flags; - Db *pDb; - } by; - struct OP_ParseSchema_stack_vars { - int iDb; - const char *zMaster; - char *zSql; - InitData initData; - } bz; - struct OP_IntegrityCk_stack_vars { - int nRoot; /* Number of tables to check. (Number of root pages.) */ - int *aRoot; /* Array of rootpage numbers for tables to be checked */ - int j; /* Loop counter */ - int nErr; /* Number of errors reported */ - char *z; /* Text of the error report */ - Mem *pnErr; /* Register keeping track of errors remaining */ - } ca; - struct OP_RowSetRead_stack_vars { - i64 val; - } cb; - struct OP_RowSetTest_stack_vars { - int iSet; - int exists; - } cc; - struct OP_Program_stack_vars { - int nMem; /* Number of memory registers for sub-program */ - int nByte; /* Bytes of runtime space required for sub-program */ - Mem *pRt; /* Register to allocate runtime space */ - Mem *pMem; /* Used to iterate through memory cells */ - Mem *pEnd; /* Last memory cell in new array */ - VdbeFrame *pFrame; /* New vdbe frame to execute in */ - SubProgram *pProgram; /* Sub-program to execute */ - void *t; /* Token identifying trigger */ - } cd; - struct OP_Param_stack_vars { - VdbeFrame *pFrame; - Mem *pIn; - } ce; - struct OP_MemMax_stack_vars { - Mem *pIn1; - VdbeFrame *pFrame; - } cf; - struct OP_AggStep_stack_vars { - int n; - int i; - Mem *pMem; - Mem *pRec; - sqlite3_context ctx; - sqlite3_value **apVal; - } cg; - struct OP_AggFinal_stack_vars { - Mem *pMem; - } ch; - struct OP_Checkpoint_stack_vars { - int i; /* Loop counter */ - int aRes[3]; /* Results */ - Mem *pMem; /* Write results here */ - } ci; - struct OP_JournalMode_stack_vars { - Btree *pBt; /* Btree to change journal mode of */ - Pager *pPager; /* Pager associated with pBt */ - int eNew; /* New journal mode */ - int eOld; /* The old journal mode */ -#ifndef SQLITE_OMIT_WAL - const char *zFilename; /* Name of database file for pPager */ -#endif - } cj; - struct OP_IncrVacuum_stack_vars { - Btree *pBt; - } ck; - struct OP_VBegin_stack_vars { - VTable *pVTab; - } cl; - struct OP_VOpen_stack_vars { - VdbeCursor *pCur; - sqlite3_vtab_cursor *pVtabCursor; - sqlite3_vtab *pVtab; - sqlite3_module *pModule; - } cm; - struct OP_VFilter_stack_vars { - int nArg; - int iQuery; - const sqlite3_module *pModule; - Mem *pQuery; - Mem *pArgc; - sqlite3_vtab_cursor *pVtabCursor; - sqlite3_vtab *pVtab; - VdbeCursor *pCur; - int res; - int i; - Mem **apArg; - } cn; - struct OP_VColumn_stack_vars { - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - Mem *pDest; - sqlite3_context sContext; - } co; - struct OP_VNext_stack_vars { - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - int res; - VdbeCursor *pCur; - } cp; - struct OP_VRename_stack_vars { - sqlite3_vtab *pVtab; - Mem *pName; - } cq; - struct OP_VUpdate_stack_vars { - sqlite3_vtab *pVtab; - sqlite3_module *pModule; - int nArg; - int i; - sqlite_int64 rowid; - Mem **apArg; - Mem *pX; - } cr; - struct OP_Trace_stack_vars { - char *zTrace; - char *z; - } cs; - } u; - /* End automatically generated code - ********************************************************************/ - - assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ - sqlite3VdbeEnter(p); - if( p->rc==SQLITE_NOMEM ){ - /* This happens if a malloc() inside a call to sqlite3_column_text() or - ** sqlite3_column_text16() failed. */ - goto no_mem; - } - assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); - p->rc = SQLITE_OK; - assert( p->explain==0 ); - p->pResultSet = 0; - db->busyHandler.nBusy = 0; - CHECK_FOR_INTERRUPT; - sqlite3VdbeIOTraceSql(p); -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - checkProgress = db->xProgress!=0; -#endif -#ifdef SQLITE_DEBUG - sqlite3BeginBenignMalloc(); - if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){ - int i; - printf("VDBE Program Listing:\n"); - sqlite3VdbePrintSql(p); - for(i=0; inOp; i++){ - sqlite3VdbePrintOp(stdout, i, &aOp[i]); - } - } - sqlite3EndBenignMalloc(); -#endif - for(pc=p->pc; rc==SQLITE_OK; pc++){ - assert( pc>=0 && pcnOp ); - if( db->mallocFailed ) goto no_mem; -#ifdef VDBE_PROFILE - origPc = pc; - start = sqlite3Hwtime(); -#endif - pOp = &aOp[pc]; - - /* Only allow tracing if SQLITE_DEBUG is defined. - */ -#ifdef SQLITE_DEBUG - if( p->trace ){ - if( pc==0 ){ - printf("VDBE Execution Trace:\n"); - sqlite3VdbePrintSql(p); - } - sqlite3VdbePrintOp(p->trace, pc, pOp); - } -#endif - - - /* Check to see if we need to simulate an interrupt. This only happens - ** if we have a special test build. - */ -#ifdef SQLITE_TEST - if( sqlite3_interrupt_count>0 ){ - sqlite3_interrupt_count--; - if( sqlite3_interrupt_count==0 ){ - sqlite3_interrupt(db); - } - } -#endif - -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - /* Call the progress callback if it is configured and the required number - ** of VDBE ops have been executed (either since this invocation of - ** sqlite3VdbeExec() or since last time the progress callback was called). - ** If the progress callback returns non-zero, exit the virtual machine with - ** a return code SQLITE_ABORT. - */ - if( checkProgress ){ - if( db->nProgressOps==nProgressOps ){ - int prc; - prc = db->xProgress(db->pProgressArg); - if( prc!=0 ){ - rc = SQLITE_INTERRUPT; - goto vdbe_error_halt; - } - nProgressOps = 0; - } - nProgressOps++; - } -#endif - - /* On any opcode with the "out2-prerelease" tag, free any - ** external allocations out of mem[p2] and set mem[p2] to be - ** an undefined integer. Opcodes will either fill in the integer - ** value or convert mem[p2] to a different type. - */ - assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); - if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=p->nMem ); - pOut = &aMem[pOp->p2]; - memAboutToChange(p, pOut); - VdbeMemRelease(pOut); - pOut->flags = MEM_Int; - } - - /* Sanity checking on other operands */ -#ifdef SQLITE_DEBUG - if( (pOp->opflags & OPFLG_IN1)!=0 ){ - assert( pOp->p1>0 ); - assert( pOp->p1<=p->nMem ); - assert( memIsValid(&aMem[pOp->p1]) ); - REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]); - } - if( (pOp->opflags & OPFLG_IN2)!=0 ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=p->nMem ); - assert( memIsValid(&aMem[pOp->p2]) ); - REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]); - } - if( (pOp->opflags & OPFLG_IN3)!=0 ){ - assert( pOp->p3>0 ); - assert( pOp->p3<=p->nMem ); - assert( memIsValid(&aMem[pOp->p3]) ); - REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]); - } - if( (pOp->opflags & OPFLG_OUT2)!=0 ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=p->nMem ); - memAboutToChange(p, &aMem[pOp->p2]); - } - if( (pOp->opflags & OPFLG_OUT3)!=0 ){ - assert( pOp->p3>0 ); - assert( pOp->p3<=p->nMem ); - memAboutToChange(p, &aMem[pOp->p3]); - } -#endif - - switch( pOp->opcode ){ - -/***************************************************************************** -** What follows is a massive switch statement where each case implements a -** separate instruction in the virtual machine. If we follow the usual -** indentation conventions, each case should be indented by 6 spaces. But -** that is a lot of wasted space on the left margin. So the code within -** the switch statement will break with convention and be flush-left. Another -** big comment (similar to this one) will mark the point in the code where -** we transition back to normal indentation. -** -** The formatting of each case is important. The makefile for SQLite -** generates two C files "opcodes.h" and "opcodes.c" by scanning this -** file looking for lines that begin with "case OP_". The opcodes.h files -** will be filled with #defines that give unique integer values to each -** opcode and the opcodes.c file is filled with an array of strings where -** each string is the symbolic name for the corresponding opcode. If the -** case statement is followed by a comment of the form "/# same as ... #/" -** that comment is used to determine the particular value of the opcode. -** -** Other keywords in the comment that follows each case are used to -** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[]. -** Keywords include: in1, in2, in3, out2_prerelease, out2, out3. See -** the mkopcodeh.awk script for additional information. -** -** Documentation about VDBE opcodes is generated by scanning this file -** for lines of that contain "Opcode:". That line and all subsequent -** comment lines are used in the generation of the opcode.html documentation -** file. -** -** SUMMARY: -** -** Formatting is important to scripts that scan this file. -** Do not deviate from the formatting style currently in use. -** -*****************************************************************************/ - -/* Opcode: Goto * P2 * * * -** -** An unconditional jump to address P2. -** The next instruction executed will be -** the one at index P2 from the beginning of -** the program. -*/ -case OP_Goto: { /* jump */ - CHECK_FOR_INTERRUPT; - pc = pOp->p2 - 1; - break; -} - -/* Opcode: Gosub P1 P2 * * * -** -** Write the current address onto register P1 -** and then jump to address P2. -*/ -case OP_Gosub: { /* jump */ - assert( pOp->p1>0 && pOp->p1<=p->nMem ); - pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Dyn)==0 ); - memAboutToChange(p, pIn1); - pIn1->flags = MEM_Int; - pIn1->u.i = pc; - REGISTER_TRACE(pOp->p1, pIn1); - pc = pOp->p2 - 1; - break; -} - -/* Opcode: Return P1 * * * * -** -** Jump to the next instruction after the address in register P1. -*/ -case OP_Return: { /* in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags & MEM_Int ); - pc = (int)pIn1->u.i; - break; -} - -/* Opcode: Yield P1 * * * * -** -** Swap the program counter with the value in register P1. -*/ -case OP_Yield: { /* in1 */ -#if 0 /* local variables moved into u.aa */ - int pcDest; -#endif /* local variables moved into u.aa */ - pIn1 = &aMem[pOp->p1]; - assert( (pIn1->flags & MEM_Dyn)==0 ); - pIn1->flags = MEM_Int; - u.aa.pcDest = (int)pIn1->u.i; - pIn1->u.i = pc; - REGISTER_TRACE(pOp->p1, pIn1); - pc = u.aa.pcDest; - break; -} - -/* Opcode: HaltIfNull P1 P2 P3 P4 * -** -** Check the value in register P3. If it is NULL then Halt using -** parameter P1, P2, and P4 as if this were a Halt instruction. If the -** value in register P3 is not NULL, then this routine is a no-op. -*/ -case OP_HaltIfNull: { /* in3 */ - pIn3 = &aMem[pOp->p3]; - if( (pIn3->flags & MEM_Null)==0 ) break; - /* Fall through into OP_Halt */ -} - -/* Opcode: Halt P1 P2 * P4 * -** -** Exit immediately. All open cursors, etc are closed -** automatically. -** -** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), -** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0). -** For errors, it can be some other value. If P1!=0 then P2 will determine -** whether or not to rollback the current transaction. Do not rollback -** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, -** then back out all changes that have occurred during this execution of the -** VDBE, but do not rollback the transaction. -** -** If P4 is not null then it is an error message string. -** -** There is an implied "Halt 0 0 0" instruction inserted at the very end of -** every program. So a jump past the last instruction of the program -** is the same as executing Halt. -*/ -case OP_Halt: { - if( pOp->p1==SQLITE_OK && p->pFrame ){ - /* Halt the sub-program. Return control to the parent frame. */ - VdbeFrame *pFrame = p->pFrame; - p->pFrame = pFrame->pParent; - p->nFrame--; - sqlite3VdbeSetChanges(db, p->nChange); - pc = sqlite3VdbeFrameRestore(pFrame); - lastRowid = db->lastRowid; - if( pOp->p2==OE_Ignore ){ - /* Instruction pc is the OP_Program that invoked the sub-program - ** currently being halted. If the p2 instruction of this OP_Halt - ** instruction is set to OE_Ignore, then the sub-program is throwing - ** an IGNORE exception. In this case jump to the address specified - ** as the p2 of the calling OP_Program. */ - pc = p->aOp[pc].p2-1; - } - aOp = p->aOp; - aMem = p->aMem; - break; - } - - p->rc = pOp->p1; - p->errorAction = (u8)pOp->p2; - p->pc = pc; - if( pOp->p4.z ){ - assert( p->rc!=SQLITE_OK ); - sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z); - }else if( p->rc ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql); - } - rc = sqlite3VdbeHalt(p); - assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); - if( rc==SQLITE_BUSY ){ - p->rc = rc = SQLITE_BUSY; - }else{ - assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); - assert( rc==SQLITE_OK || db->nDeferredCons>0 ); - rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; - } - goto vdbe_return; -} - -/* Opcode: Integer P1 P2 * * * -** -** The 32-bit integer value P1 is written into register P2. -*/ -case OP_Integer: { /* out2-prerelease */ - pOut->u.i = pOp->p1; - break; -} - -/* Opcode: Int64 * P2 * P4 * -** -** P4 is a pointer to a 64-bit integer value. -** Write that value into register P2. -*/ -case OP_Int64: { /* out2-prerelease */ - assert( pOp->p4.pI64!=0 ); - pOut->u.i = *pOp->p4.pI64; - break; -} - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* Opcode: Real * P2 * P4 * -** -** P4 is a pointer to a 64-bit floating point value. -** Write that value into register P2. -*/ -case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ - pOut->flags = MEM_Real; - assert( !sqlite3IsNaN(*pOp->p4.pReal) ); - pOut->r = *pOp->p4.pReal; - break; -} -#endif - -/* Opcode: String8 * P2 * P4 * -** -** P4 points to a nul terminated UTF-8 string. This opcode is transformed -** into an OP_String before it is executed for the first time. -*/ -case OP_String8: { /* same as TK_STRING, out2-prerelease */ - assert( pOp->p4.z!=0 ); - pOp->opcode = OP_String; - pOp->p1 = sqlite3Strlen30(pOp->p4.z); - -#ifndef SQLITE_OMIT_UTF16 - if( encoding!=SQLITE_UTF8 ){ - rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); - if( rc==SQLITE_TOOBIG ) goto too_big; - if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; - assert( pOut->zMalloc==pOut->z ); - assert( pOut->flags & MEM_Dyn ); - pOut->zMalloc = 0; - pOut->flags |= MEM_Static; - pOut->flags &= ~MEM_Dyn; - if( pOp->p4type==P4_DYNAMIC ){ - sqlite3DbFree(db, pOp->p4.z); - } - pOp->p4type = P4_DYNAMIC; - pOp->p4.z = pOut->z; - pOp->p1 = pOut->n; - } -#endif - if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - /* Fall through to the next case, OP_String */ -} - -/* Opcode: String P1 P2 * P4 * -** -** The string value P4 of length P1 (bytes) is stored in register P2. -*/ -case OP_String: { /* out2-prerelease */ - assert( pOp->p4.z!=0 ); - pOut->flags = MEM_Str|MEM_Static|MEM_Term; - pOut->z = pOp->p4.z; - pOut->n = pOp->p1; - pOut->enc = encoding; - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Null P1 P2 P3 * * -** -** Write a NULL into registers P2. If P3 greater than P2, then also write -** NULL into register P3 and every register in between P2 and P3. If P3 -** is less than P2 (typically P3 is zero) then only register P2 is -** set to NULL. -** -** If the P1 value is non-zero, then also set the MEM_Cleared flag so that -** NULL values will not compare equal even if SQLITE_NULLEQ is set on -** OP_Ne or OP_Eq. -*/ -case OP_Null: { /* out2-prerelease */ -#if 0 /* local variables moved into u.ab */ - int cnt; - u16 nullFlag; -#endif /* local variables moved into u.ab */ - u.ab.cnt = pOp->p3-pOp->p2; - assert( pOp->p3<=p->nMem ); - pOut->flags = u.ab.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; - while( u.ab.cnt>0 ){ - pOut++; - memAboutToChange(p, pOut); - VdbeMemRelease(pOut); - pOut->flags = u.ab.nullFlag; - u.ab.cnt--; - } - break; -} - - -/* Opcode: Blob P1 P2 * P4 -** -** P4 points to a blob of data P1 bytes long. Store this -** blob in register P2. -*/ -case OP_Blob: { /* out2-prerelease */ - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); - sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); - pOut->enc = encoding; - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Variable P1 P2 * P4 * -** -** Transfer the values of bound parameter P1 into register P2 -** -** If the parameter is named, then its name appears in P4 and P3==1. -** The P4 value is used by sqlite3_bind_parameter_name(). -*/ -case OP_Variable: { /* out2-prerelease */ -#if 0 /* local variables moved into u.ac */ - Mem *pVar; /* Value being transferred */ -#endif /* local variables moved into u.ac */ - - assert( pOp->p1>0 && pOp->p1<=p->nVar ); - assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] ); - u.ac.pVar = &p->aVar[pOp->p1 - 1]; - if( sqlite3VdbeMemTooBig(u.ac.pVar) ){ - goto too_big; - } - sqlite3VdbeMemShallowCopy(pOut, u.ac.pVar, MEM_Static); - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Move P1 P2 P3 * * -** -** Move the values in register P1..P1+P3 over into -** registers P2..P2+P3. Registers P1..P1+P3 are -** left holding a NULL. It is an error for register ranges -** P1..P1+P3 and P2..P2+P3 to overlap. -*/ -case OP_Move: { -#if 0 /* local variables moved into u.ad */ - char *zMalloc; /* Holding variable for allocated memory */ - int n; /* Number of registers left to copy */ - int p1; /* Register to copy from */ - int p2; /* Register to copy to */ -#endif /* local variables moved into u.ad */ - - u.ad.n = pOp->p3 + 1; - u.ad.p1 = pOp->p1; - u.ad.p2 = pOp->p2; - assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 ); - assert( u.ad.p1+u.ad.n<=u.ad.p2 || u.ad.p2+u.ad.n<=u.ad.p1 ); - - pIn1 = &aMem[u.ad.p1]; - pOut = &aMem[u.ad.p2]; - while( u.ad.n-- ){ - assert( pOut<=&aMem[p->nMem] ); - assert( pIn1<=&aMem[p->nMem] ); - assert( memIsValid(pIn1) ); - memAboutToChange(p, pOut); - u.ad.zMalloc = pOut->zMalloc; - pOut->zMalloc = 0; - sqlite3VdbeMemMove(pOut, pIn1); -#ifdef SQLITE_DEBUG - if( pOut->pScopyFrom>=&aMem[u.ad.p1] && pOut->pScopyFrom<&aMem[u.ad.p1+pOp->p3] ){ - pOut->pScopyFrom += u.ad.p1 - pOp->p2; - } -#endif - pIn1->zMalloc = u.ad.zMalloc; - REGISTER_TRACE(u.ad.p2++, pOut); - pIn1++; - pOut++; - } - break; -} - -/* Opcode: Copy P1 P2 P3 * * -** -** Make a copy of registers P1..P1+P3 into registers P2..P2+P3. -** -** This instruction makes a deep copy of the value. A duplicate -** is made of any string or blob constant. See also OP_SCopy. -*/ -case OP_Copy: { -#if 0 /* local variables moved into u.ae */ - int n; -#endif /* local variables moved into u.ae */ - - u.ae.n = pOp->p3; - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - assert( pOut!=pIn1 ); - while( 1 ){ - sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); - Deephemeralize(pOut); -#ifdef SQLITE_DEBUG - pOut->pScopyFrom = 0; -#endif - REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut); - if( (u.ae.n--)==0 ) break; - pOut++; - pIn1++; - } - break; -} - -/* Opcode: SCopy P1 P2 * * * -** -** Make a shallow copy of register P1 into register P2. -** -** This instruction makes a shallow copy of the value. If the value -** is a string or blob, then the copy is only a pointer to the -** original and hence if the original changes so will the copy. -** Worse, if the original is deallocated, the copy becomes invalid. -** Thus the program must guarantee that the original will not change -** during the lifetime of the copy. Use OP_Copy to make a complete -** copy. -*/ -case OP_SCopy: { /* in1, out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - assert( pOut!=pIn1 ); - sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); -#ifdef SQLITE_DEBUG - if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1; -#endif - REGISTER_TRACE(pOp->p2, pOut); - break; -} - -/* Opcode: ResultRow P1 P2 * * * -** -** The registers P1 through P1+P2-1 contain a single row of -** results. This opcode causes the sqlite3_step() call to terminate -** with an SQLITE_ROW return code and it sets up the sqlite3_stmt -** structure to provide access to the top P1 values as the result -** row. -*/ -case OP_ResultRow: { -#if 0 /* local variables moved into u.af */ - Mem *pMem; - int i; -#endif /* local variables moved into u.af */ - assert( p->nResColumn==pOp->p2 ); - assert( pOp->p1>0 ); - assert( pOp->p1+pOp->p2<=p->nMem+1 ); - - /* If this statement has violated immediate foreign key constraints, do - ** not return the number of rows modified. And do not RELEASE the statement - ** transaction. It needs to be rolled back. */ - if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){ - assert( db->flags&SQLITE_CountRows ); - assert( p->usesStmtJournal ); - break; - } - - /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then - ** DML statements invoke this opcode to return the number of rows - ** modified to the user. This is the only way that a VM that - ** opens a statement transaction may invoke this opcode. - ** - ** In case this is such a statement, close any statement transaction - ** opened by this VM before returning control to the user. This is to - ** ensure that statement-transactions are always nested, not overlapping. - ** If the open statement-transaction is not closed here, then the user - ** may step another VM that opens its own statement transaction. This - ** may lead to overlapping statement transactions. - ** - ** The statement transaction is never a top-level transaction. Hence - ** the RELEASE call below can never fail. - */ - assert( p->iStatement==0 || db->flags&SQLITE_CountRows ); - rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE); - if( NEVER(rc!=SQLITE_OK) ){ - break; - } - - /* Invalidate all ephemeral cursor row caches */ - p->cacheCtr = (p->cacheCtr + 2)|1; - - /* Make sure the results of the current row are \000 terminated - ** and have an assigned type. The results are de-ephemeralized as - ** a side effect. - */ - u.af.pMem = p->pResultSet = &aMem[pOp->p1]; - for(u.af.i=0; u.af.ip2; u.af.i++){ - assert( memIsValid(&u.af.pMem[u.af.i]) ); - Deephemeralize(&u.af.pMem[u.af.i]); - assert( (u.af.pMem[u.af.i].flags & MEM_Ephem)==0 - || (u.af.pMem[u.af.i].flags & (MEM_Str|MEM_Blob))==0 ); - sqlite3VdbeMemNulTerminate(&u.af.pMem[u.af.i]); - sqlite3VdbeMemStoreType(&u.af.pMem[u.af.i]); - REGISTER_TRACE(pOp->p1+u.af.i, &u.af.pMem[u.af.i]); - } - if( db->mallocFailed ) goto no_mem; - - /* Return SQLITE_ROW - */ - p->pc = pc + 1; - rc = SQLITE_ROW; - goto vdbe_return; -} - -/* Opcode: Concat P1 P2 P3 * * -** -** Add the text in register P1 onto the end of the text in -** register P2 and store the result in register P3. -** If either the P1 or P2 text are NULL then store NULL in P3. -** -** P3 = P2 || P1 -** -** It is illegal for P1 and P3 to be the same register. Sometimes, -** if P3 is the same register as P2, the implementation is able -** to avoid a memcpy(). -*/ -case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ -#if 0 /* local variables moved into u.ag */ - i64 nByte; -#endif /* local variables moved into u.ag */ - - pIn1 = &aMem[pOp->p1]; - pIn2 = &aMem[pOp->p2]; - pOut = &aMem[pOp->p3]; - assert( pIn1!=pOut ); - if( (pIn1->flags | pIn2->flags) & MEM_Null ){ - sqlite3VdbeMemSetNull(pOut); - break; - } - if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem; - Stringify(pIn1, encoding); - Stringify(pIn2, encoding); - u.ag.nByte = pIn1->n + pIn2->n; - if( u.ag.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - MemSetTypeFlag(pOut, MEM_Str); - if( sqlite3VdbeMemGrow(pOut, (int)u.ag.nByte+2, pOut==pIn2) ){ - goto no_mem; - } - if( pOut!=pIn2 ){ - memcpy(pOut->z, pIn2->z, pIn2->n); - } - memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); - pOut->z[u.ag.nByte] = 0; - pOut->z[u.ag.nByte+1] = 0; - pOut->flags |= MEM_Term; - pOut->n = (int)u.ag.nByte; - pOut->enc = encoding; - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Add P1 P2 P3 * * -** -** Add the value in register P1 to the value in register P2 -** and store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: Multiply P1 P2 P3 * * -** -** -** Multiply the value in register P1 by the value in register P2 -** and store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: Subtract P1 P2 P3 * * -** -** Subtract the value in register P1 from the value in register P2 -** and store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: Divide P1 P2 P3 * * -** -** Divide the value in register P1 by the value in register P2 -** and store the result in register P3 (P3=P2/P1). If the value in -** register P1 is zero, then the result is NULL. If either input is -** NULL, the result is NULL. -*/ -/* Opcode: Remainder P1 P2 P3 * * -** -** Compute the remainder after integer division of the value in -** register P1 by the value in register P2 and store the result in P3. -** If the value in register P2 is zero the result is NULL. -** If either operand is NULL, the result is NULL. -*/ -case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ -case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ -case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ -case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ -case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ -#if 0 /* local variables moved into u.ah */ - char bIntint; /* Started out as two integer operands */ - int flags; /* Combined MEM_* flags from both inputs */ - i64 iA; /* Integer value of left operand */ - i64 iB; /* Integer value of right operand */ - double rA; /* Real value of left operand */ - double rB; /* Real value of right operand */ -#endif /* local variables moved into u.ah */ - - pIn1 = &aMem[pOp->p1]; - applyNumericAffinity(pIn1); - pIn2 = &aMem[pOp->p2]; - applyNumericAffinity(pIn2); - pOut = &aMem[pOp->p3]; - u.ah.flags = pIn1->flags | pIn2->flags; - if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; - if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ - u.ah.iA = pIn1->u.i; - u.ah.iB = pIn2->u.i; - u.ah.bIntint = 1; - switch( pOp->opcode ){ - case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; - case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; - case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; - case OP_Divide: { - if( u.ah.iA==0 ) goto arithmetic_result_is_null; - if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math; - u.ah.iB /= u.ah.iA; - break; - } - default: { - if( u.ah.iA==0 ) goto arithmetic_result_is_null; - if( u.ah.iA==-1 ) u.ah.iA = 1; - u.ah.iB %= u.ah.iA; - break; - } - } - pOut->u.i = u.ah.iB; - MemSetTypeFlag(pOut, MEM_Int); - }else{ - u.ah.bIntint = 0; -fp_math: - u.ah.rA = sqlite3VdbeRealValue(pIn1); - u.ah.rB = sqlite3VdbeRealValue(pIn2); - switch( pOp->opcode ){ - case OP_Add: u.ah.rB += u.ah.rA; break; - case OP_Subtract: u.ah.rB -= u.ah.rA; break; - case OP_Multiply: u.ah.rB *= u.ah.rA; break; - case OP_Divide: { - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - if( u.ah.rA==(double)0 ) goto arithmetic_result_is_null; - u.ah.rB /= u.ah.rA; - break; - } - default: { - u.ah.iA = (i64)u.ah.rA; - u.ah.iB = (i64)u.ah.rB; - if( u.ah.iA==0 ) goto arithmetic_result_is_null; - if( u.ah.iA==-1 ) u.ah.iA = 1; - u.ah.rB = (double)(u.ah.iB % u.ah.iA); - break; - } - } -#ifdef SQLITE_OMIT_FLOATING_POINT - pOut->u.i = u.ah.rB; - MemSetTypeFlag(pOut, MEM_Int); -#else - if( sqlite3IsNaN(u.ah.rB) ){ - goto arithmetic_result_is_null; - } - pOut->r = u.ah.rB; - MemSetTypeFlag(pOut, MEM_Real); - if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){ - sqlite3VdbeIntegerAffinity(pOut); - } -#endif - } - break; - -arithmetic_result_is_null: - sqlite3VdbeMemSetNull(pOut); - break; -} - -/* Opcode: CollSeq P1 * * P4 -** -** P4 is a pointer to a CollSeq struct. If the next call to a user function -** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will -** be returned. This is used by the built-in min(), max() and nullif() -** functions. -** -** If P1 is not zero, then it is a register that a subsequent min() or -** max() aggregate will set to 1 if the current row is not the minimum or -** maximum. The P1 register is initialized to 0 by this instruction. -** -** The interface used by the implementation of the aforementioned functions -** to retrieve the collation sequence set by this opcode is not available -** publicly, only to user functions defined in func.c. -*/ -case OP_CollSeq: { - assert( pOp->p4type==P4_COLLSEQ ); - if( pOp->p1 ){ - sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0); - } - break; -} - -/* Opcode: Function P1 P2 P3 P4 P5 -** -** Invoke a user function (P4 is a pointer to a Function structure that -** defines the function) with P5 arguments taken from register P2 and -** successors. The result of the function is stored in register P3. -** Register P3 must not be one of the function inputs. -** -** P1 is a 32-bit bitmask indicating whether or not each argument to the -** function was determined to be constant at compile time. If the first -** argument was constant then bit 0 of P1 is set. This is used to determine -** whether meta data associated with a user function argument using the -** sqlite3_set_auxdata() API may be safely retained until the next -** invocation of this opcode. -** -** See also: AggStep and AggFinal -*/ -case OP_Function: { -#if 0 /* local variables moved into u.ai */ - int i; - Mem *pArg; - sqlite3_context ctx; - sqlite3_value **apVal; - int n; -#endif /* local variables moved into u.ai */ - - u.ai.n = pOp->p5; - u.ai.apVal = p->apArg; - assert( u.ai.apVal || u.ai.n==0 ); - assert( pOp->p3>0 && pOp->p3<=p->nMem ); - pOut = &aMem[pOp->p3]; - memAboutToChange(p, pOut); - - assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=p->nMem+1) ); - assert( pOp->p3p2 || pOp->p3>=pOp->p2+u.ai.n ); - u.ai.pArg = &aMem[pOp->p2]; - for(u.ai.i=0; u.ai.ip2+u.ai.i, u.ai.pArg); - } - - assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC ); - if( pOp->p4type==P4_FUNCDEF ){ - u.ai.ctx.pFunc = pOp->p4.pFunc; - u.ai.ctx.pVdbeFunc = 0; - }else{ - u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc; - u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc; - } - - u.ai.ctx.s.flags = MEM_Null; - u.ai.ctx.s.db = db; - u.ai.ctx.s.xDel = 0; - u.ai.ctx.s.zMalloc = 0; - - /* The output cell may already have a buffer allocated. Move - ** the pointer to u.ai.ctx.s so in case the user-function can use - ** the already allocated buffer instead of allocating a new one. - */ - sqlite3VdbeMemMove(&u.ai.ctx.s, pOut); - MemSetTypeFlag(&u.ai.ctx.s, MEM_Null); - - u.ai.ctx.isError = 0; - if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ - assert( pOp>aOp ); - assert( pOp[-1].p4type==P4_COLLSEQ ); - assert( pOp[-1].opcode==OP_CollSeq ); - u.ai.ctx.pColl = pOp[-1].p4.pColl; - } - db->lastRowid = lastRowid; - (*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */ - lastRowid = db->lastRowid; - - /* If any auxiliary data functions have been called by this user function, - ** immediately call the destructor for any non-static values. - */ - if( u.ai.ctx.pVdbeFunc ){ - sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1); - pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc; - pOp->p4type = P4_VDBEFUNC; - } - - if( db->mallocFailed ){ - /* Even though a malloc() has failed, the implementation of the - ** user function may have called an sqlite3_result_XXX() function - ** to return a value. The following call releases any resources - ** associated with such a value. - */ - sqlite3VdbeMemRelease(&u.ai.ctx.s); - goto no_mem; - } - - /* If the function returned an error, throw an exception */ - if( u.ai.ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s)); - rc = u.ai.ctx.isError; - } - - /* Copy the result of the function into register P3 */ - sqlite3VdbeChangeEncoding(&u.ai.ctx.s, encoding); - sqlite3VdbeMemMove(pOut, &u.ai.ctx.s); - if( sqlite3VdbeMemTooBig(pOut) ){ - goto too_big; - } - -#if 0 - /* The app-defined function has done something that as caused this - ** statement to expire. (Perhaps the function called sqlite3_exec() - ** with a CREATE TABLE statement.) - */ - if( p->expired ) rc = SQLITE_ABORT; -#endif - - REGISTER_TRACE(pOp->p3, pOut); - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: BitAnd P1 P2 P3 * * -** -** Take the bit-wise AND of the values in register P1 and P2 and -** store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: BitOr P1 P2 P3 * * -** -** Take the bit-wise OR of the values in register P1 and P2 and -** store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: ShiftLeft P1 P2 P3 * * -** -** Shift the integer value in register P2 to the left by the -** number of bits specified by the integer in register P1. -** Store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -/* Opcode: ShiftRight P1 P2 P3 * * -** -** Shift the integer value in register P2 to the right by the -** number of bits specified by the integer in register P1. -** Store the result in register P3. -** If either input is NULL, the result is NULL. -*/ -case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */ -case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */ -case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */ -case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ -#if 0 /* local variables moved into u.aj */ - i64 iA; - u64 uA; - i64 iB; - u8 op; -#endif /* local variables moved into u.aj */ - - pIn1 = &aMem[pOp->p1]; - pIn2 = &aMem[pOp->p2]; - pOut = &aMem[pOp->p3]; - if( (pIn1->flags | pIn2->flags) & MEM_Null ){ - sqlite3VdbeMemSetNull(pOut); - break; - } - u.aj.iA = sqlite3VdbeIntValue(pIn2); - u.aj.iB = sqlite3VdbeIntValue(pIn1); - u.aj.op = pOp->opcode; - if( u.aj.op==OP_BitAnd ){ - u.aj.iA &= u.aj.iB; - }else if( u.aj.op==OP_BitOr ){ - u.aj.iA |= u.aj.iB; - }else if( u.aj.iB!=0 ){ - assert( u.aj.op==OP_ShiftRight || u.aj.op==OP_ShiftLeft ); - - /* If shifting by a negative amount, shift in the other direction */ - if( u.aj.iB<0 ){ - assert( OP_ShiftRight==OP_ShiftLeft+1 ); - u.aj.op = 2*OP_ShiftLeft + 1 - u.aj.op; - u.aj.iB = u.aj.iB>(-64) ? -u.aj.iB : 64; - } - - if( u.aj.iB>=64 ){ - u.aj.iA = (u.aj.iA>=0 || u.aj.op==OP_ShiftLeft) ? 0 : -1; - }else{ - memcpy(&u.aj.uA, &u.aj.iA, sizeof(u.aj.uA)); - if( u.aj.op==OP_ShiftLeft ){ - u.aj.uA <<= u.aj.iB; - }else{ - u.aj.uA >>= u.aj.iB; - /* Sign-extend on a right shift of a negative number */ - if( u.aj.iA<0 ) u.aj.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.aj.iB); - } - memcpy(&u.aj.iA, &u.aj.uA, sizeof(u.aj.iA)); - } - } - pOut->u.i = u.aj.iA; - MemSetTypeFlag(pOut, MEM_Int); - break; -} - -/* Opcode: AddImm P1 P2 * * * -** -** Add the constant P2 to the value in register P1. -** The result is always an integer. -** -** To force any register to be an integer, just add 0. -*/ -case OP_AddImm: { /* in1 */ - pIn1 = &aMem[pOp->p1]; - memAboutToChange(p, pIn1); - sqlite3VdbeMemIntegerify(pIn1); - pIn1->u.i += pOp->p2; - break; -} - -/* Opcode: MustBeInt P1 P2 * * * -** -** Force the value in register P1 to be an integer. If the value -** in P1 is not an integer and cannot be converted into an integer -** without data loss, then jump immediately to P2, or if P2==0 -** raise an SQLITE_MISMATCH exception. -*/ -case OP_MustBeInt: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); - if( (pIn1->flags & MEM_Int)==0 ){ - if( pOp->p2==0 ){ - rc = SQLITE_MISMATCH; - goto abort_due_to_error; - }else{ - pc = pOp->p2 - 1; - } - }else{ - MemSetTypeFlag(pIn1, MEM_Int); - } - break; -} - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* Opcode: RealAffinity P1 * * * * -** -** If register P1 holds an integer convert it to a real value. -** -** This opcode is used when extracting information from a column that -** has REAL affinity. Such column values may still be stored as -** integers, for space efficiency, but after extraction we want them -** to have only a real value. -*/ -case OP_RealAffinity: { /* in1 */ - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Int ){ - sqlite3VdbeMemRealify(pIn1); - } - break; -} -#endif - -#ifndef SQLITE_OMIT_CAST -/* Opcode: ToText P1 * * * * -** -** Force the value in register P1 to be text. -** If the value is numeric, convert it to a string using the -** equivalent of printf(). Blob values are unchanged and -** are afterwards simply interpreted as text. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToText: { /* same as TK_TO_TEXT, in1 */ - pIn1 = &aMem[pOp->p1]; - memAboutToChange(p, pIn1); - if( pIn1->flags & MEM_Null ) break; - assert( MEM_Str==(MEM_Blob>>3) ); - pIn1->flags |= (pIn1->flags&MEM_Blob)>>3; - applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); - rc = ExpandBlob(pIn1); - assert( pIn1->flags & MEM_Str || db->mallocFailed ); - pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); - UPDATE_MAX_BLOBSIZE(pIn1); - break; -} - -/* Opcode: ToBlob P1 * * * * -** -** Force the value in register P1 to be a BLOB. -** If the value is numeric, convert it to a string first. -** Strings are simply reinterpreted as blobs with no change -** to the underlying data. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */ - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Null ) break; - if( (pIn1->flags & MEM_Blob)==0 ){ - applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); - assert( pIn1->flags & MEM_Str || db->mallocFailed ); - MemSetTypeFlag(pIn1, MEM_Blob); - }else{ - pIn1->flags &= ~(MEM_TypeMask&~MEM_Blob); - } - UPDATE_MAX_BLOBSIZE(pIn1); - break; -} - -/* Opcode: ToNumeric P1 * * * * -** -** Force the value in register P1 to be numeric (either an -** integer or a floating-point number.) -** If the value is text or blob, try to convert it to an using the -** equivalent of atoi() or atof() and store 0 if no such conversion -** is possible. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */ - pIn1 = &aMem[pOp->p1]; - sqlite3VdbeMemNumerify(pIn1); - break; -} -#endif /* SQLITE_OMIT_CAST */ - -/* Opcode: ToInt P1 * * * * -** -** Force the value in register P1 to be an integer. If -** The value is currently a real number, drop its fractional part. -** If the value is text or blob, try to convert it to an integer using the -** equivalent of atoi() and store 0 if no such conversion is possible. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToInt: { /* same as TK_TO_INT, in1 */ - pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_Null)==0 ){ - sqlite3VdbeMemIntegerify(pIn1); - } - break; -} - -#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) -/* Opcode: ToReal P1 * * * * -** -** Force the value in register P1 to be a floating point number. -** If The value is currently an integer, convert it. -** If the value is text or blob, try to convert it to an integer using the -** equivalent of atoi() and store 0.0 if no such conversion is possible. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToReal: { /* same as TK_TO_REAL, in1 */ - pIn1 = &aMem[pOp->p1]; - memAboutToChange(p, pIn1); - if( (pIn1->flags & MEM_Null)==0 ){ - sqlite3VdbeMemRealify(pIn1); - } - break; -} -#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */ - -/* Opcode: Lt P1 P2 P3 P4 P5 -** -** Compare the values in register P1 and P3. If reg(P3)flags */ - u16 flags3; /* Copy of initial value of pIn3->flags */ -#endif /* local variables moved into u.ak */ - - pIn1 = &aMem[pOp->p1]; - pIn3 = &aMem[pOp->p3]; - u.ak.flags1 = pIn1->flags; - u.ak.flags3 = pIn3->flags; - if( (u.ak.flags1 | u.ak.flags3)&MEM_Null ){ - /* One or both operands are NULL */ - if( pOp->p5 & SQLITE_NULLEQ ){ - /* If SQLITE_NULLEQ is set (which will only happen if the operator is - ** OP_Eq or OP_Ne) then take the jump or not depending on whether - ** or not both operands are null. - */ - assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); - assert( (u.ak.flags1 & MEM_Cleared)==0 ); - if( (u.ak.flags1&MEM_Null)!=0 - && (u.ak.flags3&MEM_Null)!=0 - && (u.ak.flags3&MEM_Cleared)==0 - ){ - u.ak.res = 0; /* Results are equal */ - }else{ - u.ak.res = 1; /* Results are not equal */ - } - }else{ - /* SQLITE_NULLEQ is clear and at least one operand is NULL, - ** then the result is always NULL. - ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. - */ - if( pOp->p5 & SQLITE_STOREP2 ){ - pOut = &aMem[pOp->p2]; - MemSetTypeFlag(pOut, MEM_Null); - REGISTER_TRACE(pOp->p2, pOut); - }else if( pOp->p5 & SQLITE_JUMPIFNULL ){ - pc = pOp->p2-1; - } - break; - } - }else{ - /* Neither operand is NULL. Do a comparison. */ - u.ak.affinity = pOp->p5 & SQLITE_AFF_MASK; - if( u.ak.affinity ){ - applyAffinity(pIn1, u.ak.affinity, encoding); - applyAffinity(pIn3, u.ak.affinity, encoding); - if( db->mallocFailed ) goto no_mem; - } - - assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); - ExpandBlob(pIn1); - ExpandBlob(pIn3); - u.ak.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); - } - switch( pOp->opcode ){ - case OP_Eq: u.ak.res = u.ak.res==0; break; - case OP_Ne: u.ak.res = u.ak.res!=0; break; - case OP_Lt: u.ak.res = u.ak.res<0; break; - case OP_Le: u.ak.res = u.ak.res<=0; break; - case OP_Gt: u.ak.res = u.ak.res>0; break; - default: u.ak.res = u.ak.res>=0; break; - } - - if( pOp->p5 & SQLITE_STOREP2 ){ - pOut = &aMem[pOp->p2]; - memAboutToChange(p, pOut); - MemSetTypeFlag(pOut, MEM_Int); - pOut->u.i = u.ak.res; - REGISTER_TRACE(pOp->p2, pOut); - }else if( u.ak.res ){ - pc = pOp->p2-1; - } - - /* Undo any changes made by applyAffinity() to the input registers. */ - pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.ak.flags1&MEM_TypeMask); - pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.ak.flags3&MEM_TypeMask); - break; -} - -/* Opcode: Permutation * * * P4 * -** -** Set the permutation used by the OP_Compare operator to be the array -** of integers in P4. -** -** The permutation is only valid until the next OP_Compare that has -** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should -** occur immediately prior to the OP_Compare. -*/ -case OP_Permutation: { - assert( pOp->p4type==P4_INTARRAY ); - assert( pOp->p4.ai ); - aPermute = pOp->p4.ai; - break; -} - -/* Opcode: Compare P1 P2 P3 P4 P5 -** -** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this -** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of -** the comparison for use by the next OP_Jump instruct. -** -** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is -** determined by the most recent OP_Permutation operator. If the -** OPFLAG_PERMUTE bit is clear, then register are compared in sequential -** order. -** -** P4 is a KeyInfo structure that defines collating sequences and sort -** orders for the comparison. The permutation applies to registers -** only. The KeyInfo elements are used sequentially. -** -** The comparison is a sort comparison, so NULLs compare equal, -** NULLs are less than numbers, numbers are less than strings, -** and strings are less than blobs. -*/ -case OP_Compare: { -#if 0 /* local variables moved into u.al */ - int n; - int i; - int p1; - int p2; - const KeyInfo *pKeyInfo; - int idx; - CollSeq *pColl; /* Collating sequence to use on this term */ - int bRev; /* True for DESCENDING sort order */ -#endif /* local variables moved into u.al */ - - if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; - u.al.n = pOp->p3; - u.al.pKeyInfo = pOp->p4.pKeyInfo; - assert( u.al.n>0 ); - assert( u.al.pKeyInfo!=0 ); - u.al.p1 = pOp->p1; - u.al.p2 = pOp->p2; -#if SQLITE_DEBUG - if( aPermute ){ - int k, mx = 0; - for(k=0; kmx ) mx = aPermute[k]; - assert( u.al.p1>0 && u.al.p1+mx<=p->nMem+1 ); - assert( u.al.p2>0 && u.al.p2+mx<=p->nMem+1 ); - }else{ - assert( u.al.p1>0 && u.al.p1+u.al.n<=p->nMem+1 ); - assert( u.al.p2>0 && u.al.p2+u.al.n<=p->nMem+1 ); - } -#endif /* SQLITE_DEBUG */ - for(u.al.i=0; u.al.inField ); - u.al.pColl = u.al.pKeyInfo->aColl[u.al.i]; - u.al.bRev = u.al.pKeyInfo->aSortOrder[u.al.i]; - iCompare = sqlite3MemCompare(&aMem[u.al.p1+u.al.idx], &aMem[u.al.p2+u.al.idx], u.al.pColl); - if( iCompare ){ - if( u.al.bRev ) iCompare = -iCompare; - break; - } - } - aPermute = 0; - break; -} - -/* Opcode: Jump P1 P2 P3 * * -** -** Jump to the instruction at address P1, P2, or P3 depending on whether -** in the most recent OP_Compare instruction the P1 vector was less than -** equal to, or greater than the P2 vector, respectively. -*/ -case OP_Jump: { /* jump */ - if( iCompare<0 ){ - pc = pOp->p1 - 1; - }else if( iCompare==0 ){ - pc = pOp->p2 - 1; - }else{ - pc = pOp->p3 - 1; - } - break; -} - -/* Opcode: And P1 P2 P3 * * -** -** Take the logical AND of the values in registers P1 and P2 and -** write the result into register P3. -** -** If either P1 or P2 is 0 (false) then the result is 0 even if -** the other input is NULL. A NULL and true or two NULLs give -** a NULL output. -*/ -/* Opcode: Or P1 P2 P3 * * -** -** Take the logical OR of the values in register P1 and P2 and -** store the answer in register P3. -** -** If either P1 or P2 is nonzero (true) then the result is 1 (true) -** even if the other input is NULL. A NULL and false or two NULLs -** give a NULL output. -*/ -case OP_And: /* same as TK_AND, in1, in2, out3 */ -case OP_Or: { /* same as TK_OR, in1, in2, out3 */ -#if 0 /* local variables moved into u.am */ - int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ -#endif /* local variables moved into u.am */ - - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Null ){ - u.am.v1 = 2; - }else{ - u.am.v1 = sqlite3VdbeIntValue(pIn1)!=0; - } - pIn2 = &aMem[pOp->p2]; - if( pIn2->flags & MEM_Null ){ - u.am.v2 = 2; - }else{ - u.am.v2 = sqlite3VdbeIntValue(pIn2)!=0; - } - if( pOp->opcode==OP_And ){ - static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; - u.am.v1 = and_logic[u.am.v1*3+u.am.v2]; - }else{ - static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; - u.am.v1 = or_logic[u.am.v1*3+u.am.v2]; - } - pOut = &aMem[pOp->p3]; - if( u.am.v1==2 ){ - MemSetTypeFlag(pOut, MEM_Null); - }else{ - pOut->u.i = u.am.v1; - MemSetTypeFlag(pOut, MEM_Int); - } - break; -} - -/* Opcode: Not P1 P2 * * * -** -** Interpret the value in register P1 as a boolean value. Store the -** boolean complement in register P2. If the value in register P1 is -** NULL, then a NULL is stored in P2. -*/ -case OP_Not: { /* same as TK_NOT, in1, out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - if( pIn1->flags & MEM_Null ){ - sqlite3VdbeMemSetNull(pOut); - }else{ - sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeIntValue(pIn1)); - } - break; -} - -/* Opcode: BitNot P1 P2 * * * -** -** Interpret the content of register P1 as an integer. Store the -** ones-complement of the P1 value into register P2. If P1 holds -** a NULL then store a NULL in P2. -*/ -case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ - pIn1 = &aMem[pOp->p1]; - pOut = &aMem[pOp->p2]; - if( pIn1->flags & MEM_Null ){ - sqlite3VdbeMemSetNull(pOut); - }else{ - sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1)); - } - break; -} - -/* Opcode: Once P1 P2 * * * -** -** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, -** set the flag and fall through to the next instruction. -*/ -case OP_Once: { /* jump */ - assert( pOp->p1nOnceFlag ); - if( p->aOnceFlag[pOp->p1] ){ - pc = pOp->p2-1; - }else{ - p->aOnceFlag[pOp->p1] = 1; - } - break; -} - -/* Opcode: If P1 P2 P3 * * -** -** Jump to P2 if the value in register P1 is true. The value -** is considered true if it is numeric and non-zero. If the value -** in P1 is NULL then take the jump if P3 is non-zero. -*/ -/* Opcode: IfNot P1 P2 P3 * * -** -** Jump to P2 if the value in register P1 is False. The value -** is considered false if it has a numeric value of zero. If the value -** in P1 is NULL then take the jump if P3 is zero. -*/ -case OP_If: /* jump, in1 */ -case OP_IfNot: { /* jump, in1 */ -#if 0 /* local variables moved into u.an */ - int c; -#endif /* local variables moved into u.an */ - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Null ){ - u.an.c = pOp->p3; - }else{ -#ifdef SQLITE_OMIT_FLOATING_POINT - u.an.c = sqlite3VdbeIntValue(pIn1)!=0; -#else - u.an.c = sqlite3VdbeRealValue(pIn1)!=0.0; -#endif - if( pOp->opcode==OP_IfNot ) u.an.c = !u.an.c; - } - if( u.an.c ){ - pc = pOp->p2-1; - } - break; -} - -/* Opcode: IsNull P1 P2 * * * -** -** Jump to P2 if the value in register P1 is NULL. -*/ -case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ - pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_Null)!=0 ){ - pc = pOp->p2 - 1; - } - break; -} - -/* Opcode: NotNull P1 P2 * * * -** -** Jump to P2 if the value in register P1 is not NULL. -*/ -case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ - pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_Null)==0 ){ - pc = pOp->p2 - 1; - } - break; -} - -/* Opcode: Column P1 P2 P3 P4 P5 -** -** Interpret the data that cursor P1 points to as a structure built using -** the MakeRecord instruction. (See the MakeRecord opcode for additional -** information about the format of the data.) Extract the P2-th column -** from this record. If there are less that (P2+1) -** values in the record, extract a NULL. -** -** The value extracted is stored in register P3. -** -** If the column contains fewer than P2 fields, then extract a NULL. Or, -** if the P4 argument is a P4_MEM use the value of the P4 argument as -** the result. -** -** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor, -** then the cache of the cursor is reset prior to extracting the column. -** The first OP_Column against a pseudo-table after the value of the content -** register has changed should have this bit set. -** -** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when -** the result is guaranteed to only be used as the argument of a length() -** or typeof() function, respectively. The loading of large blobs can be -** skipped for length() and all content loading can be skipped for typeof(). -*/ -case OP_Column: { -#if 0 /* local variables moved into u.ao */ - u32 payloadSize; /* Number of bytes in the record */ - i64 payloadSize64; /* Number of bytes in the record */ - int p1; /* P1 value of the opcode */ - int p2; /* column number to retrieve */ - VdbeCursor *pC; /* The VDBE cursor */ - char *zRec; /* Pointer to complete record-data */ - BtCursor *pCrsr; /* The BTree cursor */ - u32 *aType; /* aType[i] holds the numeric type of the i-th column */ - u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ - int nField; /* number of fields in the record */ - int len; /* The length of the serialized data for the column */ - int i; /* Loop counter */ - char *zData; /* Part of the record being decoded */ - Mem *pDest; /* Where to write the extracted value */ - Mem sMem; /* For storing the record being decoded */ - u8 *zIdx; /* Index into header */ - u8 *zEndHdr; /* Pointer to first byte after the header */ - u32 offset; /* Offset into the data */ - u32 szField; /* Number of bytes in the content of a field */ - int szHdr; /* Size of the header size field at start of record */ - int avail; /* Number of bytes of available data */ - u32 t; /* A type code from the record header */ - Mem *pReg; /* PseudoTable input register */ -#endif /* local variables moved into u.ao */ - - - u.ao.p1 = pOp->p1; - u.ao.p2 = pOp->p2; - u.ao.pC = 0; - memset(&u.ao.sMem, 0, sizeof(u.ao.sMem)); - assert( u.ao.p1nCursor ); - assert( pOp->p3>0 && pOp->p3<=p->nMem ); - u.ao.pDest = &aMem[pOp->p3]; - memAboutToChange(p, u.ao.pDest); - u.ao.zRec = 0; - - /* This block sets the variable u.ao.payloadSize to be the total number of - ** bytes in the record. - ** - ** u.ao.zRec is set to be the complete text of the record if it is available. - ** The complete record text is always available for pseudo-tables - ** If the record is stored in a cursor, the complete record text - ** might be available in the u.ao.pC->aRow cache. Or it might not be. - ** If the data is unavailable, u.ao.zRec is set to NULL. - ** - ** We also compute the number of columns in the record. For cursors, - ** the number of columns is stored in the VdbeCursor.nField element. - */ - u.ao.pC = p->apCsr[u.ao.p1]; - assert( u.ao.pC!=0 ); -#ifndef SQLITE_OMIT_VIRTUALTABLE - assert( u.ao.pC->pVtabCursor==0 ); -#endif - u.ao.pCrsr = u.ao.pC->pCursor; - if( u.ao.pCrsr!=0 ){ - /* The record is stored in a B-Tree */ - rc = sqlite3VdbeCursorMoveto(u.ao.pC); - if( rc ) goto abort_due_to_error; - if( u.ao.pC->nullRow ){ - u.ao.payloadSize = 0; - }else if( u.ao.pC->cacheStatus==p->cacheCtr ){ - u.ao.payloadSize = u.ao.pC->payloadSize; - u.ao.zRec = (char*)u.ao.pC->aRow; - }else if( u.ao.pC->isIndex ){ - assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ao.pCrsr, &u.ao.payloadSize64); - assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ - /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the - ** payload size, so it is impossible for u.ao.payloadSize64 to be - ** larger than 32 bits. */ - assert( (u.ao.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ao.payloadSize64 ); - u.ao.payloadSize = (u32)u.ao.payloadSize64; - }else{ - assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize); - assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - } - }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){ - u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg]; - if( u.ao.pC->multiPseudo ){ - sqlite3VdbeMemShallowCopy(u.ao.pDest, u.ao.pReg+u.ao.p2, MEM_Ephem); - Deephemeralize(u.ao.pDest); - goto op_column_out; - } - assert( u.ao.pReg->flags & MEM_Blob ); - assert( memIsValid(u.ao.pReg) ); - u.ao.payloadSize = u.ao.pReg->n; - u.ao.zRec = u.ao.pReg->z; - u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr; - assert( u.ao.payloadSize==0 || u.ao.zRec!=0 ); - }else{ - /* Consider the row to be NULL */ - u.ao.payloadSize = 0; - } - - /* If u.ao.payloadSize is 0, then just store a NULL. This can happen because of - ** nullRow or because of a corrupt database. */ - if( u.ao.payloadSize==0 ){ - MemSetTypeFlag(u.ao.pDest, MEM_Null); - goto op_column_out; - } - assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 ); - if( u.ao.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - - u.ao.nField = u.ao.pC->nField; - assert( u.ao.p2aType; - if( u.ao.pC->cacheStatus==p->cacheCtr ){ - u.ao.aOffset = u.ao.pC->aOffset; - }else{ - assert(u.ao.aType); - u.ao.avail = 0; - u.ao.pC->aOffset = u.ao.aOffset = &u.ao.aType[u.ao.nField]; - u.ao.pC->payloadSize = u.ao.payloadSize; - u.ao.pC->cacheStatus = p->cacheCtr; - - /* Figure out how many bytes are in the header */ - if( u.ao.zRec ){ - u.ao.zData = u.ao.zRec; - }else{ - if( u.ao.pC->isIndex ){ - u.ao.zData = (char*)sqlite3BtreeKeyFetch(u.ao.pCrsr, &u.ao.avail); - }else{ - u.ao.zData = (char*)sqlite3BtreeDataFetch(u.ao.pCrsr, &u.ao.avail); - } - /* If KeyFetch()/DataFetch() managed to get the entire payload, - ** save the payload in the u.ao.pC->aRow cache. That will save us from - ** having to make additional calls to fetch the content portion of - ** the record. - */ - assert( u.ao.avail>=0 ); - if( u.ao.payloadSize <= (u32)u.ao.avail ){ - u.ao.zRec = u.ao.zData; - u.ao.pC->aRow = (u8*)u.ao.zData; - }else{ - u.ao.pC->aRow = 0; - } - } - /* The following assert is true in all cases except when - ** the database file has been corrupted externally. - ** assert( u.ao.zRec!=0 || u.ao.avail>=u.ao.payloadSize || u.ao.avail>=9 ); */ - u.ao.szHdr = getVarint32((u8*)u.ao.zData, u.ao.offset); - - /* Make sure a corrupt database has not given us an oversize header. - ** Do this now to avoid an oversize memory allocation. - ** - ** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte - ** types use so much data space that there can only be 4096 and 32 of - ** them, respectively. So the maximum header length results from a - ** 3-byte type for each of the maximum of 32768 columns plus three - ** extra bytes for the header length itself. 32768*3 + 3 = 98307. - */ - if( u.ao.offset > 98307 ){ - rc = SQLITE_CORRUPT_BKPT; - goto op_column_out; - } - - /* Compute in u.ao.len the number of bytes of data we need to read in order - ** to get u.ao.nField type values. u.ao.offset is an upper bound on this. But - ** u.ao.nField might be significantly less than the true number of columns - ** in the table, and in that case, 5*u.ao.nField+3 might be smaller than u.ao.offset. - ** We want to minimize u.ao.len in order to limit the size of the memory - ** allocation, especially if a corrupt database file has caused u.ao.offset - ** to be oversized. Offset is limited to 98307 above. But 98307 might - ** still exceed Robson memory allocation limits on some configurations. - ** On systems that cannot tolerate large memory allocations, u.ao.nField*5+3 - ** will likely be much smaller since u.ao.nField will likely be less than - ** 20 or so. This insures that Robson memory allocation limits are - ** not exceeded even for corrupt database files. - */ - u.ao.len = u.ao.nField*5 + 3; - if( u.ao.len > (int)u.ao.offset ) u.ao.len = (int)u.ao.offset; - - /* The KeyFetch() or DataFetch() above are fast and will get the entire - ** record header in most cases. But they will fail to get the complete - ** record header if the record header does not fit on a single page - ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to - ** acquire the complete header text. - */ - if( !u.ao.zRec && u.ao.availisIndex, &u.ao.sMem); - if( rc!=SQLITE_OK ){ - goto op_column_out; - } - u.ao.zData = u.ao.sMem.z; - } - u.ao.zEndHdr = (u8 *)&u.ao.zData[u.ao.len]; - u.ao.zIdx = (u8 *)&u.ao.zData[u.ao.szHdr]; - - /* Scan the header and use it to fill in the u.ao.aType[] and u.ao.aOffset[] - ** arrays. u.ao.aType[u.ao.i] will contain the type integer for the u.ao.i-th - ** column and u.ao.aOffset[u.ao.i] will contain the u.ao.offset from the beginning - ** of the record to the start of the data for the u.ao.i-th column - */ - for(u.ao.i=0; u.ao.i u.ao.zEndHdr) || (u.ao.offset > u.ao.payloadSize) - || (u.ao.zIdx==u.ao.zEndHdr && u.ao.offset!=u.ao.payloadSize) ){ - rc = SQLITE_CORRUPT_BKPT; - goto op_column_out; - } - } - - /* Get the column information. If u.ao.aOffset[u.ao.p2] is non-zero, then - ** deserialize the value from the record. If u.ao.aOffset[u.ao.p2] is zero, - ** then there are not enough fields in the record to satisfy the - ** request. In this case, set the value NULL or to P4 if P4 is - ** a pointer to a Mem object. - */ - if( u.ao.aOffset[u.ao.p2] ){ - assert( rc==SQLITE_OK ); - if( u.ao.zRec ){ - /* This is the common case where the whole row fits on a single page */ - VdbeMemRelease(u.ao.pDest); - sqlite3VdbeSerialGet((u8 *)&u.ao.zRec[u.ao.aOffset[u.ao.p2]], u.ao.aType[u.ao.p2], u.ao.pDest); - }else{ - /* This branch happens only when the row overflows onto multiple pages */ - u.ao.t = u.ao.aType[u.ao.p2]; - if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 - && ((u.ao.t>=12 && (u.ao.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0) - ){ - /* Content is irrelevant for the typeof() function and for - ** the length(X) function if X is a blob. So we might as well use - ** bogus content rather than reading content from disk. NULL works - ** for text and blob and whatever is in the u.ao.payloadSize64 variable - ** will work for everything else. */ - u.ao.zData = u.ao.t<12 ? (char*)&u.ao.payloadSize64 : 0; - }else{ - u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.t); - sqlite3VdbeMemMove(&u.ao.sMem, u.ao.pDest); - rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, u.ao.aOffset[u.ao.p2], u.ao.len, u.ao.pC->isIndex, - &u.ao.sMem); - if( rc!=SQLITE_OK ){ - goto op_column_out; - } - u.ao.zData = u.ao.sMem.z; - } - sqlite3VdbeSerialGet((u8*)u.ao.zData, u.ao.t, u.ao.pDest); - } - u.ao.pDest->enc = encoding; - }else{ - if( pOp->p4type==P4_MEM ){ - sqlite3VdbeMemShallowCopy(u.ao.pDest, pOp->p4.pMem, MEM_Static); - }else{ - MemSetTypeFlag(u.ao.pDest, MEM_Null); - } - } - - /* If we dynamically allocated space to hold the data (in the - ** sqlite3VdbeMemFromBtree() call above) then transfer control of that - ** dynamically allocated space over to the u.ao.pDest structure. - ** This prevents a memory copy. - */ - if( u.ao.sMem.zMalloc ){ - assert( u.ao.sMem.z==u.ao.sMem.zMalloc ); - assert( !(u.ao.pDest->flags & MEM_Dyn) ); - assert( !(u.ao.pDest->flags & (MEM_Blob|MEM_Str)) || u.ao.pDest->z==u.ao.sMem.z ); - u.ao.pDest->flags &= ~(MEM_Ephem|MEM_Static); - u.ao.pDest->flags |= MEM_Term; - u.ao.pDest->z = u.ao.sMem.z; - u.ao.pDest->zMalloc = u.ao.sMem.zMalloc; - } - - rc = sqlite3VdbeMemMakeWriteable(u.ao.pDest); - -op_column_out: - UPDATE_MAX_BLOBSIZE(u.ao.pDest); - REGISTER_TRACE(pOp->p3, u.ao.pDest); - break; -} - -/* Opcode: Affinity P1 P2 * P4 * -** -** Apply affinities to a range of P2 registers starting with P1. -** -** P4 is a string that is P2 characters long. The nth character of the -** string indicates the column affinity that should be used for the nth -** memory cell in the range. -*/ -case OP_Affinity: { -#if 0 /* local variables moved into u.ap */ - const char *zAffinity; /* The affinity to be applied */ - char cAff; /* A single character of affinity */ -#endif /* local variables moved into u.ap */ - - u.ap.zAffinity = pOp->p4.z; - assert( u.ap.zAffinity!=0 ); - assert( u.ap.zAffinity[pOp->p2]==0 ); - pIn1 = &aMem[pOp->p1]; - while( (u.ap.cAff = *(u.ap.zAffinity++))!=0 ){ - assert( pIn1 <= &p->aMem[p->nMem] ); - assert( memIsValid(pIn1) ); - ExpandBlob(pIn1); - applyAffinity(pIn1, u.ap.cAff, encoding); - pIn1++; - } - break; -} - -/* Opcode: MakeRecord P1 P2 P3 P4 * -** -** Convert P2 registers beginning with P1 into the [record format] -** use as a data record in a database table or as a key -** in an index. The OP_Column opcode can decode the record later. -** -** P4 may be a string that is P2 characters long. The nth character of the -** string indicates the column affinity that should be used for the nth -** field of the index key. -** -** The mapping from character to affinity is given by the SQLITE_AFF_ -** macros defined in sqliteInt.h. -** -** If P4 is NULL then all index fields have the affinity NONE. -*/ -case OP_MakeRecord: { -#if 0 /* local variables moved into u.aq */ - u8 *zNewRecord; /* A buffer to hold the data for the new record */ - Mem *pRec; /* The new record */ - u64 nData; /* Number of bytes of data space */ - int nHdr; /* Number of bytes of header space */ - i64 nByte; /* Data space required for this record */ - int nZero; /* Number of zero bytes at the end of the record */ - int nVarint; /* Number of bytes in a varint */ - u32 serial_type; /* Type field */ - Mem *pData0; /* First field to be combined into the record */ - Mem *pLast; /* Last field of the record */ - int nField; /* Number of fields in the record */ - char *zAffinity; /* The affinity string for the record */ - int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] */ - int len; /* Length of a field */ -#endif /* local variables moved into u.aq */ - - /* Assuming the record contains N fields, the record format looks - ** like this: - ** - ** ------------------------------------------------------------------------ - ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | - ** ------------------------------------------------------------------------ - ** - ** Data(0) is taken from register P1. Data(1) comes from register P1+1 - ** and so froth. - ** - ** Each type field is a varint representing the serial type of the - ** corresponding data element (see sqlite3VdbeSerialType()). The - ** hdr-size field is also a varint which is the offset from the beginning - ** of the record to data0. - */ - u.aq.nData = 0; /* Number of bytes of data space */ - u.aq.nHdr = 0; /* Number of bytes of header space */ - u.aq.nZero = 0; /* Number of zero bytes at the end of the record */ - u.aq.nField = pOp->p1; - u.aq.zAffinity = pOp->p4.z; - assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=p->nMem+1 ); - u.aq.pData0 = &aMem[u.aq.nField]; - u.aq.nField = pOp->p2; - u.aq.pLast = &u.aq.pData0[u.aq.nField-1]; - u.aq.file_format = p->minWriteFileFormat; - - /* Identify the output register */ - assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 ); - pOut = &aMem[pOp->p3]; - memAboutToChange(p, pOut); - - /* Loop through the elements that will make up the record to figure - ** out how much space is required for the new record. - */ - for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){ - assert( memIsValid(u.aq.pRec) ); - if( u.aq.zAffinity ){ - applyAffinity(u.aq.pRec, u.aq.zAffinity[u.aq.pRec-u.aq.pData0], encoding); - } - if( u.aq.pRec->flags&MEM_Zero && u.aq.pRec->n>0 ){ - sqlite3VdbeMemExpandBlob(u.aq.pRec); - } - u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format); - u.aq.len = sqlite3VdbeSerialTypeLen(u.aq.serial_type); - u.aq.nData += u.aq.len; - u.aq.nHdr += sqlite3VarintLen(u.aq.serial_type); - if( u.aq.pRec->flags & MEM_Zero ){ - /* Only pure zero-filled BLOBs can be input to this Opcode. - ** We do not allow blobs with a prefix and a zero-filled tail. */ - u.aq.nZero += u.aq.pRec->u.nZero; - }else if( u.aq.len ){ - u.aq.nZero = 0; - } - } - - /* Add the initial header varint and total the size */ - u.aq.nHdr += u.aq.nVarint = sqlite3VarintLen(u.aq.nHdr); - if( u.aq.nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - - /* Make sure the output register has a buffer large enough to store - ** the new record. The output register (pOp->p3) is not allowed to - ** be one of the input registers (because the following call to - ** sqlite3VdbeMemGrow() could clobber the value before it is used). - */ - if( sqlite3VdbeMemGrow(pOut, (int)u.aq.nByte, 0) ){ - goto no_mem; - } - u.aq.zNewRecord = (u8 *)pOut->z; - - /* Write the record */ - u.aq.i = putVarint32(u.aq.zNewRecord, u.aq.nHdr); - for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){ - u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format); - u.aq.i += putVarint32(&u.aq.zNewRecord[u.aq.i], u.aq.serial_type); /* serial type */ - } - for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){ /* serial data */ - u.aq.i += sqlite3VdbeSerialPut(&u.aq.zNewRecord[u.aq.i], (int)(u.aq.nByte-u.aq.i), u.aq.pRec,u.aq.file_format); - } - assert( u.aq.i==u.aq.nByte ); - - assert( pOp->p3>0 && pOp->p3<=p->nMem ); - pOut->n = (int)u.aq.nByte; - pOut->flags = MEM_Blob | MEM_Dyn; - pOut->xDel = 0; - if( u.aq.nZero ){ - pOut->u.nZero = u.aq.nZero; - pOut->flags |= MEM_Zero; - } - pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ - REGISTER_TRACE(pOp->p3, pOut); - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Count P1 P2 * * * -** -** Store the number of entries (an integer value) in the table or index -** opened by cursor P1 in register P2 -*/ -#ifndef SQLITE_OMIT_BTREECOUNT -case OP_Count: { /* out2-prerelease */ -#if 0 /* local variables moved into u.ar */ - i64 nEntry; - BtCursor *pCrsr; -#endif /* local variables moved into u.ar */ - - u.ar.pCrsr = p->apCsr[pOp->p1]->pCursor; - if( ALWAYS(u.ar.pCrsr) ){ - rc = sqlite3BtreeCount(u.ar.pCrsr, &u.ar.nEntry); - }else{ - u.ar.nEntry = 0; - } - pOut->u.i = u.ar.nEntry; - break; -} -#endif - -/* Opcode: Savepoint P1 * * P4 * -** -** Open, release or rollback the savepoint named by parameter P4, depending -** on the value of P1. To open a new savepoint, P1==0. To release (commit) an -** existing savepoint, P1==1, or to rollback an existing savepoint P1==2. -*/ -case OP_Savepoint: { -#if 0 /* local variables moved into u.as */ - int p1; /* Value of P1 operand */ - char *zName; /* Name of savepoint */ - int nName; - Savepoint *pNew; - Savepoint *pSavepoint; - Savepoint *pTmp; - int iSavepoint; - int ii; -#endif /* local variables moved into u.as */ - - u.as.p1 = pOp->p1; - u.as.zName = pOp->p4.z; - - /* Assert that the u.as.p1 parameter is valid. Also that if there is no open - ** transaction, then there cannot be any savepoints. - */ - assert( db->pSavepoint==0 || db->autoCommit==0 ); - assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK ); - assert( db->pSavepoint || db->isTransactionSavepoint==0 ); - assert( checkSavepointCount(db) ); - - if( u.as.p1==SAVEPOINT_BEGIN ){ - if( db->writeVdbeCnt>0 ){ - /* A new savepoint cannot be created if there are active write - ** statements (i.e. open read/write incremental blob handles). - */ - sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - " - "SQL statements in progress"); - rc = SQLITE_BUSY; - }else{ - u.as.nName = sqlite3Strlen30(u.as.zName); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* This call is Ok even if this savepoint is actually a transaction - ** savepoint (and therefore should not prompt xSavepoint()) callbacks. - ** If this is a transaction savepoint being opened, it is guaranteed - ** that the db->aVTrans[] array is empty. */ - assert( db->autoCommit==0 || db->nVTrans==0 ); - rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, - db->nStatement+db->nSavepoint); - if( rc!=SQLITE_OK ) goto abort_due_to_error; -#endif - - /* Create a new savepoint structure. */ - u.as.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.as.nName+1); - if( u.as.pNew ){ - u.as.pNew->zName = (char *)&u.as.pNew[1]; - memcpy(u.as.pNew->zName, u.as.zName, u.as.nName+1); - - /* If there is no open transaction, then mark this as a special - ** "transaction savepoint". */ - if( db->autoCommit ){ - db->autoCommit = 0; - db->isTransactionSavepoint = 1; - }else{ - db->nSavepoint++; - } - - /* Link the new savepoint into the database handle's list. */ - u.as.pNew->pNext = db->pSavepoint; - db->pSavepoint = u.as.pNew; - u.as.pNew->nDeferredCons = db->nDeferredCons; - } - } - }else{ - u.as.iSavepoint = 0; - - /* Find the named savepoint. If there is no such savepoint, then an - ** an error is returned to the user. */ - for( - u.as.pSavepoint = db->pSavepoint; - u.as.pSavepoint && sqlite3StrICmp(u.as.pSavepoint->zName, u.as.zName); - u.as.pSavepoint = u.as.pSavepoint->pNext - ){ - u.as.iSavepoint++; - } - if( !u.as.pSavepoint ){ - sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName); - rc = SQLITE_ERROR; - }else if( db->writeVdbeCnt>0 && u.as.p1==SAVEPOINT_RELEASE ){ - /* It is not possible to release (commit) a savepoint if there are - ** active write statements. - */ - sqlite3SetString(&p->zErrMsg, db, - "cannot release savepoint - SQL statements in progress" - ); - rc = SQLITE_BUSY; - }else{ - - /* Determine whether or not this is a transaction savepoint. If so, - ** and this is a RELEASE command, then the current transaction - ** is committed. - */ - int isTransaction = u.as.pSavepoint->pNext==0 && db->isTransactionSavepoint; - if( isTransaction && u.as.p1==SAVEPOINT_RELEASE ){ - if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ - goto vdbe_return; - } - db->autoCommit = 1; - if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = pc; - db->autoCommit = 0; - p->rc = rc = SQLITE_BUSY; - goto vdbe_return; - } - db->isTransactionSavepoint = 0; - rc = p->rc; - }else{ - u.as.iSavepoint = db->nSavepoint - u.as.iSavepoint - 1; - if( u.as.p1==SAVEPOINT_ROLLBACK ){ - for(u.as.ii=0; u.as.iinDb; u.as.ii++){ - sqlite3BtreeTripAllCursors(db->aDb[u.as.ii].pBt, SQLITE_ABORT); - } - } - for(u.as.ii=0; u.as.iinDb; u.as.ii++){ - rc = sqlite3BtreeSavepoint(db->aDb[u.as.ii].pBt, u.as.p1, u.as.iSavepoint); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - } - if( u.as.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ - sqlite3ExpirePreparedStatements(db); - sqlite3ResetAllSchemasOfConnection(db); - db->flags = (db->flags | SQLITE_InternChanges); - } - } - - /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all - ** savepoints nested inside of the savepoint being operated on. */ - while( db->pSavepoint!=u.as.pSavepoint ){ - u.as.pTmp = db->pSavepoint; - db->pSavepoint = u.as.pTmp->pNext; - sqlite3DbFree(db, u.as.pTmp); - db->nSavepoint--; - } - - /* If it is a RELEASE, then destroy the savepoint being operated on - ** too. If it is a ROLLBACK TO, then set the number of deferred - ** constraint violations present in the database to the value stored - ** when the savepoint was created. */ - if( u.as.p1==SAVEPOINT_RELEASE ){ - assert( u.as.pSavepoint==db->pSavepoint ); - db->pSavepoint = u.as.pSavepoint->pNext; - sqlite3DbFree(db, u.as.pSavepoint); - if( !isTransaction ){ - db->nSavepoint--; - } - }else{ - db->nDeferredCons = u.as.pSavepoint->nDeferredCons; - } - - if( !isTransaction ){ - rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - } - } - } - - break; -} - -/* Opcode: AutoCommit P1 P2 * * * -** -** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll -** back any currently active btree transactions. If there are any active -** VMs (apart from this one), then a ROLLBACK fails. A COMMIT fails if -** there are active writing VMs or active VMs that use shared cache. -** -** This instruction causes the VM to halt. -*/ -case OP_AutoCommit: { -#if 0 /* local variables moved into u.at */ - int desiredAutoCommit; - int iRollback; - int turnOnAC; -#endif /* local variables moved into u.at */ - - u.at.desiredAutoCommit = pOp->p1; - u.at.iRollback = pOp->p2; - u.at.turnOnAC = u.at.desiredAutoCommit && !db->autoCommit; - assert( u.at.desiredAutoCommit==1 || u.at.desiredAutoCommit==0 ); - assert( u.at.desiredAutoCommit==1 || u.at.iRollback==0 ); - assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ - -#if 0 - if( u.at.turnOnAC && u.at.iRollback && db->activeVdbeCnt>1 ){ - /* If this instruction implements a ROLLBACK and other VMs are - ** still running, and a transaction is active, return an error indicating - ** that the other VMs must complete first. - */ - sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " - "SQL statements in progress"); - rc = SQLITE_BUSY; - }else -#endif - if( u.at.turnOnAC && !u.at.iRollback && db->writeVdbeCnt>0 ){ - /* If this instruction implements a COMMIT and other VMs are writing - ** return an error indicating that the other VMs must complete first. - */ - sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - " - "SQL statements in progress"); - rc = SQLITE_BUSY; - }else if( u.at.desiredAutoCommit!=db->autoCommit ){ - if( u.at.iRollback ){ - assert( u.at.desiredAutoCommit==1 ); - sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); - db->autoCommit = 1; - }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ - goto vdbe_return; - }else{ - db->autoCommit = (u8)u.at.desiredAutoCommit; - if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = pc; - db->autoCommit = (u8)(1-u.at.desiredAutoCommit); - p->rc = rc = SQLITE_BUSY; - goto vdbe_return; - } - } - assert( db->nStatement==0 ); - sqlite3CloseSavepoints(db); - if( p->rc==SQLITE_OK ){ - rc = SQLITE_DONE; - }else{ - rc = SQLITE_ERROR; - } - goto vdbe_return; - }else{ - sqlite3SetString(&p->zErrMsg, db, - (!u.at.desiredAutoCommit)?"cannot start a transaction within a transaction":( - (u.at.iRollback)?"cannot rollback - no transaction is active": - "cannot commit - no transaction is active")); - - rc = SQLITE_ERROR; - } - break; -} - -/* Opcode: Transaction P1 P2 * * * -** -** Begin a transaction. The transaction ends when a Commit or Rollback -** opcode is encountered. Depending on the ON CONFLICT setting, the -** transaction might also be rolled back if an error is encountered. -** -** P1 is the index of the database file on which the transaction is -** started. Index 0 is the main database file and index 1 is the -** file used for temporary tables. Indices of 2 or more are used for -** attached databases. -** -** If P2 is non-zero, then a write-transaction is started. A RESERVED lock is -** obtained on the database file when a write-transaction is started. No -** other process can start another write transaction while this transaction is -** underway. Starting a write transaction also creates a rollback journal. A -** write transaction must be started before any changes can be made to the -** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained -** on the file. -** -** If a write-transaction is started and the Vdbe.usesStmtJournal flag is -** true (this flag is set if the Vdbe may modify more than one row and may -** throw an ABORT exception), a statement transaction may also be opened. -** More specifically, a statement transaction is opened iff the database -** connection is currently not in autocommit mode, or if there are other -** active statements. A statement transaction allows the changes made by this -** VDBE to be rolled back after an error without having to roll back the -** entire transaction. If no error is encountered, the statement transaction -** will automatically commit when the VDBE halts. -** -** If P2 is zero, then a read-lock is obtained on the database file. -*/ -case OP_Transaction: { -#if 0 /* local variables moved into u.au */ - Btree *pBt; -#endif /* local variables moved into u.au */ - - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); - u.au.pBt = db->aDb[pOp->p1].pBt; - - if( u.au.pBt ){ - rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2); - if( rc==SQLITE_BUSY ){ - p->pc = pc; - p->rc = rc = SQLITE_BUSY; - goto vdbe_return; - } - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - - if( pOp->p2 && p->usesStmtJournal - && (db->autoCommit==0 || db->activeVdbeCnt>1) - ){ - assert( sqlite3BtreeIsInTrans(u.au.pBt) ); - if( p->iStatement==0 ){ - assert( db->nStatement>=0 && db->nSavepoint>=0 ); - db->nStatement++; - p->iStatement = db->nSavepoint + db->nStatement; - } - - rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement); - } - - /* Store the current value of the database handles deferred constraint - ** counter. If the statement transaction needs to be rolled back, - ** the value of this counter needs to be restored too. */ - p->nStmtDefCons = db->nDeferredCons; - } - } - break; -} - -/* Opcode: ReadCookie P1 P2 P3 * * -** -** Read cookie number P3 from database P1 and write it into register P2. -** P3==1 is the schema version. P3==2 is the database format. -** P3==3 is the recommended pager cache size, and so forth. P1==0 is -** the main database file and P1==1 is the database file used to store -** temporary tables. -** -** There must be a read-lock on the database (either a transaction -** must be started or there must be an open cursor) before -** executing this instruction. -*/ -case OP_ReadCookie: { /* out2-prerelease */ -#if 0 /* local variables moved into u.av */ - int iMeta; - int iDb; - int iCookie; -#endif /* local variables moved into u.av */ - - u.av.iDb = pOp->p1; - u.av.iCookie = pOp->p3; - assert( pOp->p3=0 && u.av.iDbnDb ); - assert( db->aDb[u.av.iDb].pBt!=0 ); - assert( (p->btreeMask & (((yDbMask)1)<aDb[u.av.iDb].pBt, u.av.iCookie, (u32 *)&u.av.iMeta); - pOut->u.i = u.av.iMeta; - break; -} - -/* Opcode: SetCookie P1 P2 P3 * * -** -** Write the content of register P3 (interpreted as an integer) -** into cookie number P2 of database P1. P2==1 is the schema version. -** P2==2 is the database format. P2==3 is the recommended pager cache -** size, and so forth. P1==0 is the main database file and P1==1 is the -** database file used to store temporary tables. -** -** A transaction must be started before executing this opcode. -*/ -case OP_SetCookie: { /* in3 */ -#if 0 /* local variables moved into u.aw */ - Db *pDb; -#endif /* local variables moved into u.aw */ - assert( pOp->p2p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); - u.aw.pDb = &db->aDb[pOp->p1]; - assert( u.aw.pDb->pBt!=0 ); - assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); - pIn3 = &aMem[pOp->p3]; - sqlite3VdbeMemIntegerify(pIn3); - /* See note about index shifting on OP_ReadCookie */ - rc = sqlite3BtreeUpdateMeta(u.aw.pDb->pBt, pOp->p2, (int)pIn3->u.i); - if( pOp->p2==BTREE_SCHEMA_VERSION ){ - /* When the schema cookie changes, record the new cookie internally */ - u.aw.pDb->pSchema->schema_cookie = (int)pIn3->u.i; - db->flags |= SQLITE_InternChanges; - }else if( pOp->p2==BTREE_FILE_FORMAT ){ - /* Record changes in the file format */ - u.aw.pDb->pSchema->file_format = (u8)pIn3->u.i; - } - if( pOp->p1==1 ){ - /* Invalidate all prepared statements whenever the TEMP database - ** schema is changed. Ticket #1644 */ - sqlite3ExpirePreparedStatements(db); - p->expired = 0; - } - break; -} - -/* Opcode: VerifyCookie P1 P2 P3 * * -** -** Check the value of global database parameter number 0 (the -** schema version) and make sure it is equal to P2 and that the -** generation counter on the local schema parse equals P3. -** -** P1 is the database number which is 0 for the main database file -** and 1 for the file holding temporary tables and some higher number -** for auxiliary databases. -** -** The cookie changes its value whenever the database schema changes. -** This operation is used to detect when that the cookie has changed -** and that the current process needs to reread the schema. -** -** Either a transaction needs to have been started or an OP_Open needs -** to be executed (to establish a read lock) before this opcode is -** invoked. -*/ -case OP_VerifyCookie: { -#if 0 /* local variables moved into u.ax */ - int iMeta; - int iGen; - Btree *pBt; -#endif /* local variables moved into u.ax */ - - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); - assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); - u.ax.pBt = db->aDb[pOp->p1].pBt; - if( u.ax.pBt ){ - sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta); - u.ax.iGen = db->aDb[pOp->p1].pSchema->iGeneration; - }else{ - u.ax.iGen = u.ax.iMeta = 0; - } - if( u.ax.iMeta!=pOp->p2 || u.ax.iGen!=pOp->p3 ){ - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); - /* If the schema-cookie from the database file matches the cookie - ** stored with the in-memory representation of the schema, do - ** not reload the schema from the database file. - ** - ** If virtual-tables are in use, this is not just an optimization. - ** Often, v-tables store their data in other SQLite tables, which - ** are queried from within xNext() and other v-table methods using - ** prepared queries. If such a query is out-of-date, we do not want to - ** discard the database schema, as the user code implementing the - ** v-table would have to be ready for the sqlite3_vtab structure itself - ** to be invalidated whenever sqlite3_step() is called from within - ** a v-table method. - */ - if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ax.iMeta ){ - sqlite3ResetOneSchema(db, pOp->p1); - } - - p->expired = 1; - rc = SQLITE_SCHEMA; - } - break; -} - -/* Opcode: OpenRead P1 P2 P3 P4 P5 -** -** Open a read-only cursor for the database table whose root page is -** P2 in a database file. The database file is determined by P3. -** P3==0 means the main database, P3==1 means the database used for -** temporary tables, and P3>1 means used the corresponding attached -** database. Give the new cursor an identifier of P1. The P1 -** values need not be contiguous but all P1 values should be small integers. -** It is an error for P1 to be negative. -** -** If P5!=0 then use the content of register P2 as the root page, not -** the value of P2 itself. -** -** There will be a read lock on the database whenever there is an -** open cursor. If the database was unlocked prior to this instruction -** then a read lock is acquired as part of this instruction. A read -** lock allows other processes to read the database but prohibits -** any other process from modifying the database. The read lock is -** released when all cursors are closed. If this instruction attempts -** to get a read lock but fails, the script terminates with an -** SQLITE_BUSY error code. -** -** The P4 value may be either an integer (P4_INT32) or a pointer to -** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo -** structure, then said structure defines the content and collating -** sequence of the index being opened. Otherwise, if P4 is an integer -** value, it is set to the number of columns in the table. -** -** See also OpenWrite. -*/ -/* Opcode: OpenWrite P1 P2 P3 P4 P5 -** -** Open a read/write cursor named P1 on the table or index whose root -** page is P2. Or if P5!=0 use the content of register P2 to find the -** root page. -** -** The P4 value may be either an integer (P4_INT32) or a pointer to -** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo -** structure, then said structure defines the content and collating -** sequence of the index being opened. Otherwise, if P4 is an integer -** value, it is set to the number of columns in the table, or to the -** largest index of any column of the table that is actually used. -** -** This instruction works just like OpenRead except that it opens the cursor -** in read/write mode. For a given table, there can be one or more read-only -** cursors or a single read/write cursor but not both. -** -** See also OpenRead. -*/ -case OP_OpenRead: -case OP_OpenWrite: { -#if 0 /* local variables moved into u.ay */ - int nField; - KeyInfo *pKeyInfo; - int p2; - int iDb; - int wrFlag; - Btree *pX; - VdbeCursor *pCur; - Db *pDb; -#endif /* local variables moved into u.ay */ - - assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); - assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); - - if( p->expired ){ - rc = SQLITE_ABORT; - break; - } - - u.ay.nField = 0; - u.ay.pKeyInfo = 0; - u.ay.p2 = pOp->p2; - u.ay.iDb = pOp->p3; - assert( u.ay.iDb>=0 && u.ay.iDbnDb ); - assert( (p->btreeMask & (((yDbMask)1)<aDb[u.ay.iDb]; - u.ay.pX = u.ay.pDb->pBt; - assert( u.ay.pX!=0 ); - if( pOp->opcode==OP_OpenWrite ){ - u.ay.wrFlag = 1; - assert( sqlite3SchemaMutexHeld(db, u.ay.iDb, 0) ); - if( u.ay.pDb->pSchema->file_format < p->minWriteFileFormat ){ - p->minWriteFileFormat = u.ay.pDb->pSchema->file_format; - } - }else{ - u.ay.wrFlag = 0; - } - if( pOp->p5 & OPFLAG_P2ISREG ){ - assert( u.ay.p2>0 ); - assert( u.ay.p2<=p->nMem ); - pIn2 = &aMem[u.ay.p2]; - assert( memIsValid(pIn2) ); - assert( (pIn2->flags & MEM_Int)!=0 ); - sqlite3VdbeMemIntegerify(pIn2); - u.ay.p2 = (int)pIn2->u.i; - /* The u.ay.p2 value always comes from a prior OP_CreateTable opcode and - ** that opcode will always set the u.ay.p2 value to 2 or more or else fail. - ** If there were a failure, the prepared statement would have halted - ** before reaching this instruction. */ - if( NEVER(u.ay.p2<2) ) { - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } - } - if( pOp->p4type==P4_KEYINFO ){ - u.ay.pKeyInfo = pOp->p4.pKeyInfo; - u.ay.pKeyInfo->enc = ENC(p->db); - u.ay.nField = u.ay.pKeyInfo->nField+1; - }else if( pOp->p4type==P4_INT32 ){ - u.ay.nField = pOp->p4.i; - } - assert( pOp->p1>=0 ); - u.ay.pCur = allocateCursor(p, pOp->p1, u.ay.nField, u.ay.iDb, 1); - if( u.ay.pCur==0 ) goto no_mem; - u.ay.pCur->nullRow = 1; - u.ay.pCur->isOrdered = 1; - rc = sqlite3BtreeCursor(u.ay.pX, u.ay.p2, u.ay.wrFlag, u.ay.pKeyInfo, u.ay.pCur->pCursor); - u.ay.pCur->pKeyInfo = u.ay.pKeyInfo; - assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); - sqlite3BtreeCursorHints(u.ay.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); - - /* Since it performs no memory allocation or IO, the only value that - ** sqlite3BtreeCursor() may return is SQLITE_OK. */ - assert( rc==SQLITE_OK ); - - /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of - ** SQLite used to check if the root-page flags were sane at this point - ** and report database corruption if they were not, but this check has - ** since moved into the btree layer. */ - u.ay.pCur->isTable = pOp->p4type!=P4_KEYINFO; - u.ay.pCur->isIndex = !u.ay.pCur->isTable; - break; -} - -/* Opcode: OpenEphemeral P1 P2 * P4 P5 -** -** Open a new cursor P1 to a transient table. -** The cursor is always opened read/write even if -** the main database is read-only. The ephemeral -** table is deleted automatically when the cursor is closed. -** -** P2 is the number of columns in the ephemeral table. -** The cursor points to a BTree table if P4==0 and to a BTree index -** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure -** that defines the format of keys in the index. -** -** This opcode was once called OpenTemp. But that created -** confusion because the term "temp table", might refer either -** to a TEMP table at the SQL level, or to a table opened by -** this opcode. Then this opcode was call OpenVirtual. But -** that created confusion with the whole virtual-table idea. -** -** The P5 parameter can be a mask of the BTREE_* flags defined -** in btree.h. These flags control aspects of the operation of -** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are -** added automatically. -*/ -/* Opcode: OpenAutoindex P1 P2 * P4 * -** -** This opcode works the same as OP_OpenEphemeral. It has a -** different name to distinguish its use. Tables created using -** by this opcode will be used for automatically created transient -** indices in joins. -*/ -case OP_OpenAutoindex: -case OP_OpenEphemeral: { -#if 0 /* local variables moved into u.az */ - VdbeCursor *pCx; -#endif /* local variables moved into u.az */ - static const int vfsFlags = - SQLITE_OPEN_READWRITE | - SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | - SQLITE_OPEN_DELETEONCLOSE | - SQLITE_OPEN_TRANSIENT_DB; - - assert( pOp->p1>=0 ); - u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); - if( u.az.pCx==0 ) goto no_mem; - u.az.pCx->nullRow = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.az.pCx->pBt, - BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(u.az.pCx->pBt, 1); - } - if( rc==SQLITE_OK ){ - /* If a transient index is required, create it by calling - ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before - ** opening it. If a transient table is required, just use the - ** automatically created table with root-page 1 (an BLOB_INTKEY table). - */ - if( pOp->p4.pKeyInfo ){ - int pgno; - assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(u.az.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); - if( rc==SQLITE_OK ){ - assert( pgno==MASTER_ROOT+1 ); - rc = sqlite3BtreeCursor(u.az.pCx->pBt, pgno, 1, - (KeyInfo*)pOp->p4.z, u.az.pCx->pCursor); - u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo; - u.az.pCx->pKeyInfo->enc = ENC(p->db); - } - u.az.pCx->isTable = 0; - }else{ - rc = sqlite3BtreeCursor(u.az.pCx->pBt, MASTER_ROOT, 1, 0, u.az.pCx->pCursor); - u.az.pCx->isTable = 1; - } - } - u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); - u.az.pCx->isIndex = !u.az.pCx->isTable; - break; -} - -/* Opcode: SorterOpen P1 P2 * P4 * -** -** This opcode works like OP_OpenEphemeral except that it opens -** a transient index that is specifically designed to sort large -** tables using an external merge-sort algorithm. -*/ -case OP_SorterOpen: { -#if 0 /* local variables moved into u.ba */ - VdbeCursor *pCx; -#endif /* local variables moved into u.ba */ - - u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); - if( u.ba.pCx==0 ) goto no_mem; - u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo; - u.ba.pCx->pKeyInfo->enc = ENC(p->db); - u.ba.pCx->isSorter = 1; - rc = sqlite3VdbeSorterInit(db, u.ba.pCx); - break; -} - -/* Opcode: OpenPseudo P1 P2 P3 * P5 -** -** Open a new cursor that points to a fake table that contains a single -** row of data. The content of that one row in the content of memory -** register P2 when P5==0. In other words, cursor P1 becomes an alias for the -** MEM_Blob content contained in register P2. When P5==1, then the -** row is represented by P3 consecutive registers beginning with P2. -** -** A pseudo-table created by this opcode is used to hold a single -** row output from the sorter so that the row can be decomposed into -** individual columns using the OP_Column opcode. The OP_Column opcode -** is the only cursor opcode that works with a pseudo-table. -** -** P3 is the number of fields in the records that will be stored by -** the pseudo-table. -*/ -case OP_OpenPseudo: { -#if 0 /* local variables moved into u.bb */ - VdbeCursor *pCx; -#endif /* local variables moved into u.bb */ - - assert( pOp->p1>=0 ); - u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); - if( u.bb.pCx==0 ) goto no_mem; - u.bb.pCx->nullRow = 1; - u.bb.pCx->pseudoTableReg = pOp->p2; - u.bb.pCx->isTable = 1; - u.bb.pCx->isIndex = 0; - u.bb.pCx->multiPseudo = pOp->p5; - break; -} - -/* Opcode: Close P1 * * * * -** -** Close a cursor previously opened as P1. If P1 is not -** currently open, this instruction is a no-op. -*/ -case OP_Close: { - assert( pOp->p1>=0 && pOp->p1nCursor ); - sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]); - p->apCsr[pOp->p1] = 0; - break; -} - -/* Opcode: SeekGe P1 P2 P3 P4 * -** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as the key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. -** -** Reposition cursor P1 so that it points to the smallest entry that -** is greater than or equal to the key value. If there are no records -** greater than or equal to the key and P2 is not zero, then jump to P2. -** -** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe -*/ -/* Opcode: SeekGt P1 P2 P3 P4 * -** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. -** -** Reposition cursor P1 so that it points to the smallest entry that -** is greater than the key value. If there are no records greater than -** the key and P2 is not zero, then jump to P2. -** -** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe -*/ -/* Opcode: SeekLt P1 P2 P3 P4 * -** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. -** -** Reposition cursor P1 so that it points to the largest entry that -** is less than the key value. If there are no records less than -** the key and P2 is not zero, then jump to P2. -** -** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe -*/ -/* Opcode: SeekLe P1 P2 P3 P4 * -** -** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), -** use the value in register P3 as a key. If cursor P1 refers -** to an SQL index, then P3 is the first in an array of P4 registers -** that are used as an unpacked index key. -** -** Reposition cursor P1 so that it points to the largest entry that -** is less than or equal to the key value. If there are no records -** less than or equal to the key and P2 is not zero, then jump to P2. -** -** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt -*/ -case OP_SeekLt: /* jump, in3 */ -case OP_SeekLe: /* jump, in3 */ -case OP_SeekGe: /* jump, in3 */ -case OP_SeekGt: { /* jump, in3 */ -#if 0 /* local variables moved into u.bc */ - int res; - int oc; - VdbeCursor *pC; - UnpackedRecord r; - int nField; - i64 iKey; /* The rowid we are to seek to */ -#endif /* local variables moved into u.bc */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p2!=0 ); - u.bc.pC = p->apCsr[pOp->p1]; - assert( u.bc.pC!=0 ); - assert( u.bc.pC->pseudoTableReg==0 ); - assert( OP_SeekLe == OP_SeekLt+1 ); - assert( OP_SeekGe == OP_SeekLt+2 ); - assert( OP_SeekGt == OP_SeekLt+3 ); - assert( u.bc.pC->isOrdered ); - if( ALWAYS(u.bc.pC->pCursor!=0) ){ - u.bc.oc = pOp->opcode; - u.bc.pC->nullRow = 0; - if( u.bc.pC->isTable ){ - /* The input value in P3 might be of any type: integer, real, string, - ** blob, or NULL. But it needs to be an integer before we can do - ** the seek, so covert it. */ - pIn3 = &aMem[pOp->p3]; - applyNumericAffinity(pIn3); - u.bc.iKey = sqlite3VdbeIntValue(pIn3); - u.bc.pC->rowidIsValid = 0; - - /* If the P3 value could not be converted into an integer without - ** loss of information, then special processing is required... */ - if( (pIn3->flags & MEM_Int)==0 ){ - if( (pIn3->flags & MEM_Real)==0 ){ - /* If the P3 value cannot be converted into any kind of a number, - ** then the seek is not possible, so jump to P2 */ - pc = pOp->p2 - 1; - break; - } - /* If we reach this point, then the P3 value must be a floating - ** point number. */ - assert( (pIn3->flags & MEM_Real)!=0 ); - - if( u.bc.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bc.iKey || pIn3->r>0) ){ - /* The P3 value is too large in magnitude to be expressed as an - ** integer. */ - u.bc.res = 1; - if( pIn3->r<0 ){ - if( u.bc.oc>=OP_SeekGe ){ assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt ); - rc = sqlite3BtreeFirst(u.bc.pC->pCursor, &u.bc.res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - } - }else{ - if( u.bc.oc<=OP_SeekLe ){ assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe ); - rc = sqlite3BtreeLast(u.bc.pC->pCursor, &u.bc.res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - } - } - if( u.bc.res ){ - pc = pOp->p2 - 1; - } - break; - }else if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekGe ){ - /* Use the ceiling() function to convert real->int */ - if( pIn3->r > (double)u.bc.iKey ) u.bc.iKey++; - }else{ - /* Use the floor() function to convert real->int */ - assert( u.bc.oc==OP_SeekLe || u.bc.oc==OP_SeekGt ); - if( pIn3->r < (double)u.bc.iKey ) u.bc.iKey--; - } - } - rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, 0, (u64)u.bc.iKey, 0, &u.bc.res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( u.bc.res==0 ){ - u.bc.pC->rowidIsValid = 1; - u.bc.pC->lastRowid = u.bc.iKey; - } - }else{ - u.bc.nField = pOp->p4.i; - assert( pOp->p4type==P4_INT32 ); - assert( u.bc.nField>0 ); - u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo; - u.bc.r.nField = (u16)u.bc.nField; - - /* The next line of code computes as follows, only faster: - ** if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){ - ** u.bc.r.flags = UNPACKED_INCRKEY; - ** }else{ - ** u.bc.r.flags = 0; - ** } - */ - u.bc.r.flags = (u8)(UNPACKED_INCRKEY * (1 & (u.bc.oc - OP_SeekLt))); - assert( u.bc.oc!=OP_SeekGt || u.bc.r.flags==UNPACKED_INCRKEY ); - assert( u.bc.oc!=OP_SeekLe || u.bc.r.flags==UNPACKED_INCRKEY ); - assert( u.bc.oc!=OP_SeekGe || u.bc.r.flags==0 ); - assert( u.bc.oc!=OP_SeekLt || u.bc.r.flags==0 ); - - u.bc.r.aMem = &aMem[pOp->p3]; -#ifdef SQLITE_DEBUG - { int i; for(i=0; ipCursor, &u.bc.r, 0, 0, &u.bc.res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - u.bc.pC->rowidIsValid = 0; - } - u.bc.pC->deferredMoveto = 0; - u.bc.pC->cacheStatus = CACHE_STALE; -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - if( u.bc.oc>=OP_SeekGe ){ assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt ); - if( u.bc.res<0 || (u.bc.res==0 && u.bc.oc==OP_SeekGt) ){ - rc = sqlite3BtreeNext(u.bc.pC->pCursor, &u.bc.res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - u.bc.pC->rowidIsValid = 0; - }else{ - u.bc.res = 0; - } - }else{ - assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe ); - if( u.bc.res>0 || (u.bc.res==0 && u.bc.oc==OP_SeekLt) ){ - rc = sqlite3BtreePrevious(u.bc.pC->pCursor, &u.bc.res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; - u.bc.pC->rowidIsValid = 0; - }else{ - /* u.bc.res might be negative because the table is empty. Check to - ** see if this is the case. - */ - u.bc.res = sqlite3BtreeEof(u.bc.pC->pCursor); - } - } - assert( pOp->p2>0 ); - if( u.bc.res ){ - pc = pOp->p2 - 1; - } - }else{ - /* This happens when attempting to open the sqlite3_master table - ** for read access returns SQLITE_EMPTY. In this case always - ** take the jump (since there are no records in the table). - */ - pc = pOp->p2 - 1; - } - break; -} - -/* Opcode: Seek P1 P2 * * * -** -** P1 is an open table cursor and P2 is a rowid integer. Arrange -** for P1 to move so that it points to the rowid given by P2. -** -** This is actually a deferred seek. Nothing actually happens until -** the cursor is used to read a record. That way, if no reads -** occur, no unnecessary I/O happens. -*/ -case OP_Seek: { /* in2 */ -#if 0 /* local variables moved into u.bd */ - VdbeCursor *pC; -#endif /* local variables moved into u.bd */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bd.pC = p->apCsr[pOp->p1]; - assert( u.bd.pC!=0 ); - if( ALWAYS(u.bd.pC->pCursor!=0) ){ - assert( u.bd.pC->isTable ); - u.bd.pC->nullRow = 0; - pIn2 = &aMem[pOp->p2]; - u.bd.pC->movetoTarget = sqlite3VdbeIntValue(pIn2); - u.bd.pC->rowidIsValid = 0; - u.bd.pC->deferredMoveto = 1; - } - break; -} - - -/* Opcode: Found P1 P2 P3 P4 * -** -** If P4==0 then register P3 holds a blob constructed by MakeRecord. If -** P4>0 then register P3 is the first of P4 registers that form an unpacked -** record. -** -** Cursor P1 is on an index btree. If the record identified by P3 and P4 -** is a prefix of any entry in P1 then a jump is made to P2 and -** P1 is left pointing at the matching entry. -*/ -/* Opcode: NotFound P1 P2 P3 P4 * -** -** If P4==0 then register P3 holds a blob constructed by MakeRecord. If -** P4>0 then register P3 is the first of P4 registers that form an unpacked -** record. -** -** Cursor P1 is on an index btree. If the record identified by P3 and P4 -** is not the prefix of any entry in P1 then a jump is made to P2. If P1 -** does contain an entry whose prefix matches the P3/P4 record then control -** falls through to the next instruction and P1 is left pointing at the -** matching entry. -** -** See also: Found, NotExists, IsUnique -*/ -case OP_NotFound: /* jump, in3 */ -case OP_Found: { /* jump, in3 */ -#if 0 /* local variables moved into u.be */ - int alreadyExists; - VdbeCursor *pC; - int res; - char *pFree; - UnpackedRecord *pIdxKey; - UnpackedRecord r; - char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; -#endif /* local variables moved into u.be */ - -#ifdef SQLITE_TEST - sqlite3_found_count++; -#endif - - u.be.alreadyExists = 0; - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p4type==P4_INT32 ); - u.be.pC = p->apCsr[pOp->p1]; - assert( u.be.pC!=0 ); - pIn3 = &aMem[pOp->p3]; - if( ALWAYS(u.be.pC->pCursor!=0) ){ - - assert( u.be.pC->isTable==0 ); - if( pOp->p4.i>0 ){ - u.be.r.pKeyInfo = u.be.pC->pKeyInfo; - u.be.r.nField = (u16)pOp->p4.i; - u.be.r.aMem = pIn3; -#ifdef SQLITE_DEBUG - { int i; for(i=0; ipKeyInfo, u.be.aTempRec, sizeof(u.be.aTempRec), &u.be.pFree - ); - if( u.be.pIdxKey==0 ) goto no_mem; - assert( pIn3->flags & MEM_Blob ); - assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */ - sqlite3VdbeRecordUnpack(u.be.pC->pKeyInfo, pIn3->n, pIn3->z, u.be.pIdxKey); - u.be.pIdxKey->flags |= UNPACKED_PREFIX_MATCH; - } - rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, u.be.pIdxKey, 0, 0, &u.be.res); - if( pOp->p4.i==0 ){ - sqlite3DbFree(db, u.be.pFree); - } - if( rc!=SQLITE_OK ){ - break; - } - u.be.alreadyExists = (u.be.res==0); - u.be.pC->deferredMoveto = 0; - u.be.pC->cacheStatus = CACHE_STALE; - } - if( pOp->opcode==OP_Found ){ - if( u.be.alreadyExists ) pc = pOp->p2 - 1; - }else{ - if( !u.be.alreadyExists ) pc = pOp->p2 - 1; - } - break; -} - -/* Opcode: IsUnique P1 P2 P3 P4 * -** -** Cursor P1 is open on an index b-tree - that is to say, a btree which -** no data and where the key are records generated by OP_MakeRecord with -** the list field being the integer ROWID of the entry that the index -** entry refers to. -** -** The P3 register contains an integer record number. Call this record -** number R. Register P4 is the first in a set of N contiguous registers -** that make up an unpacked index key that can be used with cursor P1. -** The value of N can be inferred from the cursor. N includes the rowid -** value appended to the end of the index record. This rowid value may -** or may not be the same as R. -** -** If any of the N registers beginning with register P4 contains a NULL -** value, jump immediately to P2. -** -** Otherwise, this instruction checks if cursor P1 contains an entry -** where the first (N-1) fields match but the rowid value at the end -** of the index entry is not R. If there is no such entry, control jumps -** to instruction P2. Otherwise, the rowid of the conflicting index -** entry is copied to register P3 and control falls through to the next -** instruction. -** -** See also: NotFound, NotExists, Found -*/ -case OP_IsUnique: { /* jump, in3 */ -#if 0 /* local variables moved into u.bf */ - u16 ii; - VdbeCursor *pCx; - BtCursor *pCrsr; - u16 nField; - Mem *aMx; - UnpackedRecord r; /* B-Tree index search key */ - i64 R; /* Rowid stored in register P3 */ -#endif /* local variables moved into u.bf */ - - pIn3 = &aMem[pOp->p3]; - u.bf.aMx = &aMem[pOp->p4.i]; - /* Assert that the values of parameters P1 and P4 are in range. */ - assert( pOp->p4type==P4_INT32 ); - assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem ); - assert( pOp->p1>=0 && pOp->p1nCursor ); - - /* Find the index cursor. */ - u.bf.pCx = p->apCsr[pOp->p1]; - assert( u.bf.pCx->deferredMoveto==0 ); - u.bf.pCx->seekResult = 0; - u.bf.pCx->cacheStatus = CACHE_STALE; - u.bf.pCrsr = u.bf.pCx->pCursor; - - /* If any of the values are NULL, take the jump. */ - u.bf.nField = u.bf.pCx->pKeyInfo->nField; - for(u.bf.ii=0; u.bf.iip2 - 1; - u.bf.pCrsr = 0; - break; - } - } - assert( (u.bf.aMx[u.bf.nField].flags & MEM_Null)==0 ); - - if( u.bf.pCrsr!=0 ){ - /* Populate the index search key. */ - u.bf.r.pKeyInfo = u.bf.pCx->pKeyInfo; - u.bf.r.nField = u.bf.nField + 1; - u.bf.r.flags = UNPACKED_PREFIX_SEARCH; - u.bf.r.aMem = u.bf.aMx; -#ifdef SQLITE_DEBUG - { int i; for(i=0; iu.i; - - /* Search the B-Tree index. If no conflicting record is found, jump - ** to P2. Otherwise, copy the rowid of the conflicting record to - ** register P3 and fall through to the next instruction. */ - rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, &u.bf.r, 0, 0, &u.bf.pCx->seekResult); - if( (u.bf.r.flags & UNPACKED_PREFIX_SEARCH) || u.bf.r.rowid==u.bf.R ){ - pc = pOp->p2 - 1; - }else{ - pIn3->u.i = u.bf.r.rowid; - } - } - break; -} - -/* Opcode: NotExists P1 P2 P3 * * -** -** Use the content of register P3 as an integer key. If a record -** with that key does not exist in table of P1, then jump to P2. -** If the record does exist, then fall through. The cursor is left -** pointing to the record if it exists. -** -** The difference between this operation and NotFound is that this -** operation assumes the key is an integer and that P1 is a table whereas -** NotFound assumes key is a blob constructed from MakeRecord and -** P1 is an index. -** -** See also: Found, NotFound, IsUnique -*/ -case OP_NotExists: { /* jump, in3 */ -#if 0 /* local variables moved into u.bg */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - u64 iKey; -#endif /* local variables moved into u.bg */ - - pIn3 = &aMem[pOp->p3]; - assert( pIn3->flags & MEM_Int ); - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bg.pC = p->apCsr[pOp->p1]; - assert( u.bg.pC!=0 ); - assert( u.bg.pC->isTable ); - assert( u.bg.pC->pseudoTableReg==0 ); - u.bg.pCrsr = u.bg.pC->pCursor; - if( ALWAYS(u.bg.pCrsr!=0) ){ - u.bg.res = 0; - u.bg.iKey = pIn3->u.i; - rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res); - u.bg.pC->lastRowid = pIn3->u.i; - u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0; - u.bg.pC->nullRow = 0; - u.bg.pC->cacheStatus = CACHE_STALE; - u.bg.pC->deferredMoveto = 0; - if( u.bg.res!=0 ){ - pc = pOp->p2 - 1; - assert( u.bg.pC->rowidIsValid==0 ); - } - u.bg.pC->seekResult = u.bg.res; - }else{ - /* This happens when an attempt to open a read cursor on the - ** sqlite_master table returns SQLITE_EMPTY. - */ - pc = pOp->p2 - 1; - assert( u.bg.pC->rowidIsValid==0 ); - u.bg.pC->seekResult = 0; - } - break; -} - -/* Opcode: Sequence P1 P2 * * * -** -** Find the next available sequence number for cursor P1. -** Write the sequence number into register P2. -** The sequence number on the cursor is incremented after this -** instruction. -*/ -case OP_Sequence: { /* out2-prerelease */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( p->apCsr[pOp->p1]!=0 ); - pOut->u.i = p->apCsr[pOp->p1]->seqCount++; - break; -} - - -/* Opcode: NewRowid P1 P2 P3 * * -** -** Get a new integer record number (a.k.a "rowid") used as the key to a table. -** The record number is not previously used as a key in the database -** table that cursor P1 points to. The new record number is written -** written to register P2. -** -** If P3>0 then P3 is a register in the root frame of this VDBE that holds -** the largest previously generated record number. No new record numbers are -** allowed to be less than this value. When this value reaches its maximum, -** an SQLITE_FULL error is generated. The P3 register is updated with the ' -** generated record number. This P3 mechanism is used to help implement the -** AUTOINCREMENT feature. -*/ -case OP_NewRowid: { /* out2-prerelease */ -#if 0 /* local variables moved into u.bh */ - i64 v; /* The new rowid */ - VdbeCursor *pC; /* Cursor of table to get the new rowid */ - int res; /* Result of an sqlite3BtreeLast() */ - int cnt; /* Counter to limit the number of searches */ - Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */ - VdbeFrame *pFrame; /* Root frame of VDBE */ -#endif /* local variables moved into u.bh */ - - u.bh.v = 0; - u.bh.res = 0; - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bh.pC = p->apCsr[pOp->p1]; - assert( u.bh.pC!=0 ); - if( NEVER(u.bh.pC->pCursor==0) ){ - /* The zero initialization above is all that is needed */ - }else{ - /* The next rowid or record number (different terms for the same - ** thing) is obtained in a two-step algorithm. - ** - ** First we attempt to find the largest existing rowid and add one - ** to that. But if the largest existing rowid is already the maximum - ** positive integer, we have to fall through to the second - ** probabilistic algorithm - ** - ** The second algorithm is to select a rowid at random and see if - ** it already exists in the table. If it does not exist, we have - ** succeeded. If the random rowid does exist, we select a new one - ** and try again, up to 100 times. - */ - assert( u.bh.pC->isTable ); - -#ifdef SQLITE_32BIT_ROWID -# define MAX_ROWID 0x7fffffff -#else - /* Some compilers complain about constants of the form 0x7fffffffffffffff. - ** Others complain about 0x7ffffffffffffffffLL. The following macro seems - ** to provide the constant while making all compilers happy. - */ -# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) -#endif - - if( !u.bh.pC->useRandomRowid ){ - u.bh.v = sqlite3BtreeGetCachedRowid(u.bh.pC->pCursor); - if( u.bh.v==0 ){ - rc = sqlite3BtreeLast(u.bh.pC->pCursor, &u.bh.res); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - if( u.bh.res ){ - u.bh.v = 1; /* IMP: R-61914-48074 */ - }else{ - assert( sqlite3BtreeCursorIsValid(u.bh.pC->pCursor) ); - rc = sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v); - assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ - if( u.bh.v>=MAX_ROWID ){ - u.bh.pC->useRandomRowid = 1; - }else{ - u.bh.v++; /* IMP: R-29538-34987 */ - } - } - } - -#ifndef SQLITE_OMIT_AUTOINCREMENT - if( pOp->p3 ){ - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3>0 ); - if( p->pFrame ){ - for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent); - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=u.bh.pFrame->nMem ); - u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3]; - }else{ - /* Assert that P3 is a valid memory cell. */ - assert( pOp->p3<=p->nMem ); - u.bh.pMem = &aMem[pOp->p3]; - memAboutToChange(p, u.bh.pMem); - } - assert( memIsValid(u.bh.pMem) ); - - REGISTER_TRACE(pOp->p3, u.bh.pMem); - sqlite3VdbeMemIntegerify(u.bh.pMem); - assert( (u.bh.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ - if( u.bh.pMem->u.i==MAX_ROWID || u.bh.pC->useRandomRowid ){ - rc = SQLITE_FULL; /* IMP: R-12275-61338 */ - goto abort_due_to_error; - } - if( u.bh.vu.i+1 ){ - u.bh.v = u.bh.pMem->u.i + 1; - } - u.bh.pMem->u.i = u.bh.v; - } -#endif - - sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, u.bh.vuseRandomRowid ){ - /* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the - ** largest possible integer (9223372036854775807) then the database - ** engine starts picking positive candidate ROWIDs at random until - ** it finds one that is not previously used. */ - assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is - ** an AUTOINCREMENT table. */ - /* on the first attempt, simply do one more than previous */ - u.bh.v = lastRowid; - u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ - u.bh.v++; /* ensure non-zero */ - u.bh.cnt = 0; - while( ((rc = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.v, - 0, &u.bh.res))==SQLITE_OK) - && (u.bh.res==0) - && (++u.bh.cnt<100)){ - /* collision - try another random rowid */ - sqlite3_randomness(sizeof(u.bh.v), &u.bh.v); - if( u.bh.cnt<5 ){ - /* try "small" random rowids for the initial attempts */ - u.bh.v &= 0xffffff; - }else{ - u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */ - } - u.bh.v++; /* ensure non-zero */ - } - if( rc==SQLITE_OK && u.bh.res==0 ){ - rc = SQLITE_FULL; /* IMP: R-38219-53002 */ - goto abort_due_to_error; - } - assert( u.bh.v>0 ); /* EV: R-40812-03570 */ - } - u.bh.pC->rowidIsValid = 0; - u.bh.pC->deferredMoveto = 0; - u.bh.pC->cacheStatus = CACHE_STALE; - } - pOut->u.i = u.bh.v; - break; -} - -/* Opcode: Insert P1 P2 P3 P4 P5 -** -** Write an entry into the table of cursor P1. A new entry is -** created if it doesn't already exist or the data for an existing -** entry is overwritten. The data is the value MEM_Blob stored in register -** number P2. The key is stored in register P3. The key must -** be a MEM_Int. -** -** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is -** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, -** then rowid is stored for subsequent return by the -** sqlite3_last_insert_rowid() function (otherwise it is unmodified). -** -** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of -** the last seek operation (OP_NotExists) was a success, then this -** operation will not attempt to find the appropriate row before doing -** the insert but will instead overwrite the row that the cursor is -** currently pointing to. Presumably, the prior OP_NotExists opcode -** has already positioned the cursor correctly. This is an optimization -** that boosts performance by avoiding redundant seeks. -** -** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an -** UPDATE operation. Otherwise (if the flag is clear) then this opcode -** is part of an INSERT operation. The difference is only important to -** the update hook. -** -** Parameter P4 may point to a string containing the table-name, or -** may be NULL. If it is not NULL, then the update-hook -** (sqlite3.xUpdateCallback) is invoked following a successful insert. -** -** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically -** allocated, then ownership of P2 is transferred to the pseudo-cursor -** and register P2 becomes ephemeral. If the cursor is changed, the -** value of register P2 will then change. Make sure this does not -** cause any problems.) -** -** This instruction only works on tables. The equivalent instruction -** for indices is OP_IdxInsert. -*/ -/* Opcode: InsertInt P1 P2 P3 P4 P5 -** -** This works exactly like OP_Insert except that the key is the -** integer value P3, not the value of the integer stored in register P3. -*/ -case OP_Insert: -case OP_InsertInt: { -#if 0 /* local variables moved into u.bi */ - Mem *pData; /* MEM cell holding data for the record to be inserted */ - Mem *pKey; /* MEM cell holding key for the record */ - i64 iKey; /* The integer ROWID or key for the record to be inserted */ - VdbeCursor *pC; /* Cursor to table into which insert is written */ - int nZero; /* Number of zero-bytes to append */ - int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ - const char *zDb; /* database name - used by the update hook */ - const char *zTbl; /* Table name - used by the opdate hook */ - int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ -#endif /* local variables moved into u.bi */ - - u.bi.pData = &aMem[pOp->p2]; - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( memIsValid(u.bi.pData) ); - u.bi.pC = p->apCsr[pOp->p1]; - assert( u.bi.pC!=0 ); - assert( u.bi.pC->pCursor!=0 ); - assert( u.bi.pC->pseudoTableReg==0 ); - assert( u.bi.pC->isTable ); - REGISTER_TRACE(pOp->p2, u.bi.pData); - - if( pOp->opcode==OP_Insert ){ - u.bi.pKey = &aMem[pOp->p3]; - assert( u.bi.pKey->flags & MEM_Int ); - assert( memIsValid(u.bi.pKey) ); - REGISTER_TRACE(pOp->p3, u.bi.pKey); - u.bi.iKey = u.bi.pKey->u.i; - }else{ - assert( pOp->opcode==OP_InsertInt ); - u.bi.iKey = pOp->p3; - } - - if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bi.iKey; - if( u.bi.pData->flags & MEM_Null ){ - u.bi.pData->z = 0; - u.bi.pData->n = 0; - }else{ - assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) ); - } - u.bi.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bi.pC->seekResult : 0); - if( u.bi.pData->flags & MEM_Zero ){ - u.bi.nZero = u.bi.pData->u.nZero; - }else{ - u.bi.nZero = 0; - } - sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0); - rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey, - u.bi.pData->z, u.bi.pData->n, u.bi.nZero, - pOp->p5 & OPFLAG_APPEND, u.bi.seekResult - ); - u.bi.pC->rowidIsValid = 0; - u.bi.pC->deferredMoveto = 0; - u.bi.pC->cacheStatus = CACHE_STALE; - - /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - u.bi.zDb = db->aDb[u.bi.pC->iDb].zName; - u.bi.zTbl = pOp->p4.z; - u.bi.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); - assert( u.bi.pC->isTable ); - db->xUpdateCallback(db->pUpdateArg, u.bi.op, u.bi.zDb, u.bi.zTbl, u.bi.iKey); - assert( u.bi.pC->iDb>=0 ); - } - break; -} - -/* Opcode: Delete P1 P2 * P4 * -** -** Delete the record at which the P1 cursor is currently pointing. -** -** The cursor will be left pointing at either the next or the previous -** record in the table. If it is left pointing at the next record, then -** the next Next instruction will be a no-op. Hence it is OK to delete -** a record from within an Next loop. -** -** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is -** incremented (otherwise not). -** -** P1 must not be pseudo-table. It has to be a real table with -** multiple rows. -** -** If P4 is not NULL, then it is the name of the table that P1 is -** pointing to. The update hook will be invoked, if it exists. -** If P4 is not NULL then the P1 cursor must have been positioned -** using OP_NotFound prior to invoking this opcode. -*/ -case OP_Delete: { -#if 0 /* local variables moved into u.bj */ - i64 iKey; - VdbeCursor *pC; -#endif /* local variables moved into u.bj */ - - u.bj.iKey = 0; - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bj.pC = p->apCsr[pOp->p1]; - assert( u.bj.pC!=0 ); - assert( u.bj.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */ - - /* If the update-hook will be invoked, set u.bj.iKey to the rowid of the - ** row being deleted. - */ - if( db->xUpdateCallback && pOp->p4.z ){ - assert( u.bj.pC->isTable ); - assert( u.bj.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */ - u.bj.iKey = u.bj.pC->lastRowid; - } - - /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or - ** OP_Column on the same table without any intervening operations that - ** might move or invalidate the cursor. Hence cursor u.bj.pC is always pointing - ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation - ** below is always a no-op and cannot fail. We will run it anyhow, though, - ** to guard against future changes to the code generator. - **/ - assert( u.bj.pC->deferredMoveto==0 ); - rc = sqlite3VdbeCursorMoveto(u.bj.pC); - if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - - sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0); - rc = sqlite3BtreeDelete(u.bj.pC->pCursor); - u.bj.pC->cacheStatus = CACHE_STALE; - - /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - const char *zDb = db->aDb[u.bj.pC->iDb].zName; - const char *zTbl = pOp->p4.z; - db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bj.iKey); - assert( u.bj.pC->iDb>=0 ); - } - if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; - break; -} -/* Opcode: ResetCount * * * * * -** -** The value of the change counter is copied to the database handle -** change counter (returned by subsequent calls to sqlite3_changes()). -** Then the VMs internal change counter resets to 0. -** This is used by trigger programs. -*/ -case OP_ResetCount: { - sqlite3VdbeSetChanges(db, p->nChange); - p->nChange = 0; - break; -} - -/* Opcode: SorterCompare P1 P2 P3 -** -** P1 is a sorter cursor. This instruction compares the record blob in -** register P3 with the entry that the sorter cursor currently points to. -** If, excluding the rowid fields at the end, the two records are a match, -** fall through to the next instruction. Otherwise, jump to instruction P2. -*/ -case OP_SorterCompare: { -#if 0 /* local variables moved into u.bk */ - VdbeCursor *pC; - int res; -#endif /* local variables moved into u.bk */ - - u.bk.pC = p->apCsr[pOp->p1]; - assert( isSorter(u.bk.pC) ); - pIn3 = &aMem[pOp->p3]; - rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, &u.bk.res); - if( u.bk.res ){ - pc = pOp->p2-1; - } - break; -}; - -/* Opcode: SorterData P1 P2 * * * -** -** Write into register P2 the current sorter data for sorter cursor P1. -*/ -case OP_SorterData: { -#if 0 /* local variables moved into u.bl */ - VdbeCursor *pC; -#endif /* local variables moved into u.bl */ - - pOut = &aMem[pOp->p2]; - u.bl.pC = p->apCsr[pOp->p1]; - assert( u.bl.pC->isSorter ); - rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut); - break; -} - -/* Opcode: RowData P1 P2 * * * -** -** Write into register P2 the complete row data for cursor P1. -** There is no interpretation of the data. -** It is just copied onto the P2 register exactly as -** it is found in the database file. -** -** If the P1 cursor must be pointing to a valid row (not a NULL row) -** of a real table, not a pseudo-table. -*/ -/* Opcode: RowKey P1 P2 * * * -** -** Write into register P2 the complete row key for cursor P1. -** There is no interpretation of the data. -** The key is copied onto the P3 register exactly as -** it is found in the database file. -** -** If the P1 cursor must be pointing to a valid row (not a NULL row) -** of a real table, not a pseudo-table. -*/ -case OP_RowKey: -case OP_RowData: { -#if 0 /* local variables moved into u.bm */ - VdbeCursor *pC; - BtCursor *pCrsr; - u32 n; - i64 n64; -#endif /* local variables moved into u.bm */ - - pOut = &aMem[pOp->p2]; - memAboutToChange(p, pOut); - - /* Note that RowKey and RowData are really exactly the same instruction */ - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bm.pC = p->apCsr[pOp->p1]; - assert( u.bm.pC->isSorter==0 ); - assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData ); - assert( u.bm.pC->isIndex || pOp->opcode==OP_RowData ); - assert( u.bm.pC!=0 ); - assert( u.bm.pC->nullRow==0 ); - assert( u.bm.pC->pseudoTableReg==0 ); - assert( u.bm.pC->pCursor!=0 ); - u.bm.pCrsr = u.bm.pC->pCursor; - assert( sqlite3BtreeCursorIsValid(u.bm.pCrsr) ); - - /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or - ** OP_Rewind/Op_Next with no intervening instructions that might invalidate - ** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always - ** a no-op and can never fail. But we leave it in place as a safety. - */ - assert( u.bm.pC->deferredMoveto==0 ); - rc = sqlite3VdbeCursorMoveto(u.bm.pC); - if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; - - if( u.bm.pC->isIndex ){ - assert( !u.bm.pC->isTable ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64); - assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ - if( u.bm.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - u.bm.n = (u32)u.bm.n64; - }else{ - VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bm.pCrsr, &u.bm.n); - assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - if( u.bm.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - } - if( sqlite3VdbeMemGrow(pOut, u.bm.n, 0) ){ - goto no_mem; - } - pOut->n = u.bm.n; - MemSetTypeFlag(pOut, MEM_Blob); - if( u.bm.pC->isIndex ){ - rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z); - }else{ - rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z); - } - pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - -/* Opcode: Rowid P1 P2 * * * -** -** Store in register P2 an integer which is the key of the table entry that -** P1 is currently point to. -** -** P1 can be either an ordinary table or a virtual table. There used to -** be a separate OP_VRowid opcode for use with virtual tables, but this -** one opcode now works for both table types. -*/ -case OP_Rowid: { /* out2-prerelease */ -#if 0 /* local variables moved into u.bn */ - VdbeCursor *pC; - i64 v; - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; -#endif /* local variables moved into u.bn */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bn.pC = p->apCsr[pOp->p1]; - assert( u.bn.pC!=0 ); - assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow ); - if( u.bn.pC->nullRow ){ - pOut->flags = MEM_Null; - break; - }else if( u.bn.pC->deferredMoveto ){ - u.bn.v = u.bn.pC->movetoTarget; -#ifndef SQLITE_OMIT_VIRTUALTABLE - }else if( u.bn.pC->pVtabCursor ){ - u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab; - u.bn.pModule = u.bn.pVtab->pModule; - assert( u.bn.pModule->xRowid ); - rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v); - importVtabErrMsg(p, u.bn.pVtab); -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - }else{ - assert( u.bn.pC->pCursor!=0 ); - rc = sqlite3VdbeCursorMoveto(u.bn.pC); - if( rc ) goto abort_due_to_error; - if( u.bn.pC->rowidIsValid ){ - u.bn.v = u.bn.pC->lastRowid; - }else{ - rc = sqlite3BtreeKeySize(u.bn.pC->pCursor, &u.bn.v); - assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */ - } - } - pOut->u.i = u.bn.v; - break; -} - -/* Opcode: NullRow P1 * * * * -** -** Move the cursor P1 to a null row. Any OP_Column operations -** that occur while the cursor is on the null row will always -** write a NULL. -*/ -case OP_NullRow: { -#if 0 /* local variables moved into u.bo */ - VdbeCursor *pC; -#endif /* local variables moved into u.bo */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bo.pC = p->apCsr[pOp->p1]; - assert( u.bo.pC!=0 ); - u.bo.pC->nullRow = 1; - u.bo.pC->rowidIsValid = 0; - assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor ); - if( u.bo.pC->pCursor ){ - sqlite3BtreeClearCursor(u.bo.pC->pCursor); - } - break; -} - -/* Opcode: Last P1 P2 * * * -** -** The next use of the Rowid or Column or Next instruction for P1 -** will refer to the last entry in the database table or index. -** If the table or index is empty and P2>0, then jump immediately to P2. -** If P2 is 0 or if the table or index is not empty, fall through -** to the following instruction. -*/ -case OP_Last: { /* jump */ -#if 0 /* local variables moved into u.bp */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; -#endif /* local variables moved into u.bp */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bp.pC = p->apCsr[pOp->p1]; - assert( u.bp.pC!=0 ); - u.bp.pCrsr = u.bp.pC->pCursor; - u.bp.res = 0; - if( ALWAYS(u.bp.pCrsr!=0) ){ - rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res); - } - u.bp.pC->nullRow = (u8)u.bp.res; - u.bp.pC->deferredMoveto = 0; - u.bp.pC->rowidIsValid = 0; - u.bp.pC->cacheStatus = CACHE_STALE; - if( pOp->p2>0 && u.bp.res ){ - pc = pOp->p2 - 1; - } - break; -} - - -/* Opcode: Sort P1 P2 * * * -** -** This opcode does exactly the same thing as OP_Rewind except that -** it increments an undocumented global variable used for testing. -** -** Sorting is accomplished by writing records into a sorting index, -** then rewinding that index and playing it back from beginning to -** end. We use the OP_Sort opcode instead of OP_Rewind to do the -** rewinding so that the global variable will be incremented and -** regression tests can determine whether or not the optimizer is -** correctly optimizing out sorts. -*/ -case OP_SorterSort: /* jump */ -case OP_Sort: { /* jump */ -#ifdef SQLITE_TEST - sqlite3_sort_count++; - sqlite3_search_count--; -#endif - p->aCounter[SQLITE_STMTSTATUS_SORT-1]++; - /* Fall through into OP_Rewind */ -} -/* Opcode: Rewind P1 P2 * * * -** -** The next use of the Rowid or Column or Next instruction for P1 -** will refer to the first entry in the database table or index. -** If the table or index is empty and P2>0, then jump immediately to P2. -** If P2 is 0 or if the table or index is not empty, fall through -** to the following instruction. -*/ -case OP_Rewind: { /* jump */ -#if 0 /* local variables moved into u.bq */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; -#endif /* local variables moved into u.bq */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bq.pC = p->apCsr[pOp->p1]; - assert( u.bq.pC!=0 ); - assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterSort) ); - u.bq.res = 1; - if( isSorter(u.bq.pC) ){ - rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res); - }else{ - u.bq.pCrsr = u.bq.pC->pCursor; - assert( u.bq.pCrsr ); - rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res); - u.bq.pC->atFirst = u.bq.res==0 ?1:0; - u.bq.pC->deferredMoveto = 0; - u.bq.pC->cacheStatus = CACHE_STALE; - u.bq.pC->rowidIsValid = 0; - } - u.bq.pC->nullRow = (u8)u.bq.res; - assert( pOp->p2>0 && pOp->p2nOp ); - if( u.bq.res ){ - pc = pOp->p2 - 1; - } - break; -} - -/* Opcode: Next P1 P2 * P4 P5 -** -** Advance cursor P1 so that it points to the next key/data pair in its -** table or index. If there are no more key/value pairs then fall through -** to the following instruction. But if the cursor advance was successful, -** jump immediately to P2. -** -** The P1 cursor must be for a real table, not a pseudo-table. -** -** P4 is always of type P4_ADVANCE. The function pointer points to -** sqlite3BtreeNext(). -** -** If P5 is positive and the jump is taken, then event counter -** number P5-1 in the prepared statement is incremented. -** -** See also: Prev -*/ -/* Opcode: Prev P1 P2 * * P5 -** -** Back up cursor P1 so that it points to the previous key/data pair in its -** table or index. If there is no previous key/value pairs then fall through -** to the following instruction. But if the cursor backup was successful, -** jump immediately to P2. -** -** The P1 cursor must be for a real table, not a pseudo-table. -** -** P4 is always of type P4_ADVANCE. The function pointer points to -** sqlite3BtreePrevious(). -** -** If P5 is positive and the jump is taken, then event counter -** number P5-1 in the prepared statement is incremented. -*/ -case OP_SorterNext: /* jump */ -case OP_Prev: /* jump */ -case OP_Next: { /* jump */ -#if 0 /* local variables moved into u.br */ - VdbeCursor *pC; - int res; -#endif /* local variables moved into u.br */ - - CHECK_FOR_INTERRUPT; - assert( pOp->p1>=0 && pOp->p1nCursor ); - assert( pOp->p5<=ArraySize(p->aCounter) ); - u.br.pC = p->apCsr[pOp->p1]; - if( u.br.pC==0 ){ - break; /* See ticket #2273 */ - } - assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) ); - if( isSorter(u.br.pC) ){ - assert( pOp->opcode==OP_SorterNext ); - rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res); - }else{ - u.br.res = 1; - assert( u.br.pC->deferredMoveto==0 ); - assert( u.br.pC->pCursor ); - assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); - assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); - rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res); - } - u.br.pC->nullRow = (u8)u.br.res; - u.br.pC->cacheStatus = CACHE_STALE; - if( u.br.res==0 ){ - pc = pOp->p2 - 1; - if( pOp->p5 ) p->aCounter[pOp->p5-1]++; -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - } - u.br.pC->rowidIsValid = 0; - break; -} - -/* Opcode: IdxInsert P1 P2 P3 * P5 -** -** Register P2 holds an SQL index key made using the -** MakeRecord instructions. This opcode writes that key -** into the index P1. Data for the entry is nil. -** -** P3 is a flag that provides a hint to the b-tree layer that this -** insert is likely to be an append. -** -** This instruction only works for indices. The equivalent instruction -** for tables is OP_Insert. -*/ -case OP_SorterInsert: /* in2 */ -case OP_IdxInsert: { /* in2 */ -#if 0 /* local variables moved into u.bs */ - VdbeCursor *pC; - BtCursor *pCrsr; - int nKey; - const char *zKey; -#endif /* local variables moved into u.bs */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bs.pC = p->apCsr[pOp->p1]; - assert( u.bs.pC!=0 ); - assert( u.bs.pC->isSorter==(pOp->opcode==OP_SorterInsert) ); - pIn2 = &aMem[pOp->p2]; - assert( pIn2->flags & MEM_Blob ); - u.bs.pCrsr = u.bs.pC->pCursor; - if( ALWAYS(u.bs.pCrsr!=0) ){ - assert( u.bs.pC->isTable==0 ); - rc = ExpandBlob(pIn2); - if( rc==SQLITE_OK ){ - if( isSorter(u.bs.pC) ){ - rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2); - }else{ - u.bs.nKey = pIn2->n; - u.bs.zKey = pIn2->z; - rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3, - ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0) - ); - assert( u.bs.pC->deferredMoveto==0 ); - u.bs.pC->cacheStatus = CACHE_STALE; - } - } - } - break; -} - -/* Opcode: IdxDelete P1 P2 P3 * * -** -** The content of P3 registers starting at register P2 form -** an unpacked index key. This opcode removes that entry from the -** index opened by cursor P1. -*/ -case OP_IdxDelete: { -#if 0 /* local variables moved into u.bt */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - UnpackedRecord r; -#endif /* local variables moved into u.bt */ - - assert( pOp->p3>0 ); - assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 ); - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bt.pC = p->apCsr[pOp->p1]; - assert( u.bt.pC!=0 ); - u.bt.pCrsr = u.bt.pC->pCursor; - if( ALWAYS(u.bt.pCrsr!=0) ){ - u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo; - u.bt.r.nField = (u16)pOp->p3; - u.bt.r.flags = 0; - u.bt.r.aMem = &aMem[pOp->p2]; -#ifdef SQLITE_DEBUG - { int i; for(i=0; ideferredMoveto==0 ); - u.bt.pC->cacheStatus = CACHE_STALE; - } - break; -} - -/* Opcode: IdxRowid P1 P2 * * * -** -** Write into register P2 an integer which is the last entry in the record at -** the end of the index key pointed to by cursor P1. This integer should be -** the rowid of the table entry to which this index entry points. -** -** See also: Rowid, MakeRecord. -*/ -case OP_IdxRowid: { /* out2-prerelease */ -#if 0 /* local variables moved into u.bu */ - BtCursor *pCrsr; - VdbeCursor *pC; - i64 rowid; -#endif /* local variables moved into u.bu */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bu.pC = p->apCsr[pOp->p1]; - assert( u.bu.pC!=0 ); - u.bu.pCrsr = u.bu.pC->pCursor; - pOut->flags = MEM_Null; - if( ALWAYS(u.bu.pCrsr!=0) ){ - rc = sqlite3VdbeCursorMoveto(u.bu.pC); - if( NEVER(rc) ) goto abort_due_to_error; - assert( u.bu.pC->deferredMoveto==0 ); - assert( u.bu.pC->isTable==0 ); - if( !u.bu.pC->nullRow ){ - rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - pOut->u.i = u.bu.rowid; - pOut->flags = MEM_Int; - } - } - break; -} - -/* Opcode: IdxGE P1 P2 P3 P4 P5 -** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the ROWID. Compare this key value against the index -** that P1 is currently pointing to, ignoring the ROWID on the P1 index. -** -** If the P1 index entry is greater than or equal to the key value -** then jump to P2. Otherwise fall through to the next instruction. -** -** If P5 is non-zero then the key value is increased by an epsilon -** prior to the comparison. This make the opcode work like IdxGT except -** that if the key from register P3 is a prefix of the key in the cursor, -** the result is false whereas it would be true with IdxGT. -*/ -/* Opcode: IdxLT P1 P2 P3 P4 P5 -** -** The P4 register values beginning with P3 form an unpacked index -** key that omits the ROWID. Compare this key value against the index -** that P1 is currently pointing to, ignoring the ROWID on the P1 index. -** -** If the P1 index entry is less than the key value then jump to P2. -** Otherwise fall through to the next instruction. -** -** If P5 is non-zero then the key value is increased by an epsilon prior -** to the comparison. This makes the opcode work like IdxLE. -*/ -case OP_IdxLT: /* jump */ -case OP_IdxGE: { /* jump */ -#if 0 /* local variables moved into u.bv */ - VdbeCursor *pC; - int res; - UnpackedRecord r; -#endif /* local variables moved into u.bv */ - - assert( pOp->p1>=0 && pOp->p1nCursor ); - u.bv.pC = p->apCsr[pOp->p1]; - assert( u.bv.pC!=0 ); - assert( u.bv.pC->isOrdered ); - if( ALWAYS(u.bv.pC->pCursor!=0) ){ - assert( u.bv.pC->deferredMoveto==0 ); - assert( pOp->p5==0 || pOp->p5==1 ); - assert( pOp->p4type==P4_INT32 ); - u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo; - u.bv.r.nField = (u16)pOp->p4.i; - if( pOp->p5 ){ - u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH; - }else{ - u.bv.r.flags = UNPACKED_PREFIX_MATCH; - } - u.bv.r.aMem = &aMem[pOp->p3]; -#ifdef SQLITE_DEBUG - { int i; for(i=0; iopcode==OP_IdxLT ){ - u.bv.res = -u.bv.res; - }else{ - assert( pOp->opcode==OP_IdxGE ); - u.bv.res++; - } - if( u.bv.res>0 ){ - pc = pOp->p2 - 1 ; - } - } - break; -} - -/* Opcode: Destroy P1 P2 P3 * * -** -** Delete an entire database table or index whose root page in the database -** file is given by P1. -** -** The table being destroyed is in the main database file if P3==0. If -** P3==1 then the table to be clear is in the auxiliary database file -** that is used to store tables create using CREATE TEMPORARY TABLE. -** -** If AUTOVACUUM is enabled then it is possible that another root page -** might be moved into the newly deleted root page in order to keep all -** root pages contiguous at the beginning of the database. The former -** value of the root page that moved - its value before the move occurred - -** is stored in register P2. If no page -** movement was required (because the table being dropped was already -** the last one in the database) then a zero is stored in register P2. -** If AUTOVACUUM is disabled then a zero is stored in register P2. -** -** See also: Clear -*/ -case OP_Destroy: { /* out2-prerelease */ -#if 0 /* local variables moved into u.bw */ - int iMoved; - int iCnt; - Vdbe *pVdbe; - int iDb; -#endif /* local variables moved into u.bw */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE - u.bw.iCnt = 0; - for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){ - if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 ){ - u.bw.iCnt++; - } - } -#else - u.bw.iCnt = db->activeVdbeCnt; -#endif - pOut->flags = MEM_Null; - if( u.bw.iCnt>1 ){ - rc = SQLITE_LOCKED; - p->errorAction = OE_Abort; - }else{ - u.bw.iDb = pOp->p3; - assert( u.bw.iCnt==1 ); - assert( (p->btreeMask & (((yDbMask)1)<aDb[u.bw.iDb].pBt, pOp->p1, &u.bw.iMoved); - pOut->flags = MEM_Int; - pOut->u.i = u.bw.iMoved; -#ifndef SQLITE_OMIT_AUTOVACUUM - if( rc==SQLITE_OK && u.bw.iMoved!=0 ){ - sqlite3RootPageMoved(db, u.bw.iDb, u.bw.iMoved, pOp->p1); - /* All OP_Destroy operations occur on the same btree */ - assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bw.iDb+1 ); - resetSchemaOnFault = u.bw.iDb+1; - } -#endif - } - break; -} - -/* Opcode: Clear P1 P2 P3 -** -** Delete all contents of the database table or index whose root page -** in the database file is given by P1. But, unlike Destroy, do not -** remove the table or index from the database file. -** -** The table being clear is in the main database file if P2==0. If -** P2==1 then the table to be clear is in the auxiliary database file -** that is used to store tables create using CREATE TEMPORARY TABLE. -** -** If the P3 value is non-zero, then the table referred to must be an -** intkey table (an SQL table, not an index). In this case the row change -** count is incremented by the number of rows in the table being cleared. -** If P3 is greater than zero, then the value stored in register P3 is -** also incremented by the number of rows in the table being cleared. -** -** See also: Destroy -*/ -case OP_Clear: { -#if 0 /* local variables moved into u.bx */ - int nChange; -#endif /* local variables moved into u.bx */ - - u.bx.nChange = 0; - assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 ); - rc = sqlite3BtreeClearTable( - db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0) - ); - if( pOp->p3 ){ - p->nChange += u.bx.nChange; - if( pOp->p3>0 ){ - assert( memIsValid(&aMem[pOp->p3]) ); - memAboutToChange(p, &aMem[pOp->p3]); - aMem[pOp->p3].u.i += u.bx.nChange; - } - } - break; -} - -/* Opcode: CreateTable P1 P2 * * * -** -** Allocate a new table in the main database file if P1==0 or in the -** auxiliary database file if P1==1 or in an attached database if -** P1>1. Write the root page number of the new table into -** register P2 -** -** The difference between a table and an index is this: A table must -** have a 4-byte integer key and can have arbitrary data. An index -** has an arbitrary key but no data. -** -** See also: CreateIndex -*/ -/* Opcode: CreateIndex P1 P2 * * * -** -** Allocate a new index in the main database file if P1==0 or in the -** auxiliary database file if P1==1 or in an attached database if -** P1>1. Write the root page number of the new table into -** register P2. -** -** See documentation on OP_CreateTable for additional information. -*/ -case OP_CreateIndex: /* out2-prerelease */ -case OP_CreateTable: { /* out2-prerelease */ -#if 0 /* local variables moved into u.by */ - int pgno; - int flags; - Db *pDb; -#endif /* local variables moved into u.by */ - - u.by.pgno = 0; - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); - u.by.pDb = &db->aDb[pOp->p1]; - assert( u.by.pDb->pBt!=0 ); - if( pOp->opcode==OP_CreateTable ){ - /* u.by.flags = BTREE_INTKEY; */ - u.by.flags = BTREE_INTKEY; - }else{ - u.by.flags = BTREE_BLOBKEY; - } - rc = sqlite3BtreeCreateTable(u.by.pDb->pBt, &u.by.pgno, u.by.flags); - pOut->u.i = u.by.pgno; - break; -} - -/* Opcode: ParseSchema P1 * * P4 * -** -** Read and parse all entries from the SQLITE_MASTER table of database P1 -** that match the WHERE clause P4. -** -** This opcode invokes the parser to create a new virtual machine, -** then runs the new virtual machine. It is thus a re-entrant opcode. -*/ -case OP_ParseSchema: { -#if 0 /* local variables moved into u.bz */ - int iDb; - const char *zMaster; - char *zSql; - InitData initData; -#endif /* local variables moved into u.bz */ - - /* Any prepared statement that invokes this opcode will hold mutexes - ** on every btree. This is a prerequisite for invoking - ** sqlite3InitCallback(). - */ -#ifdef SQLITE_DEBUG - for(u.bz.iDb=0; u.bz.iDbnDb; u.bz.iDb++){ - assert( u.bz.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bz.iDb].pBt) ); - } -#endif - - u.bz.iDb = pOp->p1; - assert( u.bz.iDb>=0 && u.bz.iDbnDb ); - assert( DbHasProperty(db, u.bz.iDb, DB_SchemaLoaded) ); - /* Used to be a conditional */ { - u.bz.zMaster = SCHEMA_TABLE(u.bz.iDb); - u.bz.initData.db = db; - u.bz.initData.iDb = pOp->p1; - u.bz.initData.pzErrMsg = &p->zErrMsg; - u.bz.zSql = sqlite3MPrintf(db, - "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", - db->aDb[u.bz.iDb].zName, u.bz.zMaster, pOp->p4.z); - if( u.bz.zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - assert( db->init.busy==0 ); - db->init.busy = 1; - u.bz.initData.rc = SQLITE_OK; - assert( !db->mallocFailed ); - rc = sqlite3_exec(db, u.bz.zSql, sqlite3InitCallback, &u.bz.initData, 0); - if( rc==SQLITE_OK ) rc = u.bz.initData.rc; - sqlite3DbFree(db, u.bz.zSql); - db->init.busy = 0; - } - } - if( rc ) sqlite3ResetAllSchemasOfConnection(db); - if( rc==SQLITE_NOMEM ){ - goto no_mem; - } - break; -} - -#if !defined(SQLITE_OMIT_ANALYZE) -/* Opcode: LoadAnalysis P1 * * * * -** -** Read the sqlite_stat1 table for database P1 and load the content -** of that table into the internal index hash table. This will cause -** the analysis to be used when preparing all subsequent queries. -*/ -case OP_LoadAnalysis: { - assert( pOp->p1>=0 && pOp->p1nDb ); - rc = sqlite3AnalysisLoad(db, pOp->p1); - break; -} -#endif /* !defined(SQLITE_OMIT_ANALYZE) */ - -/* Opcode: DropTable P1 * * P4 * -** -** Remove the internal (in-memory) data structures that describe -** the table named P4 in database P1. This is called after a table -** is dropped in order to keep the internal representation of the -** schema consistent with what is on disk. -*/ -case OP_DropTable: { - sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); - break; -} - -/* Opcode: DropIndex P1 * * P4 * -** -** Remove the internal (in-memory) data structures that describe -** the index named P4 in database P1. This is called after an index -** is dropped in order to keep the internal representation of the -** schema consistent with what is on disk. -*/ -case OP_DropIndex: { - sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); - break; -} - -/* Opcode: DropTrigger P1 * * P4 * -** -** Remove the internal (in-memory) data structures that describe -** the trigger named P4 in database P1. This is called after a trigger -** is dropped in order to keep the internal representation of the -** schema consistent with what is on disk. -*/ -case OP_DropTrigger: { - sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); - break; -} - - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK -/* Opcode: IntegrityCk P1 P2 P3 * P5 -** -** Do an analysis of the currently open database. Store in -** register P1 the text of an error message describing any problems. -** If no problems are found, store a NULL in register P1. -** -** The register P3 contains the maximum number of allowed errors. -** At most reg(P3) errors will be reported. -** In other words, the analysis stops as soon as reg(P1) errors are -** seen. Reg(P1) is updated with the number of errors remaining. -** -** The root page numbers of all tables in the database are integer -** stored in reg(P1), reg(P1+1), reg(P1+2), .... There are P2 tables -** total. -** -** If P5 is not zero, the check is done on the auxiliary database -** file, not the main database file. -** -** This opcode is used to implement the integrity_check pragma. -*/ -case OP_IntegrityCk: { -#if 0 /* local variables moved into u.ca */ - int nRoot; /* Number of tables to check. (Number of root pages.) */ - int *aRoot; /* Array of rootpage numbers for tables to be checked */ - int j; /* Loop counter */ - int nErr; /* Number of errors reported */ - char *z; /* Text of the error report */ - Mem *pnErr; /* Register keeping track of errors remaining */ -#endif /* local variables moved into u.ca */ - - u.ca.nRoot = pOp->p2; - assert( u.ca.nRoot>0 ); - u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) ); - if( u.ca.aRoot==0 ) goto no_mem; - assert( pOp->p3>0 && pOp->p3<=p->nMem ); - u.ca.pnErr = &aMem[pOp->p3]; - assert( (u.ca.pnErr->flags & MEM_Int)!=0 ); - assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 ); - pIn1 = &aMem[pOp->p1]; - for(u.ca.j=0; u.ca.jp5nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p5))!=0 ); - u.ca.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.ca.aRoot, u.ca.nRoot, - (int)u.ca.pnErr->u.i, &u.ca.nErr); - sqlite3DbFree(db, u.ca.aRoot); - u.ca.pnErr->u.i -= u.ca.nErr; - sqlite3VdbeMemSetNull(pIn1); - if( u.ca.nErr==0 ){ - assert( u.ca.z==0 ); - }else if( u.ca.z==0 ){ - goto no_mem; - }else{ - sqlite3VdbeMemSetStr(pIn1, u.ca.z, -1, SQLITE_UTF8, sqlite3_free); - } - UPDATE_MAX_BLOBSIZE(pIn1); - sqlite3VdbeChangeEncoding(pIn1, encoding); - break; -} -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -/* Opcode: RowSetAdd P1 P2 * * * -** -** Insert the integer value held by register P2 into a boolean index -** held in register P1. -** -** An assertion fails if P2 is not an integer. -*/ -case OP_RowSetAdd: { /* in1, in2 */ - pIn1 = &aMem[pOp->p1]; - pIn2 = &aMem[pOp->p2]; - assert( (pIn2->flags & MEM_Int)!=0 ); - if( (pIn1->flags & MEM_RowSet)==0 ){ - sqlite3VdbeMemSetRowSet(pIn1); - if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; - } - sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i); - break; -} - -/* Opcode: RowSetRead P1 P2 P3 * * -** -** Extract the smallest value from boolean index P1 and put that value into -** register P3. Or, if boolean index P1 is initially empty, leave P3 -** unchanged and jump to instruction P2. -*/ -case OP_RowSetRead: { /* jump, in1, out3 */ -#if 0 /* local variables moved into u.cb */ - i64 val; -#endif /* local variables moved into u.cb */ - CHECK_FOR_INTERRUPT; - pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_RowSet)==0 - || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0 - ){ - /* The boolean index is empty */ - sqlite3VdbeMemSetNull(pIn1); - pc = pOp->p2 - 1; - }else{ - /* A value was pulled from the index */ - sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val); - } - break; -} - -/* Opcode: RowSetTest P1 P2 P3 P4 -** -** Register P3 is assumed to hold a 64-bit integer value. If register P1 -** contains a RowSet object and that RowSet object contains -** the value held in P3, jump to register P2. Otherwise, insert the -** integer in P3 into the RowSet and continue on to the -** next opcode. -** -** The RowSet object is optimized for the case where successive sets -** of integers, where each set contains no duplicates. Each set -** of values is identified by a unique P4 value. The first set -** must have P4==0, the final set P4=-1. P4 must be either -1 or -** non-negative. For non-negative values of P4 only the lower 4 -** bits are significant. -** -** This allows optimizations: (a) when P4==0 there is no need to test -** the rowset object for P3, as it is guaranteed not to contain it, -** (b) when P4==-1 there is no need to insert the value, as it will -** never be tested for, and (c) when a value that is part of set X is -** inserted, there is no need to search to see if the same value was -** previously inserted as part of set X (only if it was previously -** inserted as part of some other set). -*/ -case OP_RowSetTest: { /* jump, in1, in3 */ -#if 0 /* local variables moved into u.cc */ - int iSet; - int exists; -#endif /* local variables moved into u.cc */ - - pIn1 = &aMem[pOp->p1]; - pIn3 = &aMem[pOp->p3]; - u.cc.iSet = pOp->p4.i; - assert( pIn3->flags&MEM_Int ); - - /* If there is anything other than a rowset object in memory cell P1, - ** delete it now and initialize P1 with an empty rowset - */ - if( (pIn1->flags & MEM_RowSet)==0 ){ - sqlite3VdbeMemSetRowSet(pIn1); - if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; - } - - assert( pOp->p4type==P4_INT32 ); - assert( u.cc.iSet==-1 || u.cc.iSet>=0 ); - if( u.cc.iSet ){ - u.cc.exists = sqlite3RowSetTest(pIn1->u.pRowSet, - (u8)(u.cc.iSet>=0 ? u.cc.iSet & 0xf : 0xff), - pIn3->u.i); - if( u.cc.exists ){ - pc = pOp->p2 - 1; - break; - } - } - if( u.cc.iSet>=0 ){ - sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); - } - break; -} - - -#ifndef SQLITE_OMIT_TRIGGER - -/* Opcode: Program P1 P2 P3 P4 * -** -** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). -** -** P1 contains the address of the memory cell that contains the first memory -** cell in an array of values used as arguments to the sub-program. P2 -** contains the address to jump to if the sub-program throws an IGNORE -** exception using the RAISE() function. Register P3 contains the address -** of a memory cell in this (the parent) VM that is used to allocate the -** memory required by the sub-vdbe at runtime. -** -** P4 is a pointer to the VM containing the trigger program. -*/ -case OP_Program: { /* jump */ -#if 0 /* local variables moved into u.cd */ - int nMem; /* Number of memory registers for sub-program */ - int nByte; /* Bytes of runtime space required for sub-program */ - Mem *pRt; /* Register to allocate runtime space */ - Mem *pMem; /* Used to iterate through memory cells */ - Mem *pEnd; /* Last memory cell in new array */ - VdbeFrame *pFrame; /* New vdbe frame to execute in */ - SubProgram *pProgram; /* Sub-program to execute */ - void *t; /* Token identifying trigger */ -#endif /* local variables moved into u.cd */ - - u.cd.pProgram = pOp->p4.pProgram; - u.cd.pRt = &aMem[pOp->p3]; - assert( u.cd.pProgram->nOp>0 ); - - /* If the p5 flag is clear, then recursive invocation of triggers is - ** disabled for backwards compatibility (p5 is set if this sub-program - ** is really a trigger, not a foreign key action, and the flag set - ** and cleared by the "PRAGMA recursive_triggers" command is clear). - ** - ** It is recursive invocation of triggers, at the SQL level, that is - ** disabled. In some cases a single trigger may generate more than one - ** SubProgram (if the trigger may be executed with more than one different - ** ON CONFLICT algorithm). SubProgram structures associated with a - ** single trigger all have the same value for the SubProgram.token - ** variable. */ - if( pOp->p5 ){ - u.cd.t = u.cd.pProgram->token; - for(u.cd.pFrame=p->pFrame; u.cd.pFrame && u.cd.pFrame->token!=u.cd.t; u.cd.pFrame=u.cd.pFrame->pParent); - if( u.cd.pFrame ) break; - } - - if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){ - rc = SQLITE_ERROR; - sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion"); - break; - } - - /* Register u.cd.pRt is used to store the memory required to save the state - ** of the current program, and the memory required at runtime to execute - ** the trigger program. If this trigger has been fired before, then u.cd.pRt - ** is already allocated. Otherwise, it must be initialized. */ - if( (u.cd.pRt->flags&MEM_Frame)==0 ){ - /* SubProgram.nMem is set to the number of memory cells used by the - ** program stored in SubProgram.aOp. As well as these, one memory - ** cell is required for each cursor used by the program. Set local - ** variable u.cd.nMem (and later, VdbeFrame.nChildMem) to this value. - */ - u.cd.nMem = u.cd.pProgram->nMem + u.cd.pProgram->nCsr; - u.cd.nByte = ROUND8(sizeof(VdbeFrame)) - + u.cd.nMem * sizeof(Mem) - + u.cd.pProgram->nCsr * sizeof(VdbeCursor *) - + u.cd.pProgram->nOnce * sizeof(u8); - u.cd.pFrame = sqlite3DbMallocZero(db, u.cd.nByte); - if( !u.cd.pFrame ){ - goto no_mem; - } - sqlite3VdbeMemRelease(u.cd.pRt); - u.cd.pRt->flags = MEM_Frame; - u.cd.pRt->u.pFrame = u.cd.pFrame; - - u.cd.pFrame->v = p; - u.cd.pFrame->nChildMem = u.cd.nMem; - u.cd.pFrame->nChildCsr = u.cd.pProgram->nCsr; - u.cd.pFrame->pc = pc; - u.cd.pFrame->aMem = p->aMem; - u.cd.pFrame->nMem = p->nMem; - u.cd.pFrame->apCsr = p->apCsr; - u.cd.pFrame->nCursor = p->nCursor; - u.cd.pFrame->aOp = p->aOp; - u.cd.pFrame->nOp = p->nOp; - u.cd.pFrame->token = u.cd.pProgram->token; - u.cd.pFrame->aOnceFlag = p->aOnceFlag; - u.cd.pFrame->nOnceFlag = p->nOnceFlag; - - u.cd.pEnd = &VdbeFrameMem(u.cd.pFrame)[u.cd.pFrame->nChildMem]; - for(u.cd.pMem=VdbeFrameMem(u.cd.pFrame); u.cd.pMem!=u.cd.pEnd; u.cd.pMem++){ - u.cd.pMem->flags = MEM_Invalid; - u.cd.pMem->db = db; - } - }else{ - u.cd.pFrame = u.cd.pRt->u.pFrame; - assert( u.cd.pProgram->nMem+u.cd.pProgram->nCsr==u.cd.pFrame->nChildMem ); - assert( u.cd.pProgram->nCsr==u.cd.pFrame->nChildCsr ); - assert( pc==u.cd.pFrame->pc ); - } - - p->nFrame++; - u.cd.pFrame->pParent = p->pFrame; - u.cd.pFrame->lastRowid = lastRowid; - u.cd.pFrame->nChange = p->nChange; - p->nChange = 0; - p->pFrame = u.cd.pFrame; - p->aMem = aMem = &VdbeFrameMem(u.cd.pFrame)[-1]; - p->nMem = u.cd.pFrame->nChildMem; - p->nCursor = (u16)u.cd.pFrame->nChildCsr; - p->apCsr = (VdbeCursor **)&aMem[p->nMem+1]; - p->aOp = aOp = u.cd.pProgram->aOp; - p->nOp = u.cd.pProgram->nOp; - p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; - p->nOnceFlag = u.cd.pProgram->nOnce; - pc = -1; - memset(p->aOnceFlag, 0, p->nOnceFlag); - - break; -} - -/* Opcode: Param P1 P2 * * * -** -** This opcode is only ever present in sub-programs called via the -** OP_Program instruction. Copy a value currently stored in a memory -** cell of the calling (parent) frame to cell P2 in the current frames -** address space. This is used by trigger programs to access the new.* -** and old.* values. -** -** The address of the cell in the parent frame is determined by adding -** the value of the P1 argument to the value of the P1 argument to the -** calling OP_Program instruction. -*/ -case OP_Param: { /* out2-prerelease */ -#if 0 /* local variables moved into u.ce */ - VdbeFrame *pFrame; - Mem *pIn; -#endif /* local variables moved into u.ce */ - u.ce.pFrame = p->pFrame; - u.ce.pIn = &u.ce.pFrame->aMem[pOp->p1 + u.ce.pFrame->aOp[u.ce.pFrame->pc].p1]; - sqlite3VdbeMemShallowCopy(pOut, u.ce.pIn, MEM_Ephem); - break; -} - -#endif /* #ifndef SQLITE_OMIT_TRIGGER */ - -#ifndef SQLITE_OMIT_FOREIGN_KEY -/* Opcode: FkCounter P1 P2 * * * -** -** Increment a "constraint counter" by P2 (P2 may be negative or positive). -** If P1 is non-zero, the database constraint counter is incremented -** (deferred foreign key constraints). Otherwise, if P1 is zero, the -** statement counter is incremented (immediate foreign key constraints). -*/ -case OP_FkCounter: { - if( pOp->p1 ){ - db->nDeferredCons += pOp->p2; - }else{ - p->nFkConstraint += pOp->p2; - } - break; -} - -/* Opcode: FkIfZero P1 P2 * * * -** -** This opcode tests if a foreign key constraint-counter is currently zero. -** If so, jump to instruction P2. Otherwise, fall through to the next -** instruction. -** -** If P1 is non-zero, then the jump is taken if the database constraint-counter -** is zero (the one that counts deferred constraint violations). If P1 is -** zero, the jump is taken if the statement constraint-counter is zero -** (immediate foreign key constraint violations). -*/ -case OP_FkIfZero: { /* jump */ - if( pOp->p1 ){ - if( db->nDeferredCons==0 ) pc = pOp->p2-1; - }else{ - if( p->nFkConstraint==0 ) pc = pOp->p2-1; - } - break; -} -#endif /* #ifndef SQLITE_OMIT_FOREIGN_KEY */ - -#ifndef SQLITE_OMIT_AUTOINCREMENT -/* Opcode: MemMax P1 P2 * * * -** -** P1 is a register in the root frame of this VM (the root frame is -** different from the current frame if this instruction is being executed -** within a sub-program). Set the value of register P1 to the maximum of -** its current value and the value in register P2. -** -** This instruction throws an error if the memory cell is not initially -** an integer. -*/ -case OP_MemMax: { /* in2 */ -#if 0 /* local variables moved into u.cf */ - Mem *pIn1; - VdbeFrame *pFrame; -#endif /* local variables moved into u.cf */ - if( p->pFrame ){ - for(u.cf.pFrame=p->pFrame; u.cf.pFrame->pParent; u.cf.pFrame=u.cf.pFrame->pParent); - u.cf.pIn1 = &u.cf.pFrame->aMem[pOp->p1]; - }else{ - u.cf.pIn1 = &aMem[pOp->p1]; - } - assert( memIsValid(u.cf.pIn1) ); - sqlite3VdbeMemIntegerify(u.cf.pIn1); - pIn2 = &aMem[pOp->p2]; - sqlite3VdbeMemIntegerify(pIn2); - if( u.cf.pIn1->u.iu.i){ - u.cf.pIn1->u.i = pIn2->u.i; - } - break; -} -#endif /* SQLITE_OMIT_AUTOINCREMENT */ - -/* Opcode: IfPos P1 P2 * * * -** -** If the value of register P1 is 1 or greater, jump to P2. -** -** It is illegal to use this instruction on a register that does -** not contain an integer. An assertion fault will result if you try. -*/ -case OP_IfPos: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - if( pIn1->u.i>0 ){ - pc = pOp->p2 - 1; - } - break; -} - -/* Opcode: IfNeg P1 P2 * * * -** -** If the value of register P1 is less than zero, jump to P2. -** -** It is illegal to use this instruction on a register that does -** not contain an integer. An assertion fault will result if you try. -*/ -case OP_IfNeg: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - if( pIn1->u.i<0 ){ - pc = pOp->p2 - 1; - } - break; -} - -/* Opcode: IfZero P1 P2 P3 * * -** -** The register P1 must contain an integer. Add literal P3 to the -** value in register P1. If the result is exactly 0, jump to P2. -** -** It is illegal to use this instruction on a register that does -** not contain an integer. An assertion fault will result if you try. -*/ -case OP_IfZero: { /* jump, in1 */ - pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags&MEM_Int ); - pIn1->u.i += pOp->p3; - if( pIn1->u.i==0 ){ - pc = pOp->p2 - 1; - } - break; -} - -/* Opcode: AggStep * P2 P3 P4 P5 -** -** Execute the step function for an aggregate. The -** function has P5 arguments. P4 is a pointer to the FuncDef -** structure that specifies the function. Use register -** P3 as the accumulator. -** -** The P5 arguments are taken from register P2 and its -** successors. -*/ -case OP_AggStep: { -#if 0 /* local variables moved into u.cg */ - int n; - int i; - Mem *pMem; - Mem *pRec; - sqlite3_context ctx; - sqlite3_value **apVal; -#endif /* local variables moved into u.cg */ - - u.cg.n = pOp->p5; - assert( u.cg.n>=0 ); - u.cg.pRec = &aMem[pOp->p2]; - u.cg.apVal = p->apArg; - assert( u.cg.apVal || u.cg.n==0 ); - for(u.cg.i=0; u.cg.ip4.pFunc; - assert( pOp->p3>0 && pOp->p3<=p->nMem ); - u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3]; - u.cg.pMem->n++; - u.cg.ctx.s.flags = MEM_Null; - u.cg.ctx.s.z = 0; - u.cg.ctx.s.zMalloc = 0; - u.cg.ctx.s.xDel = 0; - u.cg.ctx.s.db = db; - u.cg.ctx.isError = 0; - u.cg.ctx.pColl = 0; - u.cg.ctx.skipFlag = 0; - if( u.cg.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ - assert( pOp>p->aOp ); - assert( pOp[-1].p4type==P4_COLLSEQ ); - assert( pOp[-1].opcode==OP_CollSeq ); - u.cg.ctx.pColl = pOp[-1].p4.pColl; - } - (u.cg.ctx.pFunc->xStep)(&u.cg.ctx, u.cg.n, u.cg.apVal); /* IMP: R-24505-23230 */ - if( u.cg.ctx.isError ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cg.ctx.s)); - rc = u.cg.ctx.isError; - } - if( u.cg.ctx.skipFlag ){ - assert( pOp[-1].opcode==OP_CollSeq ); - u.cg.i = pOp[-1].p1; - if( u.cg.i ) sqlite3VdbeMemSetInt64(&aMem[u.cg.i], 1); - } - - sqlite3VdbeMemRelease(&u.cg.ctx.s); - - break; -} - -/* Opcode: AggFinal P1 P2 * P4 * -** -** Execute the finalizer function for an aggregate. P1 is -** the memory location that is the accumulator for the aggregate. -** -** P2 is the number of arguments that the step function takes and -** P4 is a pointer to the FuncDef for this function. The P2 -** argument is not used by this opcode. It is only there to disambiguate -** functions that can take varying numbers of arguments. The -** P4 argument is only needed for the degenerate case where -** the step function was not previously called. -*/ -case OP_AggFinal: { -#if 0 /* local variables moved into u.ch */ - Mem *pMem; -#endif /* local variables moved into u.ch */ - assert( pOp->p1>0 && pOp->p1<=p->nMem ); - u.ch.pMem = &aMem[pOp->p1]; - assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); - rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc); - if( rc ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.ch.pMem)); - } - sqlite3VdbeChangeEncoding(u.ch.pMem, encoding); - UPDATE_MAX_BLOBSIZE(u.ch.pMem); - if( sqlite3VdbeMemTooBig(u.ch.pMem) ){ - goto too_big; - } - break; -} - -#ifndef SQLITE_OMIT_WAL -/* Opcode: Checkpoint P1 P2 P3 * * -** -** Checkpoint database P1. This is a no-op if P1 is not currently in -** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL -** or RESTART. Write 1 or 0 into mem[P3] if the checkpoint returns -** SQLITE_BUSY or not, respectively. Write the number of pages in the -** WAL after the checkpoint into mem[P3+1] and the number of pages -** in the WAL that have been checkpointed after the checkpoint -** completes into mem[P3+2]. However on an error, mem[P3+1] and -** mem[P3+2] are initialized to -1. -*/ -case OP_Checkpoint: { -#if 0 /* local variables moved into u.ci */ - int i; /* Loop counter */ - int aRes[3]; /* Results */ - Mem *pMem; /* Write results here */ -#endif /* local variables moved into u.ci */ - - u.ci.aRes[0] = 0; - u.ci.aRes[1] = u.ci.aRes[2] = -1; - assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE - || pOp->p2==SQLITE_CHECKPOINT_FULL - || pOp->p2==SQLITE_CHECKPOINT_RESTART - ); - rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ci.aRes[1], &u.ci.aRes[2]); - if( rc==SQLITE_BUSY ){ - rc = SQLITE_OK; - u.ci.aRes[0] = 1; - } - for(u.ci.i=0, u.ci.pMem = &aMem[pOp->p3]; u.ci.i<3; u.ci.i++, u.ci.pMem++){ - sqlite3VdbeMemSetInt64(u.ci.pMem, (i64)u.ci.aRes[u.ci.i]); - } - break; -}; -#endif - -#ifndef SQLITE_OMIT_PRAGMA -/* Opcode: JournalMode P1 P2 P3 * P5 -** -** Change the journal mode of database P1 to P3. P3 must be one of the -** PAGER_JOURNALMODE_XXX values. If changing between the various rollback -** modes (delete, truncate, persist, off and memory), this is a simple -** operation. No IO is required. -** -** If changing into or out of WAL mode the procedure is more complicated. -** -** Write a string containing the final journal-mode to register P2. -*/ -case OP_JournalMode: { /* out2-prerelease */ -#if 0 /* local variables moved into u.cj */ - Btree *pBt; /* Btree to change journal mode of */ - Pager *pPager; /* Pager associated with pBt */ - int eNew; /* New journal mode */ - int eOld; /* The old journal mode */ -#ifndef SQLITE_OMIT_WAL - const char *zFilename; /* Name of database file for pPager */ -#endif -#endif /* local variables moved into u.cj */ - - u.cj.eNew = pOp->p3; - assert( u.cj.eNew==PAGER_JOURNALMODE_DELETE - || u.cj.eNew==PAGER_JOURNALMODE_TRUNCATE - || u.cj.eNew==PAGER_JOURNALMODE_PERSIST - || u.cj.eNew==PAGER_JOURNALMODE_OFF - || u.cj.eNew==PAGER_JOURNALMODE_MEMORY - || u.cj.eNew==PAGER_JOURNALMODE_WAL - || u.cj.eNew==PAGER_JOURNALMODE_QUERY - ); - assert( pOp->p1>=0 && pOp->p1nDb ); - - u.cj.pBt = db->aDb[pOp->p1].pBt; - u.cj.pPager = sqlite3BtreePager(u.cj.pBt); - u.cj.eOld = sqlite3PagerGetJournalMode(u.cj.pPager); - if( u.cj.eNew==PAGER_JOURNALMODE_QUERY ) u.cj.eNew = u.cj.eOld; - if( !sqlite3PagerOkToChangeJournalMode(u.cj.pPager) ) u.cj.eNew = u.cj.eOld; - -#ifndef SQLITE_OMIT_WAL - u.cj.zFilename = sqlite3PagerFilename(u.cj.pPager, 1); - - /* Do not allow a transition to journal_mode=WAL for a database - ** in temporary storage or if the VFS does not support shared memory - */ - if( u.cj.eNew==PAGER_JOURNALMODE_WAL - && (sqlite3Strlen30(u.cj.zFilename)==0 /* Temp file */ - || !sqlite3PagerWalSupported(u.cj.pPager)) /* No shared-memory support */ - ){ - u.cj.eNew = u.cj.eOld; - } - - if( (u.cj.eNew!=u.cj.eOld) - && (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL) - ){ - if( !db->autoCommit || db->activeVdbeCnt>1 ){ - rc = SQLITE_ERROR; - sqlite3SetString(&p->zErrMsg, db, - "cannot change %s wal mode from within a transaction", - (u.cj.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") - ); - break; - }else{ - - if( u.cj.eOld==PAGER_JOURNALMODE_WAL ){ - /* If leaving WAL mode, close the log file. If successful, the call - ** to PagerCloseWal() checkpoints and deletes the write-ahead-log - ** file. An EXCLUSIVE lock may still be held on the database file - ** after a successful return. - */ - rc = sqlite3PagerCloseWal(u.cj.pPager); - if( rc==SQLITE_OK ){ - sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew); - } - }else if( u.cj.eOld==PAGER_JOURNALMODE_MEMORY ){ - /* Cannot transition directly from MEMORY to WAL. Use mode OFF - ** as an intermediate */ - sqlite3PagerSetJournalMode(u.cj.pPager, PAGER_JOURNALMODE_OFF); - } - - /* Open a transaction on the database file. Regardless of the journal - ** mode, this transaction always uses a rollback journal. - */ - assert( sqlite3BtreeIsInTrans(u.cj.pBt)==0 ); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeSetVersion(u.cj.pBt, (u.cj.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1)); - } - } - } -#endif /* ifndef SQLITE_OMIT_WAL */ - - if( rc ){ - u.cj.eNew = u.cj.eOld; - } - u.cj.eNew = sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew); - - pOut = &aMem[pOp->p2]; - pOut->flags = MEM_Str|MEM_Static|MEM_Term; - pOut->z = (char *)sqlite3JournalModename(u.cj.eNew); - pOut->n = sqlite3Strlen30(pOut->z); - pOut->enc = SQLITE_UTF8; - sqlite3VdbeChangeEncoding(pOut, encoding); - break; -}; -#endif /* SQLITE_OMIT_PRAGMA */ - -#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) -/* Opcode: Vacuum * * * * * -** -** Vacuum the entire database. This opcode will cause other virtual -** machines to be created and run. It may not be called from within -** a transaction. -*/ -case OP_Vacuum: { - rc = sqlite3RunVacuum(&p->zErrMsg, db); - break; -} -#endif - -#if !defined(SQLITE_OMIT_AUTOVACUUM) -/* Opcode: IncrVacuum P1 P2 * * * -** -** Perform a single step of the incremental vacuum procedure on -** the P1 database. If the vacuum has finished, jump to instruction -** P2. Otherwise, fall through to the next instruction. -*/ -case OP_IncrVacuum: { /* jump */ -#if 0 /* local variables moved into u.ck */ - Btree *pBt; -#endif /* local variables moved into u.ck */ - - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); - u.ck.pBt = db->aDb[pOp->p1].pBt; - rc = sqlite3BtreeIncrVacuum(u.ck.pBt); - if( rc==SQLITE_DONE ){ - pc = pOp->p2 - 1; - rc = SQLITE_OK; - } - break; -} -#endif - -/* Opcode: Expire P1 * * * * -** -** Cause precompiled statements to become expired. An expired statement -** fails with an error code of SQLITE_SCHEMA if it is ever executed -** (via sqlite3_step()). -** -** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, -** then only the currently executing statement is affected. -*/ -case OP_Expire: { - if( !pOp->p1 ){ - sqlite3ExpirePreparedStatements(db); - }else{ - p->expired = 1; - } - break; -} - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* Opcode: TableLock P1 P2 P3 P4 * -** -** Obtain a lock on a particular table. This instruction is only used when -** the shared-cache feature is enabled. -** -** P1 is the index of the database in sqlite3.aDb[] of the database -** on which the lock is acquired. A readlock is obtained if P3==0 or -** a write lock if P3==1. -** -** P2 contains the root-page of the table to lock. -** -** P4 contains a pointer to the name of the table being locked. This is only -** used to generate an error message if the lock cannot be obtained. -*/ -case OP_TableLock: { - u8 isWriteLock = (u8)pOp->p3; - if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ - int p1 = pOp->p1; - assert( p1>=0 && p1nDb ); - assert( (p->btreeMask & (((yDbMask)1)<aDb[p1].pBt, pOp->p2, isWriteLock); - if( (rc&0xFF)==SQLITE_LOCKED ){ - const char *z = pOp->p4.z; - sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z); - } - } - break; -} -#endif /* SQLITE_OMIT_SHARED_CACHE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VBegin * * * P4 * -** -** P4 may be a pointer to an sqlite3_vtab structure. If so, call the -** xBegin method for that table. -** -** Also, whether or not P4 is set, check that this is not being called from -** within a callback to a virtual table xSync() method. If it is, the error -** code will be set to SQLITE_LOCKED. -*/ -case OP_VBegin: { -#if 0 /* local variables moved into u.cl */ - VTable *pVTab; -#endif /* local variables moved into u.cl */ - u.cl.pVTab = pOp->p4.pVtab; - rc = sqlite3VtabBegin(db, u.cl.pVTab); - if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab); - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VCreate P1 * * P4 * -** -** P4 is the name of a virtual table in database P1. Call the xCreate method -** for that table. -*/ -case OP_VCreate: { - rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg); - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VDestroy P1 * * P4 * -** -** P4 is the name of a virtual table in database P1. Call the xDestroy method -** of that table. -*/ -case OP_VDestroy: { - p->inVtabMethod = 2; - rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); - p->inVtabMethod = 0; - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VOpen P1 * * P4 * -** -** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. -** P1 is a cursor number. This opcode opens a cursor to the virtual -** table and stores that cursor in P1. -*/ -case OP_VOpen: { -#if 0 /* local variables moved into u.cm */ - VdbeCursor *pCur; - sqlite3_vtab_cursor *pVtabCursor; - sqlite3_vtab *pVtab; - sqlite3_module *pModule; -#endif /* local variables moved into u.cm */ - - u.cm.pCur = 0; - u.cm.pVtabCursor = 0; - u.cm.pVtab = pOp->p4.pVtab->pVtab; - u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule; - assert(u.cm.pVtab && u.cm.pModule); - rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor); - importVtabErrMsg(p, u.cm.pVtab); - if( SQLITE_OK==rc ){ - /* Initialize sqlite3_vtab_cursor base class */ - u.cm.pVtabCursor->pVtab = u.cm.pVtab; - - /* Initialize vdbe cursor object */ - u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0); - if( u.cm.pCur ){ - u.cm.pCur->pVtabCursor = u.cm.pVtabCursor; - u.cm.pCur->pModule = u.cm.pVtabCursor->pVtab->pModule; - }else{ - db->mallocFailed = 1; - u.cm.pModule->xClose(u.cm.pVtabCursor); - } - } - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VFilter P1 P2 P3 P4 * -** -** P1 is a cursor opened using VOpen. P2 is an address to jump to if -** the filtered result set is empty. -** -** P4 is either NULL or a string that was generated by the xBestIndex -** method of the module. The interpretation of the P4 string is left -** to the module implementation. -** -** This opcode invokes the xFilter method on the virtual table specified -** by P1. The integer query plan parameter to xFilter is stored in register -** P3. Register P3+1 stores the argc parameter to be passed to the -** xFilter method. Registers P3+2..P3+1+argc are the argc -** additional parameters which are passed to -** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. -** -** A jump is made to P2 if the result set after filtering would be empty. -*/ -case OP_VFilter: { /* jump */ -#if 0 /* local variables moved into u.cn */ - int nArg; - int iQuery; - const sqlite3_module *pModule; - Mem *pQuery; - Mem *pArgc; - sqlite3_vtab_cursor *pVtabCursor; - sqlite3_vtab *pVtab; - VdbeCursor *pCur; - int res; - int i; - Mem **apArg; -#endif /* local variables moved into u.cn */ - - u.cn.pQuery = &aMem[pOp->p3]; - u.cn.pArgc = &u.cn.pQuery[1]; - u.cn.pCur = p->apCsr[pOp->p1]; - assert( memIsValid(u.cn.pQuery) ); - REGISTER_TRACE(pOp->p3, u.cn.pQuery); - assert( u.cn.pCur->pVtabCursor ); - u.cn.pVtabCursor = u.cn.pCur->pVtabCursor; - u.cn.pVtab = u.cn.pVtabCursor->pVtab; - u.cn.pModule = u.cn.pVtab->pModule; - - /* Grab the index number and argc parameters */ - assert( (u.cn.pQuery->flags&MEM_Int)!=0 && u.cn.pArgc->flags==MEM_Int ); - u.cn.nArg = (int)u.cn.pArgc->u.i; - u.cn.iQuery = (int)u.cn.pQuery->u.i; - - /* Invoke the xFilter method */ - { - u.cn.res = 0; - u.cn.apArg = p->apArg; - for(u.cn.i = 0; u.cn.iinVtabMethod = 1; - rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg); - p->inVtabMethod = 0; - importVtabErrMsg(p, u.cn.pVtab); - if( rc==SQLITE_OK ){ - u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor); - } - - if( u.cn.res ){ - pc = pOp->p2 - 1; - } - } - u.cn.pCur->nullRow = 0; - - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VColumn P1 P2 P3 * * -** -** Store the value of the P2-th column of -** the row of the virtual-table that the -** P1 cursor is pointing to into register P3. -*/ -case OP_VColumn: { -#if 0 /* local variables moved into u.co */ - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - Mem *pDest; - sqlite3_context sContext; -#endif /* local variables moved into u.co */ - - VdbeCursor *pCur = p->apCsr[pOp->p1]; - assert( pCur->pVtabCursor ); - assert( pOp->p3>0 && pOp->p3<=p->nMem ); - u.co.pDest = &aMem[pOp->p3]; - memAboutToChange(p, u.co.pDest); - if( pCur->nullRow ){ - sqlite3VdbeMemSetNull(u.co.pDest); - break; - } - u.co.pVtab = pCur->pVtabCursor->pVtab; - u.co.pModule = u.co.pVtab->pModule; - assert( u.co.pModule->xColumn ); - memset(&u.co.sContext, 0, sizeof(u.co.sContext)); - - /* The output cell may already have a buffer allocated. Move - ** the current contents to u.co.sContext.s so in case the user-function - ** can use the already allocated buffer instead of allocating a - ** new one. - */ - sqlite3VdbeMemMove(&u.co.sContext.s, u.co.pDest); - MemSetTypeFlag(&u.co.sContext.s, MEM_Null); - - rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2); - importVtabErrMsg(p, u.co.pVtab); - if( u.co.sContext.isError ){ - rc = u.co.sContext.isError; - } - - /* Copy the result of the function to the P3 register. We - ** do this regardless of whether or not an error occurred to ensure any - ** dynamic allocation in u.co.sContext.s (a Mem struct) is released. - */ - sqlite3VdbeChangeEncoding(&u.co.sContext.s, encoding); - sqlite3VdbeMemMove(u.co.pDest, &u.co.sContext.s); - REGISTER_TRACE(pOp->p3, u.co.pDest); - UPDATE_MAX_BLOBSIZE(u.co.pDest); - - if( sqlite3VdbeMemTooBig(u.co.pDest) ){ - goto too_big; - } - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VNext P1 P2 * * * -** -** Advance virtual table P1 to the next row in its result set and -** jump to instruction P2. Or, if the virtual table has reached -** the end of its result set, then fall through to the next instruction. -*/ -case OP_VNext: { /* jump */ -#if 0 /* local variables moved into u.cp */ - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; - int res; - VdbeCursor *pCur; -#endif /* local variables moved into u.cp */ - - u.cp.res = 0; - u.cp.pCur = p->apCsr[pOp->p1]; - assert( u.cp.pCur->pVtabCursor ); - if( u.cp.pCur->nullRow ){ - break; - } - u.cp.pVtab = u.cp.pCur->pVtabCursor->pVtab; - u.cp.pModule = u.cp.pVtab->pModule; - assert( u.cp.pModule->xNext ); - - /* Invoke the xNext() method of the module. There is no way for the - ** underlying implementation to return an error if one occurs during - ** xNext(). Instead, if an error occurs, true is returned (indicating that - ** data is available) and the error code returned when xColumn or - ** some other method is next invoked on the save virtual table cursor. - */ - p->inVtabMethod = 1; - rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor); - p->inVtabMethod = 0; - importVtabErrMsg(p, u.cp.pVtab); - if( rc==SQLITE_OK ){ - u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor); - } - - if( !u.cp.res ){ - /* If there is data, jump to P2 */ - pc = pOp->p2 - 1; - } - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VRename P1 * * P4 * -** -** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. -** This opcode invokes the corresponding xRename method. The value -** in register P1 is passed as the zName argument to the xRename method. -*/ -case OP_VRename: { -#if 0 /* local variables moved into u.cq */ - sqlite3_vtab *pVtab; - Mem *pName; -#endif /* local variables moved into u.cq */ - - u.cq.pVtab = pOp->p4.pVtab->pVtab; - u.cq.pName = &aMem[pOp->p1]; - assert( u.cq.pVtab->pModule->xRename ); - assert( memIsValid(u.cq.pName) ); - REGISTER_TRACE(pOp->p1, u.cq.pName); - assert( u.cq.pName->flags & MEM_Str ); - testcase( u.cq.pName->enc==SQLITE_UTF8 ); - testcase( u.cq.pName->enc==SQLITE_UTF16BE ); - testcase( u.cq.pName->enc==SQLITE_UTF16LE ); - rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8); - if( rc==SQLITE_OK ){ - rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z); - importVtabErrMsg(p, u.cq.pVtab); - p->expired = 0; - } - break; -} -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VUpdate P1 P2 P3 P4 * -** -** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. -** This opcode invokes the corresponding xUpdate method. P2 values -** are contiguous memory cells starting at P3 to pass to the xUpdate -** invocation. The value in register (P3+P2-1) corresponds to the -** p2th element of the argv array passed to xUpdate. -** -** The xUpdate method will do a DELETE or an INSERT or both. -** The argv[0] element (which corresponds to memory cell P3) -** is the rowid of a row to delete. If argv[0] is NULL then no -** deletion occurs. The argv[1] element is the rowid of the new -** row. This can be NULL to have the virtual table select the new -** rowid for itself. The subsequent elements in the array are -** the values of columns in the new row. -** -** If P2==1 then no insert is performed. argv[0] is the rowid of -** a row to delete. -** -** P1 is a boolean flag. If it is set to true and the xUpdate call -** is successful, then the value returned by sqlite3_last_insert_rowid() -** is set to the value of the rowid for the row just inserted. -*/ -case OP_VUpdate: { -#if 0 /* local variables moved into u.cr */ - sqlite3_vtab *pVtab; - sqlite3_module *pModule; - int nArg; - int i; - sqlite_int64 rowid; - Mem **apArg; - Mem *pX; -#endif /* local variables moved into u.cr */ - - assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback - || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace - ); - u.cr.pVtab = pOp->p4.pVtab->pVtab; - u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule; - u.cr.nArg = pOp->p2; - assert( pOp->p4type==P4_VTAB ); - if( ALWAYS(u.cr.pModule->xUpdate) ){ - u8 vtabOnConflict = db->vtabOnConflict; - u.cr.apArg = p->apArg; - u.cr.pX = &aMem[pOp->p3]; - for(u.cr.i=0; u.cr.ivtabOnConflict = pOp->p5; - rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid); - db->vtabOnConflict = vtabOnConflict; - importVtabErrMsg(p, u.cr.pVtab); - if( rc==SQLITE_OK && pOp->p1 ){ - assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) ); - db->lastRowid = lastRowid = u.cr.rowid; - } - if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){ - if( pOp->p5==OE_Ignore ){ - rc = SQLITE_OK; - }else{ - p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5); - } - }else{ - p->nChange++; - } - } - break; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* Opcode: Pagecount P1 P2 * * * -** -** Write the current number of pages in database P1 to memory cell P2. -*/ -case OP_Pagecount: { /* out2-prerelease */ - pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); - break; -} -#endif - - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* Opcode: MaxPgcnt P1 P2 P3 * * -** -** Try to set the maximum page count for database P1 to the value in P3. -** Do not let the maximum page count fall below the current page count and -** do not change the maximum page count value if P3==0. -** -** Store the maximum page count after the change in register P2. -*/ -case OP_MaxPgcnt: { /* out2-prerelease */ - unsigned int newMax; - Btree *pBt; - - pBt = db->aDb[pOp->p1].pBt; - newMax = 0; - if( pOp->p3 ){ - newMax = sqlite3BtreeLastPage(pBt); - if( newMax < (unsigned)pOp->p3 ) newMax = (unsigned)pOp->p3; - } - pOut->u.i = sqlite3BtreeMaxPageCount(pBt, newMax); - break; -} -#endif - - -#ifndef SQLITE_OMIT_TRACE -/* Opcode: Trace * * * P4 * -** -** If tracing is enabled (by the sqlite3_trace()) interface, then -** the UTF-8 string contained in P4 is emitted on the trace callback. -*/ -case OP_Trace: { -#if 0 /* local variables moved into u.cs */ - char *zTrace; - char *z; -#endif /* local variables moved into u.cs */ - - if( db->xTrace - && !p->doingRerun - && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 - ){ - u.cs.z = sqlite3VdbeExpandSql(p, u.cs.zTrace); - db->xTrace(db->pTraceArg, u.cs.z); - sqlite3DbFree(db, u.cs.z); - } -#ifdef SQLITE_DEBUG - if( (db->flags & SQLITE_SqlTrace)!=0 - && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 - ){ - sqlite3DebugPrintf("SQL-trace: %s\n", u.cs.zTrace); - } -#endif /* SQLITE_DEBUG */ - break; -} -#endif - - -/* Opcode: Noop * * * * * -** -** Do nothing. This instruction is often useful as a jump -** destination. -*/ -/* -** The magic Explain opcode are only inserted when explain==2 (which -** is to say when the EXPLAIN QUERY PLAN syntax is used.) -** This opcode records information from the optimizer. It is the -** the same as a no-op. This opcodesnever appears in a real VM program. -*/ -default: { /* This is really OP_Noop and OP_Explain */ - assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); - break; -} - -/***************************************************************************** -** The cases of the switch statement above this line should all be indented -** by 6 spaces. But the left-most 6 spaces have been removed to improve the -** readability. From this point on down, the normal indentation rules are -** restored. -*****************************************************************************/ - } - -#ifdef VDBE_PROFILE - { - u64 elapsed = sqlite3Hwtime() - start; - pOp->cycles += elapsed; - pOp->cnt++; -#if 0 - fprintf(stdout, "%10llu ", elapsed); - sqlite3VdbePrintOp(stdout, origPc, &aOp[origPc]); -#endif - } -#endif - - /* The following code adds nothing to the actual functionality - ** of the program. It is only here for testing and debugging. - ** On the other hand, it does burn CPU cycles every time through - ** the evaluator loop. So we can leave it out when NDEBUG is defined. - */ -#ifndef NDEBUG - assert( pc>=-1 && pcnOp ); - -#ifdef SQLITE_DEBUG - if( p->trace ){ - if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc); - if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){ - registerTrace(p->trace, pOp->p2, &aMem[pOp->p2]); - } - if( pOp->opflags & OPFLG_OUT3 ){ - registerTrace(p->trace, pOp->p3, &aMem[pOp->p3]); - } - } -#endif /* SQLITE_DEBUG */ -#endif /* NDEBUG */ - } /* The end of the for(;;) loop the loops through opcodes */ - - /* If we reach this point, it means that execution is finished with - ** an error of some kind. - */ -vdbe_error_halt: - assert( rc ); - p->rc = rc; - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(rc, "statement aborts at %d: [%s] %s", - pc, p->zSql, p->zErrMsg); - sqlite3VdbeHalt(p); - if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; - rc = SQLITE_ERROR; - if( resetSchemaOnFault>0 ){ - sqlite3ResetOneSchema(db, resetSchemaOnFault-1); - } - - /* This is the only way out of this procedure. We have to - ** release the mutexes on btrees that were acquired at the - ** top. */ -vdbe_return: - db->lastRowid = lastRowid; - sqlite3VdbeLeave(p); - return rc; - - /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH - ** is encountered. - */ -too_big: - sqlite3SetString(&p->zErrMsg, db, "string or blob too big"); - rc = SQLITE_TOOBIG; - goto vdbe_error_halt; - - /* Jump to here if a malloc() fails. - */ -no_mem: - db->mallocFailed = 1; - sqlite3SetString(&p->zErrMsg, db, "out of memory"); - rc = SQLITE_NOMEM; - goto vdbe_error_halt; - - /* Jump to here for any other kind of fatal error. The "rc" variable - ** should hold the error number. - */ -abort_due_to_error: - assert( p->zErrMsg==0 ); - if( db->mallocFailed ) rc = SQLITE_NOMEM; - if( rc!=SQLITE_IOERR_NOMEM ){ - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc)); - } - goto vdbe_error_halt; - - /* Jump to here if the sqlite3_interrupt() API sets the interrupt - ** flag. - */ -abort_due_to_interrupt: - assert( db->u1.isInterrupted ); - rc = SQLITE_INTERRUPT; - p->rc = rc; - sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc)); - goto vdbe_error_halt; -} - -/************** End of vdbe.c ************************************************/ -/************** Begin file vdbeblob.c ****************************************/ -/* -** 2007 May 1 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code used to implement incremental BLOB I/O. -*/ - - -#ifndef SQLITE_OMIT_INCRBLOB - -/* -** Valid sqlite3_blob* handles point to Incrblob structures. -*/ -typedef struct Incrblob Incrblob; -struct Incrblob { - int flags; /* Copy of "flags" passed to sqlite3_blob_open() */ - int nByte; /* Size of open blob, in bytes */ - int iOffset; /* Byte offset of blob in cursor data */ - int iCol; /* Table column this handle is open on */ - BtCursor *pCsr; /* Cursor pointing at blob row */ - sqlite3_stmt *pStmt; /* Statement holding cursor open */ - sqlite3 *db; /* The associated database */ -}; - - -/* -** This function is used by both blob_open() and blob_reopen(). It seeks -** the b-tree cursor associated with blob handle p to point to row iRow. -** If successful, SQLITE_OK is returned and subsequent calls to -** sqlite3_blob_read() or sqlite3_blob_write() access the specified row. -** -** If an error occurs, or if the specified row does not exist or does not -** contain a value of type TEXT or BLOB in the column nominated when the -** blob handle was opened, then an error code is returned and *pzErr may -** be set to point to a buffer containing an error message. It is the -** responsibility of the caller to free the error message buffer using -** sqlite3DbFree(). -** -** If an error does occur, then the b-tree cursor is closed. All subsequent -** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will -** immediately return SQLITE_ABORT. -*/ -static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ - int rc; /* Error code */ - char *zErr = 0; /* Error message */ - Vdbe *v = (Vdbe *)p->pStmt; - - /* Set the value of the SQL statements only variable to integer iRow. - ** This is done directly instead of using sqlite3_bind_int64() to avoid - ** triggering asserts related to mutexes. - */ - assert( v->aVar[0].flags&MEM_Int ); - v->aVar[0].u.i = iRow; - - rc = sqlite3_step(p->pStmt); - if( rc==SQLITE_ROW ){ - u32 type = v->apCsr[0]->aType[p->iCol]; - if( type<12 ){ - zErr = sqlite3MPrintf(p->db, "cannot open value of type %s", - type==0?"null": type==7?"real": "integer" - ); - rc = SQLITE_ERROR; - sqlite3_finalize(p->pStmt); - p->pStmt = 0; - }else{ - p->iOffset = v->apCsr[0]->aOffset[p->iCol]; - p->nByte = sqlite3VdbeSerialTypeLen(type); - p->pCsr = v->apCsr[0]->pCursor; - sqlite3BtreeEnterCursor(p->pCsr); - sqlite3BtreeCacheOverflow(p->pCsr); - sqlite3BtreeLeaveCursor(p->pCsr); - } - } - - if( rc==SQLITE_ROW ){ - rc = SQLITE_OK; - }else if( p->pStmt ){ - rc = sqlite3_finalize(p->pStmt); - p->pStmt = 0; - if( rc==SQLITE_OK ){ - zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow); - rc = SQLITE_ERROR; - }else{ - zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db)); - } - } - - assert( rc!=SQLITE_OK || zErr==0 ); - assert( rc!=SQLITE_ROW && rc!=SQLITE_DONE ); - - *pzErr = zErr; - return rc; -} - -/* -** Open a blob handle. -*/ -SQLITE_API int sqlite3_blob_open( - sqlite3* db, /* The database connection */ - const char *zDb, /* The attached database containing the blob */ - const char *zTable, /* The table containing the blob */ - const char *zColumn, /* The column containing the blob */ - sqlite_int64 iRow, /* The row containing the glob */ - int flags, /* True -> read/write access, false -> read-only */ - sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */ -){ - int nAttempt = 0; - int iCol; /* Index of zColumn in row-record */ - - /* This VDBE program seeks a btree cursor to the identified - ** db/table/row entry. The reason for using a vdbe program instead - ** of writing code to use the b-tree layer directly is that the - ** vdbe program will take advantage of the various transaction, - ** locking and error handling infrastructure built into the vdbe. - ** - ** After seeking the cursor, the vdbe executes an OP_ResultRow. - ** Code external to the Vdbe then "borrows" the b-tree cursor and - ** uses it to implement the blob_read(), blob_write() and - ** blob_bytes() functions. - ** - ** The sqlite3_blob_close() function finalizes the vdbe program, - ** which closes the b-tree cursor and (possibly) commits the - ** transaction. - */ - static const VdbeOpList openBlob[] = { - {OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */ - {OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */ - {OP_TableLock, 0, 0, 0}, /* 2: Acquire a read or write lock */ - - /* One of the following two instructions is replaced by an OP_Noop. */ - {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */ - {OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */ - - {OP_Variable, 1, 1, 1}, /* 5: Push the rowid to the stack */ - {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */ - {OP_Column, 0, 0, 1}, /* 7 */ - {OP_ResultRow, 1, 0, 0}, /* 8 */ - {OP_Goto, 0, 5, 0}, /* 9 */ - {OP_Close, 0, 0, 0}, /* 10 */ - {OP_Halt, 0, 0, 0}, /* 11 */ - }; - - int rc = SQLITE_OK; - char *zErr = 0; - Table *pTab; - Parse *pParse = 0; - Incrblob *pBlob = 0; - - flags = !!flags; /* flags = (flags ? 1 : 0); */ - *ppBlob = 0; - - sqlite3_mutex_enter(db->mutex); - - pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); - if( !pBlob ) goto blob_open_out; - pParse = sqlite3StackAllocRaw(db, sizeof(*pParse)); - if( !pParse ) goto blob_open_out; - - do { - memset(pParse, 0, sizeof(Parse)); - pParse->db = db; - sqlite3DbFree(db, zErr); - zErr = 0; - - sqlite3BtreeEnterAll(db); - pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); - if( pTab && IsVirtual(pTab) ){ - pTab = 0; - sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); - } -#ifndef SQLITE_OMIT_VIEW - if( pTab && pTab->pSelect ){ - pTab = 0; - sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable); - } -#endif - if( !pTab ){ - if( pParse->zErrMsg ){ - sqlite3DbFree(db, zErr); - zErr = pParse->zErrMsg; - pParse->zErrMsg = 0; - } - rc = SQLITE_ERROR; - sqlite3BtreeLeaveAll(db); - goto blob_open_out; - } - - /* Now search pTab for the exact column. */ - for(iCol=0; iColnCol; iCol++) { - if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){ - break; - } - } - if( iCol==pTab->nCol ){ - sqlite3DbFree(db, zErr); - zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); - rc = SQLITE_ERROR; - sqlite3BtreeLeaveAll(db); - goto blob_open_out; - } - - /* If the value is being opened for writing, check that the - ** column is not indexed, and that it is not part of a foreign key. - ** It is against the rules to open a column to which either of these - ** descriptions applies for writing. */ - if( flags ){ - const char *zFault = 0; - Index *pIdx; -#ifndef SQLITE_OMIT_FOREIGN_KEY - if( db->flags&SQLITE_ForeignKeys ){ - /* Check that the column is not part of an FK child key definition. It - ** is not necessary to check if it is part of a parent key, as parent - ** key columns must be indexed. The check below will pick up this - ** case. */ - FKey *pFKey; - for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ - int j; - for(j=0; jnCol; j++){ - if( pFKey->aCol[j].iFrom==iCol ){ - zFault = "foreign key"; - } - } - } - } -#endif - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int j; - for(j=0; jnColumn; j++){ - if( pIdx->aiColumn[j]==iCol ){ - zFault = "indexed"; - } - } - } - if( zFault ){ - sqlite3DbFree(db, zErr); - zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); - rc = SQLITE_ERROR; - sqlite3BtreeLeaveAll(db); - goto blob_open_out; - } - } - - pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(db); - assert( pBlob->pStmt || db->mallocFailed ); - if( pBlob->pStmt ){ - Vdbe *v = (Vdbe *)pBlob->pStmt; - int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - - sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob); - - - /* Configure the OP_Transaction */ - sqlite3VdbeChangeP1(v, 0, iDb); - sqlite3VdbeChangeP2(v, 0, flags); - - /* Configure the OP_VerifyCookie */ - sqlite3VdbeChangeP1(v, 1, iDb); - sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie); - sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration); - - /* Make sure a mutex is held on the table to be accessed */ - sqlite3VdbeUsesBtree(v, iDb); - - /* Configure the OP_TableLock instruction */ -#ifdef SQLITE_OMIT_SHARED_CACHE - sqlite3VdbeChangeToNoop(v, 2); -#else - sqlite3VdbeChangeP1(v, 2, iDb); - sqlite3VdbeChangeP2(v, 2, pTab->tnum); - sqlite3VdbeChangeP3(v, 2, flags); - sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); -#endif - - /* Remove either the OP_OpenWrite or OpenRead. Set the P2 - ** parameter of the other to pTab->tnum. */ - sqlite3VdbeChangeToNoop(v, 4 - flags); - sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum); - sqlite3VdbeChangeP3(v, 3 + flags, iDb); - - /* Configure the number of columns. Configure the cursor to - ** think that the table has one more column than it really - ** does. An OP_Column to retrieve this imaginary column will - ** always return an SQL NULL. This is useful because it means - ** we can invoke OP_Column to fill in the vdbe cursors type - ** and offset cache without causing any IO. - */ - sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); - sqlite3VdbeChangeP2(v, 7, pTab->nCol); - if( !db->mallocFailed ){ - pParse->nVar = 1; - pParse->nMem = 1; - pParse->nTab = 1; - sqlite3VdbeMakeReady(v, pParse); - } - } - - pBlob->flags = flags; - pBlob->iCol = iCol; - pBlob->db = db; - sqlite3BtreeLeaveAll(db); - if( db->mallocFailed ){ - goto blob_open_out; - } - sqlite3_bind_int64(pBlob->pStmt, 1, iRow); - rc = blobSeekToRow(pBlob, iRow, &zErr); - } while( (++nAttempt)mallocFailed==0 ){ - *ppBlob = (sqlite3_blob *)pBlob; - }else{ - if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); - sqlite3DbFree(db, pBlob); - } - sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); - sqlite3DbFree(db, zErr); - sqlite3StackFree(db, pParse); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Close a blob handle that was previously created using -** sqlite3_blob_open(). -*/ -SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){ - Incrblob *p = (Incrblob *)pBlob; - int rc; - sqlite3 *db; - - if( p ){ - db = p->db; - sqlite3_mutex_enter(db->mutex); - rc = sqlite3_finalize(p->pStmt); - sqlite3DbFree(db, p); - sqlite3_mutex_leave(db->mutex); - }else{ - rc = SQLITE_OK; - } - return rc; -} - -/* -** Perform a read or write operation on a blob -*/ -static int blobReadWrite( - sqlite3_blob *pBlob, - void *z, - int n, - int iOffset, - int (*xCall)(BtCursor*, u32, u32, void*) -){ - int rc; - Incrblob *p = (Incrblob *)pBlob; - Vdbe *v; - sqlite3 *db; - - if( p==0 ) return SQLITE_MISUSE_BKPT; - db = p->db; - sqlite3_mutex_enter(db->mutex); - v = (Vdbe*)p->pStmt; - - if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ - /* Request is out of range. Return a transient error. */ - rc = SQLITE_ERROR; - sqlite3Error(db, SQLITE_ERROR, 0); - }else if( v==0 ){ - /* If there is no statement handle, then the blob-handle has - ** already been invalidated. Return SQLITE_ABORT in this case. - */ - rc = SQLITE_ABORT; - }else{ - /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is - ** returned, clean-up the statement handle. - */ - assert( db == v->db ); - sqlite3BtreeEnterCursor(p->pCsr); - rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); - sqlite3BtreeLeaveCursor(p->pCsr); - if( rc==SQLITE_ABORT ){ - sqlite3VdbeFinalize(v); - p->pStmt = 0; - }else{ - db->errCode = rc; - v->rc = rc; - } - } - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Read data from a blob handle. -*/ -SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ - return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData); -} - -/* -** Write data to a blob handle. -*/ -SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ - return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); -} - -/* -** Query a blob handle for the size of the data. -** -** The Incrblob.nByte field is fixed for the lifetime of the Incrblob -** so no mutex is required for access. -*/ -SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ - Incrblob *p = (Incrblob *)pBlob; - return (p && p->pStmt) ? p->nByte : 0; -} - -/* -** Move an existing blob handle to point to a different row of the same -** database table. -** -** If an error occurs, or if the specified row does not exist or does not -** contain a blob or text value, then an error code is returned and the -** database handle error code and message set. If this happens, then all -** subsequent calls to sqlite3_blob_xxx() functions (except blob_close()) -** immediately return SQLITE_ABORT. -*/ -SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ - int rc; - Incrblob *p = (Incrblob *)pBlob; - sqlite3 *db; - - if( p==0 ) return SQLITE_MISUSE_BKPT; - db = p->db; - sqlite3_mutex_enter(db->mutex); - - if( p->pStmt==0 ){ - /* If there is no statement handle, then the blob-handle has - ** already been invalidated. Return SQLITE_ABORT in this case. - */ - rc = SQLITE_ABORT; - }else{ - char *zErr; - rc = blobSeekToRow(p, iRow, &zErr); - if( rc!=SQLITE_OK ){ - sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); - sqlite3DbFree(db, zErr); - } - assert( rc!=SQLITE_SCHEMA ); - } - - rc = sqlite3ApiExit(db, rc); - assert( rc==SQLITE_OK || p->pStmt==0 ); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -#endif /* #ifndef SQLITE_OMIT_INCRBLOB */ - -/************** End of vdbeblob.c ********************************************/ -/************** Begin file vdbesort.c ****************************************/ -/* -** 2011 July 9 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code for the VdbeSorter object, used in concert with -** a VdbeCursor to sort large numbers of keys (as may be required, for -** example, by CREATE INDEX statements on tables too large to fit in main -** memory). -*/ - - - -typedef struct VdbeSorterIter VdbeSorterIter; -typedef struct SorterRecord SorterRecord; -typedef struct FileWriter FileWriter; - -/* -** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES: -** -** As keys are added to the sorter, they are written to disk in a series -** of sorted packed-memory-arrays (PMAs). The size of each PMA is roughly -** the same as the cache-size allowed for temporary databases. In order -** to allow the caller to extract keys from the sorter in sorted order, -** all PMAs currently stored on disk must be merged together. This comment -** describes the data structure used to do so. The structure supports -** merging any number of arrays in a single pass with no redundant comparison -** operations. -** -** The aIter[] array contains an iterator for each of the PMAs being merged. -** An aIter[] iterator either points to a valid key or else is at EOF. For -** the purposes of the paragraphs below, we assume that the array is actually -** N elements in size, where N is the smallest power of 2 greater to or equal -** to the number of iterators being merged. The extra aIter[] elements are -** treated as if they are empty (always at EOF). -** -** The aTree[] array is also N elements in size. The value of N is stored in -** the VdbeSorter.nTree variable. -** -** The final (N/2) elements of aTree[] contain the results of comparing -** pairs of iterator keys together. Element i contains the result of -** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the -** aTree element is set to the index of it. -** -** For the purposes of this comparison, EOF is considered greater than any -** other key value. If the keys are equal (only possible with two EOF -** values), it doesn't matter which index is stored. -** -** The (N/4) elements of aTree[] that preceed the final (N/2) described -** above contains the index of the smallest of each block of 4 iterators. -** And so on. So that aTree[1] contains the index of the iterator that -** currently points to the smallest key value. aTree[0] is unused. -** -** Example: -** -** aIter[0] -> Banana -** aIter[1] -> Feijoa -** aIter[2] -> Elderberry -** aIter[3] -> Currant -** aIter[4] -> Grapefruit -** aIter[5] -> Apple -** aIter[6] -> Durian -** aIter[7] -> EOF -** -** aTree[] = { X, 5 0, 5 0, 3, 5, 6 } -** -** The current element is "Apple" (the value of the key indicated by -** iterator 5). When the Next() operation is invoked, iterator 5 will -** be advanced to the next key in its segment. Say the next key is -** "Eggplant": -** -** aIter[5] -> Eggplant -** -** The contents of aTree[] are updated first by comparing the new iterator -** 5 key to the current key of iterator 4 (still "Grapefruit"). The iterator -** 5 value is still smaller, so aTree[6] is set to 5. And so on up the tree. -** The value of iterator 6 - "Durian" - is now smaller than that of iterator -** 5, so aTree[3] is set to 6. Key 0 is smaller than key 6 (BananaaAlloc); - sqlite3DbFree(db, pIter->aBuffer); - memset(pIter, 0, sizeof(VdbeSorterIter)); -} - -/* -** Read nByte bytes of data from the stream of data iterated by object p. -** If successful, set *ppOut to point to a buffer containing the data -** and return SQLITE_OK. Otherwise, if an error occurs, return an SQLite -** error code. -** -** The buffer indicated by *ppOut may only be considered valid until the -** next call to this function. -*/ -static int vdbeSorterIterRead( - sqlite3 *db, /* Database handle (for malloc) */ - VdbeSorterIter *p, /* Iterator */ - int nByte, /* Bytes of data to read */ - u8 **ppOut /* OUT: Pointer to buffer containing data */ -){ - int iBuf; /* Offset within buffer to read from */ - int nAvail; /* Bytes of data available in buffer */ - assert( p->aBuffer ); - - /* If there is no more data to be read from the buffer, read the next - ** p->nBuffer bytes of data from the file into it. Or, if there are less - ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ - iBuf = p->iReadOff % p->nBuffer; - if( iBuf==0 ){ - int nRead; /* Bytes to read from disk */ - int rc; /* sqlite3OsRead() return code */ - - /* Determine how many bytes of data to read. */ - if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){ - nRead = p->nBuffer; - }else{ - nRead = (int)(p->iEof - p->iReadOff); - } - assert( nRead>0 ); - - /* Read data from the file. Return early if an error occurs. */ - rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff); - assert( rc!=SQLITE_IOERR_SHORT_READ ); - if( rc!=SQLITE_OK ) return rc; - } - nAvail = p->nBuffer - iBuf; - - if( nByte<=nAvail ){ - /* The requested data is available in the in-memory buffer. In this - ** case there is no need to make a copy of the data, just return a - ** pointer into the buffer to the caller. */ - *ppOut = &p->aBuffer[iBuf]; - p->iReadOff += nByte; - }else{ - /* The requested data is not all available in the in-memory buffer. - ** In this case, allocate space at p->aAlloc[] to copy the requested - ** range into. Then return a copy of pointer p->aAlloc to the caller. */ - int nRem; /* Bytes remaining to copy */ - - /* Extend the p->aAlloc[] allocation if required. */ - if( p->nAllocnAlloc*2; - while( nByte>nNew ) nNew = nNew*2; - p->aAlloc = sqlite3DbReallocOrFree(db, p->aAlloc, nNew); - if( !p->aAlloc ) return SQLITE_NOMEM; - p->nAlloc = nNew; - } - - /* Copy as much data as is available in the buffer into the start of - ** p->aAlloc[]. */ - memcpy(p->aAlloc, &p->aBuffer[iBuf], nAvail); - p->iReadOff += nAvail; - nRem = nByte - nAvail; - - /* The following loop copies up to p->nBuffer bytes per iteration into - ** the p->aAlloc[] buffer. */ - while( nRem>0 ){ - int rc; /* vdbeSorterIterRead() return code */ - int nCopy; /* Number of bytes to copy */ - u8 *aNext; /* Pointer to buffer to copy data from */ - - nCopy = nRem; - if( nRem>p->nBuffer ) nCopy = p->nBuffer; - rc = vdbeSorterIterRead(db, p, nCopy, &aNext); - if( rc!=SQLITE_OK ) return rc; - assert( aNext!=p->aAlloc ); - memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy); - nRem -= nCopy; - } - - *ppOut = p->aAlloc; - } - - return SQLITE_OK; -} - -/* -** Read a varint from the stream of data accessed by p. Set *pnOut to -** the value read. -*/ -static int vdbeSorterIterVarint(sqlite3 *db, VdbeSorterIter *p, u64 *pnOut){ - int iBuf; - - iBuf = p->iReadOff % p->nBuffer; - if( iBuf && (p->nBuffer-iBuf)>=9 ){ - p->iReadOff += sqlite3GetVarint(&p->aBuffer[iBuf], pnOut); - }else{ - u8 aVarint[16], *a; - int i = 0, rc; - do{ - rc = vdbeSorterIterRead(db, p, 1, &a); - if( rc ) return rc; - aVarint[(i++)&0xf] = a[0]; - }while( (a[0]&0x80)!=0 ); - sqlite3GetVarint(aVarint, pnOut); - } - - return SQLITE_OK; -} - - -/* -** Advance iterator pIter to the next key in its PMA. Return SQLITE_OK if -** no error occurs, or an SQLite error code if one does. -*/ -static int vdbeSorterIterNext( - sqlite3 *db, /* Database handle (for sqlite3DbMalloc() ) */ - VdbeSorterIter *pIter /* Iterator to advance */ -){ - int rc; /* Return Code */ - u64 nRec = 0; /* Size of record in bytes */ - - if( pIter->iReadOff>=pIter->iEof ){ - /* This is an EOF condition */ - vdbeSorterIterZero(db, pIter); - return SQLITE_OK; - } - - rc = vdbeSorterIterVarint(db, pIter, &nRec); - if( rc==SQLITE_OK ){ - pIter->nKey = (int)nRec; - rc = vdbeSorterIterRead(db, pIter, (int)nRec, &pIter->aKey); - } - - return rc; -} - -/* -** Initialize iterator pIter to scan through the PMA stored in file pFile -** starting at offset iStart and ending at offset iEof-1. This function -** leaves the iterator pointing to the first key in the PMA (or EOF if the -** PMA is empty). -*/ -static int vdbeSorterIterInit( - sqlite3 *db, /* Database handle */ - const VdbeSorter *pSorter, /* Sorter object */ - i64 iStart, /* Start offset in pFile */ - VdbeSorterIter *pIter, /* Iterator to populate */ - i64 *pnByte /* IN/OUT: Increment this value by PMA size */ -){ - int rc = SQLITE_OK; - int nBuf; - - nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt); - - assert( pSorter->iWriteOff>iStart ); - assert( pIter->aAlloc==0 ); - assert( pIter->aBuffer==0 ); - pIter->pFile = pSorter->pTemp1; - pIter->iReadOff = iStart; - pIter->nAlloc = 128; - pIter->aAlloc = (u8 *)sqlite3DbMallocRaw(db, pIter->nAlloc); - pIter->nBuffer = nBuf; - pIter->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf); - - if( !pIter->aBuffer ){ - rc = SQLITE_NOMEM; - }else{ - int iBuf; - - iBuf = iStart % nBuf; - if( iBuf ){ - int nRead = nBuf - iBuf; - if( (iStart + nRead) > pSorter->iWriteOff ){ - nRead = (int)(pSorter->iWriteOff - iStart); - } - rc = sqlite3OsRead( - pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart - ); - assert( rc!=SQLITE_IOERR_SHORT_READ ); - } - - if( rc==SQLITE_OK ){ - u64 nByte; /* Size of PMA in bytes */ - pIter->iEof = pSorter->iWriteOff; - rc = vdbeSorterIterVarint(db, pIter, &nByte); - pIter->iEof = pIter->iReadOff + nByte; - *pnByte += nByte; - } - } - - if( rc==SQLITE_OK ){ - rc = vdbeSorterIterNext(db, pIter); - } - return rc; -} - - -/* -** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, -** size nKey2 bytes). Argument pKeyInfo supplies the collation functions -** used by the comparison. If an error occurs, return an SQLite error code. -** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive -** value, depending on whether key1 is smaller, equal to or larger than key2. -** -** If the bOmitRowid argument is non-zero, assume both keys end in a rowid -** field. For the purposes of the comparison, ignore it. Also, if bOmitRowid -** is true and key1 contains even a single NULL value, it is considered to -** be less than key2. Even if key2 also contains NULL values. -** -** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace -** has been allocated and contains an unpacked record that is used as key2. -*/ -static void vdbeSorterCompare( - const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */ - int bOmitRowid, /* Ignore rowid field at end of keys */ - const void *pKey1, int nKey1, /* Left side of comparison */ - const void *pKey2, int nKey2, /* Right side of comparison */ - int *pRes /* OUT: Result of comparison */ -){ - KeyInfo *pKeyInfo = pCsr->pKeyInfo; - VdbeSorter *pSorter = pCsr->pSorter; - UnpackedRecord *r2 = pSorter->pUnpacked; - int i; - - if( pKey2 ){ - sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2); - } - - if( bOmitRowid ){ - r2->nField = pKeyInfo->nField; - assert( r2->nField>0 ); - for(i=0; inField; i++){ - if( r2->aMem[i].flags & MEM_Null ){ - *pRes = -1; - return; - } - } - r2->flags |= UNPACKED_PREFIX_MATCH; - } - - *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2); -} - -/* -** This function is called to compare two iterator keys when merging -** multiple b-tree segments. Parameter iOut is the index of the aTree[] -** value to recalculate. -*/ -static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){ - VdbeSorter *pSorter = pCsr->pSorter; - int i1; - int i2; - int iRes; - VdbeSorterIter *p1; - VdbeSorterIter *p2; - - assert( iOutnTree && iOut>0 ); - - if( iOut>=(pSorter->nTree/2) ){ - i1 = (iOut - pSorter->nTree/2) * 2; - i2 = i1 + 1; - }else{ - i1 = pSorter->aTree[iOut*2]; - i2 = pSorter->aTree[iOut*2+1]; - } - - p1 = &pSorter->aIter[i1]; - p2 = &pSorter->aIter[i2]; - - if( p1->pFile==0 ){ - iRes = i2; - }else if( p2->pFile==0 ){ - iRes = i1; - }else{ - int res; - assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */ - vdbeSorterCompare( - pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res - ); - if( res<=0 ){ - iRes = i1; - }else{ - iRes = i2; - } - } - - pSorter->aTree[iOut] = iRes; - return SQLITE_OK; -} - -/* -** Initialize the temporary index cursor just opened as a sorter cursor. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *db, VdbeCursor *pCsr){ - int pgsz; /* Page size of main database */ - int mxCache; /* Cache size */ - VdbeSorter *pSorter; /* The new sorter */ - char *d; /* Dummy */ - - assert( pCsr->pKeyInfo && pCsr->pBt==0 ); - pCsr->pSorter = pSorter = sqlite3DbMallocZero(db, sizeof(VdbeSorter)); - if( pSorter==0 ){ - return SQLITE_NOMEM; - } - - pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d); - if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM; - assert( pSorter->pUnpacked==(UnpackedRecord *)d ); - - if( !sqlite3TempInMemory(db) ){ - pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); - pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; - mxCache = db->aDb[0].pSchema->cache_size; - if( mxCachemxPmaSize = mxCache * pgsz; - } - - return SQLITE_OK; -} - -/* -** Free the list of sorted records starting at pRecord. -*/ -static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){ - SorterRecord *p; - SorterRecord *pNext; - for(p=pRecord; p; p=pNext){ - pNext = p->pNext; - sqlite3DbFree(db, p); - } -} - -/* -** Free any cursor components allocated by sqlite3VdbeSorterXXX routines. -*/ -SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ - VdbeSorter *pSorter = pCsr->pSorter; - if( pSorter ){ - if( pSorter->aIter ){ - int i; - for(i=0; inTree; i++){ - vdbeSorterIterZero(db, &pSorter->aIter[i]); - } - sqlite3DbFree(db, pSorter->aIter); - } - if( pSorter->pTemp1 ){ - sqlite3OsCloseFree(pSorter->pTemp1); - } - vdbeSorterRecordFree(db, pSorter->pRecord); - sqlite3DbFree(db, pSorter->pUnpacked); - sqlite3DbFree(db, pSorter); - pCsr->pSorter = 0; - } -} - -/* -** Allocate space for a file-handle and open a temporary file. If successful, -** set *ppFile to point to the malloc'd file-handle and return SQLITE_OK. -** Otherwise, set *ppFile to 0 and return an SQLite error code. -*/ -static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){ - int dummy; - return sqlite3OsOpenMalloc(db->pVfs, 0, ppFile, - SQLITE_OPEN_TEMP_JOURNAL | - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE, &dummy - ); -} - -/* -** Merge the two sorted lists p1 and p2 into a single list. -** Set *ppOut to the head of the new list. -*/ -static void vdbeSorterMerge( - const VdbeCursor *pCsr, /* For pKeyInfo */ - SorterRecord *p1, /* First list to merge */ - SorterRecord *p2, /* Second list to merge */ - SorterRecord **ppOut /* OUT: Head of merged list */ -){ - SorterRecord *pFinal = 0; - SorterRecord **pp = &pFinal; - void *pVal2 = p2 ? p2->pVal : 0; - - while( p1 && p2 ){ - int res; - vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res); - if( res<=0 ){ - *pp = p1; - pp = &p1->pNext; - p1 = p1->pNext; - pVal2 = 0; - }else{ - *pp = p2; - pp = &p2->pNext; - p2 = p2->pNext; - if( p2==0 ) break; - pVal2 = p2->pVal; - } - } - *pp = p1 ? p1 : p2; - *ppOut = pFinal; -} - -/* -** Sort the linked list of records headed at pCsr->pRecord. Return SQLITE_OK -** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error -** occurs. -*/ -static int vdbeSorterSort(const VdbeCursor *pCsr){ - int i; - SorterRecord **aSlot; - SorterRecord *p; - VdbeSorter *pSorter = pCsr->pSorter; - - aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); - if( !aSlot ){ - return SQLITE_NOMEM; - } - - p = pSorter->pRecord; - while( p ){ - SorterRecord *pNext = p->pNext; - p->pNext = 0; - for(i=0; aSlot[i]; i++){ - vdbeSorterMerge(pCsr, p, aSlot[i], &p); - aSlot[i] = 0; - } - aSlot[i] = p; - p = pNext; - } - - p = 0; - for(i=0; i<64; i++){ - vdbeSorterMerge(pCsr, p, aSlot[i], &p); - } - pSorter->pRecord = p; - - sqlite3_free(aSlot); - return SQLITE_OK; -} - -/* -** Initialize a file-writer object. -*/ -static void fileWriterInit( - sqlite3 *db, /* Database (for malloc) */ - sqlite3_file *pFile, /* File to write to */ - FileWriter *p, /* Object to populate */ - i64 iStart /* Offset of pFile to begin writing at */ -){ - int nBuf = sqlite3BtreeGetPageSize(db->aDb[0].pBt); - - memset(p, 0, sizeof(FileWriter)); - p->aBuffer = (u8 *)sqlite3DbMallocRaw(db, nBuf); - if( !p->aBuffer ){ - p->eFWErr = SQLITE_NOMEM; - }else{ - p->iBufEnd = p->iBufStart = (iStart % nBuf); - p->iWriteOff = iStart - p->iBufStart; - p->nBuffer = nBuf; - p->pFile = pFile; - } -} - -/* -** Write nData bytes of data to the file-write object. Return SQLITE_OK -** if successful, or an SQLite error code if an error occurs. -*/ -static void fileWriterWrite(FileWriter *p, u8 *pData, int nData){ - int nRem = nData; - while( nRem>0 && p->eFWErr==0 ){ - int nCopy = nRem; - if( nCopy>(p->nBuffer - p->iBufEnd) ){ - nCopy = p->nBuffer - p->iBufEnd; - } - - memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy); - p->iBufEnd += nCopy; - if( p->iBufEnd==p->nBuffer ){ - p->eFWErr = sqlite3OsWrite(p->pFile, - &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, - p->iWriteOff + p->iBufStart - ); - p->iBufStart = p->iBufEnd = 0; - p->iWriteOff += p->nBuffer; - } - assert( p->iBufEndnBuffer ); - - nRem -= nCopy; - } -} - -/* -** Flush any buffered data to disk and clean up the file-writer object. -** The results of using the file-writer after this call are undefined. -** Return SQLITE_OK if flushing the buffered data succeeds or is not -** required. Otherwise, return an SQLite error code. -** -** Before returning, set *piEof to the offset immediately following the -** last byte written to the file. -*/ -static int fileWriterFinish(sqlite3 *db, FileWriter *p, i64 *piEof){ - int rc; - if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){ - p->eFWErr = sqlite3OsWrite(p->pFile, - &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, - p->iWriteOff + p->iBufStart - ); - } - *piEof = (p->iWriteOff + p->iBufEnd); - sqlite3DbFree(db, p->aBuffer); - rc = p->eFWErr; - memset(p, 0, sizeof(FileWriter)); - return rc; -} - -/* -** Write value iVal encoded as a varint to the file-write object. Return -** SQLITE_OK if successful, or an SQLite error code if an error occurs. -*/ -static void fileWriterWriteVarint(FileWriter *p, u64 iVal){ - int nByte; - u8 aByte[10]; - nByte = sqlite3PutVarint(aByte, iVal); - fileWriterWrite(p, aByte, nByte); -} - -/* -** Write the current contents of the in-memory linked-list to a PMA. Return -** SQLITE_OK if successful, or an SQLite error code otherwise. -** -** The format of a PMA is: -** -** * A varint. This varint contains the total number of bytes of content -** in the PMA (not including the varint itself). -** -** * One or more records packed end-to-end in order of ascending keys. -** Each record consists of a varint followed by a blob of data (the -** key). The varint is the number of bytes in the blob of data. -*/ -static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){ - int rc = SQLITE_OK; /* Return code */ - VdbeSorter *pSorter = pCsr->pSorter; - FileWriter writer; - - memset(&writer, 0, sizeof(FileWriter)); - - if( pSorter->nInMemory==0 ){ - assert( pSorter->pRecord==0 ); - return rc; - } - - rc = vdbeSorterSort(pCsr); - - /* If the first temporary PMA file has not been opened, open it now. */ - if( rc==SQLITE_OK && pSorter->pTemp1==0 ){ - rc = vdbeSorterOpenTempFile(db, &pSorter->pTemp1); - assert( rc!=SQLITE_OK || pSorter->pTemp1 ); - assert( pSorter->iWriteOff==0 ); - assert( pSorter->nPMA==0 ); - } - - if( rc==SQLITE_OK ){ - SorterRecord *p; - SorterRecord *pNext = 0; - - fileWriterInit(db, pSorter->pTemp1, &writer, pSorter->iWriteOff); - pSorter->nPMA++; - fileWriterWriteVarint(&writer, pSorter->nInMemory); - for(p=pSorter->pRecord; p; p=pNext){ - pNext = p->pNext; - fileWriterWriteVarint(&writer, p->nVal); - fileWriterWrite(&writer, p->pVal, p->nVal); - sqlite3DbFree(db, p); - } - pSorter->pRecord = p; - rc = fileWriterFinish(db, &writer, &pSorter->iWriteOff); - } - - return rc; -} - -/* -** Add a record to the sorter. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterWrite( - sqlite3 *db, /* Database handle */ - const VdbeCursor *pCsr, /* Sorter cursor */ - Mem *pVal /* Memory cell containing record */ -){ - VdbeSorter *pSorter = pCsr->pSorter; - int rc = SQLITE_OK; /* Return Code */ - SorterRecord *pNew; /* New list element */ - - assert( pSorter ); - pSorter->nInMemory += sqlite3VarintLen(pVal->n) + pVal->n; - - pNew = (SorterRecord *)sqlite3DbMallocRaw(db, pVal->n + sizeof(SorterRecord)); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - }else{ - pNew->pVal = (void *)&pNew[1]; - memcpy(pNew->pVal, pVal->z, pVal->n); - pNew->nVal = pVal->n; - pNew->pNext = pSorter->pRecord; - pSorter->pRecord = pNew; - } - - /* See if the contents of the sorter should now be written out. They - ** are written out when either of the following are true: - ** - ** * The total memory allocated for the in-memory list is greater - ** than (page-size * cache-size), or - ** - ** * The total memory allocated for the in-memory list is greater - ** than (page-size * 10) and sqlite3HeapNearlyFull() returns true. - */ - if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && ( - (pSorter->nInMemory>pSorter->mxPmaSize) - || (pSorter->nInMemory>pSorter->mnPmaSize && sqlite3HeapNearlyFull()) - )){ -#ifdef SQLITE_DEBUG - i64 nExpect = pSorter->iWriteOff - + sqlite3VarintLen(pSorter->nInMemory) - + pSorter->nInMemory; -#endif - rc = vdbeSorterListToPMA(db, pCsr); - pSorter->nInMemory = 0; - assert( rc!=SQLITE_OK || (nExpect==pSorter->iWriteOff) ); - } - - return rc; -} - -/* -** Helper function for sqlite3VdbeSorterRewind(). -*/ -static int vdbeSorterInitMerge( - sqlite3 *db, /* Database handle */ - const VdbeCursor *pCsr, /* Cursor handle for this sorter */ - i64 *pnByte /* Sum of bytes in all opened PMAs */ -){ - VdbeSorter *pSorter = pCsr->pSorter; - int rc = SQLITE_OK; /* Return code */ - int i; /* Used to iterator through aIter[] */ - i64 nByte = 0; /* Total bytes in all opened PMAs */ - - /* Initialize the iterators. */ - for(i=0; iaIter[i]; - rc = vdbeSorterIterInit(db, pSorter, pSorter->iReadOff, pIter, &nByte); - pSorter->iReadOff = pIter->iEof; - assert( rc!=SQLITE_OK || pSorter->iReadOff<=pSorter->iWriteOff ); - if( rc!=SQLITE_OK || pSorter->iReadOff>=pSorter->iWriteOff ) break; - } - - /* Initialize the aTree[] array. */ - for(i=pSorter->nTree-1; rc==SQLITE_OK && i>0; i--){ - rc = vdbeSorterDoCompare(pCsr, i); - } - - *pnByte = nByte; - return rc; -} - -/* -** Once the sorter has been populated, this function is called to prepare -** for iterating through its contents in sorted order. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ - VdbeSorter *pSorter = pCsr->pSorter; - int rc; /* Return code */ - sqlite3_file *pTemp2 = 0; /* Second temp file to use */ - i64 iWrite2 = 0; /* Write offset for pTemp2 */ - int nIter; /* Number of iterators used */ - int nByte; /* Bytes of space required for aIter/aTree */ - int N = 2; /* Power of 2 >= nIter */ - - assert( pSorter ); - - /* If no data has been written to disk, then do not do so now. Instead, - ** sort the VdbeSorter.pRecord list. The vdbe layer will read data directly - ** from the in-memory list. */ - if( pSorter->nPMA==0 ){ - *pbEof = !pSorter->pRecord; - assert( pSorter->aTree==0 ); - return vdbeSorterSort(pCsr); - } - - /* Write the current in-memory list to a PMA. */ - rc = vdbeSorterListToPMA(db, pCsr); - if( rc!=SQLITE_OK ) return rc; - - /* Allocate space for aIter[] and aTree[]. */ - nIter = pSorter->nPMA; - if( nIter>SORTER_MAX_MERGE_COUNT ) nIter = SORTER_MAX_MERGE_COUNT; - assert( nIter>0 ); - while( NaIter = (VdbeSorterIter *)sqlite3DbMallocZero(db, nByte); - if( !pSorter->aIter ) return SQLITE_NOMEM; - pSorter->aTree = (int *)&pSorter->aIter[N]; - pSorter->nTree = N; - - do { - int iNew; /* Index of new, merged, PMA */ - - for(iNew=0; - rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNTnPMA; - iNew++ - ){ - int rc2; /* Return code from fileWriterFinish() */ - FileWriter writer; /* Object used to write to disk */ - i64 nWrite; /* Number of bytes in new PMA */ - - memset(&writer, 0, sizeof(FileWriter)); - - /* If there are SORTER_MAX_MERGE_COUNT or less PMAs in file pTemp1, - ** initialize an iterator for each of them and break out of the loop. - ** These iterators will be incrementally merged as the VDBE layer calls - ** sqlite3VdbeSorterNext(). - ** - ** Otherwise, if pTemp1 contains more than SORTER_MAX_MERGE_COUNT PMAs, - ** initialize interators for SORTER_MAX_MERGE_COUNT of them. These PMAs - ** are merged into a single PMA that is written to file pTemp2. - */ - rc = vdbeSorterInitMerge(db, pCsr, &nWrite); - assert( rc!=SQLITE_OK || pSorter->aIter[ pSorter->aTree[1] ].pFile ); - if( rc!=SQLITE_OK || pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){ - break; - } - - /* Open the second temp file, if it is not already open. */ - if( pTemp2==0 ){ - assert( iWrite2==0 ); - rc = vdbeSorterOpenTempFile(db, &pTemp2); - } - - if( rc==SQLITE_OK ){ - int bEof = 0; - fileWriterInit(db, pTemp2, &writer, iWrite2); - fileWriterWriteVarint(&writer, nWrite); - while( rc==SQLITE_OK && bEof==0 ){ - VdbeSorterIter *pIter = &pSorter->aIter[ pSorter->aTree[1] ]; - assert( pIter->pFile ); - - fileWriterWriteVarint(&writer, pIter->nKey); - fileWriterWrite(&writer, pIter->aKey, pIter->nKey); - rc = sqlite3VdbeSorterNext(db, pCsr, &bEof); - } - rc2 = fileWriterFinish(db, &writer, &iWrite2); - if( rc==SQLITE_OK ) rc = rc2; - } - } - - if( pSorter->nPMA<=SORTER_MAX_MERGE_COUNT ){ - break; - }else{ - sqlite3_file *pTmp = pSorter->pTemp1; - pSorter->nPMA = iNew; - pSorter->pTemp1 = pTemp2; - pTemp2 = pTmp; - pSorter->iWriteOff = iWrite2; - pSorter->iReadOff = 0; - iWrite2 = 0; - } - }while( rc==SQLITE_OK ); - - if( pTemp2 ){ - sqlite3OsCloseFree(pTemp2); - } - *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0); - return rc; -} - -/* -** Advance to the next element in the sorter. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ - VdbeSorter *pSorter = pCsr->pSorter; - int rc; /* Return code */ - - if( pSorter->aTree ){ - int iPrev = pSorter->aTree[1];/* Index of iterator to advance */ - int i; /* Index of aTree[] to recalculate */ - - rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]); - for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){ - rc = vdbeSorterDoCompare(pCsr, i); - } - - *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0); - }else{ - SorterRecord *pFree = pSorter->pRecord; - pSorter->pRecord = pFree->pNext; - pFree->pNext = 0; - vdbeSorterRecordFree(db, pFree); - *pbEof = !pSorter->pRecord; - rc = SQLITE_OK; - } - return rc; -} - -/* -** Return a pointer to a buffer owned by the sorter that contains the -** current key. -*/ -static void *vdbeSorterRowkey( - const VdbeSorter *pSorter, /* Sorter object */ - int *pnKey /* OUT: Size of current key in bytes */ -){ - void *pKey; - if( pSorter->aTree ){ - VdbeSorterIter *pIter; - pIter = &pSorter->aIter[ pSorter->aTree[1] ]; - *pnKey = pIter->nKey; - pKey = pIter->aKey; - }else{ - *pnKey = pSorter->pRecord->nVal; - pKey = pSorter->pRecord->pVal; - } - return pKey; -} - -/* -** Copy the current sorter key into the memory cell pOut. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){ - VdbeSorter *pSorter = pCsr->pSorter; - void *pKey; int nKey; /* Sorter key to copy into pOut */ - - pKey = vdbeSorterRowkey(pSorter, &nKey); - if( sqlite3VdbeMemGrow(pOut, nKey, 0) ){ - return SQLITE_NOMEM; - } - pOut->n = nKey; - MemSetTypeFlag(pOut, MEM_Blob); - memcpy(pOut->z, pKey, nKey); - - return SQLITE_OK; -} - -/* -** Compare the key in memory cell pVal with the key that the sorter cursor -** passed as the first argument currently points to. For the purposes of -** the comparison, ignore the rowid field at the end of each record. -** -** If an error occurs, return an SQLite error code (i.e. SQLITE_NOMEM). -** Otherwise, set *pRes to a negative, zero or positive value if the -** key in pVal is smaller than, equal to or larger than the current sorter -** key. -*/ -SQLITE_PRIVATE int sqlite3VdbeSorterCompare( - const VdbeCursor *pCsr, /* Sorter cursor */ - Mem *pVal, /* Value to compare to current sorter key */ - int *pRes /* OUT: Result of comparison */ -){ - VdbeSorter *pSorter = pCsr->pSorter; - void *pKey; int nKey; /* Sorter key to compare pVal with */ - - pKey = vdbeSorterRowkey(pSorter, &nKey); - vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes); - return SQLITE_OK; -} - -/************** End of vdbesort.c ********************************************/ -/************** Begin file journal.c *****************************************/ -/* -** 2007 August 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements a special kind of sqlite3_file object used -** by SQLite to create journal files if the atomic-write optimization -** is enabled. -** -** The distinctive characteristic of this sqlite3_file is that the -** actual on disk file is created lazily. When the file is created, -** the caller specifies a buffer size for an in-memory buffer to -** be used to service read() and write() requests. The actual file -** on disk is not created or populated until either: -** -** 1) The in-memory representation grows too large for the allocated -** buffer, or -** 2) The sqlite3JournalCreate() function is called. -*/ -#ifdef SQLITE_ENABLE_ATOMIC_WRITE - - -/* -** A JournalFile object is a subclass of sqlite3_file used by -** as an open file handle for journal files. -*/ -struct JournalFile { - sqlite3_io_methods *pMethod; /* I/O methods on journal files */ - int nBuf; /* Size of zBuf[] in bytes */ - char *zBuf; /* Space to buffer journal writes */ - int iSize; /* Amount of zBuf[] currently used */ - int flags; /* xOpen flags */ - sqlite3_vfs *pVfs; /* The "real" underlying VFS */ - sqlite3_file *pReal; /* The "real" underlying file descriptor */ - const char *zJournal; /* Name of the journal file */ -}; -typedef struct JournalFile JournalFile; - -/* -** If it does not already exists, create and populate the on-disk file -** for JournalFile p. -*/ -static int createFile(JournalFile *p){ - int rc = SQLITE_OK; - if( !p->pReal ){ - sqlite3_file *pReal = (sqlite3_file *)&p[1]; - rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); - if( rc==SQLITE_OK ){ - p->pReal = pReal; - if( p->iSize>0 ){ - assert(p->iSize<=p->nBuf); - rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); - } - if( rc!=SQLITE_OK ){ - /* If an error occurred while writing to the file, close it before - ** returning. This way, SQLite uses the in-memory journal data to - ** roll back changes made to the internal page-cache before this - ** function was called. */ - sqlite3OsClose(pReal); - p->pReal = 0; - } - } - } - return rc; -} - -/* -** Close the file. -*/ -static int jrnlClose(sqlite3_file *pJfd){ - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - sqlite3OsClose(p->pReal); - } - sqlite3_free(p->zBuf); - return SQLITE_OK; -} - -/* -** Read data from the file. -*/ -static int jrnlRead( - sqlite3_file *pJfd, /* The journal file from which to read */ - void *zBuf, /* Put the results here */ - int iAmt, /* Number of bytes to read */ - sqlite_int64 iOfst /* Begin reading at this offset */ -){ - int rc = SQLITE_OK; - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); - }else if( (iAmt+iOfst)>p->iSize ){ - rc = SQLITE_IOERR_SHORT_READ; - }else{ - memcpy(zBuf, &p->zBuf[iOfst], iAmt); - } - return rc; -} - -/* -** Write data to the file. -*/ -static int jrnlWrite( - sqlite3_file *pJfd, /* The journal file into which to write */ - const void *zBuf, /* Take data to be written from here */ - int iAmt, /* Number of bytes to write */ - sqlite_int64 iOfst /* Begin writing at this offset into the file */ -){ - int rc = SQLITE_OK; - JournalFile *p = (JournalFile *)pJfd; - if( !p->pReal && (iOfst+iAmt)>p->nBuf ){ - rc = createFile(p); - } - if( rc==SQLITE_OK ){ - if( p->pReal ){ - rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); - }else{ - memcpy(&p->zBuf[iOfst], zBuf, iAmt); - if( p->iSize<(iOfst+iAmt) ){ - p->iSize = (iOfst+iAmt); - } - } - } - return rc; -} - -/* -** Truncate the file. -*/ -static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ - int rc = SQLITE_OK; - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - rc = sqlite3OsTruncate(p->pReal, size); - }else if( sizeiSize ){ - p->iSize = size; - } - return rc; -} - -/* -** Sync the file. -*/ -static int jrnlSync(sqlite3_file *pJfd, int flags){ - int rc; - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - rc = sqlite3OsSync(p->pReal, flags); - }else{ - rc = SQLITE_OK; - } - return rc; -} - -/* -** Query the size of the file in bytes. -*/ -static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ - int rc = SQLITE_OK; - JournalFile *p = (JournalFile *)pJfd; - if( p->pReal ){ - rc = sqlite3OsFileSize(p->pReal, pSize); - }else{ - *pSize = (sqlite_int64) p->iSize; - } - return rc; -} - -/* -** Table of methods for JournalFile sqlite3_file object. -*/ -static struct sqlite3_io_methods JournalFileMethods = { - 1, /* iVersion */ - jrnlClose, /* xClose */ - jrnlRead, /* xRead */ - jrnlWrite, /* xWrite */ - jrnlTruncate, /* xTruncate */ - jrnlSync, /* xSync */ - jrnlFileSize, /* xFileSize */ - 0, /* xLock */ - 0, /* xUnlock */ - 0, /* xCheckReservedLock */ - 0, /* xFileControl */ - 0, /* xSectorSize */ - 0, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0 /* xShmUnmap */ -}; - -/* -** Open a journal file. -*/ -SQLITE_PRIVATE int sqlite3JournalOpen( - sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ - const char *zName, /* Name of the journal file */ - sqlite3_file *pJfd, /* Preallocated, blank file handle */ - int flags, /* Opening flags */ - int nBuf /* Bytes buffered before opening the file */ -){ - JournalFile *p = (JournalFile *)pJfd; - memset(p, 0, sqlite3JournalSize(pVfs)); - if( nBuf>0 ){ - p->zBuf = sqlite3MallocZero(nBuf); - if( !p->zBuf ){ - return SQLITE_NOMEM; - } - }else{ - return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); - } - p->pMethod = &JournalFileMethods; - p->nBuf = nBuf; - p->flags = flags; - p->zJournal = zName; - p->pVfs = pVfs; - return SQLITE_OK; -} - -/* -** If the argument p points to a JournalFile structure, and the underlying -** file has not yet been created, create it now. -*/ -SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){ - if( p->pMethods!=&JournalFileMethods ){ - return SQLITE_OK; - } - return createFile((JournalFile *)p); -} - -/* -** The file-handle passed as the only argument is guaranteed to be an open -** file. It may or may not be of class JournalFile. If the file is a -** JournalFile, and the underlying file on disk has not yet been opened, -** return 0. Otherwise, return 1. -*/ -SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p){ - return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0); -} - -/* -** Return the number of bytes required to store a JournalFile that uses vfs -** pVfs to create the underlying on-disk files. -*/ -SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){ - return (pVfs->szOsFile+sizeof(JournalFile)); -} -#endif - -/************** End of journal.c *********************************************/ -/************** Begin file memjournal.c **************************************/ -/* -** 2008 October 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains code use to implement an in-memory rollback journal. -** The in-memory rollback journal is used to journal transactions for -** ":memory:" databases and when the journal_mode=MEMORY pragma is used. -*/ - -/* Forward references to internal structures */ -typedef struct MemJournal MemJournal; -typedef struct FilePoint FilePoint; -typedef struct FileChunk FileChunk; - -/* Space to hold the rollback journal is allocated in increments of -** this many bytes. -** -** The size chosen is a little less than a power of two. That way, -** the FileChunk object will have a size that almost exactly fills -** a power-of-two allocation. This mimimizes wasted space in power-of-two -** memory allocators. -*/ -#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*))) - -/* Macro to find the minimum of two numeric values. -*/ -#ifndef MIN -# define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -/* -** The rollback journal is composed of a linked list of these structures. -*/ -struct FileChunk { - FileChunk *pNext; /* Next chunk in the journal */ - u8 zChunk[JOURNAL_CHUNKSIZE]; /* Content of this chunk */ -}; - -/* -** An instance of this object serves as a cursor into the rollback journal. -** The cursor can be either for reading or writing. -*/ -struct FilePoint { - sqlite3_int64 iOffset; /* Offset from the beginning of the file */ - FileChunk *pChunk; /* Specific chunk into which cursor points */ -}; - -/* -** This subclass is a subclass of sqlite3_file. Each open memory-journal -** is an instance of this class. -*/ -struct MemJournal { - sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */ - FileChunk *pFirst; /* Head of in-memory chunk-list */ - FilePoint endpoint; /* Pointer to the end of the file */ - FilePoint readpoint; /* Pointer to the end of the last xRead() */ -}; - -/* -** Read data from the in-memory journal file. This is the implementation -** of the sqlite3_vfs.xRead method. -*/ -static int memjrnlRead( - sqlite3_file *pJfd, /* The journal file from which to read */ - void *zBuf, /* Put the results here */ - int iAmt, /* Number of bytes to read */ - sqlite_int64 iOfst /* Begin reading at this offset */ -){ - MemJournal *p = (MemJournal *)pJfd; - u8 *zOut = zBuf; - int nRead = iAmt; - int iChunkOffset; - FileChunk *pChunk; - - /* SQLite never tries to read past the end of a rollback journal file */ - assert( iOfst+iAmt<=p->endpoint.iOffset ); - - if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ - sqlite3_int64 iOff = 0; - for(pChunk=p->pFirst; - ALWAYS(pChunk) && (iOff+JOURNAL_CHUNKSIZE)<=iOfst; - pChunk=pChunk->pNext - ){ - iOff += JOURNAL_CHUNKSIZE; - } - }else{ - pChunk = p->readpoint.pChunk; - } - - iChunkOffset = (int)(iOfst%JOURNAL_CHUNKSIZE); - do { - int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset; - int nCopy = MIN(nRead, (JOURNAL_CHUNKSIZE - iChunkOffset)); - memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy); - zOut += nCopy; - nRead -= iSpace; - iChunkOffset = 0; - } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 ); - p->readpoint.iOffset = iOfst+iAmt; - p->readpoint.pChunk = pChunk; - - return SQLITE_OK; -} - -/* -** Write data to the file. -*/ -static int memjrnlWrite( - sqlite3_file *pJfd, /* The journal file into which to write */ - const void *zBuf, /* Take data to be written from here */ - int iAmt, /* Number of bytes to write */ - sqlite_int64 iOfst /* Begin writing at this offset into the file */ -){ - MemJournal *p = (MemJournal *)pJfd; - int nWrite = iAmt; - u8 *zWrite = (u8 *)zBuf; - - /* An in-memory journal file should only ever be appended to. Random - ** access writes are not required by sqlite. - */ - assert( iOfst==p->endpoint.iOffset ); - UNUSED_PARAMETER(iOfst); - - while( nWrite>0 ){ - FileChunk *pChunk = p->endpoint.pChunk; - int iChunkOffset = (int)(p->endpoint.iOffset%JOURNAL_CHUNKSIZE); - int iSpace = MIN(nWrite, JOURNAL_CHUNKSIZE - iChunkOffset); - - if( iChunkOffset==0 ){ - /* New chunk is required to extend the file. */ - FileChunk *pNew = sqlite3_malloc(sizeof(FileChunk)); - if( !pNew ){ - return SQLITE_IOERR_NOMEM; - } - pNew->pNext = 0; - if( pChunk ){ - assert( p->pFirst ); - pChunk->pNext = pNew; - }else{ - assert( !p->pFirst ); - p->pFirst = pNew; - } - p->endpoint.pChunk = pNew; - } - - memcpy(&p->endpoint.pChunk->zChunk[iChunkOffset], zWrite, iSpace); - zWrite += iSpace; - nWrite -= iSpace; - p->endpoint.iOffset += iSpace; - } - - return SQLITE_OK; -} - -/* -** Truncate the file. -*/ -static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ - MemJournal *p = (MemJournal *)pJfd; - FileChunk *pChunk; - assert(size==0); - UNUSED_PARAMETER(size); - pChunk = p->pFirst; - while( pChunk ){ - FileChunk *pTmp = pChunk; - pChunk = pChunk->pNext; - sqlite3_free(pTmp); - } - sqlite3MemJournalOpen(pJfd); - return SQLITE_OK; -} - -/* -** Close the file. -*/ -static int memjrnlClose(sqlite3_file *pJfd){ - memjrnlTruncate(pJfd, 0); - return SQLITE_OK; -} - - -/* -** Sync the file. -** -** Syncing an in-memory journal is a no-op. And, in fact, this routine -** is never called in a working implementation. This implementation -** exists purely as a contingency, in case some malfunction in some other -** part of SQLite causes Sync to be called by mistake. -*/ -static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - return SQLITE_OK; -} - -/* -** Query the size of the file in bytes. -*/ -static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ - MemJournal *p = (MemJournal *)pJfd; - *pSize = (sqlite_int64) p->endpoint.iOffset; - return SQLITE_OK; -} - -/* -** Table of methods for MemJournal sqlite3_file object. -*/ -static const struct sqlite3_io_methods MemJournalMethods = { - 1, /* iVersion */ - memjrnlClose, /* xClose */ - memjrnlRead, /* xRead */ - memjrnlWrite, /* xWrite */ - memjrnlTruncate, /* xTruncate */ - memjrnlSync, /* xSync */ - memjrnlFileSize, /* xFileSize */ - 0, /* xLock */ - 0, /* xUnlock */ - 0, /* xCheckReservedLock */ - 0, /* xFileControl */ - 0, /* xSectorSize */ - 0, /* xDeviceCharacteristics */ - 0, /* xShmMap */ - 0, /* xShmLock */ - 0, /* xShmBarrier */ - 0, /* xShmUnmap */ - 0, /* xFetch */ - 0 /* xUnfetch */ -}; - -/* -** Open a journal file. -*/ -SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){ - MemJournal *p = (MemJournal *)pJfd; - assert( EIGHT_BYTE_ALIGNMENT(p) ); - memset(p, 0, sqlite3MemJournalSize()); - p->pMethod = (sqlite3_io_methods*)&MemJournalMethods; -} - -/* -** Return true if the file-handle passed as an argument is -** an in-memory journal -*/ -SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *pJfd){ - return pJfd->pMethods==&MemJournalMethods; -} - -/* -** Return the number of bytes required to store a MemJournal file descriptor. -*/ -SQLITE_PRIVATE int sqlite3MemJournalSize(void){ - return sizeof(MemJournal); -} - -/************** End of memjournal.c ******************************************/ -/************** Begin file walker.c ******************************************/ -/* -** 2008 August 16 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains routines used for walking the parser tree for -** an SQL statement. -*/ -/* #include */ -/* #include */ - - -/* -** Walk an expression tree. Invoke the callback once for each node -** of the expression, while decending. (In other words, the callback -** is invoked before visiting children.) -** -** The return value from the callback should be one of the WRC_* -** constants to specify how to proceed with the walk. -** -** WRC_Continue Continue descending down the tree. -** -** WRC_Prune Do not descend into child nodes. But allow -** the walk to continue with sibling nodes. -** -** WRC_Abort Do no more callbacks. Unwind the stack and -** return the top-level walk call. -** -** The return value from this routine is WRC_Abort to abandon the tree walk -** and WRC_Continue to continue. -*/ -SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ - int rc; - if( pExpr==0 ) return WRC_Continue; - testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); - testcase( ExprHasProperty(pExpr, EP_Reduced) ); - rc = pWalker->xExprCallback(pWalker, pExpr); - if( rc==WRC_Continue - && !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){ - if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; - }else{ - if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; - } - } - return rc & WRC_Abort; -} - -/* -** Call sqlite3WalkExpr() for every expression in list p or until -** an abort request is seen. -*/ -SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){ - int i; - struct ExprList_item *pItem; - if( p ){ - for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){ - if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort; - } - } - return WRC_Continue; -} - -/* -** Walk all expressions associated with SELECT statement p. Do -** not invoke the SELECT callback on p, but do (of course) invoke -** any expr callbacks and SELECT callbacks that come from subqueries. -** Return WRC_Abort or WRC_Continue. -*/ -SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){ - if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort; - if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort; - if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort; - if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort; - return WRC_Continue; -} - -/* -** Walk the parse trees associated with all subqueries in the -** FROM clause of SELECT statement p. Do not invoke the select -** callback on p, but do invoke it on each FROM clause subquery -** and on any subqueries further down in the tree. Return -** WRC_Abort or WRC_Continue; -*/ -SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ - SrcList *pSrc; - int i; - struct SrcList_item *pItem; - - pSrc = p->pSrc; - if( ALWAYS(pSrc) ){ - for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){ - return WRC_Abort; - } - } - } - return WRC_Continue; -} - -/* -** Call sqlite3WalkExpr() for every expression in Select statement p. -** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and -** on the compound select chain, p->pPrior. Invoke the xSelectCallback() -** either before or after the walk of expressions and FROM clause, depending -** on whether pWalker->bSelectDepthFirst is false or true, respectively. -** -** Return WRC_Continue under normal conditions. Return WRC_Abort if -** there is an abort request. -** -** If the Walker does not have an xSelectCallback() then this routine -** is a no-op returning WRC_Continue. -*/ -SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ - int rc; - if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue; - rc = WRC_Continue; - pWalker->walkerDepth++; - while( p ){ - if( !pWalker->bSelectDepthFirst ){ - rc = pWalker->xSelectCallback(pWalker, p); - if( rc ) break; - } - if( sqlite3WalkSelectExpr(pWalker, p) - || sqlite3WalkSelectFrom(pWalker, p) - ){ - pWalker->walkerDepth--; - return WRC_Abort; - } - if( pWalker->bSelectDepthFirst ){ - rc = pWalker->xSelectCallback(pWalker, p); - /* Depth-first search is currently only used for - ** selectAddSubqueryTypeInfo() and that routine always returns - ** WRC_Continue (0). So the following branch is never taken. */ - if( NEVER(rc) ) break; - } - p = p->pPrior; - } - pWalker->walkerDepth--; - return rc & WRC_Abort; -} - -/************** End of walker.c **********************************************/ -/************** Begin file resolve.c *****************************************/ -/* -** 2008 August 18 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains routines used for walking the parser tree and -** resolve all identifiers by associating them with a particular -** table and column. -*/ -/* #include */ -/* #include */ - -/* -** Walk the expression tree pExpr and increase the aggregate function -** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node. -** This needs to occur when copying a TK_AGG_FUNCTION node from an -** outer query into an inner subquery. -** -** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..) -** is a helper function - a callback for the tree walker. -*/ -static int incrAggDepth(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.i; - return WRC_Continue; -} -static void incrAggFunctionDepth(Expr *pExpr, int N){ - if( N>0 ){ - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = incrAggDepth; - w.u.i = N; - sqlite3WalkExpr(&w, pExpr); - } -} - -/* -** Turn the pExpr expression into an alias for the iCol-th column of the -** result set in pEList. -** -** If the result set column is a simple column reference, then this routine -** makes an exact copy. But for any other kind of expression, this -** routine make a copy of the result set column as the argument to the -** TK_AS operator. The TK_AS operator causes the expression to be -** evaluated just once and then reused for each alias. -** -** The reason for suppressing the TK_AS term when the expression is a simple -** column reference is so that the column reference will be recognized as -** usable by indices within the WHERE clause processing logic. -** -** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means -** that in a GROUP BY clause, the expression is evaluated twice. Hence: -** -** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x -** -** Is equivalent to: -** -** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 -** -** The result of random()%5 in the GROUP BY clause is probably different -** from the result in the result-set. We might fix this someday. Or -** then again, we might not... -** -** If the reference is followed by a COLLATE operator, then make sure -** the COLLATE operator is preserved. For example: -** -** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase; -** -** Should be transformed into: -** -** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; -** -** The nSubquery parameter specifies how many levels of subquery the -** alias is removed from the original expression. The usually value is -** zero but it might be more if the alias is contained within a subquery -** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION -** structures must be increased by the nSubquery amount. -*/ -static void resolveAlias( - Parse *pParse, /* Parsing context */ - ExprList *pEList, /* A result set */ - int iCol, /* A column in the result set. 0..pEList->nExpr-1 */ - Expr *pExpr, /* Transform this into an alias to the result set */ - const char *zType, /* "GROUP" or "ORDER" or "" */ - int nSubquery /* Number of subqueries that the label is moving */ -){ - Expr *pOrig; /* The iCol-th column of the result set */ - Expr *pDup; /* Copy of pOrig */ - sqlite3 *db; /* The database connection */ - - assert( iCol>=0 && iColnExpr ); - pOrig = pEList->a[iCol].pExpr; - assert( pOrig!=0 ); - assert( pOrig->flags & EP_Resolved ); - db = pParse->db; - pDup = sqlite3ExprDup(db, pOrig, 0); - if( pDup==0 ) return; - if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ - incrAggFunctionDepth(pDup, nSubquery); - pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); - if( pDup==0 ) return; - if( pEList->a[iCol].iAlias==0 ){ - pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); - } - pDup->iTable = pEList->a[iCol].iAlias; - } - if( pExpr->op==TK_COLLATE ){ - pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); - } - - /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This - ** prevents ExprDelete() from deleting the Expr structure itself, - ** allowing it to be repopulated by the memcpy() on the following line. - ** The pExpr->u.zToken might point into memory that will be freed by the - ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to - ** make a copy of the token before doing the sqlite3DbFree(). - */ - ExprSetProperty(pExpr, EP_Static); - sqlite3ExprDelete(db, pExpr); - memcpy(pExpr, pDup, sizeof(*pExpr)); - if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ - assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); - pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); - pExpr->flags2 |= EP2_MallocedToken; - } - sqlite3DbFree(db, pDup); -} - - -/* -** Return TRUE if the name zCol occurs anywhere in the USING clause. -** -** Return FALSE if the USING clause is NULL or if it does not contain -** zCol. -*/ -static int nameInUsingClause(IdList *pUsing, const char *zCol){ - if( pUsing ){ - int k; - for(k=0; knId; k++){ - if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1; - } - } - return 0; -} - -/* -** Subqueries stores the original database, table and column names for their -** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". -** Check to see if the zSpan given to this routine matches the zDb, zTab, -** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will -** match anything. -*/ -SQLITE_PRIVATE int sqlite3MatchSpanName( - const char *zSpan, - const char *zCol, - const char *zTab, - const char *zDb -){ - int n; - for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} - if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){ - return 0; - } - zSpan += n+1; - for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} - if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){ - return 0; - } - zSpan += n+1; - if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ - return 0; - } - return 1; -} - -/* -** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up -** that name in the set of source tables in pSrcList and make the pExpr -** expression node refer back to that source column. The following changes -** are made to pExpr: -** -** pExpr->iDb Set the index in db->aDb[] of the database X -** (even if X is implied). -** pExpr->iTable Set to the cursor number for the table obtained -** from pSrcList. -** pExpr->pTab Points to the Table structure of X.Y (even if -** X and/or Y are implied.) -** pExpr->iColumn Set to the column number within the table. -** pExpr->op Set to TK_COLUMN. -** pExpr->pLeft Any expression this points to is deleted -** pExpr->pRight Any expression this points to is deleted. -** -** The zDb variable is the name of the database (the "X"). This value may be -** NULL meaning that name is of the form Y.Z or Z. Any available database -** can be used. The zTable variable is the name of the table (the "Y"). This -** value can be NULL if zDb is also NULL. If zTable is NULL it -** means that the form of the name is Z and that columns from any table -** can be used. -** -** If the name cannot be resolved unambiguously, leave an error message -** in pParse and return WRC_Abort. Return WRC_Prune on success. -*/ -static int lookupName( - Parse *pParse, /* The parsing context */ - const char *zDb, /* Name of the database containing table, or NULL */ - const char *zTab, /* Name of table containing column, or NULL */ - const char *zCol, /* Name of the column. */ - NameContext *pNC, /* The name context used to resolve the name */ - Expr *pExpr /* Make this EXPR node point to the selected column */ -){ - int i, j; /* Loop counters */ - int cnt = 0; /* Number of matching column names */ - int cntTab = 0; /* Number of matching table names */ - int nSubquery = 0; /* How many levels of subquery */ - sqlite3 *db = pParse->db; /* The database connection */ - struct SrcList_item *pItem; /* Use for looping over pSrcList items */ - struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ - NameContext *pTopNC = pNC; /* First namecontext in the list */ - Schema *pSchema = 0; /* Schema of the expression */ - int isTrigger = 0; - - assert( pNC ); /* the name context cannot be NULL. */ - assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ - assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); - - /* Initialize the node to no-match */ - pExpr->iTable = -1; - pExpr->pTab = 0; - ExprSetIrreducible(pExpr); - - /* Translate the schema name in zDb into a pointer to the corresponding - ** schema. If not found, pSchema will remain NULL and nothing will match - ** resulting in an appropriate error message toward the end of this routine - */ - if( zDb ){ - for(i=0; inDb; i++){ - assert( db->aDb[i].zName ); - if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ - pSchema = db->aDb[i].pSchema; - break; - } - } - } - - /* Start at the inner-most context and move outward until a match is found */ - while( pNC && cnt==0 ){ - ExprList *pEList; - SrcList *pSrcList = pNC->pSrcList; - - if( pSrcList ){ - for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ - Table *pTab; - Column *pCol; - - pTab = pItem->pTab; - assert( pTab!=0 && pTab->zName!=0 ); - assert( pTab->nCol>0 ); - if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ - int hit = 0; - pEList = pItem->pSelect->pEList; - for(j=0; jnExpr; j++){ - if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){ - cnt++; - cntTab = 2; - pMatch = pItem; - pExpr->iColumn = j; - hit = 1; - } - } - if( hit || zTab==0 ) continue; - } - if( zDb && pTab->pSchema!=pSchema ){ - continue; - } - if( zTab ){ - const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; - assert( zTabName!=0 ); - if( sqlite3StrICmp(zTabName, zTab)!=0 ){ - continue; - } - } - if( 0==(cntTab++) ){ - pMatch = pItem; - } - for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ - if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ - /* If there has been exactly one prior match and this match - ** is for the right-hand table of a NATURAL JOIN or is in a - ** USING clause, then skip this match. - */ - if( cnt==1 ){ - if( pItem->jointype & JT_NATURAL ) continue; - if( nameInUsingClause(pItem->pUsing, zCol) ) continue; - } - cnt++; - pMatch = pItem; - /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ - pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; - break; - } - } - } - if( pMatch ){ - pExpr->iTable = pMatch->iCursor; - pExpr->pTab = pMatch->pTab; - pSchema = pExpr->pTab->pSchema; - } - } /* if( pSrcList ) */ - -#ifndef SQLITE_OMIT_TRIGGER - /* If we have not already resolved the name, then maybe - ** it is a new.* or old.* trigger argument reference - */ - if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){ - int op = pParse->eTriggerOp; - Table *pTab = 0; - assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); - if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ - pExpr->iTable = 1; - pTab = pParse->pTriggerTab; - }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ - pExpr->iTable = 0; - pTab = pParse->pTriggerTab; - } - - if( pTab ){ - int iCol; - pSchema = pTab->pSchema; - cntTab++; - for(iCol=0; iColnCol; iCol++){ - Column *pCol = &pTab->aCol[iCol]; - if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ - if( iCol==pTab->iPKey ){ - iCol = -1; - } - break; - } - } - if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) ){ - iCol = -1; /* IMP: R-44911-55124 */ - } - if( iColnCol ){ - cnt++; - if( iCol<0 ){ - pExpr->affinity = SQLITE_AFF_INTEGER; - }else if( pExpr->iTable==0 ){ - testcase( iCol==31 ); - testcase( iCol==32 ); - pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<iColumn = (i16)iCol; - pExpr->pTab = pTab; - isTrigger = 1; - } - } - } -#endif /* !defined(SQLITE_OMIT_TRIGGER) */ - - /* - ** Perhaps the name is a reference to the ROWID - */ - if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){ - cnt = 1; - pExpr->iColumn = -1; /* IMP: R-44911-55124 */ - pExpr->affinity = SQLITE_AFF_INTEGER; - } - - /* - ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z - ** might refer to an result-set alias. This happens, for example, when - ** we are resolving names in the WHERE clause of the following command: - ** - ** SELECT a+b AS x FROM table WHERE x<10; - ** - ** In cases like this, replace pExpr with a copy of the expression that - ** forms the result set entry ("a+b" in the example) and return immediately. - ** Note that the expression in the result set should have already been - ** resolved by the time the WHERE clause is resolved. - */ - if( (pEList = pNC->pEList)!=0 - && zTab==0 - && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0) - ){ - for(j=0; jnExpr; j++){ - char *zAs = pEList->a[j].zName; - if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ - Expr *pOrig; - assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - assert( pExpr->x.pList==0 ); - assert( pExpr->x.pSelect==0 ); - pOrig = pEList->a[j].pExpr; - if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ - sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); - return WRC_Abort; - } - resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); - cnt = 1; - pMatch = 0; - assert( zTab==0 && zDb==0 ); - goto lookupname_end; - } - } - } - - /* Advance to the next name context. The loop will exit when either - ** we have a match (cnt>0) or when we run out of name contexts. - */ - if( cnt==0 ){ - pNC = pNC->pNext; - nSubquery++; - } - } - - /* - ** If X and Y are NULL (in other words if only the column name Z is - ** supplied) and the value of Z is enclosed in double-quotes, then - ** Z is a string literal if it doesn't match any column names. In that - ** case, we need to return right away and not make any changes to - ** pExpr. - ** - ** Because no reference was made to outer contexts, the pNC->nRef - ** fields are not changed in any context. - */ - if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){ - pExpr->op = TK_STRING; - pExpr->pTab = 0; - return WRC_Prune; - } - - /* - ** cnt==0 means there was not match. cnt>1 means there were two or - ** more matches. Either way, we have an error. - */ - if( cnt!=1 ){ - const char *zErr; - zErr = cnt==0 ? "no such column" : "ambiguous column name"; - if( zDb ){ - sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); - }else if( zTab ){ - sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); - }else{ - sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); - } - pParse->checkSchema = 1; - pTopNC->nErr++; - } - - /* If a column from a table in pSrcList is referenced, then record - ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes - ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the - ** column number is greater than the number of bits in the bitmask - ** then set the high-order bit of the bitmask. - */ - if( pExpr->iColumn>=0 && pMatch!=0 ){ - int n = pExpr->iColumn; - testcase( n==BMS-1 ); - if( n>=BMS ){ - n = BMS-1; - } - assert( pMatch->iCursor==pExpr->iTable ); - pMatch->colUsed |= ((Bitmask)1)<pLeft); - pExpr->pLeft = 0; - sqlite3ExprDelete(db, pExpr->pRight); - pExpr->pRight = 0; - pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); -lookupname_end: - if( cnt==1 ){ - assert( pNC!=0 ); - if( pExpr->op!=TK_AS ){ - sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); - } - /* Increment the nRef value on all name contexts from TopNC up to - ** the point where the name matched. */ - for(;;){ - assert( pTopNC!=0 ); - pTopNC->nRef++; - if( pTopNC==pNC ) break; - pTopNC = pTopNC->pNext; - } - return WRC_Prune; - } else { - return WRC_Abort; - } -} - -/* -** Allocate and return a pointer to an expression to load the column iCol -** from datasource iSrc in SrcList pSrc. -*/ -SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){ - Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); - if( p ){ - struct SrcList_item *pItem = &pSrc->a[iSrc]; - p->pTab = pItem->pTab; - p->iTable = pItem->iCursor; - if( p->pTab->iPKey==iCol ){ - p->iColumn = -1; - }else{ - p->iColumn = (ynVar)iCol; - testcase( iCol==BMS ); - testcase( iCol==BMS-1 ); - pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); - } - ExprSetProperty(p, EP_Resolved); - } - return p; -} - -/* -** This routine is callback for sqlite3WalkExpr(). -** -** Resolve symbolic names into TK_COLUMN operators for the current -** node in the expression tree. Return 0 to continue the search down -** the tree or 2 to abort the tree walk. -** -** This routine also does error checking and name resolution for -** function names. The operator for aggregate functions is changed -** to TK_AGG_FUNCTION. -*/ -static int resolveExprStep(Walker *pWalker, Expr *pExpr){ - NameContext *pNC; - Parse *pParse; - - pNC = pWalker->u.pNC; - assert( pNC!=0 ); - pParse = pNC->pParse; - assert( pParse==pWalker->pParse ); - - if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune; - ExprSetProperty(pExpr, EP_Resolved); -#ifndef NDEBUG - if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ - SrcList *pSrcList = pNC->pSrcList; - int i; - for(i=0; ipSrcList->nSrc; i++){ - assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab); - } - } -#endif - switch( pExpr->op ){ - -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) - /* The special operator TK_ROW means use the rowid for the first - ** column in the FROM clause. This is used by the LIMIT and ORDER BY - ** clause processing on UPDATE and DELETE statements. - */ - case TK_ROW: { - SrcList *pSrcList = pNC->pSrcList; - struct SrcList_item *pItem; - assert( pSrcList && pSrcList->nSrc==1 ); - pItem = pSrcList->a; - pExpr->op = TK_COLUMN; - pExpr->pTab = pItem->pTab; - pExpr->iTable = pItem->iCursor; - pExpr->iColumn = -1; - pExpr->affinity = SQLITE_AFF_INTEGER; - break; - } -#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ - - /* A lone identifier is the name of a column. - */ - case TK_ID: { - return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr); - } - - /* A table name and column name: ID.ID - ** Or a database, table and column: ID.ID.ID - */ - case TK_DOT: { - const char *zColumn; - const char *zTable; - const char *zDb; - Expr *pRight; - - /* if( pSrcList==0 ) break; */ - pRight = pExpr->pRight; - if( pRight->op==TK_ID ){ - zDb = 0; - zTable = pExpr->pLeft->u.zToken; - zColumn = pRight->u.zToken; - }else{ - assert( pRight->op==TK_DOT ); - zDb = pExpr->pLeft->u.zToken; - zTable = pRight->pLeft->u.zToken; - zColumn = pRight->pRight->u.zToken; - } - return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); - } - - /* Resolve function names - */ - case TK_CONST_FUNC: - case TK_FUNCTION: { - ExprList *pList = pExpr->x.pList; /* The argument list */ - int n = pList ? pList->nExpr : 0; /* Number of arguments */ - int no_such_func = 0; /* True if no such function exists */ - int wrong_num_args = 0; /* True if wrong number of arguments */ - int is_agg = 0; /* True if is an aggregate function */ - int auth; /* Authorization to use the function */ - int nId; /* Number of characters in function name */ - const char *zId; /* The function name. */ - FuncDef *pDef; /* Information about the function */ - u8 enc = ENC(pParse->db); /* The database encoding */ - - testcase( pExpr->op==TK_CONST_FUNC ); - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - zId = pExpr->u.zToken; - nId = sqlite3Strlen30(zId); - pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); - if( pDef==0 ){ - pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); - if( pDef==0 ){ - no_such_func = 1; - }else{ - wrong_num_args = 1; - } - }else{ - is_agg = pDef->xFunc==0; - } -#ifndef SQLITE_OMIT_AUTHORIZATION - if( pDef ){ - auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); - if( auth!=SQLITE_OK ){ - if( auth==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized to use function: %s", - pDef->zName); - pNC->nErr++; - } - pExpr->op = TK_NULL; - return WRC_Prune; - } - } -#endif - if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ - sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); - pNC->nErr++; - is_agg = 0; - }else if( no_such_func && pParse->db->init.busy==0 ){ - sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); - pNC->nErr++; - }else if( wrong_num_args ){ - sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", - nId, zId); - pNC->nErr++; - } - if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg; - sqlite3WalkExprList(pWalker, pList); - if( is_agg ){ - NameContext *pNC2 = pNC; - pExpr->op = TK_AGG_FUNCTION; - pExpr->op2 = 0; - while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ - pExpr->op2++; - pNC2 = pNC2->pNext; - } - if( pNC2 ) pNC2->ncFlags |= NC_HasAgg; - pNC->ncFlags |= NC_AllowAgg; - } - /* FIX ME: Compute pExpr->affinity based on the expected return - ** type of the function - */ - return WRC_Prune; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_SELECT: - case TK_EXISTS: testcase( pExpr->op==TK_EXISTS ); -#endif - case TK_IN: { - testcase( pExpr->op==TK_IN ); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - int nRef = pNC->nRef; -#ifndef SQLITE_OMIT_CHECK - if( (pNC->ncFlags & NC_IsCheck)!=0 ){ - sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); - } -#endif - sqlite3WalkSelect(pWalker, pExpr->x.pSelect); - assert( pNC->nRef>=nRef ); - if( nRef!=pNC->nRef ){ - ExprSetProperty(pExpr, EP_VarSelect); - } - } - break; - } -#ifndef SQLITE_OMIT_CHECK - case TK_VARIABLE: { - if( (pNC->ncFlags & NC_IsCheck)!=0 ){ - sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints"); - } - break; - } -#endif - } - return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; -} - -/* -** pEList is a list of expressions which are really the result set of the -** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause. -** This routine checks to see if pE is a simple identifier which corresponds -** to the AS-name of one of the terms of the expression list. If it is, -** this routine return an integer between 1 and N where N is the number of -** elements in pEList, corresponding to the matching entry. If there is -** no match, or if pE is not a simple identifier, then this routine -** return 0. -** -** pEList has been resolved. pE has not. -*/ -static int resolveAsName( - Parse *pParse, /* Parsing context for error messages */ - ExprList *pEList, /* List of expressions to scan */ - Expr *pE /* Expression we are trying to match */ -){ - int i; /* Loop counter */ - - UNUSED_PARAMETER(pParse); - - if( pE->op==TK_ID ){ - char *zCol = pE->u.zToken; - for(i=0; inExpr; i++){ - char *zAs = pEList->a[i].zName; - if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ - return i+1; - } - } - } - return 0; -} - -/* -** pE is a pointer to an expression which is a single term in the -** ORDER BY of a compound SELECT. The expression has not been -** name resolved. -** -** At the point this routine is called, we already know that the -** ORDER BY term is not an integer index into the result set. That -** case is handled by the calling routine. -** -** Attempt to match pE against result set columns in the left-most -** SELECT statement. Return the index i of the matching column, -** as an indication to the caller that it should sort by the i-th column. -** The left-most column is 1. In other words, the value returned is the -** same integer value that would be used in the SQL statement to indicate -** the column. -** -** If there is no match, return 0. Return -1 if an error occurs. -*/ -static int resolveOrderByTermToExprList( - Parse *pParse, /* Parsing context for error messages */ - Select *pSelect, /* The SELECT statement with the ORDER BY clause */ - Expr *pE /* The specific ORDER BY term */ -){ - int i; /* Loop counter */ - ExprList *pEList; /* The columns of the result set */ - NameContext nc; /* Name context for resolving pE */ - sqlite3 *db; /* Database connection */ - int rc; /* Return code from subprocedures */ - u8 savedSuppErr; /* Saved value of db->suppressErr */ - - assert( sqlite3ExprIsInteger(pE, &i)==0 ); - pEList = pSelect->pEList; - - /* Resolve all names in the ORDER BY term expression - */ - memset(&nc, 0, sizeof(nc)); - nc.pParse = pParse; - nc.pSrcList = pSelect->pSrc; - nc.pEList = pEList; - nc.ncFlags = NC_AllowAgg; - nc.nErr = 0; - db = pParse->db; - savedSuppErr = db->suppressErr; - db->suppressErr = 1; - rc = sqlite3ResolveExprNames(&nc, pE); - db->suppressErr = savedSuppErr; - if( rc ) return 0; - - /* Try to match the ORDER BY expression against an expression - ** in the result set. Return an 1-based index of the matching - ** result-set entry. - */ - for(i=0; inExpr; i++){ - if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){ - return i+1; - } - } - - /* If no match, return 0. */ - return 0; -} - -/* -** Generate an ORDER BY or GROUP BY term out-of-range error. -*/ -static void resolveOutOfRangeError( - Parse *pParse, /* The error context into which to write the error */ - const char *zType, /* "ORDER" or "GROUP" */ - int i, /* The index (1-based) of the term out of range */ - int mx /* Largest permissible value of i */ -){ - sqlite3ErrorMsg(pParse, - "%r %s BY term out of range - should be " - "between 1 and %d", i, zType, mx); -} - -/* -** Analyze the ORDER BY clause in a compound SELECT statement. Modify -** each term of the ORDER BY clause is a constant integer between 1 -** and N where N is the number of columns in the compound SELECT. -** -** ORDER BY terms that are already an integer between 1 and N are -** unmodified. ORDER BY terms that are integers outside the range of -** 1 through N generate an error. ORDER BY terms that are expressions -** are matched against result set expressions of compound SELECT -** beginning with the left-most SELECT and working toward the right. -** At the first match, the ORDER BY expression is transformed into -** the integer column number. -** -** Return the number of errors seen. -*/ -static int resolveCompoundOrderBy( - Parse *pParse, /* Parsing context. Leave error messages here */ - Select *pSelect /* The SELECT statement containing the ORDER BY */ -){ - int i; - ExprList *pOrderBy; - ExprList *pEList; - sqlite3 *db; - int moreToDo = 1; - - pOrderBy = pSelect->pOrderBy; - if( pOrderBy==0 ) return 0; - db = pParse->db; -#if SQLITE_MAX_COLUMN - if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); - return 1; - } -#endif - for(i=0; inExpr; i++){ - pOrderBy->a[i].done = 0; - } - pSelect->pNext = 0; - while( pSelect->pPrior ){ - pSelect->pPrior->pNext = pSelect; - pSelect = pSelect->pPrior; - } - while( pSelect && moreToDo ){ - struct ExprList_item *pItem; - moreToDo = 0; - pEList = pSelect->pEList; - assert( pEList!=0 ); - for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ - int iCol = -1; - Expr *pE, *pDup; - if( pItem->done ) continue; - pE = sqlite3ExprSkipCollate(pItem->pExpr); - if( sqlite3ExprIsInteger(pE, &iCol) ){ - if( iCol<=0 || iCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); - return 1; - } - }else{ - iCol = resolveAsName(pParse, pEList, pE); - if( iCol==0 ){ - pDup = sqlite3ExprDup(db, pE, 0); - if( !db->mallocFailed ){ - assert(pDup); - iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); - } - sqlite3ExprDelete(db, pDup); - } - } - if( iCol>0 ){ - /* Convert the ORDER BY term into an integer column number iCol, - ** taking care to preserve the COLLATE clause if it exists */ - Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); - if( pNew==0 ) return 1; - pNew->flags |= EP_IntValue; - pNew->u.iValue = iCol; - if( pItem->pExpr==pE ){ - pItem->pExpr = pNew; - }else{ - assert( pItem->pExpr->op==TK_COLLATE ); - assert( pItem->pExpr->pLeft==pE ); - pItem->pExpr->pLeft = pNew; - } - sqlite3ExprDelete(db, pE); - pItem->iOrderByCol = (u16)iCol; - pItem->done = 1; - }else{ - moreToDo = 1; - } - } - pSelect = pSelect->pNext; - } - for(i=0; inExpr; i++){ - if( pOrderBy->a[i].done==0 ){ - sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any " - "column in the result set", i+1); - return 1; - } - } - return 0; -} - -/* -** Check every term in the ORDER BY or GROUP BY clause pOrderBy of -** the SELECT statement pSelect. If any term is reference to a -** result set expression (as determined by the ExprList.a.iCol field) -** then convert that term into a copy of the corresponding result set -** column. -** -** If any errors are detected, add an error message to pParse and -** return non-zero. Return zero if no errors are seen. -*/ -SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy( - Parse *pParse, /* Parsing context. Leave error messages here */ - Select *pSelect, /* The SELECT statement containing the clause */ - ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ - const char *zType /* "ORDER" or "GROUP" */ -){ - int i; - sqlite3 *db = pParse->db; - ExprList *pEList; - struct ExprList_item *pItem; - - if( pOrderBy==0 || pParse->db->mallocFailed ) return 0; -#if SQLITE_MAX_COLUMN - if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); - return 1; - } -#endif - pEList = pSelect->pEList; - assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */ - for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ - if( pItem->iOrderByCol ){ - if( pItem->iOrderByCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); - return 1; - } - resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0); - } - } - return 0; -} - -/* -** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. -** The Name context of the SELECT statement is pNC. zType is either -** "ORDER" or "GROUP" depending on which type of clause pOrderBy is. -** -** This routine resolves each term of the clause into an expression. -** If the order-by term is an integer I between 1 and N (where N is the -** number of columns in the result set of the SELECT) then the expression -** in the resolution is a copy of the I-th result-set expression. If -** the order-by term is an identify that corresponds to the AS-name of -** a result-set expression, then the term resolves to a copy of the -** result-set expression. Otherwise, the expression is resolved in -** the usual way - using sqlite3ResolveExprNames(). -** -** This routine returns the number of errors. If errors occur, then -** an appropriate error message might be left in pParse. (OOM errors -** excepted.) -*/ -static int resolveOrderGroupBy( - NameContext *pNC, /* The name context of the SELECT statement */ - Select *pSelect, /* The SELECT statement holding pOrderBy */ - ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */ - const char *zType /* Either "ORDER" or "GROUP", as appropriate */ -){ - int i, j; /* Loop counters */ - int iCol; /* Column number */ - struct ExprList_item *pItem; /* A term of the ORDER BY clause */ - Parse *pParse; /* Parsing context */ - int nResult; /* Number of terms in the result set */ - - if( pOrderBy==0 ) return 0; - nResult = pSelect->pEList->nExpr; - pParse = pNC->pParse; - for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ - Expr *pE = pItem->pExpr; - iCol = resolveAsName(pParse, pSelect->pEList, pE); - if( iCol>0 ){ - /* If an AS-name match is found, mark this ORDER BY column as being - ** a copy of the iCol-th result-set column. The subsequent call to - ** sqlite3ResolveOrderGroupBy() will convert the expression to a - ** copy of the iCol-th result-set expression. */ - pItem->iOrderByCol = (u16)iCol; - continue; - } - if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){ - /* The ORDER BY term is an integer constant. Again, set the column - ** number so that sqlite3ResolveOrderGroupBy() will convert the - ** order-by term to a copy of the result-set expression */ - if( iCol<1 || iCol>0xffff ){ - resolveOutOfRangeError(pParse, zType, i+1, nResult); - return 1; - } - pItem->iOrderByCol = (u16)iCol; - continue; - } - - /* Otherwise, treat the ORDER BY term as an ordinary expression */ - pItem->iOrderByCol = 0; - if( sqlite3ResolveExprNames(pNC, pE) ){ - return 1; - } - for(j=0; jpEList->nExpr; j++){ - if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr)==0 ){ - pItem->iOrderByCol = j+1; - } - } - } - return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType); -} - -/* -** Resolve names in the SELECT statement p and all of its descendents. -*/ -static int resolveSelectStep(Walker *pWalker, Select *p){ - NameContext *pOuterNC; /* Context that contains this SELECT */ - NameContext sNC; /* Name context of this SELECT */ - int isCompound; /* True if p is a compound select */ - int nCompound; /* Number of compound terms processed so far */ - Parse *pParse; /* Parsing context */ - ExprList *pEList; /* Result set expression list */ - int i; /* Loop counter */ - ExprList *pGroupBy; /* The GROUP BY clause */ - Select *pLeftmost; /* Left-most of SELECT of a compound */ - sqlite3 *db; /* Database connection */ - - - assert( p!=0 ); - if( p->selFlags & SF_Resolved ){ - return WRC_Prune; - } - pOuterNC = pWalker->u.pNC; - pParse = pWalker->pParse; - db = pParse->db; - - /* Normally sqlite3SelectExpand() will be called first and will have - ** already expanded this SELECT. However, if this is a subquery within - ** an expression, sqlite3ResolveExprNames() will be called without a - ** prior call to sqlite3SelectExpand(). When that happens, let - ** sqlite3SelectPrep() do all of the processing for this SELECT. - ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and - ** this routine in the correct order. - */ - if( (p->selFlags & SF_Expanded)==0 ){ - sqlite3SelectPrep(pParse, p, pOuterNC); - return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune; - } - - isCompound = p->pPrior!=0; - nCompound = 0; - pLeftmost = p; - while( p ){ - assert( (p->selFlags & SF_Expanded)!=0 ); - assert( (p->selFlags & SF_Resolved)==0 ); - p->selFlags |= SF_Resolved; - - /* Resolve the expressions in the LIMIT and OFFSET clauses. These - ** are not allowed to refer to any names, so pass an empty NameContext. - */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - if( sqlite3ResolveExprNames(&sNC, p->pLimit) || - sqlite3ResolveExprNames(&sNC, p->pOffset) ){ - return WRC_Abort; - } - - /* Recursively resolve names in all subqueries - */ - for(i=0; ipSrc->nSrc; i++){ - struct SrcList_item *pItem = &p->pSrc->a[i]; - if( pItem->pSelect ){ - NameContext *pNC; /* Used to iterate name contexts */ - int nRef = 0; /* Refcount for pOuterNC and outer contexts */ - const char *zSavedContext = pParse->zAuthContext; - - /* Count the total number of references to pOuterNC and all of its - ** parent contexts. After resolving references to expressions in - ** pItem->pSelect, check if this value has changed. If so, then - ** SELECT statement pItem->pSelect must be correlated. Set the - ** pItem->isCorrelated flag if this is the case. */ - for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef; - - if( pItem->zName ) pParse->zAuthContext = pItem->zName; - sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC); - pParse->zAuthContext = zSavedContext; - if( pParse->nErr || db->mallocFailed ) return WRC_Abort; - - for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; - assert( pItem->isCorrelated==0 && nRef<=0 ); - pItem->isCorrelated = (nRef!=0); - } - } - - /* Set up the local name-context to pass to sqlite3ResolveExprNames() to - ** resolve the result-set expression list. - */ - sNC.ncFlags = NC_AllowAgg; - sNC.pSrcList = p->pSrc; - sNC.pNext = pOuterNC; - - /* Resolve names in the result set. */ - pEList = p->pEList; - assert( pEList!=0 ); - for(i=0; inExpr; i++){ - Expr *pX = pEList->a[i].pExpr; - if( sqlite3ResolveExprNames(&sNC, pX) ){ - return WRC_Abort; - } - } - - /* If there are no aggregate functions in the result-set, and no GROUP BY - ** expression, do not allow aggregates in any of the other expressions. - */ - assert( (p->selFlags & SF_Aggregate)==0 ); - pGroupBy = p->pGroupBy; - if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ - p->selFlags |= SF_Aggregate; - }else{ - sNC.ncFlags &= ~NC_AllowAgg; - } - - /* If a HAVING clause is present, then there must be a GROUP BY clause. - */ - if( p->pHaving && !pGroupBy ){ - sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); - return WRC_Abort; - } - - /* Add the expression list to the name-context before parsing the - ** other expressions in the SELECT statement. This is so that - ** expressions in the WHERE clause (etc.) can refer to expressions by - ** aliases in the result set. - ** - ** Minor point: If this is the case, then the expression will be - ** re-evaluated for each reference to it. - */ - sNC.pEList = p->pEList; - sNC.ncFlags |= NC_AsMaybe; - if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; - if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; - sNC.ncFlags &= ~NC_AsMaybe; - - /* The ORDER BY and GROUP BY clauses may not refer to terms in - ** outer queries - */ - sNC.pNext = 0; - sNC.ncFlags |= NC_AllowAgg; - - /* Process the ORDER BY clause for singleton SELECT statements. - ** The ORDER BY clause for compounds SELECT statements is handled - ** below, after all of the result-sets for all of the elements of - ** the compound have been resolved. - */ - if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){ - return WRC_Abort; - } - if( db->mallocFailed ){ - return WRC_Abort; - } - - /* Resolve the GROUP BY clause. At the same time, make sure - ** the GROUP BY clause does not contain aggregate functions. - */ - if( pGroupBy ){ - struct ExprList_item *pItem; - - if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){ - return WRC_Abort; - } - for(i=0, pItem=pGroupBy->a; inExpr; i++, pItem++){ - if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ - sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " - "the GROUP BY clause"); - return WRC_Abort; - } - } - } - - /* Advance to the next term of the compound - */ - p = p->pPrior; - nCompound++; - } - - /* Resolve the ORDER BY on a compound SELECT after all terms of - ** the compound have been resolved. - */ - if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){ - return WRC_Abort; - } - - return WRC_Prune; -} - -/* -** This routine walks an expression tree and resolves references to -** table columns and result-set columns. At the same time, do error -** checking on function usage and set a flag if any aggregate functions -** are seen. -** -** To resolve table columns references we look for nodes (or subtrees) of the -** form X.Y.Z or Y.Z or just Z where -** -** X: The name of a database. Ex: "main" or "temp" or -** the symbolic name assigned to an ATTACH-ed database. -** -** Y: The name of a table in a FROM clause. Or in a trigger -** one of the special names "old" or "new". -** -** Z: The name of a column in table Y. -** -** The node at the root of the subtree is modified as follows: -** -** Expr.op Changed to TK_COLUMN -** Expr.pTab Points to the Table object for X.Y -** Expr.iColumn The column index in X.Y. -1 for the rowid. -** Expr.iTable The VDBE cursor number for X.Y -** -** -** To resolve result-set references, look for expression nodes of the -** form Z (with no X and Y prefix) where the Z matches the right-hand -** size of an AS clause in the result-set of a SELECT. The Z expression -** is replaced by a copy of the left-hand side of the result-set expression. -** Table-name and function resolution occurs on the substituted expression -** tree. For example, in: -** -** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x; -** -** The "x" term of the order by is replaced by "a+b" to render: -** -** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b; -** -** Function calls are checked to make sure that the function is -** defined and that the correct number of arguments are specified. -** If the function is an aggregate function, then the NC_HasAgg flag is -** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION. -** If an expression contains aggregate functions then the EP_Agg -** property on the expression is set. -** -** An error message is left in pParse if anything is amiss. The number -** if errors is returned. -*/ -SQLITE_PRIVATE int sqlite3ResolveExprNames( - NameContext *pNC, /* Namespace to resolve expressions in. */ - Expr *pExpr /* The expression to be analyzed. */ -){ - u8 savedHasAgg; - Walker w; - - if( pExpr==0 ) return 0; -#if SQLITE_MAX_EXPR_DEPTH>0 - { - Parse *pParse = pNC->pParse; - if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){ - return 1; - } - pParse->nHeight += pExpr->nHeight; - } -#endif - savedHasAgg = pNC->ncFlags & NC_HasAgg; - pNC->ncFlags &= ~NC_HasAgg; - memset(&w, 0, sizeof(w)); - w.xExprCallback = resolveExprStep; - w.xSelectCallback = resolveSelectStep; - w.pParse = pNC->pParse; - w.u.pNC = pNC; - sqlite3WalkExpr(&w, pExpr); -#if SQLITE_MAX_EXPR_DEPTH>0 - pNC->pParse->nHeight -= pExpr->nHeight; -#endif - if( pNC->nErr>0 || w.pParse->nErr>0 ){ - ExprSetProperty(pExpr, EP_Error); - } - if( pNC->ncFlags & NC_HasAgg ){ - ExprSetProperty(pExpr, EP_Agg); - }else if( savedHasAgg ){ - pNC->ncFlags |= NC_HasAgg; - } - return ExprHasProperty(pExpr, EP_Error); -} - - -/* -** Resolve all names in all expressions of a SELECT and in all -** decendents of the SELECT, including compounds off of p->pPrior, -** subqueries in expressions, and subqueries used as FROM clause -** terms. -** -** See sqlite3ResolveExprNames() for a description of the kinds of -** transformations that occur. -** -** All SELECT statements should have been expanded using -** sqlite3SelectExpand() prior to invoking this routine. -*/ -SQLITE_PRIVATE void sqlite3ResolveSelectNames( - Parse *pParse, /* The parser context */ - Select *p, /* The SELECT statement being coded. */ - NameContext *pOuterNC /* Name context for parent SELECT statement */ -){ - Walker w; - - assert( p!=0 ); - memset(&w, 0, sizeof(w)); - w.xExprCallback = resolveExprStep; - w.xSelectCallback = resolveSelectStep; - w.pParse = pParse; - w.u.pNC = pOuterNC; - sqlite3WalkSelect(&w, p); -} - -/************** End of resolve.c *********************************************/ -/************** Begin file expr.c ********************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains routines used for analyzing expressions and -** for generating VDBE code that evaluates expressions in SQLite. -*/ - -/* -** Return the 'affinity' of the expression pExpr if any. -** -** If pExpr is a column, a reference to a column via an 'AS' alias, -** or a sub-select with a column as the return value, then the -** affinity of that column is returned. Otherwise, 0x00 is returned, -** indicating no affinity for the expression. -** -** i.e. the WHERE clause expresssions in the following statements all -** have an affinity: -** -** CREATE TABLE t1(a); -** SELECT * FROM t1 WHERE a; -** SELECT a AS b FROM t1 WHERE b; -** SELECT * FROM t1 WHERE (select a from t1); -*/ -SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ - int op; - pExpr = sqlite3ExprSkipCollate(pExpr); - op = pExpr->op; - if( op==TK_SELECT ){ - assert( pExpr->flags&EP_xIsSelect ); - return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); - } -#ifndef SQLITE_OMIT_CAST - if( op==TK_CAST ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - return sqlite3AffinityType(pExpr->u.zToken); - } -#endif - if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) - && pExpr->pTab!=0 - ){ - /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally - ** a TK_COLUMN but was previously evaluated and cached in a register */ - int j = pExpr->iColumn; - if( j<0 ) return SQLITE_AFF_INTEGER; - assert( pExpr->pTab && jpTab->nCol ); - return pExpr->pTab->aCol[j].affinity; - } - return pExpr->affinity; -} - -/* -** Set the collating sequence for expression pExpr to be the collating -** sequence named by pToken. Return a pointer to a new Expr node that -** implements the COLLATE operator. -** -** If a memory allocation error occurs, that fact is recorded in pParse->db -** and the pExpr parameter is returned unchanged. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){ - if( pCollName->n>0 ){ - Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); - if( pNew ){ - pNew->pLeft = pExpr; - pNew->flags |= EP_Collate; - pExpr = pNew; - } - } - return pExpr; -} -SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ - Token s; - assert( zC!=0 ); - s.z = zC; - s.n = sqlite3Strlen30(s.z); - return sqlite3ExprAddCollateToken(pParse, pExpr, &s); -} - -/* -** Skip over any TK_COLLATE and/or TK_AS operators at the root of -** an expression. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ - while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ - pExpr = pExpr->pLeft; - } - return pExpr; -} - -/* -** Return the collation sequence for the expression pExpr. If -** there is no defined collating sequence, return NULL. -** -** The collating sequence might be determined by a COLLATE operator -** or by the presence of a column with a defined collating sequence. -** COLLATE operators take first precedence. Left operands take -** precedence over right operands. -*/ -SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ - sqlite3 *db = pParse->db; - CollSeq *pColl = 0; - Expr *p = pExpr; - while( p ){ - int op = p->op; - if( op==TK_CAST || op==TK_UPLUS ){ - p = p->pLeft; - continue; - } - assert( op!=TK_REGISTER || p->op2!=TK_COLLATE ); - if( op==TK_COLLATE ){ - pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); - break; - } - if( p->pTab!=0 - && (op==TK_AGG_COLUMN || op==TK_COLUMN - || op==TK_REGISTER || op==TK_TRIGGER) - ){ - /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally - ** a TK_COLUMN but was previously evaluated and cached in a register */ - int j = p->iColumn; - if( j>=0 ){ - const char *zColl = p->pTab->aCol[j].zColl; - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); - } - break; - } - if( p->flags & EP_Collate ){ - if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ - p = p->pLeft; - }else{ - p = p->pRight; - } - }else{ - break; - } - } - if( sqlite3CheckCollSeq(pParse, pColl) ){ - pColl = 0; - } - return pColl; -} - -/* -** pExpr is an operand of a comparison operator. aff2 is the -** type affinity of the other operand. This routine returns the -** type affinity that should be used for the comparison operator. -*/ -SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2){ - char aff1 = sqlite3ExprAffinity(pExpr); - if( aff1 && aff2 ){ - /* Both sides of the comparison are columns. If one has numeric - ** affinity, use that. Otherwise use no affinity. - */ - if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ - return SQLITE_AFF_NUMERIC; - }else{ - return SQLITE_AFF_NONE; - } - }else if( !aff1 && !aff2 ){ - /* Neither side of the comparison is a column. Compare the - ** results directly. - */ - return SQLITE_AFF_NONE; - }else{ - /* One side is a column, the other is not. Use the columns affinity. */ - assert( aff1==0 || aff2==0 ); - return (aff1 + aff2); - } -} - -/* -** pExpr is a comparison operator. Return the type affinity that should -** be applied to both operands prior to doing the comparison. -*/ -static char comparisonAffinity(Expr *pExpr){ - char aff; - assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || - pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || - pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT ); - assert( pExpr->pLeft ); - aff = sqlite3ExprAffinity(pExpr->pLeft); - if( pExpr->pRight ){ - aff = sqlite3CompareAffinity(pExpr->pRight, aff); - }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); - }else if( !aff ){ - aff = SQLITE_AFF_NONE; - } - return aff; -} - -/* -** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. -** idx_affinity is the affinity of an indexed column. Return true -** if the index with affinity idx_affinity may be used to implement -** the comparison in pExpr. -*/ -SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ - char aff = comparisonAffinity(pExpr); - switch( aff ){ - case SQLITE_AFF_NONE: - return 1; - case SQLITE_AFF_TEXT: - return idx_affinity==SQLITE_AFF_TEXT; - default: - return sqlite3IsNumericAffinity(idx_affinity); - } -} - -/* -** Return the P5 value that should be used for a binary comparison -** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. -*/ -static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ - u8 aff = (char)sqlite3ExprAffinity(pExpr2); - aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull; - return aff; -} - -/* -** Return a pointer to the collation sequence that should be used by -** a binary comparison operator comparing pLeft and pRight. -** -** If the left hand expression has a collating sequence type, then it is -** used. Otherwise the collation sequence for the right hand expression -** is used, or the default (BINARY) if neither expression has a collating -** type. -** -** Argument pRight (but not pLeft) may be a null pointer. In this case, -** it is not considered. -*/ -SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq( - Parse *pParse, - Expr *pLeft, - Expr *pRight -){ - CollSeq *pColl; - assert( pLeft ); - if( pLeft->flags & EP_Collate ){ - pColl = sqlite3ExprCollSeq(pParse, pLeft); - }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ - pColl = sqlite3ExprCollSeq(pParse, pRight); - }else{ - pColl = sqlite3ExprCollSeq(pParse, pLeft); - if( !pColl ){ - pColl = sqlite3ExprCollSeq(pParse, pRight); - } - } - return pColl; -} - -/* -** Generate code for a comparison operator. -*/ -static int codeCompare( - Parse *pParse, /* The parsing (and code generating) context */ - Expr *pLeft, /* The left operand */ - Expr *pRight, /* The right operand */ - int opcode, /* The comparison opcode */ - int in1, int in2, /* Register holding operands */ - int dest, /* Jump here if true. */ - int jumpIfNull /* If true, jump if either operand is NULL */ -){ - int p5; - int addr; - CollSeq *p4; - - p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); - p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); - addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, - (void*)p4, P4_COLLSEQ); - sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5); - return addr; -} - -#if SQLITE_MAX_EXPR_DEPTH>0 -/* -** Check that argument nHeight is less than or equal to the maximum -** expression depth allowed. If it is not, leave an error message in -** pParse. -*/ -SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){ - int rc = SQLITE_OK; - int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH]; - if( nHeight>mxHeight ){ - sqlite3ErrorMsg(pParse, - "Expression tree is too large (maximum depth %d)", mxHeight - ); - rc = SQLITE_ERROR; - } - return rc; -} - -/* The following three functions, heightOfExpr(), heightOfExprList() -** and heightOfSelect(), are used to determine the maximum height -** of any expression tree referenced by the structure passed as the -** first argument. -** -** If this maximum height is greater than the current value pointed -** to by pnHeight, the second parameter, then set *pnHeight to that -** value. -*/ -static void heightOfExpr(Expr *p, int *pnHeight){ - if( p ){ - if( p->nHeight>*pnHeight ){ - *pnHeight = p->nHeight; - } - } -} -static void heightOfExprList(ExprList *p, int *pnHeight){ - if( p ){ - int i; - for(i=0; inExpr; i++){ - heightOfExpr(p->a[i].pExpr, pnHeight); - } - } -} -static void heightOfSelect(Select *p, int *pnHeight){ - if( p ){ - heightOfExpr(p->pWhere, pnHeight); - heightOfExpr(p->pHaving, pnHeight); - heightOfExpr(p->pLimit, pnHeight); - heightOfExpr(p->pOffset, pnHeight); - heightOfExprList(p->pEList, pnHeight); - heightOfExprList(p->pGroupBy, pnHeight); - heightOfExprList(p->pOrderBy, pnHeight); - heightOfSelect(p->pPrior, pnHeight); - } -} - -/* -** Set the Expr.nHeight variable in the structure passed as an -** argument. An expression with no children, Expr.pList or -** Expr.pSelect member has a height of 1. Any other expression -** has a height equal to the maximum height of any other -** referenced Expr plus one. -*/ -static void exprSetHeight(Expr *p){ - int nHeight = 0; - heightOfExpr(p->pLeft, &nHeight); - heightOfExpr(p->pRight, &nHeight); - if( ExprHasProperty(p, EP_xIsSelect) ){ - heightOfSelect(p->x.pSelect, &nHeight); - }else{ - heightOfExprList(p->x.pList, &nHeight); - } - p->nHeight = nHeight + 1; -} - -/* -** Set the Expr.nHeight variable using the exprSetHeight() function. If -** the height is greater than the maximum allowed expression depth, -** leave an error in pParse. -*/ -SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){ - exprSetHeight(p); - sqlite3ExprCheckHeight(pParse, p->nHeight); -} - -/* -** Return the maximum height of any expression tree referenced -** by the select statement passed as an argument. -*/ -SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){ - int nHeight = 0; - heightOfSelect(p, &nHeight); - return nHeight; -} -#else - #define exprSetHeight(y) -#endif /* SQLITE_MAX_EXPR_DEPTH>0 */ - -/* -** This routine is the core allocator for Expr nodes. -** -** Construct a new expression node and return a pointer to it. Memory -** for this node and for the pToken argument is a single allocation -** obtained from sqlite3DbMalloc(). The calling function -** is responsible for making sure the node eventually gets freed. -** -** If dequote is true, then the token (if it exists) is dequoted. -** If dequote is false, no dequoting is performance. The deQuote -** parameter is ignored if pToken is NULL or if the token does not -** appear to be quoted. If the quotes were of the form "..." (double-quotes) -** then the EP_DblQuoted flag is set on the expression node. -** -** Special case: If op==TK_INTEGER and pToken points to a string that -** can be translated into a 32-bit integer, then the token is not -** stored in u.zToken. Instead, the integer values is written -** into u.iValue and the EP_IntValue flag is set. No extra storage -** is allocated to hold the integer text and the dequote flag is ignored. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprAlloc( - sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ - int op, /* Expression opcode */ - const Token *pToken, /* Token argument. Might be NULL */ - int dequote /* True to dequote */ -){ - Expr *pNew; - int nExtra = 0; - int iValue = 0; - - if( pToken ){ - if( op!=TK_INTEGER || pToken->z==0 - || sqlite3GetInt32(pToken->z, &iValue)==0 ){ - nExtra = pToken->n+1; - assert( iValue>=0 ); - } - } - pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra); - if( pNew ){ - pNew->op = (u8)op; - pNew->iAgg = -1; - if( pToken ){ - if( nExtra==0 ){ - pNew->flags |= EP_IntValue; - pNew->u.iValue = iValue; - }else{ - int c; - pNew->u.zToken = (char*)&pNew[1]; - assert( pToken->z!=0 || pToken->n==0 ); - if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); - pNew->u.zToken[pToken->n] = 0; - if( dequote && nExtra>=3 - && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ - sqlite3Dequote(pNew->u.zToken); - if( c=='"' ) pNew->flags |= EP_DblQuoted; - } - } - } -#if SQLITE_MAX_EXPR_DEPTH>0 - pNew->nHeight = 1; -#endif - } - return pNew; -} - -/* -** Allocate a new expression node from a zero-terminated token that has -** already been dequoted. -*/ -SQLITE_PRIVATE Expr *sqlite3Expr( - sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ - int op, /* Expression opcode */ - const char *zToken /* Token argument. Might be NULL */ -){ - Token x; - x.z = zToken; - x.n = zToken ? sqlite3Strlen30(zToken) : 0; - return sqlite3ExprAlloc(db, op, &x, 0); -} - -/* -** Attach subtrees pLeft and pRight to the Expr node pRoot. -** -** If pRoot==NULL that means that a memory allocation error has occurred. -** In that case, delete the subtrees pLeft and pRight. -*/ -SQLITE_PRIVATE void sqlite3ExprAttachSubtrees( - sqlite3 *db, - Expr *pRoot, - Expr *pLeft, - Expr *pRight -){ - if( pRoot==0 ){ - assert( db->mallocFailed ); - sqlite3ExprDelete(db, pLeft); - sqlite3ExprDelete(db, pRight); - }else{ - if( pRight ){ - pRoot->pRight = pRight; - pRoot->flags |= EP_Collate & pRight->flags; - } - if( pLeft ){ - pRoot->pLeft = pLeft; - pRoot->flags |= EP_Collate & pLeft->flags; - } - exprSetHeight(pRoot); - } -} - -/* -** Allocate a Expr node which joins as many as two subtrees. -** -** One or both of the subtrees can be NULL. Return a pointer to the new -** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed, -** free the subtrees and return NULL. -*/ -SQLITE_PRIVATE Expr *sqlite3PExpr( - Parse *pParse, /* Parsing context */ - int op, /* Expression opcode */ - Expr *pLeft, /* Left operand */ - Expr *pRight, /* Right operand */ - const Token *pToken /* Argument token */ -){ - Expr *p; - if( op==TK_AND && pLeft && pRight ){ - /* Take advantage of short-circuit false optimization for AND */ - p = sqlite3ExprAnd(pParse->db, pLeft, pRight); - }else{ - p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); - sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); - } - if( p ) { - sqlite3ExprCheckHeight(pParse, p->nHeight); - } - return p; -} - -/* -** Return 1 if an expression must be FALSE in all cases and 0 if the -** expression might be true. This is an optimization. If is OK to -** return 0 here even if the expression really is always false (a -** false negative). But it is a bug to return 1 if the expression -** might be true in some rare circumstances (a false positive.) -** -** Note that if the expression is part of conditional for a -** LEFT JOIN, then we cannot determine at compile-time whether or not -** is it true or false, so always return 0. -*/ -static int exprAlwaysFalse(Expr *p){ - int v = 0; - if( ExprHasProperty(p, EP_FromJoin) ) return 0; - if( !sqlite3ExprIsInteger(p, &v) ) return 0; - return v==0; -} - -/* -** Join two expressions using an AND operator. If either expression is -** NULL, then just return the other expression. -** -** If one side or the other of the AND is known to be false, then instead -** of returning an AND expression, just return a constant expression with -** a value of false. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ - if( pLeft==0 ){ - return pRight; - }else if( pRight==0 ){ - return pLeft; - }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){ - sqlite3ExprDelete(db, pLeft); - sqlite3ExprDelete(db, pRight); - return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0); - }else{ - Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0); - sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight); - return pNew; - } -} - -/* -** Construct a new expression node for a function with multiple -** arguments. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ - Expr *pNew; - sqlite3 *db = pParse->db; - assert( pToken ); - pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1); - if( pNew==0 ){ - sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ - return 0; - } - pNew->x.pList = pList; - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - sqlite3ExprSetHeight(pParse, pNew); - return pNew; -} - -/* -** Assign a variable number to an expression that encodes a wildcard -** in the original SQL statement. -** -** Wildcards consisting of a single "?" are assigned the next sequential -** variable number. -** -** Wildcards of the form "?nnn" are assigned the number "nnn". We make -** sure "nnn" is not too be to avoid a denial of service attack when -** the SQL statement comes from an external source. -** -** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number -** as the previous instance of the same wildcard. Or if this is the first -** instance of the wildcard, the next sequenial variable number is -** assigned. -*/ -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ - sqlite3 *db = pParse->db; - const char *z; - - if( pExpr==0 ) return; - assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); - z = pExpr->u.zToken; - assert( z!=0 ); - assert( z[0]!=0 ); - if( z[1]==0 ){ - /* Wildcard of the form "?". Assign the next variable number */ - assert( z[0]=='?' ); - pExpr->iColumn = (ynVar)(++pParse->nVar); - }else{ - ynVar x = 0; - u32 n = sqlite3Strlen30(z); - if( z[0]=='?' ){ - /* Wildcard of the form "?nnn". Convert "nnn" to an integer and - ** use it as the variable number */ - i64 i; - int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); - pExpr->iColumn = x = (ynVar)i; - testcase( i==0 ); - testcase( i==1 ); - testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); - testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); - if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ - sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", - db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); - x = 0; - } - if( i>pParse->nVar ){ - pParse->nVar = (int)i; - } - }else{ - /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable - ** number as the prior appearance of the same name, or if the name - ** has never appeared before, reuse the same variable number - */ - ynVar i; - for(i=0; inzVar; i++){ - if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){ - pExpr->iColumn = x = (ynVar)i+1; - break; - } - } - if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar); - } - if( x>0 ){ - if( x>pParse->nzVar ){ - char **a; - a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); - if( a==0 ) return; /* Error reported through db->mallocFailed */ - pParse->azVar = a; - memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); - pParse->nzVar = x; - } - if( z[0]!='?' || pParse->azVar[x-1]==0 ){ - sqlite3DbFree(db, pParse->azVar[x-1]); - pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); - } - } - } - if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ - sqlite3ErrorMsg(pParse, "too many SQL variables"); - } -} - -/* -** Recursively delete an expression tree. -*/ -SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ - if( p==0 ) return; - /* Sanity check: Assert that the IntValue is non-negative if it exists */ - assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); - if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ - sqlite3ExprDelete(db, p->pLeft); - sqlite3ExprDelete(db, p->pRight); - if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){ - sqlite3DbFree(db, p->u.zToken); - } - if( ExprHasProperty(p, EP_xIsSelect) ){ - sqlite3SelectDelete(db, p->x.pSelect); - }else{ - sqlite3ExprListDelete(db, p->x.pList); - } - } - if( !ExprHasProperty(p, EP_Static) ){ - sqlite3DbFree(db, p); - } -} - -/* -** Return the number of bytes allocated for the expression structure -** passed as the first argument. This is always one of EXPR_FULLSIZE, -** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. -*/ -static int exprStructSize(Expr *p){ - if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE; - if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE; - return EXPR_FULLSIZE; -} - -/* -** The dupedExpr*Size() routines each return the number of bytes required -** to store a copy of an expression or expression tree. They differ in -** how much of the tree is measured. -** -** dupedExprStructSize() Size of only the Expr structure -** dupedExprNodeSize() Size of Expr + space for token -** dupedExprSize() Expr + token + subtree components -** -*************************************************************************** -** -** The dupedExprStructSize() function returns two values OR-ed together: -** (1) the space required for a copy of the Expr structure only and -** (2) the EP_xxx flags that indicate what the structure size should be. -** The return values is always one of: -** -** EXPR_FULLSIZE -** EXPR_REDUCEDSIZE | EP_Reduced -** EXPR_TOKENONLYSIZE | EP_TokenOnly -** -** The size of the structure can be found by masking the return value -** of this routine with 0xfff. The flags can be found by masking the -** return value with EP_Reduced|EP_TokenOnly. -** -** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size -** (unreduced) Expr objects as they or originally constructed by the parser. -** During expression analysis, extra information is computed and moved into -** later parts of teh Expr object and that extra information might get chopped -** off if the expression is reduced. Note also that it does not work to -** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal -** to reduce a pristine expression tree from the parser. The implementation -** of dupedExprStructSize() contain multiple assert() statements that attempt -** to enforce this constraint. -*/ -static int dupedExprStructSize(Expr *p, int flags){ - int nSize; - assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ - if( 0==(flags&EXPRDUP_REDUCE) ){ - nSize = EXPR_FULLSIZE; - }else{ - assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); - assert( !ExprHasProperty(p, EP_FromJoin) ); - assert( (p->flags2 & EP2_MallocedToken)==0 ); - assert( (p->flags2 & EP2_Irreducible)==0 ); - if( p->pLeft || p->pRight || p->x.pList ){ - nSize = EXPR_REDUCEDSIZE | EP_Reduced; - }else{ - nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; - } - } - return nSize; -} - -/* -** This function returns the space in bytes required to store the copy -** of the Expr structure and a copy of the Expr.u.zToken string (if that -** string is defined.) -*/ -static int dupedExprNodeSize(Expr *p, int flags){ - int nByte = dupedExprStructSize(p, flags) & 0xfff; - if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nByte += sqlite3Strlen30(p->u.zToken)+1; - } - return ROUND8(nByte); -} - -/* -** Return the number of bytes required to create a duplicate of the -** expression passed as the first argument. The second argument is a -** mask containing EXPRDUP_XXX flags. -** -** The value returned includes space to create a copy of the Expr struct -** itself and the buffer referred to by Expr.u.zToken, if any. -** -** If the EXPRDUP_REDUCE flag is set, then the return value includes -** space to duplicate all Expr nodes in the tree formed by Expr.pLeft -** and Expr.pRight variables (but not for any structures pointed to or -** descended from the Expr.x.pList or Expr.x.pSelect variables). -*/ -static int dupedExprSize(Expr *p, int flags){ - int nByte = 0; - if( p ){ - nByte = dupedExprNodeSize(p, flags); - if( flags&EXPRDUP_REDUCE ){ - nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags); - } - } - return nByte; -} - -/* -** This function is similar to sqlite3ExprDup(), except that if pzBuffer -** is not NULL then *pzBuffer is assumed to point to a buffer large enough -** to store the copy of expression p, the copies of p->u.zToken -** (if applicable), and the copies of the p->pLeft and p->pRight expressions, -** if any. Before returning, *pzBuffer is set to the first byte passed the -** portion of the buffer copied into by this function. -*/ -static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ - Expr *pNew = 0; /* Value to return */ - if( p ){ - const int isReduced = (flags&EXPRDUP_REDUCE); - u8 *zAlloc; - u32 staticFlag = 0; - - assert( pzBuffer==0 || isReduced ); - - /* Figure out where to write the new Expr structure. */ - if( pzBuffer ){ - zAlloc = *pzBuffer; - staticFlag = EP_Static; - }else{ - zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); - } - pNew = (Expr *)zAlloc; - - if( pNew ){ - /* Set nNewSize to the size allocated for the structure pointed to - ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or - ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed - ** by the copy of the p->u.zToken string (if any). - */ - const unsigned nStructSize = dupedExprStructSize(p, flags); - const int nNewSize = nStructSize & 0xfff; - int nToken; - if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nToken = sqlite3Strlen30(p->u.zToken) + 1; - }else{ - nToken = 0; - } - if( isReduced ){ - assert( ExprHasProperty(p, EP_Reduced)==0 ); - memcpy(zAlloc, p, nNewSize); - }else{ - int nSize = exprStructSize(p); - memcpy(zAlloc, p, nSize); - memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize); - } - - /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ - pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static); - pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); - pNew->flags |= staticFlag; - - /* Copy the p->u.zToken string, if any. */ - if( nToken ){ - char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; - memcpy(zToken, p->u.zToken, nToken); - } - - if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ - /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ - if( ExprHasProperty(p, EP_xIsSelect) ){ - pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced); - }else{ - pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced); - } - } - - /* Fill in pNew->pLeft and pNew->pRight. */ - if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){ - zAlloc += dupedExprNodeSize(p, flags); - if( ExprHasProperty(pNew, EP_Reduced) ){ - pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc); - pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc); - } - if( pzBuffer ){ - *pzBuffer = zAlloc; - } - }else{ - pNew->flags2 = 0; - if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ - pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); - pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); - } - } - - } - } - return pNew; -} - -/* -** The following group of routines make deep copies of expressions, -** expression lists, ID lists, and select statements. The copies can -** be deleted (by being passed to their respective ...Delete() routines) -** without effecting the originals. -** -** The expression list, ID, and source lists return by sqlite3ExprListDup(), -** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded -** by subsequent calls to sqlite*ListAppend() routines. -** -** Any tables that the SrcList might point to are not duplicated. -** -** The flags parameter contains a combination of the EXPRDUP_XXX flags. -** If the EXPRDUP_REDUCE flag is set, then the structure returned is a -** truncated version of the usual Expr structure that will be stored as -** part of the in-memory representation of the database schema. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){ - return exprDup(db, p, flags, 0); -} -SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ - ExprList *pNew; - struct ExprList_item *pItem, *pOldItem; - int i; - if( p==0 ) return 0; - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); - if( pNew==0 ) return 0; - pNew->iECursor = 0; - pNew->nExpr = i = p->nExpr; - if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; inExpr; i+=i){} - pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) ); - if( pItem==0 ){ - sqlite3DbFree(db, pNew); - return 0; - } - pOldItem = p->a; - for(i=0; inExpr; i++, pItem++, pOldItem++){ - Expr *pOldExpr = pOldItem->pExpr; - pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags); - pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); - pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); - pItem->sortOrder = pOldItem->sortOrder; - pItem->done = 0; - pItem->iOrderByCol = pOldItem->iOrderByCol; - pItem->iAlias = pOldItem->iAlias; - } - return pNew; -} - -/* -** If cursors, triggers, views and subqueries are all omitted from -** the build, then none of the following routines, except for -** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes -** called with a NULL argument. -*/ -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ - || !defined(SQLITE_OMIT_SUBQUERY) -SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ - SrcList *pNew; - int i; - int nByte; - if( p==0 ) return 0; - nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); - pNew = sqlite3DbMallocRaw(db, nByte ); - if( pNew==0 ) return 0; - pNew->nSrc = pNew->nAlloc = p->nSrc; - for(i=0; inSrc; i++){ - struct SrcList_item *pNewItem = &pNew->a[i]; - struct SrcList_item *pOldItem = &p->a[i]; - Table *pTab; - pNewItem->pSchema = pOldItem->pSchema; - pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); - pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); - pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); - pNewItem->jointype = pOldItem->jointype; - pNewItem->iCursor = pOldItem->iCursor; - pNewItem->addrFillSub = pOldItem->addrFillSub; - pNewItem->regReturn = pOldItem->regReturn; - pNewItem->isCorrelated = pOldItem->isCorrelated; - pNewItem->viaCoroutine = pOldItem->viaCoroutine; - pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); - pNewItem->notIndexed = pOldItem->notIndexed; - pNewItem->pIndex = pOldItem->pIndex; - pTab = pNewItem->pTab = pOldItem->pTab; - if( pTab ){ - pTab->nRef++; - } - pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags); - pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags); - pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing); - pNewItem->colUsed = pOldItem->colUsed; - } - return pNew; -} -SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ - IdList *pNew; - int i; - if( p==0 ) return 0; - pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); - if( pNew==0 ) return 0; - pNew->nId = p->nId; - pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); - if( pNew->a==0 ){ - sqlite3DbFree(db, pNew); - return 0; - } - /* Note that because the size of the allocation for p->a[] is not - ** necessarily a power of two, sqlite3IdListAppend() may not be called - ** on the duplicate created by this function. */ - for(i=0; inId; i++){ - struct IdList_item *pNewItem = &pNew->a[i]; - struct IdList_item *pOldItem = &p->a[i]; - pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); - pNewItem->idx = pOldItem->idx; - } - return pNew; -} -SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ - Select *pNew, *pPrior; - if( p==0 ) return 0; - pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); - if( pNew==0 ) return 0; - pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); - pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); - pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); - pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); - pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags); - pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags); - pNew->op = p->op; - pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags); - if( pPrior ) pPrior->pNext = pNew; - pNew->pNext = 0; - pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); - pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags); - pNew->iLimit = 0; - pNew->iOffset = 0; - pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; - pNew->pRightmost = 0; - pNew->addrOpenEphm[0] = -1; - pNew->addrOpenEphm[1] = -1; - pNew->addrOpenEphm[2] = -1; - return pNew; -} -#else -SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ - assert( p==0 ); - return 0; -} -#endif - - -/* -** Add a new element to the end of an expression list. If pList is -** initially NULL, then create a new expression list. -** -** If a memory allocation error occurs, the entire list is freed and -** NULL is returned. If non-NULL is returned, then it is guaranteed -** that the new entry was successfully appended. -*/ -SQLITE_PRIVATE ExprList *sqlite3ExprListAppend( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List to which to append. Might be NULL */ - Expr *pExpr /* Expression to be appended. Might be NULL */ -){ - sqlite3 *db = pParse->db; - if( pList==0 ){ - pList = sqlite3DbMallocZero(db, sizeof(ExprList) ); - if( pList==0 ){ - goto no_mem; - } - pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0])); - if( pList->a==0 ) goto no_mem; - }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ - struct ExprList_item *a; - assert( pList->nExpr>0 ); - a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0])); - if( a==0 ){ - goto no_mem; - } - pList->a = a; - } - assert( pList->a!=0 ); - if( 1 ){ - struct ExprList_item *pItem = &pList->a[pList->nExpr++]; - memset(pItem, 0, sizeof(*pItem)); - pItem->pExpr = pExpr; - } - return pList; - -no_mem: - /* Avoid leaking memory if malloc has failed. */ - sqlite3ExprDelete(db, pExpr); - sqlite3ExprListDelete(db, pList); - return 0; -} - -/* -** Set the ExprList.a[].zName element of the most recently added item -** on the expression list. -** -** pList might be NULL following an OOM error. But pName should never be -** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag -** is set. -*/ -SQLITE_PRIVATE void sqlite3ExprListSetName( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List to which to add the span. */ - Token *pName, /* Name to be added */ - int dequote /* True to cause the name to be dequoted */ -){ - assert( pList!=0 || pParse->db->mallocFailed!=0 ); - if( pList ){ - struct ExprList_item *pItem; - assert( pList->nExpr>0 ); - pItem = &pList->a[pList->nExpr-1]; - assert( pItem->zName==0 ); - pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); - if( dequote && pItem->zName ) sqlite3Dequote(pItem->zName); - } -} - -/* -** Set the ExprList.a[].zSpan element of the most recently added item -** on the expression list. -** -** pList might be NULL following an OOM error. But pSpan should never be -** NULL. If a memory allocation fails, the pParse->db->mallocFailed flag -** is set. -*/ -SQLITE_PRIVATE void sqlite3ExprListSetSpan( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List to which to add the span. */ - ExprSpan *pSpan /* The span to be added */ -){ - sqlite3 *db = pParse->db; - assert( pList!=0 || db->mallocFailed!=0 ); - if( pList ){ - struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; - assert( pList->nExpr>0 ); - assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr ); - sqlite3DbFree(db, pItem->zSpan); - pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart, - (int)(pSpan->zEnd - pSpan->zStart)); - } -} - -/* -** If the expression list pEList contains more than iLimit elements, -** leave an error message in pParse. -*/ -SQLITE_PRIVATE void sqlite3ExprListCheckLength( - Parse *pParse, - ExprList *pEList, - const char *zObject -){ - int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; - testcase( pEList && pEList->nExpr==mx ); - testcase( pEList && pEList->nExpr==mx+1 ); - if( pEList && pEList->nExpr>mx ){ - sqlite3ErrorMsg(pParse, "too many columns in %s", zObject); - } -} - -/* -** Delete an entire expression list. -*/ -SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ - int i; - struct ExprList_item *pItem; - if( pList==0 ) return; - assert( pList->a!=0 || pList->nExpr==0 ); - for(pItem=pList->a, i=0; inExpr; i++, pItem++){ - sqlite3ExprDelete(db, pItem->pExpr); - sqlite3DbFree(db, pItem->zName); - sqlite3DbFree(db, pItem->zSpan); - } - sqlite3DbFree(db, pList->a); - sqlite3DbFree(db, pList); -} - -/* -** These routines are Walker callbacks. Walker.u.pi is a pointer -** to an integer. These routines are checking an expression to see -** if it is a constant. Set *Walker.u.pi to 0 if the expression is -** not constant. -** -** These callback routines are used to implement the following: -** -** sqlite3ExprIsConstant() -** sqlite3ExprIsConstantNotJoin() -** sqlite3ExprIsConstantOrFunction() -** -*/ -static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ - - /* If pWalker->u.i is 3 then any term of the expression that comes from - ** the ON or USING clauses of a join disqualifies the expression - ** from being considered constant. */ - if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){ - pWalker->u.i = 0; - return WRC_Abort; - } - - switch( pExpr->op ){ - /* Consider functions to be constant if all their arguments are constant - ** and pWalker->u.i==2 */ - case TK_FUNCTION: - if( pWalker->u.i==2 ) return 0; - /* Fall through */ - case TK_ID: - case TK_COLUMN: - case TK_AGG_FUNCTION: - case TK_AGG_COLUMN: - testcase( pExpr->op==TK_ID ); - testcase( pExpr->op==TK_COLUMN ); - testcase( pExpr->op==TK_AGG_FUNCTION ); - testcase( pExpr->op==TK_AGG_COLUMN ); - pWalker->u.i = 0; - return WRC_Abort; - default: - testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */ - testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */ - return WRC_Continue; - } -} -static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ - UNUSED_PARAMETER(NotUsed); - pWalker->u.i = 0; - return WRC_Abort; -} -static int exprIsConst(Expr *p, int initFlag){ - Walker w; - memset(&w, 0, sizeof(w)); - w.u.i = initFlag; - w.xExprCallback = exprNodeIsConstant; - w.xSelectCallback = selectNodeIsConstant; - sqlite3WalkExpr(&w, p); - return w.u.i; -} - -/* -** Walk an expression tree. Return 1 if the expression is constant -** and 0 if it involves variables or function calls. -** -** For the purposes of this function, a double-quoted string (ex: "abc") -** is considered a variable but a single-quoted string (ex: 'abc') is -** a constant. -*/ -SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){ - return exprIsConst(p, 1); -} - -/* -** Walk an expression tree. Return 1 if the expression is constant -** that does no originate from the ON or USING clauses of a join. -** Return 0 if it involves variables or function calls or terms from -** an ON or USING clause. -*/ -SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){ - return exprIsConst(p, 3); -} - -/* -** Walk an expression tree. Return 1 if the expression is constant -** or a function call with constant arguments. Return and 0 if there -** are any variables. -** -** For the purposes of this function, a double-quoted string (ex: "abc") -** is considered a variable but a single-quoted string (ex: 'abc') is -** a constant. -*/ -SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p){ - return exprIsConst(p, 2); -} - -/* -** If the expression p codes a constant integer that is small enough -** to fit in a 32-bit integer, return 1 and put the value of the integer -** in *pValue. If the expression is not an integer or if it is too big -** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. -*/ -SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){ - int rc = 0; - - /* If an expression is an integer literal that fits in a signed 32-bit - ** integer, then the EP_IntValue flag will have already been set */ - assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0 - || sqlite3GetInt32(p->u.zToken, &rc)==0 ); - - if( p->flags & EP_IntValue ){ - *pValue = p->u.iValue; - return 1; - } - switch( p->op ){ - case TK_UPLUS: { - rc = sqlite3ExprIsInteger(p->pLeft, pValue); - break; - } - case TK_UMINUS: { - int v; - if( sqlite3ExprIsInteger(p->pLeft, &v) ){ - *pValue = -v; - rc = 1; - } - break; - } - default: break; - } - return rc; -} - -/* -** Return FALSE if there is no chance that the expression can be NULL. -** -** If the expression might be NULL or if the expression is too complex -** to tell return TRUE. -** -** This routine is used as an optimization, to skip OP_IsNull opcodes -** when we know that a value cannot be NULL. Hence, a false positive -** (returning TRUE when in fact the expression can never be NULL) might -** be a small performance hit but is otherwise harmless. On the other -** hand, a false negative (returning FALSE when the result could be NULL) -** will likely result in an incorrect answer. So when in doubt, return -** TRUE. -*/ -SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ - u8 op; - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } - op = p->op; - if( op==TK_REGISTER ) op = p->op2; - switch( op ){ - case TK_INTEGER: - case TK_STRING: - case TK_FLOAT: - case TK_BLOB: - return 0; - default: - return 1; - } -} - -/* -** Generate an OP_IsNull instruction that tests register iReg and jumps -** to location iDest if the value in iReg is NULL. The value in iReg -** was computed by pExpr. If we can look at pExpr at compile-time and -** determine that it can never generate a NULL, then the OP_IsNull operation -** can be omitted. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump( - Vdbe *v, /* The VDBE under construction */ - const Expr *pExpr, /* Only generate OP_IsNull if this expr can be NULL */ - int iReg, /* Test the value in this register for NULL */ - int iDest /* Jump here if the value is null */ -){ - if( sqlite3ExprCanBeNull(pExpr) ){ - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest); - } -} - -/* -** Return TRUE if the given expression is a constant which would be -** unchanged by OP_Affinity with the affinity given in the second -** argument. -** -** This routine is used to determine if the OP_Affinity operation -** can be omitted. When in doubt return FALSE. A false negative -** is harmless. A false positive, however, can result in the wrong -** answer. -*/ -SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){ - u8 op; - if( aff==SQLITE_AFF_NONE ) return 1; - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } - op = p->op; - if( op==TK_REGISTER ) op = p->op2; - switch( op ){ - case TK_INTEGER: { - return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC; - } - case TK_FLOAT: { - return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC; - } - case TK_STRING: { - return aff==SQLITE_AFF_TEXT; - } - case TK_BLOB: { - return 1; - } - case TK_COLUMN: { - assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */ - return p->iColumn<0 - && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC); - } - default: { - return 0; - } - } -} - -/* -** Return TRUE if the given string is a row-id column name. -*/ -SQLITE_PRIVATE int sqlite3IsRowid(const char *z){ - if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1; - if( sqlite3StrICmp(z, "ROWID")==0 ) return 1; - if( sqlite3StrICmp(z, "OID")==0 ) return 1; - return 0; -} - -/* -** Return true if we are able to the IN operator optimization on a -** query of the form -** -** x IN (SELECT ...) -** -** Where the SELECT... clause is as specified by the parameter to this -** routine. -** -** The Select object passed in has already been preprocessed and no -** errors have been found. -*/ -#ifndef SQLITE_OMIT_SUBQUERY -static int isCandidateForInOpt(Select *p){ - SrcList *pSrc; - ExprList *pEList; - Table *pTab; - if( p==0 ) return 0; /* right-hand side of IN is SELECT */ - if( p->pPrior ) return 0; /* Not a compound SELECT */ - if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ - testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); - testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); - return 0; /* No DISTINCT keyword and no aggregate functions */ - } - assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */ - if( p->pLimit ) return 0; /* Has no LIMIT clause */ - assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */ - if( p->pWhere ) return 0; /* Has no WHERE clause */ - pSrc = p->pSrc; - assert( pSrc!=0 ); - if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */ - if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */ - pTab = pSrc->a[0].pTab; - if( NEVER(pTab==0) ) return 0; - assert( pTab->pSelect==0 ); /* FROM clause is not a view */ - if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ - pEList = p->pEList; - if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ - if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */ - return 1; -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -/* -** Code an OP_Once instruction and allocate space for its flag. Return the -** address of the new instruction. -*/ -SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){ - Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ - return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++); -} - -/* -** This function is used by the implementation of the IN (...) operator. -** The pX parameter is the expression on the RHS of the IN operator, which -** might be either a list of expressions or a subquery. -** -** The job of this routine is to find or create a b-tree object that can -** be used either to test for membership in the RHS set or to iterate through -** all members of the RHS set, skipping duplicates. -** -** A cursor is opened on the b-tree object that the RHS of the IN operator -** and pX->iTable is set to the index of that cursor. -** -** The returned value of this function indicates the b-tree type, as follows: -** -** IN_INDEX_ROWID - The cursor was opened on a database table. -** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. -** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. -** IN_INDEX_EPH - The cursor was opened on a specially created and -** populated epheremal table. -** -** An existing b-tree might be used if the RHS expression pX is a simple -** subquery such as: -** -** SELECT FROM -** -** If the RHS of the IN operator is a list or a more complex subquery, then -** an ephemeral table might need to be generated from the RHS and then -** pX->iTable made to point to the ephermeral table instead of an -** existing table. -** -** If the prNotFound parameter is 0, then the b-tree will be used to iterate -** through the set members, skipping any duplicates. In this case an -** epheremal table must be used unless the selected is guaranteed -** to be unique - either because it is an INTEGER PRIMARY KEY or it -** has a UNIQUE constraint or UNIQUE index. -** -** If the prNotFound parameter is not 0, then the b-tree will be used -** for fast set membership tests. In this case an epheremal table must -** be used unless is an INTEGER PRIMARY KEY or an index can -** be found with as its left-most column. -** -** When the b-tree is being used for membership tests, the calling function -** needs to know whether or not the structure contains an SQL NULL -** value in order to correctly evaluate expressions like "X IN (Y, Z)". -** If there is any chance that the (...) might contain a NULL value at -** runtime, then a register is allocated and the register number written -** to *prNotFound. If there is no chance that the (...) contains a -** NULL value, then *prNotFound is left unchanged. -** -** If a register is allocated and its location stored in *prNotFound, then -** its initial value is NULL. If the (...) does not remain constant -** for the duration of the query (i.e. the SELECT within the (...) -** is a correlated subquery) then the value of the allocated register is -** reset to NULL each time the subquery is rerun. This allows the -** caller to use vdbe code equivalent to the following: -** -** if( register==NULL ){ -** has_null = -** register = 1 -** } -** -** in order to avoid running the -** test more often than is necessary. -*/ -#ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ - Select *p; /* SELECT to the right of IN operator */ - int eType = 0; /* Type of RHS table. IN_INDEX_* */ - int iTab = pParse->nTab++; /* Cursor of the RHS table */ - int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */ - Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ - - assert( pX->op==TK_IN ); - - /* Check to see if an existing table or index can be used to - ** satisfy the query. This is preferable to generating a new - ** ephemeral table. - */ - p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); - if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){ - sqlite3 *db = pParse->db; /* Database connection */ - Table *pTab; /* Table
. */ - Expr *pExpr; /* Expression */ - int iCol; /* Index of column */ - int iDb; /* Database idx for pTab */ - - assert( p ); /* Because of isCandidateForInOpt(p) */ - assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ - assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ - assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ - pTab = p->pSrc->a[0].pTab; - pExpr = p->pEList->a[0].pExpr; - iCol = pExpr->iColumn; - - /* Code an OP_VerifyCookie and OP_TableLock for
. */ - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - - /* This function is only called from two places. In both cases the vdbe - ** has already been allocated. So assume sqlite3GetVdbe() is always - ** successful here. - */ - assert(v); - if( iCol<0 ){ - int iAddr; - - iAddr = sqlite3CodeOnce(pParse); - - sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); - eType = IN_INDEX_ROWID; - - sqlite3VdbeJumpHere(v, iAddr); - }else{ - Index *pIdx; /* Iterator variable */ - - /* The collation sequence used by the comparison. If an index is to - ** be used in place of a temp-table, it must be ordered according - ** to this collation sequence. */ - CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); - - /* Check that the affinity that will be used to perform the - ** comparison is the same as the affinity of the column. If - ** it is not, it is not possible to use any index. - */ - int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity); - - for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ - if( (pIdx->aiColumn[0]==iCol) - && sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq - && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) - ){ - int iAddr; - char *pKey; - - pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); - iAddr = sqlite3CodeOnce(pParse); - - sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, - pKey,P4_KEYINFO_HANDOFF); - VdbeComment((v, "%s", pIdx->zName)); - assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); - eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; - - sqlite3VdbeJumpHere(v, iAddr); - if( prNotFound && !pTab->aCol[iCol].notNull ){ - *prNotFound = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); - } - } - } - } - } - - if( eType==0 ){ - /* Could not found an existing table or index to use as the RHS b-tree. - ** We will have to generate an ephemeral table to do the job. - */ - double savedNQueryLoop = pParse->nQueryLoop; - int rMayHaveNull = 0; - eType = IN_INDEX_EPH; - if( prNotFound ){ - *prNotFound = rMayHaveNull = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); - }else{ - testcase( pParse->nQueryLoop>(double)1 ); - pParse->nQueryLoop = (double)1; - if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){ - eType = IN_INDEX_ROWID; - } - } - sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID); - pParse->nQueryLoop = savedNQueryLoop; - }else{ - pX->iTable = iTab; - } - return eType; -} -#endif - -/* -** Generate code for scalar subqueries used as a subquery expression, EXISTS, -** or IN operators. Examples: -** -** (SELECT a FROM b) -- subquery -** EXISTS (SELECT a FROM b) -- EXISTS subquery -** x IN (4,5,11) -- IN operator with list on right-hand side -** x IN (SELECT a FROM b) -- IN operator with subquery on the right -** -** The pExpr parameter describes the expression that contains the IN -** operator or subquery. -** -** If parameter isRowid is non-zero, then expression pExpr is guaranteed -** to be of the form " IN (?, ?, ?)", where is a reference -** to some integer key column of a table B-Tree. In this case, use an -** intkey B-Tree to store the set of IN(...) values instead of the usual -** (slower) variable length keys B-Tree. -** -** If rMayHaveNull is non-zero, that means that the operation is an IN -** (not a SELECT or EXISTS) and that the RHS might contains NULLs. -** Furthermore, the IN is in a WHERE clause and that we really want -** to iterate over the RHS of the IN operator in order to quickly locate -** all corresponding LHS elements. All this routine does is initialize -** the register given by rMayHaveNull to NULL. Calling routines will take -** care of changing this register value to non-NULL if the RHS is NULL-free. -** -** If rMayHaveNull is zero, that means that the subquery is being used -** for membership testing only. There is no need to initialize any -** registers to indicate the presense or absence of NULLs on the RHS. -** -** For a SELECT or EXISTS operator, return the register that holds the -** result. For IN operators or if an error occurs, the return value is 0. -*/ -#ifndef SQLITE_OMIT_SUBQUERY -SQLITE_PRIVATE int sqlite3CodeSubselect( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* The IN, SELECT, or EXISTS operator */ - int rMayHaveNull, /* Register that records whether NULLs exist in RHS */ - int isRowid /* If true, LHS of IN operator is a rowid */ -){ - int testAddr = -1; /* One-time test address */ - int rReg = 0; /* Register storing resulting */ - Vdbe *v = sqlite3GetVdbe(pParse); - if( NEVER(v==0) ) return 0; - sqlite3ExprCachePush(pParse); - - /* This code must be run in its entirety every time it is encountered - ** if any of the following is true: - ** - ** * The right-hand side is a correlated subquery - ** * The right-hand side is an expression list containing variables - ** * We are inside a trigger - ** - ** If all of the above are false, then we can run this code just once - ** save the results, and reuse the same result on subsequent invocations. - */ - if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){ - testAddr = sqlite3CodeOnce(pParse); - } - -#ifndef SQLITE_OMIT_EXPLAIN - if( pParse->explain==2 ){ - char *zMsg = sqlite3MPrintf( - pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ", - pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId - ); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); - } -#endif - - switch( pExpr->op ){ - case TK_IN: { - char affinity; /* Affinity of the LHS of the IN */ - KeyInfo keyInfo; /* Keyinfo for the generated table */ - static u8 sortOrder = 0; /* Fake aSortOrder for keyInfo */ - int addr; /* Address of OP_OpenEphemeral instruction */ - Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ - - if( rMayHaveNull ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull); - } - - affinity = sqlite3ExprAffinity(pLeft); - - /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' - ** expression it is handled the same way. An ephemeral table is - ** filled with single-field index keys representing the results - ** from the SELECT or the . - ** - ** If the 'x' expression is a column value, or the SELECT... - ** statement returns a column value, then the affinity of that - ** column is used to build the index keys. If both 'x' and the - ** SELECT... statement are columns, then numeric affinity is used - ** if either column has NUMERIC or INTEGER affinity. If neither - ** 'x' nor the SELECT... statement are columns, then numeric affinity - ** is used. - */ - pExpr->iTable = pParse->nTab++; - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); - if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED); - memset(&keyInfo, 0, sizeof(keyInfo)); - keyInfo.nField = 1; - keyInfo.aSortOrder = &sortOrder; - - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - /* Case 1: expr IN (SELECT ...) - ** - ** Generate code to write the results of the select into the temporary - ** table allocated and opened above. - */ - SelectDest dest; - ExprList *pEList; - - assert( !isRowid ); - sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); - dest.affSdst = (u8)affinity; - assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); - pExpr->x.pSelect->iLimit = 0; - if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){ - return 0; - } - pEList = pExpr->x.pSelect->pEList; - if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){ - keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, - pEList->a[0].pExpr); - } - }else if( ALWAYS(pExpr->x.pList!=0) ){ - /* Case 2: expr IN (exprlist) - ** - ** For each expression, build an index key from the evaluation and - ** store it in the temporary table. If is a column, then use - ** that columns affinity when building index keys. If is not - ** a column, use numeric affinity. - */ - int i; - ExprList *pList = pExpr->x.pList; - struct ExprList_item *pItem; - int r1, r2, r3; - - if( !affinity ){ - affinity = SQLITE_AFF_NONE; - } - keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); - keyInfo.aSortOrder = &sortOrder; - - /* Loop through each expression in . */ - r1 = sqlite3GetTempReg(pParse); - r2 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Null, 0, r2); - for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ - Expr *pE2 = pItem->pExpr; - int iValToIns; - - /* If the expression is not constant then we will need to - ** disable the test that was generated above that makes sure - ** this code only executes once. Because for a non-constant - ** expression we need to rerun this code each time. - */ - if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){ - sqlite3VdbeChangeToNoop(v, testAddr); - testAddr = -1; - } - - /* Evaluate the expression and insert it into the temp table */ - if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){ - sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns); - }else{ - r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); - if( isRowid ){ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, - sqlite3VdbeCurrentAddr(v)+2); - sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); - }else{ - sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); - sqlite3ExprCacheAffinityChange(pParse, r3, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); - } - } - } - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempReg(pParse, r2); - } - if( !isRowid ){ - sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); - } - break; - } - - case TK_EXISTS: - case TK_SELECT: - default: { - /* If this has to be a scalar SELECT. Generate code to put the - ** value of this select in a memory cell and record the number - ** of the memory cell in iColumn. If this is an EXISTS, write - ** an integer 0 (not exists) or 1 (exists) into a memory cell - ** and record that memory cell in iColumn. - */ - Select *pSel; /* SELECT statement to encode */ - SelectDest dest; /* How to deal with SELECt result */ - - testcase( pExpr->op==TK_EXISTS ); - testcase( pExpr->op==TK_SELECT ); - assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); - - assert( ExprHasProperty(pExpr, EP_xIsSelect) ); - pSel = pExpr->x.pSelect; - sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); - if( pExpr->op==TK_SELECT ){ - dest.eDest = SRT_Mem; - sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm); - VdbeComment((v, "Init subquery result")); - }else{ - dest.eDest = SRT_Exists; - sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); - VdbeComment((v, "Init EXISTS result")); - } - sqlite3ExprDelete(pParse->db, pSel->pLimit); - pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, - &sqlite3IntTokens[1]); - pSel->iLimit = 0; - if( sqlite3Select(pParse, pSel, &dest) ){ - return 0; - } - rReg = dest.iSDParm; - ExprSetIrreducible(pExpr); - break; - } - } - - if( testAddr>=0 ){ - sqlite3VdbeJumpHere(v, testAddr); - } - sqlite3ExprCachePop(pParse, 1); - - return rReg; -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate code for an IN expression. -** -** x IN (SELECT ...) -** x IN (value, value, ...) -** -** The left-hand side (LHS) is a scalar expression. The right-hand side (RHS) -** is an array of zero or more values. The expression is true if the LHS is -** contained within the RHS. The value of the expression is unknown (NULL) -** if the LHS is NULL or if the LHS is not contained within the RHS and the -** RHS contains one or more NULL values. -** -** This routine generates code will jump to destIfFalse if the LHS is not -** contained within the RHS. If due to NULLs we cannot determine if the LHS -** is contained in the RHS then jump to destIfNull. If the LHS is contained -** within the RHS then fall through. -*/ -static void sqlite3ExprCodeIN( - Parse *pParse, /* Parsing and code generating context */ - Expr *pExpr, /* The IN expression */ - int destIfFalse, /* Jump here if LHS is not contained in the RHS */ - int destIfNull /* Jump here if the results are unknown due to NULLs */ -){ - int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */ - char affinity; /* Comparison affinity to use */ - int eType; /* Type of the RHS */ - int r1; /* Temporary use register */ - Vdbe *v; /* Statement under construction */ - - /* Compute the RHS. After this step, the table with cursor - ** pExpr->iTable will contains the values that make up the RHS. - */ - v = pParse->pVdbe; - assert( v!=0 ); /* OOM detected prior to this routine */ - VdbeNoopComment((v, "begin IN expr")); - eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull); - - /* Figure out the affinity to use to create a key from the results - ** of the expression. affinityStr stores a static string suitable for - ** P4 of OP_MakeRecord. - */ - affinity = comparisonAffinity(pExpr); - - /* Code the LHS, the from " IN (...)". - */ - sqlite3ExprCachePush(pParse); - r1 = sqlite3GetTempReg(pParse); - sqlite3ExprCode(pParse, pExpr->pLeft, r1); - - /* If the LHS is NULL, then the result is either false or NULL depending - ** on whether the RHS is empty or not, respectively. - */ - if( destIfNull==destIfFalse ){ - /* Shortcut for the common case where the false and NULL outcomes are - ** the same. */ - sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); - }else{ - int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); - sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); - sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); - sqlite3VdbeJumpHere(v, addr1); - } - - if( eType==IN_INDEX_ROWID ){ - /* In this case, the RHS is the ROWID of table b-tree - */ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse); - sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1); - }else{ - /* In this case, the RHS is an index b-tree. - */ - sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1); - - /* If the set membership test fails, then the result of the - ** "x IN (...)" expression must be either 0 or NULL. If the set - ** contains no NULL values, then the result is 0. If the set - ** contains one or more NULL values, then the result of the - ** expression is also NULL. - */ - if( rRhsHasNull==0 || destIfFalse==destIfNull ){ - /* This branch runs if it is known at compile time that the RHS - ** cannot contain NULL values. This happens as the result - ** of a "NOT NULL" constraint in the database schema. - ** - ** Also run this branch if NULL is equivalent to FALSE - ** for this particular IN operator. - */ - sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1); - - }else{ - /* In this branch, the RHS of the IN might contain a NULL and - ** the presence of a NULL on the RHS makes a difference in the - ** outcome. - */ - int j1, j2, j3; - - /* First check to see if the LHS is contained in the RHS. If so, - ** then the presence of NULLs in the RHS does not matter, so jump - ** over all of the code that follows. - */ - j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); - - /* Here we begin generating code that runs if the LHS is not - ** contained within the RHS. Generate additional code that - ** tests the RHS for NULLs. If the RHS contains a NULL then - ** jump to destIfNull. If there are no NULLs in the RHS then - ** jump to destIfFalse. - */ - j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull); - j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1); - sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull); - sqlite3VdbeJumpHere(v, j3); - sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1); - sqlite3VdbeJumpHere(v, j2); - - /* Jump to the appropriate target depending on whether or not - ** the RHS contains a NULL - */ - sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull); - sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); - - /* The OP_Found at the top of this branch jumps here when true, - ** causing the overall IN expression evaluation to fall through. - */ - sqlite3VdbeJumpHere(v, j1); - } - } - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ExprCachePop(pParse, 1); - VdbeComment((v, "end IN expr")); -} -#endif /* SQLITE_OMIT_SUBQUERY */ - -/* -** Duplicate an 8-byte value -*/ -static char *dup8bytes(Vdbe *v, const char *in){ - char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8); - if( out ){ - memcpy(out, in, 8); - } - return out; -} - -#ifndef SQLITE_OMIT_FLOATING_POINT -/* -** Generate an instruction that will put the floating point -** value described by z[0..n-1] into register iMem. -** -** The z[] string will probably not be zero-terminated. But the -** z[n] character is guaranteed to be something that does not look -** like the continuation of the number. -*/ -static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ - if( ALWAYS(z!=0) ){ - double value; - char *zV; - sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); - assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ - if( negateFlag ) value = -value; - zV = dup8bytes(v, (char*)&value); - sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); - } -} -#endif - - -/* -** Generate an instruction that will put the integer describe by -** text z[0..n-1] into register iMem. -** -** Expr.u.zToken is always UTF8 and zero-terminated. -*/ -static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ - Vdbe *v = pParse->pVdbe; - if( pExpr->flags & EP_IntValue ){ - int i = pExpr->u.iValue; - assert( i>=0 ); - if( negFlag ) i = -i; - sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); - }else{ - int c; - i64 value; - const char *z = pExpr->u.zToken; - assert( z!=0 ); - c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); - if( c==0 || (c==2 && negFlag) ){ - char *zV; - if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } - zV = dup8bytes(v, (char*)&value); - sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); - }else{ -#ifdef SQLITE_OMIT_FLOATING_POINT - sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); -#else - codeReal(v, z, negFlag, iMem); -#endif - } - } -} - -/* -** Clear a cache entry. -*/ -static void cacheEntryClear(Parse *pParse, struct yColCache *p){ - if( p->tempReg ){ - if( pParse->nTempRegaTempReg) ){ - pParse->aTempReg[pParse->nTempReg++] = p->iReg; - } - p->tempReg = 0; - } -} - - -/* -** Record in the column cache that a particular column from a -** particular table is stored in a particular register. -*/ -SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ - int i; - int minLru; - int idxLru; - struct yColCache *p; - - assert( iReg>0 ); /* Register numbers are always positive */ - assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ - - /* The SQLITE_ColumnCache flag disables the column cache. This is used - ** for testing only - to verify that SQLite always gets the same answer - ** with and without the column cache. - */ - if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return; - - /* First replace any existing entry. - ** - ** Actually, the way the column cache is currently used, we are guaranteed - ** that the object will never already be in cache. Verify this guarantee. - */ -#ifndef NDEBUG - for(i=0, p=pParse->aColCache; iiReg==0 || p->iTable!=iTab || p->iColumn!=iCol ); - } -#endif - - /* Find an empty slot and replace it */ - for(i=0, p=pParse->aColCache; iiReg==0 ){ - p->iLevel = pParse->iCacheLevel; - p->iTable = iTab; - p->iColumn = iCol; - p->iReg = iReg; - p->tempReg = 0; - p->lru = pParse->iCacheCnt++; - return; - } - } - - /* Replace the last recently used */ - minLru = 0x7fffffff; - idxLru = -1; - for(i=0, p=pParse->aColCache; ilrulru; - } - } - if( ALWAYS(idxLru>=0) ){ - p = &pParse->aColCache[idxLru]; - p->iLevel = pParse->iCacheLevel; - p->iTable = iTab; - p->iColumn = iCol; - p->iReg = iReg; - p->tempReg = 0; - p->lru = pParse->iCacheCnt++; - return; - } -} - -/* -** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. -** Purge the range of registers from the column cache. -*/ -SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ - int i; - int iLast = iReg + nReg - 1; - struct yColCache *p; - for(i=0, p=pParse->aColCache; iiReg; - if( r>=iReg && r<=iLast ){ - cacheEntryClear(pParse, p); - p->iReg = 0; - } - } -} - -/* -** Remember the current column cache context. Any new entries added -** added to the column cache after this call are removed when the -** corresponding pop occurs. -*/ -SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ - pParse->iCacheLevel++; -} - -/* -** Remove from the column cache any entries that were added since the -** the previous N Push operations. In other words, restore the cache -** to the state it was in N Pushes ago. -*/ -SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse, int N){ - int i; - struct yColCache *p; - assert( N>0 ); - assert( pParse->iCacheLevel>=N ); - pParse->iCacheLevel -= N; - for(i=0, p=pParse->aColCache; iiReg && p->iLevel>pParse->iCacheLevel ){ - cacheEntryClear(pParse, p); - p->iReg = 0; - } - } -} - -/* -** When a cached column is reused, make sure that its register is -** no longer available as a temp register. ticket #3879: that same -** register might be in the cache in multiple places, so be sure to -** get them all. -*/ -static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ - int i; - struct yColCache *p; - for(i=0, p=pParse->aColCache; iiReg==iReg ){ - p->tempReg = 0; - } - } -} - -/* -** Generate code to extract the value of the iCol-th column of a table. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( - Vdbe *v, /* The VDBE under construction */ - Table *pTab, /* The table containing the value */ - int iTabCur, /* The cursor for this table */ - int iCol, /* Index of the column to extract */ - int regOut /* Extract the valud into this register */ -){ - if( iCol<0 || iCol==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); - }else{ - int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; - sqlite3VdbeAddOp3(v, op, iTabCur, iCol, regOut); - } - if( iCol>=0 ){ - sqlite3ColumnDefault(v, pTab, iCol, regOut); - } -} - -/* -** Generate code that will extract the iColumn-th column from -** table pTab and store the column value in a register. An effort -** is made to store the column value in register iReg, but this is -** not guaranteed. The location of the column value is returned. -** -** There must be an open cursor to pTab in iTable when this routine -** is called. If iColumn<0 then code is generated that extracts the rowid. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( - Parse *pParse, /* Parsing and code generating context */ - Table *pTab, /* Description of the table we are reading from */ - int iColumn, /* Index of the table column */ - int iTable, /* The cursor pointing to the table */ - int iReg, /* Store results here */ - u8 p5 /* P5 value for OP_Column */ -){ - Vdbe *v = pParse->pVdbe; - int i; - struct yColCache *p; - - for(i=0, p=pParse->aColCache; iiReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ - p->lru = pParse->iCacheCnt++; - sqlite3ExprCachePinRegister(pParse, p->iReg); - return p->iReg; - } - } - assert( v!=0 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); - if( p5 ){ - sqlite3VdbeChangeP5(v, p5); - }else{ - sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg); - } - return iReg; -} - -/* -** Clear all column cache entries. -*/ -SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ - int i; - struct yColCache *p; - - for(i=0, p=pParse->aColCache; iiReg ){ - cacheEntryClear(pParse, p); - p->iReg = 0; - } - } -} - -/* -** Record the fact that an affinity change has occurred on iCount -** registers starting with iStart. -*/ -SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ - sqlite3ExprCacheRemove(pParse, iStart, iCount); -} - -/* -** Generate code to move content from registers iFrom...iFrom+nReg-1 -** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ - int i; - struct yColCache *p; - assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); - sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1); - for(i=0, p=pParse->aColCache; iiReg; - if( x>=iFrom && xiReg += iTo-iFrom; - } - } -} - -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) -/* -** Return true if any register in the range iFrom..iTo (inclusive) -** is used as part of the column cache. -** -** This routine is used within assert() and testcase() macros only -** and does not appear in a normal build. -*/ -static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ - int i; - struct yColCache *p; - for(i=0, p=pParse->aColCache; iiReg; - if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ - } - return 0; -} -#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */ - -/* -** Generate code into the current Vdbe to evaluate the given -** expression. Attempt to store the results in register "target". -** Return the register where results are stored. -** -** With this routine, there is no guarantee that results will -** be stored in target. The result might be stored in some other -** register if it is convenient to do so. The calling function -** must check the return code and move the results to the desired -** register. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ - Vdbe *v = pParse->pVdbe; /* The VM under construction */ - int op; /* The opcode being coded */ - int inReg = target; /* Results stored in register inReg */ - int regFree1 = 0; /* If non-zero free this temporary register */ - int regFree2 = 0; /* If non-zero free this temporary register */ - int r1, r2, r3, r4; /* Various register numbers */ - sqlite3 *db = pParse->db; /* The database connection */ - - assert( target>0 && target<=pParse->nMem ); - if( v==0 ){ - assert( pParse->db->mallocFailed ); - return 0; - } - - if( pExpr==0 ){ - op = TK_NULL; - }else{ - op = pExpr->op; - } - switch( op ){ - case TK_AGG_COLUMN: { - AggInfo *pAggInfo = pExpr->pAggInfo; - struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; - if( !pAggInfo->directMode ){ - assert( pCol->iMem>0 ); - inReg = pCol->iMem; - break; - }else if( pAggInfo->useSortingIdx ){ - sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, - pCol->iSorterColumn, target); - break; - } - /* Otherwise, fall thru into the TK_COLUMN case */ - } - case TK_COLUMN: { - if( pExpr->iTable<0 ){ - /* This only happens when coding check constraints */ - assert( pParse->ckBase>0 ); - inReg = pExpr->iColumn + pParse->ckBase; - }else{ - inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, - pExpr->iColumn, pExpr->iTable, target, - pExpr->op2); - } - break; - } - case TK_INTEGER: { - codeInteger(pParse, pExpr, 0, target); - break; - } -#ifndef SQLITE_OMIT_FLOATING_POINT - case TK_FLOAT: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - codeReal(v, pExpr->u.zToken, 0, target); - break; - } -#endif - case TK_STRING: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); - break; - } - case TK_NULL: { - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - break; - } -#ifndef SQLITE_OMIT_BLOB_LITERAL - case TK_BLOB: { - int n; - const char *z; - char *zBlob; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); - assert( pExpr->u.zToken[1]=='\'' ); - z = &pExpr->u.zToken[2]; - n = sqlite3Strlen30(z) - 1; - assert( z[n]=='\'' ); - zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); - sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); - break; - } -#endif - case TK_VARIABLE: { - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - assert( pExpr->u.zToken!=0 ); - assert( pExpr->u.zToken[0]!=0 ); - sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); - if( pExpr->u.zToken[1]!=0 ){ - assert( pExpr->u.zToken[0]=='?' - || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 ); - sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC); - } - break; - } - case TK_REGISTER: { - inReg = pExpr->iTable; - break; - } - case TK_AS: { - inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - break; - } -#ifndef SQLITE_OMIT_CAST - case TK_CAST: { - /* Expressions of the form: CAST(pLeft AS token) */ - int aff, to_op; - inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - aff = sqlite3AffinityType(pExpr->u.zToken); - to_op = aff - SQLITE_AFF_TEXT + OP_ToText; - assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); - assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); - assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); - assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); - assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); - testcase( to_op==OP_ToText ); - testcase( to_op==OP_ToBlob ); - testcase( to_op==OP_ToNumeric ); - testcase( to_op==OP_ToInt ); - testcase( to_op==OP_ToReal ); - if( inReg!=target ){ - sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); - inReg = target; - } - sqlite3VdbeAddOp1(v, to_op, inReg); - testcase( usedAsColumnCache(pParse, inReg, inReg) ); - sqlite3ExprCacheAffinityChange(pParse, inReg, 1); - break; - } -#endif /* SQLITE_OMIT_CAST */ - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - assert( TK_LT==OP_Lt ); - assert( TK_LE==OP_Le ); - assert( TK_GT==OP_Gt ); - assert( TK_GE==OP_Ge ); - assert( TK_EQ==OP_Eq ); - assert( TK_NE==OP_Ne ); - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, inReg, SQLITE_STOREP2); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( op==TK_IS ); - testcase( op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (op==TK_IS) ? TK_EQ : TK_NE; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_AND: - case TK_OR: - case TK_PLUS: - case TK_STAR: - case TK_MINUS: - case TK_REM: - case TK_BITAND: - case TK_BITOR: - case TK_SLASH: - case TK_LSHIFT: - case TK_RSHIFT: - case TK_CONCAT: { - assert( TK_AND==OP_And ); - assert( TK_OR==OP_Or ); - assert( TK_PLUS==OP_Add ); - assert( TK_MINUS==OP_Subtract ); - assert( TK_REM==OP_Remainder ); - assert( TK_BITAND==OP_BitAnd ); - assert( TK_BITOR==OP_BitOr ); - assert( TK_SLASH==OP_Divide ); - assert( TK_LSHIFT==OP_ShiftLeft ); - assert( TK_RSHIFT==OP_ShiftRight ); - assert( TK_CONCAT==OP_Concat ); - testcase( op==TK_AND ); - testcase( op==TK_OR ); - testcase( op==TK_PLUS ); - testcase( op==TK_MINUS ); - testcase( op==TK_REM ); - testcase( op==TK_BITAND ); - testcase( op==TK_BITOR ); - testcase( op==TK_SLASH ); - testcase( op==TK_LSHIFT ); - testcase( op==TK_RSHIFT ); - testcase( op==TK_CONCAT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - sqlite3VdbeAddOp3(v, op, r2, r1, target); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_UMINUS: { - Expr *pLeft = pExpr->pLeft; - assert( pLeft ); - if( pLeft->op==TK_INTEGER ){ - codeInteger(pParse, pLeft, 1, target); -#ifndef SQLITE_OMIT_FLOATING_POINT - }else if( pLeft->op==TK_FLOAT ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - codeReal(v, pLeft->u.zToken, 1, target); -#endif - }else{ - regFree1 = r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); - sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); - testcase( regFree2==0 ); - } - inReg = target; - break; - } - case TK_BITNOT: - case TK_NOT: { - assert( TK_BITNOT==OP_BitNot ); - assert( TK_NOT==OP_Not ); - testcase( op==TK_BITNOT ); - testcase( op==TK_NOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - testcase( regFree1==0 ); - inReg = target; - sqlite3VdbeAddOp2(v, op, r1, inReg); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - int addr; - assert( TK_ISNULL==OP_IsNull ); - assert( TK_NOTNULL==OP_NotNull ); - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); - sqlite3VdbeAddOp2(v, OP_Integer, 1, target); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - testcase( regFree1==0 ); - addr = sqlite3VdbeAddOp1(v, op, r1); - sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); - sqlite3VdbeJumpHere(v, addr); - break; - } - case TK_AGG_FUNCTION: { - AggInfo *pInfo = pExpr->pAggInfo; - if( pInfo==0 ){ - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); - }else{ - inReg = pInfo->aFunc[pExpr->iAgg].iMem; - } - break; - } - case TK_CONST_FUNC: - case TK_FUNCTION: { - ExprList *pFarg; /* List of function arguments */ - int nFarg; /* Number of function arguments */ - FuncDef *pDef; /* The function definition object */ - int nId; /* Length of the function name in bytes */ - const char *zId; /* The function name */ - int constMask = 0; /* Mask of function arguments that are constant */ - int i; /* Loop counter */ - u8 enc = ENC(db); /* The text encoding used by this database */ - CollSeq *pColl = 0; /* A collating sequence */ - - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - testcase( op==TK_CONST_FUNC ); - testcase( op==TK_FUNCTION ); - if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ - pFarg = 0; - }else{ - pFarg = pExpr->x.pList; - } - nFarg = pFarg ? pFarg->nExpr : 0; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - zId = pExpr->u.zToken; - nId = sqlite3Strlen30(zId); - pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0); - if( pDef==0 ){ - sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId); - break; - } - - /* Attempt a direct implementation of the built-in COALESCE() and - ** IFNULL() functions. This avoids unnecessary evalation of - ** arguments past the first non-NULL argument. - */ - if( pDef->flags & SQLITE_FUNC_COALESCE ){ - int endCoalesce = sqlite3VdbeMakeLabel(v); - assert( nFarg>=2 ); - sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); - for(i=1; ia[i].pExpr, target); - sqlite3ExprCachePop(pParse, 1); - } - sqlite3VdbeResolveLabel(v, endCoalesce); - break; - } - - - if( pFarg ){ - r1 = sqlite3GetTempRange(pParse, nFarg); - - /* For length() and typeof() functions with a column argument, - ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG - ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data - ** loading. - */ - if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ - u8 exprOp; - assert( nFarg==1 ); - assert( pFarg->a[0].pExpr!=0 ); - exprOp = pFarg->a[0].pExpr->op; - if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ - assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); - assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); - testcase( pDef->flags==SQLITE_FUNC_LENGTH ); - pFarg->a[0].pExpr->op2 = pDef->flags; - } - } - - sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ - sqlite3ExprCodeExprList(pParse, pFarg, r1, 1); - sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */ - }else{ - r1 = 0; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Possibly overload the function if the first argument is - ** a virtual table column. - ** - ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the - ** second argument, not the first, as the argument to test to - ** see if it is a column in a virtual table. This is done because - ** the left operand of infix functions (the operand we want to - ** control overloading) ends up as the second argument to the - ** function. The expression "A glob B" is equivalent to - ** "glob(B,A). We want to use the A in "A glob B" to test - ** for function overloading. But we use the B term in "glob(B,A)". - */ - if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ - pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); - }else if( nFarg>0 ){ - pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); - } -#endif - for(i=0; ia[i].pExpr) ){ - constMask |= (1<flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ - pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); - } - } - if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){ - if( !pColl ) pColl = db->pDfltColl; - sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); - } - sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, - (char*)pDef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u8)nFarg); - if( nFarg ){ - sqlite3ReleaseTempRange(pParse, r1, nFarg); - } - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_EXISTS: - case TK_SELECT: { - testcase( op==TK_EXISTS ); - testcase( op==TK_SELECT ); - inReg = sqlite3CodeSubselect(pParse, pExpr, 0, 0); - break; - } - case TK_IN: { - int destIfFalse = sqlite3VdbeMakeLabel(v); - int destIfNull = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); - sqlite3VdbeAddOp2(v, OP_Integer, 1, target); - sqlite3VdbeResolveLabel(v, destIfFalse); - sqlite3VdbeAddOp2(v, OP_AddImm, target, 0); - sqlite3VdbeResolveLabel(v, destIfNull); - break; - } -#endif /* SQLITE_OMIT_SUBQUERY */ - - - /* - ** x BETWEEN y AND z - ** - ** This is equivalent to - ** - ** x>=y AND x<=z - ** - ** X is stored in pExpr->pLeft. - ** Y is stored in pExpr->pList->a[0].pExpr. - ** Z is stored in pExpr->pList->a[1].pExpr. - */ - case TK_BETWEEN: { - Expr *pLeft = pExpr->pLeft; - struct ExprList_item *pLItem = pExpr->x.pList->a; - Expr *pRight = pLItem->pExpr; - - r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - r3 = sqlite3GetTempReg(pParse); - r4 = sqlite3GetTempReg(pParse); - codeCompare(pParse, pLeft, pRight, OP_Ge, - r1, r2, r3, SQLITE_STOREP2); - pLItem++; - pRight = pLItem->pExpr; - sqlite3ReleaseTempReg(pParse, regFree2); - r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); - testcase( regFree2==0 ); - codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); - sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); - sqlite3ReleaseTempReg(pParse, r3); - sqlite3ReleaseTempReg(pParse, r4); - break; - } - case TK_COLLATE: - case TK_UPLUS: { - inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - break; - } - - case TK_TRIGGER: { - /* If the opcode is TK_TRIGGER, then the expression is a reference - ** to a column in the new.* or old.* pseudo-tables available to - ** trigger programs. In this case Expr.iTable is set to 1 for the - ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn - ** is set to the column of the pseudo-table to read, or to -1 to - ** read the rowid field. - ** - ** The expression is implemented using an OP_Param opcode. The p1 - ** parameter is set to 0 for an old.rowid reference, or to (i+1) - ** to reference another column of the old.* pseudo-table, where - ** i is the index of the column. For a new.rowid reference, p1 is - ** set to (n+1), where n is the number of columns in each pseudo-table. - ** For a reference to any other column in the new.* pseudo-table, p1 - ** is set to (n+2+i), where n and i are as defined previously. For - ** example, if the table on which triggers are being fired is - ** declared as: - ** - ** CREATE TABLE t1(a, b); - ** - ** Then p1 is interpreted as follows: - ** - ** p1==0 -> old.rowid p1==3 -> new.rowid - ** p1==1 -> old.a p1==4 -> new.a - ** p1==2 -> old.b p1==5 -> new.b - */ - Table *pTab = pExpr->pTab; - int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; - - assert( pExpr->iTable==0 || pExpr->iTable==1 ); - assert( pExpr->iColumn>=-1 && pExpr->iColumnnCol ); - assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey ); - assert( p1>=0 && p1<(pTab->nCol*2+2) ); - - sqlite3VdbeAddOp2(v, OP_Param, p1, target); - VdbeComment((v, "%s.%s -> $%d", - (pExpr->iTable ? "new" : "old"), - (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), - target - )); - -#ifndef SQLITE_OMIT_FLOATING_POINT - /* If the column has REAL affinity, it may currently be stored as an - ** integer. Use OP_RealAffinity to make sure it is really real. */ - if( pExpr->iColumn>=0 - && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL - ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, target); - } -#endif - break; - } - - - /* - ** Form A: - ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END - ** - ** Form B: - ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END - ** - ** Form A is can be transformed into the equivalent form B as follows: - ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ... - ** WHEN x=eN THEN rN ELSE y END - ** - ** X (if it exists) is in pExpr->pLeft. - ** Y is in pExpr->pRight. The Y is also optional. If there is no - ** ELSE clause and no other term matches, then the result of the - ** exprssion is NULL. - ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1]. - ** - ** The result of the expression is the Ri for the first matching Ei, - ** or if there is no matching Ei, the ELSE term Y, or if there is - ** no ELSE term, NULL. - */ - default: assert( op==TK_CASE ); { - int endLabel; /* GOTO label for end of CASE stmt */ - int nextCase; /* GOTO label for next WHEN clause */ - int nExpr; /* 2x number of WHEN terms */ - int i; /* Loop counter */ - ExprList *pEList; /* List of WHEN terms */ - struct ExprList_item *aListelem; /* Array of WHEN terms */ - Expr opCompare; /* The X==Ei expression */ - Expr cacheX; /* Cached expression X */ - Expr *pX; /* The X expression */ - Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ - VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; ) - - assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); - assert((pExpr->x.pList->nExpr % 2) == 0); - assert(pExpr->x.pList->nExpr > 0); - pEList = pExpr->x.pList; - aListelem = pEList->a; - nExpr = pEList->nExpr; - endLabel = sqlite3VdbeMakeLabel(v); - if( (pX = pExpr->pLeft)!=0 ){ - cacheX = *pX; - testcase( pX->op==TK_COLUMN ); - testcase( pX->op==TK_REGISTER ); - cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); - testcase( regFree1==0 ); - cacheX.op = TK_REGISTER; - opCompare.op = TK_EQ; - opCompare.pLeft = &cacheX; - pTest = &opCompare; - /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001: - ** The value in regFree1 might get SCopy-ed into the file result. - ** So make sure that the regFree1 register is not reused for other - ** purposes and possibly overwritten. */ - regFree1 = 0; - } - for(i=0; iop==TK_COLUMN ); - sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); - testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); - testcase( aListelem[i+1].pExpr->op==TK_REGISTER ); - sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); - sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel); - sqlite3ExprCachePop(pParse, 1); - sqlite3VdbeResolveLabel(v, nextCase); - } - if( pExpr->pRight ){ - sqlite3ExprCachePush(pParse); - sqlite3ExprCode(pParse, pExpr->pRight, target); - sqlite3ExprCachePop(pParse, 1); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - } - assert( db->mallocFailed || pParse->nErr>0 - || pParse->iCacheLevel==iCacheLevel ); - sqlite3VdbeResolveLabel(v, endLabel); - break; - } -#ifndef SQLITE_OMIT_TRIGGER - case TK_RAISE: { - assert( pExpr->affinity==OE_Rollback - || pExpr->affinity==OE_Abort - || pExpr->affinity==OE_Fail - || pExpr->affinity==OE_Ignore - ); - if( !pParse->pTriggerTab ){ - sqlite3ErrorMsg(pParse, - "RAISE() may only be used within a trigger-program"); - return 0; - } - if( pExpr->affinity==OE_Abort ){ - sqlite3MayAbort(pParse); - } - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - if( pExpr->affinity==OE_Ignore ){ - sqlite3VdbeAddOp4( - v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); - }else{ - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, - pExpr->affinity, pExpr->u.zToken, 0); - } - - break; - } -#endif - } - sqlite3ReleaseTempReg(pParse, regFree1); - sqlite3ReleaseTempReg(pParse, regFree2); - return inReg; -} - -/* -** Generate code to evaluate an expression and store the results -** into a register. Return the register number where the results -** are stored. -** -** If the register is a temporary register that can be deallocated, -** then write its number into *pReg. If the result register is not -** a temporary, then set *pReg to zero. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ - int r1 = sqlite3GetTempReg(pParse); - int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); - if( r2==r1 ){ - *pReg = r1; - }else{ - sqlite3ReleaseTempReg(pParse, r1); - *pReg = 0; - } - return r2; -} - -/* -** Generate code that will evaluate expression pExpr and store the -** results in register target. The results are guaranteed to appear -** in register target. -*/ -SQLITE_PRIVATE int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ - int inReg; - - assert( target>0 && target<=pParse->nMem ); - if( pExpr && pExpr->op==TK_REGISTER ){ - sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target); - }else{ - inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); - assert( pParse->pVdbe || pParse->db->mallocFailed ); - if( inReg!=target && pParse->pVdbe ){ - sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); - } - } - return target; -} - -/* -** Generate code that evalutes the given expression and puts the result -** in register target. -** -** Also make a copy of the expression results into another "cache" register -** and modify the expression so that the next time it is evaluated, -** the result is a copy of the cache register. -** -** This routine is used for expressions that are used multiple -** times. They are evaluated once and the results of the expression -** are reused. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ - Vdbe *v = pParse->pVdbe; - int inReg; - inReg = sqlite3ExprCode(pParse, pExpr, target); - assert( target>0 ); - /* This routine is called for terms to INSERT or UPDATE. And the only - ** other place where expressions can be converted into TK_REGISTER is - ** in WHERE clause processing. So as currently implemented, there is - ** no way for a TK_REGISTER to exist here. But it seems prudent to - ** keep the ALWAYS() in case the conditions above change with future - ** modifications or enhancements. */ - if( ALWAYS(pExpr->op!=TK_REGISTER) ){ - int iMem; - iMem = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem); - pExpr->iTable = iMem; - pExpr->op2 = pExpr->op; - pExpr->op = TK_REGISTER; - } - return inReg; -} - -#if defined(SQLITE_ENABLE_TREE_EXPLAIN) -/* -** Generate a human-readable explanation of an expression tree. -*/ -SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){ - int op; /* The opcode being coded */ - const char *zBinOp = 0; /* Binary operator */ - const char *zUniOp = 0; /* Unary operator */ - if( pExpr==0 ){ - op = TK_NULL; - }else{ - op = pExpr->op; - } - switch( op ){ - case TK_AGG_COLUMN: { - sqlite3ExplainPrintf(pOut, "AGG{%d:%d}", - pExpr->iTable, pExpr->iColumn); - break; - } - case TK_COLUMN: { - if( pExpr->iTable<0 ){ - /* This only happens when coding check constraints */ - sqlite3ExplainPrintf(pOut, "COLUMN(%d)", pExpr->iColumn); - }else{ - sqlite3ExplainPrintf(pOut, "{%d:%d}", - pExpr->iTable, pExpr->iColumn); - } - break; - } - case TK_INTEGER: { - if( pExpr->flags & EP_IntValue ){ - sqlite3ExplainPrintf(pOut, "%d", pExpr->u.iValue); - }else{ - sqlite3ExplainPrintf(pOut, "%s", pExpr->u.zToken); - } - break; - } -#ifndef SQLITE_OMIT_FLOATING_POINT - case TK_FLOAT: { - sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken); - break; - } -#endif - case TK_STRING: { - sqlite3ExplainPrintf(pOut,"%Q", pExpr->u.zToken); - break; - } - case TK_NULL: { - sqlite3ExplainPrintf(pOut,"NULL"); - break; - } -#ifndef SQLITE_OMIT_BLOB_LITERAL - case TK_BLOB: { - sqlite3ExplainPrintf(pOut,"%s", pExpr->u.zToken); - break; - } -#endif - case TK_VARIABLE: { - sqlite3ExplainPrintf(pOut,"VARIABLE(%s,%d)", - pExpr->u.zToken, pExpr->iColumn); - break; - } - case TK_REGISTER: { - sqlite3ExplainPrintf(pOut,"REGISTER(%d)", pExpr->iTable); - break; - } - case TK_AS: { - sqlite3ExplainExpr(pOut, pExpr->pLeft); - break; - } -#ifndef SQLITE_OMIT_CAST - case TK_CAST: { - /* Expressions of the form: CAST(pLeft AS token) */ - const char *zAff = "unk"; - switch( sqlite3AffinityType(pExpr->u.zToken) ){ - case SQLITE_AFF_TEXT: zAff = "TEXT"; break; - case SQLITE_AFF_NONE: zAff = "NONE"; break; - case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break; - case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break; - case SQLITE_AFF_REAL: zAff = "REAL"; break; - } - sqlite3ExplainPrintf(pOut, "CAST-%s(", zAff); - sqlite3ExplainExpr(pOut, pExpr->pLeft); - sqlite3ExplainPrintf(pOut, ")"); - break; - } -#endif /* SQLITE_OMIT_CAST */ - case TK_LT: zBinOp = "LT"; break; - case TK_LE: zBinOp = "LE"; break; - case TK_GT: zBinOp = "GT"; break; - case TK_GE: zBinOp = "GE"; break; - case TK_NE: zBinOp = "NE"; break; - case TK_EQ: zBinOp = "EQ"; break; - case TK_IS: zBinOp = "IS"; break; - case TK_ISNOT: zBinOp = "ISNOT"; break; - case TK_AND: zBinOp = "AND"; break; - case TK_OR: zBinOp = "OR"; break; - case TK_PLUS: zBinOp = "ADD"; break; - case TK_STAR: zBinOp = "MUL"; break; - case TK_MINUS: zBinOp = "SUB"; break; - case TK_REM: zBinOp = "REM"; break; - case TK_BITAND: zBinOp = "BITAND"; break; - case TK_BITOR: zBinOp = "BITOR"; break; - case TK_SLASH: zBinOp = "DIV"; break; - case TK_LSHIFT: zBinOp = "LSHIFT"; break; - case TK_RSHIFT: zBinOp = "RSHIFT"; break; - case TK_CONCAT: zBinOp = "CONCAT"; break; - - case TK_UMINUS: zUniOp = "UMINUS"; break; - case TK_UPLUS: zUniOp = "UPLUS"; break; - case TK_BITNOT: zUniOp = "BITNOT"; break; - case TK_NOT: zUniOp = "NOT"; break; - case TK_ISNULL: zUniOp = "ISNULL"; break; - case TK_NOTNULL: zUniOp = "NOTNULL"; break; - - case TK_COLLATE: { - sqlite3ExplainExpr(pOut, pExpr->pLeft); - sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken); - break; - } - - case TK_AGG_FUNCTION: - case TK_CONST_FUNC: - case TK_FUNCTION: { - ExprList *pFarg; /* List of function arguments */ - if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ - pFarg = 0; - }else{ - pFarg = pExpr->x.pList; - } - if( op==TK_AGG_FUNCTION ){ - sqlite3ExplainPrintf(pOut, "AGG_FUNCTION%d:%s(", - pExpr->op2, pExpr->u.zToken); - }else{ - sqlite3ExplainPrintf(pOut, "FUNCTION:%s(", pExpr->u.zToken); - } - if( pFarg ){ - sqlite3ExplainExprList(pOut, pFarg); - } - sqlite3ExplainPrintf(pOut, ")"); - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_EXISTS: { - sqlite3ExplainPrintf(pOut, "EXISTS("); - sqlite3ExplainSelect(pOut, pExpr->x.pSelect); - sqlite3ExplainPrintf(pOut,")"); - break; - } - case TK_SELECT: { - sqlite3ExplainPrintf(pOut, "("); - sqlite3ExplainSelect(pOut, pExpr->x.pSelect); - sqlite3ExplainPrintf(pOut, ")"); - break; - } - case TK_IN: { - sqlite3ExplainPrintf(pOut, "IN("); - sqlite3ExplainExpr(pOut, pExpr->pLeft); - sqlite3ExplainPrintf(pOut, ","); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - sqlite3ExplainSelect(pOut, pExpr->x.pSelect); - }else{ - sqlite3ExplainExprList(pOut, pExpr->x.pList); - } - sqlite3ExplainPrintf(pOut, ")"); - break; - } -#endif /* SQLITE_OMIT_SUBQUERY */ - - /* - ** x BETWEEN y AND z - ** - ** This is equivalent to - ** - ** x>=y AND x<=z - ** - ** X is stored in pExpr->pLeft. - ** Y is stored in pExpr->pList->a[0].pExpr. - ** Z is stored in pExpr->pList->a[1].pExpr. - */ - case TK_BETWEEN: { - Expr *pX = pExpr->pLeft; - Expr *pY = pExpr->x.pList->a[0].pExpr; - Expr *pZ = pExpr->x.pList->a[1].pExpr; - sqlite3ExplainPrintf(pOut, "BETWEEN("); - sqlite3ExplainExpr(pOut, pX); - sqlite3ExplainPrintf(pOut, ","); - sqlite3ExplainExpr(pOut, pY); - sqlite3ExplainPrintf(pOut, ","); - sqlite3ExplainExpr(pOut, pZ); - sqlite3ExplainPrintf(pOut, ")"); - break; - } - case TK_TRIGGER: { - /* If the opcode is TK_TRIGGER, then the expression is a reference - ** to a column in the new.* or old.* pseudo-tables available to - ** trigger programs. In this case Expr.iTable is set to 1 for the - ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn - ** is set to the column of the pseudo-table to read, or to -1 to - ** read the rowid field. - */ - sqlite3ExplainPrintf(pOut, "%s(%d)", - pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn); - break; - } - case TK_CASE: { - sqlite3ExplainPrintf(pOut, "CASE("); - sqlite3ExplainExpr(pOut, pExpr->pLeft); - sqlite3ExplainPrintf(pOut, ","); - sqlite3ExplainExprList(pOut, pExpr->x.pList); - break; - } -#ifndef SQLITE_OMIT_TRIGGER - case TK_RAISE: { - const char *zType = "unk"; - switch( pExpr->affinity ){ - case OE_Rollback: zType = "rollback"; break; - case OE_Abort: zType = "abort"; break; - case OE_Fail: zType = "fail"; break; - case OE_Ignore: zType = "ignore"; break; - } - sqlite3ExplainPrintf(pOut, "RAISE-%s(%s)", zType, pExpr->u.zToken); - break; - } -#endif - } - if( zBinOp ){ - sqlite3ExplainPrintf(pOut,"%s(", zBinOp); - sqlite3ExplainExpr(pOut, pExpr->pLeft); - sqlite3ExplainPrintf(pOut,","); - sqlite3ExplainExpr(pOut, pExpr->pRight); - sqlite3ExplainPrintf(pOut,")"); - }else if( zUniOp ){ - sqlite3ExplainPrintf(pOut,"%s(", zUniOp); - sqlite3ExplainExpr(pOut, pExpr->pLeft); - sqlite3ExplainPrintf(pOut,")"); - } -} -#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */ - -#if defined(SQLITE_ENABLE_TREE_EXPLAIN) -/* -** Generate a human-readable explanation of an expression list. -*/ -SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){ - int i; - if( pList==0 || pList->nExpr==0 ){ - sqlite3ExplainPrintf(pOut, "(empty-list)"); - return; - }else if( pList->nExpr==1 ){ - sqlite3ExplainExpr(pOut, pList->a[0].pExpr); - }else{ - sqlite3ExplainPush(pOut); - for(i=0; inExpr; i++){ - sqlite3ExplainPrintf(pOut, "item[%d] = ", i); - sqlite3ExplainPush(pOut); - sqlite3ExplainExpr(pOut, pList->a[i].pExpr); - sqlite3ExplainPop(pOut); - if( pList->a[i].zName ){ - sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName); - } - if( pList->a[i].bSpanIsTab ){ - sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan); - } - if( inExpr-1 ){ - sqlite3ExplainNL(pOut); - } - } - sqlite3ExplainPop(pOut); - } -} -#endif /* SQLITE_DEBUG */ - -/* -** Return TRUE if pExpr is an constant expression that is appropriate -** for factoring out of a loop. Appropriate expressions are: -** -** * Any expression that evaluates to two or more opcodes. -** -** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null, -** or OP_Variable that does not need to be placed in a -** specific register. -** -** There is no point in factoring out single-instruction constant -** expressions that need to be placed in a particular register. -** We could factor them out, but then we would end up adding an -** OP_SCopy instruction to move the value into the correct register -** later. We might as well just use the original instruction and -** avoid the OP_SCopy. -*/ -static int isAppropriateForFactoring(Expr *p){ - if( !sqlite3ExprIsConstantNotJoin(p) ){ - return 0; /* Only constant expressions are appropriate for factoring */ - } - if( (p->flags & EP_FixedDest)==0 ){ - return 1; /* Any constant without a fixed destination is appropriate */ - } - while( p->op==TK_UPLUS ) p = p->pLeft; - switch( p->op ){ -#ifndef SQLITE_OMIT_BLOB_LITERAL - case TK_BLOB: -#endif - case TK_VARIABLE: - case TK_INTEGER: - case TK_FLOAT: - case TK_NULL: - case TK_STRING: { - testcase( p->op==TK_BLOB ); - testcase( p->op==TK_VARIABLE ); - testcase( p->op==TK_INTEGER ); - testcase( p->op==TK_FLOAT ); - testcase( p->op==TK_NULL ); - testcase( p->op==TK_STRING ); - /* Single-instruction constants with a fixed destination are - ** better done in-line. If we factor them, they will just end - ** up generating an OP_SCopy to move the value to the destination - ** register. */ - return 0; - } - case TK_UMINUS: { - if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){ - return 0; - } - break; - } - default: { - break; - } - } - return 1; -} - -/* -** If pExpr is a constant expression that is appropriate for -** factoring out of a loop, then evaluate the expression -** into a register and convert the expression into a TK_REGISTER -** expression. -*/ -static int evalConstExpr(Walker *pWalker, Expr *pExpr){ - Parse *pParse = pWalker->pParse; - switch( pExpr->op ){ - case TK_IN: - case TK_REGISTER: { - return WRC_Prune; - } - case TK_COLLATE: { - return WRC_Continue; - } - case TK_FUNCTION: - case TK_AGG_FUNCTION: - case TK_CONST_FUNC: { - /* The arguments to a function have a fixed destination. - ** Mark them this way to avoid generated unneeded OP_SCopy - ** instructions. - */ - ExprList *pList = pExpr->x.pList; - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - if( pList ){ - int i = pList->nExpr; - struct ExprList_item *pItem = pList->a; - for(; i>0; i--, pItem++){ - if( ALWAYS(pItem->pExpr) ) pItem->pExpr->flags |= EP_FixedDest; - } - } - break; - } - } - if( isAppropriateForFactoring(pExpr) ){ - int r1 = ++pParse->nMem; - int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); - /* If r2!=r1, it means that register r1 is never used. That is harmless - ** but suboptimal, so we want to know about the situation to fix it. - ** Hence the following assert: */ - assert( r2==r1 ); - pExpr->op2 = pExpr->op; - pExpr->op = TK_REGISTER; - pExpr->iTable = r2; - return WRC_Prune; - } - return WRC_Continue; -} - -/* -** Preevaluate constant subexpressions within pExpr and store the -** results in registers. Modify pExpr so that the constant subexpresions -** are TK_REGISTER opcodes that refer to the precomputed values. -** -** This routine is a no-op if the jump to the cookie-check code has -** already occur. Since the cookie-check jump is generated prior to -** any other serious processing, this check ensures that there is no -** way to accidently bypass the constant initializations. -** -** This routine is also a no-op if the SQLITE_FactorOutConst optimization -** is disabled via the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) -** interface. This allows test logic to verify that the same answer is -** obtained for queries regardless of whether or not constants are -** precomputed into registers or if they are inserted in-line. -*/ -SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ - Walker w; - if( pParse->cookieGoto ) return; - if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return; - memset(&w, 0, sizeof(w)); - w.xExprCallback = evalConstExpr; - w.pParse = pParse; - sqlite3WalkExpr(&w, pExpr); -} - - -/* -** Generate code that pushes the value of every element of the given -** expression list into a sequence of registers beginning at target. -** -** Return the number of elements evaluated. -*/ -SQLITE_PRIVATE int sqlite3ExprCodeExprList( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* The expression list to be coded */ - int target, /* Where to write results */ - int doHardCopy /* Make a hard copy of every element */ -){ - struct ExprList_item *pItem; - int i, n; - assert( pList!=0 ); - assert( target>0 ); - assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ - n = pList->nExpr; - for(pItem=pList->a, i=0; ipExpr; - int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); - if( inReg!=target+i ){ - sqlite3VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy, - inReg, target+i); - } - } - return n; -} - -/* -** Generate code for a BETWEEN operator. -** -** x BETWEEN y AND z -** -** The above is equivalent to -** -** x>=y AND x<=z -** -** Code it as such, taking care to do the common subexpression -** elementation of x. -*/ -static void exprCodeBetween( - Parse *pParse, /* Parsing and code generating context */ - Expr *pExpr, /* The BETWEEN expression */ - int dest, /* Jump here if the jump is taken */ - int jumpIfTrue, /* Take the jump if the BETWEEN is true */ - int jumpIfNull /* Take the jump if the BETWEEN is NULL */ -){ - Expr exprAnd; /* The AND operator in x>=y AND x<=z */ - Expr compLeft; /* The x>=y term */ - Expr compRight; /* The x<=z term */ - Expr exprX; /* The x subexpression */ - int regFree1 = 0; /* Temporary use register */ - - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - exprX = *pExpr->pLeft; - exprAnd.op = TK_AND; - exprAnd.pLeft = &compLeft; - exprAnd.pRight = &compRight; - compLeft.op = TK_GE; - compLeft.pLeft = &exprX; - compLeft.pRight = pExpr->x.pList->a[0].pExpr; - compRight.op = TK_LE; - compRight.pLeft = &exprX; - compRight.pRight = pExpr->x.pList->a[1].pExpr; - exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1); - exprX.op = TK_REGISTER; - if( jumpIfTrue ){ - sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull); - }else{ - sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull); - } - sqlite3ReleaseTempReg(pParse, regFree1); - - /* Ensure adequate test coverage */ - testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1==0 ); - testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1!=0 ); - testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1==0 ); - testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1!=0 ); - testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1==0 ); - testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1!=0 ); - testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1==0 ); - testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1!=0 ); -} - -/* -** Generate code for a boolean expression such that a jump is made -** to the label "dest" if the expression is true but execution -** continues straight thru if the expression is false. -** -** If the expression evaluates to NULL (neither true nor false), then -** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL. -** -** This code depends on the fact that certain token values (ex: TK_EQ) -** are the same as opcode values (ex: OP_Eq) that implement the corresponding -** operation. Special comments in vdbe.c and the mkopcodeh.awk script in -** the make process cause these values to align. Assert()s in the code -** below verify that the numbers are aligned correctly. -*/ -SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ - Vdbe *v = pParse->pVdbe; - int op = 0; - int regFree1 = 0; - int regFree2 = 0; - int r1, r2; - - assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); - if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ - if( NEVER(pExpr==0) ) return; /* No way this can happen */ - op = pExpr->op; - switch( op ){ - case TK_AND: { - int d2 = sqlite3VdbeMakeLabel(v); - testcase( jumpIfNull==0 ); - sqlite3ExprCachePush(pParse); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - sqlite3ExprCachePop(pParse, 1); - break; - } - case TK_OR: { - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - break; - } - case TK_NOT: { - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - break; - } - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - assert( TK_LT==OP_Lt ); - assert( TK_LE==OP_Le ); - assert( TK_GT==OP_Gt ); - assert( TK_GE==OP_Ge ); - assert( TK_EQ==OP_Eq ); - assert( TK_NE==OP_Ne ); - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); - testcase( jumpIfNull==0 ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( op==TK_IS ); - testcase( op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (op==TK_IS) ? TK_EQ : TK_NE; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - assert( TK_ISNULL==OP_IsNull ); - assert( TK_NOTNULL==OP_NotNull ); - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeAddOp2(v, op, r1, dest); - testcase( regFree1==0 ); - break; - } - case TK_BETWEEN: { - testcase( jumpIfNull==0 ); - exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull); - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_IN: { - int destIfFalse = sqlite3VdbeMakeLabel(v); - int destIfNull = jumpIfNull ? dest : destIfFalse; - sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); - sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); - sqlite3VdbeResolveLabel(v, destIfFalse); - break; - } -#endif - default: { - r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); - sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); - testcase( regFree1==0 ); - testcase( jumpIfNull==0 ); - break; - } - } - sqlite3ReleaseTempReg(pParse, regFree1); - sqlite3ReleaseTempReg(pParse, regFree2); -} - -/* -** Generate code for a boolean expression such that a jump is made -** to the label "dest" if the expression is false but execution -** continues straight thru if the expression is true. -** -** If the expression evaluates to NULL (neither true nor false) then -** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull -** is 0. -*/ -SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ - Vdbe *v = pParse->pVdbe; - int op = 0; - int regFree1 = 0; - int regFree2 = 0; - int r1, r2; - - assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); - if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ - if( pExpr==0 ) return; - - /* The value of pExpr->op and op are related as follows: - ** - ** pExpr->op op - ** --------- ---------- - ** TK_ISNULL OP_NotNull - ** TK_NOTNULL OP_IsNull - ** TK_NE OP_Eq - ** TK_EQ OP_Ne - ** TK_GT OP_Le - ** TK_LE OP_Gt - ** TK_GE OP_Lt - ** TK_LT OP_Ge - ** - ** For other values of pExpr->op, op is undefined and unused. - ** The value of TK_ and OP_ constants are arranged such that we - ** can compute the mapping above using the following expression. - ** Assert()s verify that the computation is correct. - */ - op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1); - - /* Verify correct alignment of TK_ and OP_ constants - */ - assert( pExpr->op!=TK_ISNULL || op==OP_NotNull ); - assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull ); - assert( pExpr->op!=TK_NE || op==OP_Eq ); - assert( pExpr->op!=TK_EQ || op==OP_Ne ); - assert( pExpr->op!=TK_LT || op==OP_Ge ); - assert( pExpr->op!=TK_LE || op==OP_Gt ); - assert( pExpr->op!=TK_GT || op==OP_Le ); - assert( pExpr->op!=TK_GE || op==OP_Lt ); - - switch( pExpr->op ){ - case TK_AND: { - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - break; - } - case TK_OR: { - int d2 = sqlite3VdbeMakeLabel(v); - testcase( jumpIfNull==0 ); - sqlite3ExprCachePush(pParse); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - sqlite3ExprCachePop(pParse, 1); - break; - } - case TK_NOT: { - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); - break; - } - case TK_LT: - case TK_LE: - case TK_GT: - case TK_GE: - case TK_NE: - case TK_EQ: { - testcase( op==TK_LT ); - testcase( op==TK_LE ); - testcase( op==TK_GT ); - testcase( op==TK_GE ); - testcase( op==TK_EQ ); - testcase( op==TK_NE ); - testcase( jumpIfNull==0 ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, jumpIfNull); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_IS: - case TK_ISNOT: { - testcase( pExpr->op==TK_IS ); - testcase( pExpr->op==TK_ISNOT ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; - codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, - r1, r2, dest, SQLITE_NULLEQ); - testcase( regFree1==0 ); - testcase( regFree2==0 ); - break; - } - case TK_ISNULL: - case TK_NOTNULL: { - testcase( op==TK_ISNULL ); - testcase( op==TK_NOTNULL ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - sqlite3VdbeAddOp2(v, op, r1, dest); - testcase( regFree1==0 ); - break; - } - case TK_BETWEEN: { - testcase( jumpIfNull==0 ); - exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull); - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_IN: { - if( jumpIfNull ){ - sqlite3ExprCodeIN(pParse, pExpr, dest, dest); - }else{ - int destIfNull = sqlite3VdbeMakeLabel(v); - sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull); - sqlite3VdbeResolveLabel(v, destIfNull); - } - break; - } -#endif - default: { - r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); - sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); - testcase( regFree1==0 ); - testcase( jumpIfNull==0 ); - break; - } - } - sqlite3ReleaseTempReg(pParse, regFree1); - sqlite3ReleaseTempReg(pParse, regFree2); -} - -/* -** Do a deep comparison of two expression trees. Return 0 if the two -** expressions are completely identical. Return 1 if they differ only -** by a COLLATE operator at the top level. Return 2 if there are differences -** other than the top-level COLLATE operator. -** -** Sometimes this routine will return 2 even if the two expressions -** really are equivalent. If we cannot prove that the expressions are -** identical, we return 2 just to be safe. So if this routine -** returns 2, then you do not really know for certain if the two -** expressions are the same. But if you get a 0 or 1 return, then you -** can be sure the expressions are the same. In the places where -** this routine is used, it does not hurt to get an extra 2 - that -** just might result in some slightly slower code. But returning -** an incorrect 0 or 1 could lead to a malfunction. -*/ -SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){ - if( pA==0||pB==0 ){ - return pB==pA ? 0 : 2; - } - assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); - assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); - if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ - return 2; - } - if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; - if( pA->op!=pB->op ){ - if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){ - return 1; - } - if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){ - return 1; - } - return 2; - } - if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; - if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; - if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; - if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; - if( ExprHasProperty(pA, EP_IntValue) ){ - if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ - return 2; - } - }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ - if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; - if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ - return pA->op==TK_COLLATE ? 1 : 2; - } - } - return 0; -} - -/* -** Compare two ExprList objects. Return 0 if they are identical and -** non-zero if they differ in any way. -** -** This routine might return non-zero for equivalent ExprLists. The -** only consequence will be disabled optimizations. But this routine -** must never return 0 if the two ExprList objects are different, or -** a malfunction will result. -** -** Two NULL pointers are considered to be the same. But a NULL pointer -** always differs from a non-NULL pointer. -*/ -SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){ - int i; - if( pA==0 && pB==0 ) return 0; - if( pA==0 || pB==0 ) return 1; - if( pA->nExpr!=pB->nExpr ) return 1; - for(i=0; inExpr; i++){ - Expr *pExprA = pA->a[i].pExpr; - Expr *pExprB = pB->a[i].pExpr; - if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; - if( sqlite3ExprCompare(pExprA, pExprB) ) return 1; - } - return 0; -} - -/* -** An instance of the following structure is used by the tree walker -** to count references to table columns in the arguments of an -** aggregate function, in order to implement the -** sqlite3FunctionThisSrc() routine. -*/ -struct SrcCount { - SrcList *pSrc; /* One particular FROM clause in a nested query */ - int nThis; /* Number of references to columns in pSrcList */ - int nOther; /* Number of references to columns in other FROM clauses */ -}; - -/* -** Count the number of references to columns. -*/ -static int exprSrcCount(Walker *pWalker, Expr *pExpr){ - /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc() - ** is always called before sqlite3ExprAnalyzeAggregates() and so the - ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If - ** sqlite3FunctionUsesThisSrc() is used differently in the future, the - ** NEVER() will need to be removed. */ - if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){ - int i; - struct SrcCount *p = pWalker->u.pSrcCount; - SrcList *pSrc = p->pSrc; - for(i=0; inSrc; i++){ - if( pExpr->iTable==pSrc->a[i].iCursor ) break; - } - if( inSrc ){ - p->nThis++; - }else{ - p->nOther++; - } - } - return WRC_Continue; -} - -/* -** Determine if any of the arguments to the pExpr Function reference -** pSrcList. Return true if they do. Also return true if the function -** has no arguments or has only constant arguments. Return false if pExpr -** references columns but not columns of tables found in pSrcList. -*/ -SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ - Walker w; - struct SrcCount cnt; - assert( pExpr->op==TK_AGG_FUNCTION ); - memset(&w, 0, sizeof(w)); - w.xExprCallback = exprSrcCount; - w.u.pSrcCount = &cnt; - cnt.pSrc = pSrcList; - cnt.nThis = 0; - cnt.nOther = 0; - sqlite3WalkExprList(&w, pExpr->x.pList); - return cnt.nThis>0 || cnt.nOther==0; -} - -/* -** Add a new element to the pAggInfo->aCol[] array. Return the index of -** the new element. Return a negative number if malloc fails. -*/ -static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){ - int i; - pInfo->aCol = sqlite3ArrayAllocate( - db, - pInfo->aCol, - sizeof(pInfo->aCol[0]), - &pInfo->nColumn, - &i - ); - return i; -} - -/* -** Add a new element to the pAggInfo->aFunc[] array. Return the index of -** the new element. Return a negative number if malloc fails. -*/ -static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ - int i; - pInfo->aFunc = sqlite3ArrayAllocate( - db, - pInfo->aFunc, - sizeof(pInfo->aFunc[0]), - &pInfo->nFunc, - &i - ); - return i; -} - -/* -** This is the xExprCallback for a tree walker. It is used to -** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates -** for additional information. -*/ -static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ - int i; - NameContext *pNC = pWalker->u.pNC; - Parse *pParse = pNC->pParse; - SrcList *pSrcList = pNC->pSrcList; - AggInfo *pAggInfo = pNC->pAggInfo; - - switch( pExpr->op ){ - case TK_AGG_COLUMN: - case TK_COLUMN: { - testcase( pExpr->op==TK_AGG_COLUMN ); - testcase( pExpr->op==TK_COLUMN ); - /* Check to see if the column is in one of the tables in the FROM - ** clause of the aggregate query */ - if( ALWAYS(pSrcList!=0) ){ - struct SrcList_item *pItem = pSrcList->a; - for(i=0; inSrc; i++, pItem++){ - struct AggInfo_col *pCol; - assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); - if( pExpr->iTable==pItem->iCursor ){ - /* If we reach this point, it means that pExpr refers to a table - ** that is in the FROM clause of the aggregate query. - ** - ** Make an entry for the column in pAggInfo->aCol[] if there - ** is not an entry there already. - */ - int k; - pCol = pAggInfo->aCol; - for(k=0; knColumn; k++, pCol++){ - if( pCol->iTable==pExpr->iTable && - pCol->iColumn==pExpr->iColumn ){ - break; - } - } - if( (k>=pAggInfo->nColumn) - && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 - ){ - pCol = &pAggInfo->aCol[k]; - pCol->pTab = pExpr->pTab; - pCol->iTable = pExpr->iTable; - pCol->iColumn = pExpr->iColumn; - pCol->iMem = ++pParse->nMem; - pCol->iSorterColumn = -1; - pCol->pExpr = pExpr; - if( pAggInfo->pGroupBy ){ - int j, n; - ExprList *pGB = pAggInfo->pGroupBy; - struct ExprList_item *pTerm = pGB->a; - n = pGB->nExpr; - for(j=0; jpExpr; - if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable && - pE->iColumn==pExpr->iColumn ){ - pCol->iSorterColumn = j; - break; - } - } - } - if( pCol->iSorterColumn<0 ){ - pCol->iSorterColumn = pAggInfo->nSortingColumn++; - } - } - /* There is now an entry for pExpr in pAggInfo->aCol[] (either - ** because it was there before or because we just created it). - ** Convert the pExpr to be a TK_AGG_COLUMN referring to that - ** pAggInfo->aCol[] entry. - */ - ExprSetIrreducible(pExpr); - pExpr->pAggInfo = pAggInfo; - pExpr->op = TK_AGG_COLUMN; - pExpr->iAgg = (i16)k; - break; - } /* endif pExpr->iTable==pItem->iCursor */ - } /* end loop over pSrcList */ - } - return WRC_Prune; - } - case TK_AGG_FUNCTION: { - if( (pNC->ncFlags & NC_InAggFunc)==0 - && pWalker->walkerDepth==pExpr->op2 - ){ - /* Check to see if pExpr is a duplicate of another aggregate - ** function that is already in the pAggInfo structure - */ - struct AggInfo_func *pItem = pAggInfo->aFunc; - for(i=0; inFunc; i++, pItem++){ - if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){ - break; - } - } - if( i>=pAggInfo->nFunc ){ - /* pExpr is original. Make a new entry in pAggInfo->aFunc[] - */ - u8 enc = ENC(pParse->db); - i = addAggInfoFunc(pParse->db, pAggInfo); - if( i>=0 ){ - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pItem = &pAggInfo->aFunc[i]; - pItem->pExpr = pExpr; - pItem->iMem = ++pParse->nMem; - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), - pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); - if( pExpr->flags & EP_Distinct ){ - pItem->iDistinct = pParse->nTab++; - }else{ - pItem->iDistinct = -1; - } - } - } - /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry - */ - assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); - ExprSetIrreducible(pExpr); - pExpr->iAgg = (i16)i; - pExpr->pAggInfo = pAggInfo; - return WRC_Prune; - }else{ - return WRC_Continue; - } - } - } - return WRC_Continue; -} -static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ - UNUSED_PARAMETER(pWalker); - UNUSED_PARAMETER(pSelect); - return WRC_Continue; -} - -/* -** Analyze the pExpr expression looking for aggregate functions and -** for variables that need to be added to AggInfo object that pNC->pAggInfo -** points to. Additional entries are made on the AggInfo object as -** necessary. -** -** This routine should only be called after the expression has been -** analyzed by sqlite3ResolveExprNames(). -*/ -SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ - Walker w; - memset(&w, 0, sizeof(w)); - w.xExprCallback = analyzeAggregate; - w.xSelectCallback = analyzeAggregatesInSelect; - w.u.pNC = pNC; - assert( pNC->pSrcList!=0 ); - sqlite3WalkExpr(&w, pExpr); -} - -/* -** Call sqlite3ExprAnalyzeAggregates() for every expression in an -** expression list. Return the number of errors. -** -** If an error is found, the analysis is cut short. -*/ -SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ - struct ExprList_item *pItem; - int i; - if( pList ){ - for(pItem=pList->a, i=0; inExpr; i++, pItem++){ - sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); - } - } -} - -/* -** Allocate a single new register for use to hold some intermediate result. -*/ -SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){ - if( pParse->nTempReg==0 ){ - return ++pParse->nMem; - } - return pParse->aTempReg[--pParse->nTempReg]; -} - -/* -** Deallocate a register, making available for reuse for some other -** purpose. -** -** If a register is currently being used by the column cache, then -** the dallocation is deferred until the column cache line that uses -** the register becomes stale. -*/ -SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ - if( iReg && pParse->nTempRegaTempReg) ){ - int i; - struct yColCache *p; - for(i=0, p=pParse->aColCache; iiReg==iReg ){ - p->tempReg = 1; - return; - } - } - pParse->aTempReg[pParse->nTempReg++] = iReg; - } -} - -/* -** Allocate or deallocate a block of nReg consecutive registers -*/ -SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){ - int i, n; - i = pParse->iRangeReg; - n = pParse->nRangeReg; - if( nReg<=n ){ - assert( !usedAsColumnCache(pParse, i, i+n-1) ); - pParse->iRangeReg += nReg; - pParse->nRangeReg -= nReg; - }else{ - i = pParse->nMem+1; - pParse->nMem += nReg; - } - return i; -} -SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ - sqlite3ExprCacheRemove(pParse, iReg, nReg); - if( nReg>pParse->nRangeReg ){ - pParse->nRangeReg = nReg; - pParse->iRangeReg = iReg; - } -} - -/* -** Mark all temporary registers as being unavailable for reuse. -*/ -SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){ - pParse->nTempReg = 0; - pParse->nRangeReg = 0; -} - -/************** End of expr.c ************************************************/ -/************** Begin file alter.c *******************************************/ -/* -** 2005 February 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that used to generate VDBE code -** that implements the ALTER TABLE command. -*/ - -/* -** The code in this file only exists if we are not omitting the -** ALTER TABLE logic from the build. -*/ -#ifndef SQLITE_OMIT_ALTERTABLE - - -/* -** This function is used by SQL generated to implement the -** ALTER TABLE command. The first argument is the text of a CREATE TABLE or -** CREATE INDEX command. The second is a table name. The table name in -** the CREATE TABLE or CREATE INDEX statement is replaced with the third -** argument and the result returned. Examples: -** -** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') -** -> 'CREATE TABLE def(a, b, c)' -** -** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') -** -> 'CREATE INDEX i ON def(a, b, c)' -*/ -static void renameTableFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - unsigned char const *zSql = sqlite3_value_text(argv[0]); - unsigned char const *zTableName = sqlite3_value_text(argv[1]); - - int token; - Token tname; - unsigned char const *zCsr = zSql; - int len = 0; - char *zRet; - - sqlite3 *db = sqlite3_context_db_handle(context); - - UNUSED_PARAMETER(NotUsed); - - /* The principle used to locate the table name in the CREATE TABLE - ** statement is that the table name is the first non-space token that - ** is immediately followed by a TK_LP or TK_USING token. - */ - if( zSql ){ - do { - if( !*zCsr ){ - /* Ran out of input before finding an opening bracket. Return NULL. */ - return; - } - - /* Store the token that zCsr points to in tname. */ - tname.z = (char*)zCsr; - tname.n = len; - - /* Advance zCsr to the next token. Store that token type in 'token', - ** and its length in 'len' (to be used next iteration of this loop). - */ - do { - zCsr += len; - len = sqlite3GetToken(zCsr, &token); - } while( token==TK_SPACE ); - assert( len>0 ); - } while( token!=TK_LP && token!=TK_USING ); - - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, - zTableName, tname.z+tname.n); - sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); - } -} - -/* -** This C function implements an SQL user function that is used by SQL code -** generated by the ALTER TABLE ... RENAME command to modify the definition -** of any foreign key constraints that use the table being renamed as the -** parent table. It is passed three arguments: -** -** 1) The complete text of the CREATE TABLE statement being modified, -** 2) The old name of the table being renamed, and -** 3) The new name of the table being renamed. -** -** It returns the new CREATE TABLE statement. For example: -** -** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3') -** -> 'CREATE TABLE t1(a REFERENCES t3)' -*/ -#ifndef SQLITE_OMIT_FOREIGN_KEY -static void renameParentFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - char *zOutput = 0; - char *zResult; - unsigned char const *zInput = sqlite3_value_text(argv[0]); - unsigned char const *zOld = sqlite3_value_text(argv[1]); - unsigned char const *zNew = sqlite3_value_text(argv[2]); - - unsigned const char *z; /* Pointer to token */ - int n; /* Length of token z */ - int token; /* Type of token */ - - UNUSED_PARAMETER(NotUsed); - for(z=zInput; *z; z=z+n){ - n = sqlite3GetToken(z, &token); - if( token==TK_REFERENCES ){ - char *zParent; - do { - z += n; - n = sqlite3GetToken(z, &token); - }while( token==TK_SPACE ); - - zParent = sqlite3DbStrNDup(db, (const char *)z, n); - if( zParent==0 ) break; - sqlite3Dequote(zParent); - if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ - char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", - (zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew - ); - sqlite3DbFree(db, zOutput); - zOutput = zOut; - zInput = &z[n]; - } - sqlite3DbFree(db, zParent); - } - } - - zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput), - sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC); - sqlite3DbFree(db, zOutput); -} -#endif - -#ifndef SQLITE_OMIT_TRIGGER -/* This function is used by SQL generated to implement the -** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER -** statement. The second is a table name. The table name in the CREATE -** TRIGGER statement is replaced with the third argument and the result -** returned. This is analagous to renameTableFunc() above, except for CREATE -** TRIGGER, not CREATE INDEX and CREATE TABLE. -*/ -static void renameTriggerFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - unsigned char const *zSql = sqlite3_value_text(argv[0]); - unsigned char const *zTableName = sqlite3_value_text(argv[1]); - - int token; - Token tname; - int dist = 3; - unsigned char const *zCsr = zSql; - int len = 0; - char *zRet; - sqlite3 *db = sqlite3_context_db_handle(context); - - UNUSED_PARAMETER(NotUsed); - - /* The principle used to locate the table name in the CREATE TRIGGER - ** statement is that the table name is the first token that is immediatedly - ** preceded by either TK_ON or TK_DOT and immediatedly followed by one - ** of TK_WHEN, TK_BEGIN or TK_FOR. - */ - if( zSql ){ - do { - - if( !*zCsr ){ - /* Ran out of input before finding the table name. Return NULL. */ - return; - } - - /* Store the token that zCsr points to in tname. */ - tname.z = (char*)zCsr; - tname.n = len; - - /* Advance zCsr to the next token. Store that token type in 'token', - ** and its length in 'len' (to be used next iteration of this loop). - */ - do { - zCsr += len; - len = sqlite3GetToken(zCsr, &token); - }while( token==TK_SPACE ); - assert( len>0 ); - - /* Variable 'dist' stores the number of tokens read since the most - ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN - ** token is read and 'dist' equals 2, the condition stated above - ** to be met. - ** - ** Note that ON cannot be a database, table or column name, so - ** there is no need to worry about syntax like - ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. - */ - dist++; - if( token==TK_DOT || token==TK_ON ){ - dist = 0; - } - } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); - - /* Variable tname now contains the token that is the old table-name - ** in the CREATE TRIGGER statement. - */ - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql, - zTableName, tname.z+tname.n); - sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); - } -} -#endif /* !SQLITE_OMIT_TRIGGER */ - -/* -** Register built-in functions used to help implement ALTER TABLE -*/ -SQLITE_PRIVATE void sqlite3AlterFunctions(void){ - static SQLITE_WSD FuncDef aAlterTableFuncs[] = { - FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), -#ifndef SQLITE_OMIT_TRIGGER - FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), -#endif -#ifndef SQLITE_OMIT_FOREIGN_KEY - FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), -#endif - }; - int i; - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); - FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAlterTableFuncs); - - for(i=0; i OR name= OR ... -** -** If argument zWhere is NULL, then a pointer string containing the text -** "name=" is returned, where is the quoted version -** of the string passed as argument zConstant. The returned buffer is -** allocated using sqlite3DbMalloc(). It is the responsibility of the -** caller to ensure that it is eventually freed. -** -** If argument zWhere is not NULL, then the string returned is -** " OR name=", where is the contents of zWhere. -** In this case zWhere is passed to sqlite3DbFree() before returning. -** -*/ -static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){ - char *zNew; - if( !zWhere ){ - zNew = sqlite3MPrintf(db, "name=%Q", zConstant); - }else{ - zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant); - sqlite3DbFree(db, zWhere); - } - return zNew; -} - -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) -/* -** Generate the text of a WHERE expression which can be used to select all -** tables that have foreign key constraints that refer to table pTab (i.e. -** constraints for which pTab is the parent table) from the sqlite_master -** table. -*/ -static char *whereForeignKeys(Parse *pParse, Table *pTab){ - FKey *p; - char *zWhere = 0; - for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ - zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName); - } - return zWhere; -} -#endif - -/* -** Generate the text of a WHERE expression which can be used to select all -** temporary triggers on table pTab from the sqlite_temp_master table. If -** table pTab has no temporary triggers, or is itself stored in the -** temporary database, NULL is returned. -*/ -static char *whereTempTriggers(Parse *pParse, Table *pTab){ - Trigger *pTrig; - char *zWhere = 0; - const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ - - /* If the table is not located in the temp-db (in which case NULL is - ** returned, loop through the tables list of triggers. For each trigger - ** that is not part of the temp-db schema, add a clause to the WHERE - ** expression being built up in zWhere. - */ - if( pTab->pSchema!=pTempSchema ){ - sqlite3 *db = pParse->db; - for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ - if( pTrig->pSchema==pTempSchema ){ - zWhere = whereOrName(db, zWhere, pTrig->zName); - } - } - } - if( zWhere ){ - char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere); - sqlite3DbFree(pParse->db, zWhere); - zWhere = zNew; - } - return zWhere; -} - -/* -** Generate code to drop and reload the internal representation of table -** pTab from the database, including triggers and temporary triggers. -** Argument zName is the name of the table in the database schema at -** the time the generated code is executed. This can be different from -** pTab->zName if this function is being called to code part of an -** "ALTER TABLE RENAME TO" statement. -*/ -static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ - Vdbe *v; - char *zWhere; - int iDb; /* Index of database containing pTab */ -#ifndef SQLITE_OMIT_TRIGGER - Trigger *pTrig; -#endif - - v = sqlite3GetVdbe(pParse); - if( NEVER(v==0) ) return; - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - assert( iDb>=0 ); - -#ifndef SQLITE_OMIT_TRIGGER - /* Drop any table triggers from the internal schema. */ - for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ - int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); - assert( iTrigDb==iDb || iTrigDb==1 ); - sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0); - } -#endif - - /* Drop the table and index from the internal schema. */ - sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); - - /* Reload the table, index and permanent trigger schemas. */ - zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); - if( !zWhere ) return; - sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); - -#ifndef SQLITE_OMIT_TRIGGER - /* Now, if the table is not stored in the temp database, reload any temp - ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. - */ - if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ - sqlite3VdbeAddParseSchemaOp(v, 1, zWhere); - } -#endif -} - -/* -** Parameter zName is the name of a table that is about to be altered -** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). -** If the table is a system table, this function leaves an error message -** in pParse->zErr (system tables may not be altered) and returns non-zero. -** -** Or, if zName is not a system table, zero is returned. -*/ -static int isSystemTable(Parse *pParse, const char *zName){ - if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ - sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); - return 1; - } - return 0; -} - -/* -** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" -** command. -*/ -SQLITE_PRIVATE void sqlite3AlterRenameTable( - Parse *pParse, /* Parser context. */ - SrcList *pSrc, /* The table to rename. */ - Token *pName /* The new table name. */ -){ - int iDb; /* Database that contains the table */ - char *zDb; /* Name of database iDb */ - Table *pTab; /* Table being renamed */ - char *zName = 0; /* NULL-terminated version of pName */ - sqlite3 *db = pParse->db; /* Database connection */ - int nTabName; /* Number of UTF-8 characters in zTabName */ - const char *zTabName; /* Original name of the table */ - Vdbe *v; -#ifndef SQLITE_OMIT_TRIGGER - char *zWhere = 0; /* Where clause to locate temp triggers */ -#endif - VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ - int savedDbFlags; /* Saved value of db->flags */ - - savedDbFlags = db->flags; - if( NEVER(db->mallocFailed) ) goto exit_rename_table; - assert( pSrc->nSrc==1 ); - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); - - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( !pTab ) goto exit_rename_table; - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - zDb = db->aDb[iDb].zName; - db->flags |= SQLITE_PreferBuiltin; - - /* Get a NULL terminated version of the new table name. */ - zName = sqlite3NameFromToken(db, pName); - if( !zName ) goto exit_rename_table; - - /* Check that a table or index named 'zName' does not already exist - ** in database iDb. If so, this is an error. - */ - if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){ - sqlite3ErrorMsg(pParse, - "there is already another table or index with this name: %s", zName); - goto exit_rename_table; - } - - /* Make sure it is not a system table being altered, or a reserved name - ** that the table is being renamed to. - */ - if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ - goto exit_rename_table; - } - if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto - exit_rename_table; - } - -#ifndef SQLITE_OMIT_VIEW - if( pTab->pSelect ){ - sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName); - goto exit_rename_table; - } -#endif - -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Invoke the authorization callback. */ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ - goto exit_rename_table; - } -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto exit_rename_table; - } - if( IsVirtual(pTab) ){ - pVTab = sqlite3GetVTable(db, pTab); - if( pVTab->pVtab->pModule->xRename==0 ){ - pVTab = 0; - } - } -#endif - - /* Begin a transaction and code the VerifyCookie for database iDb. - ** Then modify the schema cookie (since the ALTER TABLE modifies the - ** schema). Open a statement transaction if the table is a virtual - ** table. - */ - v = sqlite3GetVdbe(pParse); - if( v==0 ){ - goto exit_rename_table; - } - sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb); - sqlite3ChangeCookie(pParse, iDb); - - /* If this is a virtual table, invoke the xRename() function if - ** one is defined. The xRename() callback will modify the names - ** of any resources used by the v-table implementation (including other - ** SQLite tables) that are identified by the name of the virtual table. - */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( pVTab ){ - int i = ++pParse->nMem; - sqlite3VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0); - sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); - sqlite3MayAbort(pParse); - } -#endif - - /* figure out how many UTF-8 characters are in zName */ - zTabName = pTab->zName; - nTabName = sqlite3Utf8CharLen(zTabName, -1); - -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - if( db->flags&SQLITE_ForeignKeys ){ - /* If foreign-key support is enabled, rewrite the CREATE TABLE - ** statements corresponding to all child tables of foreign key constraints - ** for which the renamed table is the parent table. */ - if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ - sqlite3NestedParse(pParse, - "UPDATE \"%w\".%s SET " - "sql = sqlite_rename_parent(sql, %Q, %Q) " - "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere); - sqlite3DbFree(db, zWhere); - } - } -#endif - - /* Modify the sqlite_master table to use the new table name. */ - sqlite3NestedParse(pParse, - "UPDATE %Q.%s SET " -#ifdef SQLITE_OMIT_TRIGGER - "sql = sqlite_rename_table(sql, %Q), " -#else - "sql = CASE " - "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" - "ELSE sqlite_rename_table(sql, %Q) END, " -#endif - "tbl_name = %Q, " - "name = CASE " - "WHEN type='table' THEN %Q " - "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " - "'sqlite_autoindex_' || %Q || substr(name,%d+18) " - "ELSE name END " - "WHERE tbl_name=%Q COLLATE nocase AND " - "(type='table' OR type='index' OR type='trigger');", - zDb, SCHEMA_TABLE(iDb), zName, zName, zName, -#ifndef SQLITE_OMIT_TRIGGER - zName, -#endif - zName, nTabName, zTabName - ); - -#ifndef SQLITE_OMIT_AUTOINCREMENT - /* If the sqlite_sequence table exists in this database, then update - ** it with the new table name. - */ - if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ - sqlite3NestedParse(pParse, - "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q", - zDb, zName, pTab->zName); - } -#endif - -#ifndef SQLITE_OMIT_TRIGGER - /* If there are TEMP triggers on this table, modify the sqlite_temp_master - ** table. Don't do this if the table being ALTERed is itself located in - ** the temp database. - */ - if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ - sqlite3NestedParse(pParse, - "UPDATE sqlite_temp_master SET " - "sql = sqlite_rename_trigger(sql, %Q), " - "tbl_name = %Q " - "WHERE %s;", zName, zName, zWhere); - sqlite3DbFree(db, zWhere); - } -#endif - -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - if( db->flags&SQLITE_ForeignKeys ){ - FKey *p; - for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ - Table *pFrom = p->pFrom; - if( pFrom!=pTab ){ - reloadTableSchema(pParse, p->pFrom, pFrom->zName); - } - } - } -#endif - - /* Drop and reload the internal table schema. */ - reloadTableSchema(pParse, pTab, zName); - -exit_rename_table: - sqlite3SrcListDelete(db, pSrc); - sqlite3DbFree(db, zName); - db->flags = savedDbFlags; -} - - -/* -** Generate code to make sure the file format number is at least minFormat. -** The generated code will increase the file format number if necessary. -*/ -SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ - Vdbe *v; - v = sqlite3GetVdbe(pParse); - /* The VDBE should have been allocated before this routine is called. - ** If that allocation failed, we would have quit before reaching this - ** point */ - if( ALWAYS(v) ){ - int r1 = sqlite3GetTempReg(pParse); - int r2 = sqlite3GetTempReg(pParse); - int j1; - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); - sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); - j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, r2); - sqlite3VdbeJumpHere(v, j1); - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempReg(pParse, r2); - } -} - -/* -** This function is called after an "ALTER TABLE ... ADD" statement -** has been parsed. Argument pColDef contains the text of the new -** column definition. -** -** The Table structure pParse->pNewTable was extended to include -** the new column during parsing. -*/ -SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ - Table *pNew; /* Copy of pParse->pNewTable */ - Table *pTab; /* Table being altered */ - int iDb; /* Database number */ - const char *zDb; /* Database name */ - const char *zTab; /* Table name */ - char *zCol; /* Null-terminated column definition */ - Column *pCol; /* The new column */ - Expr *pDflt; /* Default value for the new column */ - sqlite3 *db; /* The database connection; */ - - db = pParse->db; - if( pParse->nErr || db->mallocFailed ) return; - pNew = pParse->pNewTable; - assert( pNew ); - - assert( sqlite3BtreeHoldsAllMutexes(db) ); - iDb = sqlite3SchemaToIndex(db, pNew->pSchema); - zDb = db->aDb[iDb].zName; - zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ - pCol = &pNew->aCol[pNew->nCol-1]; - pDflt = pCol->pDflt; - pTab = sqlite3FindTable(db, zTab, zDb); - assert( pTab ); - -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Invoke the authorization callback. */ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ - return; - } -#endif - - /* If the default value for the new column was specified with a - ** literal NULL, then set pDflt to 0. This simplifies checking - ** for an SQL NULL default below. - */ - if( pDflt && pDflt->op==TK_NULL ){ - pDflt = 0; - } - - /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. - ** If there is a NOT NULL constraint, then the default value for the - ** column must not be NULL. - */ - if( pCol->colFlags & COLFLAG_PRIMKEY ){ - sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); - return; - } - if( pNew->pIndex ){ - sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); - return; - } - if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){ - sqlite3ErrorMsg(pParse, - "Cannot add a REFERENCES column with non-NULL default value"); - return; - } - if( pCol->notNull && !pDflt ){ - sqlite3ErrorMsg(pParse, - "Cannot add a NOT NULL column with default value NULL"); - return; - } - - /* Ensure the default expression is something that sqlite3ValueFromExpr() - ** can handle (i.e. not CURRENT_TIME etc.) - */ - if( pDflt ){ - sqlite3_value *pVal; - if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){ - db->mallocFailed = 1; - return; - } - if( !pVal ){ - sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); - return; - } - sqlite3ValueFree(pVal); - } - - /* Modify the CREATE TABLE statement. */ - zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); - if( zCol ){ - char *zEnd = &zCol[pColDef->n-1]; - int savedDbFlags = db->flags; - while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ - *zEnd-- = '\0'; - } - db->flags |= SQLITE_PreferBuiltin; - sqlite3NestedParse(pParse, - "UPDATE \"%w\".%s SET " - "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " - "WHERE type = 'table' AND name = %Q", - zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, - zTab - ); - sqlite3DbFree(db, zCol); - db->flags = savedDbFlags; - } - - /* If the default value of the new column is NULL, then set the file - ** format to 2. If the default value of the new column is not NULL, - ** the file format becomes 3. - */ - sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); - - /* Reload the schema of the modified table. */ - reloadTableSchema(pParse, pTab, pTab->zName); -} - -/* -** This function is called by the parser after the table-name in -** an "ALTER TABLE ADD" statement is parsed. Argument -** pSrc is the full-name of the table being altered. -** -** This routine makes a (partial) copy of the Table structure -** for the table being altered and sets Parse.pNewTable to point -** to it. Routines called by the parser as the column definition -** is parsed (i.e. sqlite3AddColumn()) add the new Column data to -** the copy. The copy of the Table structure is deleted by tokenize.c -** after parsing is finished. -** -** Routine sqlite3AlterFinishAddColumn() will be called to complete -** coding the "ALTER TABLE ... ADD" statement. -*/ -SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ - Table *pNew; - Table *pTab; - Vdbe *v; - int iDb; - int i; - int nAlloc; - sqlite3 *db = pParse->db; - - /* Look up the table being altered. */ - assert( pParse->pNewTable==0 ); - assert( sqlite3BtreeHoldsAllMutexes(db) ); - if( db->mallocFailed ) goto exit_begin_add_column; - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( !pTab ) goto exit_begin_add_column; - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); - goto exit_begin_add_column; - } -#endif - - /* Make sure this is not an attempt to ALTER a view. */ - if( pTab->pSelect ){ - sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); - goto exit_begin_add_column; - } - if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ - goto exit_begin_add_column; - } - - assert( pTab->addColOffset>0 ); - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - - /* Put a copy of the Table struct in Parse.pNewTable for the - ** sqlite3AddColumn() function and friends to modify. But modify - ** the name by adding an "sqlite_altertab_" prefix. By adding this - ** prefix, we insure that the name will not collide with an existing - ** table because user table are not allowed to have the "sqlite_" - ** prefix on their name. - */ - pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); - if( !pNew ) goto exit_begin_add_column; - pParse->pNewTable = pNew; - pNew->nRef = 1; - pNew->nCol = pTab->nCol; - assert( pNew->nCol>0 ); - nAlloc = (((pNew->nCol-1)/8)*8)+8; - assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); - pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); - pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); - if( !pNew->aCol || !pNew->zName ){ - db->mallocFailed = 1; - goto exit_begin_add_column; - } - memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); - for(i=0; inCol; i++){ - Column *pCol = &pNew->aCol[i]; - pCol->zName = sqlite3DbStrDup(db, pCol->zName); - pCol->zColl = 0; - pCol->zType = 0; - pCol->pDflt = 0; - pCol->zDflt = 0; - } - pNew->pSchema = db->aDb[iDb].pSchema; - pNew->addColOffset = pTab->addColOffset; - pNew->nRef = 1; - - /* Begin a transaction and increment the schema cookie. */ - sqlite3BeginWriteOperation(pParse, 0, iDb); - v = sqlite3GetVdbe(pParse); - if( !v ) goto exit_begin_add_column; - sqlite3ChangeCookie(pParse, iDb); - -exit_begin_add_column: - sqlite3SrcListDelete(db, pSrc); - return; -} -#endif /* SQLITE_ALTER_TABLE */ - -/************** End of alter.c ***********************************************/ -/************** Begin file analyze.c *****************************************/ -/* -** 2005 July 8 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code associated with the ANALYZE command. -** -** The ANALYZE command gather statistics about the content of tables -** and indices. These statistics are made available to the query planner -** to help it make better decisions about how to perform queries. -** -** The following system tables are or have been supported: -** -** CREATE TABLE sqlite_stat1(tbl, idx, stat); -** CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample); -** CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample); -** -** Additional tables might be added in future releases of SQLite. -** The sqlite_stat2 table is not created or used unless the SQLite version -** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled -** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated. -** The sqlite_stat2 table is superceded by sqlite_stat3, which is only -** created and used by SQLite versions 3.7.9 and later and with -** SQLITE_ENABLE_STAT3 defined. The fucntionality of sqlite_stat3 -** is a superset of sqlite_stat2. -** -** Format of sqlite_stat1: -** -** There is normally one row per index, with the index identified by the -** name in the idx column. The tbl column is the name of the table to -** which the index belongs. In each such row, the stat column will be -** a string consisting of a list of integers. The first integer in this -** list is the number of rows in the index and in the table. The second -** integer is the average number of rows in the index that have the same -** value in the first column of the index. The third integer is the average -** number of rows in the index that have the same value for the first two -** columns. The N-th integer (for N>1) is the average number of rows in -** the index which have the same value for the first N-1 columns. For -** a K-column index, there will be K+1 integers in the stat column. If -** the index is unique, then the last integer will be 1. -** -** The list of integers in the stat column can optionally be followed -** by the keyword "unordered". The "unordered" keyword, if it is present, -** must be separated from the last integer by a single space. If the -** "unordered" keyword is present, then the query planner assumes that -** the index is unordered and will not use the index for a range query. -** -** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat -** column contains a single integer which is the (estimated) number of -** rows in the table identified by sqlite_stat1.tbl. -** -** Format of sqlite_stat2: -** -** The sqlite_stat2 is only created and is only used if SQLite is compiled -** with SQLITE_ENABLE_STAT2 and if the SQLite version number is between -** 3.6.18 and 3.7.8. The "stat2" table contains additional information -** about the distribution of keys within an index. The index is identified by -** the "idx" column and the "tbl" column is the name of the table to which -** the index belongs. There are usually 10 rows in the sqlite_stat2 -** table for each index. -** -** The sqlite_stat2 entries for an index that have sampleno between 0 and 9 -** inclusive are samples of the left-most key value in the index taken at -** evenly spaced points along the index. Let the number of samples be S -** (10 in the standard build) and let C be the number of rows in the index. -** Then the sampled rows are given by: -** -** rownumber = (i*C*2 + C)/(S*2) -** -** For i between 0 and S-1. Conceptually, the index space is divided into -** S uniform buckets and the samples are the middle row from each bucket. -** -** The format for sqlite_stat2 is recorded here for legacy reference. This -** version of SQLite does not support sqlite_stat2. It neither reads nor -** writes the sqlite_stat2 table. This version of SQLite only supports -** sqlite_stat3. -** -** Format for sqlite_stat3: -** -** The sqlite_stat3 is an enhancement to sqlite_stat2. A new name is -** used to avoid compatibility problems. -** -** The format of the sqlite_stat3 table is similar to the format of -** the sqlite_stat2 table. There are multiple entries for each index. -** The idx column names the index and the tbl column is the table of the -** index. If the idx and tbl columns are the same, then the sample is -** of the INTEGER PRIMARY KEY. The sample column is a value taken from -** the left-most column of the index. The nEq column is the approximate -** number of entires in the index whose left-most column exactly matches -** the sample. nLt is the approximate number of entires whose left-most -** column is less than the sample. The nDLt column is the approximate -** number of distinct left-most entries in the index that are less than -** the sample. -** -** Future versions of SQLite might change to store a string containing -** multiple integers values in the nDLt column of sqlite_stat3. The first -** integer will be the number of prior index entires that are distinct in -** the left-most column. The second integer will be the number of prior index -** entries that are distinct in the first two columns. The third integer -** will be the number of prior index entries that are distinct in the first -** three columns. And so forth. With that extension, the nDLt field is -** similar in function to the sqlite_stat1.stat field. -** -** There can be an arbitrary number of sqlite_stat3 entries per index. -** The ANALYZE command will typically generate sqlite_stat3 tables -** that contain between 10 and 40 samples which are distributed across -** the key space, though not uniformly, and which include samples with -** largest possible nEq values. -*/ -#ifndef SQLITE_OMIT_ANALYZE - -/* -** This routine generates code that opens the sqlite_stat1 table for -** writing with cursor iStatCur. If the library was built with the -** SQLITE_ENABLE_STAT3 macro defined, then the sqlite_stat3 table is -** opened for writing using cursor (iStatCur+1) -** -** If the sqlite_stat1 tables does not previously exist, it is created. -** Similarly, if the sqlite_stat3 table does not exist and the library -** is compiled with SQLITE_ENABLE_STAT3 defined, it is created. -** -** Argument zWhere may be a pointer to a buffer containing a table name, -** or it may be a NULL pointer. If it is not NULL, then all entries in -** the sqlite_stat1 and (if applicable) sqlite_stat3 tables associated -** with the named table are deleted. If zWhere==0, then code is generated -** to delete all stat table entries. -*/ -static void openStatTable( - Parse *pParse, /* Parsing context */ - int iDb, /* The database we are looking in */ - int iStatCur, /* Open the sqlite_stat1 table on this cursor */ - const char *zWhere, /* Delete entries for this table or index */ - const char *zWhereType /* Either "tbl" or "idx" */ -){ - static const struct { - const char *zName; - const char *zCols; - } aTable[] = { - { "sqlite_stat1", "tbl,idx,stat" }, -#ifdef SQLITE_ENABLE_STAT3 - { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" }, -#endif - }; - - int aRoot[] = {0, 0}; - u8 aCreateTbl[] = {0, 0}; - - int i; - sqlite3 *db = pParse->db; - Db *pDb; - Vdbe *v = sqlite3GetVdbe(pParse); - if( v==0 ) return; - assert( sqlite3BtreeHoldsAllMutexes(db) ); - assert( sqlite3VdbeDb(v)==db ); - pDb = &db->aDb[iDb]; - - /* Create new statistic tables if they do not exist, or clear them - ** if they do already exist. - */ - for(i=0; izName))==0 ){ - /* The sqlite_stat[12] table does not exist. Create it. Note that a - ** side-effect of the CREATE TABLE statement is to leave the rootpage - ** of the new table in register pParse->regRoot. This is important - ** because the OpenWrite opcode below will be needing it. */ - sqlite3NestedParse(pParse, - "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols - ); - aRoot[i] = pParse->regRoot; - aCreateTbl[i] = OPFLAG_P2ISREG; - }else{ - /* The table already exists. If zWhere is not NULL, delete all entries - ** associated with the table zWhere. If zWhere is NULL, delete the - ** entire contents of the table. */ - aRoot[i] = pStat->tnum; - sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab); - if( zWhere ){ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere - ); - }else{ - /* The sqlite_stat[12] table already exists. Delete all rows. */ - sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb); - } - } - } - - /* Open the sqlite_stat[13] tables for writing. */ - for(i=0; ia[0])*mxSample; - p = sqlite3MallocZero( n ); - if( p==0 ){ - sqlite3_result_error_nomem(context); - return; - } - p->a = (struct Stat3Sample*)&p[1]; - p->nRow = nRow; - p->mxSample = mxSample; - p->nPSample = p->nRow/(mxSample/3+1) + 1; - sqlite3_randomness(sizeof(p->iPrn), &p->iPrn); - sqlite3_result_blob(context, p, sizeof(p), sqlite3_free); -} -static const FuncDef stat3InitFuncdef = { - 2, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ - 0, /* pUserData */ - 0, /* pNext */ - stat3Init, /* xFunc */ - 0, /* xStep */ - 0, /* xFinalize */ - "stat3_init", /* zName */ - 0, /* pHash */ - 0 /* pDestructor */ -}; - - -/* -** Implementation of the stat3_push(nEq,nLt,nDLt,rowid,P) SQL function. The -** arguments describe a single key instance. This routine makes the -** decision about whether or not to retain this key for the sqlite_stat3 -** table. -** -** The return value is NULL. -*/ -static void stat3Push( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[4]); - tRowcnt nEq = sqlite3_value_int64(argv[0]); - tRowcnt nLt = sqlite3_value_int64(argv[1]); - tRowcnt nDLt = sqlite3_value_int64(argv[2]); - i64 rowid = sqlite3_value_int64(argv[3]); - u8 isPSample = 0; - u8 doInsert = 0; - int iMin = p->iMin; - struct Stat3Sample *pSample; - int i; - u32 h; - - UNUSED_PARAMETER(context); - UNUSED_PARAMETER(argc); - if( nEq==0 ) return; - h = p->iPrn = p->iPrn*1103515245 + 12345; - if( (nLt/p->nPSample)!=((nEq+nLt)/p->nPSample) ){ - doInsert = isPSample = 1; - }else if( p->nSamplemxSample ){ - doInsert = 1; - }else{ - if( nEq>p->a[iMin].nEq || (nEq==p->a[iMin].nEq && h>p->a[iMin].iHash) ){ - doInsert = 1; - } - } - if( !doInsert ) return; - if( p->nSample==p->mxSample ){ - assert( p->nSample - iMin - 1 >= 0 ); - memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1)); - pSample = &p->a[p->nSample-1]; - }else{ - pSample = &p->a[p->nSample++]; - } - pSample->iRowid = rowid; - pSample->nEq = nEq; - pSample->nLt = nLt; - pSample->nDLt = nDLt; - pSample->iHash = h; - pSample->isPSample = isPSample; - - /* Find the new minimum */ - if( p->nSample==p->mxSample ){ - pSample = p->a; - i = 0; - while( pSample->isPSample ){ - i++; - pSample++; - assert( inSample ); - } - nEq = pSample->nEq; - h = pSample->iHash; - iMin = i; - for(i++, pSample++; inSample; i++, pSample++){ - if( pSample->isPSample ) continue; - if( pSample->nEqnEq==nEq && pSample->iHashnEq; - h = pSample->iHash; - } - } - p->iMin = iMin; - } -} -static const FuncDef stat3PushFuncdef = { - 5, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ - 0, /* pUserData */ - 0, /* pNext */ - stat3Push, /* xFunc */ - 0, /* xStep */ - 0, /* xFinalize */ - "stat3_push", /* zName */ - 0, /* pHash */ - 0 /* pDestructor */ -}; - -/* -** Implementation of the stat3_get(P,N,...) SQL function. This routine is -** used to query the results. Content is returned for the Nth sqlite_stat3 -** row where N is between 0 and S-1 and S is the number of samples. The -** value returned depends on the number of arguments. -** -** argc==2 result: rowid -** argc==3 result: nEq -** argc==4 result: nLt -** argc==5 result: nDLt -*/ -static void stat3Get( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int n = sqlite3_value_int(argv[1]); - Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[0]); - - assert( p!=0 ); - if( p->nSample<=n ) return; - switch( argc ){ - case 2: sqlite3_result_int64(context, p->a[n].iRowid); break; - case 3: sqlite3_result_int64(context, p->a[n].nEq); break; - case 4: sqlite3_result_int64(context, p->a[n].nLt); break; - default: sqlite3_result_int64(context, p->a[n].nDLt); break; - } -} -static const FuncDef stat3GetFuncdef = { - -1, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ - 0, /* pUserData */ - 0, /* pNext */ - stat3Get, /* xFunc */ - 0, /* xStep */ - 0, /* xFinalize */ - "stat3_get", /* zName */ - 0, /* pHash */ - 0 /* pDestructor */ -}; -#endif /* SQLITE_ENABLE_STAT3 */ - - - - -/* -** Generate code to do an analysis of all indices associated with -** a single table. -*/ -static void analyzeOneTable( - Parse *pParse, /* Parser context */ - Table *pTab, /* Table whose indices are to be analyzed */ - Index *pOnlyIdx, /* If not NULL, only analyze this one index */ - int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */ - int iMem /* Available memory locations begin here */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - Index *pIdx; /* An index to being analyzed */ - int iIdxCur; /* Cursor open on index being analyzed */ - Vdbe *v; /* The virtual machine being built up */ - int i; /* Loop counter */ - int topOfLoop; /* The top of the loop */ - int endOfLoop; /* The end of the loop */ - int jZeroRows = -1; /* Jump from here if number of rows is zero */ - int iDb; /* Index of database containing pTab */ - int regTabname = iMem++; /* Register containing table name */ - int regIdxname = iMem++; /* Register containing index name */ - int regStat1 = iMem++; /* The stat column of sqlite_stat1 */ -#ifdef SQLITE_ENABLE_STAT3 - int regNumEq = regStat1; /* Number of instances. Same as regStat1 */ - int regNumLt = iMem++; /* Number of keys less than regSample */ - int regNumDLt = iMem++; /* Number of distinct keys less than regSample */ - int regSample = iMem++; /* The next sample value */ - int regRowid = regSample; /* Rowid of a sample */ - int regAccum = iMem++; /* Register to hold Stat3Accum object */ - int regLoop = iMem++; /* Loop counter */ - int regCount = iMem++; /* Number of rows in the table or index */ - int regTemp1 = iMem++; /* Intermediate register */ - int regTemp2 = iMem++; /* Intermediate register */ - int once = 1; /* One-time initialization */ - int shortJump = 0; /* Instruction address */ - int iTabCur = pParse->nTab++; /* Table cursor */ -#endif - int regCol = iMem++; /* Content of a column in analyzed table */ - int regRec = iMem++; /* Register holding completed record */ - int regTemp = iMem++; /* Temporary use register */ - int regNewRowid = iMem++; /* Rowid for the inserted record */ - - - v = sqlite3GetVdbe(pParse); - if( v==0 || NEVER(pTab==0) ){ - return; - } - if( pTab->tnum==0 ){ - /* Do not gather statistics on views or virtual tables */ - return; - } - if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){ - /* Do not gather statistics on system tables */ - return; - } - assert( sqlite3BtreeHoldsAllMutexes(db) ); - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=0 ); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, - db->aDb[iDb].zName ) ){ - return; - } -#endif - - /* Establish a read-lock on the table at the shared-cache level. */ - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - - iIdxCur = pParse->nTab++; - sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int nCol; - KeyInfo *pKey; - int addrIfNot = 0; /* address of OP_IfNot */ - int *aChngAddr; /* Array of jump instruction addresses */ - - if( pOnlyIdx && pOnlyIdx!=pIdx ) continue; - VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName)); - nCol = pIdx->nColumn; - aChngAddr = sqlite3DbMallocRaw(db, sizeof(int)*nCol); - if( aChngAddr==0 ) continue; - pKey = sqlite3IndexKeyinfo(pParse, pIdx); - if( iMem+1+(nCol*2)>pParse->nMem ){ - pParse->nMem = iMem+1+(nCol*2); - } - - /* Open a cursor to the index to be analyzed. */ - assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); - sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, - (char *)pKey, P4_KEYINFO_HANDOFF); - VdbeComment((v, "%s", pIdx->zName)); - - /* Populate the register containing the index name. */ - sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0); - -#ifdef SQLITE_ENABLE_STAT3 - if( once ){ - once = 0; - sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); - } - sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regCount); - sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_STAT3_SAMPLES, regTemp1); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumEq); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumLt); - sqlite3VdbeAddOp2(v, OP_Integer, -1, regNumDLt); - sqlite3VdbeAddOp3(v, OP_Null, 0, regSample, regAccum); - sqlite3VdbeAddOp4(v, OP_Function, 1, regCount, regAccum, - (char*)&stat3InitFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 2); -#endif /* SQLITE_ENABLE_STAT3 */ - - /* The block of memory cells initialized here is used as follows. - ** - ** iMem: - ** The total number of rows in the table. - ** - ** iMem+1 .. iMem+nCol: - ** Number of distinct entries in index considering the - ** left-most N columns only, where N is between 1 and nCol, - ** inclusive. - ** - ** iMem+nCol+1 .. Mem+2*nCol: - ** Previous value of indexed columns, from left to right. - ** - ** Cells iMem through iMem+nCol are initialized to 0. The others are - ** initialized to contain an SQL NULL. - */ - for(i=0; i<=nCol; i++){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i); - } - for(i=0; iazColl!=0 ); - assert( pIdx->azColl[i]!=0 ); - pColl = sqlite3LocateCollSeq(pParse, pIdx->azColl[i]); - aChngAddr[i] = sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1, - (char*)pColl, P4_COLLSEQ); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); - VdbeComment((v, "jump if column %d changed", i)); -#ifdef SQLITE_ENABLE_STAT3 - if( i==0 ){ - sqlite3VdbeAddOp2(v, OP_AddImm, regNumEq, 1); - VdbeComment((v, "incr repeat count")); - } -#endif - } - sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop); - for(i=0; inColumn, regRowid); - sqlite3VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt); - sqlite3VdbeAddOp2(v, OP_AddImm, regNumDLt, 1); - sqlite3VdbeAddOp2(v, OP_Integer, 1, regNumEq); -#endif - } - sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1); - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1); - } - sqlite3DbFree(db, aChngAddr); - - /* Always jump here after updating the iMem+1...iMem+1+nCol counters */ - sqlite3VdbeResolveLabel(v, endOfLoop); - - sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop); - sqlite3VdbeAddOp1(v, OP_Close, iIdxCur); -#ifdef SQLITE_ENABLE_STAT3 - sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2, - (char*)&stat3PushFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 5); - sqlite3VdbeAddOp2(v, OP_Integer, -1, regLoop); - shortJump = - sqlite3VdbeAddOp2(v, OP_AddImm, regLoop, 1); - sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regTemp1, - (char*)&stat3GetFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 2); - sqlite3VdbeAddOp1(v, OP_IsNull, regTemp1); - sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, shortJump, regTemp1); - sqlite3VdbeAddOp3(v, OP_Column, iTabCur, pIdx->aiColumn[0], regSample); - sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[0], regSample); - sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumEq, - (char*)&stat3GetFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 3); - sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumLt, - (char*)&stat3GetFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 4); - sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumDLt, - (char*)&stat3GetFuncdef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, 5); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regRec, "bbbbbb", 0); - sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); - sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid); - sqlite3VdbeAddOp2(v, OP_Goto, 0, shortJump); - sqlite3VdbeJumpHere(v, shortJump+2); -#endif - - /* Store the results in sqlite_stat1. - ** - ** The result is a single row of the sqlite_stat1 table. The first - ** two columns are the names of the table and index. The third column - ** is a string composed of a list of integer statistics about the - ** index. The first integer in the list is the total number of entries - ** in the index. There is one additional integer in the list for each - ** column of the table. This additional integer is a guess of how many - ** rows of the table the index will select. If D is the count of distinct - ** values and K is the total number of rows, then the integer is computed - ** as: - ** - ** I = (K+D-1)/D - ** - ** If K==0 then no entry is made into the sqlite_stat1 table. - ** If K>0 then it is always the case the D>0 so division by zero - ** is never possible. - */ - sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regStat1); - if( jZeroRows<0 ){ - jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem); - } - for(i=0; ipIndex==0 ){ - sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb); - VdbeComment((v, "%s", pTab->zName)); - sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat1); - sqlite3VdbeAddOp1(v, OP_Close, iIdxCur); - jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1); - }else{ - sqlite3VdbeJumpHere(v, jZeroRows); - jZeroRows = sqlite3VdbeAddOp0(v, OP_Goto); - } - sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0); - sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); - sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - if( pParse->nMemnMem = regRec; - sqlite3VdbeJumpHere(v, jZeroRows); -} - - -/* -** Generate code that will cause the most recent index analysis to -** be loaded into internal hash tables where is can be used. -*/ -static void loadAnalysis(Parse *pParse, int iDb){ - Vdbe *v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb); - } -} - -/* -** Generate code that will do an analysis of an entire database -*/ -static void analyzeDatabase(Parse *pParse, int iDb){ - sqlite3 *db = pParse->db; - Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ - HashElem *k; - int iStatCur; - int iMem; - - sqlite3BeginWriteOperation(pParse, 0, iDb); - iStatCur = pParse->nTab; - pParse->nTab += 3; - openStatTable(pParse, iDb, iStatCur, 0, 0); - iMem = pParse->nMem+1; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ - Table *pTab = (Table*)sqliteHashData(k); - analyzeOneTable(pParse, pTab, 0, iStatCur, iMem); - } - loadAnalysis(pParse, iDb); -} - -/* -** Generate code that will do an analysis of a single table in -** a database. If pOnlyIdx is not NULL then it is a single index -** in pTab that should be analyzed. -*/ -static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){ - int iDb; - int iStatCur; - - assert( pTab!=0 ); - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - sqlite3BeginWriteOperation(pParse, 0, iDb); - iStatCur = pParse->nTab; - pParse->nTab += 3; - if( pOnlyIdx ){ - openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx"); - }else{ - openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl"); - } - analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem+1); - loadAnalysis(pParse, iDb); -} - -/* -** Generate code for the ANALYZE command. The parser calls this routine -** when it recognizes an ANALYZE command. -** -** ANALYZE -- 1 -** ANALYZE -- 2 -** ANALYZE ?.? -- 3 -** -** Form 1 causes all indices in all attached databases to be analyzed. -** Form 2 analyzes all indices the single database named. -** Form 3 analyzes all indices associated with the named table. -*/ -SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ - sqlite3 *db = pParse->db; - int iDb; - int i; - char *z, *zDb; - Table *pTab; - Index *pIdx; - Token *pTableName; - - /* Read the database schema. If an error occurs, leave an error message - ** and code in pParse and return NULL. */ - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - return; - } - - assert( pName2!=0 || pName1==0 ); - if( pName1==0 ){ - /* Form 1: Analyze everything */ - for(i=0; inDb; i++){ - if( i==1 ) continue; /* Do not analyze the TEMP database */ - analyzeDatabase(pParse, i); - } - }else if( pName2->n==0 ){ - /* Form 2: Analyze the database or table named */ - iDb = sqlite3FindDb(db, pName1); - if( iDb>=0 ){ - analyzeDatabase(pParse, iDb); - }else{ - z = sqlite3NameFromToken(db, pName1); - if( z ){ - if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){ - analyzeTable(pParse, pIdx->pTable, pIdx); - }else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){ - analyzeTable(pParse, pTab, 0); - } - sqlite3DbFree(db, z); - } - } - }else{ - /* Form 3: Analyze the fully qualified table name */ - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); - if( iDb>=0 ){ - zDb = db->aDb[iDb].zName; - z = sqlite3NameFromToken(db, pTableName); - if( z ){ - if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ - analyzeTable(pParse, pIdx->pTable, pIdx); - }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){ - analyzeTable(pParse, pTab, 0); - } - sqlite3DbFree(db, z); - } - } - } -} - -/* -** Used to pass information from the analyzer reader through to the -** callback routine. -*/ -typedef struct analysisInfo analysisInfo; -struct analysisInfo { - sqlite3 *db; - const char *zDatabase; -}; - -/* -** This callback is invoked once for each index when reading the -** sqlite_stat1 table. -** -** argv[0] = name of the table -** argv[1] = name of the index (might be NULL) -** argv[2] = results of analysis - on integer for each column -** -** Entries for which argv[1]==NULL simply record the number of rows in -** the table. -*/ -static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ - analysisInfo *pInfo = (analysisInfo*)pData; - Index *pIndex; - Table *pTable; - int i, c, n; - tRowcnt v; - const char *z; - - assert( argc==3 ); - UNUSED_PARAMETER2(NotUsed, argc); - - if( argv==0 || argv[0]==0 || argv[2]==0 ){ - return 0; - } - pTable = sqlite3FindTable(pInfo->db, argv[0], pInfo->zDatabase); - if( pTable==0 ){ - return 0; - } - if( argv[1] ){ - pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase); - }else{ - pIndex = 0; - } - n = pIndex ? pIndex->nColumn : 0; - z = argv[2]; - for(i=0; *z && i<=n; i++){ - v = 0; - while( (c=z[0])>='0' && c<='9' ){ - v = v*10 + c - '0'; - z++; - } - if( i==0 ) pTable->nRowEst = v; - if( pIndex==0 ) break; - pIndex->aiRowEst[i] = v; - if( *z==' ' ) z++; - if( strcmp(z, "unordered")==0 ){ - pIndex->bUnordered = 1; - break; - } - } - return 0; -} - -/* -** If the Index.aSample variable is not NULL, delete the aSample[] array -** and its contents. -*/ -SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){ -#ifdef SQLITE_ENABLE_STAT3 - if( pIdx->aSample ){ - int j; - for(j=0; jnSample; j++){ - IndexSample *p = &pIdx->aSample[j]; - if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){ - sqlite3DbFree(db, p->u.z); - } - } - sqlite3DbFree(db, pIdx->aSample); - } - if( db && db->pnBytesFreed==0 ){ - pIdx->nSample = 0; - pIdx->aSample = 0; - } -#else - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(pIdx); -#endif -} - -#ifdef SQLITE_ENABLE_STAT3 -/* -** Load content from the sqlite_stat3 table into the Index.aSample[] -** arrays of all indices. -*/ -static int loadStat3(sqlite3 *db, const char *zDb){ - int rc; /* Result codes from subroutines */ - sqlite3_stmt *pStmt = 0; /* An SQL statement being run */ - char *zSql; /* Text of the SQL statement */ - Index *pPrevIdx = 0; /* Previous index in the loop */ - int idx = 0; /* slot in pIdx->aSample[] for next sample */ - int eType; /* Datatype of a sample */ - IndexSample *pSample; /* A slot in pIdx->aSample[] */ - - assert( db->lookaside.bEnabled==0 ); - if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){ - return SQLITE_OK; - } - - zSql = sqlite3MPrintf(db, - "SELECT idx,count(*) FROM %Q.sqlite_stat3" - " GROUP BY idx", zDb); - if( !zSql ){ - return SQLITE_NOMEM; - } - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - sqlite3DbFree(db, zSql); - if( rc ) return rc; - - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - char *zIndex; /* Index name */ - Index *pIdx; /* Pointer to the index object */ - int nSample; /* Number of samples */ - - zIndex = (char *)sqlite3_column_text(pStmt, 0); - if( zIndex==0 ) continue; - nSample = sqlite3_column_int(pStmt, 1); - pIdx = sqlite3FindIndex(db, zIndex, zDb); - if( pIdx==0 ) continue; - assert( pIdx->nSample==0 ); - pIdx->nSample = nSample; - pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample)); - pIdx->avgEq = pIdx->aiRowEst[1]; - if( pIdx->aSample==0 ){ - db->mallocFailed = 1; - sqlite3_finalize(pStmt); - return SQLITE_NOMEM; - } - } - rc = sqlite3_finalize(pStmt); - if( rc ) return rc; - - zSql = sqlite3MPrintf(db, - "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb); - if( !zSql ){ - return SQLITE_NOMEM; - } - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - sqlite3DbFree(db, zSql); - if( rc ) return rc; - - while( sqlite3_step(pStmt)==SQLITE_ROW ){ - char *zIndex; /* Index name */ - Index *pIdx; /* Pointer to the index object */ - int i; /* Loop counter */ - tRowcnt sumEq; /* Sum of the nEq values */ - - zIndex = (char *)sqlite3_column_text(pStmt, 0); - if( zIndex==0 ) continue; - pIdx = sqlite3FindIndex(db, zIndex, zDb); - if( pIdx==0 ) continue; - if( pIdx==pPrevIdx ){ - idx++; - }else{ - pPrevIdx = pIdx; - idx = 0; - } - assert( idxnSample ); - pSample = &pIdx->aSample[idx]; - pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 1); - pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 2); - pSample->nDLt = (tRowcnt)sqlite3_column_int64(pStmt, 3); - if( idx==pIdx->nSample-1 ){ - if( pSample->nDLt>0 ){ - for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq; - pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt; - } - if( pIdx->avgEq<=0 ) pIdx->avgEq = 1; - } - eType = sqlite3_column_type(pStmt, 4); - pSample->eType = (u8)eType; - switch( eType ){ - case SQLITE_INTEGER: { - pSample->u.i = sqlite3_column_int64(pStmt, 4); - break; - } - case SQLITE_FLOAT: { - pSample->u.r = sqlite3_column_double(pStmt, 4); - break; - } - case SQLITE_NULL: { - break; - } - default: assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); { - const char *z = (const char *)( - (eType==SQLITE_BLOB) ? - sqlite3_column_blob(pStmt, 4): - sqlite3_column_text(pStmt, 4) - ); - int n = z ? sqlite3_column_bytes(pStmt, 4) : 0; - pSample->nByte = n; - if( n < 1){ - pSample->u.z = 0; - }else{ - pSample->u.z = sqlite3DbMallocRaw(db, n); - if( pSample->u.z==0 ){ - db->mallocFailed = 1; - sqlite3_finalize(pStmt); - return SQLITE_NOMEM; - } - memcpy(pSample->u.z, z, n); - } - } - } - } - return sqlite3_finalize(pStmt); -} -#endif /* SQLITE_ENABLE_STAT3 */ - -/* -** Load the content of the sqlite_stat1 and sqlite_stat3 tables. The -** contents of sqlite_stat1 are used to populate the Index.aiRowEst[] -** arrays. The contents of sqlite_stat3 are used to populate the -** Index.aSample[] arrays. -** -** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR -** is returned. In this case, even if SQLITE_ENABLE_STAT3 was defined -** during compilation and the sqlite_stat3 table is present, no data is -** read from it. -** -** If SQLITE_ENABLE_STAT3 was defined during compilation and the -** sqlite_stat3 table is not present in the database, SQLITE_ERROR is -** returned. However, in this case, data is read from the sqlite_stat1 -** table (if it is present) before returning. -** -** If an OOM error occurs, this function always sets db->mallocFailed. -** This means if the caller does not care about other errors, the return -** code may be ignored. -*/ -SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ - analysisInfo sInfo; - HashElem *i; - char *zSql; - int rc; - - assert( iDb>=0 && iDbnDb ); - assert( db->aDb[iDb].pBt!=0 ); - - /* Clear any prior statistics */ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ - Index *pIdx = sqliteHashData(i); - sqlite3DefaultRowEst(pIdx); -#ifdef SQLITE_ENABLE_STAT3 - sqlite3DeleteIndexSamples(db, pIdx); - pIdx->aSample = 0; -#endif - } - - /* Check to make sure the sqlite_stat1 table exists */ - sInfo.db = db; - sInfo.zDatabase = db->aDb[iDb].zName; - if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ - return SQLITE_ERROR; - } - - /* Load new statistics out of the sqlite_stat1 table */ - zSql = sqlite3MPrintf(db, - "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); - if( zSql==0 ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); - sqlite3DbFree(db, zSql); - } - - - /* Load the statistics from the sqlite_stat3 table. */ -#ifdef SQLITE_ENABLE_STAT3 - if( rc==SQLITE_OK ){ - int lookasideEnabled = db->lookaside.bEnabled; - db->lookaside.bEnabled = 0; - rc = loadStat3(db, sInfo.zDatabase); - db->lookaside.bEnabled = lookasideEnabled; - } -#endif - - if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; - } - return rc; -} - - -#endif /* SQLITE_OMIT_ANALYZE */ - -/************** End of analyze.c *********************************************/ -/************** Begin file attach.c ******************************************/ -/* -** 2003 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the ATTACH and DETACH commands. -*/ - -#ifndef SQLITE_OMIT_ATTACH -/* -** Resolve an expression that was part of an ATTACH or DETACH statement. This -** is slightly different from resolving a normal SQL expression, because simple -** identifiers are treated as strings, not possible column names or aliases. -** -** i.e. if the parser sees: -** -** ATTACH DATABASE abc AS def -** -** it treats the two expressions as literal strings 'abc' and 'def' instead of -** looking for columns of the same name. -** -** This only applies to the root node of pExpr, so the statement: -** -** ATTACH DATABASE abc||def AS 'db2' -** -** will fail because neither abc or def can be resolved. -*/ -static int resolveAttachExpr(NameContext *pName, Expr *pExpr) -{ - int rc = SQLITE_OK; - if( pExpr ){ - if( pExpr->op!=TK_ID ){ - rc = sqlite3ResolveExprNames(pName, pExpr); - if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){ - sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken); - return SQLITE_ERROR; - } - }else{ - pExpr->op = TK_STRING; - } - } - return rc; -} - -/* -** An SQL user-function registered to do the work of an ATTACH statement. The -** three arguments to the function come directly from an attach statement: -** -** ATTACH DATABASE x AS y KEY z -** -** SELECT sqlite_attach(x, y, z) -** -** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the -** third argument. -*/ -static void attachFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - int i; - int rc = 0; - sqlite3 *db = sqlite3_context_db_handle(context); - const char *zName; - const char *zFile; - char *zPath = 0; - char *zErr = 0; - unsigned int flags; - Db *aNew; - char *zErrDyn = 0; - sqlite3_vfs *pVfs; - - UNUSED_PARAMETER(NotUsed); - - zFile = (const char *)sqlite3_value_text(argv[0]); - zName = (const char *)sqlite3_value_text(argv[1]); - if( zFile==0 ) zFile = ""; - if( zName==0 ) zName = ""; - - /* Check for the following errors: - ** - ** * Too many attached databases, - ** * Transaction currently open - ** * Specified database name already being used. - */ - if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ - zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", - db->aLimit[SQLITE_LIMIT_ATTACHED] - ); - goto attach_error; - } - if( !db->autoCommit ){ - zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction"); - goto attach_error; - } - for(i=0; inDb; i++){ - char *z = db->aDb[i].zName; - assert( z && zName ); - if( sqlite3StrICmp(z, zName)==0 ){ - zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); - goto attach_error; - } - } - - /* Allocate the new entry in the db->aDb[] array and initialize the schema - ** hash tables. - */ - if( db->aDb==db->aDbStatic ){ - aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); - if( aNew==0 ) return; - memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); - }else{ - aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); - if( aNew==0 ) return; - } - db->aDb = aNew; - aNew = &db->aDb[db->nDb]; - memset(aNew, 0, sizeof(*aNew)); - - /* Open the database file. If the btree is successfully opened, use - ** it to obtain the database schema. At this point the schema may - ** or may not be initialized. - */ - flags = db->openFlags; - rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - assert( pVfs ); - flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags); - sqlite3_free( zPath ); - db->nDb++; - if( rc==SQLITE_CONSTRAINT ){ - rc = SQLITE_ERROR; - zErrDyn = sqlite3MPrintf(db, "database is already attached"); - }else if( rc==SQLITE_OK ){ - Pager *pPager; - aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); - if( !aNew->pSchema ){ - rc = SQLITE_NOMEM; - }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ - zErrDyn = sqlite3MPrintf(db, - "attached databases must use the same text encoding as main database"); - rc = SQLITE_ERROR; - } - pPager = sqlite3BtreePager(aNew->pBt); - sqlite3PagerLockingMode(pPager, db->dfltLockMode); - sqlite3BtreeSecureDelete(aNew->pBt, - sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); - } - aNew->safety_level = 3; - aNew->zName = sqlite3DbStrDup(db, zName); - if( rc==SQLITE_OK && aNew->zName==0 ){ - rc = SQLITE_NOMEM; - } - - -#ifdef SQLITE_HAS_CODEC - if( rc==SQLITE_OK ){ - extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); - extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); - int nKey; - char *zKey; - int t = sqlite3_value_type(argv[2]); - switch( t ){ - case SQLITE_INTEGER: - case SQLITE_FLOAT: - zErrDyn = sqlite3DbStrDup(db, "Invalid key value"); - rc = SQLITE_ERROR; - break; - - case SQLITE_TEXT: - case SQLITE_BLOB: - nKey = sqlite3_value_bytes(argv[2]); - zKey = (char *)sqlite3_value_blob(argv[2]); - rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); - break; - - case SQLITE_NULL: - /* No key specified. Use the key from the main database */ - sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){ - rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); - } - break; - } - } -#endif - - /* If the file was opened successfully, read the schema for the new database. - ** If this fails, or if opening the file failed, then close the file and - ** remove the entry from the db->aDb[] array. i.e. put everything back the way - ** we found it. - */ - if( rc==SQLITE_OK ){ - sqlite3BtreeEnterAll(db); - rc = sqlite3Init(db, &zErrDyn); - sqlite3BtreeLeaveAll(db); - } - if( rc ){ - int iDb = db->nDb - 1; - assert( iDb>=2 ); - if( db->aDb[iDb].pBt ){ - sqlite3BtreeClose(db->aDb[iDb].pBt); - db->aDb[iDb].pBt = 0; - db->aDb[iDb].pSchema = 0; - } - sqlite3ResetAllSchemasOfConnection(db); - db->nDb = iDb; - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - db->mallocFailed = 1; - sqlite3DbFree(db, zErrDyn); - zErrDyn = sqlite3MPrintf(db, "out of memory"); - }else if( zErrDyn==0 ){ - zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); - } - goto attach_error; - } - - return; - -attach_error: - /* Return an error if we get here */ - if( zErrDyn ){ - sqlite3_result_error(context, zErrDyn, -1); - sqlite3DbFree(db, zErrDyn); - } - if( rc ) sqlite3_result_error_code(context, rc); -} - -/* -** An SQL user-function registered to do the work of an DETACH statement. The -** three arguments to the function come directly from a detach statement: -** -** DETACH DATABASE x -** -** SELECT sqlite_detach(x) -*/ -static void detachFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - const char *zName = (const char *)sqlite3_value_text(argv[0]); - sqlite3 *db = sqlite3_context_db_handle(context); - int i; - Db *pDb = 0; - char zErr[128]; - - UNUSED_PARAMETER(NotUsed); - - if( zName==0 ) zName = ""; - for(i=0; inDb; i++){ - pDb = &db->aDb[i]; - if( pDb->pBt==0 ) continue; - if( sqlite3StrICmp(pDb->zName, zName)==0 ) break; - } - - if( i>=db->nDb ){ - sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName); - goto detach_error; - } - if( i<2 ){ - sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); - goto detach_error; - } - if( !db->autoCommit ){ - sqlite3_snprintf(sizeof(zErr), zErr, - "cannot DETACH database within transaction"); - goto detach_error; - } - if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){ - sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); - goto detach_error; - } - - sqlite3BtreeClose(pDb->pBt); - pDb->pBt = 0; - pDb->pSchema = 0; - sqlite3ResetAllSchemasOfConnection(db); - return; - -detach_error: - sqlite3_result_error(context, zErr, -1); -} - -/* -** This procedure generates VDBE code for a single invocation of either the -** sqlite_detach() or sqlite_attach() SQL user functions. -*/ -static void codeAttach( - Parse *pParse, /* The parser context */ - int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */ - FuncDef const *pFunc,/* FuncDef wrapper for detachFunc() or attachFunc() */ - Expr *pAuthArg, /* Expression to pass to authorization callback */ - Expr *pFilename, /* Name of database file */ - Expr *pDbname, /* Name of the database to use internally */ - Expr *pKey /* Database key for encryption extension */ -){ - int rc; - NameContext sName; - Vdbe *v; - sqlite3* db = pParse->db; - int regArgs; - - memset(&sName, 0, sizeof(NameContext)); - sName.pParse = pParse; - - if( - SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || - SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || - SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) - ){ - pParse->nErr++; - goto attach_end; - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - if( pAuthArg ){ - char *zAuthArg; - if( pAuthArg->op==TK_STRING ){ - zAuthArg = pAuthArg->u.zToken; - }else{ - zAuthArg = 0; - } - rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); - if(rc!=SQLITE_OK ){ - goto attach_end; - } - } -#endif /* SQLITE_OMIT_AUTHORIZATION */ - - - v = sqlite3GetVdbe(pParse); - regArgs = sqlite3GetTempRange(pParse, 4); - sqlite3ExprCode(pParse, pFilename, regArgs); - sqlite3ExprCode(pParse, pDbname, regArgs+1); - sqlite3ExprCode(pParse, pKey, regArgs+2); - - assert( v || db->mallocFailed ); - if( v ){ - sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3); - assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg ); - sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg)); - sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF); - - /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this - ** statement only). For DETACH, set it to false (expire all existing - ** statements). - */ - sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH)); - } - -attach_end: - sqlite3ExprDelete(db, pFilename); - sqlite3ExprDelete(db, pDbname); - sqlite3ExprDelete(db, pKey); -} - -/* -** Called by the parser to compile a DETACH statement. -** -** DETACH pDbname -*/ -SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){ - static const FuncDef detach_func = { - 1, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ - 0, /* pUserData */ - 0, /* pNext */ - detachFunc, /* xFunc */ - 0, /* xStep */ - 0, /* xFinalize */ - "sqlite_detach", /* zName */ - 0, /* pHash */ - 0 /* pDestructor */ - }; - codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname); -} - -/* -** Called by the parser to compile an ATTACH statement. -** -** ATTACH p AS pDbname KEY pKey -*/ -SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ - static const FuncDef attach_func = { - 3, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ - 0, /* pUserData */ - 0, /* pNext */ - attachFunc, /* xFunc */ - 0, /* xStep */ - 0, /* xFinalize */ - "sqlite_attach", /* zName */ - 0, /* pHash */ - 0 /* pDestructor */ - }; - codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); -} -#endif /* SQLITE_OMIT_ATTACH */ - -/* -** Initialize a DbFixer structure. This routine must be called prior -** to passing the structure to one of the sqliteFixAAAA() routines below. -** -** The return value indicates whether or not fixation is required. TRUE -** means we do need to fix the database references, FALSE means we do not. -*/ -SQLITE_PRIVATE int sqlite3FixInit( - DbFixer *pFix, /* The fixer to be initialized */ - Parse *pParse, /* Error messages will be written here */ - int iDb, /* This is the database that must be used */ - const char *zType, /* "view", "trigger", or "index" */ - const Token *pName /* Name of the view, trigger, or index */ -){ - sqlite3 *db; - - if( NEVER(iDb<0) || iDb==1 ) return 0; - db = pParse->db; - assert( db->nDb>iDb ); - pFix->pParse = pParse; - pFix->zDb = db->aDb[iDb].zName; - pFix->pSchema = db->aDb[iDb].pSchema; - pFix->zType = zType; - pFix->pName = pName; - return 1; -} - -/* -** The following set of routines walk through the parse tree and assign -** a specific database to all table references where the database name -** was left unspecified in the original SQL statement. The pFix structure -** must have been initialized by a prior call to sqlite3FixInit(). -** -** These routines are used to make sure that an index, trigger, or -** view in one database does not refer to objects in a different database. -** (Exception: indices, triggers, and views in the TEMP database are -** allowed to refer to anything.) If a reference is explicitly made -** to an object in a different database, an error message is added to -** pParse->zErrMsg and these routines return non-zero. If everything -** checks out, these routines return 0. -*/ -SQLITE_PRIVATE int sqlite3FixSrcList( - DbFixer *pFix, /* Context of the fixation */ - SrcList *pList /* The Source list to check and modify */ -){ - int i; - const char *zDb; - struct SrcList_item *pItem; - - if( NEVER(pList==0) ) return 0; - zDb = pFix->zDb; - for(i=0, pItem=pList->a; inSrc; i++, pItem++){ - if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ - sqlite3ErrorMsg(pFix->pParse, - "%s %T cannot reference objects in database %s", - pFix->zType, pFix->pName, pItem->zDatabase); - return 1; - } - sqlite3DbFree(pFix->pParse->db, pItem->zDatabase); - pItem->zDatabase = 0; - pItem->pSchema = pFix->pSchema; -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) - if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; - if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; -#endif - } - return 0; -} -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) -SQLITE_PRIVATE int sqlite3FixSelect( - DbFixer *pFix, /* Context of the fixation */ - Select *pSelect /* The SELECT statement to be fixed to one database */ -){ - while( pSelect ){ - if( sqlite3FixExprList(pFix, pSelect->pEList) ){ - return 1; - } - if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ - return 1; - } - if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ - return 1; - } - if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ - return 1; - } - pSelect = pSelect->pPrior; - } - return 0; -} -SQLITE_PRIVATE int sqlite3FixExpr( - DbFixer *pFix, /* Context of the fixation */ - Expr *pExpr /* The expression to be fixed to one database */ -){ - while( pExpr ){ - if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; - }else{ - if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; - } - if( sqlite3FixExpr(pFix, pExpr->pRight) ){ - return 1; - } - pExpr = pExpr->pLeft; - } - return 0; -} -SQLITE_PRIVATE int sqlite3FixExprList( - DbFixer *pFix, /* Context of the fixation */ - ExprList *pList /* The expression to be fixed to one database */ -){ - int i; - struct ExprList_item *pItem; - if( pList==0 ) return 0; - for(i=0, pItem=pList->a; inExpr; i++, pItem++){ - if( sqlite3FixExpr(pFix, pItem->pExpr) ){ - return 1; - } - } - return 0; -} -#endif - -#ifndef SQLITE_OMIT_TRIGGER -SQLITE_PRIVATE int sqlite3FixTriggerStep( - DbFixer *pFix, /* Context of the fixation */ - TriggerStep *pStep /* The trigger step be fixed to one database */ -){ - while( pStep ){ - if( sqlite3FixSelect(pFix, pStep->pSelect) ){ - return 1; - } - if( sqlite3FixExpr(pFix, pStep->pWhere) ){ - return 1; - } - if( sqlite3FixExprList(pFix, pStep->pExprList) ){ - return 1; - } - pStep = pStep->pNext; - } - return 0; -} -#endif - -/************** End of attach.c **********************************************/ -/************** Begin file auth.c ********************************************/ -/* -** 2003 January 11 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the sqlite3_set_authorizer() -** API. This facility is an optional feature of the library. Embedded -** systems that do not need this facility may omit it by recompiling -** the library with -DSQLITE_OMIT_AUTHORIZATION=1 -*/ - -/* -** All of the code in this file may be omitted by defining a single -** macro. -*/ -#ifndef SQLITE_OMIT_AUTHORIZATION - -/* -** Set or clear the access authorization function. -** -** The access authorization function is be called during the compilation -** phase to verify that the user has read and/or write access permission on -** various fields of the database. The first argument to the auth function -** is a copy of the 3rd argument to this routine. The second argument -** to the auth function is one of these constants: -** -** SQLITE_CREATE_INDEX -** SQLITE_CREATE_TABLE -** SQLITE_CREATE_TEMP_INDEX -** SQLITE_CREATE_TEMP_TABLE -** SQLITE_CREATE_TEMP_TRIGGER -** SQLITE_CREATE_TEMP_VIEW -** SQLITE_CREATE_TRIGGER -** SQLITE_CREATE_VIEW -** SQLITE_DELETE -** SQLITE_DROP_INDEX -** SQLITE_DROP_TABLE -** SQLITE_DROP_TEMP_INDEX -** SQLITE_DROP_TEMP_TABLE -** SQLITE_DROP_TEMP_TRIGGER -** SQLITE_DROP_TEMP_VIEW -** SQLITE_DROP_TRIGGER -** SQLITE_DROP_VIEW -** SQLITE_INSERT -** SQLITE_PRAGMA -** SQLITE_READ -** SQLITE_SELECT -** SQLITE_TRANSACTION -** SQLITE_UPDATE -** -** The third and fourth arguments to the auth function are the name of -** the table and the column that are being accessed. The auth function -** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If -** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY -** means that the SQL statement will never-run - the sqlite3_exec() call -** will return with an error. SQLITE_IGNORE means that the SQL statement -** should run but attempts to read the specified column will return NULL -** and attempts to write the column will be ignored. -** -** Setting the auth function to NULL disables this hook. The default -** setting of the auth function is NULL. -*/ -SQLITE_API int sqlite3_set_authorizer( - sqlite3 *db, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pArg -){ - sqlite3_mutex_enter(db->mutex); - db->xAuth = xAuth; - db->pAuthArg = pArg; - sqlite3ExpirePreparedStatements(db); - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -/* -** Write an error message into pParse->zErrMsg that explains that the -** user-supplied authorization function returned an illegal value. -*/ -static void sqliteAuthBadReturnCode(Parse *pParse){ - sqlite3ErrorMsg(pParse, "authorizer malfunction"); - pParse->rc = SQLITE_ERROR; -} - -/* -** Invoke the authorization callback for permission to read column zCol from -** table zTab in database zDb. This function assumes that an authorization -** callback has been registered (i.e. that sqlite3.xAuth is not NULL). -** -** If SQLITE_IGNORE is returned and pExpr is not NULL, then pExpr is changed -** to an SQL NULL expression. Otherwise, if pExpr is NULL, then SQLITE_IGNORE -** is treated as SQLITE_DENY. In this case an error is left in pParse. -*/ -SQLITE_PRIVATE int sqlite3AuthReadCol( - Parse *pParse, /* The parser context */ - const char *zTab, /* Table name */ - const char *zCol, /* Column name */ - int iDb /* Index of containing database. */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - char *zDb = db->aDb[iDb].zName; /* Name of attached database */ - int rc; /* Auth callback return code */ - - rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext); - if( rc==SQLITE_DENY ){ - if( db->nDb>2 || iDb!=0 ){ - sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol); - }else{ - sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol); - } - pParse->rc = SQLITE_AUTH; - }else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){ - sqliteAuthBadReturnCode(pParse); - } - return rc; -} - -/* -** The pExpr should be a TK_COLUMN expression. The table referred to -** is in pTabList or else it is the NEW or OLD table of a trigger. -** Check to see if it is OK to read this particular column. -** -** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN -** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, -** then generate an error. -*/ -SQLITE_PRIVATE void sqlite3AuthRead( - Parse *pParse, /* The parser context */ - Expr *pExpr, /* The expression to check authorization on */ - Schema *pSchema, /* The schema of the expression */ - SrcList *pTabList /* All table that pExpr might refer to */ -){ - sqlite3 *db = pParse->db; - Table *pTab = 0; /* The table being read */ - const char *zCol; /* Name of the column of the table */ - int iSrc; /* Index in pTabList->a[] of table being read */ - int iDb; /* The index of the database the expression refers to */ - int iCol; /* Index of column in table */ - - if( db->xAuth==0 ) return; - iDb = sqlite3SchemaToIndex(pParse->db, pSchema); - if( iDb<0 ){ - /* An attempt to read a column out of a subquery or other - ** temporary table. */ - return; - } - - assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); - if( pExpr->op==TK_TRIGGER ){ - pTab = pParse->pTriggerTab; - }else{ - assert( pTabList ); - for(iSrc=0; ALWAYS(iSrcnSrc); iSrc++){ - if( pExpr->iTable==pTabList->a[iSrc].iCursor ){ - pTab = pTabList->a[iSrc].pTab; - break; - } - } - } - iCol = pExpr->iColumn; - if( NEVER(pTab==0) ) return; - - if( iCol>=0 ){ - assert( iColnCol ); - zCol = pTab->aCol[iCol].zName; - }else if( pTab->iPKey>=0 ){ - assert( pTab->iPKeynCol ); - zCol = pTab->aCol[pTab->iPKey].zName; - }else{ - zCol = "ROWID"; - } - assert( iDb>=0 && iDbnDb ); - if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){ - pExpr->op = TK_NULL; - } -} - -/* -** Do an authorization check using the code and arguments given. Return -** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY -** is returned, then the error count and error message in pParse are -** modified appropriately. -*/ -SQLITE_PRIVATE int sqlite3AuthCheck( - Parse *pParse, - int code, - const char *zArg1, - const char *zArg2, - const char *zArg3 -){ - sqlite3 *db = pParse->db; - int rc; - - /* Don't do any authorization checks if the database is initialising - ** or if the parser is being invoked from within sqlite3_declare_vtab. - */ - if( db->init.busy || IN_DECLARE_VTAB ){ - return SQLITE_OK; - } - - if( db->xAuth==0 ){ - return SQLITE_OK; - } - rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext); - if( rc==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized"); - pParse->rc = SQLITE_AUTH; - }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ - rc = SQLITE_DENY; - sqliteAuthBadReturnCode(pParse); - } - return rc; -} - -/* -** Push an authorization context. After this routine is called, the -** zArg3 argument to authorization callbacks will be zContext until -** popped. Or if pParse==0, this routine is a no-op. -*/ -SQLITE_PRIVATE void sqlite3AuthContextPush( - Parse *pParse, - AuthContext *pContext, - const char *zContext -){ - assert( pParse ); - pContext->pParse = pParse; - pContext->zAuthContext = pParse->zAuthContext; - pParse->zAuthContext = zContext; -} - -/* -** Pop an authorization context that was previously pushed -** by sqlite3AuthContextPush -*/ -SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){ - if( pContext->pParse ){ - pContext->pParse->zAuthContext = pContext->zAuthContext; - pContext->pParse = 0; - } -} - -#endif /* SQLITE_OMIT_AUTHORIZATION */ - -/************** End of auth.c ************************************************/ -/************** Begin file build.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the SQLite parser -** when syntax rules are reduced. The routines in this file handle the -** following kinds of SQL syntax: -** -** CREATE TABLE -** DROP TABLE -** CREATE INDEX -** DROP INDEX -** creating ID lists -** BEGIN TRANSACTION -** COMMIT -** ROLLBACK -*/ - -/* -** This routine is called when a new SQL statement is beginning to -** be parsed. Initialize the pParse structure as needed. -*/ -SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){ - pParse->explain = (u8)explainFlag; - pParse->nVar = 0; -} - -#ifndef SQLITE_OMIT_SHARED_CACHE -/* -** The TableLock structure is only used by the sqlite3TableLock() and -** codeTableLocks() functions. -*/ -struct TableLock { - int iDb; /* The database containing the table to be locked */ - int iTab; /* The root page of the table to be locked */ - u8 isWriteLock; /* True for write lock. False for a read lock */ - const char *zName; /* Name of the table */ -}; - -/* -** Record the fact that we want to lock a table at run-time. -** -** The table to be locked has root page iTab and is found in database iDb. -** A read or a write lock can be taken depending on isWritelock. -** -** This routine just records the fact that the lock is desired. The -** code to make the lock occur is generated by a later call to -** codeTableLocks() which occurs during sqlite3FinishCoding(). -*/ -SQLITE_PRIVATE void sqlite3TableLock( - Parse *pParse, /* Parsing context */ - int iDb, /* Index of the database containing the table to lock */ - int iTab, /* Root page number of the table to be locked */ - u8 isWriteLock, /* True for a write lock */ - const char *zName /* Name of the table to be locked */ -){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - int i; - int nBytes; - TableLock *p; - assert( iDb>=0 ); - - for(i=0; inTableLock; i++){ - p = &pToplevel->aTableLock[i]; - if( p->iDb==iDb && p->iTab==iTab ){ - p->isWriteLock = (p->isWriteLock || isWriteLock); - return; - } - } - - nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1); - pToplevel->aTableLock = - sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes); - if( pToplevel->aTableLock ){ - p = &pToplevel->aTableLock[pToplevel->nTableLock++]; - p->iDb = iDb; - p->iTab = iTab; - p->isWriteLock = isWriteLock; - p->zName = zName; - }else{ - pToplevel->nTableLock = 0; - pToplevel->db->mallocFailed = 1; - } -} - -/* -** Code an OP_TableLock instruction for each table locked by the -** statement (configured by calls to sqlite3TableLock()). -*/ -static void codeTableLocks(Parse *pParse){ - int i; - Vdbe *pVdbe; - - pVdbe = sqlite3GetVdbe(pParse); - assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */ - - for(i=0; inTableLock; i++){ - TableLock *p = &pParse->aTableLock[i]; - int p1 = p->iDb; - sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, - p->zName, P4_STATIC); - } -} -#else - #define codeTableLocks(x) -#endif - -/* -** This routine is called after a single SQL statement has been -** parsed and a VDBE program to execute that statement has been -** prepared. This routine puts the finishing touches on the -** VDBE program and resets the pParse structure for the next -** parse. -** -** Note that if an error occurred, it might be the case that -** no VDBE code was generated. -*/ -SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ - sqlite3 *db; - Vdbe *v; - - assert( pParse->pToplevel==0 ); - db = pParse->db; - if( db->mallocFailed ) return; - if( pParse->nested ) return; - if( pParse->nErr ) return; - - /* Begin by generating some termination code at the end of the - ** vdbe program - */ - v = sqlite3GetVdbe(pParse); - assert( !pParse->isMultiWrite - || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); - if( v ){ - sqlite3VdbeAddOp0(v, OP_Halt); - - /* The cookie mask contains one bit for each database file open. - ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are - ** set for each database that is used. Generate code to start a - ** transaction on each used database and to verify the schema cookie - ** on each used database. - */ - if( pParse->cookieGoto>0 ){ - yDbMask mask; - int iDb; - sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); - for(iDb=0, mask=1; iDbnDb; mask<<=1, iDb++){ - if( (mask & pParse->cookieMask)==0 ) continue; - sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); - if( db->init.busy==0 ){ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - sqlite3VdbeAddOp3(v, OP_VerifyCookie, - iDb, pParse->cookieValue[iDb], - db->aDb[iDb].pSchema->iGeneration); - } - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - { - int i; - for(i=0; inVtabLock; i++){ - char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); - sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); - } - pParse->nVtabLock = 0; - } -#endif - - /* Once all the cookies have been verified and transactions opened, - ** obtain the required table-locks. This is a no-op unless the - ** shared-cache feature is enabled. - */ - codeTableLocks(pParse); - - /* Initialize any AUTOINCREMENT data structures required. - */ - sqlite3AutoincrementBegin(pParse); - - /* Finally, jump back to the beginning of the executable code. */ - sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto); - } - } - - - /* Get the VDBE program ready for execution - */ - if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){ -#ifdef SQLITE_DEBUG - FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; - sqlite3VdbeTrace(v, trace); -#endif - assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ - /* A minimum of one cursor is required if autoincrement is used - * See ticket [a696379c1f08866] */ - if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1; - sqlite3VdbeMakeReady(v, pParse); - pParse->rc = SQLITE_DONE; - pParse->colNamesSet = 0; - }else{ - pParse->rc = SQLITE_ERROR; - } - pParse->nTab = 0; - pParse->nMem = 0; - pParse->nSet = 0; - pParse->nVar = 0; - pParse->cookieMask = 0; - pParse->cookieGoto = 0; -} - -/* -** Run the parser and code generator recursively in order to generate -** code for the SQL statement given onto the end of the pParse context -** currently under construction. When the parser is run recursively -** this way, the final OP_Halt is not appended and other initialization -** and finalization steps are omitted because those are handling by the -** outermost parser. -** -** Not everything is nestable. This facility is designed to permit -** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use -** care if you decide to try to use this routine for some other purposes. -*/ -SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ - va_list ap; - char *zSql; - char *zErrMsg = 0; - sqlite3 *db = pParse->db; -# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) - char saveBuf[SAVE_SZ]; - - if( pParse->nErr ) return; - assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ - va_start(ap, zFormat); - zSql = sqlite3VMPrintf(db, zFormat, ap); - va_end(ap); - if( zSql==0 ){ - return; /* A malloc must have failed */ - } - pParse->nested++; - memcpy(saveBuf, &pParse->nVar, SAVE_SZ); - memset(&pParse->nVar, 0, SAVE_SZ); - sqlite3RunParser(pParse, zSql, &zErrMsg); - sqlite3DbFree(db, zErrMsg); - sqlite3DbFree(db, zSql); - memcpy(&pParse->nVar, saveBuf, SAVE_SZ); - pParse->nested--; -} - -/* -** Locate the in-memory structure that describes a particular database -** table given the name of that table and (optionally) the name of the -** database containing the table. Return NULL if not found. -** -** If zDatabase is 0, all databases are searched for the table and the -** first matching table is returned. (No checking for duplicate table -** names is done.) The search order is TEMP first, then MAIN, then any -** auxiliary databases added using the ATTACH command. -** -** See also sqlite3LocateTable(). -*/ -SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ - Table *p = 0; - int i; - int nName; - assert( zName!=0 ); - nName = sqlite3Strlen30(zName); - /* All mutexes are required for schema access. Make sure we hold them. */ - assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); - for(i=OMIT_TEMPDB; inDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName); - if( p ) break; - } - return p; -} - -/* -** Locate the in-memory structure that describes a particular database -** table given the name of that table and (optionally) the name of the -** database containing the table. Return NULL if not found. Also leave an -** error message in pParse->zErrMsg. -** -** The difference between this routine and sqlite3FindTable() is that this -** routine leaves an error message in pParse->zErrMsg where -** sqlite3FindTable() does not. -*/ -SQLITE_PRIVATE Table *sqlite3LocateTable( - Parse *pParse, /* context in which to report errors */ - int isView, /* True if looking for a VIEW rather than a TABLE */ - const char *zName, /* Name of the table we are looking for */ - const char *zDbase /* Name of the database. Might be NULL */ -){ - Table *p; - - /* Read the database schema. If an error occurs, leave an error message - ** and code in pParse and return NULL. */ - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - return 0; - } - - p = sqlite3FindTable(pParse->db, zName, zDbase); - if( p==0 ){ - const char *zMsg = isView ? "no such view" : "no such table"; - if( zDbase ){ - sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); - }else{ - sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); - } - pParse->checkSchema = 1; - } - return p; -} - -/* -** Locate the table identified by *p. -** -** This is a wrapper around sqlite3LocateTable(). The difference between -** sqlite3LocateTable() and this function is that this function restricts -** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be -** non-NULL if it is part of a view or trigger program definition. See -** sqlite3FixSrcList() for details. -*/ -SQLITE_PRIVATE Table *sqlite3LocateTableItem( - Parse *pParse, - int isView, - struct SrcList_item *p -){ - const char *zDb; - assert( p->pSchema==0 || p->zDatabase==0 ); - if( p->pSchema ){ - int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); - zDb = pParse->db->aDb[iDb].zName; - }else{ - zDb = p->zDatabase; - } - return sqlite3LocateTable(pParse, isView, p->zName, zDb); -} - -/* -** Locate the in-memory structure that describes -** a particular index given the name of that index -** and the name of the database that contains the index. -** Return NULL if not found. -** -** If zDatabase is 0, all databases are searched for the -** table and the first matching index is returned. (No checking -** for duplicate index names is done.) The search order is -** TEMP first, then MAIN, then any auxiliary databases added -** using the ATTACH command. -*/ -SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ - Index *p = 0; - int i; - int nName = sqlite3Strlen30(zName); - /* All mutexes are required for schema access. Make sure we hold them. */ - assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); - for(i=OMIT_TEMPDB; inDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - Schema *pSchema = db->aDb[j].pSchema; - assert( pSchema ); - if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&pSchema->idxHash, zName, nName); - if( p ) break; - } - return p; -} - -/* -** Reclaim the memory used by an index -*/ -static void freeIndex(sqlite3 *db, Index *p){ -#ifndef SQLITE_OMIT_ANALYZE - sqlite3DeleteIndexSamples(db, p); -#endif - sqlite3DbFree(db, p->zColAff); - sqlite3DbFree(db, p); -} - -/* -** For the index called zIdxName which is found in the database iDb, -** unlike that index from its Table then remove the index from -** the index hash table and free all memory structures associated -** with the index. -*/ -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ - Index *pIndex; - int len; - Hash *pHash; - - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pHash = &db->aDb[iDb].pSchema->idxHash; - len = sqlite3Strlen30(zIdxName); - pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0); - if( ALWAYS(pIndex) ){ - if( pIndex->pTable->pIndex==pIndex ){ - pIndex->pTable->pIndex = pIndex->pNext; - }else{ - Index *p; - /* Justification of ALWAYS(); The index must be on the list of - ** indices. */ - p = pIndex->pTable->pIndex; - while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; } - if( ALWAYS(p && p->pNext==pIndex) ){ - p->pNext = pIndex->pNext; - } - } - freeIndex(db, pIndex); - } - db->flags |= SQLITE_InternChanges; -} - -/* -** Look through the list of open database files in db->aDb[] and if -** any have been closed, remove them from the list. Reallocate the -** db->aDb[] structure to a smaller size, if possible. -** -** Entry 0 (the "main" database) and entry 1 (the "temp" database) -** are never candidates for being collapsed. -*/ -SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){ - int i, j; - for(i=j=2; inDb; i++){ - struct Db *pDb = &db->aDb[i]; - if( pDb->pBt==0 ){ - sqlite3DbFree(db, pDb->zName); - pDb->zName = 0; - continue; - } - if( jaDb[j] = db->aDb[i]; - } - j++; - } - memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); - db->nDb = j; - if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ - memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); - sqlite3DbFree(db, db->aDb); - db->aDb = db->aDbStatic; - } -} - -/* -** Reset the schema for the database at index iDb. Also reset the -** TEMP schema. -*/ -SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ - Db *pDb; - assert( iDbnDb ); - - /* Case 1: Reset the single schema identified by iDb */ - pDb = &db->aDb[iDb]; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - assert( pDb->pSchema!=0 ); - sqlite3SchemaClear(pDb->pSchema); - - /* If any database other than TEMP is reset, then also reset TEMP - ** since TEMP might be holding triggers that reference tables in the - ** other database. - */ - if( iDb!=1 ){ - pDb = &db->aDb[1]; - assert( pDb->pSchema!=0 ); - sqlite3SchemaClear(pDb->pSchema); - } - return; -} - -/* -** Erase all schema information from all attached databases (including -** "main" and "temp") for a single database connection. -*/ -SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ - int i; - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Db *pDb = &db->aDb[i]; - if( pDb->pSchema ){ - sqlite3SchemaClear(pDb->pSchema); - } - } - db->flags &= ~SQLITE_InternChanges; - sqlite3VtabUnlockList(db); - sqlite3BtreeLeaveAll(db); - sqlite3CollapseDatabaseArray(db); -} - -/* -** This routine is called when a commit occurs. -*/ -SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ - db->flags &= ~SQLITE_InternChanges; -} - -/* -** Delete memory allocated for the column names of a table or view (the -** Table.aCol[] array). -*/ -static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){ - int i; - Column *pCol; - assert( pTable!=0 ); - if( (pCol = pTable->aCol)!=0 ){ - for(i=0; inCol; i++, pCol++){ - sqlite3DbFree(db, pCol->zName); - sqlite3ExprDelete(db, pCol->pDflt); - sqlite3DbFree(db, pCol->zDflt); - sqlite3DbFree(db, pCol->zType); - sqlite3DbFree(db, pCol->zColl); - } - sqlite3DbFree(db, pTable->aCol); - } -} - -/* -** Remove the memory data structures associated with the given -** Table. No changes are made to disk by this routine. -** -** This routine just deletes the data structure. It does not unlink -** the table data structure from the hash table. But it does destroy -** memory structures of the indices and foreign keys associated with -** the table. -** -** The db parameter is optional. It is needed if the Table object -** contains lookaside memory. (Table objects in the schema do not use -** lookaside memory, but some ephemeral Table objects do.) Or the -** db parameter can be used with db->pnBytesFreed to measure the memory -** used by the Table object. -*/ -SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ - Index *pIndex, *pNext; - TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */ - - assert( !pTable || pTable->nRef>0 ); - - /* Do not delete the table until the reference count reaches zero. */ - if( !pTable ) return; - if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return; - - /* Record the number of outstanding lookaside allocations in schema Tables - ** prior to doing any free() operations. Since schema Tables do not use - ** lookaside, this number should not change. */ - TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ? - db->lookaside.nOut : 0 ); - - /* Delete all indices associated with this table. */ - for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ - pNext = pIndex->pNext; - assert( pIndex->pSchema==pTable->pSchema ); - if( !db || db->pnBytesFreed==0 ){ - char *zName = pIndex->zName; - TESTONLY ( Index *pOld = ) sqlite3HashInsert( - &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0 - ); - assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); - assert( pOld==pIndex || pOld==0 ); - } - freeIndex(db, pIndex); - } - - /* Delete any foreign keys attached to this table. */ - sqlite3FkDelete(db, pTable); - - /* Delete the Table structure itself. - */ - sqliteDeleteColumnNames(db, pTable); - sqlite3DbFree(db, pTable->zName); - sqlite3DbFree(db, pTable->zColAff); - sqlite3SelectDelete(db, pTable->pSelect); -#ifndef SQLITE_OMIT_CHECK - sqlite3ExprListDelete(db, pTable->pCheck); -#endif -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3VtabClear(db, pTable); -#endif - sqlite3DbFree(db, pTable); - - /* Verify that no lookaside memory was used by schema tables */ - assert( nLookaside==0 || nLookaside==db->lookaside.nOut ); -} - -/* -** Unlink the given table from the hash tables and the delete the -** table structure with all its indices and foreign keys. -*/ -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ - Table *p; - Db *pDb; - - assert( db!=0 ); - assert( iDb>=0 && iDbnDb ); - assert( zTabName ); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ - pDb = &db->aDb[iDb]; - p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, - sqlite3Strlen30(zTabName),0); - sqlite3DeleteTable(db, p); - db->flags |= SQLITE_InternChanges; -} - -/* -** Given a token, return a string that consists of the text of that -** token. Space to hold the returned string -** is obtained from sqliteMalloc() and must be freed by the calling -** function. -** -** Any quotation marks (ex: "name", 'name', [name], or `name`) that -** surround the body of the token are removed. -** -** Tokens are often just pointers into the original SQL text and so -** are not \000 terminated and are not persistent. The returned string -** is \000 terminated and is persistent. -*/ -SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ - char *zName; - if( pName ){ - zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n); - sqlite3Dequote(zName); - }else{ - zName = 0; - } - return zName; -} - -/* -** Open the sqlite_master table stored in database number iDb for -** writing. The table is opened using cursor 0. -*/ -SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){ - Vdbe *v = sqlite3GetVdbe(p); - sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); - sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb); - sqlite3VdbeChangeP4(v, -1, (char *)5, P4_INT32); /* 5 column table */ - if( p->nTab==0 ){ - p->nTab = 1; - } -} - -/* -** Parameter zName points to a nul-terminated buffer containing the name -** of a database ("main", "temp" or the name of an attached db). This -** function returns the index of the named database in db->aDb[], or -** -1 if the named db cannot be found. -*/ -SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){ - int i = -1; /* Database number */ - if( zName ){ - Db *pDb; - int n = sqlite3Strlen30(zName); - for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ - if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) && - 0==sqlite3StrICmp(pDb->zName, zName) ){ - break; - } - } - } - return i; -} - -/* -** The token *pName contains the name of a database (either "main" or -** "temp" or the name of an attached db). This routine returns the -** index of the named database in db->aDb[], or -1 if the named db -** does not exist. -*/ -SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){ - int i; /* Database number */ - char *zName; /* Name we are searching for */ - zName = sqlite3NameFromToken(db, pName); - i = sqlite3FindDbName(db, zName); - sqlite3DbFree(db, zName); - return i; -} - -/* The table or view or trigger name is passed to this routine via tokens -** pName1 and pName2. If the table name was fully qualified, for example: -** -** CREATE TABLE xxx.yyy (...); -** -** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if -** the table name is not fully qualified, i.e.: -** -** CREATE TABLE yyy(...); -** -** Then pName1 is set to "yyy" and pName2 is "". -** -** This routine sets the *ppUnqual pointer to point at the token (pName1 or -** pName2) that stores the unqualified table name. The index of the -** database "xxx" is returned. -*/ -SQLITE_PRIVATE int sqlite3TwoPartName( - Parse *pParse, /* Parsing and code generating context */ - Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */ - Token *pName2, /* The "yyy" in the name "xxx.yyy" */ - Token **pUnqual /* Write the unqualified object name here */ -){ - int iDb; /* Database holding the object */ - sqlite3 *db = pParse->db; - - if( ALWAYS(pName2!=0) && pName2->n>0 ){ - if( db->init.busy ) { - sqlite3ErrorMsg(pParse, "corrupt database"); - pParse->nErr++; - return -1; - } - *pUnqual = pName2; - iDb = sqlite3FindDb(db, pName1); - if( iDb<0 ){ - sqlite3ErrorMsg(pParse, "unknown database %T", pName1); - pParse->nErr++; - return -1; - } - }else{ - assert( db->init.iDb==0 || db->init.busy ); - iDb = db->init.iDb; - *pUnqual = pName1; - } - return iDb; -} - -/* -** This routine is used to check if the UTF-8 string zName is a legal -** unqualified name for a new schema object (table, index, view or -** trigger). All names are legal except those that begin with the string -** "sqlite_" (in upper, lower or mixed case). This portion of the namespace -** is reserved for internal use. -*/ -SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){ - if( !pParse->db->init.busy && pParse->nested==0 - && (pParse->db->flags & SQLITE_WriteSchema)==0 - && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ - sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); - return SQLITE_ERROR; - } - return SQLITE_OK; -} - -/* -** Begin constructing a new table representation in memory. This is -** the first of several action routines that get called in response -** to a CREATE TABLE statement. In particular, this routine is called -** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp -** flag is true if the table should be stored in the auxiliary database -** file instead of in the main database file. This is normally the case -** when the "TEMP" or "TEMPORARY" keyword occurs in between -** CREATE and TABLE. -** -** The new table record is initialized and put in pParse->pNewTable. -** As more of the CREATE TABLE statement is parsed, additional action -** routines will be called to add more information to this record. -** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine -** is called to complete the construction of the new table record. -*/ -SQLITE_PRIVATE void sqlite3StartTable( - Parse *pParse, /* Parser context */ - Token *pName1, /* First part of the name of the table or view */ - Token *pName2, /* Second part of the name of the table or view */ - int isTemp, /* True if this is a TEMP table */ - int isView, /* True if this is a VIEW */ - int isVirtual, /* True if this is a VIRTUAL table */ - int noErr /* Do nothing if table already exists */ -){ - Table *pTable; - char *zName = 0; /* The name of the new table */ - sqlite3 *db = pParse->db; - Vdbe *v; - int iDb; /* Database number to create the table in */ - Token *pName; /* Unqualified name of the table to create */ - - /* The table or view name to create is passed to this routine via tokens - ** pName1 and pName2. If the table name was fully qualified, for example: - ** - ** CREATE TABLE xxx.yyy (...); - ** - ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if - ** the table name is not fully qualified, i.e.: - ** - ** CREATE TABLE yyy(...); - ** - ** Then pName1 is set to "yyy" and pName2 is "". - ** - ** The call below sets the pName pointer to point at the token (pName1 or - ** pName2) that stores the unqualified table name. The variable iDb is - ** set to the index of the database that the table or view is to be - ** created in. - */ - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); - if( iDb<0 ) return; - if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){ - /* If creating a temp table, the name may not be qualified. Unless - ** the database name is "temp" anyway. */ - sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); - return; - } - if( !OMIT_TEMPDB && isTemp ) iDb = 1; - - pParse->sNameToken = *pName; - zName = sqlite3NameFromToken(db, pName); - if( zName==0 ) return; - if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ - goto begin_table_error; - } - if( db->init.iDb==1 ) isTemp = 1; -#ifndef SQLITE_OMIT_AUTHORIZATION - assert( (isTemp & 1)==isTemp ); - { - int code; - char *zDb = db->aDb[iDb].zName; - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ - goto begin_table_error; - } - if( isView ){ - if( !OMIT_TEMPDB && isTemp ){ - code = SQLITE_CREATE_TEMP_VIEW; - }else{ - code = SQLITE_CREATE_VIEW; - } - }else{ - if( !OMIT_TEMPDB && isTemp ){ - code = SQLITE_CREATE_TEMP_TABLE; - }else{ - code = SQLITE_CREATE_TABLE; - } - } - if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ - goto begin_table_error; - } - } -#endif - - /* Make sure the new table name does not collide with an existing - ** index or table name in the same database. Issue an error message if - ** it does. The exception is if the statement being parsed was passed - ** to an sqlite3_declare_vtab() call. In that case only the column names - ** and types will be used, so there is no need to test for namespace - ** collisions. - */ - if( !IN_DECLARE_VTAB ){ - char *zDb = db->aDb[iDb].zName; - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto begin_table_error; - } - pTable = sqlite3FindTable(db, zName, zDb); - if( pTable ){ - if( !noErr ){ - sqlite3ErrorMsg(pParse, "table %T already exists", pName); - }else{ - assert( !db->init.busy ); - sqlite3CodeVerifySchema(pParse, iDb); - } - goto begin_table_error; - } - if( sqlite3FindIndex(db, zName, zDb)!=0 ){ - sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); - goto begin_table_error; - } - } - - pTable = sqlite3DbMallocZero(db, sizeof(Table)); - if( pTable==0 ){ - db->mallocFailed = 1; - pParse->rc = SQLITE_NOMEM; - pParse->nErr++; - goto begin_table_error; - } - pTable->zName = zName; - pTable->iPKey = -1; - pTable->pSchema = db->aDb[iDb].pSchema; - pTable->nRef = 1; - pTable->nRowEst = 1000000; - assert( pParse->pNewTable==0 ); - pParse->pNewTable = pTable; - - /* If this is the magic sqlite_sequence table used by autoincrement, - ** then record a pointer to this table in the main database structure - ** so that INSERT can find the table easily. - */ -#ifndef SQLITE_OMIT_AUTOINCREMENT - if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pTable->pSchema->pSeqTab = pTable; - } -#endif - - /* Begin generating the code that will insert the table record into - ** the SQLITE_MASTER table. Note in particular that we must go ahead - ** and allocate the record number for the table entry now. Before any - ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause - ** indices to be created and the table record must come before the - ** indices. Hence, the record number for the table must be allocated - ** now. - */ - if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ - int j1; - int fileFormat; - int reg1, reg2, reg3; - sqlite3BeginWriteOperation(pParse, 0, iDb); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( isVirtual ){ - sqlite3VdbeAddOp0(v, OP_VBegin); - } -#endif - - /* If the file format and encoding in the database have not been set, - ** set them now. - */ - reg1 = pParse->regRowid = ++pParse->nMem; - reg2 = pParse->regRoot = ++pParse->nMem; - reg3 = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT); - sqlite3VdbeUsesBtree(v, iDb); - j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); - fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? - 1 : SQLITE_MAX_FILE_FORMAT; - sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3); - sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3); - sqlite3VdbeJumpHere(v, j1); - - /* This just creates a place-holder record in the sqlite_master table. - ** The record created does not contain anything yet. It will be replaced - ** by the real entry in code generated at sqlite3EndTable(). - ** - ** The rowid for the new entry is left in register pParse->regRowid. - ** The root page number of the new table is left in reg pParse->regRoot. - ** The rowid and root page number values are needed by the code that - ** sqlite3EndTable will generate. - */ -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) - if( isView || isVirtual ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2); - }else -#endif - { - sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2); - } - sqlite3OpenMasterTable(pParse, iDb); - sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); - sqlite3VdbeAddOp2(v, OP_Null, 0, reg3); - sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3VdbeAddOp0(v, OP_Close); - } - - /* Normal (non-error) return. */ - return; - - /* If an error occurs, we jump here */ -begin_table_error: - sqlite3DbFree(db, zName); - return; -} - -/* -** This macro is used to compare two strings in a case-insensitive manner. -** It is slightly faster than calling sqlite3StrICmp() directly, but -** produces larger code. -** -** WARNING: This macro is not compatible with the strcmp() family. It -** returns true if the two strings are equal, otherwise false. -*/ -#define STRICMP(x, y) (\ -sqlite3UpperToLower[*(unsigned char *)(x)]== \ -sqlite3UpperToLower[*(unsigned char *)(y)] \ -&& sqlite3StrICmp((x)+1,(y)+1)==0 ) - -/* -** Add a new column to the table currently being constructed. -** -** The parser calls this routine once for each column declaration -** in a CREATE TABLE statement. sqlite3StartTable() gets called -** first to get things going. Then this routine is called for each -** column. -*/ -SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName){ - Table *p; - int i; - char *z; - Column *pCol; - sqlite3 *db = pParse->db; - if( (p = pParse->pNewTable)==0 ) return; -#if SQLITE_MAX_COLUMN - if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); - return; - } -#endif - z = sqlite3NameFromToken(db, pName); - if( z==0 ) return; - for(i=0; inCol; i++){ - if( STRICMP(z, p->aCol[i].zName) ){ - sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); - sqlite3DbFree(db, z); - return; - } - } - if( (p->nCol & 0x7)==0 ){ - Column *aNew; - aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0])); - if( aNew==0 ){ - sqlite3DbFree(db, z); - return; - } - p->aCol = aNew; - } - pCol = &p->aCol[p->nCol]; - memset(pCol, 0, sizeof(p->aCol[0])); - pCol->zName = z; - - /* If there is no type specified, columns have the default affinity - ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will - ** be called next to set pCol->affinity correctly. - */ - pCol->affinity = SQLITE_AFF_NONE; - p->nCol++; -} - -/* -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. A "NOT NULL" constraint has -** been seen on a column. This routine sets the notNull flag on -** the column currently under construction. -*/ -SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ - Table *p; - p = pParse->pNewTable; - if( p==0 || NEVER(p->nCol<1) ) return; - p->aCol[p->nCol-1].notNull = (u8)onError; -} - -/* -** Scan the column type name zType (length nType) and return the -** associated affinity type. -** -** This routine does a case-independent search of zType for the -** substrings in the following table. If one of the substrings is -** found, the corresponding affinity is returned. If zType contains -** more than one of the substrings, entries toward the top of -** the table take priority. For example, if zType is 'BLOBINT', -** SQLITE_AFF_INTEGER is returned. -** -** Substring | Affinity -** -------------------------------- -** 'INT' | SQLITE_AFF_INTEGER -** 'CHAR' | SQLITE_AFF_TEXT -** 'CLOB' | SQLITE_AFF_TEXT -** 'TEXT' | SQLITE_AFF_TEXT -** 'BLOB' | SQLITE_AFF_NONE -** 'REAL' | SQLITE_AFF_REAL -** 'FLOA' | SQLITE_AFF_REAL -** 'DOUB' | SQLITE_AFF_REAL -** -** If none of the substrings in the above table are found, -** SQLITE_AFF_NUMERIC is returned. -*/ -SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){ - u32 h = 0; - char aff = SQLITE_AFF_NUMERIC; - - if( zIn ) while( zIn[0] ){ - h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; - zIn++; - if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ - aff = SQLITE_AFF_TEXT; - }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ - aff = SQLITE_AFF_TEXT; - }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ - aff = SQLITE_AFF_TEXT; - }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ - && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){ - aff = SQLITE_AFF_NONE; -#ifndef SQLITE_OMIT_FLOATING_POINT - }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ - && aff==SQLITE_AFF_NUMERIC ){ - aff = SQLITE_AFF_REAL; - }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */ - && aff==SQLITE_AFF_NUMERIC ){ - aff = SQLITE_AFF_REAL; - }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */ - && aff==SQLITE_AFF_NUMERIC ){ - aff = SQLITE_AFF_REAL; -#endif - }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ - aff = SQLITE_AFF_INTEGER; - break; - } - } - - return aff; -} - -/* -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. The pFirst token is the first -** token in the sequence of tokens that describe the type of the -** column currently under construction. pLast is the last token -** in the sequence. Use this information to construct a string -** that contains the typename of the column and store that string -** in zType. -*/ -SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){ - Table *p; - Column *pCol; - - p = pParse->pNewTable; - if( p==0 || NEVER(p->nCol<1) ) return; - pCol = &p->aCol[p->nCol-1]; - assert( pCol->zType==0 ); - pCol->zType = sqlite3NameFromToken(pParse->db, pType); - pCol->affinity = sqlite3AffinityType(pCol->zType); -} - -/* -** The expression is the default value for the most recently added column -** of the table currently under construction. -** -** Default value expressions must be constant. Raise an exception if this -** is not the case. -** -** This routine is called by the parser while in the middle of -** parsing a CREATE TABLE statement. -*/ -SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ - Table *p; - Column *pCol; - sqlite3 *db = pParse->db; - p = pParse->pNewTable; - if( p!=0 ){ - pCol = &(p->aCol[p->nCol-1]); - if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr) ){ - sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", - pCol->zName); - }else{ - /* A copy of pExpr is used instead of the original, as pExpr contains - ** tokens that point to volatile memory. The 'span' of the expression - ** is required by pragma table_info. - */ - sqlite3ExprDelete(db, pCol->pDflt); - pCol->pDflt = sqlite3ExprDup(db, pSpan->pExpr, EXPRDUP_REDUCE); - sqlite3DbFree(db, pCol->zDflt); - pCol->zDflt = sqlite3DbStrNDup(db, (char*)pSpan->zStart, - (int)(pSpan->zEnd - pSpan->zStart)); - } - } - sqlite3ExprDelete(db, pSpan->pExpr); -} - -/* -** Designate the PRIMARY KEY for the table. pList is a list of names -** of columns that form the primary key. If pList is NULL, then the -** most recently added column of the table is the primary key. -** -** A table can have at most one primary key. If the table already has -** a primary key (and this is the second primary key) then create an -** error. -** -** If the PRIMARY KEY is on a single column whose datatype is INTEGER, -** then we will try to use that column as the rowid. Set the Table.iPKey -** field of the table under construction to be the index of the -** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is -** no INTEGER PRIMARY KEY. -** -** If the key is not an INTEGER PRIMARY KEY, then create a unique -** index for the key. No index is created for INTEGER PRIMARY KEYs. -*/ -SQLITE_PRIVATE void sqlite3AddPrimaryKey( - Parse *pParse, /* Parsing context */ - ExprList *pList, /* List of field names to be indexed */ - int onError, /* What to do with a uniqueness conflict */ - int autoInc, /* True if the AUTOINCREMENT keyword is present */ - int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ -){ - Table *pTab = pParse->pNewTable; - char *zType = 0; - int iCol = -1, i; - if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; - if( pTab->tabFlags & TF_HasPrimaryKey ){ - sqlite3ErrorMsg(pParse, - "table \"%s\" has more than one primary key", pTab->zName); - goto primary_key_exit; - } - pTab->tabFlags |= TF_HasPrimaryKey; - if( pList==0 ){ - iCol = pTab->nCol - 1; - pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; - }else{ - for(i=0; inExpr; i++){ - for(iCol=0; iColnCol; iCol++){ - if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ - break; - } - } - if( iColnCol ){ - pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; - } - } - if( pList->nExpr>1 ) iCol = -1; - } - if( iCol>=0 && iColnCol ){ - zType = pTab->aCol[iCol].zType; - } - if( zType && sqlite3StrICmp(zType, "INTEGER")==0 - && sortOrder==SQLITE_SO_ASC ){ - pTab->iPKey = iCol; - pTab->keyConf = (u8)onError; - assert( autoInc==0 || autoInc==1 ); - pTab->tabFlags |= autoInc*TF_Autoincrement; - }else if( autoInc ){ -#ifndef SQLITE_OMIT_AUTOINCREMENT - sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " - "INTEGER PRIMARY KEY"); -#endif - }else{ - Index *p; - p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0); - if( p ){ - p->autoIndex = 2; - } - pList = 0; - } - -primary_key_exit: - sqlite3ExprListDelete(pParse->db, pList); - return; -} - -/* -** Add a new CHECK constraint to the table currently under construction. -*/ -SQLITE_PRIVATE void sqlite3AddCheckConstraint( - Parse *pParse, /* Parsing context */ - Expr *pCheckExpr /* The check expression */ -){ -#ifndef SQLITE_OMIT_CHECK - Table *pTab = pParse->pNewTable; - if( pTab && !IN_DECLARE_VTAB ){ - pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr); - if( pParse->constraintName.n ){ - sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1); - } - }else -#endif - { - sqlite3ExprDelete(pParse->db, pCheckExpr); - } -} - -/* -** Set the collation function of the most recently parsed table column -** to the CollSeq given. -*/ -SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){ - Table *p; - int i; - char *zColl; /* Dequoted name of collation sequence */ - sqlite3 *db; - - if( (p = pParse->pNewTable)==0 ) return; - i = p->nCol-1; - db = pParse->db; - zColl = sqlite3NameFromToken(db, pToken); - if( !zColl ) return; - - if( sqlite3LocateCollSeq(pParse, zColl) ){ - Index *pIdx; - p->aCol[i].zColl = zColl; - - /* If the column is declared as " PRIMARY KEY COLLATE ", - ** then an index may have been created on this column before the - ** collation type was added. Correct this if it is the case. - */ - for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->nColumn==1 ); - if( pIdx->aiColumn[0]==i ){ - pIdx->azColl[0] = p->aCol[i].zColl; - } - } - }else{ - sqlite3DbFree(db, zColl); - } -} - -/* -** This function returns the collation sequence for database native text -** encoding identified by the string zName, length nName. -** -** If the requested collation sequence is not available, or not available -** in the database native encoding, the collation factory is invoked to -** request it. If the collation factory does not supply such a sequence, -** and the sequence is available in another text encoding, then that is -** returned instead. -** -** If no versions of the requested collations sequence are available, or -** another error occurs, NULL is returned and an error message written into -** pParse. -** -** This routine is a wrapper around sqlite3FindCollSeq(). This routine -** invokes the collation factory if the named collation cannot be found -** and generates an error message. -** -** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq() -*/ -SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){ - sqlite3 *db = pParse->db; - u8 enc = ENC(db); - u8 initbusy = db->init.busy; - CollSeq *pColl; - - pColl = sqlite3FindCollSeq(db, enc, zName, initbusy); - if( !initbusy && (!pColl || !pColl->xCmp) ){ - pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName); - } - - return pColl; -} - - -/* -** Generate code that will increment the schema cookie. -** -** The schema cookie is used to determine when the schema for the -** database changes. After each schema change, the cookie value -** changes. When a process first reads the schema it records the -** cookie. Thereafter, whenever it goes to access the database, -** it checks the cookie to make sure the schema has not changed -** since it was last read. -** -** This plan is not completely bullet-proof. It is possible for -** the schema to change multiple times and for the cookie to be -** set back to prior value. But schema changes are infrequent -** and the probability of hitting the same cookie value is only -** 1 chance in 2^32. So we're safe enough. -*/ -SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ - int r1 = sqlite3GetTempReg(pParse); - sqlite3 *db = pParse->db; - Vdbe *v = pParse->pVdbe; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1); - sqlite3ReleaseTempReg(pParse, r1); -} - -/* -** Measure the number of characters needed to output the given -** identifier. The number returned includes any quotes used -** but does not include the null terminator. -** -** The estimate is conservative. It might be larger that what is -** really needed. -*/ -static int identLength(const char *z){ - int n; - for(n=0; *z; n++, z++){ - if( *z=='"' ){ n++; } - } - return n + 2; -} - -/* -** The first parameter is a pointer to an output buffer. The second -** parameter is a pointer to an integer that contains the offset at -** which to write into the output buffer. This function copies the -** nul-terminated string pointed to by the third parameter, zSignedIdent, -** to the specified offset in the buffer and updates *pIdx to refer -** to the first byte after the last byte written before returning. -** -** If the string zSignedIdent consists entirely of alpha-numeric -** characters, does not begin with a digit and is not an SQL keyword, -** then it is copied to the output buffer exactly as it is. Otherwise, -** it is quoted using double-quotes. -*/ -static void identPut(char *z, int *pIdx, char *zSignedIdent){ - unsigned char *zIdent = (unsigned char*)zSignedIdent; - int i, j, needQuote; - i = *pIdx; - - for(j=0; zIdent[j]; j++){ - if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break; - } - needQuote = sqlite3Isdigit(zIdent[0]) || sqlite3KeywordCode(zIdent, j)!=TK_ID; - if( !needQuote ){ - needQuote = zIdent[j]; - } - - if( needQuote ) z[i++] = '"'; - for(j=0; zIdent[j]; j++){ - z[i++] = zIdent[j]; - if( zIdent[j]=='"' ) z[i++] = '"'; - } - if( needQuote ) z[i++] = '"'; - z[i] = 0; - *pIdx = i; -} - -/* -** Generate a CREATE TABLE statement appropriate for the given -** table. Memory to hold the text of the statement is obtained -** from sqliteMalloc() and must be freed by the calling function. -*/ -static char *createTableStmt(sqlite3 *db, Table *p){ - int i, k, n; - char *zStmt; - char *zSep, *zSep2, *zEnd; - Column *pCol; - n = 0; - for(pCol = p->aCol, i=0; inCol; i++, pCol++){ - n += identLength(pCol->zName) + 5; - } - n += identLength(p->zName); - if( n<50 ){ - zSep = ""; - zSep2 = ","; - zEnd = ")"; - }else{ - zSep = "\n "; - zSep2 = ",\n "; - zEnd = "\n)"; - } - n += 35 + 6*p->nCol; - zStmt = sqlite3DbMallocRaw(0, n); - if( zStmt==0 ){ - db->mallocFailed = 1; - return 0; - } - sqlite3_snprintf(n, zStmt, "CREATE TABLE "); - k = sqlite3Strlen30(zStmt); - identPut(zStmt, &k, p->zName); - zStmt[k++] = '('; - for(pCol=p->aCol, i=0; inCol; i++, pCol++){ - static const char * const azType[] = { - /* SQLITE_AFF_TEXT */ " TEXT", - /* SQLITE_AFF_NONE */ "", - /* SQLITE_AFF_NUMERIC */ " NUM", - /* SQLITE_AFF_INTEGER */ " INT", - /* SQLITE_AFF_REAL */ " REAL" - }; - int len; - const char *zType; - - sqlite3_snprintf(n-k, &zStmt[k], zSep); - k += sqlite3Strlen30(&zStmt[k]); - zSep = zSep2; - identPut(zStmt, &k, pCol->zName); - assert( pCol->affinity-SQLITE_AFF_TEXT >= 0 ); - assert( pCol->affinity-SQLITE_AFF_TEXT < ArraySize(azType) ); - testcase( pCol->affinity==SQLITE_AFF_TEXT ); - testcase( pCol->affinity==SQLITE_AFF_NONE ); - testcase( pCol->affinity==SQLITE_AFF_NUMERIC ); - testcase( pCol->affinity==SQLITE_AFF_INTEGER ); - testcase( pCol->affinity==SQLITE_AFF_REAL ); - - zType = azType[pCol->affinity - SQLITE_AFF_TEXT]; - len = sqlite3Strlen30(zType); - assert( pCol->affinity==SQLITE_AFF_NONE - || pCol->affinity==sqlite3AffinityType(zType) ); - memcpy(&zStmt[k], zType, len); - k += len; - assert( k<=n ); - } - sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd); - return zStmt; -} - -/* -** This routine is called to report the final ")" that terminates -** a CREATE TABLE statement. -** -** The table structure that other action routines have been building -** is added to the internal hash tables, assuming no errors have -** occurred. -** -** An entry for the table is made in the master table on disk, unless -** this is a temporary table or db->init.busy==1. When db->init.busy==1 -** it means we are reading the sqlite_master table because we just -** connected to the database or because the sqlite_master table has -** recently changed, so the entry for this table already exists in -** the sqlite_master table. We do not want to create it again. -** -** If the pSelect argument is not NULL, it means that this routine -** was called to create a table generated from a -** "CREATE TABLE ... AS SELECT ..." statement. The column names of -** the new table will match the result set of the SELECT. -*/ -SQLITE_PRIVATE void sqlite3EndTable( - Parse *pParse, /* Parse context */ - Token *pCons, /* The ',' token after the last column defn. */ - Token *pEnd, /* The final ')' token in the CREATE TABLE */ - Select *pSelect /* Select from a "CREATE ... AS SELECT" */ -){ - Table *p; - sqlite3 *db = pParse->db; - int iDb; - - if( (pEnd==0 && pSelect==0) || db->mallocFailed ){ - return; - } - p = pParse->pNewTable; - if( p==0 ) return; - - assert( !db->init.busy || !pSelect ); - - iDb = sqlite3SchemaToIndex(db, p->pSchema); - -#ifndef SQLITE_OMIT_CHECK - /* Resolve names in all CHECK constraint expressions. - */ - if( p->pCheck ){ - SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ - NameContext sNC; /* Name context for pParse->pNewTable */ - ExprList *pList; /* List of all CHECK constraints */ - int i; /* Loop counter */ - - memset(&sNC, 0, sizeof(sNC)); - memset(&sSrc, 0, sizeof(sSrc)); - sSrc.nSrc = 1; - sSrc.a[0].zName = p->zName; - sSrc.a[0].pTab = p; - sSrc.a[0].iCursor = -1; - sNC.pParse = pParse; - sNC.pSrcList = &sSrc; - sNC.ncFlags = NC_IsCheck; - pList = p->pCheck; - for(i=0; inExpr; i++){ - if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){ - return; - } - } - } -#endif /* !defined(SQLITE_OMIT_CHECK) */ - - /* If the db->init.busy is 1 it means we are reading the SQL off the - ** "sqlite_master" or "sqlite_temp_master" table on the disk. - ** So do not write to the disk again. Extract the root page number - ** for the table from the db->init.newTnum field. (The page number - ** should have been put there by the sqliteOpenCb routine.) - */ - if( db->init.busy ){ - p->tnum = db->init.newTnum; - } - - /* If not initializing, then create a record for the new table - ** in the SQLITE_MASTER table of the database. - ** - ** If this is a TEMPORARY table, write the entry into the auxiliary - ** file instead of into the main database file. - */ - if( !db->init.busy ){ - int n; - Vdbe *v; - char *zType; /* "view" or "table" */ - char *zType2; /* "VIEW" or "TABLE" */ - char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */ - - v = sqlite3GetVdbe(pParse); - if( NEVER(v==0) ) return; - - sqlite3VdbeAddOp1(v, OP_Close, 0); - - /* - ** Initialize zType for the new view or table. - */ - if( p->pSelect==0 ){ - /* A regular table */ - zType = "table"; - zType2 = "TABLE"; -#ifndef SQLITE_OMIT_VIEW - }else{ - /* A view */ - zType = "view"; - zType2 = "VIEW"; -#endif - } - - /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT - ** statement to populate the new table. The root-page number for the - ** new table is in register pParse->regRoot. - ** - ** Once the SELECT has been coded by sqlite3Select(), it is in a - ** suitable state to query for the column names and types to be used - ** by the new table. - ** - ** A shared-cache write-lock is not required to write to the new table, - ** as a schema-lock must have already been obtained to create it. Since - ** a schema-lock excludes all other database users, the write-lock would - ** be redundant. - */ - if( pSelect ){ - SelectDest dest; - Table *pSelTab; - - assert(pParse->nTab==1); - sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); - sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); - pParse->nTab = 2; - sqlite3SelectDestInit(&dest, SRT_Table, 1); - sqlite3Select(pParse, pSelect, &dest); - sqlite3VdbeAddOp1(v, OP_Close, 1); - if( pParse->nErr==0 ){ - pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); - if( pSelTab==0 ) return; - assert( p->aCol==0 ); - p->nCol = pSelTab->nCol; - p->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqlite3DeleteTable(db, pSelTab); - } - } - - /* Compute the complete text of the CREATE statement */ - if( pSelect ){ - zStmt = createTableStmt(db, p); - }else{ - n = (int)(pEnd->z - pParse->sNameToken.z) + 1; - zStmt = sqlite3MPrintf(db, - "CREATE %s %.*s", zType2, n, pParse->sNameToken.z - ); - } - - /* A slot for the record has already been allocated in the - ** SQLITE_MASTER table. We just need to update that slot with all - ** the information we've collected. - */ - sqlite3NestedParse(pParse, - "UPDATE %Q.%s " - "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " - "WHERE rowid=#%d", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), - zType, - p->zName, - p->zName, - pParse->regRoot, - zStmt, - pParse->regRowid - ); - sqlite3DbFree(db, zStmt); - sqlite3ChangeCookie(pParse, iDb); - -#ifndef SQLITE_OMIT_AUTOINCREMENT - /* Check to see if we need to create an sqlite_sequence table for - ** keeping track of autoincrement keys. - */ - if( p->tabFlags & TF_Autoincrement ){ - Db *pDb = &db->aDb[iDb]; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( pDb->pSchema->pSeqTab==0 ){ - sqlite3NestedParse(pParse, - "CREATE TABLE %Q.sqlite_sequence(name,seq)", - pDb->zName - ); - } - } -#endif - - /* Reparse everything to update our internal data structures */ - sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "tbl_name='%q'", p->zName)); - } - - - /* Add the table to the in-memory representation of the database. - */ - if( db->init.busy ){ - Table *pOld; - Schema *pSchema = p->pSchema; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, - sqlite3Strlen30(p->zName),p); - if( pOld ){ - assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ - db->mallocFailed = 1; - return; - } - pParse->pNewTable = 0; - db->flags |= SQLITE_InternChanges; - -#ifndef SQLITE_OMIT_ALTERTABLE - if( !p->pSelect ){ - const char *zName = (const char *)pParse->sNameToken.z; - int nName; - assert( !pSelect && pCons && pEnd ); - if( pCons->z==0 ){ - pCons = pEnd; - } - nName = (int)((const char *)pCons->z - zName); - p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName); - } -#endif - } -} - -#ifndef SQLITE_OMIT_VIEW -/* -** The parser calls this routine in order to create a new VIEW -*/ -SQLITE_PRIVATE void sqlite3CreateView( - Parse *pParse, /* The parsing context */ - Token *pBegin, /* The CREATE token that begins the statement */ - Token *pName1, /* The token that holds the name of the view */ - Token *pName2, /* The token that holds the name of the view */ - Select *pSelect, /* A SELECT statement that will become the new view */ - int isTemp, /* TRUE for a TEMPORARY view */ - int noErr /* Suppress error messages if VIEW already exists */ -){ - Table *p; - int n; - const char *z; - Token sEnd; - DbFixer sFix; - Token *pName = 0; - int iDb; - sqlite3 *db = pParse->db; - - if( pParse->nVar>0 ){ - sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); - sqlite3SelectDelete(db, pSelect); - return; - } - sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); - p = pParse->pNewTable; - if( p==0 || pParse->nErr ){ - sqlite3SelectDelete(db, pSelect); - return; - } - sqlite3TwoPartName(pParse, pName1, pName2, &pName); - iDb = sqlite3SchemaToIndex(db, p->pSchema); - if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) - && sqlite3FixSelect(&sFix, pSelect) - ){ - sqlite3SelectDelete(db, pSelect); - return; - } - - /* Make a copy of the entire SELECT statement that defines the view. - ** This will force all the Expr.token.z values to be dynamically - ** allocated rather than point to the input string - which means that - ** they will persist after the current sqlite3_exec() call returns. - */ - p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - sqlite3SelectDelete(db, pSelect); - if( db->mallocFailed ){ - return; - } - if( !db->init.busy ){ - sqlite3ViewGetColumnNames(pParse, p); - } - - /* Locate the end of the CREATE VIEW statement. Make sEnd point to - ** the end. - */ - sEnd = pParse->sLastToken; - if( ALWAYS(sEnd.z[0]!=0) && sEnd.z[0]!=';' ){ - sEnd.z += sEnd.n; - } - sEnd.n = 0; - n = (int)(sEnd.z - pBegin->z); - z = pBegin->z; - while( ALWAYS(n>0) && sqlite3Isspace(z[n-1]) ){ n--; } - sEnd.z = &z[n-1]; - sEnd.n = 1; - - /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ - sqlite3EndTable(pParse, 0, &sEnd, 0); - return; -} -#endif /* SQLITE_OMIT_VIEW */ - -#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) -/* -** The Table structure pTable is really a VIEW. Fill in the names of -** the columns of the view in the pTable structure. Return the number -** of errors. If an error is seen leave an error message in pParse->zErrMsg. -*/ -SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ - Table *pSelTab; /* A fake table from which we get the result set */ - Select *pSel; /* Copy of the SELECT that implements the view */ - int nErr = 0; /* Number of errors encountered */ - int n; /* Temporarily holds the number of cursors assigned */ - sqlite3 *db = pParse->db; /* Database connection for malloc errors */ - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); - - assert( pTable ); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3VtabCallConnect(pParse, pTable) ){ - return SQLITE_ERROR; - } - if( IsVirtual(pTable) ) return 0; -#endif - -#ifndef SQLITE_OMIT_VIEW - /* A positive nCol means the columns names for this view are - ** already known. - */ - if( pTable->nCol>0 ) return 0; - - /* A negative nCol is a special marker meaning that we are currently - ** trying to compute the column names. If we enter this routine with - ** a negative nCol, it means two or more views form a loop, like this: - ** - ** CREATE VIEW one AS SELECT * FROM two; - ** CREATE VIEW two AS SELECT * FROM one; - ** - ** Actually, the error above is now caught prior to reaching this point. - ** But the following test is still important as it does come up - ** in the following: - ** - ** CREATE TABLE main.ex1(a); - ** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1; - ** SELECT * FROM temp.ex1; - */ - if( pTable->nCol<0 ){ - sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); - return 1; - } - assert( pTable->nCol>=0 ); - - /* If we get this far, it means we need to compute the table names. - ** Note that the call to sqlite3ResultSetOfSelect() will expand any - ** "*" elements in the results set of the view and will assign cursors - ** to the elements of the FROM clause. But we do not want these changes - ** to be permanent. So the computation is done on a copy of the SELECT - ** statement that defines the view. - */ - assert( pTable->pSelect ); - pSel = sqlite3SelectDup(db, pTable->pSelect, 0); - if( pSel ){ - u8 enableLookaside = db->lookaside.bEnabled; - n = pParse->nTab; - sqlite3SrcListAssignCursors(pParse, pSel->pSrc); - pTable->nCol = -1; - db->lookaside.bEnabled = 0; -#ifndef SQLITE_OMIT_AUTHORIZATION - xAuth = db->xAuth; - db->xAuth = 0; - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); - db->xAuth = xAuth; -#else - pSelTab = sqlite3ResultSetOfSelect(pParse, pSel); -#endif - db->lookaside.bEnabled = enableLookaside; - pParse->nTab = n; - if( pSelTab ){ - assert( pTable->aCol==0 ); - pTable->nCol = pSelTab->nCol; - pTable->aCol = pSelTab->aCol; - pSelTab->nCol = 0; - pSelTab->aCol = 0; - sqlite3DeleteTable(db, pSelTab); - assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) ); - pTable->pSchema->flags |= DB_UnresetViews; - }else{ - pTable->nCol = 0; - nErr++; - } - sqlite3SelectDelete(db, pSel); - } else { - nErr++; - } -#endif /* SQLITE_OMIT_VIEW */ - return nErr; -} -#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ - -#ifndef SQLITE_OMIT_VIEW -/* -** Clear the column names from every VIEW in database idx. -*/ -static void sqliteViewResetAll(sqlite3 *db, int idx){ - HashElem *i; - assert( sqlite3SchemaMutexHeld(db, idx, 0) ); - if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; - for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ - Table *pTab = sqliteHashData(i); - if( pTab->pSelect ){ - sqliteDeleteColumnNames(db, pTab); - pTab->aCol = 0; - pTab->nCol = 0; - } - } - DbClearProperty(db, idx, DB_UnresetViews); -} -#else -# define sqliteViewResetAll(A,B) -#endif /* SQLITE_OMIT_VIEW */ - -/* -** This function is called by the VDBE to adjust the internal schema -** used by SQLite when the btree layer moves a table root page. The -** root-page of a table or index in database iDb has changed from iFrom -** to iTo. -** -** Ticket #1728: The symbol table might still contain information -** on tables and/or indices that are the process of being deleted. -** If you are unlucky, one of those deleted indices or tables might -** have the same rootpage number as the real table or index that is -** being moved. So we cannot stop searching after the first match -** because the first match might be for one of the deleted indices -** or tables and not the table/index that is actually being moved. -** We must continue looping until all tables and indices with -** rootpage==iFrom have been converted to have a rootpage of iTo -** in order to be certain that we got the right one. -*/ -#ifndef SQLITE_OMIT_AUTOVACUUM -SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){ - HashElem *pElem; - Hash *pHash; - Db *pDb; - - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pDb = &db->aDb[iDb]; - pHash = &pDb->pSchema->tblHash; - for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ - Table *pTab = sqliteHashData(pElem); - if( pTab->tnum==iFrom ){ - pTab->tnum = iTo; - } - } - pHash = &pDb->pSchema->idxHash; - for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ - Index *pIdx = sqliteHashData(pElem); - if( pIdx->tnum==iFrom ){ - pIdx->tnum = iTo; - } - } -} -#endif - -/* -** Write code to erase the table with root-page iTable from database iDb. -** Also write code to modify the sqlite_master table and internal schema -** if a root-page of another table is moved by the btree-layer whilst -** erasing iTable (this can happen with an auto-vacuum database). -*/ -static void destroyRootPage(Parse *pParse, int iTable, int iDb){ - Vdbe *v = sqlite3GetVdbe(pParse); - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); - sqlite3MayAbort(pParse); -#ifndef SQLITE_OMIT_AUTOVACUUM - /* OP_Destroy stores an in integer r1. If this integer - ** is non-zero, then it is the root page number of a table moved to - ** location iTable. The following code modifies the sqlite_master table to - ** reflect this. - ** - ** The "#NNN" in the SQL is a special constant that means whatever value - ** is in register NNN. See grammar rules associated with the TK_REGISTER - ** token for additional information. - */ - sqlite3NestedParse(pParse, - "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d", - pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1); -#endif - sqlite3ReleaseTempReg(pParse, r1); -} - -/* -** Write VDBE code to erase table pTab and all associated indices on disk. -** Code to update the sqlite_master tables and internal schema definitions -** in case a root-page belonging to another table is moved by the btree layer -** is also added (this can happen with an auto-vacuum database). -*/ -static void destroyTable(Parse *pParse, Table *pTab){ -#ifdef SQLITE_OMIT_AUTOVACUUM - Index *pIdx; - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - destroyRootPage(pParse, pTab->tnum, iDb); - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - destroyRootPage(pParse, pIdx->tnum, iDb); - } -#else - /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM - ** is not defined), then it is important to call OP_Destroy on the - ** table and index root-pages in order, starting with the numerically - ** largest root-page number. This guarantees that none of the root-pages - ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the - ** following were coded: - ** - ** OP_Destroy 4 0 - ** ... - ** OP_Destroy 5 0 - ** - ** and root page 5 happened to be the largest root-page number in the - ** database, then root page 5 would be moved to page 4 by the - ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit - ** a free-list page. - */ - int iTab = pTab->tnum; - int iDestroyed = 0; - - while( 1 ){ - Index *pIdx; - int iLargest = 0; - - if( iDestroyed==0 || iTabpIndex; pIdx; pIdx=pIdx->pNext){ - int iIdx = pIdx->tnum; - assert( pIdx->pSchema==pTab->pSchema ); - if( (iDestroyed==0 || (iIdxiLargest ){ - iLargest = iIdx; - } - } - if( iLargest==0 ){ - return; - }else{ - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - assert( iDb>=0 && iDbdb->nDb ); - destroyRootPage(pParse, iLargest, iDb); - iDestroyed = iLargest; - } - } -#endif -} - -/* -** Remove entries from the sqlite_statN tables (for N in (1,2,3)) -** after a DROP INDEX or DROP TABLE command. -*/ -static void sqlite3ClearStatTables( - Parse *pParse, /* The parsing context */ - int iDb, /* The database number */ - const char *zType, /* "idx" or "tbl" */ - const char *zName /* Name of index or table */ -){ - int i; - const char *zDbName = pParse->db->aDb[iDb].zName; - for(i=1; i<=3; i++){ - char zTab[24]; - sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i); - if( sqlite3FindTable(pParse->db, zTab, zDbName) ){ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.%s WHERE %s=%Q", - zDbName, zTab, zType, zName - ); - } - } -} - -/* -** Generate code to drop a table. -*/ -SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){ - Vdbe *v; - sqlite3 *db = pParse->db; - Trigger *pTrigger; - Db *pDb = &db->aDb[iDb]; - - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); - sqlite3BeginWriteOperation(pParse, 1, iDb); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - sqlite3VdbeAddOp0(v, OP_VBegin); - } -#endif - - /* Drop all triggers associated with the table being dropped. Code - ** is generated to remove entries from sqlite_master and/or - ** sqlite_temp_master if required. - */ - pTrigger = sqlite3TriggerList(pParse, pTab); - while( pTrigger ){ - assert( pTrigger->pSchema==pTab->pSchema || - pTrigger->pSchema==db->aDb[1].pSchema ); - sqlite3DropTriggerPtr(pParse, pTrigger); - pTrigger = pTrigger->pNext; - } - -#ifndef SQLITE_OMIT_AUTOINCREMENT - /* Remove any entries of the sqlite_sequence table associated with - ** the table being dropped. This is done before the table is dropped - ** at the btree level, in case the sqlite_sequence table needs to - ** move as a result of the drop (can happen in auto-vacuum mode). - */ - if( pTab->tabFlags & TF_Autoincrement ){ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.sqlite_sequence WHERE name=%Q", - pDb->zName, pTab->zName - ); - } -#endif - - /* Drop all SQLITE_MASTER table and index entries that refer to the - ** table. The program name loops through the master table and deletes - ** every row that refers to a table of the same name as the one being - ** dropped. Triggers are handled separately because a trigger can be - ** created in the temp database that refers to a table in another - ** database. - */ - sqlite3NestedParse(pParse, - "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", - pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); - if( !isView && !IsVirtual(pTab) ){ - destroyTable(pParse, pTab); - } - - /* Remove the table entry from SQLite's internal schema and modify - ** the schema cookie. - */ - if( IsVirtual(pTab) ){ - sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0); - } - sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); - sqlite3ChangeCookie(pParse, iDb); - sqliteViewResetAll(db, iDb); -} - -/* -** This routine is called to do the work of a DROP TABLE statement. -** pName is the name of the table to be dropped. -*/ -SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ - Table *pTab; - Vdbe *v; - sqlite3 *db = pParse->db; - int iDb; - - if( db->mallocFailed ){ - goto exit_drop_table; - } - assert( pParse->nErr==0 ); - assert( pName->nSrc==1 ); - if( noErr ) db->suppressErr++; - pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); - if( noErr ) db->suppressErr--; - - if( pTab==0 ){ - if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); - goto exit_drop_table; - } - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=0 && iDbnDb ); - - /* If pTab is a virtual table, call ViewGetColumnNames() to ensure - ** it is initialized. - */ - if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto exit_drop_table; - } -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int code; - const char *zTab = SCHEMA_TABLE(iDb); - const char *zDb = db->aDb[iDb].zName; - const char *zArg2 = 0; - if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ - goto exit_drop_table; - } - if( isView ){ - if( !OMIT_TEMPDB && iDb==1 ){ - code = SQLITE_DROP_TEMP_VIEW; - }else{ - code = SQLITE_DROP_VIEW; - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - }else if( IsVirtual(pTab) ){ - code = SQLITE_DROP_VTABLE; - zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName; -#endif - }else{ - if( !OMIT_TEMPDB && iDb==1 ){ - code = SQLITE_DROP_TEMP_TABLE; - }else{ - code = SQLITE_DROP_TABLE; - } - } - if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){ - goto exit_drop_table; - } - if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ - goto exit_drop_table; - } - } -#endif - if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 - && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){ - sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); - goto exit_drop_table; - } - -#ifndef SQLITE_OMIT_VIEW - /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used - ** on a table. - */ - if( isView && pTab->pSelect==0 ){ - sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); - goto exit_drop_table; - } - if( !isView && pTab->pSelect ){ - sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); - goto exit_drop_table; - } -#endif - - /* Generate code to remove the table from the master table - ** on disk. - */ - v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3BeginWriteOperation(pParse, 1, iDb); - sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); - sqlite3FkDropTable(pParse, pName, pTab); - sqlite3CodeDropTable(pParse, pTab, iDb, isView); - } - -exit_drop_table: - sqlite3SrcListDelete(db, pName); -} - -/* -** This routine is called to create a new foreign key on the table -** currently under construction. pFromCol determines which columns -** in the current table point to the foreign key. If pFromCol==0 then -** connect the key to the last column inserted. pTo is the name of -** the table referred to. pToCol is a list of tables in the other -** pTo table that the foreign key points to. flags contains all -** information about the conflict resolution algorithms specified -** in the ON DELETE, ON UPDATE and ON INSERT clauses. -** -** An FKey structure is created and added to the table currently -** under construction in the pParse->pNewTable field. -** -** The foreign key is set for IMMEDIATE processing. A subsequent call -** to sqlite3DeferForeignKey() might change this to DEFERRED. -*/ -SQLITE_PRIVATE void sqlite3CreateForeignKey( - Parse *pParse, /* Parsing context */ - ExprList *pFromCol, /* Columns in this table that point to other table */ - Token *pTo, /* Name of the other table */ - ExprList *pToCol, /* Columns in the other table */ - int flags /* Conflict resolution algorithms. */ -){ - sqlite3 *db = pParse->db; -#ifndef SQLITE_OMIT_FOREIGN_KEY - FKey *pFKey = 0; - FKey *pNextTo; - Table *p = pParse->pNewTable; - int nByte; - int i; - int nCol; - char *z; - - assert( pTo!=0 ); - if( p==0 || IN_DECLARE_VTAB ) goto fk_end; - if( pFromCol==0 ){ - int iCol = p->nCol-1; - if( NEVER(iCol<0) ) goto fk_end; - if( pToCol && pToCol->nExpr!=1 ){ - sqlite3ErrorMsg(pParse, "foreign key on %s" - " should reference only one column of table %T", - p->aCol[iCol].zName, pTo); - goto fk_end; - } - nCol = 1; - }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){ - sqlite3ErrorMsg(pParse, - "number of columns in foreign key does not match the number of " - "columns in the referenced table"); - goto fk_end; - }else{ - nCol = pFromCol->nExpr; - } - nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1; - if( pToCol ){ - for(i=0; inExpr; i++){ - nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1; - } - } - pFKey = sqlite3DbMallocZero(db, nByte ); - if( pFKey==0 ){ - goto fk_end; - } - pFKey->pFrom = p; - pFKey->pNextFrom = p->pFKey; - z = (char*)&pFKey->aCol[nCol]; - pFKey->zTo = z; - memcpy(z, pTo->z, pTo->n); - z[pTo->n] = 0; - sqlite3Dequote(z); - z += pTo->n+1; - pFKey->nCol = nCol; - if( pFromCol==0 ){ - pFKey->aCol[0].iFrom = p->nCol-1; - }else{ - for(i=0; inCol; j++){ - if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){ - pFKey->aCol[i].iFrom = j; - break; - } - } - if( j>=p->nCol ){ - sqlite3ErrorMsg(pParse, - "unknown column \"%s\" in foreign key definition", - pFromCol->a[i].zName); - goto fk_end; - } - } - } - if( pToCol ){ - for(i=0; ia[i].zName); - pFKey->aCol[i].zCol = z; - memcpy(z, pToCol->a[i].zName, n); - z[n] = 0; - z += n+1; - } - } - pFKey->isDeferred = 0; - pFKey->aAction[0] = (u8)(flags & 0xff); /* ON DELETE action */ - pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */ - - assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); - pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, - pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey - ); - if( pNextTo==pFKey ){ - db->mallocFailed = 1; - goto fk_end; - } - if( pNextTo ){ - assert( pNextTo->pPrevTo==0 ); - pFKey->pNextTo = pNextTo; - pNextTo->pPrevTo = pFKey; - } - - /* Link the foreign key to the table as the last step. - */ - p->pFKey = pFKey; - pFKey = 0; - -fk_end: - sqlite3DbFree(db, pFKey); -#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ - sqlite3ExprListDelete(db, pFromCol); - sqlite3ExprListDelete(db, pToCol); -} - -/* -** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED -** clause is seen as part of a foreign key definition. The isDeferred -** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. -** The behavior of the most recently created foreign key is adjusted -** accordingly. -*/ -SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ -#ifndef SQLITE_OMIT_FOREIGN_KEY - Table *pTab; - FKey *pFKey; - if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; - assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */ - pFKey->isDeferred = (u8)isDeferred; -#endif -} - -/* -** Generate code that will erase and refill index *pIdx. This is -** used to initialize a newly created index or to recompute the -** content of an index in response to a REINDEX command. -** -** if memRootPage is not negative, it means that the index is newly -** created. The register specified by memRootPage contains the -** root page number of the index. If memRootPage is negative, then -** the index already exists and must be cleared before being refilled and -** the root page number of the index is taken from pIndex->tnum. -*/ -static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ - Table *pTab = pIndex->pTable; /* The table that is indexed */ - int iTab = pParse->nTab++; /* Btree cursor used for pTab */ - int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */ - int iSorter; /* Cursor opened by OpenSorter (if in use) */ - int addr1; /* Address of top of loop */ - int addr2; /* Address to jump to for next iteration */ - int tnum; /* Root page of index */ - Vdbe *v; /* Generate code into this virtual machine */ - KeyInfo *pKey; /* KeyInfo for index */ - int regRecord; /* Register holding assemblied index record */ - sqlite3 *db = pParse->db; /* The database connection */ - int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); - -#ifndef SQLITE_OMIT_AUTHORIZATION - if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, - db->aDb[iDb].zName ) ){ - return; - } -#endif - - /* Require a write-lock on the table to perform this operation */ - sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); - - v = sqlite3GetVdbe(pParse); - if( v==0 ) return; - if( memRootPage>=0 ){ - tnum = memRootPage; - }else{ - tnum = pIndex->tnum; - sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); - } - pKey = sqlite3IndexKeyinfo(pParse, pIndex); - sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, - (char *)pKey, P4_KEYINFO_HANDOFF); - sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); - - /* Open the sorter cursor if we are to use one. */ - iSorter = pParse->nTab++; - sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO); - - /* Open the table. Loop through all rows of the table, inserting index - ** records into the sorter. */ - sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); - regRecord = sqlite3GetTempReg(pParse); - - sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1); - sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); - sqlite3VdbeJumpHere(v, addr1); - addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); - if( pIndex->onError!=OE_None ){ - int j2 = sqlite3VdbeCurrentAddr(v) + 3; - sqlite3VdbeAddOp2(v, OP_Goto, 0, j2); - addr2 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord); - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE, - OE_Abort, "indexed columns are not unique", P4_STATIC - ); - }else{ - addr2 = sqlite3VdbeCurrentAddr(v); - } - sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord); - sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); - sqlite3VdbeJumpHere(v, addr1); - - sqlite3VdbeAddOp1(v, OP_Close, iTab); - sqlite3VdbeAddOp1(v, OP_Close, iIdx); - sqlite3VdbeAddOp1(v, OP_Close, iSorter); -} - -/* -** Create a new index for an SQL table. pName1.pName2 is the name of the index -** and pTblList is the name of the table that is to be indexed. Both will -** be NULL for a primary key or an index that is created to satisfy a -** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable -** as the table to be indexed. pParse->pNewTable is a table that is -** currently being constructed by a CREATE TABLE statement. -** -** pList is a list of columns to be indexed. pList will be NULL if this -** is a primary key or unique-constraint on the most recent column added -** to the table currently under construction. -** -** If the index is created successfully, return a pointer to the new Index -** structure. This is used by sqlite3AddPrimaryKey() to mark the index -** as the tables primary key (Index.autoIndex==2). -*/ -SQLITE_PRIVATE Index *sqlite3CreateIndex( - Parse *pParse, /* All information about this parse */ - Token *pName1, /* First part of index name. May be NULL */ - Token *pName2, /* Second part of index name. May be NULL */ - SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */ - ExprList *pList, /* A list of columns to be indexed */ - int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ - Token *pStart, /* The CREATE token that begins this statement */ - Token *pEnd, /* The ")" that closes the CREATE INDEX statement */ - int sortOrder, /* Sort order of primary key when pList==NULL */ - int ifNotExist /* Omit error if index already exists */ -){ - Index *pRet = 0; /* Pointer to return */ - Table *pTab = 0; /* Table to be indexed */ - Index *pIndex = 0; /* The index to be created */ - char *zName = 0; /* Name of the index */ - int nName; /* Number of characters in zName */ - int i, j; - Token nullId; /* Fake token for an empty ID list */ - DbFixer sFix; /* For assigning database names to pTable */ - int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ - sqlite3 *db = pParse->db; - Db *pDb; /* The specific table containing the indexed database */ - int iDb; /* Index of the database that is being written */ - Token *pName = 0; /* Unqualified name of the index to create */ - struct ExprList_item *pListItem; /* For looping over pList */ - int nCol; - int nExtra = 0; - char *zExtra; - - assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */ - assert( pParse->nErr==0 ); /* Never called with prior errors */ - if( db->mallocFailed || IN_DECLARE_VTAB ){ - goto exit_create_index; - } - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto exit_create_index; - } - - /* - ** Find the table that is to be indexed. Return early if not found. - */ - if( pTblName!=0 ){ - - /* Use the two-part index name to determine the database - ** to search for the table. 'Fix' the table name to this db - ** before looking up the table. - */ - assert( pName1 && pName2 ); - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); - if( iDb<0 ) goto exit_create_index; - assert( pName && pName->z ); - -#ifndef SQLITE_OMIT_TEMPDB - /* If the index name was unqualified, check if the table - ** is a temp table. If so, set the database to 1. Do not do this - ** if initialising a database schema. - */ - if( !db->init.busy ){ - pTab = sqlite3SrcListLookup(pParse, pTblName); - if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ - iDb = 1; - } - } -#endif - - if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) && - sqlite3FixSrcList(&sFix, pTblName) - ){ - /* Because the parser constructs pTblName from a single identifier, - ** sqlite3FixSrcList can never fail. */ - assert(0); - } - pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]); - assert( db->mallocFailed==0 || pTab==0 ); - if( pTab==0 ) goto exit_create_index; - assert( db->aDb[iDb].pSchema==pTab->pSchema ); - }else{ - assert( pName==0 ); - assert( pStart==0 ); - pTab = pParse->pNewTable; - if( !pTab ) goto exit_create_index; - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - } - pDb = &db->aDb[iDb]; - - assert( pTab!=0 ); - assert( pParse->nErr==0 ); - if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 - && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){ - sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); - goto exit_create_index; - } -#ifndef SQLITE_OMIT_VIEW - if( pTab->pSelect ){ - sqlite3ErrorMsg(pParse, "views may not be indexed"); - goto exit_create_index; - } -#endif -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "virtual tables may not be indexed"); - goto exit_create_index; - } -#endif - - /* - ** Find the name of the index. Make sure there is not already another - ** index or table with the same name. - ** - ** Exception: If we are reading the names of permanent indices from the - ** sqlite_master table (because some other process changed the schema) and - ** one of the index names collides with the name of a temporary table or - ** index, then we will continue to process this index. - ** - ** If pName==0 it means that we are - ** dealing with a primary key or UNIQUE constraint. We have to invent our - ** own name. - */ - if( pName ){ - zName = sqlite3NameFromToken(db, pName); - if( zName==0 ) goto exit_create_index; - assert( pName->z!=0 ); - if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ - goto exit_create_index; - } - if( !db->init.busy ){ - if( sqlite3FindTable(db, zName, 0)!=0 ){ - sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); - goto exit_create_index; - } - } - if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ - if( !ifNotExist ){ - sqlite3ErrorMsg(pParse, "index %s already exists", zName); - }else{ - assert( !db->init.busy ); - sqlite3CodeVerifySchema(pParse, iDb); - } - goto exit_create_index; - } - }else{ - int n; - Index *pLoop; - for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} - zName = sqlite3MPrintf(db, "sqlite_autoindex_%s_%d", pTab->zName, n); - if( zName==0 ){ - goto exit_create_index; - } - } - - /* Check for authorization to create an index. - */ -#ifndef SQLITE_OMIT_AUTHORIZATION - { - const char *zDb = pDb->zName; - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ - goto exit_create_index; - } - i = SQLITE_CREATE_INDEX; - if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX; - if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){ - goto exit_create_index; - } - } -#endif - - /* If pList==0, it means this routine was called to make a primary - ** key out of the last column added to the table under construction. - ** So create a fake list to simulate this. - */ - if( pList==0 ){ - nullId.z = pTab->aCol[pTab->nCol-1].zName; - nullId.n = sqlite3Strlen30((char*)nullId.z); - pList = sqlite3ExprListAppend(pParse, 0, 0); - if( pList==0 ) goto exit_create_index; - sqlite3ExprListSetName(pParse, pList, &nullId, 0); - pList->a[0].sortOrder = (u8)sortOrder; - } - - /* Figure out how many bytes of space are required to store explicitly - ** specified collation sequence names. - */ - for(i=0; inExpr; i++){ - Expr *pExpr = pList->a[i].pExpr; - if( pExpr ){ - assert( pExpr->op==TK_COLLATE ); - nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken)); - } - } - - /* - ** Allocate the index structure. - */ - nName = sqlite3Strlen30(zName); - nCol = pList->nExpr; - pIndex = sqlite3DbMallocZero(db, - ROUND8(sizeof(Index)) + /* Index structure */ - ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */ - sizeof(char *)*nCol + /* Index.azColl */ - sizeof(int)*nCol + /* Index.aiColumn */ - sizeof(u8)*nCol + /* Index.aSortOrder */ - nName + 1 + /* Index.zName */ - nExtra /* Collation sequence names */ - ); - if( db->mallocFailed ){ - goto exit_create_index; - } - zExtra = (char*)pIndex; - pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))]; - pIndex->azColl = (char**) - ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1)); - assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) ); - assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) ); - pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); - pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]); - pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); - zExtra = (char *)(&pIndex->zName[nName+1]); - memcpy(pIndex->zName, zName, nName+1); - pIndex->pTable = pTab; - pIndex->nColumn = pList->nExpr; - pIndex->onError = (u8)onError; - pIndex->autoIndex = (u8)(pName==0); - pIndex->pSchema = db->aDb[iDb].pSchema; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - - /* Check to see if we should honor DESC requests on index columns - */ - if( pDb->pSchema->file_format>=4 ){ - sortOrderMask = -1; /* Honor DESC */ - }else{ - sortOrderMask = 0; /* Ignore DESC */ - } - - /* Scan the names of the columns of the table to be indexed and - ** load the column indices into the Index structure. Report an error - ** if any column is not found. - ** - ** TODO: Add a test to make sure that the same column is not named - ** more than once within the same index. Only the first instance of - ** the column will ever be used by the optimizer. Note that using the - ** same column more than once cannot be an error because that would - ** break backwards compatibility - it needs to be a warning. - */ - for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ - const char *zColName = pListItem->zName; - Column *pTabCol; - int requestedSortOrder; - char *zColl; /* Collation sequence name */ - - for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ - if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; - } - if( j>=pTab->nCol ){ - sqlite3ErrorMsg(pParse, "table %s has no column named %s", - pTab->zName, zColName); - pParse->checkSchema = 1; - goto exit_create_index; - } - pIndex->aiColumn[i] = j; - if( pListItem->pExpr ){ - int nColl; - assert( pListItem->pExpr->op==TK_COLLATE ); - zColl = pListItem->pExpr->u.zToken; - nColl = sqlite3Strlen30(zColl) + 1; - assert( nExtra>=nColl ); - memcpy(zExtra, zColl, nColl); - zColl = zExtra; - zExtra += nColl; - nExtra -= nColl; - }else{ - zColl = pTab->aCol[j].zColl; - if( !zColl ) zColl = "BINARY"; - } - if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){ - goto exit_create_index; - } - pIndex->azColl[i] = zColl; - requestedSortOrder = pListItem->sortOrder & sortOrderMask; - pIndex->aSortOrder[i] = (u8)requestedSortOrder; - } - sqlite3DefaultRowEst(pIndex); - - if( pTab==pParse->pNewTable ){ - /* This routine has been called to create an automatic index as a - ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or - ** a PRIMARY KEY or UNIQUE clause following the column definitions. - ** i.e. one of: - ** - ** CREATE TABLE t(x PRIMARY KEY, y); - ** CREATE TABLE t(x, y, UNIQUE(x, y)); - ** - ** Either way, check to see if the table already has such an index. If - ** so, don't bother creating this one. This only applies to - ** automatically created indices. Users can do as they wish with - ** explicit indices. - ** - ** Two UNIQUE or PRIMARY KEY constraints are considered equivalent - ** (and thus suppressing the second one) even if they have different - ** sort orders. - ** - ** If there are different collating sequences or if the columns of - ** the constraint occur in different orders, then the constraints are - ** considered distinct and both result in separate indices. - */ - Index *pIdx; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - int k; - assert( pIdx->onError!=OE_None ); - assert( pIdx->autoIndex ); - assert( pIndex->onError!=OE_None ); - - if( pIdx->nColumn!=pIndex->nColumn ) continue; - for(k=0; knColumn; k++){ - const char *z1; - const char *z2; - if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; - z1 = pIdx->azColl[k]; - z2 = pIndex->azColl[k]; - if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break; - } - if( k==pIdx->nColumn ){ - if( pIdx->onError!=pIndex->onError ){ - /* This constraint creates the same index as a previous - ** constraint specified somewhere in the CREATE TABLE statement. - ** However the ON CONFLICT clauses are different. If both this - ** constraint and the previous equivalent constraint have explicit - ** ON CONFLICT clauses this is an error. Otherwise, use the - ** explicitly specified behavior for the index. - */ - if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){ - sqlite3ErrorMsg(pParse, - "conflicting ON CONFLICT clauses specified", 0); - } - if( pIdx->onError==OE_Default ){ - pIdx->onError = pIndex->onError; - } - } - goto exit_create_index; - } - } - } - - /* Link the new Index structure to its table and to the other - ** in-memory database structures. - */ - if( db->init.busy ){ - Index *p; - assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); - p = sqlite3HashInsert(&pIndex->pSchema->idxHash, - pIndex->zName, sqlite3Strlen30(pIndex->zName), - pIndex); - if( p ){ - assert( p==pIndex ); /* Malloc must have failed */ - db->mallocFailed = 1; - goto exit_create_index; - } - db->flags |= SQLITE_InternChanges; - if( pTblName!=0 ){ - pIndex->tnum = db->init.newTnum; - } - } - - /* If the db->init.busy is 0 then create the index on disk. This - ** involves writing the index into the master table and filling in the - ** index with the current table contents. - ** - ** The db->init.busy is 0 when the user first enters a CREATE INDEX - ** command. db->init.busy is 1 when a database is opened and - ** CREATE INDEX statements are read out of the master table. In - ** the latter case the index already exists on disk, which is why - ** we don't want to recreate it. - ** - ** If pTblName==0 it means this index is generated as a primary key - ** or UNIQUE constraint of a CREATE TABLE statement. Since the table - ** has just been created, it contains no data and the index initialization - ** step can be skipped. - */ - else{ /* if( db->init.busy==0 ) */ - Vdbe *v; - char *zStmt; - int iMem = ++pParse->nMem; - - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto exit_create_index; - - - /* Create the rootpage for the index - */ - sqlite3BeginWriteOperation(pParse, 1, iDb); - sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem); - - /* Gather the complete text of the CREATE INDEX statement into - ** the zStmt variable - */ - if( pStart ){ - assert( pEnd!=0 ); - /* A named index with an explicit CREATE INDEX statement */ - zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", - onError==OE_None ? "" : " UNIQUE", - (int)(pEnd->z - pName->z) + 1, - pName->z); - }else{ - /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ - /* zStmt = sqlite3MPrintf(""); */ - zStmt = 0; - } - - /* Add an entry in sqlite_master for this index - */ - sqlite3NestedParse(pParse, - "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), - pIndex->zName, - pTab->zName, - iMem, - zStmt - ); - sqlite3DbFree(db, zStmt); - - /* Fill the index with data and reparse the schema. Code an OP_Expire - ** to invalidate all pre-compiled statements. - */ - if( pTblName ){ - sqlite3RefillIndex(pParse, pIndex, iMem); - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); - sqlite3VdbeAddOp1(v, OP_Expire, 0); - } - } - - /* When adding an index to the list of indices for a table, make - ** sure all indices labeled OE_Replace come after all those labeled - ** OE_Ignore. This is necessary for the correct constraint check - ** processing (in sqlite3GenerateConstraintChecks()) as part of - ** UPDATE and INSERT statements. - */ - if( db->init.busy || pTblName==0 ){ - if( onError!=OE_Replace || pTab->pIndex==0 - || pTab->pIndex->onError==OE_Replace){ - pIndex->pNext = pTab->pIndex; - pTab->pIndex = pIndex; - }else{ - Index *pOther = pTab->pIndex; - while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ - pOther = pOther->pNext; - } - pIndex->pNext = pOther->pNext; - pOther->pNext = pIndex; - } - pRet = pIndex; - pIndex = 0; - } - - /* Clean up before exiting */ -exit_create_index: - if( pIndex ){ - sqlite3DbFree(db, pIndex->zColAff); - sqlite3DbFree(db, pIndex); - } - sqlite3ExprListDelete(db, pList); - sqlite3SrcListDelete(db, pTblName); - sqlite3DbFree(db, zName); - return pRet; -} - -/* -** Fill the Index.aiRowEst[] array with default information - information -** to be used when we have not run the ANALYZE command. -** -** aiRowEst[0] is suppose to contain the number of elements in the index. -** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the -** number of rows in the table that match any particular value of the -** first column of the index. aiRowEst[2] is an estimate of the number -** of rows that match any particular combiniation of the first 2 columns -** of the index. And so forth. It must always be the case that -* -** aiRowEst[N]<=aiRowEst[N-1] -** aiRowEst[N]>=1 -** -** Apart from that, we have little to go on besides intuition as to -** how aiRowEst[] should be initialized. The numbers generated here -** are based on typical values found in actual indices. -*/ -SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){ - tRowcnt *a = pIdx->aiRowEst; - int i; - tRowcnt n; - assert( a!=0 ); - a[0] = pIdx->pTable->nRowEst; - if( a[0]<10 ) a[0] = 10; - n = 10; - for(i=1; i<=pIdx->nColumn; i++){ - a[i] = n; - if( n>5 ) n--; - } - if( pIdx->onError!=OE_None ){ - a[pIdx->nColumn] = 1; - } -} - -/* -** This routine will drop an existing named index. This routine -** implements the DROP INDEX statement. -*/ -SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ - Index *pIndex; - Vdbe *v; - sqlite3 *db = pParse->db; - int iDb; - - assert( pParse->nErr==0 ); /* Never called with prior errors */ - if( db->mallocFailed ){ - goto exit_drop_index; - } - assert( pName->nSrc==1 ); - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto exit_drop_index; - } - pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); - if( pIndex==0 ){ - if( !ifExists ){ - sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); - }else{ - sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); - } - pParse->checkSchema = 1; - goto exit_drop_index; - } - if( pIndex->autoIndex ){ - sqlite3ErrorMsg(pParse, "index associated with UNIQUE " - "or PRIMARY KEY constraint cannot be dropped", 0); - goto exit_drop_index; - } - iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int code = SQLITE_DROP_INDEX; - Table *pTab = pIndex->pTable; - const char *zDb = db->aDb[iDb].zName; - const char *zTab = SCHEMA_TABLE(iDb); - if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ - goto exit_drop_index; - } - if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX; - if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ - goto exit_drop_index; - } - } -#endif - - /* Generate code to remove the index and from the master table */ - v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3BeginWriteOperation(pParse, 1, iDb); - sqlite3NestedParse(pParse, - "DELETE FROM %Q.%s WHERE name=%Q AND type='index'", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName - ); - sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName); - sqlite3ChangeCookie(pParse, iDb); - destroyRootPage(pParse, pIndex->tnum, iDb); - sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); - } - -exit_drop_index: - sqlite3SrcListDelete(db, pName); -} - -/* -** pArray is a pointer to an array of objects. Each object in the -** array is szEntry bytes in size. This routine uses sqlite3DbRealloc() -** to extend the array so that there is space for a new object at the end. -** -** When this function is called, *pnEntry contains the current size of -** the array (in entries - so the allocation is ((*pnEntry) * szEntry) bytes -** in total). -** -** If the realloc() is successful (i.e. if no OOM condition occurs), the -** space allocated for the new object is zeroed, *pnEntry updated to -** reflect the new size of the array and a pointer to the new allocation -** returned. *pIdx is set to the index of the new array entry in this case. -** -** Otherwise, if the realloc() fails, *pIdx is set to -1, *pnEntry remains -** unchanged and a copy of pArray returned. -*/ -SQLITE_PRIVATE void *sqlite3ArrayAllocate( - sqlite3 *db, /* Connection to notify of malloc failures */ - void *pArray, /* Array of objects. Might be reallocated */ - int szEntry, /* Size of each object in the array */ - int *pnEntry, /* Number of objects currently in use */ - int *pIdx /* Write the index of a new slot here */ -){ - char *z; - int n = *pnEntry; - if( (n & (n-1))==0 ){ - int sz = (n==0) ? 1 : 2*n; - void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry); - if( pNew==0 ){ - *pIdx = -1; - return pArray; - } - pArray = pNew; - } - z = (char*)pArray; - memset(&z[n * szEntry], 0, szEntry); - *pIdx = n; - ++*pnEntry; - return pArray; -} - -/* -** Append a new element to the given IdList. Create a new IdList if -** need be. -** -** A new IdList is returned, or NULL if malloc() fails. -*/ -SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ - int i; - if( pList==0 ){ - pList = sqlite3DbMallocZero(db, sizeof(IdList) ); - if( pList==0 ) return 0; - } - pList->a = sqlite3ArrayAllocate( - db, - pList->a, - sizeof(pList->a[0]), - &pList->nId, - &i - ); - if( i<0 ){ - sqlite3IdListDelete(db, pList); - return 0; - } - pList->a[i].zName = sqlite3NameFromToken(db, pToken); - return pList; -} - -/* -** Delete an IdList. -*/ -SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ - int i; - if( pList==0 ) return; - for(i=0; inId; i++){ - sqlite3DbFree(db, pList->a[i].zName); - } - sqlite3DbFree(db, pList->a); - sqlite3DbFree(db, pList); -} - -/* -** Return the index in pList of the identifier named zId. Return -1 -** if not found. -*/ -SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){ - int i; - if( pList==0 ) return -1; - for(i=0; inId; i++){ - if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; - } - return -1; -} - -/* -** Expand the space allocated for the given SrcList object by -** creating nExtra new slots beginning at iStart. iStart is zero based. -** New slots are zeroed. -** -** For example, suppose a SrcList initially contains two entries: A,B. -** To append 3 new entries onto the end, do this: -** -** sqlite3SrcListEnlarge(db, pSrclist, 3, 2); -** -** After the call above it would contain: A, B, nil, nil, nil. -** If the iStart argument had been 1 instead of 2, then the result -** would have been: A, nil, nil, nil, B. To prepend the new slots, -** the iStart value would be 0. The result then would -** be: nil, nil, nil, A, B. -** -** If a memory allocation fails the SrcList is unchanged. The -** db->mallocFailed flag will be set to true. -*/ -SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge( - sqlite3 *db, /* Database connection to notify of OOM errors */ - SrcList *pSrc, /* The SrcList to be enlarged */ - int nExtra, /* Number of new slots to add to pSrc->a[] */ - int iStart /* Index in pSrc->a[] of first new slot */ -){ - int i; - - /* Sanity checking on calling parameters */ - assert( iStart>=0 ); - assert( nExtra>=1 ); - assert( pSrc!=0 ); - assert( iStart<=pSrc->nSrc ); - - /* Allocate additional space if needed */ - if( pSrc->nSrc+nExtra>pSrc->nAlloc ){ - SrcList *pNew; - int nAlloc = pSrc->nSrc+nExtra; - int nGot; - pNew = sqlite3DbRealloc(db, pSrc, - sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) ); - if( pNew==0 ){ - assert( db->mallocFailed ); - return pSrc; - } - pSrc = pNew; - nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1; - pSrc->nAlloc = (u16)nGot; - } - - /* Move existing slots that come after the newly inserted slots - ** out of the way */ - for(i=pSrc->nSrc-1; i>=iStart; i--){ - pSrc->a[i+nExtra] = pSrc->a[i]; - } - pSrc->nSrc += (i16)nExtra; - - /* Zero the newly allocated slots */ - memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra); - for(i=iStart; ia[i].iCursor = -1; - } - - /* Return a pointer to the enlarged SrcList */ - return pSrc; -} - - -/* -** Append a new table name to the given SrcList. Create a new SrcList if -** need be. A new entry is created in the SrcList even if pTable is NULL. -** -** A SrcList is returned, or NULL if there is an OOM error. The returned -** SrcList might be the same as the SrcList that was input or it might be -** a new one. If an OOM error does occurs, then the prior value of pList -** that is input to this routine is automatically freed. -** -** If pDatabase is not null, it means that the table has an optional -** database name prefix. Like this: "database.table". The pDatabase -** points to the table name and the pTable points to the database name. -** The SrcList.a[].zName field is filled with the table name which might -** come from pTable (if pDatabase is NULL) or from pDatabase. -** SrcList.a[].zDatabase is filled with the database name from pTable, -** or with NULL if no database is specified. -** -** In other words, if call like this: -** -** sqlite3SrcListAppend(D,A,B,0); -** -** Then B is a table name and the database name is unspecified. If called -** like this: -** -** sqlite3SrcListAppend(D,A,B,C); -** -** Then C is the table name and B is the database name. If C is defined -** then so is B. In other words, we never have a case where: -** -** sqlite3SrcListAppend(D,A,0,C); -** -** Both pTable and pDatabase are assumed to be quoted. They are dequoted -** before being added to the SrcList. -*/ -SQLITE_PRIVATE SrcList *sqlite3SrcListAppend( - sqlite3 *db, /* Connection to notify of malloc failures */ - SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */ - Token *pTable, /* Table to append */ - Token *pDatabase /* Database of the table */ -){ - struct SrcList_item *pItem; - assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */ - if( pList==0 ){ - pList = sqlite3DbMallocZero(db, sizeof(SrcList) ); - if( pList==0 ) return 0; - pList->nAlloc = 1; - } - pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); - if( db->mallocFailed ){ - sqlite3SrcListDelete(db, pList); - return 0; - } - pItem = &pList->a[pList->nSrc-1]; - if( pDatabase && pDatabase->z==0 ){ - pDatabase = 0; - } - if( pDatabase ){ - Token *pTemp = pDatabase; - pDatabase = pTable; - pTable = pTemp; - } - pItem->zName = sqlite3NameFromToken(db, pTable); - pItem->zDatabase = sqlite3NameFromToken(db, pDatabase); - return pList; -} - -/* -** Assign VdbeCursor index numbers to all tables in a SrcList -*/ -SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ - int i; - struct SrcList_item *pItem; - assert(pList || pParse->db->mallocFailed ); - if( pList ){ - for(i=0, pItem=pList->a; inSrc; i++, pItem++){ - if( pItem->iCursor>=0 ) break; - pItem->iCursor = pParse->nTab++; - if( pItem->pSelect ){ - sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); - } - } - } -} - -/* -** Delete an entire SrcList including all its substructure. -*/ -SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ - int i; - struct SrcList_item *pItem; - if( pList==0 ) return; - for(pItem=pList->a, i=0; inSrc; i++, pItem++){ - sqlite3DbFree(db, pItem->zDatabase); - sqlite3DbFree(db, pItem->zName); - sqlite3DbFree(db, pItem->zAlias); - sqlite3DbFree(db, pItem->zIndex); - sqlite3DeleteTable(db, pItem->pTab); - sqlite3SelectDelete(db, pItem->pSelect); - sqlite3ExprDelete(db, pItem->pOn); - sqlite3IdListDelete(db, pItem->pUsing); - } - sqlite3DbFree(db, pList); -} - -/* -** This routine is called by the parser to add a new term to the -** end of a growing FROM clause. The "p" parameter is the part of -** the FROM clause that has already been constructed. "p" is NULL -** if this is the first term of the FROM clause. pTable and pDatabase -** are the name of the table and database named in the FROM clause term. -** pDatabase is NULL if the database name qualifier is missing - the -** usual case. If the term has a alias, then pAlias points to the -** alias token. If the term is a subquery, then pSubquery is the -** SELECT statement that the subquery encodes. The pTable and -** pDatabase parameters are NULL for subqueries. The pOn and pUsing -** parameters are the content of the ON and USING clauses. -** -** Return a new SrcList which encodes is the FROM with the new -** term added. -*/ -SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm( - Parse *pParse, /* Parsing context */ - SrcList *p, /* The left part of the FROM clause already seen */ - Token *pTable, /* Name of the table to add to the FROM clause */ - Token *pDatabase, /* Name of the database containing pTable */ - Token *pAlias, /* The right-hand side of the AS subexpression */ - Select *pSubquery, /* A subquery used in place of a table name */ - Expr *pOn, /* The ON clause of a join */ - IdList *pUsing /* The USING clause of a join */ -){ - struct SrcList_item *pItem; - sqlite3 *db = pParse->db; - if( !p && (pOn || pUsing) ){ - sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", - (pOn ? "ON" : "USING") - ); - goto append_from_error; - } - p = sqlite3SrcListAppend(db, p, pTable, pDatabase); - if( p==0 || NEVER(p->nSrc==0) ){ - goto append_from_error; - } - pItem = &p->a[p->nSrc-1]; - assert( pAlias!=0 ); - if( pAlias->n ){ - pItem->zAlias = sqlite3NameFromToken(db, pAlias); - } - pItem->pSelect = pSubquery; - pItem->pOn = pOn; - pItem->pUsing = pUsing; - return p; - - append_from_error: - assert( p==0 ); - sqlite3ExprDelete(db, pOn); - sqlite3IdListDelete(db, pUsing); - sqlite3SelectDelete(db, pSubquery); - return 0; -} - -/* -** Add an INDEXED BY or NOT INDEXED clause to the most recently added -** element of the source-list passed as the second argument. -*/ -SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ - assert( pIndexedBy!=0 ); - if( p && ALWAYS(p->nSrc>0) ){ - struct SrcList_item *pItem = &p->a[p->nSrc-1]; - assert( pItem->notIndexed==0 && pItem->zIndex==0 ); - if( pIndexedBy->n==1 && !pIndexedBy->z ){ - /* A "NOT INDEXED" clause was supplied. See parse.y - ** construct "indexed_opt" for details. */ - pItem->notIndexed = 1; - }else{ - pItem->zIndex = sqlite3NameFromToken(pParse->db, pIndexedBy); - } - } -} - -/* -** When building up a FROM clause in the parser, the join operator -** is initially attached to the left operand. But the code generator -** expects the join operator to be on the right operand. This routine -** Shifts all join operators from left to right for an entire FROM -** clause. -** -** Example: Suppose the join is like this: -** -** A natural cross join B -** -** The operator is "natural cross join". The A and B operands are stored -** in p->a[0] and p->a[1], respectively. The parser initially stores the -** operator with A. This routine shifts that operator over to B. -*/ -SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){ - if( p ){ - int i; - assert( p->a || p->nSrc==0 ); - for(i=p->nSrc-1; i>0; i--){ - p->a[i].jointype = p->a[i-1].jointype; - } - p->a[0].jointype = 0; - } -} - -/* -** Begin a transaction -*/ -SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ - sqlite3 *db; - Vdbe *v; - int i; - - assert( pParse!=0 ); - db = pParse->db; - assert( db!=0 ); -/* if( db->aDb[0].pBt==0 ) return; */ - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ){ - return; - } - v = sqlite3GetVdbe(pParse); - if( !v ) return; - if( type!=TK_DEFERRED ){ - for(i=0; inDb; i++){ - sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); - sqlite3VdbeUsesBtree(v, i); - } - } - sqlite3VdbeAddOp2(v, OP_AutoCommit, 0, 0); -} - -/* -** Commit a transaction -*/ -SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){ - Vdbe *v; - - assert( pParse!=0 ); - assert( pParse->db!=0 ); - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){ - return; - } - v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); - } -} - -/* -** Rollback a transaction -*/ -SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){ - Vdbe *v; - - assert( pParse!=0 ); - assert( pParse->db!=0 ); - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ){ - return; - } - v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1); - } -} - -/* -** This function is called by the parser when it parses a command to create, -** release or rollback an SQL savepoint. -*/ -SQLITE_PRIVATE void sqlite3Savepoint(Parse *pParse, int op, Token *pName){ - char *zName = sqlite3NameFromToken(pParse->db, pName); - if( zName ){ - Vdbe *v = sqlite3GetVdbe(pParse); -#ifndef SQLITE_OMIT_AUTHORIZATION - static const char * const az[] = { "BEGIN", "RELEASE", "ROLLBACK" }; - assert( !SAVEPOINT_BEGIN && SAVEPOINT_RELEASE==1 && SAVEPOINT_ROLLBACK==2 ); -#endif - if( !v || sqlite3AuthCheck(pParse, SQLITE_SAVEPOINT, az[op], zName, 0) ){ - sqlite3DbFree(pParse->db, zName); - return; - } - sqlite3VdbeAddOp4(v, OP_Savepoint, op, 0, 0, zName, P4_DYNAMIC); - } -} - -/* -** Make sure the TEMP database is open and available for use. Return -** the number of errors. Leave any error messages in the pParse structure. -*/ -SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ - sqlite3 *db = pParse->db; - if( db->aDb[1].pBt==0 && !pParse->explain ){ - int rc; - Btree *pBt; - static const int flags = - SQLITE_OPEN_READWRITE | - SQLITE_OPEN_CREATE | - SQLITE_OPEN_EXCLUSIVE | - SQLITE_OPEN_DELETEONCLOSE | - SQLITE_OPEN_TEMP_DB; - - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags); - if( rc!=SQLITE_OK ){ - sqlite3ErrorMsg(pParse, "unable to open a temporary database " - "file for storing temporary tables"); - pParse->rc = rc; - return 1; - } - db->aDb[1].pBt = pBt; - assert( db->aDb[1].pSchema ); - if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ - db->mallocFailed = 1; - return 1; - } - } - return 0; -} - -/* -** Generate VDBE code that will verify the schema cookie and start -** a read-transaction for all named database files. -** -** It is important that all schema cookies be verified and all -** read transactions be started before anything else happens in -** the VDBE program. But this routine can be called after much other -** code has been generated. So here is what we do: -** -** The first time this routine is called, we code an OP_Goto that -** will jump to a subroutine at the end of the program. Then we -** record every database that needs its schema verified in the -** pParse->cookieMask field. Later, after all other code has been -** generated, the subroutine that does the cookie verifications and -** starts the transactions will be coded and the OP_Goto P2 value -** will be made to point to that subroutine. The generation of the -** cookie verification subroutine code happens in sqlite3FinishCoding(). -** -** If iDb<0 then code the OP_Goto only - don't set flag to verify the -** schema on any databases. This can be used to position the OP_Goto -** early in the code, before we know if any database tables will be used. -*/ -SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - -#ifndef SQLITE_OMIT_TRIGGER - if( pToplevel!=pParse ){ - /* This branch is taken if a trigger is currently being coded. In this - ** case, set cookieGoto to a non-zero value to show that this function - ** has been called. This is used by the sqlite3ExprCodeConstants() - ** function. */ - pParse->cookieGoto = -1; - } -#endif - if( pToplevel->cookieGoto==0 ){ - Vdbe *v = sqlite3GetVdbe(pToplevel); - if( v==0 ) return; /* This only happens if there was a prior error */ - pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; - } - if( iDb>=0 ){ - sqlite3 *db = pToplevel->db; - yDbMask mask; - - assert( iDbnDb ); - assert( db->aDb[iDb].pBt!=0 || iDb==1 ); - assert( iDbcookieMask & mask)==0 ){ - pToplevel->cookieMask |= mask; - pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; - if( !OMIT_TEMPDB && iDb==1 ){ - sqlite3OpenTempDatabase(pToplevel); - } - } - } -} - -/* -** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each -** attached database. Otherwise, invoke it for the database named zDb only. -*/ -SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){ - sqlite3 *db = pParse->db; - int i; - for(i=0; inDb; i++){ - Db *pDb = &db->aDb[i]; - if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zName)) ){ - sqlite3CodeVerifySchema(pParse, i); - } - } -} - -/* -** Generate VDBE code that prepares for doing an operation that -** might change the database. -** -** This routine starts a new transaction if we are not already within -** a transaction. If we are already within a transaction, then a checkpoint -** is set if the setStatement parameter is true. A checkpoint should -** be set for operations that might fail (due to a constraint) part of -** the way through and which will need to undo some writes without having to -** rollback the whole transaction. For operations where all constraints -** can be checked before any changes are made to the database, it is never -** necessary to undo a write and the checkpoint should not be set. -*/ -SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - sqlite3CodeVerifySchema(pParse, iDb); - pToplevel->writeMask |= ((yDbMask)1)<isMultiWrite |= setStatement; -} - -/* -** Indicate that the statement currently under construction might write -** more than one entry (example: deleting one row then inserting another, -** inserting multiple rows in a table, or inserting a row and index entries.) -** If an abort occurs after some of these writes have completed, then it will -** be necessary to undo the completed writes. -*/ -SQLITE_PRIVATE void sqlite3MultiWrite(Parse *pParse){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - pToplevel->isMultiWrite = 1; -} - -/* -** The code generator calls this routine if is discovers that it is -** possible to abort a statement prior to completion. In order to -** perform this abort without corrupting the database, we need to make -** sure that the statement is protected by a statement transaction. -** -** Technically, we only need to set the mayAbort flag if the -** isMultiWrite flag was previously set. There is a time dependency -** such that the abort must occur after the multiwrite. This makes -** some statements involving the REPLACE conflict resolution algorithm -** go a little faster. But taking advantage of this time dependency -** makes it more difficult to prove that the code is correct (in -** particular, it prevents us from writing an effective -** implementation of sqlite3AssertMayAbort()) and so we have chosen -** to take the safe route and skip the optimization. -*/ -SQLITE_PRIVATE void sqlite3MayAbort(Parse *pParse){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - pToplevel->mayAbort = 1; -} - -/* -** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT -** error. The onError parameter determines which (if any) of the statement -** and/or current transaction is rolled back. -*/ -SQLITE_PRIVATE void sqlite3HaltConstraint( - Parse *pParse, /* Parsing context */ - int errCode, /* extended error code */ - int onError, /* Constraint type */ - char *p4, /* Error message */ - int p4type /* P4_STATIC or P4_TRANSIENT */ -){ - Vdbe *v = sqlite3GetVdbe(pParse); - assert( (errCode&0xff)==SQLITE_CONSTRAINT ); - if( onError==OE_Abort ){ - sqlite3MayAbort(pParse); - } - sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type); -} - -/* -** Check to see if pIndex uses the collating sequence pColl. Return -** true if it does and false if it does not. -*/ -#ifndef SQLITE_OMIT_REINDEX -static int collationMatch(const char *zColl, Index *pIndex){ - int i; - assert( zColl!=0 ); - for(i=0; inColumn; i++){ - const char *z = pIndex->azColl[i]; - assert( z!=0 ); - if( 0==sqlite3StrICmp(z, zColl) ){ - return 1; - } - } - return 0; -} -#endif - -/* -** Recompute all indices of pTab that use the collating sequence pColl. -** If pColl==0 then recompute all indices of pTab. -*/ -#ifndef SQLITE_OMIT_REINDEX -static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){ - Index *pIndex; /* An index associated with pTab */ - - for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ - if( zColl==0 || collationMatch(zColl, pIndex) ){ - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3RefillIndex(pParse, pIndex, -1); - } - } -} -#endif - -/* -** Recompute all indices of all tables in all databases where the -** indices use the collating sequence pColl. If pColl==0 then recompute -** all indices everywhere. -*/ -#ifndef SQLITE_OMIT_REINDEX -static void reindexDatabases(Parse *pParse, char const *zColl){ - Db *pDb; /* A single database */ - int iDb; /* The database index number */ - sqlite3 *db = pParse->db; /* The database connection */ - HashElem *k; /* For looping over tables in pDb */ - Table *pTab; /* A table in the database */ - - assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */ - for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){ - assert( pDb!=0 ); - for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ - pTab = (Table*)sqliteHashData(k); - reindexTable(pParse, pTab, zColl); - } - } -} -#endif - -/* -** Generate code for the REINDEX command. -** -** REINDEX -- 1 -** REINDEX -- 2 -** REINDEX ?.? -- 3 -** REINDEX ?.? -- 4 -** -** Form 1 causes all indices in all attached databases to be rebuilt. -** Form 2 rebuilds all indices in all databases that use the named -** collating function. Forms 3 and 4 rebuild the named index or all -** indices associated with the named table. -*/ -#ifndef SQLITE_OMIT_REINDEX -SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ - CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */ - char *z; /* Name of a table or index */ - const char *zDb; /* Name of the database */ - Table *pTab; /* A table in the database */ - Index *pIndex; /* An index associated with pTab */ - int iDb; /* The database index number */ - sqlite3 *db = pParse->db; /* The database connection */ - Token *pObjName; /* Name of the table or index to be reindexed */ - - /* Read the database schema. If an error occurs, leave an error message - ** and code in pParse and return NULL. */ - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - return; - } - - if( pName1==0 ){ - reindexDatabases(pParse, 0); - return; - }else if( NEVER(pName2==0) || pName2->z==0 ){ - char *zColl; - assert( pName1->z ); - zColl = sqlite3NameFromToken(pParse->db, pName1); - if( !zColl ) return; - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); - if( pColl ){ - reindexDatabases(pParse, zColl); - sqlite3DbFree(db, zColl); - return; - } - sqlite3DbFree(db, zColl); - } - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); - if( iDb<0 ) return; - z = sqlite3NameFromToken(db, pObjName); - if( z==0 ) return; - zDb = db->aDb[iDb].zName; - pTab = sqlite3FindTable(db, z, zDb); - if( pTab ){ - reindexTable(pParse, pTab, 0); - sqlite3DbFree(db, z); - return; - } - pIndex = sqlite3FindIndex(db, z, zDb); - sqlite3DbFree(db, z); - if( pIndex ){ - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3RefillIndex(pParse, pIndex, -1); - return; - } - sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); -} -#endif - -/* -** Return a dynamicly allocated KeyInfo structure that can be used -** with OP_OpenRead or OP_OpenWrite to access database index pIdx. -** -** If successful, a pointer to the new structure is returned. In this case -** the caller is responsible for calling sqlite3DbFree(db, ) on the returned -** pointer. If an error occurs (out of memory or missing collation -** sequence), NULL is returned and the state of pParse updated to reflect -** the error. -*/ -SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ - int i; - int nCol = pIdx->nColumn; - int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol; - sqlite3 *db = pParse->db; - KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes); - - if( pKey ){ - pKey->db = pParse->db; - pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]); - assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) ); - for(i=0; iazColl[i]; - assert( zColl ); - pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl); - pKey->aSortOrder[i] = pIdx->aSortOrder[i]; - } - pKey->nField = (u16)nCol; - } - - if( pParse->nErr ){ - sqlite3DbFree(db, pKey); - pKey = 0; - } - return pKey; -} - -/************** End of build.c ***********************************************/ -/************** Begin file callback.c ****************************************/ -/* -** 2005 May 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains functions used to access the internal hash tables -** of user defined functions and collation sequences. -*/ - - -/* -** Invoke the 'collation needed' callback to request a collation sequence -** in the encoding enc of name zName, length nName. -*/ -static void callCollNeeded(sqlite3 *db, int enc, const char *zName){ - assert( !db->xCollNeeded || !db->xCollNeeded16 ); - if( db->xCollNeeded ){ - char *zExternal = sqlite3DbStrDup(db, zName); - if( !zExternal ) return; - db->xCollNeeded(db->pCollNeededArg, db, enc, zExternal); - sqlite3DbFree(db, zExternal); - } -#ifndef SQLITE_OMIT_UTF16 - if( db->xCollNeeded16 ){ - char const *zExternal; - sqlite3_value *pTmp = sqlite3ValueNew(db); - sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); - zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); - if( zExternal ){ - db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); - } - sqlite3ValueFree(pTmp); - } -#endif -} - -/* -** This routine is called if the collation factory fails to deliver a -** collation function in the best encoding but there may be other versions -** of this collation function (for other text encodings) available. Use one -** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if -** possible. -*/ -static int synthCollSeq(sqlite3 *db, CollSeq *pColl){ - CollSeq *pColl2; - char *z = pColl->zName; - int i; - static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; - for(i=0; i<3; i++){ - pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0); - if( pColl2->xCmp!=0 ){ - memcpy(pColl, pColl2, sizeof(CollSeq)); - pColl->xDel = 0; /* Do not copy the destructor */ - return SQLITE_OK; - } - } - return SQLITE_ERROR; -} - -/* -** This function is responsible for invoking the collation factory callback -** or substituting a collation sequence of a different encoding when the -** requested collation sequence is not available in the desired encoding. -** -** If it is not NULL, then pColl must point to the database native encoding -** collation sequence with name zName, length nName. -** -** The return value is either the collation sequence to be used in database -** db for collation type name zName, length nName, or NULL, if no collation -** sequence can be found. If no collation is found, leave an error message. -** -** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq() -*/ -SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq( - Parse *pParse, /* Parsing context */ - u8 enc, /* The desired encoding for the collating sequence */ - CollSeq *pColl, /* Collating sequence with native encoding, or NULL */ - const char *zName /* Collating sequence name */ -){ - CollSeq *p; - sqlite3 *db = pParse->db; - - p = pColl; - if( !p ){ - p = sqlite3FindCollSeq(db, enc, zName, 0); - } - if( !p || !p->xCmp ){ - /* No collation sequence of this type for this encoding is registered. - ** Call the collation factory to see if it can supply us with one. - */ - callCollNeeded(db, enc, zName); - p = sqlite3FindCollSeq(db, enc, zName, 0); - } - if( p && !p->xCmp && synthCollSeq(db, p) ){ - p = 0; - } - assert( !p || p->xCmp ); - if( p==0 ){ - sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); - } - return p; -} - -/* -** This routine is called on a collation sequence before it is used to -** check that it is defined. An undefined collation sequence exists when -** a database is loaded that contains references to collation sequences -** that have not been defined by sqlite3_create_collation() etc. -** -** If required, this routine calls the 'collation needed' callback to -** request a definition of the collating sequence. If this doesn't work, -** an equivalent collating sequence that uses a text encoding different -** from the main database is substituted, if one is available. -*/ -SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ - if( pColl ){ - const char *zName = pColl->zName; - sqlite3 *db = pParse->db; - CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName); - if( !p ){ - return SQLITE_ERROR; - } - assert( p==pColl ); - } - return SQLITE_OK; -} - - - -/* -** Locate and return an entry from the db.aCollSeq hash table. If the entry -** specified by zName and nName is not found and parameter 'create' is -** true, then create a new entry. Otherwise return NULL. -** -** Each pointer stored in the sqlite3.aCollSeq hash table contains an -** array of three CollSeq structures. The first is the collation sequence -** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. -** -** Stored immediately after the three collation sequences is a copy of -** the collation sequence name. A pointer to this string is stored in -** each collation sequence structure. -*/ -static CollSeq *findCollSeqEntry( - sqlite3 *db, /* Database connection */ - const char *zName, /* Name of the collating sequence */ - int create /* Create a new entry if true */ -){ - CollSeq *pColl; - int nName = sqlite3Strlen30(zName); - pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); - - if( 0==pColl && create ){ - pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); - if( pColl ){ - CollSeq *pDel = 0; - pColl[0].zName = (char*)&pColl[3]; - pColl[0].enc = SQLITE_UTF8; - pColl[1].zName = (char*)&pColl[3]; - pColl[1].enc = SQLITE_UTF16LE; - pColl[2].zName = (char*)&pColl[3]; - pColl[2].enc = SQLITE_UTF16BE; - memcpy(pColl[0].zName, zName, nName); - pColl[0].zName[nName] = 0; - pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); - - /* If a malloc() failure occurred in sqlite3HashInsert(), it will - ** return the pColl pointer to be deleted (because it wasn't added - ** to the hash table). - */ - assert( pDel==0 || pDel==pColl ); - if( pDel!=0 ){ - db->mallocFailed = 1; - sqlite3DbFree(db, pDel); - pColl = 0; - } - } - } - return pColl; -} - -/* -** Parameter zName points to a UTF-8 encoded string nName bytes long. -** Return the CollSeq* pointer for the collation sequence named zName -** for the encoding 'enc' from the database 'db'. -** -** If the entry specified is not found and 'create' is true, then create a -** new entry. Otherwise return NULL. -** -** A separate function sqlite3LocateCollSeq() is a wrapper around -** this routine. sqlite3LocateCollSeq() invokes the collation factory -** if necessary and generates an error message if the collating sequence -** cannot be found. -** -** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq() -*/ -SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq( - sqlite3 *db, - u8 enc, - const char *zName, - int create -){ - CollSeq *pColl; - if( zName ){ - pColl = findCollSeqEntry(db, zName, create); - }else{ - pColl = db->pDfltColl; - } - assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); - assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); - if( pColl ) pColl += enc-1; - return pColl; -} - -/* During the search for the best function definition, this procedure -** is called to test how well the function passed as the first argument -** matches the request for a function with nArg arguments in a system -** that uses encoding enc. The value returned indicates how well the -** request is matched. A higher value indicates a better match. -** -** If nArg is -1 that means to only return a match (non-zero) if p->nArg -** is also -1. In other words, we are searching for a function that -** takes a variable number of arguments. -** -** If nArg is -2 that means that we are searching for any function -** regardless of the number of arguments it uses, so return a positive -** match score for any -** -** The returned value is always between 0 and 6, as follows: -** -** 0: Not a match. -** 1: UTF8/16 conversion required and function takes any number of arguments. -** 2: UTF16 byte order change required and function takes any number of args. -** 3: encoding matches and function takes any number of arguments -** 4: UTF8/16 conversion required - argument count matches exactly -** 5: UTF16 byte order conversion required - argument count matches exactly -** 6: Perfect match: encoding and argument count match exactly. -** -** If nArg==(-2) then any function with a non-null xStep or xFunc is -** a perfect match and any function with both xStep and xFunc NULL is -** a non-match. -*/ -#define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */ -static int matchQuality( - FuncDef *p, /* The function we are evaluating for match quality */ - int nArg, /* Desired number of arguments. (-1)==any */ - u8 enc /* Desired text encoding */ -){ - int match; - - /* nArg of -2 is a special case */ - if( nArg==(-2) ) return (p->xFunc==0 && p->xStep==0) ? 0 : FUNC_PERFECT_MATCH; - - /* Wrong number of arguments means "no match" */ - if( p->nArg!=nArg && p->nArg>=0 ) return 0; - - /* Give a better score to a function with a specific number of arguments - ** than to function that accepts any number of arguments. */ - if( p->nArg==nArg ){ - match = 4; - }else{ - match = 1; - } - - /* Bonus points if the text encoding matches */ - if( enc==p->iPrefEnc ){ - match += 2; /* Exact encoding match */ - }else if( (enc & p->iPrefEnc & 2)!=0 ){ - match += 1; /* Both are UTF16, but with different byte orders */ - } - - return match; -} - -/* -** Search a FuncDefHash for a function with the given name. Return -** a pointer to the matching FuncDef if found, or 0 if there is no match. -*/ -static FuncDef *functionSearch( - FuncDefHash *pHash, /* Hash table to search */ - int h, /* Hash of the name */ - const char *zFunc, /* Name of function */ - int nFunc /* Number of bytes in zFunc */ -){ - FuncDef *p; - for(p=pHash->a[h]; p; p=p->pHash){ - if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){ - return p; - } - } - return 0; -} - -/* -** Insert a new FuncDef into a FuncDefHash hash table. -*/ -SQLITE_PRIVATE void sqlite3FuncDefInsert( - FuncDefHash *pHash, /* The hash table into which to insert */ - FuncDef *pDef /* The function definition to insert */ -){ - FuncDef *pOther; - int nName = sqlite3Strlen30(pDef->zName); - u8 c1 = (u8)pDef->zName[0]; - int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a); - pOther = functionSearch(pHash, h, pDef->zName, nName); - if( pOther ){ - assert( pOther!=pDef && pOther->pNext!=pDef ); - pDef->pNext = pOther->pNext; - pOther->pNext = pDef; - }else{ - pDef->pNext = 0; - pDef->pHash = pHash->a[h]; - pHash->a[h] = pDef; - } -} - - - -/* -** Locate a user function given a name, a number of arguments and a flag -** indicating whether the function prefers UTF-16 over UTF-8. Return a -** pointer to the FuncDef structure that defines that function, or return -** NULL if the function does not exist. -** -** If the createFlag argument is true, then a new (blank) FuncDef -** structure is created and liked into the "db" structure if a -** no matching function previously existed. -** -** If nArg is -2, then the first valid function found is returned. A -** function is valid if either xFunc or xStep is non-zero. The nArg==(-2) -** case is used to see if zName is a valid function name for some number -** of arguments. If nArg is -2, then createFlag must be 0. -** -** If createFlag is false, then a function with the required name and -** number of arguments may be returned even if the eTextRep flag does not -** match that requested. -*/ -SQLITE_PRIVATE FuncDef *sqlite3FindFunction( - sqlite3 *db, /* An open database */ - const char *zName, /* Name of the function. Not null-terminated */ - int nName, /* Number of characters in the name */ - int nArg, /* Number of arguments. -1 means any number */ - u8 enc, /* Preferred text encoding */ - u8 createFlag /* Create new entry if true and does not otherwise exist */ -){ - FuncDef *p; /* Iterator variable */ - FuncDef *pBest = 0; /* Best match found so far */ - int bestScore = 0; /* Score of best match */ - int h; /* Hash value */ - - assert( nArg>=(-2) ); - assert( nArg>=(-1) || createFlag==0 ); - assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); - h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); - - /* First search for a match amongst the application-defined functions. - */ - p = functionSearch(&db->aFunc, h, zName, nName); - while( p ){ - int score = matchQuality(p, nArg, enc); - if( score>bestScore ){ - pBest = p; - bestScore = score; - } - p = p->pNext; - } - - /* If no match is found, search the built-in functions. - ** - ** If the SQLITE_PreferBuiltin flag is set, then search the built-in - ** functions even if a prior app-defined function was found. And give - ** priority to built-in functions. - ** - ** Except, if createFlag is true, that means that we are trying to - ** install a new function. Whatever FuncDef structure is returned it will - ** have fields overwritten with new information appropriate for the - ** new function. But the FuncDefs for built-in functions are read-only. - ** So we must not search for built-ins when creating a new function. - */ - if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); - bestScore = 0; - p = functionSearch(pHash, h, zName, nName); - while( p ){ - int score = matchQuality(p, nArg, enc); - if( score>bestScore ){ - pBest = p; - bestScore = score; - } - p = p->pNext; - } - } - - /* If the createFlag parameter is true and the search did not reveal an - ** exact match for the name, number of arguments and encoding, then add a - ** new entry to the hash table and return it. - */ - if( createFlag && bestScorezName = (char *)&pBest[1]; - pBest->nArg = (u16)nArg; - pBest->iPrefEnc = enc; - memcpy(pBest->zName, zName, nName); - pBest->zName[nName] = 0; - sqlite3FuncDefInsert(&db->aFunc, pBest); - } - - if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ - return pBest; - } - return 0; -} - -/* -** Free all resources held by the schema structure. The void* argument points -** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the -** pointer itself, it just cleans up subsidiary resources (i.e. the contents -** of the schema hash tables). -** -** The Schema.cache_size variable is not cleared. -*/ -SQLITE_PRIVATE void sqlite3SchemaClear(void *p){ - Hash temp1; - Hash temp2; - HashElem *pElem; - Schema *pSchema = (Schema *)p; - - temp1 = pSchema->tblHash; - temp2 = pSchema->trigHash; - sqlite3HashInit(&pSchema->trigHash); - sqlite3HashClear(&pSchema->idxHash); - for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ - sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem)); - } - sqlite3HashClear(&temp2); - sqlite3HashInit(&pSchema->tblHash); - for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ - Table *pTab = sqliteHashData(pElem); - sqlite3DeleteTable(0, pTab); - } - sqlite3HashClear(&temp1); - sqlite3HashClear(&pSchema->fkeyHash); - pSchema->pSeqTab = 0; - if( pSchema->flags & DB_SchemaLoaded ){ - pSchema->iGeneration++; - pSchema->flags &= ~DB_SchemaLoaded; - } -} - -/* -** Find and return the schema associated with a BTree. Create -** a new one if necessary. -*/ -SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ - Schema * p; - if( pBt ){ - p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear); - }else{ - p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); - } - if( !p ){ - db->mallocFailed = 1; - }else if ( 0==p->file_format ){ - sqlite3HashInit(&p->tblHash); - sqlite3HashInit(&p->idxHash); - sqlite3HashInit(&p->trigHash); - sqlite3HashInit(&p->fkeyHash); - p->enc = SQLITE_UTF8; - } - return p; -} - -/************** End of callback.c ********************************************/ -/************** Begin file delete.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** in order to generate code for DELETE FROM statements. -*/ - -/* -** While a SrcList can in general represent multiple tables and subqueries -** (as in the FROM clause of a SELECT statement) in this case it contains -** the name of a single table, as one might find in an INSERT, DELETE, -** or UPDATE statement. Look up that table in the symbol table and -** return a pointer. Set an error message and return NULL if the table -** name is not found or if any other error occurs. -** -** The following fields are initialized appropriate in pSrc: -** -** pSrc->a[0].pTab Pointer to the Table object -** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one -** -*/ -SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ - struct SrcList_item *pItem = pSrc->a; - Table *pTab; - assert( pItem && pSrc->nSrc==1 ); - pTab = sqlite3LocateTableItem(pParse, 0, pItem); - sqlite3DeleteTable(pParse->db, pItem->pTab); - pItem->pTab = pTab; - if( pTab ){ - pTab->nRef++; - } - if( sqlite3IndexedByLookup(pParse, pItem) ){ - pTab = 0; - } - return pTab; -} - -/* -** Check to make sure the given table is writable. If it is not -** writable, generate an error message and return 1. If it is -** writable return 0; -*/ -SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ - /* A table is not writable under the following circumstances: - ** - ** 1) It is a virtual table and no implementation of the xUpdate method - ** has been provided, or - ** 2) It is a system table (i.e. sqlite_master), this call is not - ** part of a nested parse and writable_schema pragma has not - ** been specified. - ** - ** In either case leave an error message in pParse and return non-zero. - */ - if( ( IsVirtual(pTab) - && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ) - || ( (pTab->tabFlags & TF_Readonly)!=0 - && (pParse->db->flags & SQLITE_WriteSchema)==0 - && pParse->nested==0 ) - ){ - sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); - return 1; - } - -#ifndef SQLITE_OMIT_VIEW - if( !viewOk && pTab->pSelect ){ - sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); - return 1; - } -#endif - return 0; -} - - -#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) -/* -** Evaluate a view and store its result in an ephemeral table. The -** pWhere argument is an optional WHERE clause that restricts the -** set of rows in the view that are to be added to the ephemeral table. -*/ -SQLITE_PRIVATE void sqlite3MaterializeView( - Parse *pParse, /* Parsing context */ - Table *pView, /* View definition */ - Expr *pWhere, /* Optional WHERE clause to be added */ - int iCur /* Cursor number for ephemerial table */ -){ - SelectDest dest; - Select *pSel; - SrcList *pFrom; - sqlite3 *db = pParse->db; - int iDb = sqlite3SchemaToIndex(db, pView->pSchema); - - pWhere = sqlite3ExprDup(db, pWhere, 0); - pFrom = sqlite3SrcListAppend(db, 0, 0, 0); - - if( pFrom ){ - assert( pFrom->nSrc==1 ); - pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); - pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); - assert( pFrom->a[0].pOn==0 ); - assert( pFrom->a[0].pUsing==0 ); - } - - pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); - if( pSel ) pSel->selFlags |= SF_Materialize; - - sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); - sqlite3Select(pParse, pSel, &dest); - sqlite3SelectDelete(db, pSel); -} -#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ - -#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) -/* -** Generate an expression tree to implement the WHERE, ORDER BY, -** and LIMIT/OFFSET portion of DELETE and UPDATE statements. -** -** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1; -** \__________________________/ -** pLimitWhere (pInClause) -*/ -SQLITE_PRIVATE Expr *sqlite3LimitWhere( - Parse *pParse, /* The parser context */ - SrcList *pSrc, /* the FROM clause -- which tables to scan */ - Expr *pWhere, /* The WHERE clause. May be null */ - ExprList *pOrderBy, /* The ORDER BY clause. May be null */ - Expr *pLimit, /* The LIMIT clause. May be null */ - Expr *pOffset, /* The OFFSET clause. May be null */ - char *zStmtType /* Either DELETE or UPDATE. For error messages. */ -){ - Expr *pWhereRowid = NULL; /* WHERE rowid .. */ - Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ - Expr *pSelectRowid = NULL; /* SELECT rowid ... */ - ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ - SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ - Select *pSelect = NULL; /* Complete SELECT tree */ - - /* Check that there isn't an ORDER BY without a LIMIT clause. - */ - if( pOrderBy && (pLimit == 0) ) { - sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); - goto limit_where_cleanup_2; - } - - /* We only need to generate a select expression if there - ** is a limit/offset term to enforce. - */ - if( pLimit == 0 ) { - /* if pLimit is null, pOffset will always be null as well. */ - assert( pOffset == 0 ); - return pWhere; - } - - /* Generate a select expression tree to enforce the limit/offset - ** term for the DELETE or UPDATE statement. For example: - ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 - ** becomes: - ** DELETE FROM table_a WHERE rowid IN ( - ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 - ** ); - */ - - pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); - if( pSelectRowid == 0 ) goto limit_where_cleanup_2; - pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); - if( pEList == 0 ) goto limit_where_cleanup_2; - - /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree - ** and the SELECT subtree. */ - pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); - if( pSelectSrc == 0 ) { - sqlite3ExprListDelete(pParse->db, pEList); - goto limit_where_cleanup_2; - } - - /* generate the SELECT expression tree. */ - pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, - pOrderBy,0,pLimit,pOffset); - if( pSelect == 0 ) return 0; - - /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ - pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); - if( pWhereRowid == 0 ) goto limit_where_cleanup_1; - pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0); - if( pInClause == 0 ) goto limit_where_cleanup_1; - - pInClause->x.pSelect = pSelect; - pInClause->flags |= EP_xIsSelect; - sqlite3ExprSetHeight(pParse, pInClause); - return pInClause; - - /* something went wrong. clean up anything allocated. */ -limit_where_cleanup_1: - sqlite3SelectDelete(pParse->db, pSelect); - return 0; - -limit_where_cleanup_2: - sqlite3ExprDelete(pParse->db, pWhere); - sqlite3ExprListDelete(pParse->db, pOrderBy); - sqlite3ExprDelete(pParse->db, pLimit); - sqlite3ExprDelete(pParse->db, pOffset); - return 0; -} -#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ - -/* -** Generate code for a DELETE FROM statement. -** -** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; -** \________/ \________________/ -** pTabList pWhere -*/ -SQLITE_PRIVATE void sqlite3DeleteFrom( - Parse *pParse, /* The parser context */ - SrcList *pTabList, /* The table from which we should delete things */ - Expr *pWhere /* The WHERE clause. May be null */ -){ - Vdbe *v; /* The virtual database engine */ - Table *pTab; /* The table from which records will be deleted */ - const char *zDb; /* Name of database holding pTab */ - int end, addr = 0; /* A couple addresses of generated code */ - int i; /* Loop counter */ - WhereInfo *pWInfo; /* Information about the WHERE clause */ - Index *pIdx; /* For looping over indices of the table */ - int iCur; /* VDBE Cursor number for pTab */ - sqlite3 *db; /* Main database structure */ - AuthContext sContext; /* Authorization context */ - NameContext sNC; /* Name context to resolve expressions in */ - int iDb; /* Database number */ - int memCnt = -1; /* Memory cell used for change counting */ - int rcauth; /* Value returned by authorization callback */ - -#ifndef SQLITE_OMIT_TRIGGER - int isView; /* True if attempting to delete from a view */ - Trigger *pTrigger; /* List of table triggers, if required */ -#endif - - memset(&sContext, 0, sizeof(sContext)); - db = pParse->db; - if( pParse->nErr || db->mallocFailed ){ - goto delete_from_cleanup; - } - assert( pTabList->nSrc==1 ); - - /* Locate the table which we want to delete. This table has to be - ** put in an SrcList structure because some of the subroutines we - ** will be calling are designed to work with multiple tables and expect - ** an SrcList* parameter instead of just a Table* parameter. - */ - pTab = sqlite3SrcListLookup(pParse, pTabList); - if( pTab==0 ) goto delete_from_cleanup; - - /* Figure out if we have any triggers and if the table being - ** deleted from is a view - */ -#ifndef SQLITE_OMIT_TRIGGER - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); - isView = pTab->pSelect!=0; -#else -# define pTrigger 0 -# define isView 0 -#endif -#ifdef SQLITE_OMIT_VIEW -# undef isView -# define isView 0 -#endif - - /* If pTab is really a view, make sure it has been initialized. - */ - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto delete_from_cleanup; - } - - if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ - goto delete_from_cleanup; - } - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDbnDb ); - zDb = db->aDb[iDb].zName; - rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); - assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); - if( rcauth==SQLITE_DENY ){ - goto delete_from_cleanup; - } - assert(!isView || pTrigger); - - /* Assign cursor number to the table and all its indices. - */ - assert( pTabList->nSrc==1 ); - iCur = pTabList->a[0].iCursor = pParse->nTab++; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - pParse->nTab++; - } - - /* Start the view context - */ - if( isView ){ - sqlite3AuthContextPush(pParse, &sContext, pTab->zName); - } - - /* Begin generating code. - */ - v = sqlite3GetVdbe(pParse); - if( v==0 ){ - goto delete_from_cleanup; - } - if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, 1, iDb); - - /* If we are trying to delete from a view, realize that view into - ** a ephemeral table. - */ -#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) - if( isView ){ - sqlite3MaterializeView(pParse, pTab, pWhere, iCur); - } -#endif - - /* Resolve the column names in the WHERE clause. - */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pSrcList = pTabList; - if( sqlite3ResolveExprNames(&sNC, pWhere) ){ - goto delete_from_cleanup; - } - - /* Initialize the counter of the number of rows deleted, if - ** we are counting rows. - */ - if( db->flags & SQLITE_CountRows ){ - memCnt = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); - } - -#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION - /* Special case: A DELETE without a WHERE clause deletes everything. - ** It is easier just to erase the whole table. Prior to version 3.6.5, - ** this optimization caused the row change count (the value returned by - ** API function sqlite3_count_changes) to be set incorrectly. */ - if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) - && 0==sqlite3FkRequired(pParse, pTab, 0, 0) - ){ - assert( !isView ); - sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, - pTab->zName, P4_STATIC); - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - assert( pIdx->pSchema==pTab->pSchema ); - sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); - } - }else -#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ - /* The usual case: There is a WHERE clause so we have to scan through - ** the table and pick which records to delete. - */ - { - int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */ - int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ - int regRowid; /* Actual register containing rowids */ - - /* Collect rowids of every row to be deleted. - */ - sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); - pWInfo = sqlite3WhereBegin( - pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0 - ); - if( pWInfo==0 ) goto delete_from_cleanup; - regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0); - sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid); - if( db->flags & SQLITE_CountRows ){ - sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); - } - sqlite3WhereEnd(pWInfo); - - /* Delete every item whose key was written to the list during the - ** database scan. We have to delete items after the scan is complete - ** because deleting an item can change the scan order. */ - end = sqlite3VdbeMakeLabel(v); - - /* Unless this is a view, open cursors for the table we are - ** deleting from and all its indices. If this is a view, then the - ** only effect this statement has is to fire the INSTEAD OF - ** triggers. */ - if( !isView ){ - sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); - } - - addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid); - - /* Delete the row */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); - sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, OE_Abort); - sqlite3MayAbort(pParse); - }else -#endif - { - int count = (pParse->nested==0); /* True to count changes */ - sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default); - } - - /* End of the delete loop */ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); - sqlite3VdbeResolveLabel(v, end); - - /* Close the cursors open on the table and its indexes. */ - if( !isView && !IsVirtual(pTab) ){ - for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum); - } - sqlite3VdbeAddOp1(v, OP_Close, iCur); - } - } - - /* Update the sqlite_sequence table by storing the content of the - ** maximum rowid counter values recorded while inserting into - ** autoincrement tables. - */ - if( pParse->nested==0 && pParse->pTriggerTab==0 ){ - sqlite3AutoincrementEnd(pParse); - } - - /* Return the number of rows that were deleted. If this routine is - ** generating code because of a call to sqlite3NestedParse(), do not - ** invoke the callback function. - */ - if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ - sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); - } - -delete_from_cleanup: - sqlite3AuthContextPop(&sContext); - sqlite3SrcListDelete(db, pTabList); - sqlite3ExprDelete(db, pWhere); - return; -} -/* Make sure "isView" and other macros defined above are undefined. Otherwise -** thely may interfere with compilation of other functions in this file -** (or in another file, if this file becomes part of the amalgamation). */ -#ifdef isView - #undef isView -#endif -#ifdef pTrigger - #undef pTrigger -#endif - -/* -** This routine generates VDBE code that causes a single row of a -** single table to be deleted. -** -** The VDBE must be in a particular state when this routine is called. -** These are the requirements: -** -** 1. A read/write cursor pointing to pTab, the table containing the row -** to be deleted, must be opened as cursor number $iCur. -** -** 2. Read/write cursors for all indices of pTab must be open as -** cursor number base+i for the i-th index. -** -** 3. The record number of the row to be deleted must be stored in -** memory cell iRowid. -** -** This routine generates code to remove both the table record and all -** index entries that point to that record. -*/ -SQLITE_PRIVATE void sqlite3GenerateRowDelete( - Parse *pParse, /* Parsing context */ - Table *pTab, /* Table containing the row to be deleted */ - int iCur, /* Cursor number for the table */ - int iRowid, /* Memory cell that contains the rowid to delete */ - int count, /* If non-zero, increment the row change counter */ - Trigger *pTrigger, /* List of triggers to (potentially) fire */ - int onconf /* Default ON CONFLICT policy for triggers */ -){ - Vdbe *v = pParse->pVdbe; /* Vdbe */ - int iOld = 0; /* First register in OLD.* array */ - int iLabel; /* Label resolved to end of generated code */ - - /* Vdbe is guaranteed to have been allocated by this stage. */ - assert( v ); - - /* Seek cursor iCur to the row to delete. If this row no longer exists - ** (this can happen if a trigger program has already deleted it), do - ** not attempt to delete it or fire any DELETE triggers. */ - iLabel = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid); - - /* If there are any triggers to fire, allocate a range of registers to - ** use for the old.* references in the triggers. */ - if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){ - u32 mask; /* Mask of OLD.* columns in use */ - int iCol; /* Iterator used while populating OLD.* */ - - /* TODO: Could use temporary registers here. Also could attempt to - ** avoid copying the contents of the rowid register. */ - mask = sqlite3TriggerColmask( - pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf - ); - mask |= sqlite3FkOldmask(pParse, pTab); - iOld = pParse->nMem+1; - pParse->nMem += (1 + pTab->nCol); - - /* Populate the OLD.* pseudo-table register array. These values will be - ** used by any BEFORE and AFTER triggers that exist. */ - sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld); - for(iCol=0; iColnCol; iCol++){ - if( mask==0xffffffff || mask&(1<pSelect==0 ){ - sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0); - sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); - if( count ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); - } - } - - /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to - ** handle rows (possibly in other tables) that refer via a foreign key - ** to the row just deleted. */ - sqlite3FkActions(pParse, pTab, 0, iOld); - - /* Invoke AFTER DELETE trigger programs. */ - sqlite3CodeRowTrigger(pParse, pTrigger, - TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel - ); - - /* Jump here if the row had already been deleted before any BEFORE - ** trigger programs were invoked. Or if a trigger program throws a - ** RAISE(IGNORE) exception. */ - sqlite3VdbeResolveLabel(v, iLabel); -} - -/* -** This routine generates VDBE code that causes the deletion of all -** index entries associated with a single row of a single table. -** -** The VDBE must be in a particular state when this routine is called. -** These are the requirements: -** -** 1. A read/write cursor pointing to pTab, the table containing the row -** to be deleted, must be opened as cursor number "iCur". -** -** 2. Read/write cursors for all indices of pTab must be open as -** cursor number iCur+i for the i-th index. -** -** 3. The "iCur" cursor must be pointing to the row that is to be -** deleted. -*/ -SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( - Parse *pParse, /* Parsing and code generating context */ - Table *pTab, /* Table containing the row to be deleted */ - int iCur, /* Cursor number for the table */ - int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ -){ - int i; - Index *pIdx; - int r1; - - for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue; - r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0); - sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1); - } -} - -/* -** Generate code that will assemble an index key and put it in register -** regOut. The key with be for index pIdx which is an index on pTab. -** iCur is the index of a cursor open on the pTab table and pointing to -** the entry that needs indexing. -** -** Return a register number which is the first in a block of -** registers that holds the elements of the index key. The -** block of registers has already been deallocated by the time -** this routine returns. -*/ -SQLITE_PRIVATE int sqlite3GenerateIndexKey( - Parse *pParse, /* Parsing context */ - Index *pIdx, /* The index for which to generate a key */ - int iCur, /* Cursor number for the pIdx->pTable table */ - int regOut, /* Write the new index key to this register */ - int doMakeRec /* Run the OP_MakeRecord instruction if true */ -){ - Vdbe *v = pParse->pVdbe; - int j; - Table *pTab = pIdx->pTable; - int regBase; - int nCol; - - nCol = pIdx->nColumn; - regBase = sqlite3GetTempRange(pParse, nCol+1); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol); - for(j=0; jaiColumn[j]; - if( idx==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); - sqlite3ColumnDefault(v, pTab, idx, -1); - } - } - if( doMakeRec ){ - const char *zAff; - if( pTab->pSelect - || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt) - ){ - zAff = 0; - }else{ - zAff = sqlite3IndexAffinityStr(v, pIdx); - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); - sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT); - } - sqlite3ReleaseTempRange(pParse, regBase, nCol+1); - return regBase; -} - -/************** End of delete.c **********************************************/ -/************** Begin file func.c ********************************************/ -/* -** 2002 February 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the C functions that implement various SQL -** functions of SQLite. -** -** There is only one exported symbol in this file - the function -** sqliteRegisterBuildinFunctions() found at the bottom of the file. -** All other code has file scope. -*/ -/* #include */ -/* #include */ - -/* -** Return the collating function associated with a function. -*/ -static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ - return context->pColl; -} - -/* -** Indicate that the accumulator load should be skipped on this -** iteration of the aggregate loop. -*/ -static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ - context->skipFlag = 1; -} - -/* -** Implementation of the non-aggregate min() and max() functions -*/ -static void minmaxFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int i; - int mask; /* 0 for min() or 0xffffffff for max() */ - int iBest; - CollSeq *pColl; - - assert( argc>1 ); - mask = sqlite3_user_data(context)==0 ? 0 : -1; - pColl = sqlite3GetFuncCollSeq(context); - assert( pColl ); - assert( mask==-1 || mask==0 ); - iBest = 0; - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - for(i=1; i=0 ){ - testcase( mask==0 ); - iBest = i; - } - } - sqlite3_result_value(context, argv[iBest]); -} - -/* -** Return the type of the argument. -*/ -static void typeofFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - const char *z = 0; - UNUSED_PARAMETER(NotUsed); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_INTEGER: z = "integer"; break; - case SQLITE_TEXT: z = "text"; break; - case SQLITE_FLOAT: z = "real"; break; - case SQLITE_BLOB: z = "blob"; break; - default: z = "null"; break; - } - sqlite3_result_text(context, z, -1, SQLITE_STATIC); -} - - -/* -** Implementation of the length() function -*/ -static void lengthFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int len; - - assert( argc==1 ); - UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_BLOB: - case SQLITE_INTEGER: - case SQLITE_FLOAT: { - sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); - break; - } - case SQLITE_TEXT: { - const unsigned char *z = sqlite3_value_text(argv[0]); - if( z==0 ) return; - len = 0; - while( *z ){ - len++; - SQLITE_SKIP_UTF8(z); - } - sqlite3_result_int(context, len); - break; - } - default: { - sqlite3_result_null(context); - break; - } - } -} - -/* -** Implementation of the abs() function. -** -** IMP: R-23979-26855 The abs(X) function returns the absolute value of -** the numeric argument X. -*/ -static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - assert( argc==1 ); - UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_INTEGER: { - i64 iVal = sqlite3_value_int64(argv[0]); - if( iVal<0 ){ - if( (iVal<<1)==0 ){ - /* IMP: R-35460-15084 If X is the integer -9223372036854775807 then - ** abs(X) throws an integer overflow error since there is no - ** equivalent positive 64-bit two complement value. */ - sqlite3_result_error(context, "integer overflow", -1); - return; - } - iVal = -iVal; - } - sqlite3_result_int64(context, iVal); - break; - } - case SQLITE_NULL: { - /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */ - sqlite3_result_null(context); - break; - } - default: { - /* Because sqlite3_value_double() returns 0.0 if the argument is not - ** something that can be converted into a number, we have: - ** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that - ** cannot be converted to a numeric value. - */ - double rVal = sqlite3_value_double(argv[0]); - if( rVal<0 ) rVal = -rVal; - sqlite3_result_double(context, rVal); - break; - } - } -} - -/* -** Implementation of the instr() function. -** -** instr(haystack,needle) finds the first occurrence of needle -** in haystack and returns the number of previous characters plus 1, -** or 0 if needle does not occur within haystack. -** -** If both haystack and needle are BLOBs, then the result is one more than -** the number of bytes in haystack prior to the first occurrence of needle, -** or 0 if needle never occurs in haystack. -*/ -static void instrFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zHaystack; - const unsigned char *zNeedle; - int nHaystack; - int nNeedle; - int typeHaystack, typeNeedle; - int N = 1; - int isText; - - UNUSED_PARAMETER(argc); - typeHaystack = sqlite3_value_type(argv[0]); - typeNeedle = sqlite3_value_type(argv[1]); - if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return; - nHaystack = sqlite3_value_bytes(argv[0]); - nNeedle = sqlite3_value_bytes(argv[1]); - if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ - zHaystack = sqlite3_value_blob(argv[0]); - zNeedle = sqlite3_value_blob(argv[1]); - isText = 0; - }else{ - zHaystack = sqlite3_value_text(argv[0]); - zNeedle = sqlite3_value_text(argv[1]); - isText = 1; - } - while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){ - N++; - do{ - nHaystack--; - zHaystack++; - }while( isText && (zHaystack[0]&0xc0)==0x80 ); - } - if( nNeedle>nHaystack ) N = 0; - sqlite3_result_int(context, N); -} - -/* -** Implementation of the substr() function. -** -** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. -** p1 is 1-indexed. So substr(x,1,1) returns the first character -** of x. If x is text, then we actually count UTF-8 characters. -** If x is a blob, then we count bytes. -** -** If p1 is negative, then we begin abs(p1) from the end of x[]. -** -** If p2 is negative, return the p2 characters preceeding p1. -*/ -static void substrFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *z; - const unsigned char *z2; - int len; - int p0type; - i64 p1, p2; - int negP2 = 0; - - assert( argc==3 || argc==2 ); - if( sqlite3_value_type(argv[1])==SQLITE_NULL - || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL) - ){ - return; - } - p0type = sqlite3_value_type(argv[0]); - p1 = sqlite3_value_int(argv[1]); - if( p0type==SQLITE_BLOB ){ - len = sqlite3_value_bytes(argv[0]); - z = sqlite3_value_blob(argv[0]); - if( z==0 ) return; - assert( len==sqlite3_value_bytes(argv[0]) ); - }else{ - z = sqlite3_value_text(argv[0]); - if( z==0 ) return; - len = 0; - if( p1<0 ){ - for(z2=z; *z2; len++){ - SQLITE_SKIP_UTF8(z2); - } - } - } - if( argc==3 ){ - p2 = sqlite3_value_int(argv[2]); - if( p2<0 ){ - p2 = -p2; - negP2 = 1; - } - }else{ - p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH]; - } - if( p1<0 ){ - p1 += len; - if( p1<0 ){ - p2 += p1; - if( p2<0 ) p2 = 0; - p1 = 0; - } - }else if( p1>0 ){ - p1--; - }else if( p2>0 ){ - p2--; - } - if( negP2 ){ - p1 -= p2; - if( p1<0 ){ - p2 += p1; - p1 = 0; - } - } - assert( p1>=0 && p2>=0 ); - if( p0type!=SQLITE_BLOB ){ - while( *z && p1 ){ - SQLITE_SKIP_UTF8(z); - p1--; - } - for(z2=z; *z2 && p2; p2--){ - SQLITE_SKIP_UTF8(z2); - } - sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT); - }else{ - if( p1+p2>len ){ - p2 = len-p1; - if( p2<0 ) p2 = 0; - } - sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT); - } -} - -/* -** Implementation of the round() function -*/ -#ifndef SQLITE_OMIT_FLOATING_POINT -static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - int n = 0; - double r; - char *zBuf; - assert( argc==1 || argc==2 ); - if( argc==2 ){ - if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; - n = sqlite3_value_int(argv[1]); - if( n>30 ) n = 30; - if( n<0 ) n = 0; - } - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - r = sqlite3_value_double(argv[0]); - /* If Y==0 and X will fit in a 64-bit int, - ** handle the rounding directly, - ** otherwise use printf. - */ - if( n==0 && r>=0 && r0 ); - testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); - if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - z = 0; - }else{ - z = sqlite3Malloc((int)nByte); - if( !z ){ - sqlite3_result_error_nomem(context); - } - } - return z; -} - -/* -** Implementation of the upper() and lower() SQL functions. -*/ -static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - char *z1; - const char *z2; - int i, n; - UNUSED_PARAMETER(argc); - z2 = (char*)sqlite3_value_text(argv[0]); - n = sqlite3_value_bytes(argv[0]); - /* Verify that the call to _bytes() does not invalidate the _text() pointer */ - assert( z2==(char*)sqlite3_value_text(argv[0]) ); - if( z2 ){ - z1 = contextMalloc(context, ((i64)n)+1); - if( z1 ){ - for(i=0; imatchOne; - u8 matchAll = pInfo->matchAll; - u8 matchSet = pInfo->matchSet; - u8 noCase = pInfo->noCase; - int prevEscape = 0; /* True if the previous character was 'escape' */ - - while( (c = sqlite3Utf8Read(&zPattern))!=0 ){ - if( c==matchAll && !prevEscape ){ - while( (c=sqlite3Utf8Read(&zPattern)) == matchAll - || c == matchOne ){ - if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ - return 0; - } - } - if( c==0 ){ - return 1; - }else if( c==esc ){ - c = sqlite3Utf8Read(&zPattern); - if( c==0 ){ - return 0; - } - }else if( c==matchSet ){ - assert( esc==0 ); /* This is GLOB, not LIKE */ - assert( matchSet<0x80 ); /* '[' is a single-byte character */ - while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){ - SQLITE_SKIP_UTF8(zString); - } - return *zString!=0; - } - while( (c2 = sqlite3Utf8Read(&zString))!=0 ){ - if( noCase ){ - GlogUpperToLower(c2); - GlogUpperToLower(c); - while( c2 != 0 && c2 != c ){ - c2 = sqlite3Utf8Read(&zString); - GlogUpperToLower(c2); - } - }else{ - while( c2 != 0 && c2 != c ){ - c2 = sqlite3Utf8Read(&zString); - } - } - if( c2==0 ) return 0; - if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; - } - return 0; - }else if( c==matchOne && !prevEscape ){ - if( sqlite3Utf8Read(&zString)==0 ){ - return 0; - } - }else if( c==matchSet ){ - u32 prior_c = 0; - assert( esc==0 ); /* This only occurs for GLOB, not LIKE */ - seen = 0; - invert = 0; - c = sqlite3Utf8Read(&zString); - if( c==0 ) return 0; - c2 = sqlite3Utf8Read(&zPattern); - if( c2=='^' ){ - invert = 1; - c2 = sqlite3Utf8Read(&zPattern); - } - if( c2==']' ){ - if( c==']' ) seen = 1; - c2 = sqlite3Utf8Read(&zPattern); - } - while( c2 && c2!=']' ){ - if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ - c2 = sqlite3Utf8Read(&zPattern); - if( c>=prior_c && c<=c2 ) seen = 1; - prior_c = 0; - }else{ - if( c==c2 ){ - seen = 1; - } - prior_c = c2; - } - c2 = sqlite3Utf8Read(&zPattern); - } - if( c2==0 || (seen ^ invert)==0 ){ - return 0; - } - }else if( esc==c && !prevEscape ){ - prevEscape = 1; - }else{ - c2 = sqlite3Utf8Read(&zString); - if( noCase ){ - GlogUpperToLower(c); - GlogUpperToLower(c2); - } - if( c!=c2 ){ - return 0; - } - prevEscape = 0; - } - } - return *zString==0; -} - -/* -** The sqlite3_strglob() interface. -*/ -SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ - return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0; -} - -/* -** Count the number of times that the LIKE operator (or GLOB which is -** just a variation of LIKE) gets called. This is used for testing -** only. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_like_count = 0; -#endif - - -/* -** Implementation of the like() SQL function. This function implements -** the build-in LIKE operator. The first argument to the function is the -** pattern and the second argument is the string. So, the SQL statements: -** -** A LIKE B -** -** is implemented as like(B,A). -** -** This same function (with a different compareInfo structure) computes -** the GLOB operator. -*/ -static void likeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zA, *zB; - u32 escape = 0; - int nPat; - sqlite3 *db = sqlite3_context_db_handle(context); - - zB = sqlite3_value_text(argv[0]); - zA = sqlite3_value_text(argv[1]); - - /* Limit the length of the LIKE or GLOB pattern to avoid problems - ** of deep recursion and N*N behavior in patternCompare(). - */ - nPat = sqlite3_value_bytes(argv[0]); - testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ); - testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 ); - if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){ - sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); - return; - } - assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */ - - if( argc==3 ){ - /* The escape character string must consist of a single UTF-8 character. - ** Otherwise, return an error. - */ - const unsigned char *zEsc = sqlite3_value_text(argv[2]); - if( zEsc==0 ) return; - if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ - sqlite3_result_error(context, - "ESCAPE expression must be a single character", -1); - return; - } - escape = sqlite3Utf8Read(&zEsc); - } - if( zA && zB ){ - struct compareInfo *pInfo = sqlite3_user_data(context); -#ifdef SQLITE_TEST - sqlite3_like_count++; -#endif - - sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)); - } -} - -/* -** Implementation of the NULLIF(x,y) function. The result is the first -** argument if the arguments are different. The result is NULL if the -** arguments are equal to each other. -*/ -static void nullifFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - CollSeq *pColl = sqlite3GetFuncCollSeq(context); - UNUSED_PARAMETER(NotUsed); - if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){ - sqlite3_result_value(context, argv[0]); - } -} - -/* -** Implementation of the sqlite_version() function. The result is the version -** of the SQLite library that is running. -*/ -static void versionFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **NotUsed2 -){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - /* IMP: R-48699-48617 This function is an SQL wrapper around the - ** sqlite3_libversion() C-interface. */ - sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC); -} - -/* -** Implementation of the sqlite_source_id() function. The result is a string -** that identifies the particular version of the source code used to build -** SQLite. -*/ -static void sourceidFunc( - sqlite3_context *context, - int NotUsed, - sqlite3_value **NotUsed2 -){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - /* IMP: R-24470-31136 This function is an SQL wrapper around the - ** sqlite3_sourceid() C interface. */ - sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC); -} - -/* -** Implementation of the sqlite_log() function. This is a wrapper around -** sqlite3_log(). The return value is NULL. The function exists purely for -** its side-effects. -*/ -static void errlogFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(context); - sqlite3_log(sqlite3_value_int(argv[0]), "%s", sqlite3_value_text(argv[1])); -} - -/* -** Implementation of the sqlite_compileoption_used() function. -** The result is an integer that identifies if the compiler option -** was used to build SQLite. -*/ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -static void compileoptionusedFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *zOptName; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL - ** function is a wrapper around the sqlite3_compileoption_used() C/C++ - ** function. - */ - if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){ - sqlite3_result_int(context, sqlite3_compileoption_used(zOptName)); - } -} -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -/* -** Implementation of the sqlite_compileoption_get() function. -** The result is a string that identifies the compiler options -** used to build SQLite. -*/ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -static void compileoptiongetFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int n; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function - ** is a wrapper around the sqlite3_compileoption_get() C/C++ function. - */ - n = sqlite3_value_int(argv[0]); - sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC); -} -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -/* Array for converting from half-bytes (nybbles) into ASCII hex -** digits. */ -static const char hexdigits[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -/* -** EXPERIMENTAL - This is not an official function. The interface may -** change. This function may disappear. Do not write code that depends -** on this function. -** -** Implementation of the QUOTE() function. This function takes a single -** argument. If the argument is numeric, the return value is the same as -** the argument. If the argument is NULL, the return value is the string -** "NULL". Otherwise, the argument is enclosed in single quotes with -** single-quote escapes. -*/ -static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - assert( argc==1 ); - UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_FLOAT: { - double r1, r2; - char zBuf[50]; - r1 = sqlite3_value_double(argv[0]); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1); - sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8); - if( r1!=r2 ){ - sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1); - } - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); - break; - } - case SQLITE_INTEGER: { - sqlite3_result_value(context, argv[0]); - break; - } - case SQLITE_BLOB: { - char *zText = 0; - char const *zBlob = sqlite3_value_blob(argv[0]); - int nBlob = sqlite3_value_bytes(argv[0]); - assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ - zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); - if( zText ){ - int i; - for(i=0; i>4)&0x0F]; - zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F]; - } - zText[(nBlob*2)+2] = '\''; - zText[(nBlob*2)+3] = '\0'; - zText[0] = 'X'; - zText[1] = '\''; - sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); - sqlite3_free(zText); - } - break; - } - case SQLITE_TEXT: { - int i,j; - u64 n; - const unsigned char *zArg = sqlite3_value_text(argv[0]); - char *z; - - if( zArg==0 ) return; - for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } - z = contextMalloc(context, ((i64)i)+((i64)n)+3); - if( z ){ - z[0] = '\''; - for(i=0, j=1; zArg[i]; i++){ - z[j++] = zArg[i]; - if( zArg[i]=='\'' ){ - z[j++] = '\''; - } - } - z[j++] = '\''; - z[j] = 0; - sqlite3_result_text(context, z, j, sqlite3_free); - } - break; - } - default: { - assert( sqlite3_value_type(argv[0])==SQLITE_NULL ); - sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); - break; - } - } -} - -/* -** The unicode() function. Return the integer unicode code-point value -** for the first character of the input string. -*/ -static void unicodeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *z = sqlite3_value_text(argv[0]); - (void)argc; - if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z)); -} - -/* -** The char() function takes zero or more arguments, each of which is -** an integer. It constructs a string where each character of the string -** is the unicode character for the corresponding integer argument. -*/ -static void charFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - unsigned char *z, *zOut; - int i; - zOut = z = sqlite3_malloc( argc*4 ); - if( z==0 ){ - sqlite3_result_error_nomem(context); - return; - } - for(i=0; i0x10ffff ) x = 0xfffd; - c = (unsigned)(x & 0x1fffff); - if( c<0x00080 ){ - *zOut++ = (u8)(c&0xFF); - }else if( c<0x00800 ){ - *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); - *zOut++ = 0x80 + (u8)(c & 0x3F); - }else if( c<0x10000 ){ - *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); - *zOut++ = 0x80 + (u8)(c & 0x3F); - }else{ - *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); - *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); - *zOut++ = 0x80 + (u8)(c & 0x3F); - } \ - } - sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free); -} - -/* -** The hex() function. Interpret the argument as a blob. Return -** a hexadecimal rendering as text. -*/ -static void hexFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int i, n; - const unsigned char *pBlob; - char *zHex, *z; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - pBlob = sqlite3_value_blob(argv[0]); - n = sqlite3_value_bytes(argv[0]); - assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ - z = zHex = contextMalloc(context, ((i64)n)*2 + 1); - if( zHex ){ - for(i=0; i>4)&0xf]; - *(z++) = hexdigits[c&0xf]; - } - *z = 0; - sqlite3_result_text(context, zHex, n*2, sqlite3_free); - } -} - -/* -** The zeroblob(N) function returns a zero-filled blob of size N bytes. -*/ -static void zeroblobFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - i64 n; - sqlite3 *db = sqlite3_context_db_handle(context); - assert( argc==1 ); - UNUSED_PARAMETER(argc); - n = sqlite3_value_int64(argv[0]); - testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); - if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - }else{ - sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */ - } -} - -/* -** The replace() function. Three arguments are all strings: call -** them A, B, and C. The result is also a string which is derived -** from A by replacing every occurance of B with C. The match -** must be exact. Collating sequences are not used. -*/ -static void replaceFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zStr; /* The input string A */ - const unsigned char *zPattern; /* The pattern string B */ - const unsigned char *zRep; /* The replacement string C */ - unsigned char *zOut; /* The output */ - int nStr; /* Size of zStr */ - int nPattern; /* Size of zPattern */ - int nRep; /* Size of zRep */ - i64 nOut; /* Maximum size of zOut */ - int loopLimit; /* Last zStr[] that might match zPattern[] */ - int i, j; /* Loop counters */ - - assert( argc==3 ); - UNUSED_PARAMETER(argc); - zStr = sqlite3_value_text(argv[0]); - if( zStr==0 ) return; - nStr = sqlite3_value_bytes(argv[0]); - assert( zStr==sqlite3_value_text(argv[0]) ); /* No encoding change */ - zPattern = sqlite3_value_text(argv[1]); - if( zPattern==0 ){ - assert( sqlite3_value_type(argv[1])==SQLITE_NULL - || sqlite3_context_db_handle(context)->mallocFailed ); - return; - } - if( zPattern[0]==0 ){ - assert( sqlite3_value_type(argv[1])!=SQLITE_NULL ); - sqlite3_result_value(context, argv[0]); - return; - } - nPattern = sqlite3_value_bytes(argv[1]); - assert( zPattern==sqlite3_value_text(argv[1]) ); /* No encoding change */ - zRep = sqlite3_value_text(argv[2]); - if( zRep==0 ) return; - nRep = sqlite3_value_bytes(argv[2]); - assert( zRep==sqlite3_value_text(argv[2]) ); - nOut = nStr + 1; - assert( nOutaLimit[SQLITE_LIMIT_LENGTH] ); - testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); - if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - sqlite3_free(zOut); - return; - } - zOld = zOut; - zOut = sqlite3_realloc(zOut, (int)nOut); - if( zOut==0 ){ - sqlite3_result_error_nomem(context); - sqlite3_free(zOld); - return; - } - memcpy(&zOut[j], zRep, nRep); - j += nRep; - i += nPattern-1; - } - } - assert( j+nStr-i+1==nOut ); - memcpy(&zOut[j], &zStr[i], nStr-i); - j += nStr - i; - assert( j<=nOut ); - zOut[j] = 0; - sqlite3_result_text(context, (char*)zOut, j, sqlite3_free); -} - -/* -** Implementation of the TRIM(), LTRIM(), and RTRIM() functions. -** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both. -*/ -static void trimFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zIn; /* Input string */ - const unsigned char *zCharSet; /* Set of characters to trim */ - int nIn; /* Number of bytes in input */ - int flags; /* 1: trimleft 2: trimright 3: trim */ - int i; /* Loop counter */ - unsigned char *aLen = 0; /* Length of each character in zCharSet */ - unsigned char **azChar = 0; /* Individual characters in zCharSet */ - int nChar; /* Number of characters in zCharSet */ - - if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - return; - } - zIn = sqlite3_value_text(argv[0]); - if( zIn==0 ) return; - nIn = sqlite3_value_bytes(argv[0]); - assert( zIn==sqlite3_value_text(argv[0]) ); - if( argc==1 ){ - static const unsigned char lenOne[] = { 1 }; - static unsigned char * const azOne[] = { (u8*)" " }; - nChar = 1; - aLen = (u8*)lenOne; - azChar = (unsigned char **)azOne; - zCharSet = 0; - }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){ - return; - }else{ - const unsigned char *z; - for(z=zCharSet, nChar=0; *z; nChar++){ - SQLITE_SKIP_UTF8(z); - } - if( nChar>0 ){ - azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1)); - if( azChar==0 ){ - return; - } - aLen = (unsigned char*)&azChar[nChar]; - for(z=zCharSet, nChar=0; *z; nChar++){ - azChar[nChar] = (unsigned char *)z; - SQLITE_SKIP_UTF8(z); - aLen[nChar] = (u8)(z - azChar[nChar]); - } - } - } - if( nChar>0 ){ - flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context)); - if( flags & 1 ){ - while( nIn>0 ){ - int len = 0; - for(i=0; i=nChar ) break; - zIn += len; - nIn -= len; - } - } - if( flags & 2 ){ - while( nIn>0 ){ - int len = 0; - for(i=0; i=nChar ) break; - nIn -= len; - } - } - if( zCharSet ){ - sqlite3_free(azChar); - } - } - sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); -} - - -/* IMP: R-25361-16150 This function is omitted from SQLite by default. It -** is only available if the SQLITE_SOUNDEX compile-time option is used -** when SQLite is built. -*/ -#ifdef SQLITE_SOUNDEX -/* -** Compute the soundex encoding of a word. -** -** IMP: R-59782-00072 The soundex(X) function returns a string that is the -** soundex encoding of the string X. -*/ -static void soundexFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - char zResult[8]; - const u8 *zIn; - int i, j; - static const unsigned char iCode[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, - 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, - 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, - }; - assert( argc==1 ); - zIn = (u8*)sqlite3_value_text(argv[0]); - if( zIn==0 ) zIn = (u8*)""; - for(i=0; zIn[i] && !sqlite3Isalpha(zIn[i]); i++){} - if( zIn[i] ){ - u8 prevcode = iCode[zIn[i]&0x7f]; - zResult[0] = sqlite3Toupper(zIn[i]); - for(j=1; j<4 && zIn[i]; i++){ - int code = iCode[zIn[i]&0x7f]; - if( code>0 ){ - if( code!=prevcode ){ - prevcode = code; - zResult[j++] = code + '0'; - } - }else{ - prevcode = 0; - } - } - while( j<4 ){ - zResult[j++] = '0'; - } - zResult[j] = 0; - sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); - }else{ - /* IMP: R-64894-50321 The string "?000" is returned if the argument - ** is NULL or contains no ASCII alphabetic characters. */ - sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); - } -} -#endif /* SQLITE_SOUNDEX */ - -#ifndef SQLITE_OMIT_LOAD_EXTENSION -/* -** A function that loads a shared-library extension then returns NULL. -*/ -static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ - const char *zFile = (const char *)sqlite3_value_text(argv[0]); - const char *zProc; - sqlite3 *db = sqlite3_context_db_handle(context); - char *zErrMsg = 0; - - if( argc==2 ){ - zProc = (const char *)sqlite3_value_text(argv[1]); - }else{ - zProc = 0; - } - if( zFile && sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){ - sqlite3_result_error(context, zErrMsg, -1); - sqlite3_free(zErrMsg); - } -} -#endif - - -/* -** An instance of the following structure holds the context of a -** sum() or avg() aggregate computation. -*/ -typedef struct SumCtx SumCtx; -struct SumCtx { - double rSum; /* Floating point sum */ - i64 iSum; /* Integer sum */ - i64 cnt; /* Number of elements summed */ - u8 overflow; /* True if integer overflow seen */ - u8 approx; /* True if non-integer value was input to the sum */ -}; - -/* -** Routines used to compute the sum, average, and total. -** -** The SUM() function follows the (broken) SQL standard which means -** that it returns NULL if it sums over no inputs. TOTAL returns -** 0.0 in that case. In addition, TOTAL always returns a float where -** SUM might return an integer if it never encounters a floating point -** value. TOTAL never fails, but SUM might through an exception if -** it overflows an integer. -*/ -static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ - SumCtx *p; - int type; - assert( argc==1 ); - UNUSED_PARAMETER(argc); - p = sqlite3_aggregate_context(context, sizeof(*p)); - type = sqlite3_value_numeric_type(argv[0]); - if( p && type!=SQLITE_NULL ){ - p->cnt++; - if( type==SQLITE_INTEGER ){ - i64 v = sqlite3_value_int64(argv[0]); - p->rSum += v; - if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){ - p->overflow = 1; - } - }else{ - p->rSum += sqlite3_value_double(argv[0]); - p->approx = 1; - } - } -} -static void sumFinalize(sqlite3_context *context){ - SumCtx *p; - p = sqlite3_aggregate_context(context, 0); - if( p && p->cnt>0 ){ - if( p->overflow ){ - sqlite3_result_error(context,"integer overflow",-1); - }else if( p->approx ){ - sqlite3_result_double(context, p->rSum); - }else{ - sqlite3_result_int64(context, p->iSum); - } - } -} -static void avgFinalize(sqlite3_context *context){ - SumCtx *p; - p = sqlite3_aggregate_context(context, 0); - if( p && p->cnt>0 ){ - sqlite3_result_double(context, p->rSum/(double)p->cnt); - } -} -static void totalFinalize(sqlite3_context *context){ - SumCtx *p; - p = sqlite3_aggregate_context(context, 0); - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - sqlite3_result_double(context, p ? p->rSum : (double)0); -} - -/* -** The following structure keeps track of state information for the -** count() aggregate function. -*/ -typedef struct CountCtx CountCtx; -struct CountCtx { - i64 n; -}; - -/* -** Routines to implement the count() aggregate function. -*/ -static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ - CountCtx *p; - p = sqlite3_aggregate_context(context, sizeof(*p)); - if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ - p->n++; - } - -#ifndef SQLITE_OMIT_DEPRECATED - /* The sqlite3_aggregate_count() function is deprecated. But just to make - ** sure it still operates correctly, verify that its count agrees with our - ** internal count when using count(*) and when the total count can be - ** expressed as a 32-bit integer. */ - assert( argc==1 || p==0 || p->n>0x7fffffff - || p->n==sqlite3_aggregate_count(context) ); -#endif -} -static void countFinalize(sqlite3_context *context){ - CountCtx *p; - p = sqlite3_aggregate_context(context, 0); - sqlite3_result_int64(context, p ? p->n : 0); -} - -/* -** Routines to implement min() and max() aggregate functions. -*/ -static void minmaxStep( - sqlite3_context *context, - int NotUsed, - sqlite3_value **argv -){ - Mem *pArg = (Mem *)argv[0]; - Mem *pBest; - UNUSED_PARAMETER(NotUsed); - - pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); - if( !pBest ) return; - - if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); - }else if( pBest->flags ){ - int max; - int cmp; - CollSeq *pColl = sqlite3GetFuncCollSeq(context); - /* This step function is used for both the min() and max() aggregates, - ** the only difference between the two being that the sense of the - ** comparison is inverted. For the max() aggregate, the - ** sqlite3_user_data() function returns (void *)-1. For min() it - ** returns (void *)db, where db is the sqlite3* database pointer. - ** Therefore the next statement sets variable 'max' to 1 for the max() - ** aggregate, or 0 for min(). - */ - max = sqlite3_user_data(context)!=0; - cmp = sqlite3MemCompare(pBest, pArg, pColl); - if( (max && cmp<0) || (!max && cmp>0) ){ - sqlite3VdbeMemCopy(pBest, pArg); - }else{ - sqlite3SkipAccumulatorLoad(context); - } - }else{ - sqlite3VdbeMemCopy(pBest, pArg); - } -} -static void minMaxFinalize(sqlite3_context *context){ - sqlite3_value *pRes; - pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); - if( pRes ){ - if( pRes->flags ){ - sqlite3_result_value(context, pRes); - } - sqlite3VdbeMemRelease(pRes); - } -} - -/* -** group_concat(EXPR, ?SEPARATOR?) -*/ -static void groupConcatStep( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const char *zVal; - StrAccum *pAccum; - const char *zSep; - int nVal, nSep; - assert( argc==1 || argc==2 ); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); - - if( pAccum ){ - sqlite3 *db = sqlite3_context_db_handle(context); - int firstTerm = pAccum->useMalloc==0; - pAccum->useMalloc = 2; - pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; - if( !firstTerm ){ - if( argc==2 ){ - zSep = (char*)sqlite3_value_text(argv[1]); - nSep = sqlite3_value_bytes(argv[1]); - }else{ - zSep = ","; - nSep = 1; - } - sqlite3StrAccumAppend(pAccum, zSep, nSep); - } - zVal = (char*)sqlite3_value_text(argv[0]); - nVal = sqlite3_value_bytes(argv[0]); - sqlite3StrAccumAppend(pAccum, zVal, nVal); - } -} -static void groupConcatFinalize(sqlite3_context *context){ - StrAccum *pAccum; - pAccum = sqlite3_aggregate_context(context, 0); - if( pAccum ){ - if( pAccum->tooBig ){ - sqlite3_result_error_toobig(context); - }else if( pAccum->mallocFailed ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, - sqlite3_free); - } - } -} - -/* -** This routine does per-connection function registration. Most -** of the built-in functions above are part of the global function set. -** This routine only deals with those that are not global. -*/ -SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ - int rc = sqlite3_overload_function(db, "MATCH", 2); - assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); - if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; - } -} - -/* -** Set the LIKEOPT flag on the 2-argument function with the given name. -*/ -static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){ - FuncDef *pDef; - pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName), - 2, SQLITE_UTF8, 0); - if( ALWAYS(pDef) ){ - pDef->flags = flagVal; - } -} - -/* -** Register the built-in LIKE and GLOB functions. The caseSensitive -** parameter determines whether or not the LIKE operator is case -** sensitive. GLOB is always case sensitive. -*/ -SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ - struct compareInfo *pInfo; - if( caseSensitive ){ - pInfo = (struct compareInfo*)&likeInfoAlt; - }else{ - pInfo = (struct compareInfo*)&likeInfoNorm; - } - sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); - sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); - sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, - (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0); - setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); - setLikeOptFlag(db, "like", - caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); -} - -/* -** pExpr points to an expression which implements a function. If -** it is appropriate to apply the LIKE optimization to that function -** then set aWc[0] through aWc[2] to the wildcard characters and -** return TRUE. If the function is not a LIKE-style function then -** return FALSE. -*/ -SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ - FuncDef *pDef; - if( pExpr->op!=TK_FUNCTION - || !pExpr->x.pList - || pExpr->x.pList->nExpr!=2 - ){ - return 0; - } - assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pDef = sqlite3FindFunction(db, pExpr->u.zToken, - sqlite3Strlen30(pExpr->u.zToken), - 2, SQLITE_UTF8, 0); - if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ - return 0; - } - - /* The memcpy() statement assumes that the wildcard characters are - ** the first three statements in the compareInfo structure. The - ** asserts() that follow verify that assumption - */ - memcpy(aWc, pDef->pUserData, 3); - assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll ); - assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne ); - assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet ); - *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0; - return 1; -} - -/* -** All all of the FuncDef structures in the aBuiltinFunc[] array above -** to the global function hash table. This occurs at start-time (as -** a consequence of calling sqlite3_initialize()). -** -** After this routine runs -*/ -SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ - /* - ** The following array holds FuncDef structures for all of the functions - ** defined in this file. - ** - ** The array cannot be constant since changes are made to the - ** FuncDef.pHash elements at start-time. The elements of this array - ** are read-only after initialization is complete. - */ - static SQLITE_WSD FuncDef aBuiltinFunc[] = { - FUNCTION(ltrim, 1, 1, 0, trimFunc ), - FUNCTION(ltrim, 2, 1, 0, trimFunc ), - FUNCTION(rtrim, 1, 2, 0, trimFunc ), - FUNCTION(rtrim, 2, 2, 0, trimFunc ), - FUNCTION(trim, 1, 3, 0, trimFunc ), - FUNCTION(trim, 2, 3, 0, trimFunc ), - FUNCTION(min, -1, 0, 1, minmaxFunc ), - FUNCTION(min, 0, 0, 1, 0 ), - AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ), - FUNCTION(max, -1, 1, 1, minmaxFunc ), - FUNCTION(max, 0, 1, 1, 0 ), - AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), - FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), - FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), - FUNCTION(instr, 2, 0, 0, instrFunc ), - FUNCTION(substr, 2, 0, 0, substrFunc ), - FUNCTION(substr, 3, 0, 0, substrFunc ), - FUNCTION(unicode, 1, 0, 0, unicodeFunc ), - FUNCTION(char, -1, 0, 0, charFunc ), - FUNCTION(abs, 1, 0, 0, absFunc ), -#ifndef SQLITE_OMIT_FLOATING_POINT - FUNCTION(round, 1, 0, 0, roundFunc ), - FUNCTION(round, 2, 0, 0, roundFunc ), -#endif - FUNCTION(upper, 1, 0, 0, upperFunc ), - FUNCTION(lower, 1, 0, 0, lowerFunc ), - FUNCTION(coalesce, 1, 0, 0, 0 ), - FUNCTION(coalesce, 0, 0, 0, 0 ), - FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE), - FUNCTION(hex, 1, 0, 0, hexFunc ), - FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE), - FUNCTION(random, 0, 0, 0, randomFunc ), - FUNCTION(randomblob, 1, 0, 0, randomBlob ), - FUNCTION(nullif, 2, 0, 1, nullifFunc ), - FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), - FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), - FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), - FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - FUNCTION(quote, 1, 0, 0, quoteFunc ), - FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), - FUNCTION(changes, 0, 0, 0, changes ), - FUNCTION(total_changes, 0, 0, 0, total_changes ), - FUNCTION(replace, 3, 0, 0, replaceFunc ), - FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), - #ifdef SQLITE_SOUNDEX - FUNCTION(soundex, 1, 0, 0, soundexFunc ), - #endif - #ifndef SQLITE_OMIT_LOAD_EXTENSION - FUNCTION(load_extension, 1, 0, 0, loadExt ), - FUNCTION(load_extension, 2, 0, 0, loadExt ), - #endif - AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), - AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), - AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), - /* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */ - {0,SQLITE_UTF8,SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0}, - AGGREGATE(count, 1, 0, 0, countStep, countFinalize ), - AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize), - AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), - - LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), - #ifdef SQLITE_CASE_SENSITIVE_LIKE - LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), - LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), - #else - LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE), - LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE), - #endif - }; - - int i; - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); - FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc); - - for(i=0; idb->mallocFailed flag is set. -*/ -SQLITE_PRIVATE int sqlite3FkLocateIndex( - Parse *pParse, /* Parse context to store any error in */ - Table *pParent, /* Parent table of FK constraint pFKey */ - FKey *pFKey, /* Foreign key to find index for */ - Index **ppIdx, /* OUT: Unique index on parent table */ - int **paiCol /* OUT: Map of index columns in pFKey */ -){ - Index *pIdx = 0; /* Value to return via *ppIdx */ - int *aiCol = 0; /* Value to return via *paiCol */ - int nCol = pFKey->nCol; /* Number of columns in parent key */ - char *zKey = pFKey->aCol[0].zCol; /* Name of left-most parent key column */ - - /* The caller is responsible for zeroing output parameters. */ - assert( ppIdx && *ppIdx==0 ); - assert( !paiCol || *paiCol==0 ); - assert( pParse ); - - /* If this is a non-composite (single column) foreign key, check if it - ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx - ** and *paiCol set to zero and return early. - ** - ** Otherwise, for a composite foreign key (more than one column), allocate - ** space for the aiCol array (returned via output parameter *paiCol). - ** Non-composite foreign keys do not require the aiCol array. - */ - if( nCol==1 ){ - /* The FK maps to the IPK if any of the following are true: - ** - ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly - ** mapped to the primary key of table pParent, or - ** 2) The FK is explicitly mapped to a column declared as INTEGER - ** PRIMARY KEY. - */ - if( pParent->iPKey>=0 ){ - if( !zKey ) return 0; - if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0; - } - }else if( paiCol ){ - assert( nCol>1 ); - aiCol = (int *)sqlite3DbMallocRaw(pParse->db, nCol*sizeof(int)); - if( !aiCol ) return 1; - *paiCol = aiCol; - } - - for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){ - /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number - ** of columns. If each indexed column corresponds to a foreign key - ** column of pFKey, then this index is a winner. */ - - if( zKey==0 ){ - /* If zKey is NULL, then this foreign key is implicitly mapped to - ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be - ** identified by the test (Index.autoIndex==2). */ - if( pIdx->autoIndex==2 ){ - if( aiCol ){ - int i; - for(i=0; iaCol[i].iFrom; - } - break; - } - }else{ - /* If zKey is non-NULL, then this foreign key was declared to - ** map to an explicit list of columns in table pParent. Check if this - ** index matches those columns. Also, check that the index uses - ** the default collation sequences for each column. */ - int i, j; - for(i=0; iaiColumn[i]; /* Index of column in parent tbl */ - char *zDfltColl; /* Def. collation for column */ - char *zIdxCol; /* Name of indexed column */ - - /* If the index uses a collation sequence that is different from - ** the default collation sequence for the column, this index is - ** unusable. Bail out early in this case. */ - zDfltColl = pParent->aCol[iCol].zColl; - if( !zDfltColl ){ - zDfltColl = "BINARY"; - } - if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; - - zIdxCol = pParent->aCol[iCol].zName; - for(j=0; jaCol[j].zCol, zIdxCol)==0 ){ - if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom; - break; - } - } - if( j==nCol ) break; - } - if( i==nCol ) break; /* pIdx is usable */ - } - } - } - - if( !pIdx ){ - if( !pParse->disableTriggers ){ - sqlite3ErrorMsg(pParse, - "foreign key mismatch - \"%w\" referencing \"%w\"", - pFKey->pFrom->zName, pFKey->zTo); - } - sqlite3DbFree(pParse->db, aiCol); - return 1; - } - - *ppIdx = pIdx; - return 0; -} - -/* -** This function is called when a row is inserted into or deleted from the -** child table of foreign key constraint pFKey. If an SQL UPDATE is executed -** on the child table of pFKey, this function is invoked twice for each row -** affected - once to "delete" the old row, and then again to "insert" the -** new row. -** -** Each time it is called, this function generates VDBE code to locate the -** row in the parent table that corresponds to the row being inserted into -** or deleted from the child table. If the parent row can be found, no -** special action is taken. Otherwise, if the parent row can *not* be -** found in the parent table: -** -** Operation | FK type | Action taken -** -------------------------------------------------------------------------- -** INSERT immediate Increment the "immediate constraint counter". -** -** DELETE immediate Decrement the "immediate constraint counter". -** -** INSERT deferred Increment the "deferred constraint counter". -** -** DELETE deferred Decrement the "deferred constraint counter". -** -** These operations are identified in the comment at the top of this file -** (fkey.c) as "I.1" and "D.1". -*/ -static void fkLookupParent( - Parse *pParse, /* Parse context */ - int iDb, /* Index of database housing pTab */ - Table *pTab, /* Parent table of FK pFKey */ - Index *pIdx, /* Unique index on parent key columns in pTab */ - FKey *pFKey, /* Foreign key constraint */ - int *aiCol, /* Map from parent key columns to child table columns */ - int regData, /* Address of array containing child table row */ - int nIncr, /* Increment constraint counter by this */ - int isIgnore /* If true, pretend pTab contains all NULL values */ -){ - int i; /* Iterator variable */ - Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */ - int iCur = pParse->nTab - 1; /* Cursor number to use */ - int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */ - - /* If nIncr is less than zero, then check at runtime if there are any - ** outstanding constraints to resolve. If there are not, there is no need - ** to check if deleting this row resolves any outstanding violations. - ** - ** Check if any of the key columns in the child table row are NULL. If - ** any are, then the constraint is considered satisfied. No need to - ** search for a matching row in the parent table. */ - if( nIncr<0 ){ - sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk); - } - for(i=0; inCol; i++){ - int iReg = aiCol[i] + regData + 1; - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); - } - - if( isIgnore==0 ){ - if( pIdx==0 ){ - /* If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY - ** column of the parent table (table pTab). */ - int iMustBeInt; /* Address of MustBeInt instruction */ - int regTemp = sqlite3GetTempReg(pParse); - - /* Invoke MustBeInt to coerce the child key value to an integer (i.e. - ** apply the affinity of the parent key). If this fails, then there - ** is no matching parent key. Before using MustBeInt, make a copy of - ** the value. Otherwise, the value inserted into the child key column - ** will have INTEGER affinity applied to it, which may not be correct. */ - sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp); - iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0); - - /* If the parent table is the same as the child table, and we are about - ** to increment the constraint-counter (i.e. this is an INSERT operation), - ** then check if the row being inserted matches itself. If so, do not - ** increment the constraint-counter. */ - if( pTab==pFKey->pFrom && nIncr==1 ){ - sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp); - } - - sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp); - sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - sqlite3VdbeJumpHere(v, iMustBeInt); - sqlite3ReleaseTempReg(pParse, regTemp); - }else{ - int nCol = pFKey->nCol; - int regTemp = sqlite3GetTempRange(pParse, nCol); - int regRec = sqlite3GetTempReg(pParse); - KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); - - sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); - sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); - for(i=0; ipFrom && nIncr==1 ){ - int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1; - for(i=0; iaiColumn[i]+1+regData; - assert( aiCol[i]!=pTab->iPKey ); - if( pIdx->aiColumn[i]==pTab->iPKey ){ - /* The parent key is a composite key that includes the IPK column */ - iParent = regData; - } - sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); - sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); - } - sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk); - } - - sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec); - sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); - sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); - - sqlite3ReleaseTempReg(pParse, regRec); - sqlite3ReleaseTempRange(pParse, regTemp, nCol); - } - } - - if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ - /* Special case: If this is an INSERT statement that will insert exactly - ** one row into the table, raise a constraint immediately instead of - ** incrementing a counter. This is necessary as the VM code is being - ** generated for will not open a statement transaction. */ - assert( nIncr==1 ); - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, - OE_Abort, "foreign key constraint failed", P4_STATIC - ); - }else{ - if( nIncr>0 && pFKey->isDeferred==0 ){ - sqlite3ParseToplevel(pParse)->mayAbort = 1; - } - sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); - } - - sqlite3VdbeResolveLabel(v, iOk); - sqlite3VdbeAddOp1(v, OP_Close, iCur); -} - -/* -** This function is called to generate code executed when a row is deleted -** from the parent table of foreign key constraint pFKey and, if pFKey is -** deferred, when a row is inserted into the same table. When generating -** code for an SQL UPDATE operation, this function may be called twice - -** once to "delete" the old row and once to "insert" the new row. -** -** The code generated by this function scans through the rows in the child -** table that correspond to the parent table row being deleted or inserted. -** For each child row found, one of the following actions is taken: -** -** Operation | FK type | Action taken -** -------------------------------------------------------------------------- -** DELETE immediate Increment the "immediate constraint counter". -** Or, if the ON (UPDATE|DELETE) action is RESTRICT, -** throw a "foreign key constraint failed" exception. -** -** INSERT immediate Decrement the "immediate constraint counter". -** -** DELETE deferred Increment the "deferred constraint counter". -** Or, if the ON (UPDATE|DELETE) action is RESTRICT, -** throw a "foreign key constraint failed" exception. -** -** INSERT deferred Decrement the "deferred constraint counter". -** -** These operations are identified in the comment at the top of this file -** (fkey.c) as "I.2" and "D.2". -*/ -static void fkScanChildren( - Parse *pParse, /* Parse context */ - SrcList *pSrc, /* SrcList containing the table to scan */ - Table *pTab, - Index *pIdx, /* Foreign key index */ - FKey *pFKey, /* Foreign key relationship */ - int *aiCol, /* Map from pIdx cols to child table cols */ - int regData, /* Referenced table data starts here */ - int nIncr /* Amount to increment deferred counter by */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - int i; /* Iterator variable */ - Expr *pWhere = 0; /* WHERE clause to scan with */ - NameContext sNameContext; /* Context used to resolve WHERE clause */ - WhereInfo *pWInfo; /* Context used by sqlite3WhereXXX() */ - int iFkIfZero = 0; /* Address of OP_FkIfZero */ - Vdbe *v = sqlite3GetVdbe(pParse); - - assert( !pIdx || pIdx->pTable==pTab ); - - if( nIncr<0 ){ - iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0); - } - - /* Create an Expr object representing an SQL expression like: - ** - ** = AND = ... - ** - ** The collation sequence used for the comparison should be that of - ** the parent key columns. The affinity of the parent key column should - ** be applied to each child key value before the comparison takes place. - */ - for(i=0; inCol; i++){ - Expr *pLeft; /* Value from parent table row */ - Expr *pRight; /* Column ref to child table */ - Expr *pEq; /* Expression (pLeft = pRight) */ - int iCol; /* Index of column in child table */ - const char *zCol; /* Name of column in child table */ - - pLeft = sqlite3Expr(db, TK_REGISTER, 0); - if( pLeft ){ - /* Set the collation sequence and affinity of the LHS of each TK_EQ - ** expression to the parent key column defaults. */ - if( pIdx ){ - Column *pCol; - const char *zColl; - iCol = pIdx->aiColumn[i]; - pCol = &pTab->aCol[iCol]; - if( pTab->iPKey==iCol ) iCol = -1; - pLeft->iTable = regData+iCol+1; - pLeft->affinity = pCol->affinity; - zColl = pCol->zColl; - if( zColl==0 ) zColl = db->pDfltColl->zName; - pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl); - }else{ - pLeft->iTable = regData; - pLeft->affinity = SQLITE_AFF_INTEGER; - } - } - iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; - assert( iCol>=0 ); - zCol = pFKey->pFrom->aCol[iCol].zName; - pRight = sqlite3Expr(db, TK_ID, zCol); - pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); - pWhere = sqlite3ExprAnd(db, pWhere, pEq); - } - - /* If the child table is the same as the parent table, and this scan - ** is taking place as part of a DELETE operation (operation D.2), omit the - ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE - ** clause, where $rowid is the rowid of the row being deleted. */ - if( pTab==pFKey->pFrom && nIncr>0 ){ - Expr *pEq; /* Expression (pLeft = pRight) */ - Expr *pLeft; /* Value from parent table row */ - Expr *pRight; /* Column ref to child table */ - pLeft = sqlite3Expr(db, TK_REGISTER, 0); - pRight = sqlite3Expr(db, TK_COLUMN, 0); - if( pLeft && pRight ){ - pLeft->iTable = regData; - pLeft->affinity = SQLITE_AFF_INTEGER; - pRight->iTable = pSrc->a[0].iCursor; - pRight->iColumn = -1; - } - pEq = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0); - pWhere = sqlite3ExprAnd(db, pWhere, pEq); - } - - /* Resolve the references in the WHERE clause. */ - memset(&sNameContext, 0, sizeof(NameContext)); - sNameContext.pSrcList = pSrc; - sNameContext.pParse = pParse; - sqlite3ResolveExprNames(&sNameContext, pWhere); - - /* Create VDBE to loop through the entries in pSrc that match the WHERE - ** clause. If the constraint is not deferred, throw an exception for - ** each row found. Otherwise, for deferred constraints, increment the - ** deferred constraint counter by nIncr for each row selected. */ - pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); - if( nIncr>0 && pFKey->isDeferred==0 ){ - sqlite3ParseToplevel(pParse)->mayAbort = 1; - } - sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); - if( pWInfo ){ - sqlite3WhereEnd(pWInfo); - } - - /* Clean up the WHERE clause constructed above. */ - sqlite3ExprDelete(db, pWhere); - if( iFkIfZero ){ - sqlite3VdbeJumpHere(v, iFkIfZero); - } -} - -/* -** This function returns a pointer to the head of a linked list of FK -** constraints for which table pTab is the parent table. For example, -** given the following schema: -** -** CREATE TABLE t1(a PRIMARY KEY); -** CREATE TABLE t2(b REFERENCES t1(a); -** -** Calling this function with table "t1" as an argument returns a pointer -** to the FKey structure representing the foreign key constraint on table -** "t2". Calling this function with "t2" as the argument would return a -** NULL pointer (as there are no FK constraints for which t2 is the parent -** table). -*/ -SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){ - int nName = sqlite3Strlen30(pTab->zName); - return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName); -} - -/* -** The second argument is a Trigger structure allocated by the -** fkActionTrigger() routine. This function deletes the Trigger structure -** and all of its sub-components. -** -** The Trigger structure or any of its sub-components may be allocated from -** the lookaside buffer belonging to database handle dbMem. -*/ -static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ - if( p ){ - TriggerStep *pStep = p->step_list; - sqlite3ExprDelete(dbMem, pStep->pWhere); - sqlite3ExprListDelete(dbMem, pStep->pExprList); - sqlite3SelectDelete(dbMem, pStep->pSelect); - sqlite3ExprDelete(dbMem, p->pWhen); - sqlite3DbFree(dbMem, p); - } -} - -/* -** This function is called to generate code that runs when table pTab is -** being dropped from the database. The SrcList passed as the second argument -** to this function contains a single entry guaranteed to resolve to -** table pTab. -** -** Normally, no code is required. However, if either -** -** (a) The table is the parent table of a FK constraint, or -** (b) The table is the child table of a deferred FK constraint and it is -** determined at runtime that there are outstanding deferred FK -** constraint violations in the database, -** -** then the equivalent of "DELETE FROM " is executed before dropping -** the table from the database. Triggers are disabled while running this -** DELETE, but foreign key actions are not. -*/ -SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ - sqlite3 *db = pParse->db; - if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){ - int iSkip = 0; - Vdbe *v = sqlite3GetVdbe(pParse); - - assert( v ); /* VDBE has already been allocated */ - if( sqlite3FkReferences(pTab)==0 ){ - /* Search for a deferred foreign key constraint for which this table - ** is the child table. If one cannot be found, return without - ** generating any VDBE code. If one can be found, then jump over - ** the entire DELETE if there are no outstanding deferred constraints - ** when this statement is run. */ - FKey *p; - for(p=pTab->pFKey; p; p=p->pNextFrom){ - if( p->isDeferred ) break; - } - if( !p ) return; - iSkip = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); - } - - pParse->disableTriggers = 1; - sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0); - pParse->disableTriggers = 0; - - /* If the DELETE has generated immediate foreign key constraint - ** violations, halt the VDBE and return an error at this point, before - ** any modifications to the schema are made. This is because statement - ** transactions are not able to rollback schema changes. */ - sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, - OE_Abort, "foreign key constraint failed", P4_STATIC - ); - - if( iSkip ){ - sqlite3VdbeResolveLabel(v, iSkip); - } - } -} - -/* -** This function is called when inserting, deleting or updating a row of -** table pTab to generate VDBE code to perform foreign key constraint -** processing for the operation. -** -** For a DELETE operation, parameter regOld is passed the index of the -** first register in an array of (pTab->nCol+1) registers containing the -** rowid of the row being deleted, followed by each of the column values -** of the row being deleted, from left to right. Parameter regNew is passed -** zero in this case. -** -** For an INSERT operation, regOld is passed zero and regNew is passed the -** first register of an array of (pTab->nCol+1) registers containing the new -** row data. -** -** For an UPDATE operation, this function is called twice. Once before -** the original record is deleted from the table using the calling convention -** described for DELETE. Then again after the original record is deleted -** but before the new record is inserted using the INSERT convention. -*/ -SQLITE_PRIVATE void sqlite3FkCheck( - Parse *pParse, /* Parse context */ - Table *pTab, /* Row is being deleted from this table */ - int regOld, /* Previous row data is stored here */ - int regNew /* New row data is stored here */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - FKey *pFKey; /* Used to iterate through FKs */ - int iDb; /* Index of database containing pTab */ - const char *zDb; /* Name of database containing pTab */ - int isIgnoreErrors = pParse->disableTriggers; - - /* Exactly one of regOld and regNew should be non-zero. */ - assert( (regOld==0)!=(regNew==0) ); - - /* If foreign-keys are disabled, this function is a no-op. */ - if( (db->flags&SQLITE_ForeignKeys)==0 ) return; - - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zDb = db->aDb[iDb].zName; - - /* Loop through all the foreign key constraints for which pTab is the - ** child table (the table that the foreign key definition is part of). */ - for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ - Table *pTo; /* Parent table of foreign key pFKey */ - Index *pIdx = 0; /* Index on key columns in pTo */ - int *aiFree = 0; - int *aiCol; - int iCol; - int i; - int isIgnore = 0; - - /* Find the parent table of this foreign key. Also find a unique index - ** on the parent key columns in the parent table. If either of these - ** schema items cannot be located, set an error in pParse and return - ** early. */ - if( pParse->disableTriggers ){ - pTo = sqlite3FindTable(db, pFKey->zTo, zDb); - }else{ - pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); - } - if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ - assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); - if( !isIgnoreErrors || db->mallocFailed ) return; - if( pTo==0 ){ - /* If isIgnoreErrors is true, then a table is being dropped. In this - ** case SQLite runs a "DELETE FROM xxx" on the table being dropped - ** before actually dropping it in order to check FK constraints. - ** If the parent table of an FK constraint on the current table is - ** missing, behave as if it is empty. i.e. decrement the relevant - ** FK counter for each row of the current table with non-NULL keys. - */ - Vdbe *v = sqlite3GetVdbe(pParse); - int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; - for(i=0; inCol; i++){ - int iReg = pFKey->aCol[i].iFrom + regOld + 1; - sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); - } - sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1); - } - continue; - } - assert( pFKey->nCol==1 || (aiFree && pIdx) ); - - if( aiFree ){ - aiCol = aiFree; - }else{ - iCol = pFKey->aCol[0].iFrom; - aiCol = &iCol; - } - for(i=0; inCol; i++){ - if( aiCol[i]==pTab->iPKey ){ - aiCol[i] = -1; - } -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Request permission to read the parent key columns. If the - ** authorization callback returns SQLITE_IGNORE, behave as if any - ** values read from the parent table are NULL. */ - if( db->xAuth ){ - int rcauth; - char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; - rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); - isIgnore = (rcauth==SQLITE_IGNORE); - } -#endif - } - - /* Take a shared-cache advisory read-lock on the parent table. Allocate - ** a cursor to use to search the unique index on the parent key columns - ** in the parent table. */ - sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName); - pParse->nTab++; - - if( regOld!=0 ){ - /* A row is being removed from the child table. Search for the parent. - ** If the parent does not exist, removing the child row resolves an - ** outstanding foreign key constraint violation. */ - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore); - } - if( regNew!=0 ){ - /* A row is being added to the child table. If a parent row cannot - ** be found, adding the child row has violated the FK constraint. */ - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore); - } - - sqlite3DbFree(db, aiFree); - } - - /* Loop through all the foreign key constraints that refer to this table */ - for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ - Index *pIdx = 0; /* Foreign key index for pFKey */ - SrcList *pSrc; - int *aiCol = 0; - - if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ - assert( regOld==0 && regNew!=0 ); - /* Inserting a single row into a parent table cannot cause an immediate - ** foreign key violation. So do nothing in this case. */ - continue; - } - - if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ - if( !isIgnoreErrors || db->mallocFailed ) return; - continue; - } - assert( aiCol || pFKey->nCol==1 ); - - /* Create a SrcList structure containing a single table (the table - ** the foreign key that refers to this table is attached to). This - ** is required for the sqlite3WhereXXX() interface. */ - pSrc = sqlite3SrcListAppend(db, 0, 0, 0); - if( pSrc ){ - struct SrcList_item *pItem = pSrc->a; - pItem->pTab = pFKey->pFrom; - pItem->zName = pFKey->pFrom->zName; - pItem->pTab->nRef++; - pItem->iCursor = pParse->nTab++; - - if( regNew!=0 ){ - fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); - } - if( regOld!=0 ){ - /* If there is a RESTRICT action configured for the current operation - ** on the parent table of this FK, then throw an exception - ** immediately if the FK constraint is violated, even if this is a - ** deferred trigger. That's what RESTRICT means. To defer checking - ** the constraint, the FK should specify NO ACTION (represented - ** using OE_None). NO ACTION is the default. */ - fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); - } - pItem->zName = 0; - sqlite3SrcListDelete(db, pSrc); - } - sqlite3DbFree(db, aiCol); - } -} - -#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x))) - -/* -** This function is called before generating code to update or delete a -** row contained in table pTab. -*/ -SQLITE_PRIVATE u32 sqlite3FkOldmask( - Parse *pParse, /* Parse context */ - Table *pTab /* Table being modified */ -){ - u32 mask = 0; - if( pParse->db->flags&SQLITE_ForeignKeys ){ - FKey *p; - int i; - for(p=pTab->pFKey; p; p=p->pNextFrom){ - for(i=0; inCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); - } - for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ - Index *pIdx = 0; - sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); - if( pIdx ){ - for(i=0; inColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); - } - } - } - return mask; -} - -/* -** This function is called before generating code to update or delete a -** row contained in table pTab. If the operation is a DELETE, then -** parameter aChange is passed a NULL value. For an UPDATE, aChange points -** to an array of size N, where N is the number of columns in table pTab. -** If the i'th column is not modified by the UPDATE, then the corresponding -** entry in the aChange[] array is set to -1. If the column is modified, -** the value is 0 or greater. Parameter chngRowid is set to true if the -** UPDATE statement modifies the rowid fields of the table. -** -** If any foreign key processing will be required, this function returns -** true. If there is no foreign key related processing, this function -** returns false. -*/ -SQLITE_PRIVATE int sqlite3FkRequired( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being modified */ - int *aChange, /* Non-NULL for UPDATE operations */ - int chngRowid /* True for UPDATE that affects rowid */ -){ - if( pParse->db->flags&SQLITE_ForeignKeys ){ - if( !aChange ){ - /* A DELETE operation. Foreign key processing is required if the - ** table in question is either the child or parent table for any - ** foreign key constraint. */ - return (sqlite3FkReferences(pTab) || pTab->pFKey); - }else{ - /* This is an UPDATE. Foreign key processing is only required if the - ** operation modifies one or more child or parent key columns. */ - int i; - FKey *p; - - /* Check if any child key columns are being modified. */ - for(p=pTab->pFKey; p; p=p->pNextFrom){ - for(i=0; inCol; i++){ - int iChildKey = p->aCol[i].iFrom; - if( aChange[iChildKey]>=0 ) return 1; - if( iChildKey==pTab->iPKey && chngRowid ) return 1; - } - } - - /* Check if any parent key columns are being modified. */ - for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ - for(i=0; inCol; i++){ - char *zKey = p->aCol[i].zCol; - int iKey; - for(iKey=0; iKeynCol; iKey++){ - Column *pCol = &pTab->aCol[iKey]; - if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey) - : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){ - if( aChange[iKey]>=0 ) return 1; - if( iKey==pTab->iPKey && chngRowid ) return 1; - } - } - } - } - } - } - return 0; -} - -/* -** This function is called when an UPDATE or DELETE operation is being -** compiled on table pTab, which is the parent table of foreign-key pFKey. -** If the current operation is an UPDATE, then the pChanges parameter is -** passed a pointer to the list of columns being modified. If it is a -** DELETE, pChanges is passed a NULL pointer. -** -** It returns a pointer to a Trigger structure containing a trigger -** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. -** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is -** returned (these actions require no special handling by the triggers -** sub-system, code for them is created by fkScanChildren()). -** -** For example, if pFKey is the foreign key and pTab is table "p" in -** the following schema: -** -** CREATE TABLE p(pk PRIMARY KEY); -** CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE); -** -** then the returned trigger structure is equivalent to: -** -** CREATE TRIGGER ... DELETE ON p BEGIN -** DELETE FROM c WHERE ck = old.pk; -** END; -** -** The returned pointer is cached as part of the foreign key object. It -** is eventually freed along with the rest of the foreign key object by -** sqlite3FkDelete(). -*/ -static Trigger *fkActionTrigger( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being updated or deleted from */ - FKey *pFKey, /* Foreign key to get action for */ - ExprList *pChanges /* Change-list for UPDATE, NULL for DELETE */ -){ - sqlite3 *db = pParse->db; /* Database handle */ - int action; /* One of OE_None, OE_Cascade etc. */ - Trigger *pTrigger; /* Trigger definition to return */ - int iAction = (pChanges!=0); /* 1 for UPDATE, 0 for DELETE */ - - action = pFKey->aAction[iAction]; - pTrigger = pFKey->apTrigger[iAction]; - - if( action!=OE_None && !pTrigger ){ - u8 enableLookaside; /* Copy of db->lookaside.bEnabled */ - char const *zFrom; /* Name of child table */ - int nFrom; /* Length in bytes of zFrom */ - Index *pIdx = 0; /* Parent key index for this FK */ - int *aiCol = 0; /* child table cols -> parent key cols */ - TriggerStep *pStep = 0; /* First (only) step of trigger program */ - Expr *pWhere = 0; /* WHERE clause of trigger step */ - ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ - Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ - int i; /* Iterator variable */ - Expr *pWhen = 0; /* WHEN clause for the trigger */ - - if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; - assert( aiCol || pFKey->nCol==1 ); - - for(i=0; inCol; i++){ - Token tOld = { "old", 3 }; /* Literal "old" token */ - Token tNew = { "new", 3 }; /* Literal "new" token */ - Token tFromCol; /* Name of column in child table */ - Token tToCol; /* Name of column in parent table */ - int iFromCol; /* Idx of column in child table */ - Expr *pEq; /* tFromCol = OLD.tToCol */ - - iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; - assert( iFromCol>=0 ); - tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid"; - tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; - - tToCol.n = sqlite3Strlen30(tToCol.z); - tFromCol.n = sqlite3Strlen30(tFromCol.z); - - /* Create the expression "OLD.zToCol = zFromCol". It is important - ** that the "OLD.zToCol" term is on the LHS of the = operator, so - ** that the affinity and collation sequence associated with the - ** parent table are used for the comparison. */ - pEq = sqlite3PExpr(pParse, TK_EQ, - sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) - , 0), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol) - , 0); - pWhere = sqlite3ExprAnd(db, pWhere, pEq); - - /* For ON UPDATE, construct the next term of the WHEN clause. - ** The final WHEN clause will be like this: - ** - ** WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN) - */ - if( pChanges ){ - pEq = sqlite3PExpr(pParse, TK_IS, - sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), - 0), - sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), - 0), - 0); - pWhen = sqlite3ExprAnd(db, pWhen, pEq); - } - - if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ - Expr *pNew; - if( action==OE_Cascade ){ - pNew = sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) - , 0); - }else if( action==OE_SetDflt ){ - Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; - if( pDflt ){ - pNew = sqlite3ExprDup(db, pDflt, 0); - }else{ - pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); - } - }else{ - pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); - } - pList = sqlite3ExprListAppend(pParse, pList, pNew); - sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); - } - } - sqlite3DbFree(db, aiCol); - - zFrom = pFKey->pFrom->zName; - nFrom = sqlite3Strlen30(zFrom); - - if( action==OE_Restrict ){ - Token tFrom; - Expr *pRaise; - - tFrom.z = zFrom; - tFrom.n = nFrom; - pRaise = sqlite3Expr(db, TK_RAISE, "foreign key constraint failed"); - if( pRaise ){ - pRaise->affinity = OE_Abort; - } - pSelect = sqlite3SelectNew(pParse, - sqlite3ExprListAppend(pParse, 0, pRaise), - sqlite3SrcListAppend(db, 0, &tFrom, 0), - pWhere, - 0, 0, 0, 0, 0, 0 - ); - pWhere = 0; - } - - /* Disable lookaside memory allocation */ - enableLookaside = db->lookaside.bEnabled; - db->lookaside.bEnabled = 0; - - pTrigger = (Trigger *)sqlite3DbMallocZero(db, - sizeof(Trigger) + /* struct Trigger */ - sizeof(TriggerStep) + /* Single step in trigger program */ - nFrom + 1 /* Space for pStep->target.z */ - ); - if( pTrigger ){ - pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; - pStep->target.z = (char *)&pStep[1]; - pStep->target.n = nFrom; - memcpy((char *)pStep->target.z, zFrom, nFrom); - - pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); - pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - if( pWhen ){ - pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0); - pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); - } - } - - /* Re-enable the lookaside buffer, if it was disabled earlier. */ - db->lookaside.bEnabled = enableLookaside; - - sqlite3ExprDelete(db, pWhere); - sqlite3ExprDelete(db, pWhen); - sqlite3ExprListDelete(db, pList); - sqlite3SelectDelete(db, pSelect); - if( db->mallocFailed==1 ){ - fkTriggerDelete(db, pTrigger); - return 0; - } - assert( pStep!=0 ); - - switch( action ){ - case OE_Restrict: - pStep->op = TK_SELECT; - break; - case OE_Cascade: - if( !pChanges ){ - pStep->op = TK_DELETE; - break; - } - default: - pStep->op = TK_UPDATE; - } - pStep->pTrig = pTrigger; - pTrigger->pSchema = pTab->pSchema; - pTrigger->pTabSchema = pTab->pSchema; - pFKey->apTrigger[iAction] = pTrigger; - pTrigger->op = (pChanges ? TK_UPDATE : TK_DELETE); - } - - return pTrigger; -} - -/* -** This function is called when deleting or updating a row to implement -** any required CASCADE, SET NULL or SET DEFAULT actions. -*/ -SQLITE_PRIVATE void sqlite3FkActions( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being updated or deleted from */ - ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */ - int regOld /* Address of array containing old row */ -){ - /* If foreign-key support is enabled, iterate through all FKs that - ** refer to table pTab. If there is an action associated with the FK - ** for this operation (either update or delete), invoke the associated - ** trigger sub-program. */ - if( pParse->db->flags&SQLITE_ForeignKeys ){ - FKey *pFKey; /* Iterator variable */ - for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ - Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges); - if( pAction ){ - sqlite3CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0); - } - } - } -} - -#endif /* ifndef SQLITE_OMIT_TRIGGER */ - -/* -** Free all memory associated with foreign key definitions attached to -** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash -** hash table. -*/ -SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ - FKey *pFKey; /* Iterator variable */ - FKey *pNext; /* Copy of pFKey->pNextFrom */ - - assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); - for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){ - - /* Remove the FK from the fkeyHash hash table. */ - if( !db || db->pnBytesFreed==0 ){ - if( pFKey->pPrevTo ){ - pFKey->pPrevTo->pNextTo = pFKey->pNextTo; - }else{ - void *p = (void *)pFKey->pNextTo; - const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); - sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p); - } - if( pFKey->pNextTo ){ - pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; - } - } - - /* EV: R-30323-21917 Each foreign key constraint in SQLite is - ** classified as either immediate or deferred. - */ - assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 ); - - /* Delete any triggers created to implement actions for this FK. */ -#ifndef SQLITE_OMIT_TRIGGER - fkTriggerDelete(db, pFKey->apTrigger[0]); - fkTriggerDelete(db, pFKey->apTrigger[1]); -#endif - - pNext = pFKey->pNextFrom; - sqlite3DbFree(db, pFKey); - } -} -#endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */ - -/************** End of fkey.c ************************************************/ -/************** Begin file insert.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle INSERT statements in SQLite. -*/ - -/* -** Generate code that will open a table for reading. -*/ -SQLITE_PRIVATE void sqlite3OpenTable( - Parse *p, /* Generate code into this VDBE */ - int iCur, /* The cursor number of the table */ - int iDb, /* The database index in sqlite3.aDb[] */ - Table *pTab, /* The table to be opened */ - int opcode /* OP_OpenRead or OP_OpenWrite */ -){ - Vdbe *v; - assert( !IsVirtual(pTab) ); - v = sqlite3GetVdbe(p); - assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); - sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName); - sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); - sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32); - VdbeComment((v, "%s", pTab->zName)); -} - -/* -** Return a pointer to the column affinity string associated with index -** pIdx. A column affinity string has one character for each column in -** the table, according to the affinity of the column: -** -** Character Column affinity -** ------------------------------ -** 'a' TEXT -** 'b' NONE -** 'c' NUMERIC -** 'd' INTEGER -** 'e' REAL -** -** An extra 'd' is appended to the end of the string to cover the -** rowid that appears as the last column in every index. -** -** Memory for the buffer containing the column index affinity string -** is managed along with the rest of the Index structure. It will be -** released when sqlite3DeleteIndex() is called. -*/ -SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ - if( !pIdx->zColAff ){ - /* The first time a column affinity string for a particular index is - ** required, it is allocated and populated here. It is then stored as - ** a member of the Index structure for subsequent use. - ** - ** The column affinity string will eventually be deleted by - ** sqliteDeleteIndex() when the Index structure itself is cleaned - ** up. - */ - int n; - Table *pTab = pIdx->pTable; - sqlite3 *db = sqlite3VdbeDb(v); - pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+2); - if( !pIdx->zColAff ){ - db->mallocFailed = 1; - return 0; - } - for(n=0; nnColumn; n++){ - pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; - } - pIdx->zColAff[n++] = SQLITE_AFF_INTEGER; - pIdx->zColAff[n] = 0; - } - - return pIdx->zColAff; -} - -/* -** Set P4 of the most recently inserted opcode to a column affinity -** string for table pTab. A column affinity string has one character -** for each column indexed by the index, according to the affinity of the -** column: -** -** Character Column affinity -** ------------------------------ -** 'a' TEXT -** 'b' NONE -** 'c' NUMERIC -** 'd' INTEGER -** 'e' REAL -*/ -SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ - /* The first time a column affinity string for a particular table - ** is required, it is allocated and populated here. It is then - ** stored as a member of the Table structure for subsequent use. - ** - ** The column affinity string will eventually be deleted by - ** sqlite3DeleteTable() when the Table structure itself is cleaned up. - */ - if( !pTab->zColAff ){ - char *zColAff; - int i; - sqlite3 *db = sqlite3VdbeDb(v); - - zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); - if( !zColAff ){ - db->mallocFailed = 1; - return; - } - - for(i=0; inCol; i++){ - zColAff[i] = pTab->aCol[i].affinity; - } - zColAff[pTab->nCol] = '\0'; - - pTab->zColAff = zColAff; - } - - sqlite3VdbeChangeP4(v, -1, pTab->zColAff, P4_TRANSIENT); -} - -/* -** Return non-zero if the table pTab in database iDb or any of its indices -** have been opened at any point in the VDBE program beginning at location -** iStartAddr throught the end of the program. This is used to see if -** a statement of the form "INSERT INTO SELECT ..." can -** run without using temporary table for the results of the SELECT. -*/ -static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){ - Vdbe *v = sqlite3GetVdbe(p); - int i; - int iEnd = sqlite3VdbeCurrentAddr(v); -#ifndef SQLITE_OMIT_VIRTUALTABLE - VTable *pVTab = IsVirtual(pTab) ? sqlite3GetVTable(p->db, pTab) : 0; -#endif - - for(i=iStartAddr; iopcode==OP_OpenRead && pOp->p3==iDb ){ - Index *pIndex; - int tnum = pOp->p2; - if( tnum==pTab->tnum ){ - return 1; - } - for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ - if( tnum==pIndex->tnum ){ - return 1; - } - } - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pVTab ){ - assert( pOp->p4.pVtab!=0 ); - assert( pOp->p4type==P4_VTAB ); - return 1; - } -#endif - } - return 0; -} - -#ifndef SQLITE_OMIT_AUTOINCREMENT -/* -** Locate or create an AutoincInfo structure associated with table pTab -** which is in database iDb. Return the register number for the register -** that holds the maximum rowid. -** -** There is at most one AutoincInfo structure per table even if the -** same table is autoincremented multiple times due to inserts within -** triggers. A new AutoincInfo structure is created if this is the -** first use of table pTab. On 2nd and subsequent uses, the original -** AutoincInfo structure is used. -** -** Three memory locations are allocated: -** -** (1) Register to hold the name of the pTab table. -** (2) Register to hold the maximum ROWID of pTab. -** (3) Register to hold the rowid in sqlite_sequence of pTab -** -** The 2nd register is the one that is returned. That is all the -** insert routine needs to know about. -*/ -static int autoIncBegin( - Parse *pParse, /* Parsing context */ - int iDb, /* Index of the database holding pTab */ - Table *pTab /* The table we are writing to */ -){ - int memId = 0; /* Register holding maximum rowid */ - if( pTab->tabFlags & TF_Autoincrement ){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - AutoincInfo *pInfo; - - pInfo = pToplevel->pAinc; - while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } - if( pInfo==0 ){ - pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo)); - if( pInfo==0 ) return 0; - pInfo->pNext = pToplevel->pAinc; - pToplevel->pAinc = pInfo; - pInfo->pTab = pTab; - pInfo->iDb = iDb; - pToplevel->nMem++; /* Register to hold name of table */ - pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ - pToplevel->nMem++; /* Rowid in sqlite_sequence */ - } - memId = pInfo->regCtr; - } - return memId; -} - -/* -** This routine generates code that will initialize all of the -** register used by the autoincrement tracker. -*/ -SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ - AutoincInfo *p; /* Information about an AUTOINCREMENT */ - sqlite3 *db = pParse->db; /* The database connection */ - Db *pDb; /* Database only autoinc table */ - int memId; /* Register holding max rowid */ - int addr; /* A VDBE address */ - Vdbe *v = pParse->pVdbe; /* VDBE under construction */ - - /* This routine is never called during trigger-generation. It is - ** only called from the top-level */ - assert( pParse->pTriggerTab==0 ); - assert( pParse==sqlite3ParseToplevel(pParse) ); - - assert( v ); /* We failed long ago if this is not so */ - for(p = pParse->pAinc; p; p = p->pNext){ - pDb = &db->aDb[p->iDb]; - memId = p->regCtr; - assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); - sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); - sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1); - addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); - sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); - sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); - sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); - sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); - sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); - sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); - sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); - sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); - sqlite3VdbeAddOp0(v, OP_Close); - } -} - -/* -** Update the maximum rowid for an autoincrement calculation. -** -** This routine should be called when the top of the stack holds a -** new rowid that is about to be inserted. If that new rowid is -** larger than the maximum rowid in the memId memory cell, then the -** memory cell is updated. The stack is unchanged. -*/ -static void autoIncStep(Parse *pParse, int memId, int regRowid){ - if( memId>0 ){ - sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); - } -} - -/* -** This routine generates the code needed to write autoincrement -** maximum rowid values back into the sqlite_sequence register. -** Every statement that might do an INSERT into an autoincrement -** table (either directly or through triggers) needs to call this -** routine just before the "exit" code. -*/ -SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){ - AutoincInfo *p; - Vdbe *v = pParse->pVdbe; - sqlite3 *db = pParse->db; - - assert( v ); - for(p = pParse->pAinc; p; p = p->pNext){ - Db *pDb = &db->aDb[p->iDb]; - int j1, j2, j3, j4, j5; - int iRec; - int memId = p->regCtr; - - iRec = sqlite3GetTempReg(pParse); - assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); - sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); - j2 = sqlite3VdbeAddOp0(v, OP_Rewind); - j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec); - j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); - sqlite3VdbeAddOp2(v, OP_Next, 0, j3); - sqlite3VdbeJumpHere(v, j2); - sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); - j5 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, j4); - sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); - sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeJumpHere(v, j5); - sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); - sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3VdbeAddOp0(v, OP_Close); - sqlite3ReleaseTempReg(pParse, iRec); - } -} -#else -/* -** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines -** above are all no-ops -*/ -# define autoIncBegin(A,B,C) (0) -# define autoIncStep(A,B,C) -#endif /* SQLITE_OMIT_AUTOINCREMENT */ - - -/* -** Generate code for a co-routine that will evaluate a subquery one -** row at a time. -** -** The pSelect parameter is the subquery that the co-routine will evaluation. -** Information about the location of co-routine and the registers it will use -** is returned by filling in the pDest object. -** -** Registers are allocated as follows: -** -** pDest->iSDParm The register holding the next entry-point of the -** co-routine. Run the co-routine to its next breakpoint -** by calling "OP_Yield $X" where $X is pDest->iSDParm. -** -** pDest->iSDParm+1 The register holding the "completed" flag for the -** co-routine. This register is 0 if the previous Yield -** generated a new result row, or 1 if the subquery -** has completed. If the Yield is called again -** after this register becomes 1, then the VDBE will -** halt with an SQLITE_INTERNAL error. -** -** pDest->iSdst First result register. -** -** pDest->nSdst Number of result registers. -** -** This routine handles all of the register allocation and fills in the -** pDest structure appropriately. -** -** Here is a schematic of the generated code assuming that X is the -** co-routine entry-point register reg[pDest->iSDParm], that EOF is the -** completed flag reg[pDest->iSDParm+1], and R and S are the range of -** registers that hold the result set, reg[pDest->iSdst] through -** reg[pDest->iSdst+pDest->nSdst-1]: -** -** X <- A -** EOF <- 0 -** goto B -** A: setup for the SELECT -** loop rows in the SELECT -** load results into registers R..S -** yield X -** end loop -** cleanup after the SELECT -** EOF <- 1 -** yield X -** halt-error -** B: -** -** To use this subroutine, the caller generates code as follows: -** -** [ Co-routine generated by this subroutine, shown above ] -** S: yield X -** if EOF goto E -** if skip this row, goto C -** if terminate loop, goto E -** deal with this row -** C: goto S -** E: -*/ -SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){ - int regYield; /* Register holding co-routine entry-point */ - int regEof; /* Register holding co-routine completion flag */ - int addrTop; /* Top of the co-routine */ - int j1; /* Jump instruction */ - int rc; /* Result code */ - Vdbe *v; /* VDBE under construction */ - - regYield = ++pParse->nMem; - regEof = ++pParse->nMem; - v = sqlite3GetVdbe(pParse); - addrTop = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */ - VdbeComment((v, "Co-routine entry point")); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ - VdbeComment((v, "Co-routine completion flag")); - sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield); - j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); - rc = sqlite3Select(pParse, pSelect, pDest); - assert( pParse->nErr==0 || rc ); - if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM; - if( rc ) return rc; - sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */ - sqlite3VdbeAddOp1(v, OP_Yield, regYield); /* yield X */ - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort); - VdbeComment((v, "End of coroutine")); - sqlite3VdbeJumpHere(v, j1); /* label B: */ - return rc; -} - - - -/* Forward declaration */ -static int xferOptimization( - Parse *pParse, /* Parser context */ - Table *pDest, /* The table we are inserting into */ - Select *pSelect, /* A SELECT statement to use as the data source */ - int onError, /* How to handle constraint errors */ - int iDbDest /* The database of pDest */ -); - -/* -** This routine is call to handle SQL of the following forms: -** -** insert into TABLE (IDLIST) values(EXPRLIST) -** insert into TABLE (IDLIST) select -** -** The IDLIST following the table name is always optional. If omitted, -** then a list of all columns for the table is substituted. The IDLIST -** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted. -** -** The pList parameter holds EXPRLIST in the first form of the INSERT -** statement above, and pSelect is NULL. For the second form, pList is -** NULL and pSelect is a pointer to the select statement used to generate -** data for the insert. -** -** The code generated follows one of four templates. For a simple -** select with data coming from a VALUES clause, the code executes -** once straight down through. Pseudo-code follows (we call this -** the "1st template"): -** -** open write cursor to
and its indices -** puts VALUES clause expressions onto the stack -** write the resulting record into
-** cleanup -** -** The three remaining templates assume the statement is of the form -** -** INSERT INTO
SELECT ... -** -** If the SELECT clause is of the restricted form "SELECT * FROM " - -** in other words if the SELECT pulls all columns from a single table -** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and -** if and are distinct tables but have identical -** schemas, including all the same indices, then a special optimization -** is invoked that copies raw records from over to . -** See the xferOptimization() function for the implementation of this -** template. This is the 2nd template. -** -** open a write cursor to
-** open read cursor on -** transfer all records in over to
-** close cursors -** foreach index on
-** open a write cursor on the
index -** open a read cursor on the corresponding index -** transfer all records from the read to the write cursors -** close cursors -** end foreach -** -** The 3rd template is for when the second template does not apply -** and the SELECT clause does not read from
at any time. -** The generated code follows this template: -** -** EOF <- 0 -** X <- A -** goto B -** A: setup for the SELECT -** loop over the rows in the SELECT -** load values into registers R..R+n -** yield X -** end loop -** cleanup after the SELECT -** EOF <- 1 -** yield X -** goto A -** B: open write cursor to
and its indices -** C: yield X -** if EOF goto D -** insert the select result into
from R..R+n -** goto C -** D: cleanup -** -** The 4th template is used if the insert statement takes its -** values from a SELECT but the data is being inserted into a table -** that is also read as part of the SELECT. In the third form, -** we have to use a intermediate table to store the results of -** the select. The template is like this: -** -** EOF <- 0 -** X <- A -** goto B -** A: setup for the SELECT -** loop over the tables in the SELECT -** load value into register R..R+n -** yield X -** end loop -** cleanup after the SELECT -** EOF <- 1 -** yield X -** halt-error -** B: open temp table -** L: yield X -** if EOF goto M -** insert row from R..R+n into temp table -** goto L -** M: open write cursor to
and its indices -** rewind temp table -** C: loop over rows of intermediate table -** transfer values form intermediate table into
-** end loop -** D: cleanup -*/ -SQLITE_PRIVATE void sqlite3Insert( - Parse *pParse, /* Parser context */ - SrcList *pTabList, /* Name of table into which we are inserting */ - ExprList *pList, /* List of values to be inserted */ - Select *pSelect, /* A SELECT statement to use as the data source */ - IdList *pColumn, /* Column names corresponding to IDLIST. */ - int onError /* How to handle constraint errors */ -){ - sqlite3 *db; /* The main database structure */ - Table *pTab; /* The table to insert into. aka TABLE */ - char *zTab; /* Name of the table into which we are inserting */ - const char *zDb; /* Name of the database holding this table */ - int i, j, idx; /* Loop counters */ - Vdbe *v; /* Generate code into this virtual machine */ - Index *pIdx; /* For looping over indices of the table */ - int nColumn; /* Number of columns in the data */ - int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ - int baseCur = 0; /* VDBE Cursor number for pTab */ - int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ - int endOfLoop; /* Label for the end of the insertion loop */ - int useTempTable = 0; /* Store SELECT results in intermediate table */ - int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ - int addrInsTop = 0; /* Jump to label "D" */ - int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ - int addrSelect = 0; /* Address of coroutine that implements the SELECT */ - SelectDest dest; /* Destination for SELECT on rhs of INSERT */ - int iDb; /* Index of database holding TABLE */ - Db *pDb; /* The database containing table being inserted into */ - int appendFlag = 0; /* True if the insert is likely to be an append */ - - /* Register allocations */ - int regFromSelect = 0;/* Base register for data coming from SELECT */ - int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ - int regRowCount = 0; /* Memory cell used for the row counter */ - int regIns; /* Block of regs holding rowid+data being inserted */ - int regRowid; /* registers holding insert rowid */ - int regData; /* register holding first column to insert */ - int regEof = 0; /* Register recording end of SELECT data */ - int *aRegIdx = 0; /* One register allocated to each index */ - -#ifndef SQLITE_OMIT_TRIGGER - int isView; /* True if attempting to insert into a view */ - Trigger *pTrigger; /* List of triggers on pTab, if required */ - int tmask; /* Mask of trigger times */ -#endif - - db = pParse->db; - memset(&dest, 0, sizeof(dest)); - if( pParse->nErr || db->mallocFailed ){ - goto insert_cleanup; - } - - /* Locate the table into which we will be inserting new information. - */ - assert( pTabList->nSrc==1 ); - zTab = pTabList->a[0].zName; - if( NEVER(zTab==0) ) goto insert_cleanup; - pTab = sqlite3SrcListLookup(pParse, pTabList); - if( pTab==0 ){ - goto insert_cleanup; - } - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDbnDb ); - pDb = &db->aDb[iDb]; - zDb = pDb->zName; - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ - goto insert_cleanup; - } - - /* Figure out if we have any triggers and if the table being - ** inserted into is a view - */ -#ifndef SQLITE_OMIT_TRIGGER - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); - isView = pTab->pSelect!=0; -#else -# define pTrigger 0 -# define tmask 0 -# define isView 0 -#endif -#ifdef SQLITE_OMIT_VIEW -# undef isView -# define isView 0 -#endif - assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) ); - - /* If pTab is really a view, make sure it has been initialized. - ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual - ** module table). - */ - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto insert_cleanup; - } - - /* Ensure that: - * (a) the table is not read-only, - * (b) that if it is a view then ON INSERT triggers exist - */ - if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ - goto insert_cleanup; - } - - /* Allocate a VDBE - */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto insert_cleanup; - if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb); - -#ifndef SQLITE_OMIT_XFER_OPT - /* If the statement is of the form - ** - ** INSERT INTO SELECT * FROM ; - ** - ** Then special optimizations can be applied that make the transfer - ** very fast and which reduce fragmentation of indices. - ** - ** This is the 2nd template. - */ - if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ - assert( !pTrigger ); - assert( pList==0 ); - goto insert_end; - } -#endif /* SQLITE_OMIT_XFER_OPT */ - - /* If this is an AUTOINCREMENT table, look up the sequence number in the - ** sqlite_sequence table and store it in memory cell regAutoinc. - */ - regAutoinc = autoIncBegin(pParse, iDb, pTab); - - /* Figure out how many columns of data are supplied. If the data - ** is coming from a SELECT statement, then generate a co-routine that - ** produces a single row of the SELECT on each invocation. The - ** co-routine is the common header to the 3rd and 4th templates. - */ - if( pSelect ){ - /* Data is coming from a SELECT. Generate a co-routine to run that - ** SELECT. */ - int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest); - if( rc ) goto insert_cleanup; - - regEof = dest.iSDParm + 1; - regFromSelect = dest.iSdst; - assert( pSelect->pEList ); - nColumn = pSelect->pEList->nExpr; - assert( dest.nSdst==nColumn ); - - /* Set useTempTable to TRUE if the result of the SELECT statement - ** should be written into a temporary table (template 4). Set to - ** FALSE if each* row of the SELECT can be written directly into - ** the destination table (template 3). - ** - ** A temp table must be used if the table being updated is also one - ** of the tables being read by the SELECT statement. Also use a - ** temp table in the case of row triggers. - */ - if( pTrigger || readsTable(pParse, addrSelect, iDb, pTab) ){ - useTempTable = 1; - } - - if( useTempTable ){ - /* Invoke the coroutine to extract information from the SELECT - ** and add it to a transient table srcTab. The code generated - ** here is from the 4th template: - ** - ** B: open temp table - ** L: yield X - ** if EOF goto M - ** insert row from R..R+n into temp table - ** goto L - ** M: ... - */ - int regRec; /* Register to hold packed record */ - int regTempRowid; /* Register to hold temp table ROWID */ - int addrTop; /* Label "L" */ - int addrIf; /* Address of jump to M */ - - srcTab = pParse->nTab++; - regRec = sqlite3GetTempReg(pParse); - regTempRowid = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); - addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); - addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); - sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid); - sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); - sqlite3VdbeJumpHere(v, addrIf); - sqlite3ReleaseTempReg(pParse, regRec); - sqlite3ReleaseTempReg(pParse, regTempRowid); - } - }else{ - /* This is the case if the data for the INSERT is coming from a VALUES - ** clause - */ - NameContext sNC; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - srcTab = -1; - assert( useTempTable==0 ); - nColumn = pList ? pList->nExpr : 0; - for(i=0; ia[i].pExpr) ){ - goto insert_cleanup; - } - } - } - - /* Make sure the number of columns in the source data matches the number - ** of columns to be inserted into the table. - */ - if( IsVirtual(pTab) ){ - for(i=0; inCol; i++){ - nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); - } - } - if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ - sqlite3ErrorMsg(pParse, - "table %S has %d columns but %d values were supplied", - pTabList, 0, pTab->nCol-nHidden, nColumn); - goto insert_cleanup; - } - if( pColumn!=0 && nColumn!=pColumn->nId ){ - sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); - goto insert_cleanup; - } - - /* If the INSERT statement included an IDLIST term, then make sure - ** all elements of the IDLIST really are columns of the table and - ** remember the column indices. - ** - ** If the table has an INTEGER PRIMARY KEY column and that column - ** is named in the IDLIST, then record in the keyColumn variable - ** the index into IDLIST of the primary key column. keyColumn is - ** the index of the primary key as it appears in IDLIST, not as - ** is appears in the original table. (The index of the primary - ** key in the original table is pTab->iPKey.) - */ - if( pColumn ){ - for(i=0; inId; i++){ - pColumn->a[i].idx = -1; - } - for(i=0; inId; i++){ - for(j=0; jnCol; j++){ - if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ - pColumn->a[i].idx = j; - if( j==pTab->iPKey ){ - keyColumn = i; - } - break; - } - } - if( j>=pTab->nCol ){ - if( sqlite3IsRowid(pColumn->a[i].zName) ){ - keyColumn = i; - }else{ - sqlite3ErrorMsg(pParse, "table %S has no column named %s", - pTabList, 0, pColumn->a[i].zName); - pParse->checkSchema = 1; - goto insert_cleanup; - } - } - } - } - - /* If there is no IDLIST term but the table has an integer primary - ** key, the set the keyColumn variable to the primary key column index - ** in the original table definition. - */ - if( pColumn==0 && nColumn>0 ){ - keyColumn = pTab->iPKey; - } - - /* Initialize the count of rows to be inserted - */ - if( db->flags & SQLITE_CountRows ){ - regRowCount = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); - } - - /* If this is not a view, open the table and and all indices */ - if( !isView ){ - int nIdx; - - baseCur = pParse->nTab; - nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite); - aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); - if( aRegIdx==0 ){ - goto insert_cleanup; - } - for(i=0; inMem; - } - } - - /* This is the top of the main insertion loop */ - if( useTempTable ){ - /* This block codes the top of loop only. The complete loop is the - ** following pseudocode (template 4): - ** - ** rewind temp table - ** C: loop over rows of intermediate table - ** transfer values form intermediate table into
- ** end loop - ** D: ... - */ - addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); - addrCont = sqlite3VdbeCurrentAddr(v); - }else if( pSelect ){ - /* This block codes the top of loop only. The complete loop is the - ** following pseudocode (template 3): - ** - ** C: yield X - ** if EOF goto D - ** insert the select result into
from R..R+n - ** goto C - ** D: ... - */ - addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); - addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof); - } - - /* Allocate registers for holding the rowid of the new row, - ** the content of the new row, and the assemblied row record. - */ - regRowid = regIns = pParse->nMem+1; - pParse->nMem += pTab->nCol + 1; - if( IsVirtual(pTab) ){ - regRowid++; - pParse->nMem++; - } - regData = regRowid+1; - - /* Run the BEFORE and INSTEAD OF triggers, if there are any - */ - endOfLoop = sqlite3VdbeMakeLabel(v); - if( tmask & TRIGGER_BEFORE ){ - int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1); - - /* build the NEW.* reference row. Note that if there is an INTEGER - ** PRIMARY KEY into which a NULL is being inserted, that NULL will be - ** translated into a unique ID for the row. But on a BEFORE trigger, - ** we do not know what the unique ID will be (because the insert has - ** not happened yet) so we substitute a rowid of -1 - */ - if( keyColumn<0 ){ - sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); - }else{ - int j1; - if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regCols); - }else{ - assert( pSelect==0 ); /* Otherwise useTempTable is true */ - sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regCols); - } - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); - sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); - sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); - } - - /* Cannot have triggers on a virtual table. If it were possible, - ** this block would have to account for hidden column. - */ - assert( !IsVirtual(pTab) ); - - /* Create the new column data - */ - for(i=0; inCol; i++){ - if( pColumn==0 ){ - j = i; - }else{ - for(j=0; jnId; j++){ - if( pColumn->a[j].idx==i ) break; - } - } - if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){ - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1); - }else if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); - }else{ - assert( pSelect==0 ); /* Otherwise useTempTable is true */ - sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1); - } - } - - /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, - ** do not attempt any conversions before assembling the record. - ** If this is a real table, attempt conversions as required by the - ** table column affinities. - */ - if( !isView ){ - sqlite3VdbeAddOp2(v, OP_Affinity, regCols+1, pTab->nCol); - sqlite3TableAffinityStr(v, pTab); - } - - /* Fire BEFORE or INSTEAD OF triggers */ - sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, - pTab, regCols-pTab->nCol-1, onError, endOfLoop); - - sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1); - } - - /* Push the record number for the new entry onto the stack. The - ** record number is a randomly generate integer created by NewRowid - ** except when the table has an INTEGER PRIMARY KEY column, in which - ** case the record number is the same as that column. - */ - if( !isView ){ - if( IsVirtual(pTab) ){ - /* The row that the VUpdate opcode will delete: none */ - sqlite3VdbeAddOp2(v, OP_Null, 0, regIns); - } - if( keyColumn>=0 ){ - if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); - }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid); - }else{ - VdbeOp *pOp; - sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid); - pOp = sqlite3VdbeGetOp(v, -1); - if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ - appendFlag = 1; - pOp->opcode = OP_NewRowid; - pOp->p1 = baseCur; - pOp->p2 = regRowid; - pOp->p3 = regAutoinc; - } - } - /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid - ** to generate a unique primary key value. - */ - if( !appendFlag ){ - int j1; - if( !IsVirtual(pTab) ){ - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); - sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc); - sqlite3VdbeJumpHere(v, j1); - }else{ - j1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2); - } - sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); - } - }else if( IsVirtual(pTab) ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); - }else{ - sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc); - appendFlag = 1; - } - autoIncStep(pParse, regAutoinc, regRowid); - - /* Push onto the stack, data for all columns of the new entry, beginning - ** with the first column. - */ - nHidden = 0; - for(i=0; inCol; i++){ - int iRegStore = regRowid+1+i; - if( i==pTab->iPKey ){ - /* The value of the INTEGER PRIMARY KEY column is always a NULL. - ** Whenever this column is read, the record number will be substituted - ** in its place. So will fill this column with a NULL to avoid - ** taking up data space with information that will never be used. */ - sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore); - continue; - } - if( pColumn==0 ){ - if( IsHiddenColumn(&pTab->aCol[i]) ){ - assert( IsVirtual(pTab) ); - j = -1; - nHidden++; - }else{ - j = i - nHidden; - } - }else{ - for(j=0; jnId; j++){ - if( pColumn->a[j].idx==i ) break; - } - } - if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){ - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore); - }else if( useTempTable ){ - sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); - }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore); - }else{ - sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore); - } - } - - /* Generate code to check constraints and generate index keys and - ** do the insertion. - */ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pTab) ){ - const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); - sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); - sqlite3MayAbort(pParse); - }else -#endif - { - int isReplace; /* Set to true if constraints may cause a replace */ - sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx, - keyColumn>=0, 0, onError, endOfLoop, &isReplace - ); - sqlite3FkCheck(pParse, pTab, 0, regIns); - sqlite3CompleteInsertion( - pParse, pTab, baseCur, regIns, aRegIdx, 0, appendFlag, isReplace==0 - ); - } - } - - /* Update the count of rows that are inserted - */ - if( (db->flags & SQLITE_CountRows)!=0 ){ - sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); - } - - if( pTrigger ){ - /* Code AFTER triggers */ - sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, - pTab, regData-2-pTab->nCol, onError, endOfLoop); - } - - /* The bottom of the main insertion loop, if the data source - ** is a SELECT statement. - */ - sqlite3VdbeResolveLabel(v, endOfLoop); - if( useTempTable ){ - sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); - sqlite3VdbeJumpHere(v, addrInsTop); - sqlite3VdbeAddOp1(v, OP_Close, srcTab); - }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrCont); - sqlite3VdbeJumpHere(v, addrInsTop); - } - - if( !IsVirtual(pTab) && !isView ){ - /* Close all tables opened */ - sqlite3VdbeAddOp1(v, OP_Close, baseCur); - for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ - sqlite3VdbeAddOp1(v, OP_Close, idx+baseCur); - } - } - -insert_end: - /* Update the sqlite_sequence table by storing the content of the - ** maximum rowid counter values recorded while inserting into - ** autoincrement tables. - */ - if( pParse->nested==0 && pParse->pTriggerTab==0 ){ - sqlite3AutoincrementEnd(pParse); - } - - /* - ** Return the number of rows inserted. If this routine is - ** generating code because of a call to sqlite3NestedParse(), do not - ** invoke the callback function. - */ - if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ - sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); - } - -insert_cleanup: - sqlite3SrcListDelete(db, pTabList); - sqlite3ExprListDelete(db, pList); - sqlite3SelectDelete(db, pSelect); - sqlite3IdListDelete(db, pColumn); - sqlite3DbFree(db, aRegIdx); -} - -/* Make sure "isView" and other macros defined above are undefined. Otherwise -** thely may interfere with compilation of other functions in this file -** (or in another file, if this file becomes part of the amalgamation). */ -#ifdef isView - #undef isView -#endif -#ifdef pTrigger - #undef pTrigger -#endif -#ifdef tmask - #undef tmask -#endif - - -/* -** Generate code to do constraint checks prior to an INSERT or an UPDATE. -** -** The input is a range of consecutive registers as follows: -** -** 1. The rowid of the row after the update. -** -** 2. The data in the first column of the entry after the update. -** -** i. Data from middle columns... -** -** N. The data in the last column of the entry after the update. -** -** The regRowid parameter is the index of the register containing (1). -** -** If isUpdate is true and rowidChng is non-zero, then rowidChng contains -** the address of a register containing the rowid before the update takes -** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate -** is false, indicating an INSERT statement, then a non-zero rowidChng -** indicates that the rowid was explicitly specified as part of the -** INSERT statement. If rowidChng is false, it means that the rowid is -** computed automatically in an insert or that the rowid value is not -** modified by an update. -** -** The code generated by this routine store new index entries into -** registers identified by aRegIdx[]. No index entry is created for -** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is -** the same as the order of indices on the linked list of indices -** attached to the table. -** -** This routine also generates code to check constraints. NOT NULL, -** CHECK, and UNIQUE constraints are all checked. If a constraint fails, -** then the appropriate action is performed. There are five possible -** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE. -** -** Constraint type Action What Happens -** --------------- ---------- ---------------------------------------- -** any ROLLBACK The current transaction is rolled back and -** sqlite3_exec() returns immediately with a -** return code of SQLITE_CONSTRAINT. -** -** any ABORT Back out changes from the current command -** only (do not do a complete rollback) then -** cause sqlite3_exec() to return immediately -** with SQLITE_CONSTRAINT. -** -** any FAIL Sqlite3_exec() returns immediately with a -** return code of SQLITE_CONSTRAINT. The -** transaction is not rolled back and any -** prior changes are retained. -** -** any IGNORE The record number and data is popped from -** the stack and there is an immediate jump -** to label ignoreDest. -** -** NOT NULL REPLACE The NULL value is replace by the default -** value for that column. If the default value -** is NULL, the action is the same as ABORT. -** -** UNIQUE REPLACE The other row that conflicts with the row -** being inserted is removed. -** -** CHECK REPLACE Illegal. The results in an exception. -** -** Which action to take is determined by the overrideError parameter. -** Or if overrideError==OE_Default, then the pParse->onError parameter -** is used. Or if pParse->onError==OE_Default then the onError value -** for the constraint is used. -** -** The calling routine must open a read/write cursor for pTab with -** cursor number "baseCur". All indices of pTab must also have open -** read/write cursors with cursor number baseCur+i for the i-th cursor. -** Except, if there is no possibility of a REPLACE action then -** cursors do not need to be open for indices where aRegIdx[i]==0. -*/ -SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( - Parse *pParse, /* The parser context */ - Table *pTab, /* the table into which we are inserting */ - int baseCur, /* Index of a read/write cursor pointing at pTab */ - int regRowid, /* Index of the range of input registers */ - int *aRegIdx, /* Register used by each index. 0 for unused indices */ - int rowidChng, /* True if the rowid might collide with existing entry */ - int isUpdate, /* True for UPDATE, False for INSERT */ - int overrideError, /* Override onError to this if not OE_Default */ - int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ - int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */ -){ - int i; /* loop counter */ - Vdbe *v; /* VDBE under constrution */ - int nCol; /* Number of columns */ - int onError; /* Conflict resolution strategy */ - int j1; /* Addresss of jump instruction */ - int j2 = 0, j3; /* Addresses of jump instructions */ - int regData; /* Register containing first data column */ - int iCur; /* Table cursor number */ - Index *pIdx; /* Pointer to one of the indices */ - sqlite3 *db; /* Database connection */ - int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ - int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid; - - db = pParse->db; - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); - assert( pTab->pSelect==0 ); /* This table is not a VIEW */ - nCol = pTab->nCol; - regData = regRowid + 1; - - /* Test all NOT NULL constraints. - */ - for(i=0; iiPKey ){ - continue; - } - onError = pTab->aCol[i].notNull; - if( onError==OE_None ) continue; - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ - onError = OE_Abort; - } - assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail - || onError==OE_Ignore || onError==OE_Replace ); - switch( onError ){ - case OE_Abort: - sqlite3MayAbort(pParse); - case OE_Rollback: - case OE_Fail: { - char *zMsg; - sqlite3VdbeAddOp3(v, OP_HaltIfNull, - SQLITE_CONSTRAINT_NOTNULL, onError, regData+i); - zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL", - pTab->zName, pTab->aCol[i].zName); - sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC); - break; - } - case OE_Ignore: { - sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest); - break; - } - default: { - assert( onError==OE_Replace ); - j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i); - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i); - sqlite3VdbeJumpHere(v, j1); - break; - } - } - } - - /* Test all CHECK constraints - */ -#ifndef SQLITE_OMIT_CHECK - if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ - ExprList *pCheck = pTab->pCheck; - pParse->ckBase = regData; - onError = overrideError!=OE_Default ? overrideError : OE_Abort; - for(i=0; inExpr; i++){ - int allOk = sqlite3VdbeMakeLabel(v); - sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); - if( onError==OE_Ignore ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); - }else{ - char *zConsName = pCheck->a[i].zName; - if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ - if( zConsName ){ - zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); - }else{ - zConsName = 0; - } - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK, - onError, zConsName, P4_DYNAMIC); - } - sqlite3VdbeResolveLabel(v, allOk); - } - } -#endif /* !defined(SQLITE_OMIT_CHECK) */ - - /* If we have an INTEGER PRIMARY KEY, make sure the primary key - ** of the new record does not previously exist. Except, if this - ** is an UPDATE and the primary key is not changing, that is OK. - */ - if( rowidChng ){ - onError = pTab->keyConf; - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - - if( isUpdate ){ - j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng); - } - j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid); - switch( onError ){ - default: { - onError = OE_Abort; - /* Fall thru into the next case */ - } - case OE_Rollback: - case OE_Abort: - case OE_Fail: { - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY, - onError, "PRIMARY KEY must be unique", P4_STATIC); - break; - } - case OE_Replace: { - /* If there are DELETE triggers on this table and the - ** recursive-triggers flag is set, call GenerateRowDelete() to - ** remove the conflicting row from the table. This will fire - ** the triggers and remove both the table and index b-tree entries. - ** - ** Otherwise, if there are no triggers or the recursive-triggers - ** flag is not set, but the table has one or more indexes, call - ** GenerateRowIndexDelete(). This removes the index b-tree entries - ** only. The table b-tree entry will be replaced by the new entry - ** when it is inserted. - ** - ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called, - ** also invoke MultiWrite() to indicate that this VDBE may require - ** statement rollback (if the statement is aborted after the delete - ** takes place). Earlier versions called sqlite3MultiWrite() regardless, - ** but being more selective here allows statements like: - ** - ** REPLACE INTO t(rowid) VALUES($newrowid) - ** - ** to run without a statement journal if there are no indexes on the - ** table. - */ - Trigger *pTrigger = 0; - if( db->flags&SQLITE_RecTriggers ){ - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); - } - if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ - sqlite3MultiWrite(pParse); - sqlite3GenerateRowDelete( - pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace - ); - }else if( pTab->pIndex ){ - sqlite3MultiWrite(pParse); - sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); - } - seenReplace = 1; - break; - } - case OE_Ignore: { - assert( seenReplace==0 ); - sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); - break; - } - } - sqlite3VdbeJumpHere(v, j3); - if( isUpdate ){ - sqlite3VdbeJumpHere(v, j2); - } - } - - /* Test all UNIQUE constraints by creating entries for each UNIQUE - ** index and making sure that duplicate entries do not already exist. - ** Add the new records to the indices as we go. - */ - for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){ - int regIdx; - int regR; - - if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */ - - /* Create a key for accessing the index entry */ - regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1); - for(i=0; inColumn; i++){ - int idx = pIdx->aiColumn[i]; - if( idx==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); - }else{ - sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i); - } - } - sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]); - sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT); - sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1); - - /* Find out what action to take in case there is an indexing conflict */ - onError = pIdx->onError; - if( onError==OE_None ){ - sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); - continue; /* pIdx is not a UNIQUE index */ - } - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - if( seenReplace ){ - if( onError==OE_Ignore ) onError = OE_Replace; - else if( onError==OE_Fail ) onError = OE_Abort; - } - - /* Check to see if the new index entry will be unique */ - regR = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR); - j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0, - regR, SQLITE_INT_TO_PTR(regIdx), - P4_INT32); - sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); - - /* Generate code that executes if the new index entry is not unique */ - assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail - || onError==OE_Ignore || onError==OE_Replace ); - switch( onError ){ - case OE_Rollback: - case OE_Abort: - case OE_Fail: { - int j; - StrAccum errMsg; - const char *zSep; - char *zErr; - - sqlite3StrAccumInit(&errMsg, 0, 0, 200); - errMsg.db = db; - zSep = pIdx->nColumn>1 ? "columns " : "column "; - for(j=0; jnColumn; j++){ - char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; - sqlite3StrAccumAppend(&errMsg, zSep, -1); - zSep = ", "; - sqlite3StrAccumAppend(&errMsg, zCol, -1); - } - sqlite3StrAccumAppend(&errMsg, - pIdx->nColumn>1 ? " are not unique" : " is not unique", -1); - zErr = sqlite3StrAccumFinish(&errMsg); - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE, - onError, zErr, 0); - sqlite3DbFree(errMsg.db, zErr); - break; - } - case OE_Ignore: { - assert( seenReplace==0 ); - sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); - break; - } - default: { - Trigger *pTrigger = 0; - assert( onError==OE_Replace ); - sqlite3MultiWrite(pParse); - if( db->flags&SQLITE_RecTriggers ){ - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); - } - sqlite3GenerateRowDelete( - pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace - ); - seenReplace = 1; - break; - } - } - sqlite3VdbeJumpHere(v, j3); - sqlite3ReleaseTempReg(pParse, regR); - } - - if( pbMayReplace ){ - *pbMayReplace = seenReplace; - } -} - -/* -** This routine generates code to finish the INSERT or UPDATE operation -** that was started by a prior call to sqlite3GenerateConstraintChecks. -** A consecutive range of registers starting at regRowid contains the -** rowid and the content to be inserted. -** -** The arguments to this routine should be the same as the first six -** arguments to sqlite3GenerateConstraintChecks. -*/ -SQLITE_PRIVATE void sqlite3CompleteInsertion( - Parse *pParse, /* The parser context */ - Table *pTab, /* the table into which we are inserting */ - int baseCur, /* Index of a read/write cursor pointing at pTab */ - int regRowid, /* Range of content */ - int *aRegIdx, /* Register used by each index. 0 for unused indices */ - int isUpdate, /* True for UPDATE, False for INSERT */ - int appendBias, /* True if this is likely to be an append */ - int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */ -){ - int i; - Vdbe *v; - int nIdx; - Index *pIdx; - u8 pik_flags; - int regData; - int regRec; - - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); - assert( pTab->pSelect==0 ); /* This table is not a VIEW */ - for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} - for(i=nIdx-1; i>=0; i--){ - if( aRegIdx[i]==0 ) continue; - sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); - if( useSeekResult ){ - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - } - } - regData = regRowid + 1; - regRec = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); - sqlite3TableAffinityStr(v, pTab); - sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); - if( pParse->nested ){ - pik_flags = 0; - }else{ - pik_flags = OPFLAG_NCHANGE; - pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); - } - if( appendBias ){ - pik_flags |= OPFLAG_APPEND; - } - if( useSeekResult ){ - pik_flags |= OPFLAG_USESEEKRESULT; - } - sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid); - if( !pParse->nested ){ - sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); - } - sqlite3VdbeChangeP5(v, pik_flags); -} - -/* -** Generate code that will open cursors for a table and for all -** indices of that table. The "baseCur" parameter is the cursor number used -** for the table. Indices are opened on subsequent cursors. -** -** Return the number of indices on the table. -*/ -SQLITE_PRIVATE int sqlite3OpenTableAndIndices( - Parse *pParse, /* Parsing context */ - Table *pTab, /* Table to be opened */ - int baseCur, /* Cursor number assigned to the table */ - int op /* OP_OpenRead or OP_OpenWrite */ -){ - int i; - int iDb; - Index *pIdx; - Vdbe *v; - - if( IsVirtual(pTab) ) return 0; - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); - sqlite3OpenTable(pParse, baseCur, iDb, pTab, op); - for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); - assert( pIdx->pSchema==pTab->pSchema ); - sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb, - (char*)pKey, P4_KEYINFO_HANDOFF); - VdbeComment((v, "%s", pIdx->zName)); - } - if( pParse->nTabnTab = baseCur+i; - } - return i-1; -} - - -#ifdef SQLITE_TEST -/* -** The following global variable is incremented whenever the -** transfer optimization is used. This is used for testing -** purposes only - to make sure the transfer optimization really -** is happening when it is suppose to. -*/ -SQLITE_API int sqlite3_xferopt_count; -#endif /* SQLITE_TEST */ - - -#ifndef SQLITE_OMIT_XFER_OPT -/* -** Check to collation names to see if they are compatible. -*/ -static int xferCompatibleCollation(const char *z1, const char *z2){ - if( z1==0 ){ - return z2==0; - } - if( z2==0 ){ - return 0; - } - return sqlite3StrICmp(z1, z2)==0; -} - - -/* -** Check to see if index pSrc is compatible as a source of data -** for index pDest in an insert transfer optimization. The rules -** for a compatible index: -** -** * The index is over the same set of columns -** * The same DESC and ASC markings occurs on all columns -** * The same onError processing (OE_Abort, OE_Ignore, etc) -** * The same collating sequence on each column -*/ -static int xferCompatibleIndex(Index *pDest, Index *pSrc){ - int i; - assert( pDest && pSrc ); - assert( pDest->pTable!=pSrc->pTable ); - if( pDest->nColumn!=pSrc->nColumn ){ - return 0; /* Different number of columns */ - } - if( pDest->onError!=pSrc->onError ){ - return 0; /* Different conflict resolution strategies */ - } - for(i=0; inColumn; i++){ - if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ - return 0; /* Different columns indexed */ - } - if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ - return 0; /* Different sort orders */ - } - if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){ - return 0; /* Different collating sequences */ - } - } - - /* If no test above fails then the indices must be compatible */ - return 1; -} - -/* -** Attempt the transfer optimization on INSERTs of the form -** -** INSERT INTO tab1 SELECT * FROM tab2; -** -** The xfer optimization transfers raw records from tab2 over to tab1. -** Columns are not decoded and reassemblied, which greatly improves -** performance. Raw index records are transferred in the same way. -** -** The xfer optimization is only attempted if tab1 and tab2 are compatible. -** There are lots of rules for determining compatibility - see comments -** embedded in the code for details. -** -** This routine returns TRUE if the optimization is guaranteed to be used. -** Sometimes the xfer optimization will only work if the destination table -** is empty - a factor that can only be determined at run-time. In that -** case, this routine generates code for the xfer optimization but also -** does a test to see if the destination table is empty and jumps over the -** xfer optimization code if the test fails. In that case, this routine -** returns FALSE so that the caller will know to go ahead and generate -** an unoptimized transfer. This routine also returns FALSE if there -** is no chance that the xfer optimization can be applied. -** -** This optimization is particularly useful at making VACUUM run faster. -*/ -static int xferOptimization( - Parse *pParse, /* Parser context */ - Table *pDest, /* The table we are inserting into */ - Select *pSelect, /* A SELECT statement to use as the data source */ - int onError, /* How to handle constraint errors */ - int iDbDest /* The database of pDest */ -){ - ExprList *pEList; /* The result set of the SELECT */ - Table *pSrc; /* The table in the FROM clause of SELECT */ - Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ - struct SrcList_item *pItem; /* An element of pSelect->pSrc */ - int i; /* Loop counter */ - int iDbSrc; /* The database of pSrc */ - int iSrc, iDest; /* Cursors from source and destination */ - int addr1, addr2; /* Loop addresses */ - int emptyDestTest; /* Address of test for empty pDest */ - int emptySrcTest; /* Address of test for empty pSrc */ - Vdbe *v; /* The VDBE we are building */ - KeyInfo *pKey; /* Key information for an index */ - int regAutoinc; /* Memory register used by AUTOINC */ - int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ - int regData, regRowid; /* Registers holding data and rowid */ - - if( pSelect==0 ){ - return 0; /* Must be of the form INSERT INTO ... SELECT ... */ - } - if( sqlite3TriggerList(pParse, pDest) ){ - return 0; /* tab1 must not have triggers */ - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( pDest->tabFlags & TF_Virtual ){ - return 0; /* tab1 must not be a virtual table */ - } -#endif - if( onError==OE_Default ){ - if( pDest->iPKey>=0 ) onError = pDest->keyConf; - if( onError==OE_Default ) onError = OE_Abort; - } - assert(pSelect->pSrc); /* allocated even if there is no FROM clause */ - if( pSelect->pSrc->nSrc!=1 ){ - return 0; /* FROM clause must have exactly one term */ - } - if( pSelect->pSrc->a[0].pSelect ){ - return 0; /* FROM clause cannot contain a subquery */ - } - if( pSelect->pWhere ){ - return 0; /* SELECT may not have a WHERE clause */ - } - if( pSelect->pOrderBy ){ - return 0; /* SELECT may not have an ORDER BY clause */ - } - /* Do not need to test for a HAVING clause. If HAVING is present but - ** there is no ORDER BY, we will get an error. */ - if( pSelect->pGroupBy ){ - return 0; /* SELECT may not have a GROUP BY clause */ - } - if( pSelect->pLimit ){ - return 0; /* SELECT may not have a LIMIT clause */ - } - assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ - if( pSelect->pPrior ){ - return 0; /* SELECT may not be a compound query */ - } - if( pSelect->selFlags & SF_Distinct ){ - return 0; /* SELECT may not be DISTINCT */ - } - pEList = pSelect->pEList; - assert( pEList!=0 ); - if( pEList->nExpr!=1 ){ - return 0; /* The result set must have exactly one column */ - } - assert( pEList->a[0].pExpr ); - if( pEList->a[0].pExpr->op!=TK_ALL ){ - return 0; /* The result set must be the special operator "*" */ - } - - /* At this point we have established that the statement is of the - ** correct syntactic form to participate in this optimization. Now - ** we have to check the semantics. - */ - pItem = pSelect->pSrc->a; - pSrc = sqlite3LocateTableItem(pParse, 0, pItem); - if( pSrc==0 ){ - return 0; /* FROM clause does not contain a real table */ - } - if( pSrc==pDest ){ - return 0; /* tab1 and tab2 may not be the same table */ - } -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( pSrc->tabFlags & TF_Virtual ){ - return 0; /* tab2 must not be a virtual table */ - } -#endif - if( pSrc->pSelect ){ - return 0; /* tab2 may not be a view */ - } - if( pDest->nCol!=pSrc->nCol ){ - return 0; /* Number of columns must be the same in tab1 and tab2 */ - } - if( pDest->iPKey!=pSrc->iPKey ){ - return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ - } - for(i=0; inCol; i++){ - if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){ - return 0; /* Affinity must be the same on all columns */ - } - if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){ - return 0; /* Collating sequence must be the same on all columns */ - } - if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){ - return 0; /* tab2 must be NOT NULL if tab1 is */ - } - } - for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ - if( pDestIdx->onError!=OE_None ){ - destHasUniqueIdx = 1; - } - for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ - if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; - } - if( pSrcIdx==0 ){ - return 0; /* pDestIdx has no corresponding index in pSrc */ - } - } -#ifndef SQLITE_OMIT_CHECK - if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){ - return 0; /* Tables have different CHECK constraints. Ticket #2252 */ - } -#endif -#ifndef SQLITE_OMIT_FOREIGN_KEY - /* Disallow the transfer optimization if the destination table constains - ** any foreign key constraints. This is more restrictive than necessary. - ** But the main beneficiary of the transfer optimization is the VACUUM - ** command, and the VACUUM command disables foreign key constraints. So - ** the extra complication to make this rule less restrictive is probably - ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] - */ - if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ - return 0; - } -#endif - if( (pParse->db->flags & SQLITE_CountRows)!=0 ){ - return 0; /* xfer opt does not play well with PRAGMA count_changes */ - } - - /* If we get this far, it means that the xfer optimization is at - ** least a possibility, though it might only work if the destination - ** table (tab1) is initially empty. - */ -#ifdef SQLITE_TEST - sqlite3_xferopt_count++; -#endif - iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); - v = sqlite3GetVdbe(pParse); - sqlite3CodeVerifySchema(pParse, iDbSrc); - iSrc = pParse->nTab++; - iDest = pParse->nTab++; - regAutoinc = autoIncBegin(pParse, iDbDest, pDest); - sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); - if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ - || destHasUniqueIdx /* (2) */ - || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ - ){ - /* In some circumstances, we are able to run the xfer optimization - ** only if the destination table is initially empty. This code makes - ** that determination. Conditions under which the destination must - ** be empty: - ** - ** (1) There is no INTEGER PRIMARY KEY but there are indices. - ** (If the destination is not initially empty, the rowid fields - ** of index entries might need to change.) - ** - ** (2) The destination has a unique index. (The xfer optimization - ** is unable to test uniqueness.) - ** - ** (3) onError is something other than OE_Abort and OE_Rollback. - */ - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); - emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); - sqlite3VdbeJumpHere(v, addr1); - }else{ - emptyDestTest = 0; - } - sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); - emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); - regData = sqlite3GetTempReg(pParse); - regRowid = sqlite3GetTempReg(pParse); - if( pDest->iPKey>=0 ){ - addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); - addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY, - onError, "PRIMARY KEY must be unique", P4_STATIC); - sqlite3VdbeJumpHere(v, addr2); - autoIncStep(pParse, regAutoinc, regRowid); - }else if( pDest->pIndex==0 ){ - addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); - }else{ - addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); - assert( (pDest->tabFlags & TF_Autoincrement)==0 ); - } - sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); - sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); - sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); - sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); - sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); - for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ - for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ - if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; - } - assert( pSrcIdx ); - sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); - sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); - pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); - sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc, - (char*)pKey, P4_KEYINFO_HANDOFF); - VdbeComment((v, "%s", pSrcIdx->zName)); - pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); - sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest, - (char*)pKey, P4_KEYINFO_HANDOFF); - VdbeComment((v, "%s", pDestIdx->zName)); - addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); - sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); - sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); - sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); - sqlite3VdbeJumpHere(v, addr1); - } - sqlite3VdbeJumpHere(v, emptySrcTest); - sqlite3ReleaseTempReg(pParse, regRowid); - sqlite3ReleaseTempReg(pParse, regData); - sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); - sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); - if( emptyDestTest ){ - sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); - sqlite3VdbeJumpHere(v, emptyDestTest); - sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); - return 0; - }else{ - return 1; - } -} -#endif /* SQLITE_OMIT_XFER_OPT */ - -/************** End of insert.c **********************************************/ -/************** Begin file legacy.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Main file for the SQLite library. The routines in this file -** implement the programmer interface to the library. Routines in -** other files are for internal use by SQLite and should not be -** accessed by users of the library. -*/ - - -/* -** Execute SQL code. Return one of the SQLITE_ success/failure -** codes. Also write an error message into memory obtained from -** malloc() and make *pzErrMsg point to that message. -** -** If the SQL is a query, then for each row in the query result -** the xCallback() function is called. pArg becomes the first -** argument to xCallback(). If xCallback=NULL then no callback -** is invoked, even for queries. -*/ -SQLITE_API int sqlite3_exec( - sqlite3 *db, /* The database on which the SQL executes */ - const char *zSql, /* The SQL to be executed */ - sqlite3_callback xCallback, /* Invoke this callback routine */ - void *pArg, /* First argument to xCallback() */ - char **pzErrMsg /* Write error messages here */ -){ - int rc = SQLITE_OK; /* Return code */ - const char *zLeftover; /* Tail of unprocessed SQL */ - sqlite3_stmt *pStmt = 0; /* The current SQL statement */ - char **azCols = 0; /* Names of result columns */ - int callbackIsInit; /* True if callback data is initialized */ - - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; - if( zSql==0 ) zSql = ""; - - sqlite3_mutex_enter(db->mutex); - sqlite3Error(db, SQLITE_OK, 0); - while( rc==SQLITE_OK && zSql[0] ){ - int nCol; - char **azVals = 0; - - pStmt = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); - assert( rc==SQLITE_OK || pStmt==0 ); - if( rc!=SQLITE_OK ){ - continue; - } - if( !pStmt ){ - /* this happens for a comment or white-space */ - zSql = zLeftover; - continue; - } - - callbackIsInit = 0; - nCol = sqlite3_column_count(pStmt); - - while( 1 ){ - int i; - rc = sqlite3_step(pStmt); - - /* Invoke the callback function if required */ - if( xCallback && (SQLITE_ROW==rc || - (SQLITE_DONE==rc && !callbackIsInit - && db->flags&SQLITE_NullCallback)) ){ - if( !callbackIsInit ){ - azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); - if( azCols==0 ){ - goto exec_out; - } - for(i=0; imallocFailed = 1; - goto exec_out; - } - } - } - if( xCallback(pArg, nCol, azVals, azCols) ){ - rc = SQLITE_ABORT; - sqlite3VdbeFinalize((Vdbe *)pStmt); - pStmt = 0; - sqlite3Error(db, SQLITE_ABORT, 0); - goto exec_out; - } - } - - if( rc!=SQLITE_ROW ){ - rc = sqlite3VdbeFinalize((Vdbe *)pStmt); - pStmt = 0; - zSql = zLeftover; - while( sqlite3Isspace(zSql[0]) ) zSql++; - break; - } - } - - sqlite3DbFree(db, azCols); - azCols = 0; - } - -exec_out: - if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt); - sqlite3DbFree(db, azCols); - - rc = sqlite3ApiExit(db, rc); - if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){ - int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db)); - *pzErrMsg = sqlite3Malloc(nErrMsg); - if( *pzErrMsg ){ - memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); - }else{ - rc = SQLITE_NOMEM; - sqlite3Error(db, SQLITE_NOMEM, 0); - } - }else if( pzErrMsg ){ - *pzErrMsg = 0; - } - - assert( (rc&db->errMask)==rc ); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/************** End of legacy.c **********************************************/ -/************** Begin file loadext.c *****************************************/ -/* -** 2006 June 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to dynamically load extensions into -** the SQLite library. -*/ - -#ifndef SQLITE_CORE - #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ -#endif -/************** Include sqlite3ext.h in the middle of loadext.c **************/ -/************** Begin file sqlite3ext.h **************************************/ -/* -** 2006 June 7 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the SQLite interface for use by -** shared libraries that want to be imported as extensions into -** an SQLite instance. Shared libraries that intend to be loaded -** as extensions by SQLite should #include this file instead of -** sqlite3.h. -*/ -#ifndef _SQLITE3EXT_H_ -#define _SQLITE3EXT_H_ - -typedef struct sqlite3_api_routines sqlite3_api_routines; - -/* -** The following structure holds pointers to all of the SQLite API -** routines. -** -** WARNING: In order to maintain backwards compatibility, add new -** interfaces to the end of this structure only. If you insert new -** interfaces in the middle of this structure, then older different -** versions of SQLite will not be able to load each others' shared -** libraries! -*/ -struct sqlite3_api_routines { - void * (*aggregate_context)(sqlite3_context*,int nBytes); - int (*aggregate_count)(sqlite3_context*); - int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); - int (*bind_double)(sqlite3_stmt*,int,double); - int (*bind_int)(sqlite3_stmt*,int,int); - int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); - int (*bind_null)(sqlite3_stmt*,int); - int (*bind_parameter_count)(sqlite3_stmt*); - int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); - const char * (*bind_parameter_name)(sqlite3_stmt*,int); - int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); - int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); - int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); - int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); - int (*busy_timeout)(sqlite3*,int ms); - int (*changes)(sqlite3*); - int (*close)(sqlite3*); - int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*, - int eTextRep,const char*)); - int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*, - int eTextRep,const void*)); - const void * (*column_blob)(sqlite3_stmt*,int iCol); - int (*column_bytes)(sqlite3_stmt*,int iCol); - int (*column_bytes16)(sqlite3_stmt*,int iCol); - int (*column_count)(sqlite3_stmt*pStmt); - const char * (*column_database_name)(sqlite3_stmt*,int); - const void * (*column_database_name16)(sqlite3_stmt*,int); - const char * (*column_decltype)(sqlite3_stmt*,int i); - const void * (*column_decltype16)(sqlite3_stmt*,int); - double (*column_double)(sqlite3_stmt*,int iCol); - int (*column_int)(sqlite3_stmt*,int iCol); - sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); - const char * (*column_name)(sqlite3_stmt*,int); - const void * (*column_name16)(sqlite3_stmt*,int); - const char * (*column_origin_name)(sqlite3_stmt*,int); - const void * (*column_origin_name16)(sqlite3_stmt*,int); - const char * (*column_table_name)(sqlite3_stmt*,int); - const void * (*column_table_name16)(sqlite3_stmt*,int); - const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); - const void * (*column_text16)(sqlite3_stmt*,int iCol); - int (*column_type)(sqlite3_stmt*,int iCol); - sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); - void * (*commit_hook)(sqlite3*,int(*)(void*),void*); - int (*complete)(const char*sql); - int (*complete16)(const void*sql); - int (*create_collation)(sqlite3*,const char*,int,void*, - int(*)(void*,int,const void*,int,const void*)); - int (*create_collation16)(sqlite3*,const void*,int,void*, - int(*)(void*,int,const void*,int,const void*)); - int (*create_function)(sqlite3*,const char*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*)); - int (*create_function16)(sqlite3*,const void*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*)); - int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); - int (*data_count)(sqlite3_stmt*pStmt); - sqlite3 * (*db_handle)(sqlite3_stmt*); - int (*declare_vtab)(sqlite3*,const char*); - int (*enable_shared_cache)(int); - int (*errcode)(sqlite3*db); - const char * (*errmsg)(sqlite3*); - const void * (*errmsg16)(sqlite3*); - int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); - int (*expired)(sqlite3_stmt*); - int (*finalize)(sqlite3_stmt*pStmt); - void (*free)(void*); - void (*free_table)(char**result); - int (*get_autocommit)(sqlite3*); - void * (*get_auxdata)(sqlite3_context*,int); - int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); - int (*global_recover)(void); - void (*interruptx)(sqlite3*); - sqlite_int64 (*last_insert_rowid)(sqlite3*); - const char * (*libversion)(void); - int (*libversion_number)(void); - void *(*malloc)(int); - char * (*mprintf)(const char*,...); - int (*open)(const char*,sqlite3**); - int (*open16)(const void*,sqlite3**); - int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); - int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); - void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); - void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); - void *(*realloc)(void*,int); - int (*reset)(sqlite3_stmt*pStmt); - void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_double)(sqlite3_context*,double); - void (*result_error)(sqlite3_context*,const char*,int); - void (*result_error16)(sqlite3_context*,const void*,int); - void (*result_int)(sqlite3_context*,int); - void (*result_int64)(sqlite3_context*,sqlite_int64); - void (*result_null)(sqlite3_context*); - void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); - void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); - void (*result_value)(sqlite3_context*,sqlite3_value*); - void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); - int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, - const char*,const char*),void*); - void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); - char * (*snprintf)(int,char*,const char*,...); - int (*step)(sqlite3_stmt*); - int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, - char const**,char const**,int*,int*,int*); - void (*thread_cleanup)(void); - int (*total_changes)(sqlite3*); - void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); - int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); - void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*, - sqlite_int64),void*); - void * (*user_data)(sqlite3_context*); - const void * (*value_blob)(sqlite3_value*); - int (*value_bytes)(sqlite3_value*); - int (*value_bytes16)(sqlite3_value*); - double (*value_double)(sqlite3_value*); - int (*value_int)(sqlite3_value*); - sqlite_int64 (*value_int64)(sqlite3_value*); - int (*value_numeric_type)(sqlite3_value*); - const unsigned char * (*value_text)(sqlite3_value*); - const void * (*value_text16)(sqlite3_value*); - const void * (*value_text16be)(sqlite3_value*); - const void * (*value_text16le)(sqlite3_value*); - int (*value_type)(sqlite3_value*); - char *(*vmprintf)(const char*,va_list); - /* Added ??? */ - int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); - /* Added by 3.3.13 */ - int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); - int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); - int (*clear_bindings)(sqlite3_stmt*); - /* Added by 3.4.1 */ - int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*, - void (*xDestroy)(void *)); - /* Added by 3.5.0 */ - int (*bind_zeroblob)(sqlite3_stmt*,int,int); - int (*blob_bytes)(sqlite3_blob*); - int (*blob_close)(sqlite3_blob*); - int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64, - int,sqlite3_blob**); - int (*blob_read)(sqlite3_blob*,void*,int,int); - int (*blob_write)(sqlite3_blob*,const void*,int,int); - int (*create_collation_v2)(sqlite3*,const char*,int,void*, - int(*)(void*,int,const void*,int,const void*), - void(*)(void*)); - int (*file_control)(sqlite3*,const char*,int,void*); - sqlite3_int64 (*memory_highwater)(int); - sqlite3_int64 (*memory_used)(void); - sqlite3_mutex *(*mutex_alloc)(int); - void (*mutex_enter)(sqlite3_mutex*); - void (*mutex_free)(sqlite3_mutex*); - void (*mutex_leave)(sqlite3_mutex*); - int (*mutex_try)(sqlite3_mutex*); - int (*open_v2)(const char*,sqlite3**,int,const char*); - int (*release_memory)(int); - void (*result_error_nomem)(sqlite3_context*); - void (*result_error_toobig)(sqlite3_context*); - int (*sleep)(int); - void (*soft_heap_limit)(int); - sqlite3_vfs *(*vfs_find)(const char*); - int (*vfs_register)(sqlite3_vfs*,int); - int (*vfs_unregister)(sqlite3_vfs*); - int (*xthreadsafe)(void); - void (*result_zeroblob)(sqlite3_context*,int); - void (*result_error_code)(sqlite3_context*,int); - int (*test_control)(int, ...); - void (*randomness)(int,void*); - sqlite3 *(*context_db_handle)(sqlite3_context*); - int (*extended_result_codes)(sqlite3*,int); - int (*limit)(sqlite3*,int,int); - sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*); - const char *(*sql)(sqlite3_stmt*); - int (*status)(int,int*,int*,int); - int (*backup_finish)(sqlite3_backup*); - sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*); - int (*backup_pagecount)(sqlite3_backup*); - int (*backup_remaining)(sqlite3_backup*); - int (*backup_step)(sqlite3_backup*,int); - const char *(*compileoption_get)(int); - int (*compileoption_used)(const char*); - int (*create_function_v2)(sqlite3*,const char*,int,int,void*, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void(*xDestroy)(void*)); - int (*db_config)(sqlite3*,int,...); - sqlite3_mutex *(*db_mutex)(sqlite3*); - int (*db_status)(sqlite3*,int,int*,int*,int); - int (*extended_errcode)(sqlite3*); - void (*log)(int,const char*,...); - sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64); - const char *(*sourceid)(void); - int (*stmt_status)(sqlite3_stmt*,int,int); - int (*strnicmp)(const char*,const char*,int); - int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); - int (*wal_autocheckpoint)(sqlite3*,int); - int (*wal_checkpoint)(sqlite3*,const char*); - void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); - int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); - int (*vtab_config)(sqlite3*,int op,...); - int (*vtab_on_conflict)(sqlite3*); - /* Version 3.7.16 and later */ - int (*close_v2)(sqlite3*); - const char *(*db_filename)(sqlite3*,const char*); - int (*db_readonly)(sqlite3*,const char*); - int (*db_release_memory)(sqlite3*); - const char *(*errstr)(int); - int (*stmt_busy)(sqlite3_stmt*); - int (*stmt_readonly)(sqlite3_stmt*); - int (*stricmp)(const char*,const char*); - int (*uri_boolean)(const char*,const char*,int); - sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); - const char *(*uri_parameter)(const char*,const char*); - char *(*vsnprintf)(int,char*,const char*,va_list); - int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); -}; - -/* -** The following macros redefine the API routines so that they are -** redirected throught the global sqlite3_api structure. -** -** This header file is also used by the loadext.c source file -** (part of the main SQLite library - not an extension) so that -** it can get access to the sqlite3_api_routines structure -** definition. But the main library does not want to redefine -** the API. So the redefinition macros are only valid if the -** SQLITE_CORE macros is undefined. -*/ -#ifndef SQLITE_CORE -#define sqlite3_aggregate_context sqlite3_api->aggregate_context -#ifndef SQLITE_OMIT_DEPRECATED -#define sqlite3_aggregate_count sqlite3_api->aggregate_count -#endif -#define sqlite3_bind_blob sqlite3_api->bind_blob -#define sqlite3_bind_double sqlite3_api->bind_double -#define sqlite3_bind_int sqlite3_api->bind_int -#define sqlite3_bind_int64 sqlite3_api->bind_int64 -#define sqlite3_bind_null sqlite3_api->bind_null -#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count -#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index -#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name -#define sqlite3_bind_text sqlite3_api->bind_text -#define sqlite3_bind_text16 sqlite3_api->bind_text16 -#define sqlite3_bind_value sqlite3_api->bind_value -#define sqlite3_busy_handler sqlite3_api->busy_handler -#define sqlite3_busy_timeout sqlite3_api->busy_timeout -#define sqlite3_changes sqlite3_api->changes -#define sqlite3_close sqlite3_api->close -#define sqlite3_collation_needed sqlite3_api->collation_needed -#define sqlite3_collation_needed16 sqlite3_api->collation_needed16 -#define sqlite3_column_blob sqlite3_api->column_blob -#define sqlite3_column_bytes sqlite3_api->column_bytes -#define sqlite3_column_bytes16 sqlite3_api->column_bytes16 -#define sqlite3_column_count sqlite3_api->column_count -#define sqlite3_column_database_name sqlite3_api->column_database_name -#define sqlite3_column_database_name16 sqlite3_api->column_database_name16 -#define sqlite3_column_decltype sqlite3_api->column_decltype -#define sqlite3_column_decltype16 sqlite3_api->column_decltype16 -#define sqlite3_column_double sqlite3_api->column_double -#define sqlite3_column_int sqlite3_api->column_int -#define sqlite3_column_int64 sqlite3_api->column_int64 -#define sqlite3_column_name sqlite3_api->column_name -#define sqlite3_column_name16 sqlite3_api->column_name16 -#define sqlite3_column_origin_name sqlite3_api->column_origin_name -#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 -#define sqlite3_column_table_name sqlite3_api->column_table_name -#define sqlite3_column_table_name16 sqlite3_api->column_table_name16 -#define sqlite3_column_text sqlite3_api->column_text -#define sqlite3_column_text16 sqlite3_api->column_text16 -#define sqlite3_column_type sqlite3_api->column_type -#define sqlite3_column_value sqlite3_api->column_value -#define sqlite3_commit_hook sqlite3_api->commit_hook -#define sqlite3_complete sqlite3_api->complete -#define sqlite3_complete16 sqlite3_api->complete16 -#define sqlite3_create_collation sqlite3_api->create_collation -#define sqlite3_create_collation16 sqlite3_api->create_collation16 -#define sqlite3_create_function sqlite3_api->create_function -#define sqlite3_create_function16 sqlite3_api->create_function16 -#define sqlite3_create_module sqlite3_api->create_module -#define sqlite3_create_module_v2 sqlite3_api->create_module_v2 -#define sqlite3_data_count sqlite3_api->data_count -#define sqlite3_db_handle sqlite3_api->db_handle -#define sqlite3_declare_vtab sqlite3_api->declare_vtab -#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache -#define sqlite3_errcode sqlite3_api->errcode -#define sqlite3_errmsg sqlite3_api->errmsg -#define sqlite3_errmsg16 sqlite3_api->errmsg16 -#define sqlite3_exec sqlite3_api->exec -#ifndef SQLITE_OMIT_DEPRECATED -#define sqlite3_expired sqlite3_api->expired -#endif -#define sqlite3_finalize sqlite3_api->finalize -#define sqlite3_free sqlite3_api->free -#define sqlite3_free_table sqlite3_api->free_table -#define sqlite3_get_autocommit sqlite3_api->get_autocommit -#define sqlite3_get_auxdata sqlite3_api->get_auxdata -#define sqlite3_get_table sqlite3_api->get_table -#ifndef SQLITE_OMIT_DEPRECATED -#define sqlite3_global_recover sqlite3_api->global_recover -#endif -#define sqlite3_interrupt sqlite3_api->interruptx -#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid -#define sqlite3_libversion sqlite3_api->libversion -#define sqlite3_libversion_number sqlite3_api->libversion_number -#define sqlite3_malloc sqlite3_api->malloc -#define sqlite3_mprintf sqlite3_api->mprintf -#define sqlite3_open sqlite3_api->open -#define sqlite3_open16 sqlite3_api->open16 -#define sqlite3_prepare sqlite3_api->prepare -#define sqlite3_prepare16 sqlite3_api->prepare16 -#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 -#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 -#define sqlite3_profile sqlite3_api->profile -#define sqlite3_progress_handler sqlite3_api->progress_handler -#define sqlite3_realloc sqlite3_api->realloc -#define sqlite3_reset sqlite3_api->reset -#define sqlite3_result_blob sqlite3_api->result_blob -#define sqlite3_result_double sqlite3_api->result_double -#define sqlite3_result_error sqlite3_api->result_error -#define sqlite3_result_error16 sqlite3_api->result_error16 -#define sqlite3_result_int sqlite3_api->result_int -#define sqlite3_result_int64 sqlite3_api->result_int64 -#define sqlite3_result_null sqlite3_api->result_null -#define sqlite3_result_text sqlite3_api->result_text -#define sqlite3_result_text16 sqlite3_api->result_text16 -#define sqlite3_result_text16be sqlite3_api->result_text16be -#define sqlite3_result_text16le sqlite3_api->result_text16le -#define sqlite3_result_value sqlite3_api->result_value -#define sqlite3_rollback_hook sqlite3_api->rollback_hook -#define sqlite3_set_authorizer sqlite3_api->set_authorizer -#define sqlite3_set_auxdata sqlite3_api->set_auxdata -#define sqlite3_snprintf sqlite3_api->snprintf -#define sqlite3_step sqlite3_api->step -#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata -#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup -#define sqlite3_total_changes sqlite3_api->total_changes -#define sqlite3_trace sqlite3_api->trace -#ifndef SQLITE_OMIT_DEPRECATED -#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings -#endif -#define sqlite3_update_hook sqlite3_api->update_hook -#define sqlite3_user_data sqlite3_api->user_data -#define sqlite3_value_blob sqlite3_api->value_blob -#define sqlite3_value_bytes sqlite3_api->value_bytes -#define sqlite3_value_bytes16 sqlite3_api->value_bytes16 -#define sqlite3_value_double sqlite3_api->value_double -#define sqlite3_value_int sqlite3_api->value_int -#define sqlite3_value_int64 sqlite3_api->value_int64 -#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type -#define sqlite3_value_text sqlite3_api->value_text -#define sqlite3_value_text16 sqlite3_api->value_text16 -#define sqlite3_value_text16be sqlite3_api->value_text16be -#define sqlite3_value_text16le sqlite3_api->value_text16le -#define sqlite3_value_type sqlite3_api->value_type -#define sqlite3_vmprintf sqlite3_api->vmprintf -#define sqlite3_overload_function sqlite3_api->overload_function -#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 -#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 -#define sqlite3_clear_bindings sqlite3_api->clear_bindings -#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob -#define sqlite3_blob_bytes sqlite3_api->blob_bytes -#define sqlite3_blob_close sqlite3_api->blob_close -#define sqlite3_blob_open sqlite3_api->blob_open -#define sqlite3_blob_read sqlite3_api->blob_read -#define sqlite3_blob_write sqlite3_api->blob_write -#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 -#define sqlite3_file_control sqlite3_api->file_control -#define sqlite3_memory_highwater sqlite3_api->memory_highwater -#define sqlite3_memory_used sqlite3_api->memory_used -#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc -#define sqlite3_mutex_enter sqlite3_api->mutex_enter -#define sqlite3_mutex_free sqlite3_api->mutex_free -#define sqlite3_mutex_leave sqlite3_api->mutex_leave -#define sqlite3_mutex_try sqlite3_api->mutex_try -#define sqlite3_open_v2 sqlite3_api->open_v2 -#define sqlite3_release_memory sqlite3_api->release_memory -#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem -#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig -#define sqlite3_sleep sqlite3_api->sleep -#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit -#define sqlite3_vfs_find sqlite3_api->vfs_find -#define sqlite3_vfs_register sqlite3_api->vfs_register -#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister -#define sqlite3_threadsafe sqlite3_api->xthreadsafe -#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob -#define sqlite3_result_error_code sqlite3_api->result_error_code -#define sqlite3_test_control sqlite3_api->test_control -#define sqlite3_randomness sqlite3_api->randomness -#define sqlite3_context_db_handle sqlite3_api->context_db_handle -#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes -#define sqlite3_limit sqlite3_api->limit -#define sqlite3_next_stmt sqlite3_api->next_stmt -#define sqlite3_sql sqlite3_api->sql -#define sqlite3_status sqlite3_api->status -#define sqlite3_backup_finish sqlite3_api->backup_finish -#define sqlite3_backup_init sqlite3_api->backup_init -#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount -#define sqlite3_backup_remaining sqlite3_api->backup_remaining -#define sqlite3_backup_step sqlite3_api->backup_step -#define sqlite3_compileoption_get sqlite3_api->compileoption_get -#define sqlite3_compileoption_used sqlite3_api->compileoption_used -#define sqlite3_create_function_v2 sqlite3_api->create_function_v2 -#define sqlite3_db_config sqlite3_api->db_config -#define sqlite3_db_mutex sqlite3_api->db_mutex -#define sqlite3_db_status sqlite3_api->db_status -#define sqlite3_extended_errcode sqlite3_api->extended_errcode -#define sqlite3_log sqlite3_api->log -#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64 -#define sqlite3_sourceid sqlite3_api->sourceid -#define sqlite3_stmt_status sqlite3_api->stmt_status -#define sqlite3_strnicmp sqlite3_api->strnicmp -#define sqlite3_unlock_notify sqlite3_api->unlock_notify -#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint -#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint -#define sqlite3_wal_hook sqlite3_api->wal_hook -#define sqlite3_blob_reopen sqlite3_api->blob_reopen -#define sqlite3_vtab_config sqlite3_api->vtab_config -#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict -/* Version 3.7.16 and later */ -#define sqlite3_close_v2 sqlite3_api->close_v2 -#define sqlite3_db_filename sqlite3_api->db_filename -#define sqlite3_db_readonly sqlite3_api->db_readonly -#define sqlite3_db_release_memory sqlite3_api->db_release_memory -#define sqlite3_errstr sqlite3_api->errstr -#define sqlite3_stmt_busy sqlite3_api->stmt_busy -#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly -#define sqlite3_stricmp sqlite3_api->stricmp -#define sqlite3_uri_boolean sqlite3_api->uri_boolean -#define sqlite3_uri_int64 sqlite3_api->uri_int64 -#define sqlite3_uri_parameter sqlite3_api->uri_parameter -#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf -#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 -#endif /* SQLITE_CORE */ - -#ifndef SQLITE_CORE - /* This case when the file really is being compiled as a loadable - ** extension */ -# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; -# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; -#else - /* This case when the file is being statically linked into the - ** application */ -# define SQLITE_EXTENSION_INIT1 /*no-op*/ -# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ -#endif - -#endif /* _SQLITE3EXT_H_ */ - -/************** End of sqlite3ext.h ******************************************/ -/************** Continuing where we left off in loadext.c ********************/ -/* #include */ - -#ifndef SQLITE_OMIT_LOAD_EXTENSION - -/* -** Some API routines are omitted when various features are -** excluded from a build of SQLite. Substitute a NULL pointer -** for any missing APIs. -*/ -#ifndef SQLITE_ENABLE_COLUMN_METADATA -# define sqlite3_column_database_name 0 -# define sqlite3_column_database_name16 0 -# define sqlite3_column_table_name 0 -# define sqlite3_column_table_name16 0 -# define sqlite3_column_origin_name 0 -# define sqlite3_column_origin_name16 0 -# define sqlite3_table_column_metadata 0 -#endif - -#ifdef SQLITE_OMIT_AUTHORIZATION -# define sqlite3_set_authorizer 0 -#endif - -#ifdef SQLITE_OMIT_UTF16 -# define sqlite3_bind_text16 0 -# define sqlite3_collation_needed16 0 -# define sqlite3_column_decltype16 0 -# define sqlite3_column_name16 0 -# define sqlite3_column_text16 0 -# define sqlite3_complete16 0 -# define sqlite3_create_collation16 0 -# define sqlite3_create_function16 0 -# define sqlite3_errmsg16 0 -# define sqlite3_open16 0 -# define sqlite3_prepare16 0 -# define sqlite3_prepare16_v2 0 -# define sqlite3_result_error16 0 -# define sqlite3_result_text16 0 -# define sqlite3_result_text16be 0 -# define sqlite3_result_text16le 0 -# define sqlite3_value_text16 0 -# define sqlite3_value_text16be 0 -# define sqlite3_value_text16le 0 -# define sqlite3_column_database_name16 0 -# define sqlite3_column_table_name16 0 -# define sqlite3_column_origin_name16 0 -#endif - -#ifdef SQLITE_OMIT_COMPLETE -# define sqlite3_complete 0 -# define sqlite3_complete16 0 -#endif - -#ifdef SQLITE_OMIT_DECLTYPE -# define sqlite3_column_decltype16 0 -# define sqlite3_column_decltype 0 -#endif - -#ifdef SQLITE_OMIT_PROGRESS_CALLBACK -# define sqlite3_progress_handler 0 -#endif - -#ifdef SQLITE_OMIT_VIRTUALTABLE -# define sqlite3_create_module 0 -# define sqlite3_create_module_v2 0 -# define sqlite3_declare_vtab 0 -# define sqlite3_vtab_config 0 -# define sqlite3_vtab_on_conflict 0 -#endif - -#ifdef SQLITE_OMIT_SHARED_CACHE -# define sqlite3_enable_shared_cache 0 -#endif - -#ifdef SQLITE_OMIT_TRACE -# define sqlite3_profile 0 -# define sqlite3_trace 0 -#endif - -#ifdef SQLITE_OMIT_GET_TABLE -# define sqlite3_free_table 0 -# define sqlite3_get_table 0 -#endif - -#ifdef SQLITE_OMIT_INCRBLOB -#define sqlite3_bind_zeroblob 0 -#define sqlite3_blob_bytes 0 -#define sqlite3_blob_close 0 -#define sqlite3_blob_open 0 -#define sqlite3_blob_read 0 -#define sqlite3_blob_write 0 -#define sqlite3_blob_reopen 0 -#endif - -/* -** The following structure contains pointers to all SQLite API routines. -** A pointer to this structure is passed into extensions when they are -** loaded so that the extension can make calls back into the SQLite -** library. -** -** When adding new APIs, add them to the bottom of this structure -** in order to preserve backwards compatibility. -** -** Extensions that use newer APIs should first call the -** sqlite3_libversion_number() to make sure that the API they -** intend to use is supported by the library. Extensions should -** also check to make sure that the pointer to the function is -** not NULL before calling it. -*/ -static const sqlite3_api_routines sqlite3Apis = { - sqlite3_aggregate_context, -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_aggregate_count, -#else - 0, -#endif - sqlite3_bind_blob, - sqlite3_bind_double, - sqlite3_bind_int, - sqlite3_bind_int64, - sqlite3_bind_null, - sqlite3_bind_parameter_count, - sqlite3_bind_parameter_index, - sqlite3_bind_parameter_name, - sqlite3_bind_text, - sqlite3_bind_text16, - sqlite3_bind_value, - sqlite3_busy_handler, - sqlite3_busy_timeout, - sqlite3_changes, - sqlite3_close, - sqlite3_collation_needed, - sqlite3_collation_needed16, - sqlite3_column_blob, - sqlite3_column_bytes, - sqlite3_column_bytes16, - sqlite3_column_count, - sqlite3_column_database_name, - sqlite3_column_database_name16, - sqlite3_column_decltype, - sqlite3_column_decltype16, - sqlite3_column_double, - sqlite3_column_int, - sqlite3_column_int64, - sqlite3_column_name, - sqlite3_column_name16, - sqlite3_column_origin_name, - sqlite3_column_origin_name16, - sqlite3_column_table_name, - sqlite3_column_table_name16, - sqlite3_column_text, - sqlite3_column_text16, - sqlite3_column_type, - sqlite3_column_value, - sqlite3_commit_hook, - sqlite3_complete, - sqlite3_complete16, - sqlite3_create_collation, - sqlite3_create_collation16, - sqlite3_create_function, - sqlite3_create_function16, - sqlite3_create_module, - sqlite3_data_count, - sqlite3_db_handle, - sqlite3_declare_vtab, - sqlite3_enable_shared_cache, - sqlite3_errcode, - sqlite3_errmsg, - sqlite3_errmsg16, - sqlite3_exec, -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_expired, -#else - 0, -#endif - sqlite3_finalize, - sqlite3_free, - sqlite3_free_table, - sqlite3_get_autocommit, - sqlite3_get_auxdata, - sqlite3_get_table, - 0, /* Was sqlite3_global_recover(), but that function is deprecated */ - sqlite3_interrupt, - sqlite3_last_insert_rowid, - sqlite3_libversion, - sqlite3_libversion_number, - sqlite3_malloc, - sqlite3_mprintf, - sqlite3_open, - sqlite3_open16, - sqlite3_prepare, - sqlite3_prepare16, - sqlite3_profile, - sqlite3_progress_handler, - sqlite3_realloc, - sqlite3_reset, - sqlite3_result_blob, - sqlite3_result_double, - sqlite3_result_error, - sqlite3_result_error16, - sqlite3_result_int, - sqlite3_result_int64, - sqlite3_result_null, - sqlite3_result_text, - sqlite3_result_text16, - sqlite3_result_text16be, - sqlite3_result_text16le, - sqlite3_result_value, - sqlite3_rollback_hook, - sqlite3_set_authorizer, - sqlite3_set_auxdata, - sqlite3_snprintf, - sqlite3_step, - sqlite3_table_column_metadata, -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_thread_cleanup, -#else - 0, -#endif - sqlite3_total_changes, - sqlite3_trace, -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_transfer_bindings, -#else - 0, -#endif - sqlite3_update_hook, - sqlite3_user_data, - sqlite3_value_blob, - sqlite3_value_bytes, - sqlite3_value_bytes16, - sqlite3_value_double, - sqlite3_value_int, - sqlite3_value_int64, - sqlite3_value_numeric_type, - sqlite3_value_text, - sqlite3_value_text16, - sqlite3_value_text16be, - sqlite3_value_text16le, - sqlite3_value_type, - sqlite3_vmprintf, - /* - ** The original API set ends here. All extensions can call any - ** of the APIs above provided that the pointer is not NULL. But - ** before calling APIs that follow, extension should check the - ** sqlite3_libversion_number() to make sure they are dealing with - ** a library that is new enough to support that API. - ************************************************************************* - */ - sqlite3_overload_function, - - /* - ** Added after 3.3.13 - */ - sqlite3_prepare_v2, - sqlite3_prepare16_v2, - sqlite3_clear_bindings, - - /* - ** Added for 3.4.1 - */ - sqlite3_create_module_v2, - - /* - ** Added for 3.5.0 - */ - sqlite3_bind_zeroblob, - sqlite3_blob_bytes, - sqlite3_blob_close, - sqlite3_blob_open, - sqlite3_blob_read, - sqlite3_blob_write, - sqlite3_create_collation_v2, - sqlite3_file_control, - sqlite3_memory_highwater, - sqlite3_memory_used, -#ifdef SQLITE_MUTEX_OMIT - 0, - 0, - 0, - 0, - 0, -#else - sqlite3_mutex_alloc, - sqlite3_mutex_enter, - sqlite3_mutex_free, - sqlite3_mutex_leave, - sqlite3_mutex_try, -#endif - sqlite3_open_v2, - sqlite3_release_memory, - sqlite3_result_error_nomem, - sqlite3_result_error_toobig, - sqlite3_sleep, - sqlite3_soft_heap_limit, - sqlite3_vfs_find, - sqlite3_vfs_register, - sqlite3_vfs_unregister, - - /* - ** Added for 3.5.8 - */ - sqlite3_threadsafe, - sqlite3_result_zeroblob, - sqlite3_result_error_code, - sqlite3_test_control, - sqlite3_randomness, - sqlite3_context_db_handle, - - /* - ** Added for 3.6.0 - */ - sqlite3_extended_result_codes, - sqlite3_limit, - sqlite3_next_stmt, - sqlite3_sql, - sqlite3_status, - - /* - ** Added for 3.7.4 - */ - sqlite3_backup_finish, - sqlite3_backup_init, - sqlite3_backup_pagecount, - sqlite3_backup_remaining, - sqlite3_backup_step, -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - sqlite3_compileoption_get, - sqlite3_compileoption_used, -#else - 0, - 0, -#endif - sqlite3_create_function_v2, - sqlite3_db_config, - sqlite3_db_mutex, - sqlite3_db_status, - sqlite3_extended_errcode, - sqlite3_log, - sqlite3_soft_heap_limit64, - sqlite3_sourceid, - sqlite3_stmt_status, - sqlite3_strnicmp, -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - sqlite3_unlock_notify, -#else - 0, -#endif -#ifndef SQLITE_OMIT_WAL - sqlite3_wal_autocheckpoint, - sqlite3_wal_checkpoint, - sqlite3_wal_hook, -#else - 0, - 0, - 0, -#endif - sqlite3_blob_reopen, - sqlite3_vtab_config, - sqlite3_vtab_on_conflict, - sqlite3_close_v2, - sqlite3_db_filename, - sqlite3_db_readonly, - sqlite3_db_release_memory, - sqlite3_errstr, - sqlite3_stmt_busy, - sqlite3_stmt_readonly, - sqlite3_stricmp, - sqlite3_uri_boolean, - sqlite3_uri_int64, - sqlite3_uri_parameter, - sqlite3_vsnprintf, - sqlite3_wal_checkpoint_v2 -}; - -/* -** Attempt to load an SQLite extension library contained in the file -** zFile. The entry point is zProc. zProc may be 0 in which case a -** default entry point name (sqlite3_extension_init) is used. Use -** of the default name is recommended. -** -** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong. -** -** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with -** error message text. The calling function should free this memory -** by calling sqlite3DbFree(db, ). -*/ -static int sqlite3LoadExtension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -){ - sqlite3_vfs *pVfs = db->pVfs; - void *handle; - int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); - char *zErrmsg = 0; - const char *zEntry; - char *zAltEntry = 0; - void **aHandle; - int nMsg = 300 + sqlite3Strlen30(zFile); - int ii; - - /* Shared library endings to try if zFile cannot be loaded as written */ - static const char *azEndings[] = { -#if SQLITE_OS_WIN - "dll" -#elif defined(__APPLE__) - "dylib" -#else - "so" -#endif - }; - - - if( pzErrMsg ) *pzErrMsg = 0; - - /* Ticket #1863. To avoid a creating security problems for older - ** applications that relink against newer versions of SQLite, the - ** ability to run load_extension is turned off by default. One - ** must call sqlite3_enable_load_extension() to turn on extension - ** loading. Otherwise you get the following error. - */ - if( (db->flags & SQLITE_LoadExtension)==0 ){ - if( pzErrMsg ){ - *pzErrMsg = sqlite3_mprintf("not authorized"); - } - return SQLITE_ERROR; - } - - zEntry = zProc ? zProc : "sqlite3_extension_init"; - - handle = sqlite3OsDlOpen(pVfs, zFile); -#if SQLITE_OS_UNIX || SQLITE_OS_WIN - for(ii=0; ii sqlite3_example_init - ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init - */ - if( xInit==0 && zProc==0 ){ - int iFile, iEntry, c; - int ncFile = sqlite3Strlen30(zFile); - zAltEntry = sqlite3_malloc(ncFile+30); - if( zAltEntry==0 ){ - sqlite3OsDlClose(pVfs, handle); - return SQLITE_NOMEM; - } - memcpy(zAltEntry, "sqlite3_", 8); - for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){} - iFile++; - if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; - for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ - if( sqlite3Isalpha(c) ){ - zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; - } - } - memcpy(zAltEntry+iEntry, "_init", 6); - zEntry = zAltEntry; - xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) - sqlite3OsDlSym(pVfs, handle, zEntry); - } - if( xInit==0 ){ - if( pzErrMsg ){ - nMsg += sqlite3Strlen30(zEntry); - *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); - if( zErrmsg ){ - sqlite3_snprintf(nMsg, zErrmsg, - "no entry point [%s] in shared library [%s]", zEntry, zFile); - sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); - } - } - sqlite3OsDlClose(pVfs, handle); - sqlite3_free(zAltEntry); - return SQLITE_ERROR; - } - sqlite3_free(zAltEntry); - if( xInit(db, &zErrmsg, &sqlite3Apis) ){ - if( pzErrMsg ){ - *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg); - } - sqlite3_free(zErrmsg); - sqlite3OsDlClose(pVfs, handle); - return SQLITE_ERROR; - } - - /* Append the new shared library handle to the db->aExtension array. */ - aHandle = sqlite3DbMallocZero(db, sizeof(handle)*(db->nExtension+1)); - if( aHandle==0 ){ - return SQLITE_NOMEM; - } - if( db->nExtension>0 ){ - memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension); - } - sqlite3DbFree(db, db->aExtension); - db->aExtension = aHandle; - - db->aExtension[db->nExtension++] = handle; - return SQLITE_OK; -} -SQLITE_API int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -){ - int rc; - sqlite3_mutex_enter(db->mutex); - rc = sqlite3LoadExtension(db, zFile, zProc, pzErrMsg); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Call this routine when the database connection is closing in order -** to clean up loaded extensions -*/ -SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){ - int i; - assert( sqlite3_mutex_held(db->mutex) ); - for(i=0; inExtension; i++){ - sqlite3OsDlClose(db->pVfs, db->aExtension[i]); - } - sqlite3DbFree(db, db->aExtension); -} - -/* -** Enable or disable extension loading. Extension loading is disabled by -** default so as not to open security holes in older applications. -*/ -SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ - sqlite3_mutex_enter(db->mutex); - if( onoff ){ - db->flags |= SQLITE_LoadExtension; - }else{ - db->flags &= ~SQLITE_LoadExtension; - } - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - -/* -** The auto-extension code added regardless of whether or not extension -** loading is supported. We need a dummy sqlite3Apis pointer for that -** code if regular extension loading is not available. This is that -** dummy pointer. -*/ -#ifdef SQLITE_OMIT_LOAD_EXTENSION -static const sqlite3_api_routines sqlite3Apis = { 0 }; -#endif - - -/* -** The following object holds the list of automatically loaded -** extensions. -** -** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER -** mutex must be held while accessing this list. -*/ -typedef struct sqlite3AutoExtList sqlite3AutoExtList; -static SQLITE_WSD struct sqlite3AutoExtList { - int nExt; /* Number of entries in aExt[] */ - void (**aExt)(void); /* Pointers to the extension init functions */ -} sqlite3Autoext = { 0, 0 }; - -/* The "wsdAutoext" macro will resolve to the autoextension -** state vector. If writable static data is unsupported on the target, -** we have to locate the state vector at run-time. In the more common -** case where writable static data is supported, wsdStat can refer directly -** to the "sqlite3Autoext" state vector declared above. -*/ -#ifdef SQLITE_OMIT_WSD -# define wsdAutoextInit \ - sqlite3AutoExtList *x = &GLOBAL(sqlite3AutoExtList,sqlite3Autoext) -# define wsdAutoext x[0] -#else -# define wsdAutoextInit -# define wsdAutoext sqlite3Autoext -#endif - - -/* -** Register a statically linked extension that is automatically -** loaded by every new database connection. -*/ -SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){ - int rc = SQLITE_OK; -#ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ){ - return rc; - }else -#endif - { - int i; -#if SQLITE_THREADSAFE - sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); -#endif - wsdAutoextInit; - sqlite3_mutex_enter(mutex); - for(i=0; i=wsdAutoext.nExt ){ - xInit = 0; - go = 0; - }else{ - xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) - wsdAutoext.aExt[i]; - } - sqlite3_mutex_leave(mutex); - zErrmsg = 0; - if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){ - sqlite3Error(db, rc, - "automatic extension loading failed: %s", zErrmsg); - go = 0; - } - sqlite3_free(zErrmsg); - } -} - -/************** End of loadext.c *********************************************/ -/************** Begin file pragma.c ******************************************/ -/* -** 2003 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the PRAGMA command. -*/ - -/* -** Interpret the given string as a safety level. Return 0 for OFF, -** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or -** unrecognized string argument. The FULL option is disallowed -** if the omitFull parameter it 1. -** -** Note that the values returned are one less that the values that -** should be passed into sqlite3BtreeSetSafetyLevel(). The is done -** to support legacy SQL code. The safety level used to be boolean -** and older scripts may have used numbers 0 for OFF and 1 for ON. -*/ -static u8 getSafetyLevel(const char *z, int omitFull, int dflt){ - /* 123456789 123456789 */ - static const char zText[] = "onoffalseyestruefull"; - static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; - static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; - static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; - int i, n; - if( sqlite3Isdigit(*z) ){ - return (u8)sqlite3Atoi(z); - } - n = sqlite3Strlen30(z); - for(i=0; i=0&&i<=2)?i:0); -} -#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* -** Interpret the given string as a temp db location. Return 1 for file -** backed temporary databases, 2 for the Red-Black tree in memory database -** and 0 to use the compile-time default. -*/ -static int getTempStore(const char *z){ - if( z[0]>='0' && z[0]<='2' ){ - return z[0] - '0'; - }else if( sqlite3StrICmp(z, "file")==0 ){ - return 1; - }else if( sqlite3StrICmp(z, "memory")==0 ){ - return 2; - }else{ - return 0; - } -} -#endif /* SQLITE_PAGER_PRAGMAS */ - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* -** Invalidate temp storage, either when the temp storage is changed -** from default, or when 'file' and the temp_store_directory has changed -*/ -static int invalidateTempStorage(Parse *pParse){ - sqlite3 *db = pParse->db; - if( db->aDb[1].pBt!=0 ){ - if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){ - sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " - "from within a transaction"); - return SQLITE_ERROR; - } - sqlite3BtreeClose(db->aDb[1].pBt); - db->aDb[1].pBt = 0; - sqlite3ResetAllSchemasOfConnection(db); - } - return SQLITE_OK; -} -#endif /* SQLITE_PAGER_PRAGMAS */ - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* -** If the TEMP database is open, close it and mark the database schema -** as needing reloading. This must be done when using the SQLITE_TEMP_STORE -** or DEFAULT_TEMP_STORE pragmas. -*/ -static int changeTempStorage(Parse *pParse, const char *zStorageType){ - int ts = getTempStore(zStorageType); - sqlite3 *db = pParse->db; - if( db->temp_store==ts ) return SQLITE_OK; - if( invalidateTempStorage( pParse ) != SQLITE_OK ){ - return SQLITE_ERROR; - } - db->temp_store = (u8)ts; - return SQLITE_OK; -} -#endif /* SQLITE_PAGER_PRAGMAS */ - -/* -** Generate code to return a single integer value. -*/ -static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){ - Vdbe *v = sqlite3GetVdbe(pParse); - int mem = ++pParse->nMem; - i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value)); - if( pI64 ){ - memcpy(pI64, &value, sizeof(value)); - } - sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); -} - -#ifndef SQLITE_OMIT_FLAG_PRAGMAS -/* -** Check to see if zRight and zLeft refer to a pragma that queries -** or changes one of the flags in db->flags. Return 1 if so and 0 if not. -** Also, implement the pragma. -*/ -static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ - static const struct sPragmaType { - const char *zName; /* Name of the pragma */ - int mask; /* Mask for the db->flags value */ - } aPragma[] = { - { "full_column_names", SQLITE_FullColNames }, - { "short_column_names", SQLITE_ShortColNames }, - { "count_changes", SQLITE_CountRows }, - { "empty_result_callbacks", SQLITE_NullCallback }, - { "legacy_file_format", SQLITE_LegacyFileFmt }, - { "fullfsync", SQLITE_FullFSync }, - { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, - { "reverse_unordered_selects", SQLITE_ReverseOrder }, -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX - { "automatic_index", SQLITE_AutoIndex }, -#endif -#ifdef SQLITE_DEBUG - { "sql_trace", SQLITE_SqlTrace }, - { "vdbe_listing", SQLITE_VdbeListing }, - { "vdbe_trace", SQLITE_VdbeTrace }, - { "vdbe_addoptrace", SQLITE_VdbeAddopTrace}, - { "vdbe_debug", SQLITE_SqlTrace | SQLITE_VdbeListing - | SQLITE_VdbeTrace }, -#endif -#ifndef SQLITE_OMIT_CHECK - { "ignore_check_constraints", SQLITE_IgnoreChecks }, -#endif - /* The following is VERY experimental */ - { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, - - /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted - ** flag if there are any active statements. */ - { "read_uncommitted", SQLITE_ReadUncommitted }, - { "recursive_triggers", SQLITE_RecTriggers }, - - /* This flag may only be set if both foreign-key and trigger support - ** are present in the build. */ -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { "foreign_keys", SQLITE_ForeignKeys }, -#endif - }; - int i; - const struct sPragmaType *p; - for(i=0, p=aPragma; izName)==0 ){ - sqlite3 *db = pParse->db; - Vdbe *v; - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); /* Already allocated by sqlite3Pragma() */ - if( ALWAYS(v) ){ - if( zRight==0 ){ - returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 ); - }else{ - int mask = p->mask; /* Mask of bits to set or clear. */ - if( db->autoCommit==0 ){ - /* Foreign key support may not be enabled or disabled while not - ** in auto-commit mode. */ - mask &= ~(SQLITE_ForeignKeys); - } - - if( sqlite3GetBoolean(zRight, 0) ){ - db->flags |= mask; - }else{ - db->flags &= ~mask; - } - - /* Many of the flag-pragmas modify the code generated by the SQL - ** compiler (eg. count_changes). So add an opcode to expire all - ** compiled SQL statements after modifying a pragma value. - */ - sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); - } - } - - return 1; - } - } - return 0; -} -#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ - -/* -** Return a human-readable name for a constraint resolution action. -*/ -#ifndef SQLITE_OMIT_FOREIGN_KEY -static const char *actionName(u8 action){ - const char *zName; - switch( action ){ - case OE_SetNull: zName = "SET NULL"; break; - case OE_SetDflt: zName = "SET DEFAULT"; break; - case OE_Cascade: zName = "CASCADE"; break; - case OE_Restrict: zName = "RESTRICT"; break; - default: zName = "NO ACTION"; - assert( action==OE_None ); break; - } - return zName; -} -#endif - - -/* -** Parameter eMode must be one of the PAGER_JOURNALMODE_XXX constants -** defined in pager.h. This function returns the associated lowercase -** journal-mode name. -*/ -SQLITE_PRIVATE const char *sqlite3JournalModename(int eMode){ - static char * const azModeName[] = { - "delete", "persist", "off", "truncate", "memory" -#ifndef SQLITE_OMIT_WAL - , "wal" -#endif - }; - assert( PAGER_JOURNALMODE_DELETE==0 ); - assert( PAGER_JOURNALMODE_PERSIST==1 ); - assert( PAGER_JOURNALMODE_OFF==2 ); - assert( PAGER_JOURNALMODE_TRUNCATE==3 ); - assert( PAGER_JOURNALMODE_MEMORY==4 ); - assert( PAGER_JOURNALMODE_WAL==5 ); - assert( eMode>=0 && eMode<=ArraySize(azModeName) ); - - if( eMode==ArraySize(azModeName) ) return 0; - return azModeName[eMode]; -} - -/* -** Process a pragma statement. -** -** Pragmas are of this form: -** -** PRAGMA [database.]id [= value] -** -** The identifier might also be a string. The value is a string, and -** identifier, or a number. If minusFlag is true, then the value is -** a number that was preceded by a minus sign. -** -** If the left side is "database.id" then pId1 is the database name -** and pId2 is the id. If the left side is just "id" then pId1 is the -** id and pId2 is any empty string. -*/ -SQLITE_PRIVATE void sqlite3Pragma( - Parse *pParse, - Token *pId1, /* First part of [database.]id field */ - Token *pId2, /* Second part of [database.]id field, or NULL */ - Token *pValue, /* Token for , or NULL */ - int minusFlag /* True if a '-' sign preceded */ -){ - char *zLeft = 0; /* Nul-terminated UTF-8 string */ - char *zRight = 0; /* Nul-terminated UTF-8 string , or NULL */ - const char *zDb = 0; /* The database name */ - Token *pId; /* Pointer to token */ - int iDb; /* Database index for */ - char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ - int rc; /* return value form SQLITE_FCNTL_PRAGMA */ - sqlite3 *db = pParse->db; /* The database connection */ - Db *pDb; /* The specific database being pragmaed */ - Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ - - if( v==0 ) return; - sqlite3VdbeRunOnlyOnce(v); - pParse->nMem = 2; - - /* Interpret the [database.] part of the pragma statement. iDb is the - ** index of the database this pragma is being applied to in db.aDb[]. */ - iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); - if( iDb<0 ) return; - pDb = &db->aDb[iDb]; - - /* If the temp database has been explicitly named as part of the - ** pragma, make sure it is open. - */ - if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){ - return; - } - - zLeft = sqlite3NameFromToken(db, pId); - if( !zLeft ) return; - if( minusFlag ){ - zRight = sqlite3MPrintf(db, "-%T", pValue); - }else{ - zRight = sqlite3NameFromToken(db, pValue); - } - - assert( pId2 ); - zDb = pId2->n>0 ? pDb->zName : 0; - if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ - goto pragma_out; - } - - /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS - ** connection. If it returns SQLITE_OK, then assume that the VFS - ** handled the pragma and generate a no-op prepared statement. - */ - aFcntl[0] = 0; - aFcntl[1] = zLeft; - aFcntl[2] = zRight; - aFcntl[3] = 0; - db->busyHandler.nBusy = 0; - rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); - if( rc==SQLITE_OK ){ - if( aFcntl[0] ){ - int mem = ++pParse->nMem; - sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); - sqlite3_free(aFcntl[0]); - } - }else if( rc!=SQLITE_NOTFOUND ){ - if( aFcntl[0] ){ - sqlite3ErrorMsg(pParse, "%s", aFcntl[0]); - sqlite3_free(aFcntl[0]); - } - pParse->nErr++; - pParse->rc = rc; - }else - - -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) - /* - ** PRAGMA [database.]default_cache_size - ** PRAGMA [database.]default_cache_size=N - ** - ** The first form reports the current persistent setting for the - ** page cache size. The value returned is the maximum number of - ** pages in the page cache. The second form sets both the current - ** page cache size value and the persistent page cache size value - ** stored in the database file. - ** - ** Older versions of SQLite would set the default cache size to a - ** negative number to indicate synchronous=OFF. These days, synchronous - ** is always on by default regardless of the sign of the default cache - ** size. But continue to take the absolute value of the default cache - ** size of historical compatibility. - */ - if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ - static const VdbeOpList getCacheSize[] = { - { OP_Transaction, 0, 0, 0}, /* 0 */ - { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ - { OP_IfPos, 1, 8, 0}, - { OP_Integer, 0, 2, 0}, - { OP_Subtract, 1, 2, 1}, - { OP_IfPos, 1, 8, 0}, - { OP_Integer, 0, 1, 0}, /* 6 */ - { OP_Noop, 0, 0, 0}, - { OP_ResultRow, 1, 1, 0}, - }; - int addr; - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - sqlite3VdbeUsesBtree(v, iDb); - if( !zRight ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); - pParse->nMem += 2; - addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); - sqlite3VdbeChangeP1(v, addr, iDb); - sqlite3VdbeChangeP1(v, addr+1, iDb); - sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE); - }else{ - int size = sqlite3AbsInt32(sqlite3Atoi(zRight)); - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3VdbeAddOp2(v, OP_Integer, size, 1); - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pDb->pSchema->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); - } - }else -#endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */ - -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - /* - ** PRAGMA [database.]page_size - ** PRAGMA [database.]page_size=N - ** - ** The first form reports the current setting for the - ** database page size in bytes. The second form sets the - ** database page size value. The value can only be set if - ** the database has not yet been created. - */ - if( sqlite3StrICmp(zLeft,"page_size")==0 ){ - Btree *pBt = pDb->pBt; - assert( pBt!=0 ); - if( !zRight ){ - int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0; - returnSingleInt(pParse, "page_size", size); - }else{ - /* Malloc may fail when setting the page-size, as there is an internal - ** buffer that the pager module resizes using sqlite3_realloc(). - */ - db->nextPagesize = sqlite3Atoi(zRight); - if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){ - db->mallocFailed = 1; - } - } - }else - - /* - ** PRAGMA [database.]secure_delete - ** PRAGMA [database.]secure_delete=ON/OFF - ** - ** The first form reports the current setting for the - ** secure_delete flag. The second form changes the secure_delete - ** flag setting and reports thenew value. - */ - if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){ - Btree *pBt = pDb->pBt; - int b = -1; - assert( pBt!=0 ); - if( zRight ){ - b = sqlite3GetBoolean(zRight, 0); - } - if( pId2->n==0 && b>=0 ){ - int ii; - for(ii=0; iinDb; ii++){ - sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b); - } - } - b = sqlite3BtreeSecureDelete(pBt, b); - returnSingleInt(pParse, "secure_delete", b); - }else - - /* - ** PRAGMA [database.]max_page_count - ** PRAGMA [database.]max_page_count=N - ** - ** The first form reports the current setting for the - ** maximum number of pages in the database file. The - ** second form attempts to change this setting. Both - ** forms return the current setting. - ** - ** The absolute value of N is used. This is undocumented and might - ** change. The only purpose is to provide an easy way to test - ** the sqlite3AbsInt32() function. - ** - ** PRAGMA [database.]page_count - ** - ** Return the number of pages in the specified database. - */ - if( sqlite3StrICmp(zLeft,"page_count")==0 - || sqlite3StrICmp(zLeft,"max_page_count")==0 - ){ - int iReg; - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - sqlite3CodeVerifySchema(pParse, iDb); - iReg = ++pParse->nMem; - if( sqlite3Tolower(zLeft[0])=='p' ){ - sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg); - }else{ - sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, - sqlite3AbsInt32(sqlite3Atoi(zRight))); - } - sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); - }else - - /* - ** PRAGMA [database.]locking_mode - ** PRAGMA [database.]locking_mode = (normal|exclusive) - */ - if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){ - const char *zRet = "normal"; - int eMode = getLockingMode(zRight); - - if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){ - /* Simple "PRAGMA locking_mode;" statement. This is a query for - ** the current default locking mode (which may be different to - ** the locking-mode of the main database). - */ - eMode = db->dfltLockMode; - }else{ - Pager *pPager; - if( pId2->n==0 ){ - /* This indicates that no database name was specified as part - ** of the PRAGMA command. In this case the locking-mode must be - ** set on all attached databases, as well as the main db file. - ** - ** Also, the sqlite3.dfltLockMode variable is set so that - ** any subsequently attached databases also use the specified - ** locking mode. - */ - int ii; - assert(pDb==&db->aDb[0]); - for(ii=2; iinDb; ii++){ - pPager = sqlite3BtreePager(db->aDb[ii].pBt); - sqlite3PagerLockingMode(pPager, eMode); - } - db->dfltLockMode = (u8)eMode; - } - pPager = sqlite3BtreePager(pDb->pBt); - eMode = sqlite3PagerLockingMode(pPager, eMode); - } - - assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE); - if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ - zRet = "exclusive"; - } - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - }else - - /* - ** PRAGMA [database.]journal_mode - ** PRAGMA [database.]journal_mode = - ** (delete|persist|off|truncate|memory|wal|off) - */ - if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){ - int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ - int ii; /* Loop counter */ - - /* Force the schema to be loaded on all databases. This causes all - ** database files to be opened and the journal_modes set. This is - ** necessary because subsequent processing must know if the databases - ** are in WAL mode. */ - if( sqlite3ReadSchema(pParse) ){ - goto pragma_out; - } - - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC); - - if( zRight==0 ){ - /* If there is no "=MODE" part of the pragma, do a query for the - ** current mode */ - eMode = PAGER_JOURNALMODE_QUERY; - }else{ - const char *zMode; - int n = sqlite3Strlen30(zRight); - for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){ - if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break; - } - if( !zMode ){ - /* If the "=MODE" part does not match any known journal mode, - ** then do a query */ - eMode = PAGER_JOURNALMODE_QUERY; - } - } - if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){ - /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */ - iDb = 0; - pId2->n = 1; - } - for(ii=db->nDb-1; ii>=0; ii--){ - if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ - sqlite3VdbeUsesBtree(v, ii); - sqlite3VdbeAddOp3(v, OP_JournalMode, ii, 1, eMode); - } - } - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - }else - - /* - ** PRAGMA [database.]journal_size_limit - ** PRAGMA [database.]journal_size_limit=N - ** - ** Get or set the size limit on rollback journal files. - */ - if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){ - Pager *pPager = sqlite3BtreePager(pDb->pBt); - i64 iLimit = -2; - if( zRight ){ - sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8); - if( iLimit<-1 ) iLimit = -1; - } - iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); - returnSingleInt(pParse, "journal_size_limit", iLimit); - }else - -#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ - - /* - ** PRAGMA [database.]auto_vacuum - ** PRAGMA [database.]auto_vacuum=N - ** - ** Get or set the value of the database 'auto-vacuum' parameter. - ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL - */ -#ifndef SQLITE_OMIT_AUTOVACUUM - if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){ - Btree *pBt = pDb->pBt; - assert( pBt!=0 ); - if( sqlite3ReadSchema(pParse) ){ - goto pragma_out; - } - if( !zRight ){ - int auto_vacuum; - if( ALWAYS(pBt) ){ - auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt); - }else{ - auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM; - } - returnSingleInt(pParse, "auto_vacuum", auto_vacuum); - }else{ - int eAuto = getAutoVacuum(zRight); - assert( eAuto>=0 && eAuto<=2 ); - db->nextAutovac = (u8)eAuto; - if( ALWAYS(eAuto>=0) ){ - /* Call SetAutoVacuum() to set initialize the internal auto and - ** incr-vacuum flags. This is required in case this connection - ** creates the database file. It is important that it is created - ** as an auto-vacuum capable db. - */ - rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); - if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ - /* When setting the auto_vacuum mode to either "full" or - ** "incremental", write the value of meta[6] in the database - ** file. Before writing to meta[6], check that meta[3] indicates - ** that this really is an auto-vacuum capable database. - */ - static const VdbeOpList setMeta6[] = { - { OP_Transaction, 0, 1, 0}, /* 0 */ - { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE}, - { OP_If, 1, 0, 0}, /* 2 */ - { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ - { OP_Integer, 0, 1, 0}, /* 4 */ - { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */ - }; - int iAddr; - iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); - sqlite3VdbeChangeP1(v, iAddr, iDb); - sqlite3VdbeChangeP1(v, iAddr+1, iDb); - sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); - sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); - sqlite3VdbeChangeP1(v, iAddr+5, iDb); - sqlite3VdbeUsesBtree(v, iDb); - } - } - } - }else -#endif - - /* - ** PRAGMA [database.]incremental_vacuum(N) - ** - ** Do N steps of incremental vacuuming on a database. - */ -#ifndef SQLITE_OMIT_AUTOVACUUM - if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){ - int iLimit, addr; - if( sqlite3ReadSchema(pParse) ){ - goto pragma_out; - } - if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ - iLimit = 0x7fffffff; - } - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); - addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); - sqlite3VdbeAddOp1(v, OP_ResultRow, 1); - sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); - sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); - sqlite3VdbeJumpHere(v, addr); - }else -#endif - -#ifndef SQLITE_OMIT_PAGER_PRAGMAS - /* - ** PRAGMA [database.]cache_size - ** PRAGMA [database.]cache_size=N - ** - ** The first form reports the current local setting for the - ** page cache size. The second form sets the local - ** page cache size value. If N is positive then that is the - ** number of pages in the cache. If N is negative, then the - ** number of pages is adjusted so that the cache uses -N kibibytes - ** of memory. - */ - if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( !zRight ){ - returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); - }else{ - int size = sqlite3Atoi(zRight); - pDb->pSchema->cache_size = size; - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); - } - }else - - /* - ** PRAGMA [database.]mmap_size(N) - ** - ** Used to set mapping size limit. The mapping size limit is - ** used to limit the aggregate size of all memory mapped regions of the - ** database file. If this parameter is set to zero, then memory mapping - ** is not used at all. If N is negative, then the default memory map - ** limit determined by sqlite3_config(SQLITE_CONFIG_MMAP_SIZE) is set. - ** The parameter N is measured in bytes. - ** - ** This value is advisory. The underlying VFS is free to memory map - ** as little or as much as it wants. Except, if N is set to 0 then the - ** upper layers will never invoke the xFetch interfaces to the VFS. - */ - if( sqlite3StrICmp(zLeft,"mmap_size")==0 ){ - sqlite3_int64 sz; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( zRight ){ - int ii; - sqlite3Atoi64(zRight, &sz, 1000, SQLITE_UTF8); - if( sz<0 ) sz = sqlite3GlobalConfig.szMmap; - if( pId2->n==0 ) db->szMmap = sz; - for(ii=db->nDb-1; ii>=0; ii--){ - if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ - sqlite3BtreeSetMmapLimit(db->aDb[ii].pBt, sz); - } - } - } - sz = -1; - if( sqlite3_file_control(db,zDb,SQLITE_FCNTL_MMAP_SIZE,&sz)==SQLITE_OK ){ -#if SQLITE_MAX_MMAP_SIZE==0 - sz = 0; -#endif - returnSingleInt(pParse, "mmap_size", sz); - } - }else - - /* - ** PRAGMA temp_store - ** PRAGMA temp_store = "default"|"memory"|"file" - ** - ** Return or set the local value of the temp_store flag. Changing - ** the local value does not make changes to the disk file and the default - ** value will be restored the next time the database is opened. - ** - ** Note that it is possible for the library compile-time options to - ** override this setting - */ - if( sqlite3StrICmp(zLeft, "temp_store")==0 ){ - if( !zRight ){ - returnSingleInt(pParse, "temp_store", db->temp_store); - }else{ - changeTempStorage(pParse, zRight); - } - }else - - /* - ** PRAGMA temp_store_directory - ** PRAGMA temp_store_directory = ""|"directory_name" - ** - ** Return or set the local value of the temp_store_directory flag. Changing - ** the value sets a specific directory to be used for temporary files. - ** Setting to a null string reverts to the default temporary directory search. - ** If temporary directory is changed, then invalidateTempStorage. - ** - */ - if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){ - if( !zRight ){ - if( sqlite3_temp_directory ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, - "temp_store_directory", SQLITE_STATIC); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - } - }else{ -#ifndef SQLITE_OMIT_WSD - if( zRight[0] ){ - int res; - rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); - if( rc!=SQLITE_OK || res==0 ){ - sqlite3ErrorMsg(pParse, "not a writable directory"); - goto pragma_out; - } - } - if( SQLITE_TEMP_STORE==0 - || (SQLITE_TEMP_STORE==1 && db->temp_store<=1) - || (SQLITE_TEMP_STORE==2 && db->temp_store==1) - ){ - invalidateTempStorage(pParse); - } - sqlite3_free(sqlite3_temp_directory); - if( zRight[0] ){ - sqlite3_temp_directory = sqlite3_mprintf("%s", zRight); - }else{ - sqlite3_temp_directory = 0; - } -#endif /* SQLITE_OMIT_WSD */ - } - }else - -#if SQLITE_OS_WIN - /* - ** PRAGMA data_store_directory - ** PRAGMA data_store_directory = ""|"directory_name" - ** - ** Return or set the local value of the data_store_directory flag. Changing - ** the value sets a specific directory to be used for database files that - ** were specified with a relative pathname. Setting to a null string reverts - ** to the default database directory, which for database files specified with - ** a relative path will probably be based on the current directory for the - ** process. Database file specified with an absolute path are not impacted - ** by this setting, regardless of its value. - ** - */ - if( sqlite3StrICmp(zLeft, "data_store_directory")==0 ){ - if( !zRight ){ - if( sqlite3_data_directory ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, - "data_store_directory", SQLITE_STATIC); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_data_directory, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - } - }else{ -#ifndef SQLITE_OMIT_WSD - if( zRight[0] ){ - int res; - rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); - if( rc!=SQLITE_OK || res==0 ){ - sqlite3ErrorMsg(pParse, "not a writable directory"); - goto pragma_out; - } - } - sqlite3_free(sqlite3_data_directory); - if( zRight[0] ){ - sqlite3_data_directory = sqlite3_mprintf("%s", zRight); - }else{ - sqlite3_data_directory = 0; - } -#endif /* SQLITE_OMIT_WSD */ - } - }else -#endif - -#if !defined(SQLITE_ENABLE_LOCKING_STYLE) -# if defined(__APPLE__) -# define SQLITE_ENABLE_LOCKING_STYLE 1 -# else -# define SQLITE_ENABLE_LOCKING_STYLE 0 -# endif -#endif -#if SQLITE_ENABLE_LOCKING_STYLE - /* - ** PRAGMA [database.]lock_proxy_file - ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path" - ** - ** Return or set the value of the lock_proxy_file flag. Changing - ** the value sets a specific file to be used for database access locks. - ** - */ - if( sqlite3StrICmp(zLeft, "lock_proxy_file")==0 ){ - if( !zRight ){ - Pager *pPager = sqlite3BtreePager(pDb->pBt); - char *proxy_file_path = NULL; - sqlite3_file *pFile = sqlite3PagerFile(pPager); - sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, - &proxy_file_path); - - if( proxy_file_path ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, - "lock_proxy_file", SQLITE_STATIC); - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, proxy_file_path, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - } - }else{ - Pager *pPager = sqlite3BtreePager(pDb->pBt); - sqlite3_file *pFile = sqlite3PagerFile(pPager); - int res; - if( zRight[0] ){ - res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, - zRight); - } else { - res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE, - NULL); - } - if( res!=SQLITE_OK ){ - sqlite3ErrorMsg(pParse, "failed to set lock proxy file"); - goto pragma_out; - } - } - }else -#endif /* SQLITE_ENABLE_LOCKING_STYLE */ - - /* - ** PRAGMA [database.]synchronous - ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL - ** - ** Return or set the local value of the synchronous flag. Changing - ** the local value does not make changes to the disk file and the - ** default value will be restored the next time the database is - ** opened. - */ - if( sqlite3StrICmp(zLeft,"synchronous")==0 ){ - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - if( !zRight ){ - returnSingleInt(pParse, "synchronous", pDb->safety_level-1); - }else{ - if( !db->autoCommit ){ - sqlite3ErrorMsg(pParse, - "Safety level may not be changed inside a transaction"); - }else{ - pDb->safety_level = getSafetyLevel(zRight,0,1)+1; - } - } - }else -#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ - -#ifndef SQLITE_OMIT_FLAG_PRAGMAS - if( flagPragma(pParse, zLeft, zRight) ){ - /* The flagPragma() subroutine also generates any necessary code - ** there is nothing more to do here */ - }else -#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ - -#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS - /* - ** PRAGMA table_info(
) - ** - ** Return a single row for each column of the named table. The columns of - ** the returned data set are: - ** - ** cid: Column id (numbered from left to right, starting at 0) - ** name: Column name - ** type: Column declaration type. - ** notnull: True if 'NOT NULL' is part of column declaration - ** dflt_value: The default value for the column, if any. - */ - if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ - Table *pTab; - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - pTab = sqlite3FindTable(db, zRight, zDb); - if( pTab ){ - int i, k; - int nHidden = 0; - Column *pCol; - Index *pPk; - for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){} - sqlite3VdbeSetNumCols(v, 6); - pParse->nMem = 6; - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC); - sqlite3ViewGetColumnNames(pParse, pTab); - for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ - if( IsHiddenColumn(pCol) ){ - nHidden++; - continue; - } - sqlite3VdbeAddOp2(v, OP_Integer, i-nHidden, 1); - sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, - pCol->zType ? pCol->zType : "", 0); - sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); - if( pCol->zDflt ){ - sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, 5); - } - if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ - k = 0; - }else if( pPk==0 ){ - k = 1; - }else{ - for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} - } - sqlite3VdbeAddOp2(v, OP_Integer, k, 6); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); - } - } - }else - - if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){ - Index *pIdx; - Table *pTab; - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - pIdx = sqlite3FindIndex(db, zRight, zDb); - if( pIdx ){ - int i; - pTab = pIdx->pTable; - sqlite3VdbeSetNumCols(v, 3); - pParse->nMem = 3; - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC); - for(i=0; inColumn; i++){ - int cnum = pIdx->aiColumn[i]; - sqlite3VdbeAddOp2(v, OP_Integer, i, 1); - sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2); - assert( pTab->nCol>cnum ); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); - } - } - }else - - if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){ - Index *pIdx; - Table *pTab; - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - pTab = sqlite3FindTable(db, zRight, zDb); - if( pTab ){ - v = sqlite3GetVdbe(pParse); - pIdx = pTab->pIndex; - if( pIdx ){ - int i = 0; - sqlite3VdbeSetNumCols(v, 3); - pParse->nMem = 3; - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); - while(pIdx){ - sqlite3VdbeAddOp2(v, OP_Integer, i, 1); - sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); - sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); - ++i; - pIdx = pIdx->pNext; - } - } - } - }else - - if( sqlite3StrICmp(zLeft, "database_list")==0 ){ - int i; - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - sqlite3VdbeSetNumCols(v, 3); - pParse->nMem = 3; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC); - for(i=0; inDb; i++){ - if( db->aDb[i].pBt==0 ) continue; - assert( db->aDb[i].zName!=0 ); - sqlite3VdbeAddOp2(v, OP_Integer, i, 1); - sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, - sqlite3BtreeGetFilename(db->aDb[i].pBt), 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); - } - }else - - if( sqlite3StrICmp(zLeft, "collation_list")==0 ){ - int i = 0; - HashElem *p; - sqlite3VdbeSetNumCols(v, 2); - pParse->nMem = 2; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); - for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ - CollSeq *pColl = (CollSeq *)sqliteHashData(p); - sqlite3VdbeAddOp2(v, OP_Integer, i++, 1); - sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); - } - }else -#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ - -#ifndef SQLITE_OMIT_FOREIGN_KEY - if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){ - FKey *pFK; - Table *pTab; - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - pTab = sqlite3FindTable(db, zRight, zDb); - if( pTab ){ - v = sqlite3GetVdbe(pParse); - pFK = pTab->pFKey; - if( pFK ){ - int i = 0; - sqlite3VdbeSetNumCols(v, 8); - pParse->nMem = 8; - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 7, COLNAME_NAME, "match", SQLITE_STATIC); - while(pFK){ - int j; - for(j=0; jnCol; j++){ - char *zCol = pFK->aCol[j].zCol; - char *zOnDelete = (char *)actionName(pFK->aAction[0]); - char *zOnUpdate = (char *)actionName(pFK->aAction[1]); - sqlite3VdbeAddOp2(v, OP_Integer, i, 1); - sqlite3VdbeAddOp2(v, OP_Integer, j, 2); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0); - sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, - pTab->aCol[pFK->aCol[j].iFrom].zName, 0); - sqlite3VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0); - sqlite3VdbeAddOp4(v, OP_String8, 0, 6, 0, zOnUpdate, 0); - sqlite3VdbeAddOp4(v, OP_String8, 0, 7, 0, zOnDelete, 0); - sqlite3VdbeAddOp4(v, OP_String8, 0, 8, 0, "NONE", 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8); - } - ++i; - pFK = pFK->pNextFrom; - } - } - } - }else -#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ - -#ifndef SQLITE_OMIT_FOREIGN_KEY -#ifndef SQLITE_OMIT_TRIGGER - if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){ - FKey *pFK; /* A foreign key constraint */ - Table *pTab; /* Child table contain "REFERENCES" keyword */ - Table *pParent; /* Parent table that child points to */ - Index *pIdx; /* Index in the parent table */ - int i; /* Loop counter: Foreign key number for pTab */ - int j; /* Loop counter: Field of the foreign key */ - HashElem *k; /* Loop counter: Next table in schema */ - int x; /* result variable */ - int regResult; /* 3 registers to hold a result row */ - int regKey; /* Register to hold key for checking the FK */ - int regRow; /* Registers to hold a row from pTab */ - int addrTop; /* Top of a loop checking foreign keys */ - int addrOk; /* Jump here if the key is OK */ - int *aiCols; /* child to parent column mapping */ - - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - regResult = pParse->nMem+1; - pParse->nMem += 4; - regKey = ++pParse->nMem; - regRow = ++pParse->nMem; - v = sqlite3GetVdbe(pParse); - sqlite3VdbeSetNumCols(v, 4); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC); - sqlite3CodeVerifySchema(pParse, iDb); - k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); - while( k ){ - if( zRight ){ - pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); - k = 0; - }else{ - pTab = (Table*)sqliteHashData(k); - k = sqliteHashNext(k); - } - if( pTab==0 || pTab->pFKey==0 ) continue; - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; - sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); - sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, - P4_TRANSIENT); - for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ - pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); - if( pParent==0 ) break; - pIdx = 0; - sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); - x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); - if( x==0 ){ - if( pIdx==0 ){ - sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); - }else{ - KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); - sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); - sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); - } - }else{ - k = 0; - break; - } - } - if( pFK ) break; - if( pParse->nTabnTab = i; - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); - for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ - pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); - assert( pParent!=0 ); - pIdx = 0; - aiCols = 0; - x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); - assert( x==0 ); - addrOk = sqlite3VdbeMakeLabel(v); - if( pIdx==0 ){ - int iKey = pFK->aCol[0].iFrom; - assert( iKey>=0 && iKeynCol ); - if( iKey!=pTab->iPKey ){ - sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); - sqlite3ColumnDefault(v, pTab, iKey, regRow); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); - sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, - sqlite3VdbeCurrentAddr(v)+3); - }else{ - sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); - } - sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); - sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - }else{ - for(j=0; jnCol; j++){ - sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, - aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j); - sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); - } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); - sqlite3VdbeChangeP4(v, -1, - sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); - sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); - } - sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); - sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, - pFK->zTo, P4_TRANSIENT); - sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); - sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); - sqlite3VdbeResolveLabel(v, addrOk); - sqlite3DbFree(db, aiCols); - } - sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); - sqlite3VdbeJumpHere(v, addrTop); - } - }else -#endif /* !defined(SQLITE_OMIT_TRIGGER) */ -#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ - -#ifndef NDEBUG - if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ - if( zRight ){ - if( sqlite3GetBoolean(zRight, 0) ){ - sqlite3ParserTrace(stderr, "parser: "); - }else{ - sqlite3ParserTrace(0, 0); - } - } - }else -#endif - - /* Reinstall the LIKE and GLOB functions. The variant of LIKE - ** used will be case sensitive or not depending on the RHS. - */ - if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){ - if( zRight ){ - sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0)); - } - }else - -#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX -# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 -#endif - -#ifndef SQLITE_OMIT_INTEGRITY_CHECK - /* Pragma "quick_check" is an experimental reduced version of - ** integrity_check designed to detect most database corruption - ** without most of the overhead of a full integrity-check. - */ - if( sqlite3StrICmp(zLeft, "integrity_check")==0 - || sqlite3StrICmp(zLeft, "quick_check")==0 - ){ - int i, j, addr, mxErr; - - /* Code that appears at the end of the integrity check. If no error - ** messages have been generated, output OK. Otherwise output the - ** error message - */ - static const VdbeOpList endCode[] = { - { OP_AddImm, 1, 0, 0}, /* 0 */ - { OP_IfNeg, 1, 0, 0}, /* 1 */ - { OP_String8, 0, 3, 0}, /* 2 */ - { OP_ResultRow, 3, 1, 0}, - }; - - int isQuick = (sqlite3Tolower(zLeft[0])=='q'); - - /* If the PRAGMA command was of the form "PRAGMA .integrity_check", - ** then iDb is set to the index of the database identified by . - ** In this case, the integrity of database iDb only is verified by - ** the VDBE created below. - ** - ** Otherwise, if the command was simply "PRAGMA integrity_check" (or - ** "PRAGMA quick_check"), then iDb is set to 0. In this case, set iDb - ** to -1 here, to indicate that the VDBE should verify the integrity - ** of all attached databases. */ - assert( iDb>=0 ); - assert( iDb==0 || pId2->z ); - if( pId2->z==0 ) iDb = -1; - - /* Initialize the VDBE program */ - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - pParse->nMem = 6; - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); - - /* Set the maximum error count */ - mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; - if( zRight ){ - sqlite3GetInt32(zRight, &mxErr); - if( mxErr<=0 ){ - mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; - } - } - sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ - - /* Do an integrity check on each database file */ - for(i=0; inDb; i++){ - HashElem *x; - Hash *pTbls; - int cnt = 0; - - if( OMIT_TEMPDB && i==1 ) continue; - if( iDb>=0 && i!=iDb ) continue; - - sqlite3CodeVerifySchema(pParse, i); - addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ - sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); - sqlite3VdbeJumpHere(v, addr); - - /* Do an integrity check of the B-Tree - ** - ** Begin by filling registers 2, 3, ... with the root pages numbers - ** for all tables and indices in the database. - */ - assert( sqlite3SchemaMutexHeld(db, i, 0) ); - pTbls = &db->aDb[i].pSchema->tblHash; - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - Index *pIdx; - sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt); - cnt++; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt); - cnt++; - } - } - - /* Make sure sufficient number of registers have been allocated */ - if( pParse->nMem < cnt+4 ){ - pParse->nMem = cnt+4; - } - - /* Do the b-tree integrity checks */ - sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); - sqlite3VdbeChangeP5(v, (u8)i); - addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, - sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), - P4_DYNAMIC); - sqlite3VdbeAddOp2(v, OP_Move, 2, 4); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); - sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1); - sqlite3VdbeJumpHere(v, addr); - - /* Make sure all the indices are constructed correctly. - */ - for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - Index *pIdx; - int loopTop; - - if( pTab->pIndex==0 ) continue; - addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ - sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); - sqlite3VdbeJumpHere(v, addr); - sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); - sqlite3VdbeAddOp2(v, OP_Integer, 0, 2); /* reg(2) will count entries */ - loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0); - sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */ - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - int jmp2; - int r1; - static const VdbeOpList idxErr[] = { - { OP_AddImm, 1, -1, 0}, - { OP_String8, 0, 3, 0}, /* 1 */ - { OP_Rowid, 1, 4, 0}, - { OP_String8, 0, 5, 0}, /* 3 */ - { OP_String8, 0, 6, 0}, /* 4 */ - { OP_Concat, 4, 3, 3}, - { OP_Concat, 5, 3, 3}, - { OP_Concat, 6, 3, 3}, - { OP_ResultRow, 3, 1, 0}, - { OP_IfPos, 1, 0, 0}, /* 9 */ - { OP_Halt, 0, 0, 0}, - }; - r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0); - jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nColumn+1); - addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); - sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC); - sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC); - sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_TRANSIENT); - sqlite3VdbeJumpHere(v, addr+9); - sqlite3VdbeJumpHere(v, jmp2); - } - sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1); - sqlite3VdbeJumpHere(v, loopTop); - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - static const VdbeOpList cntIdx[] = { - { OP_Integer, 0, 3, 0}, - { OP_Rewind, 0, 0, 0}, /* 1 */ - { OP_AddImm, 3, 1, 0}, - { OP_Next, 0, 0, 0}, /* 3 */ - { OP_Eq, 2, 0, 3}, /* 4 */ - { OP_AddImm, 1, -1, 0}, - { OP_String8, 0, 2, 0}, /* 6 */ - { OP_String8, 0, 3, 0}, /* 7 */ - { OP_Concat, 3, 2, 2}, - { OP_ResultRow, 2, 1, 0}, - }; - addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); - sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); - sqlite3VdbeJumpHere(v, addr); - addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); - sqlite3VdbeChangeP1(v, addr+1, j+2); - sqlite3VdbeChangeP2(v, addr+1, addr+4); - sqlite3VdbeChangeP1(v, addr+3, j+2); - sqlite3VdbeChangeP2(v, addr+3, addr+2); - sqlite3VdbeJumpHere(v, addr+4); - sqlite3VdbeChangeP4(v, addr+6, - "wrong # of entries in index ", P4_STATIC); - sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_TRANSIENT); - } - } - } - addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); - sqlite3VdbeChangeP2(v, addr, -mxErr); - sqlite3VdbeJumpHere(v, addr+1); - sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC); - }else -#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ - -#ifndef SQLITE_OMIT_UTF16 - /* - ** PRAGMA encoding - ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" - ** - ** In its first form, this pragma returns the encoding of the main - ** database. If the database is not initialized, it is initialized now. - ** - ** The second form of this pragma is a no-op if the main database file - ** has not already been initialized. In this case it sets the default - ** encoding that will be used for the main database file if a new file - ** is created. If an existing main database file is opened, then the - ** default text encoding for the existing database is used. - ** - ** In all cases new databases created using the ATTACH command are - ** created to use the same default text encoding as the main database. If - ** the main database has not been initialized and/or created when ATTACH - ** is executed, this is done before the ATTACH operation. - ** - ** In the second form this pragma sets the text encoding to be used in - ** new database files created using this database handle. It is only - ** useful if invoked immediately after the main database i - */ - if( sqlite3StrICmp(zLeft, "encoding")==0 ){ - static const struct EncName { - char *zName; - u8 enc; - } encnames[] = { - { "UTF8", SQLITE_UTF8 }, - { "UTF-8", SQLITE_UTF8 }, /* Must be element [1] */ - { "UTF-16le", SQLITE_UTF16LE }, /* Must be element [2] */ - { "UTF-16be", SQLITE_UTF16BE }, /* Must be element [3] */ - { "UTF16le", SQLITE_UTF16LE }, - { "UTF16be", SQLITE_UTF16BE }, - { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */ - { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */ - { 0, 0 } - }; - const struct EncName *pEnc; - if( !zRight ){ /* "PRAGMA encoding" */ - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", SQLITE_STATIC); - sqlite3VdbeAddOp2(v, OP_String8, 0, 1); - assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 ); - assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE ); - assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE ); - sqlite3VdbeChangeP4(v, -1, encnames[ENC(pParse->db)].zName, P4_STATIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - }else{ /* "PRAGMA encoding = XXX" */ - /* Only change the value of sqlite.enc if the database handle is not - ** initialized. If the main database exists, the new sqlite.enc value - ** will be overwritten when the schema is next loaded. If it does not - ** already exists, it will be created to use the new encoding value. - */ - if( - !(DbHasProperty(db, 0, DB_SchemaLoaded)) || - DbHasProperty(db, 0, DB_Empty) - ){ - for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ - if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ - ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; - break; - } - } - if( !pEnc->zName ){ - sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); - } - } - } - }else -#endif /* SQLITE_OMIT_UTF16 */ - -#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS - /* - ** PRAGMA [database.]schema_version - ** PRAGMA [database.]schema_version = - ** - ** PRAGMA [database.]user_version - ** PRAGMA [database.]user_version = - ** - ** PRAGMA [database.]freelist_count = - ** - ** PRAGMA [database.]application_id - ** PRAGMA [database.]application_id = - ** - ** The pragma's schema_version and user_version are used to set or get - ** the value of the schema-version and user-version, respectively. Both - ** the schema-version and the user-version are 32-bit signed integers - ** stored in the database header. - ** - ** The schema-cookie is usually only manipulated internally by SQLite. It - ** is incremented by SQLite whenever the database schema is modified (by - ** creating or dropping a table or index). The schema version is used by - ** SQLite each time a query is executed to ensure that the internal cache - ** of the schema used when compiling the SQL query matches the schema of - ** the database against which the compiled query is actually executed. - ** Subverting this mechanism by using "PRAGMA schema_version" to modify - ** the schema-version is potentially dangerous and may lead to program - ** crashes or database corruption. Use with caution! - ** - ** The user-version is not used internally by SQLite. It may be used by - ** applications for any purpose. - */ - if( sqlite3StrICmp(zLeft, "schema_version")==0 - || sqlite3StrICmp(zLeft, "user_version")==0 - || sqlite3StrICmp(zLeft, "freelist_count")==0 - || sqlite3StrICmp(zLeft, "application_id")==0 - ){ - int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ - sqlite3VdbeUsesBtree(v, iDb); - switch( zLeft[0] ){ - case 'a': case 'A': - iCookie = BTREE_APPLICATION_ID; - break; - case 'f': case 'F': - iCookie = BTREE_FREE_PAGE_COUNT; - break; - case 's': case 'S': - iCookie = BTREE_SCHEMA_VERSION; - break; - default: - iCookie = BTREE_USER_VERSION; - break; - } - - if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){ - /* Write the specified cookie value */ - static const VdbeOpList setCookie[] = { - { OP_Transaction, 0, 1, 0}, /* 0 */ - { OP_Integer, 0, 1, 0}, /* 1 */ - { OP_SetCookie, 0, 0, 1}, /* 2 */ - }; - int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); - sqlite3VdbeChangeP1(v, addr, iDb); - sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight)); - sqlite3VdbeChangeP1(v, addr+2, iDb); - sqlite3VdbeChangeP2(v, addr+2, iCookie); - }else{ - /* Read the specified cookie value */ - static const VdbeOpList readCookie[] = { - { OP_Transaction, 0, 0, 0}, /* 0 */ - { OP_ReadCookie, 0, 1, 0}, /* 1 */ - { OP_ResultRow, 1, 1, 0} - }; - int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); - sqlite3VdbeChangeP1(v, addr, iDb); - sqlite3VdbeChangeP1(v, addr+1, iDb); - sqlite3VdbeChangeP3(v, addr+1, iCookie); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); - } - }else -#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ - -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - /* - ** PRAGMA compile_options - ** - ** Return the names of all compile-time options used in this build, - ** one option per row. - */ - if( sqlite3StrICmp(zLeft, "compile_options")==0 ){ - int i = 0; - const char *zOpt; - sqlite3VdbeSetNumCols(v, 1); - pParse->nMem = 1; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC); - while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); - } - }else -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -#ifndef SQLITE_OMIT_WAL - /* - ** PRAGMA [database.]wal_checkpoint = passive|full|restart - ** - ** Checkpoint the database. - */ - if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){ - int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); - int eMode = SQLITE_CHECKPOINT_PASSIVE; - if( zRight ){ - if( sqlite3StrICmp(zRight, "full")==0 ){ - eMode = SQLITE_CHECKPOINT_FULL; - }else if( sqlite3StrICmp(zRight, "restart")==0 ){ - eMode = SQLITE_CHECKPOINT_RESTART; - } - } - if( sqlite3ReadSchema(pParse) ) goto pragma_out; - sqlite3VdbeSetNumCols(v, 3); - pParse->nMem = 3; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC); - - sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); - }else - - /* - ** PRAGMA wal_autocheckpoint - ** PRAGMA wal_autocheckpoint = N - ** - ** Configure a database connection to automatically checkpoint a database - ** after accumulating N frames in the log. Or query for the current value - ** of N. - */ - if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){ - if( zRight ){ - sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); - } - returnSingleInt(pParse, "wal_autocheckpoint", - db->xWalCallback==sqlite3WalDefaultHook ? - SQLITE_PTR_TO_INT(db->pWalArg) : 0); - }else -#endif - - /* - ** PRAGMA shrink_memory - ** - ** This pragma attempts to free as much memory as possible from the - ** current database connection. - */ - if( sqlite3StrICmp(zLeft, "shrink_memory")==0 ){ - sqlite3_db_release_memory(db); - }else - - /* - ** PRAGMA busy_timeout - ** PRAGMA busy_timeout = N - ** - ** Call sqlite3_busy_timeout(db, N). Return the current timeout value - ** if one is set. If no busy handler or a different busy handler is set - ** then 0 is returned. Setting the busy_timeout to 0 or negative - ** disables the timeout. - */ - if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){ - if( zRight ){ - sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); - } - returnSingleInt(pParse, "timeout", db->busyTimeout); - }else - -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - /* - ** Report the current state of file logs for all databases - */ - if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ - static const char *const azLockName[] = { - "unlocked", "shared", "reserved", "pending", "exclusive" - }; - int i; - sqlite3VdbeSetNumCols(v, 2); - pParse->nMem = 2; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC); - for(i=0; inDb; i++){ - Btree *pBt; - const char *zState = "unknown"; - int j; - if( db->aDb[i].zName==0 ) continue; - sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC); - pBt = db->aDb[i].pBt; - if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ - zState = "closed"; - }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, - SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ - zState = azLockName[j]; - } - sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); - } - - }else -#endif - -#ifdef SQLITE_HAS_CODEC - if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){ - sqlite3_key(db, zRight, sqlite3Strlen30(zRight)); - }else - if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){ - sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight)); - }else - if( zRight && (sqlite3StrICmp(zLeft, "hexkey")==0 || - sqlite3StrICmp(zLeft, "hexrekey")==0) ){ - int i, h1, h2; - char zKey[40]; - for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){ - h1 += 9*(1&(h1>>6)); - h2 += 9*(1&(h2>>6)); - zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4); - } - if( (zLeft[3] & 0xf)==0xb ){ - sqlite3_key(db, zKey, i/2); - }else{ - sqlite3_rekey(db, zKey, i/2); - } - }else -#endif -#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) - if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){ -#ifdef SQLITE_HAS_CODEC - if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ - sqlite3_activate_see(&zRight[4]); - } -#endif -#ifdef SQLITE_ENABLE_CEROD - if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ - sqlite3_activate_cerod(&zRight[6]); - } -#endif - }else -#endif - - - {/* Empty ELSE clause */} - - /* - ** Reset the safety level, in case the fullfsync flag or synchronous - ** setting changed. - */ -#ifndef SQLITE_OMIT_PAGER_PRAGMAS - if( db->autoCommit ){ - sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, - (db->flags&SQLITE_FullFSync)!=0, - (db->flags&SQLITE_CkptFullFSync)!=0); - } -#endif -pragma_out: - sqlite3DbFree(db, zLeft); - sqlite3DbFree(db, zRight); -} - -#endif /* SQLITE_OMIT_PRAGMA */ - -/************** End of pragma.c **********************************************/ -/************** Begin file prepare.c *****************************************/ -/* -** 2005 May 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the implementation of the sqlite3_prepare() -** interface, and routines that contribute to loading the database schema -** from disk. -*/ - -/* -** Fill the InitData structure with an error message that indicates -** that the database is corrupt. -*/ -static void corruptSchema( - InitData *pData, /* Initialization context */ - const char *zObj, /* Object being parsed at the point of error */ - const char *zExtra /* Error information */ -){ - sqlite3 *db = pData->db; - if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ - if( zObj==0 ) zObj = "?"; - sqlite3SetString(pData->pzErrMsg, db, - "malformed database schema (%s)", zObj); - if( zExtra ){ - *pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg, - "%s - %s", *pData->pzErrMsg, zExtra); - } - } - pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT; -} - -/* -** This is the callback routine for the code that initializes the -** database. See sqlite3Init() below for additional information. -** This routine is also called from the OP_ParseSchema opcode of the VDBE. -** -** Each callback contains the following information: -** -** argv[0] = name of thing being created -** argv[1] = root page number for table or index. 0 for trigger or view. -** argv[2] = SQL text for the CREATE statement. -** -*/ -SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ - InitData *pData = (InitData*)pInit; - sqlite3 *db = pData->db; - int iDb = pData->iDb; - - assert( argc==3 ); - UNUSED_PARAMETER2(NotUsed, argc); - assert( sqlite3_mutex_held(db->mutex) ); - DbClearProperty(db, iDb, DB_Empty); - if( db->mallocFailed ){ - corruptSchema(pData, argv[0], 0); - return 1; - } - - assert( iDb>=0 && iDbnDb ); - if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ - if( argv[1]==0 ){ - corruptSchema(pData, argv[0], 0); - }else if( argv[2] && argv[2][0] ){ - /* Call the parser to process a CREATE TABLE, INDEX or VIEW. - ** But because db->init.busy is set to 1, no VDBE code is generated - ** or executed. All the parser does is build the internal data - ** structures that describe the table, index, or view. - */ - int rc; - sqlite3_stmt *pStmt; - TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ - - assert( db->init.busy ); - db->init.iDb = iDb; - db->init.newTnum = sqlite3Atoi(argv[1]); - db->init.orphanTrigger = 0; - TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); - rc = db->errCode; - assert( (rc&0xFF)==(rcp&0xFF) ); - db->init.iDb = 0; - if( SQLITE_OK!=rc ){ - if( db->init.orphanTrigger ){ - assert( iDb==1 ); - }else{ - pData->rc = rc; - if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; - }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ - corruptSchema(pData, argv[0], sqlite3_errmsg(db)); - } - } - } - sqlite3_finalize(pStmt); - }else if( argv[0]==0 ){ - corruptSchema(pData, 0, 0); - }else{ - /* If the SQL column is blank it means this is an index that - ** was created to be the PRIMARY KEY or to fulfill a UNIQUE - ** constraint for a CREATE TABLE. The index should have already - ** been created when we processed the CREATE TABLE. All we have - ** to do here is record the root page number for that index. - */ - Index *pIndex; - pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); - if( pIndex==0 ){ - /* This can occur if there exists an index on a TEMP table which - ** has the same name as another index on a permanent index. Since - ** the permanent table is hidden by the TEMP table, we can also - ** safely ignore the index on the permanent table. - */ - /* Do Nothing */; - }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){ - corruptSchema(pData, argv[0], "invalid rootpage"); - } - } - return 0; -} - -/* -** Attempt to read the database schema and initialize internal -** data structures for a single database file. The index of the -** database file is given by iDb. iDb==0 is used for the main -** database. iDb==1 should never be used. iDb>=2 is used for -** auxiliary databases. Return one of the SQLITE_ error codes to -** indicate success or failure. -*/ -static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ - int rc; - int i; -#ifndef SQLITE_OMIT_DEPRECATED - int size; -#endif - Table *pTab; - Db *pDb; - char const *azArg[4]; - int meta[5]; - InitData initData; - char const *zMasterSchema; - char const *zMasterName; - int openedTransaction = 0; - - /* - ** The master database table has a structure like this - */ - static const char master_schema[] = - "CREATE TABLE sqlite_master(\n" - " type text,\n" - " name text,\n" - " tbl_name text,\n" - " rootpage integer,\n" - " sql text\n" - ")" - ; -#ifndef SQLITE_OMIT_TEMPDB - static const char temp_master_schema[] = - "CREATE TEMP TABLE sqlite_temp_master(\n" - " type text,\n" - " name text,\n" - " tbl_name text,\n" - " rootpage integer,\n" - " sql text\n" - ")" - ; -#else - #define temp_master_schema 0 -#endif - - assert( iDb>=0 && iDbnDb ); - assert( db->aDb[iDb].pSchema ); - assert( sqlite3_mutex_held(db->mutex) ); - assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); - - /* zMasterSchema and zInitScript are set to point at the master schema - ** and initialisation script appropriate for the database being - ** initialized. zMasterName is the name of the master table. - */ - if( !OMIT_TEMPDB && iDb==1 ){ - zMasterSchema = temp_master_schema; - }else{ - zMasterSchema = master_schema; - } - zMasterName = SCHEMA_TABLE(iDb); - - /* Construct the schema tables. */ - azArg[0] = zMasterName; - azArg[1] = "1"; - azArg[2] = zMasterSchema; - azArg[3] = 0; - initData.db = db; - initData.iDb = iDb; - initData.rc = SQLITE_OK; - initData.pzErrMsg = pzErrMsg; - sqlite3InitCallback(&initData, 3, (char **)azArg, 0); - if( initData.rc ){ - rc = initData.rc; - goto error_out; - } - pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); - if( ALWAYS(pTab) ){ - pTab->tabFlags |= TF_Readonly; - } - - /* Create a cursor to hold the database open - */ - pDb = &db->aDb[iDb]; - if( pDb->pBt==0 ){ - if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){ - DbSetProperty(db, 1, DB_SchemaLoaded); - } - return SQLITE_OK; - } - - /* If there is not already a read-only (or read-write) transaction opened - ** on the b-tree database, open one now. If a transaction is opened, it - ** will be closed before this function returns. */ - sqlite3BtreeEnter(pDb->pBt); - if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){ - rc = sqlite3BtreeBeginTrans(pDb->pBt, 0); - if( rc!=SQLITE_OK ){ - sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); - goto initone_error_out; - } - openedTransaction = 1; - } - - /* Get the database meta information. - ** - ** Meta values are as follows: - ** meta[0] Schema cookie. Changes with each schema change. - ** meta[1] File format of schema layer. - ** meta[2] Size of the page cache. - ** meta[3] Largest rootpage (auto/incr_vacuum mode) - ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE - ** meta[5] User version - ** meta[6] Incremental vacuum mode - ** meta[7] unused - ** meta[8] unused - ** meta[9] unused - ** - ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to - ** the possible values of meta[4]. - */ - for(i=0; ipBt, i+1, (u32 *)&meta[i]); - } - pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; - - /* If opening a non-empty database, check the text encoding. For the - ** main database, set sqlite3.enc to the encoding of the main database. - ** For an attached db, it is an error if the encoding is not the same - ** as sqlite3.enc. - */ - if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */ - if( iDb==0 ){ -#ifndef SQLITE_OMIT_UTF16 - u8 encoding; - /* If opening the main database, set ENC(db). */ - encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; - if( encoding==0 ) encoding = SQLITE_UTF8; - ENC(db) = encoding; -#else - ENC(db) = SQLITE_UTF8; -#endif - }else{ - /* If opening an attached database, the encoding much match ENC(db) */ - if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){ - sqlite3SetString(pzErrMsg, db, "attached databases must use the same" - " text encoding as main database"); - rc = SQLITE_ERROR; - goto initone_error_out; - } - } - }else{ - DbSetProperty(db, iDb, DB_Empty); - } - pDb->pSchema->enc = ENC(db); - - if( pDb->pSchema->cache_size==0 ){ -#ifndef SQLITE_OMIT_DEPRECATED - size = sqlite3AbsInt32(meta[BTREE_DEFAULT_CACHE_SIZE-1]); - if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; } - pDb->pSchema->cache_size = size; -#else - pDb->pSchema->cache_size = SQLITE_DEFAULT_CACHE_SIZE; -#endif - sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); - } - - /* - ** file_format==1 Version 3.0.0. - ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN - ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults - ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants - */ - pDb->pSchema->file_format = (u8)meta[BTREE_FILE_FORMAT-1]; - if( pDb->pSchema->file_format==0 ){ - pDb->pSchema->file_format = 1; - } - if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){ - sqlite3SetString(pzErrMsg, db, "unsupported file format"); - rc = SQLITE_ERROR; - goto initone_error_out; - } - - /* Ticket #2804: When we open a database in the newer file format, - ** clear the legacy_file_format pragma flag so that a VACUUM will - ** not downgrade the database and thus invalidate any descending - ** indices that the user might have created. - */ - if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){ - db->flags &= ~SQLITE_LegacyFileFmt; - } - - /* Read the schema information out of the schema tables - */ - assert( db->init.busy ); - { - char *zSql; - zSql = sqlite3MPrintf(db, - "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid", - db->aDb[iDb].zName, zMasterName); -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); - xAuth = db->xAuth; - db->xAuth = 0; -#endif - rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); -#ifndef SQLITE_OMIT_AUTHORIZATION - db->xAuth = xAuth; - } -#endif - if( rc==SQLITE_OK ) rc = initData.rc; - sqlite3DbFree(db, zSql); -#ifndef SQLITE_OMIT_ANALYZE - if( rc==SQLITE_OK ){ - sqlite3AnalysisLoad(db, iDb); - } -#endif - } - if( db->mallocFailed ){ - rc = SQLITE_NOMEM; - sqlite3ResetAllSchemasOfConnection(db); - } - if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ - /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider - ** the schema loaded, even if errors occurred. In this situation the - ** current sqlite3_prepare() operation will fail, but the following one - ** will attempt to compile the supplied statement against whatever subset - ** of the schema was loaded before the error occurred. The primary - ** purpose of this is to allow access to the sqlite_master table - ** even when its contents have been corrupted. - */ - DbSetProperty(db, iDb, DB_SchemaLoaded); - rc = SQLITE_OK; - } - - /* Jump here for an error that occurs after successfully allocating - ** curMain and calling sqlite3BtreeEnter(). For an error that occurs - ** before that point, jump to error_out. - */ -initone_error_out: - if( openedTransaction ){ - sqlite3BtreeCommit(pDb->pBt); - } - sqlite3BtreeLeave(pDb->pBt); - -error_out: - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - db->mallocFailed = 1; - } - return rc; -} - -/* -** Initialize all database files - the main database file, the file -** used to store temporary tables, and any additional database files -** created using ATTACH statements. Return a success code. If an -** error occurs, write an error message into *pzErrMsg. -** -** After a database is initialized, the DB_SchemaLoaded bit is set -** bit is set in the flags field of the Db structure. If the database -** file was of zero-length, then the DB_Empty flag is also set. -*/ -SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ - int i, rc; - int commit_internal = !(db->flags&SQLITE_InternChanges); - - assert( sqlite3_mutex_held(db->mutex) ); - rc = SQLITE_OK; - db->init.busy = 1; - for(i=0; rc==SQLITE_OK && inDb; i++){ - if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; - rc = sqlite3InitOne(db, i, pzErrMsg); - if( rc ){ - sqlite3ResetOneSchema(db, i); - } - } - - /* Once all the other databases have been initialized, load the schema - ** for the TEMP database. This is loaded last, as the TEMP database - ** schema may contain references to objects in other databases. - */ -#ifndef SQLITE_OMIT_TEMPDB - if( rc==SQLITE_OK && ALWAYS(db->nDb>1) - && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ - rc = sqlite3InitOne(db, 1, pzErrMsg); - if( rc ){ - sqlite3ResetOneSchema(db, 1); - } - } -#endif - - db->init.busy = 0; - if( rc==SQLITE_OK && commit_internal ){ - sqlite3CommitInternalChanges(db); - } - - return rc; -} - -/* -** This routine is a no-op if the database schema is already initialized. -** Otherwise, the schema is loaded. An error code is returned. -*/ -SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){ - int rc = SQLITE_OK; - sqlite3 *db = pParse->db; - assert( sqlite3_mutex_held(db->mutex) ); - if( !db->init.busy ){ - rc = sqlite3Init(db, &pParse->zErrMsg); - } - if( rc!=SQLITE_OK ){ - pParse->rc = rc; - pParse->nErr++; - } - return rc; -} - - -/* -** Check schema cookies in all databases. If any cookie is out -** of date set pParse->rc to SQLITE_SCHEMA. If all schema cookies -** make no changes to pParse->rc. -*/ -static void schemaIsValid(Parse *pParse){ - sqlite3 *db = pParse->db; - int iDb; - int rc; - int cookie; - - assert( pParse->checkSchema ); - assert( sqlite3_mutex_held(db->mutex) ); - for(iDb=0; iDbnDb; iDb++){ - int openedTransaction = 0; /* True if a transaction is opened */ - Btree *pBt = db->aDb[iDb].pBt; /* Btree database to read cookie from */ - if( pBt==0 ) continue; - - /* If there is not already a read-only (or read-write) transaction opened - ** on the b-tree database, open one now. If a transaction is opened, it - ** will be closed immediately after reading the meta-value. */ - if( !sqlite3BtreeIsInReadTrans(pBt) ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - db->mallocFailed = 1; - } - if( rc!=SQLITE_OK ) return; - openedTransaction = 1; - } - - /* Read the schema cookie from the database. If it does not match the - ** value stored as part of the in-memory schema representation, - ** set Parse.rc to SQLITE_SCHEMA. */ - sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ - sqlite3ResetOneSchema(db, iDb); - pParse->rc = SQLITE_SCHEMA; - } - - /* Close the transaction, if one was opened. */ - if( openedTransaction ){ - sqlite3BtreeCommit(pBt); - } - } -} - -/* -** Convert a schema pointer into the iDb index that indicates -** which database file in db->aDb[] the schema refers to. -** -** If the same database is attached more than once, the first -** attached database is returned. -*/ -SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ - int i = -1000000; - - /* If pSchema is NULL, then return -1000000. This happens when code in - ** expr.c is trying to resolve a reference to a transient table (i.e. one - ** created by a sub-select). In this case the return value of this - ** function should never be used. - ** - ** We return -1000000 instead of the more usual -1 simply because using - ** -1000000 as the incorrect index into db->aDb[] is much - ** more likely to cause a segfault than -1 (of course there are assert() - ** statements too, but it never hurts to play the odds). - */ - assert( sqlite3_mutex_held(db->mutex) ); - if( pSchema ){ - for(i=0; ALWAYS(inDb); i++){ - if( db->aDb[i].pSchema==pSchema ){ - break; - } - } - assert( i>=0 && inDb ); - } - return i; -} - -/* -** Compile the UTF-8 encoded SQL statement zSql into a statement handle. -*/ -static int sqlite3Prepare( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ - Vdbe *pReprepare, /* VM being reprepared */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - Parse *pParse; /* Parsing context */ - char *zErrMsg = 0; /* Error message */ - int rc = SQLITE_OK; /* Result code */ - int i; /* Loop counter */ - - /* Allocate the parsing context */ - pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); - if( pParse==0 ){ - rc = SQLITE_NOMEM; - goto end_prepare; - } - pParse->pReprepare = pReprepare; - assert( ppStmt && *ppStmt==0 ); - assert( !db->mallocFailed ); - assert( sqlite3_mutex_held(db->mutex) ); - - /* Check to verify that it is possible to get a read lock on all - ** database schemas. The inability to get a read lock indicates that - ** some other database connection is holding a write-lock, which in - ** turn means that the other connection has made uncommitted changes - ** to the schema. - ** - ** Were we to proceed and prepare the statement against the uncommitted - ** schema changes and if those schema changes are subsequently rolled - ** back and different changes are made in their place, then when this - ** prepared statement goes to run the schema cookie would fail to detect - ** the schema change. Disaster would follow. - ** - ** This thread is currently holding mutexes on all Btrees (because - ** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it - ** is not possible for another thread to start a new schema change - ** while this routine is running. Hence, we do not need to hold - ** locks on the schema, we just need to make sure nobody else is - ** holding them. - ** - ** Note that setting READ_UNCOMMITTED overrides most lock detection, - ** but it does *not* override schema lock detection, so this all still - ** works even if READ_UNCOMMITTED is set. - */ - for(i=0; inDb; i++) { - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - assert( sqlite3BtreeHoldsMutex(pBt) ); - rc = sqlite3BtreeSchemaLocked(pBt); - if( rc ){ - const char *zDb = db->aDb[i].zName; - sqlite3Error(db, rc, "database schema is locked: %s", zDb); - testcase( db->flags & SQLITE_ReadUncommitted ); - goto end_prepare; - } - } - } - - sqlite3VtabUnlockList(db); - - pParse->db = db; - pParse->nQueryLoop = (double)1; - if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ - char *zSqlCopy; - int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; - testcase( nBytes==mxLen ); - testcase( nBytes==mxLen+1 ); - if( nBytes>mxLen ){ - sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); - rc = sqlite3ApiExit(db, SQLITE_TOOBIG); - goto end_prepare; - } - zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); - if( zSqlCopy ){ - sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); - sqlite3DbFree(db, zSqlCopy); - pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; - }else{ - pParse->zTail = &zSql[nBytes]; - } - }else{ - sqlite3RunParser(pParse, zSql, &zErrMsg); - } - assert( 1==(int)pParse->nQueryLoop ); - - if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM; - } - if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; - if( pParse->checkSchema ){ - schemaIsValid(pParse); - } - if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM; - } - if( pzTail ){ - *pzTail = pParse->zTail; - } - rc = pParse->rc; - -#ifndef SQLITE_OMIT_EXPLAIN - if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){ - static const char * const azColName[] = { - "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", - "selectid", "order", "from", "detail" - }; - int iFirst, mx; - if( pParse->explain==2 ){ - sqlite3VdbeSetNumCols(pParse->pVdbe, 4); - iFirst = 8; - mx = 12; - }else{ - sqlite3VdbeSetNumCols(pParse->pVdbe, 8); - iFirst = 0; - mx = 8; - } - for(i=iFirst; ipVdbe, i-iFirst, COLNAME_NAME, - azColName[i], SQLITE_STATIC); - } - } -#endif - - if( db->init.busy==0 ){ - Vdbe *pVdbe = pParse->pVdbe; - sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); - } - if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ - sqlite3VdbeFinalize(pParse->pVdbe); - assert(!(*ppStmt)); - }else{ - *ppStmt = (sqlite3_stmt*)pParse->pVdbe; - } - - if( zErrMsg ){ - sqlite3Error(db, rc, "%s", zErrMsg); - sqlite3DbFree(db, zErrMsg); - }else{ - sqlite3Error(db, rc, 0); - } - - /* Delete any TriggerPrg structures allocated while parsing this statement. */ - while( pParse->pTriggerPrg ){ - TriggerPrg *pT = pParse->pTriggerPrg; - pParse->pTriggerPrg = pT->pNext; - sqlite3DbFree(db, pT); - } - -end_prepare: - - sqlite3StackFree(db, pParse); - rc = sqlite3ApiExit(db, rc); - assert( (rc&db->errMask)==rc ); - return rc; -} -static int sqlite3LockAndPrepare( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ - Vdbe *pOld, /* VM being reprepared */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - int rc; - assert( ppStmt!=0 ); - *ppStmt = 0; - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeEnterAll(db); - rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); - if( rc==SQLITE_SCHEMA ){ - sqlite3_finalize(*ppStmt); - rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); - } - sqlite3BtreeLeaveAll(db); - sqlite3_mutex_leave(db->mutex); - assert( rc==SQLITE_OK || *ppStmt==0 ); - return rc; -} - -/* -** Rerun the compilation of a statement after a schema change. -** -** If the statement is successfully recompiled, return SQLITE_OK. Otherwise, -** if the statement cannot be recompiled because another connection has -** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error -** occurs, return SQLITE_SCHEMA. -*/ -SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){ - int rc; - sqlite3_stmt *pNew; - const char *zSql; - sqlite3 *db; - - assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) ); - zSql = sqlite3_sql((sqlite3_stmt *)p); - assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */ - db = sqlite3VdbeDb(p); - assert( sqlite3_mutex_held(db->mutex) ); - rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0); - if( rc ){ - if( rc==SQLITE_NOMEM ){ - db->mallocFailed = 1; - } - assert( pNew==0 ); - return rc; - }else{ - assert( pNew!=0 ); - } - sqlite3VdbeSwap((Vdbe*)pNew, p); - sqlite3TransferBindings(pNew, (sqlite3_stmt*)p); - sqlite3VdbeResetStepResult((Vdbe*)pNew); - sqlite3VdbeFinalize((Vdbe*)pNew); - return SQLITE_OK; -} - - -/* -** Two versions of the official API. Legacy and new use. In the legacy -** version, the original SQL text is not saved in the prepared statement -** and so if a schema change occurs, SQLITE_SCHEMA is returned by -** sqlite3_step(). In the new version, the original SQL text is retained -** and the statement is automatically recompiled if an schema change -** occurs. -*/ -SQLITE_API int sqlite3_prepare( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - int rc; - rc = sqlite3LockAndPrepare(db,zSql,nBytes,0,0,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ - return rc; -} -SQLITE_API int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle. */ - const char *zSql, /* UTF-8 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ -){ - int rc; - rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ - return rc; -} - - -#ifndef SQLITE_OMIT_UTF16 -/* -** Compile the UTF-16 encoded SQL statement zSql into a statement handle. -*/ -static int sqlite3Prepare16( - sqlite3 *db, /* Database handle. */ - const void *zSql, /* UTF-16 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const void **pzTail /* OUT: End of parsed string */ -){ - /* This function currently works by first transforming the UTF-16 - ** encoded string to UTF-8, then invoking sqlite3_prepare(). The - ** tricky bit is figuring out the pointer to return in *pzTail. - */ - char *zSql8; - const char *zTail8 = 0; - int rc = SQLITE_OK; - - assert( ppStmt ); - *ppStmt = 0; - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - sqlite3_mutex_enter(db->mutex); - zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); - if( zSql8 ){ - rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); - } - - if( zTail8 && pzTail ){ - /* If sqlite3_prepare returns a tail pointer, we calculate the - ** equivalent pointer into the UTF-16 string by counting the unicode - ** characters between zSql8 and zTail8, and then returning a pointer - ** the same number of characters into the UTF-16 string. - */ - int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8)); - *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed); - } - sqlite3DbFree(db, zSql8); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Two versions of the official API. Legacy and new use. In the legacy -** version, the original SQL text is not saved in the prepared statement -** and so if a schema change occurs, SQLITE_SCHEMA is returned by -** sqlite3_step(). In the new version, the original SQL text is retained -** and the statement is automatically recompiled if an schema change -** occurs. -*/ -SQLITE_API int sqlite3_prepare16( - sqlite3 *db, /* Database handle. */ - const void *zSql, /* UTF-16 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const void **pzTail /* OUT: End of parsed string */ -){ - int rc; - rc = sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ - return rc; -} -SQLITE_API int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle. */ - const void *zSql, /* UTF-16 encoded SQL statement. */ - int nBytes, /* Length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const void **pzTail /* OUT: End of parsed string */ -){ - int rc; - rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ - return rc; -} - -#endif /* SQLITE_OMIT_UTF16 */ - -/************** End of prepare.c *********************************************/ -/************** Begin file select.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle SELECT statements in SQLite. -*/ - - -/* -** Delete all the content of a Select structure but do not deallocate -** the select structure itself. -*/ -static void clearSelect(sqlite3 *db, Select *p){ - sqlite3ExprListDelete(db, p->pEList); - sqlite3SrcListDelete(db, p->pSrc); - sqlite3ExprDelete(db, p->pWhere); - sqlite3ExprListDelete(db, p->pGroupBy); - sqlite3ExprDelete(db, p->pHaving); - sqlite3ExprListDelete(db, p->pOrderBy); - sqlite3SelectDelete(db, p->pPrior); - sqlite3ExprDelete(db, p->pLimit); - sqlite3ExprDelete(db, p->pOffset); -} - -/* -** Initialize a SelectDest structure. -*/ -SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ - pDest->eDest = (u8)eDest; - pDest->iSDParm = iParm; - pDest->affSdst = 0; - pDest->iSdst = 0; - pDest->nSdst = 0; -} - - -/* -** Allocate a new Select structure and return a pointer to that -** structure. -*/ -SQLITE_PRIVATE Select *sqlite3SelectNew( - Parse *pParse, /* Parsing context */ - ExprList *pEList, /* which columns to include in the result */ - SrcList *pSrc, /* the FROM clause -- which tables to scan */ - Expr *pWhere, /* the WHERE clause */ - ExprList *pGroupBy, /* the GROUP BY clause */ - Expr *pHaving, /* the HAVING clause */ - ExprList *pOrderBy, /* the ORDER BY clause */ - u16 selFlags, /* Flag parameters, such as SF_Distinct */ - Expr *pLimit, /* LIMIT value. NULL means not used */ - Expr *pOffset /* OFFSET value. NULL means no offset */ -){ - Select *pNew; - Select standin; - sqlite3 *db = pParse->db; - pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); - assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */ - if( pNew==0 ){ - assert( db->mallocFailed ); - pNew = &standin; - memset(pNew, 0, sizeof(*pNew)); - } - if( pEList==0 ){ - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0)); - } - pNew->pEList = pEList; - if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); - pNew->pSrc = pSrc; - pNew->pWhere = pWhere; - pNew->pGroupBy = pGroupBy; - pNew->pHaving = pHaving; - pNew->pOrderBy = pOrderBy; - pNew->selFlags = selFlags; - pNew->op = TK_SELECT; - pNew->pLimit = pLimit; - pNew->pOffset = pOffset; - assert( pOffset==0 || pLimit!=0 ); - pNew->addrOpenEphm[0] = -1; - pNew->addrOpenEphm[1] = -1; - pNew->addrOpenEphm[2] = -1; - if( db->mallocFailed ) { - clearSelect(db, pNew); - if( pNew!=&standin ) sqlite3DbFree(db, pNew); - pNew = 0; - }else{ - assert( pNew->pSrc!=0 || pParse->nErr>0 ); - } - assert( pNew!=&standin ); - return pNew; -} - -/* -** Delete the given Select structure and all of its substructures. -*/ -SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ - if( p ){ - clearSelect(db, p); - sqlite3DbFree(db, p); - } -} - -/* -** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the -** type of join. Return an integer constant that expresses that type -** in terms of the following bit values: -** -** JT_INNER -** JT_CROSS -** JT_OUTER -** JT_NATURAL -** JT_LEFT -** JT_RIGHT -** -** A full outer join is the combination of JT_LEFT and JT_RIGHT. -** -** If an illegal or unsupported join type is seen, then still return -** a join type, but put an error in the pParse structure. -*/ -SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ - int jointype = 0; - Token *apAll[3]; - Token *p; - /* 0123456789 123456789 123456789 123 */ - static const char zKeyText[] = "naturaleftouterightfullinnercross"; - static const struct { - u8 i; /* Beginning of keyword text in zKeyText[] */ - u8 nChar; /* Length of the keyword in characters */ - u8 code; /* Join type mask */ - } aKeyword[] = { - /* natural */ { 0, 7, JT_NATURAL }, - /* left */ { 6, 4, JT_LEFT|JT_OUTER }, - /* outer */ { 10, 5, JT_OUTER }, - /* right */ { 14, 5, JT_RIGHT|JT_OUTER }, - /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, - /* inner */ { 23, 5, JT_INNER }, - /* cross */ { 28, 5, JT_INNER|JT_CROSS }, - }; - int i, j; - apAll[0] = pA; - apAll[1] = pB; - apAll[2] = pC; - for(i=0; i<3 && apAll[i]; i++){ - p = apAll[i]; - for(j=0; jn==aKeyword[j].nChar - && sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){ - jointype |= aKeyword[j].code; - break; - } - } - testcase( j==0 || j==1 || j==2 || j==3 || j==4 || j==5 || j==6 ); - if( j>=ArraySize(aKeyword) ){ - jointype |= JT_ERROR; - break; - } - } - if( - (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || - (jointype & JT_ERROR)!=0 - ){ - const char *zSp = " "; - assert( pB!=0 ); - if( pC==0 ){ zSp++; } - sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " - "%T %T%s%T", pA, pB, zSp, pC); - jointype = JT_INNER; - }else if( (jointype & JT_OUTER)!=0 - && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){ - sqlite3ErrorMsg(pParse, - "RIGHT and FULL OUTER JOINs are not currently supported"); - jointype = JT_INNER; - } - return jointype; -} - -/* -** Return the index of a column in a table. Return -1 if the column -** is not contained in the table. -*/ -static int columnIndex(Table *pTab, const char *zCol){ - int i; - for(i=0; inCol; i++){ - if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i; - } - return -1; -} - -/* -** Search the first N tables in pSrc, from left to right, looking for a -** table that has a column named zCol. -** -** When found, set *piTab and *piCol to the table index and column index -** of the matching column and return TRUE. -** -** If not found, return FALSE. -*/ -static int tableAndColumnIndex( - SrcList *pSrc, /* Array of tables to search */ - int N, /* Number of tables in pSrc->a[] to search */ - const char *zCol, /* Name of the column we are looking for */ - int *piTab, /* Write index of pSrc->a[] here */ - int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */ -){ - int i; /* For looping over tables in pSrc */ - int iCol; /* Index of column matching zCol */ - - assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */ - for(i=0; ia[i].pTab, zCol); - if( iCol>=0 ){ - if( piTab ){ - *piTab = i; - *piCol = iCol; - } - return 1; - } - } - return 0; -} - -/* -** This function is used to add terms implied by JOIN syntax to the -** WHERE clause expression of a SELECT statement. The new term, which -** is ANDed with the existing WHERE clause, is of the form: -** -** (tab1.col1 = tab2.col2) -** -** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the -** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is -** column iColRight of tab2. -*/ -static void addWhereTerm( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* List of tables in FROM clause */ - int iLeft, /* Index of first table to join in pSrc */ - int iColLeft, /* Index of column in first table */ - int iRight, /* Index of second table in pSrc */ - int iColRight, /* Index of column in second table */ - int isOuterJoin, /* True if this is an OUTER join */ - Expr **ppWhere /* IN/OUT: The WHERE clause to add to */ -){ - sqlite3 *db = pParse->db; - Expr *pE1; - Expr *pE2; - Expr *pEq; - - assert( iLeftnSrc>iRight ); - assert( pSrc->a[iLeft].pTab ); - assert( pSrc->a[iRight].pTab ); - - pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft); - pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight); - - pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0); - if( pEq && isOuterJoin ){ - ExprSetProperty(pEq, EP_FromJoin); - assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) ); - ExprSetIrreducible(pEq); - pEq->iRightJoinTable = (i16)pE2->iTable; - } - *ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq); -} - -/* -** Set the EP_FromJoin property on all terms of the given expression. -** And set the Expr.iRightJoinTable to iTable for every term in the -** expression. -** -** The EP_FromJoin property is used on terms of an expression to tell -** the LEFT OUTER JOIN processing logic that this term is part of the -** join restriction specified in the ON or USING clause and not a part -** of the more general WHERE clause. These terms are moved over to the -** WHERE clause during join processing but we need to remember that they -** originated in the ON or USING clause. -** -** The Expr.iRightJoinTable tells the WHERE clause processing that the -** expression depends on table iRightJoinTable even if that table is not -** explicitly mentioned in the expression. That information is needed -** for cases like this: -** -** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5 -** -** The where clause needs to defer the handling of the t1.x=5 -** term until after the t2 loop of the join. In that way, a -** NULL t2 row will be inserted whenever t1.x!=5. If we do not -** defer the handling of t1.x=5, it will be processed immediately -** after the t1 loop and rows with t1.x!=5 will never appear in -** the output, which is incorrect. -*/ -static void setJoinExpr(Expr *p, int iTable){ - while( p ){ - ExprSetProperty(p, EP_FromJoin); - assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); - ExprSetIrreducible(p); - p->iRightJoinTable = (i16)iTable; - setJoinExpr(p->pLeft, iTable); - p = p->pRight; - } -} - -/* -** This routine processes the join information for a SELECT statement. -** ON and USING clauses are converted into extra terms of the WHERE clause. -** NATURAL joins also create extra WHERE clause terms. -** -** The terms of a FROM clause are contained in the Select.pSrc structure. -** The left most table is the first entry in Select.pSrc. The right-most -** table is the last entry. The join operator is held in the entry to -** the left. Thus entry 0 contains the join operator for the join between -** entries 0 and 1. Any ON or USING clauses associated with the join are -** also attached to the left entry. -** -** This routine returns the number of errors encountered. -*/ -static int sqliteProcessJoin(Parse *pParse, Select *p){ - SrcList *pSrc; /* All tables in the FROM clause */ - int i, j; /* Loop counters */ - struct SrcList_item *pLeft; /* Left table being joined */ - struct SrcList_item *pRight; /* Right table being joined */ - - pSrc = p->pSrc; - pLeft = &pSrc->a[0]; - pRight = &pLeft[1]; - for(i=0; inSrc-1; i++, pRight++, pLeft++){ - Table *pLeftTab = pLeft->pTab; - Table *pRightTab = pRight->pTab; - int isOuter; - - if( NEVER(pLeftTab==0 || pRightTab==0) ) continue; - isOuter = (pRight->jointype & JT_OUTER)!=0; - - /* When the NATURAL keyword is present, add WHERE clause terms for - ** every column that the two tables have in common. - */ - if( pRight->jointype & JT_NATURAL ){ - if( pRight->pOn || pRight->pUsing ){ - sqlite3ErrorMsg(pParse, "a NATURAL join may not have " - "an ON or USING clause", 0); - return 1; - } - for(j=0; jnCol; j++){ - char *zName; /* Name of column in the right table */ - int iLeft; /* Matching left table */ - int iLeftCol; /* Matching column in the left table */ - - zName = pRightTab->aCol[j].zName; - if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){ - addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j, - isOuter, &p->pWhere); - } - } - } - - /* Disallow both ON and USING clauses in the same join - */ - if( pRight->pOn && pRight->pUsing ){ - sqlite3ErrorMsg(pParse, "cannot have both ON and USING " - "clauses in the same join"); - return 1; - } - - /* Add the ON clause to the end of the WHERE clause, connected by - ** an AND operator. - */ - if( pRight->pOn ){ - if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor); - p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn); - pRight->pOn = 0; - } - - /* Create extra terms on the WHERE clause for each column named - ** in the USING clause. Example: If the two tables to be joined are - ** A and B and the USING clause names X, Y, and Z, then add this - ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z - ** Report an error if any column mentioned in the USING clause is - ** not contained in both tables to be joined. - */ - if( pRight->pUsing ){ - IdList *pList = pRight->pUsing; - for(j=0; jnId; j++){ - char *zName; /* Name of the term in the USING clause */ - int iLeft; /* Table on the left with matching column name */ - int iLeftCol; /* Column number of matching column on the left */ - int iRightCol; /* Column number of matching column on the right */ - - zName = pList->a[j].zName; - iRightCol = columnIndex(pRightTab, zName); - if( iRightCol<0 - || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) - ){ - sqlite3ErrorMsg(pParse, "cannot join using column %s - column " - "not present in both tables", zName); - return 1; - } - addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol, - isOuter, &p->pWhere); - } - } - } - return 0; -} - -/* -** Insert code into "v" that will push the record on the top of the -** stack into the sorter. -*/ -static void pushOntoSorter( - Parse *pParse, /* Parser context */ - ExprList *pOrderBy, /* The ORDER BY clause */ - Select *pSelect, /* The whole SELECT statement */ - int regData /* Register holding data to be sorted */ -){ - Vdbe *v = pParse->pVdbe; - int nExpr = pOrderBy->nExpr; - int regBase = sqlite3GetTempRange(pParse, nExpr+2); - int regRecord = sqlite3GetTempReg(pParse); - int op; - sqlite3ExprCacheClear(pParse); - sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0); - sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); - sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); - if( pSelect->selFlags & SF_UseSorter ){ - op = OP_SorterInsert; - }else{ - op = OP_IdxInsert; - } - sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord); - sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); - if( pSelect->iLimit ){ - int addr1, addr2; - int iLimit; - if( pSelect->iOffset ){ - iLimit = pSelect->iOffset+1; - }else{ - iLimit = pSelect->iLimit; - } - addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); - sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); - addr2 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, addr1); - sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor); - sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor); - sqlite3VdbeJumpHere(v, addr2); - } -} - -/* -** Add code to implement the OFFSET -*/ -static void codeOffset( - Vdbe *v, /* Generate code into this VM */ - Select *p, /* The SELECT statement being coded */ - int iContinue /* Jump here to skip the current record */ -){ - if( p->iOffset && iContinue!=0 ){ - int addr; - sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1); - addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset); - sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); - VdbeComment((v, "skip OFFSET records")); - sqlite3VdbeJumpHere(v, addr); - } -} - -/* -** Add code that will check to make sure the N registers starting at iMem -** form a distinct entry. iTab is a sorting index that holds previously -** seen combinations of the N values. A new entry is made in iTab -** if the current N values are new. -** -** A jump to addrRepeat is made and the N+1 values are popped from the -** stack if the top N elements are not distinct. -*/ -static void codeDistinct( - Parse *pParse, /* Parsing and code generating context */ - int iTab, /* A sorting index used to test for distinctness */ - int addrRepeat, /* Jump to here if not distinct */ - int N, /* Number of elements */ - int iMem /* First element */ -){ - Vdbe *v; - int r1; - - v = pParse->pVdbe; - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); - sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); - sqlite3ReleaseTempReg(pParse, r1); -} - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** Generate an error message when a SELECT is used within a subexpression -** (example: "a IN (SELECT * FROM table)") but it has more than 1 result -** column. We do this in a subroutine because the error used to occur -** in multiple places. (The error only occurs in one place now, but we -** retain the subroutine to minimize code disruption.) -*/ -static int checkForMultiColumnSelectError( - Parse *pParse, /* Parse context. */ - SelectDest *pDest, /* Destination of SELECT results */ - int nExpr /* Number of result columns returned by SELECT */ -){ - int eDest = pDest->eDest; - if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){ - sqlite3ErrorMsg(pParse, "only a single result allowed for " - "a SELECT that is part of an expression"); - return 1; - }else{ - return 0; - } -} -#endif - -/* -** An instance of the following object is used to record information about -** how to process the DISTINCT keyword, to simplify passing that information -** into the selectInnerLoop() routine. -*/ -typedef struct DistinctCtx DistinctCtx; -struct DistinctCtx { - u8 isTnct; /* True if the DISTINCT keyword is present */ - u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */ - int tabTnct; /* Ephemeral table used for DISTINCT processing */ - int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */ -}; - -/* -** This routine generates the code for the inside of the inner loop -** of a SELECT. -** -** If srcTab and nColumn are both zero, then the pEList expressions -** are evaluated in order to get the data for this row. If nColumn>0 -** then data is pulled from srcTab and pEList is used only to get the -** datatypes for each column. -*/ -static void selectInnerLoop( - Parse *pParse, /* The parser context */ - Select *p, /* The complete select statement being coded */ - ExprList *pEList, /* List of values being extracted */ - int srcTab, /* Pull data from this table */ - int nColumn, /* Number of columns in the source table */ - ExprList *pOrderBy, /* If not NULL, sort results using this key */ - DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */ - SelectDest *pDest, /* How to dispose of the results */ - int iContinue, /* Jump here to continue with next row */ - int iBreak /* Jump here to break out of the inner loop */ -){ - Vdbe *v = pParse->pVdbe; - int i; - int hasDistinct; /* True if the DISTINCT keyword is present */ - int regResult; /* Start of memory holding result set */ - int eDest = pDest->eDest; /* How to dispose of results */ - int iParm = pDest->iSDParm; /* First argument to disposal method */ - int nResultCol; /* Number of result columns */ - - assert( v ); - if( NEVER(v==0) ) return; - assert( pEList!=0 ); - hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; - if( pOrderBy==0 && !hasDistinct ){ - codeOffset(v, p, iContinue); - } - - /* Pull the requested columns. - */ - if( nColumn>0 ){ - nResultCol = nColumn; - }else{ - nResultCol = pEList->nExpr; - } - if( pDest->iSdst==0 ){ - pDest->iSdst = pParse->nMem+1; - pDest->nSdst = nResultCol; - pParse->nMem += nResultCol; - }else{ - assert( pDest->nSdst==nResultCol ); - } - regResult = pDest->iSdst; - if( nColumn>0 ){ - for(i=0; inExpr==nColumn ); - switch( pDistinct->eTnctType ){ - case WHERE_DISTINCT_ORDERED: { - VdbeOp *pOp; /* No longer required OpenEphemeral instr. */ - int iJump; /* Jump destination */ - int regPrev; /* Previous row content */ - - /* Allocate space for the previous row */ - regPrev = pParse->nMem+1; - pParse->nMem += nColumn; - - /* Change the OP_OpenEphemeral coded earlier to an OP_Null - ** sets the MEM_Cleared bit on the first register of the - ** previous value. This will cause the OP_Ne below to always - ** fail on the first iteration of the loop even if the first - ** row is all NULLs. - */ - sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct); - pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct); - pOp->opcode = OP_Null; - pOp->p1 = 1; - pOp->p2 = regPrev; - - iJump = sqlite3VdbeCurrentAddr(v) + nColumn; - for(i=0; ia[i].pExpr); - if( iaddrTnct); - break; - } - - default: { - assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED ); - codeDistinct(pParse, pDistinct->tabTnct, iContinue, nColumn, regResult); - break; - } - } - if( pOrderBy==0 ){ - codeOffset(v, p, iContinue); - } - } - - switch( eDest ){ - /* In this mode, write each query result to the key of the temporary - ** table iParm. - */ -#ifndef SQLITE_OMIT_COMPOUND_SELECT - case SRT_Union: { - int r1; - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); - sqlite3ReleaseTempReg(pParse, r1); - break; - } - - /* Construct a record from the query result, but instead of - ** saving that record, use it as a key to delete elements from - ** the temporary table iParm. - */ - case SRT_Except: { - sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn); - break; - } -#endif - - /* Store the result as data using a unique key. - */ - case SRT_Table: - case SRT_EphemTab: { - int r1 = sqlite3GetTempReg(pParse); - testcase( eDest==SRT_Table ); - testcase( eDest==SRT_EphemTab ); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); - if( pOrderBy ){ - pushOntoSorter(pParse, pOrderBy, p, r1); - }else{ - int r2 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); - sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3ReleaseTempReg(pParse, r2); - } - sqlite3ReleaseTempReg(pParse, r1); - break; - } - -#ifndef SQLITE_OMIT_SUBQUERY - /* If we are creating a set for an "expr IN (SELECT ...)" construct, - ** then there should be a single item on the stack. Write this - ** item into the set table with bogus data. - */ - case SRT_Set: { - assert( nColumn==1 ); - pDest->affSdst = - sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst); - if( pOrderBy ){ - /* At first glance you would think we could optimize out the - ** ORDER BY in this case since the order of entries in the set - ** does not matter. But there might be a LIMIT clause, in which - ** case the order does matter */ - pushOntoSorter(pParse, pOrderBy, p, regResult); - }else{ - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1); - sqlite3ExprCacheAffinityChange(pParse, regResult, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); - sqlite3ReleaseTempReg(pParse, r1); - } - break; - } - - /* If any row exist in the result set, record that fact and abort. - */ - case SRT_Exists: { - sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); - /* The LIMIT clause will terminate the loop for us */ - break; - } - - /* If this is a scalar select that is part of an expression, then - ** store the results in the appropriate memory cell and break out - ** of the scan loop. - */ - case SRT_Mem: { - assert( nColumn==1 ); - if( pOrderBy ){ - pushOntoSorter(pParse, pOrderBy, p, regResult); - }else{ - sqlite3ExprCodeMove(pParse, regResult, iParm, 1); - /* The LIMIT clause will jump out of the loop for us */ - } - break; - } -#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ - - /* Send the data to the callback function or to a subroutine. In the - ** case of a subroutine, the subroutine itself is responsible for - ** popping the data from the stack. - */ - case SRT_Coroutine: - case SRT_Output: { - testcase( eDest==SRT_Coroutine ); - testcase( eDest==SRT_Output ); - if( pOrderBy ){ - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); - pushOntoSorter(pParse, pOrderBy, p, r1); - sqlite3ReleaseTempReg(pParse, r1); - }else if( eDest==SRT_Coroutine ){ - sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); - }else{ - sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); - sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn); - } - break; - } - -#if !defined(SQLITE_OMIT_TRIGGER) - /* Discard the results. This is used for SELECT statements inside - ** the body of a TRIGGER. The purpose of such selects is to call - ** user-defined functions that have side effects. We do not care - ** about the actual results of the select. - */ - default: { - assert( eDest==SRT_Discard ); - break; - } -#endif - } - - /* Jump to the end of the loop if the LIMIT is reached. Except, if - ** there is a sorter, in which case the sorter has already limited - ** the output for us. - */ - if( pOrderBy==0 && p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); - } -} - -/* -** Given an expression list, generate a KeyInfo structure that records -** the collating sequence for each expression in that expression list. -** -** If the ExprList is an ORDER BY or GROUP BY clause then the resulting -** KeyInfo structure is appropriate for initializing a virtual index to -** implement that clause. If the ExprList is the result set of a SELECT -** then the KeyInfo structure is appropriate for initializing a virtual -** index to implement a DISTINCT test. -** -** Space to hold the KeyInfo structure is obtain from malloc. The calling -** function is responsible for seeing that this structure is eventually -** freed. Add the KeyInfo structure to the P4 field of an opcode using -** P4_KEYINFO_HANDOFF is the usual way of dealing with this. -*/ -static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ - sqlite3 *db = pParse->db; - int nExpr; - KeyInfo *pInfo; - struct ExprList_item *pItem; - int i; - - nExpr = pList->nExpr; - pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) ); - if( pInfo ){ - pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr]; - pInfo->nField = (u16)nExpr; - pInfo->enc = ENC(db); - pInfo->db = db; - for(i=0, pItem=pList->a; ipExpr); - if( !pColl ){ - pColl = db->pDfltColl; - } - pInfo->aColl[i] = pColl; - pInfo->aSortOrder[i] = pItem->sortOrder; - } - } - return pInfo; -} - -#ifndef SQLITE_OMIT_COMPOUND_SELECT -/* -** Name of the connection operator, used for error messages. -*/ -static const char *selectOpName(int id){ - char *z; - switch( id ){ - case TK_ALL: z = "UNION ALL"; break; - case TK_INTERSECT: z = "INTERSECT"; break; - case TK_EXCEPT: z = "EXCEPT"; break; - default: z = "UNION"; break; - } - return z; -} -#endif /* SQLITE_OMIT_COMPOUND_SELECT */ - -#ifndef SQLITE_OMIT_EXPLAIN -/* -** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function -** is a no-op. Otherwise, it adds a single row of output to the EQP result, -** where the caption is of the form: -** -** "USE TEMP B-TREE FOR xxx" -** -** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which -** is determined by the zUsage argument. -*/ -static void explainTempTable(Parse *pParse, const char *zUsage){ - if( pParse->explain==2 ){ - Vdbe *v = pParse->pVdbe; - char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); - } -} - -/* -** Assign expression b to lvalue a. A second, no-op, version of this macro -** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code -** in sqlite3Select() to assign values to structure member variables that -** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the -** code with #ifndef directives. -*/ -# define explainSetInteger(a, b) a = b - -#else -/* No-op versions of the explainXXX() functions and macros. */ -# define explainTempTable(y,z) -# define explainSetInteger(y,z) -#endif - -#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT) -/* -** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function -** is a no-op. Otherwise, it adds a single row of output to the EQP result, -** where the caption is of one of the two forms: -** -** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)" -** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)" -** -** where iSub1 and iSub2 are the integers passed as the corresponding -** function parameters, and op is the text representation of the parameter -** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT, -** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is -** false, or the second form if it is true. -*/ -static void explainComposite( - Parse *pParse, /* Parse context */ - int op, /* One of TK_UNION, TK_EXCEPT etc. */ - int iSub1, /* Subquery id 1 */ - int iSub2, /* Subquery id 2 */ - int bUseTmp /* True if a temp table was used */ -){ - assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL ); - if( pParse->explain==2 ){ - Vdbe *v = pParse->pVdbe; - char *zMsg = sqlite3MPrintf( - pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2, - bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op) - ); - sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); - } -} -#else -/* No-op versions of the explainXXX() functions and macros. */ -# define explainComposite(v,w,x,y,z) -#endif - -/* -** If the inner loop was generated using a non-null pOrderBy argument, -** then the results were placed in a sorter. After the loop is terminated -** we need to run the sorter and output the results. The following -** routine generates the code needed to do that. -*/ -static void generateSortTail( - Parse *pParse, /* Parsing context */ - Select *p, /* The SELECT statement */ - Vdbe *v, /* Generate code into this VDBE */ - int nColumn, /* Number of columns of data */ - SelectDest *pDest /* Write the sorted results here */ -){ - int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */ - int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ - int addr; - int iTab; - int pseudoTab = 0; - ExprList *pOrderBy = p->pOrderBy; - - int eDest = pDest->eDest; - int iParm = pDest->iSDParm; - - int regRow; - int regRowid; - - iTab = pOrderBy->iECursor; - regRow = sqlite3GetTempReg(pParse); - if( eDest==SRT_Output || eDest==SRT_Coroutine ){ - pseudoTab = pParse->nTab++; - sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn); - regRowid = 0; - }else{ - regRowid = sqlite3GetTempReg(pParse); - } - if( p->selFlags & SF_UseSorter ){ - int regSortOut = ++pParse->nMem; - int ptab2 = pParse->nTab++; - sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2); - addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); - codeOffset(v, p, addrContinue); - sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut); - sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow); - sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); - }else{ - addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); - codeOffset(v, p, addrContinue); - sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow); - } - switch( eDest ){ - case SRT_Table: - case SRT_EphemTab: { - testcase( eDest==SRT_Table ); - testcase( eDest==SRT_EphemTab ); - sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case SRT_Set: { - assert( nColumn==1 ); - sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, - &pDest->affSdst, 1); - sqlite3ExprCacheAffinityChange(pParse, regRow, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); - break; - } - case SRT_Mem: { - assert( nColumn==1 ); - sqlite3ExprCodeMove(pParse, regRow, iParm, 1); - /* The LIMIT clause will terminate the loop for us */ - break; - } -#endif - default: { - int i; - assert( eDest==SRT_Output || eDest==SRT_Coroutine ); - testcase( eDest==SRT_Output ); - testcase( eDest==SRT_Coroutine ); - for(i=0; iiSdst+i ); - sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iSdst+i); - if( i==0 ){ - sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); - } - } - if( eDest==SRT_Output ){ - sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); - sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn); - }else{ - sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); - } - break; - } - } - sqlite3ReleaseTempReg(pParse, regRow); - sqlite3ReleaseTempReg(pParse, regRowid); - - /* The bottom of the loop - */ - sqlite3VdbeResolveLabel(v, addrContinue); - if( p->selFlags & SF_UseSorter ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); - }else{ - sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); - } - sqlite3VdbeResolveLabel(v, addrBreak); - if( eDest==SRT_Output || eDest==SRT_Coroutine ){ - sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0); - } -} - -/* -** Return a pointer to a string containing the 'declaration type' of the -** expression pExpr. The string may be treated as static by the caller. -** -** The declaration type is the exact datatype definition extracted from the -** original CREATE TABLE statement if the expression is a column. The -** declaration type for a ROWID field is INTEGER. Exactly when an expression -** is considered a column can be complex in the presence of subqueries. The -** result-set expression in all of the following SELECT statements is -** considered a column by this function. -** -** SELECT col FROM tbl; -** SELECT (SELECT col FROM tbl; -** SELECT (SELECT col FROM tbl); -** SELECT abc FROM (SELECT col AS abc FROM tbl); -** -** The declaration type for any expression other than a column is NULL. -*/ -static const char *columnType( - NameContext *pNC, - Expr *pExpr, - const char **pzOriginDb, - const char **pzOriginTab, - const char **pzOriginCol -){ - char const *zType = 0; - char const *zOriginDb = 0; - char const *zOriginTab = 0; - char const *zOriginCol = 0; - int j; - if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0; - - switch( pExpr->op ){ - case TK_AGG_COLUMN: - case TK_COLUMN: { - /* The expression is a column. Locate the table the column is being - ** extracted from in NameContext.pSrcList. This table may be real - ** database table or a subquery. - */ - Table *pTab = 0; /* Table structure column is extracted from */ - Select *pS = 0; /* Select the column is extracted from */ - int iCol = pExpr->iColumn; /* Index of column in pTab */ - testcase( pExpr->op==TK_AGG_COLUMN ); - testcase( pExpr->op==TK_COLUMN ); - while( pNC && !pTab ){ - SrcList *pTabList = pNC->pSrcList; - for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); - if( jnSrc ){ - pTab = pTabList->a[j].pTab; - pS = pTabList->a[j].pSelect; - }else{ - pNC = pNC->pNext; - } - } - - if( pTab==0 ){ - /* At one time, code such as "SELECT new.x" within a trigger would - ** cause this condition to run. Since then, we have restructured how - ** trigger code is generated and so this condition is no longer - ** possible. However, it can still be true for statements like - ** the following: - ** - ** CREATE TABLE t1(col INTEGER); - ** SELECT (SELECT t1.col) FROM FROM t1; - ** - ** when columnType() is called on the expression "t1.col" in the - ** sub-select. In this case, set the column type to NULL, even - ** though it should really be "INTEGER". - ** - ** This is not a problem, as the column type of "t1.col" is never - ** used. When columnType() is called on the expression - ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT - ** branch below. */ - break; - } - - assert( pTab && pExpr->pTab==pTab ); - if( pS ){ - /* The "table" is actually a sub-select or a view in the FROM clause - ** of the SELECT statement. Return the declaration type and origin - ** data for the result-set column of the sub-select. - */ - if( iCol>=0 && ALWAYS(iColpEList->nExpr) ){ - /* If iCol is less than zero, then the expression requests the - ** rowid of the sub-select or view. This expression is legal (see - ** test case misc2.2.2) - it always evaluates to NULL. - */ - NameContext sNC; - Expr *p = pS->pEList->a[iCol].pExpr; - sNC.pSrcList = pS->pSrc; - sNC.pNext = pNC; - sNC.pParse = pNC->pParse; - zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); - } - }else if( ALWAYS(pTab->pSchema) ){ - /* A real table */ - assert( !pS ); - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==-1 || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zType = "INTEGER"; - zOriginCol = "rowid"; - }else{ - zType = pTab->aCol[iCol].zType; - zOriginCol = pTab->aCol[iCol].zName; - } - zOriginTab = pTab->zName; - if( pNC->pParse ){ - int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); - zOriginDb = pNC->pParse->db->aDb[iDb].zName; - } - } - break; - } -#ifndef SQLITE_OMIT_SUBQUERY - case TK_SELECT: { - /* The expression is a sub-select. Return the declaration type and - ** origin info for the single column in the result set of the SELECT - ** statement. - */ - NameContext sNC; - Select *pS = pExpr->x.pSelect; - Expr *p = pS->pEList->a[0].pExpr; - assert( ExprHasProperty(pExpr, EP_xIsSelect) ); - sNC.pSrcList = pS->pSrc; - sNC.pNext = pNC; - sNC.pParse = pNC->pParse; - zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); - break; - } -#endif - } - - if( pzOriginDb ){ - assert( pzOriginTab && pzOriginCol ); - *pzOriginDb = zOriginDb; - *pzOriginTab = zOriginTab; - *pzOriginCol = zOriginCol; - } - return zType; -} - -/* -** Generate code that will tell the VDBE the declaration types of columns -** in the result set. -*/ -static void generateColumnTypes( - Parse *pParse, /* Parser context */ - SrcList *pTabList, /* List of tables */ - ExprList *pEList /* Expressions defining the result set */ -){ -#ifndef SQLITE_OMIT_DECLTYPE - Vdbe *v = pParse->pVdbe; - int i; - NameContext sNC; - sNC.pSrcList = pTabList; - sNC.pParse = pParse; - for(i=0; inExpr; i++){ - Expr *p = pEList->a[i].pExpr; - const char *zType; -#ifdef SQLITE_ENABLE_COLUMN_METADATA - const char *zOrigDb = 0; - const char *zOrigTab = 0; - const char *zOrigCol = 0; - zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); - - /* The vdbe must make its own copy of the column-type and other - ** column specific strings, in case the schema is reset before this - ** virtual machine is deleted. - */ - sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT); - sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); - sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); -#else - zType = columnType(&sNC, p, 0, 0, 0); -#endif - sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); - } -#endif /* SQLITE_OMIT_DECLTYPE */ -} - -/* -** Generate code that will tell the VDBE the names of columns -** in the result set. This information is used to provide the -** azCol[] values in the callback. -*/ -static void generateColumnNames( - Parse *pParse, /* Parser context */ - SrcList *pTabList, /* List of tables */ - ExprList *pEList /* Expressions defining the result set */ -){ - Vdbe *v = pParse->pVdbe; - int i, j; - sqlite3 *db = pParse->db; - int fullNames, shortNames; - -#ifndef SQLITE_OMIT_EXPLAIN - /* If this is an EXPLAIN, skip this step */ - if( pParse->explain ){ - return; - } -#endif - - if( pParse->colNamesSet || NEVER(v==0) || db->mallocFailed ) return; - pParse->colNamesSet = 1; - fullNames = (db->flags & SQLITE_FullColNames)!=0; - shortNames = (db->flags & SQLITE_ShortColNames)!=0; - sqlite3VdbeSetNumCols(v, pEList->nExpr); - for(i=0; inExpr; i++){ - Expr *p; - p = pEList->a[i].pExpr; - if( NEVER(p==0) ) continue; - if( pEList->a[i].zName ){ - char *zName = pEList->a[i].zName; - sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); - }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){ - Table *pTab; - char *zCol; - int iCol = p->iColumn; - for(j=0; ALWAYS(jnSrc); j++){ - if( pTabList->a[j].iCursor==p->iTable ) break; - } - assert( jnSrc ); - pTab = pTabList->a[j].pTab; - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==-1 || (iCol>=0 && iColnCol) ); - if( iCol<0 ){ - zCol = "rowid"; - }else{ - zCol = pTab->aCol[iCol].zName; - } - if( !shortNames && !fullNames ){ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, - sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); - }else if( fullNames ){ - char *zName = 0; - zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol); - sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC); - }else{ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT); - } - }else{ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, - sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); - } - } - generateColumnTypes(pParse, pTabList, pEList); -} - -/* -** Given a an expression list (which is really the list of expressions -** that form the result set of a SELECT statement) compute appropriate -** column names for a table that would hold the expression list. -** -** All column names will be unique. -** -** Only the column names are computed. Column.zType, Column.zColl, -** and other fields of Column are zeroed. -** -** Return SQLITE_OK on success. If a memory allocation error occurs, -** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. -*/ -static int selectColumnsFromExprList( - Parse *pParse, /* Parsing context */ - ExprList *pEList, /* Expr list from which to derive column names */ - i16 *pnCol, /* Write the number of columns here */ - Column **paCol /* Write the new column list here */ -){ - sqlite3 *db = pParse->db; /* Database connection */ - int i, j; /* Loop counters */ - int cnt; /* Index added to make the name unique */ - Column *aCol, *pCol; /* For looping over result columns */ - int nCol; /* Number of columns in the result set */ - Expr *p; /* Expression for a single result column */ - char *zName; /* Column name */ - int nName; /* Size of name in zName[] */ - - if( pEList ){ - nCol = pEList->nExpr; - aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); - testcase( aCol==0 ); - }else{ - nCol = 0; - aCol = 0; - } - *pnCol = nCol; - *paCol = aCol; - - for(i=0, pCol=aCol; ia[i].pExpr); - if( (zName = pEList->a[i].zName)!=0 ){ - /* If the column contains an "AS " phrase, use as the name */ - zName = sqlite3DbStrDup(db, zName); - }else{ - Expr *pColExpr = p; /* The expression that is the result column name */ - Table *pTab; /* Table associated with this expression */ - while( pColExpr->op==TK_DOT ){ - pColExpr = pColExpr->pRight; - assert( pColExpr!=0 ); - } - if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){ - /* For columns use the column name name */ - int iCol = pColExpr->iColumn; - pTab = pColExpr->pTab; - if( iCol<0 ) iCol = pTab->iPKey; - zName = sqlite3MPrintf(db, "%s", - iCol>=0 ? pTab->aCol[iCol].zName : "rowid"); - }else if( pColExpr->op==TK_ID ){ - assert( !ExprHasProperty(pColExpr, EP_IntValue) ); - zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken); - }else{ - /* Use the original text of the column expression as its name */ - zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan); - } - } - if( db->mallocFailed ){ - sqlite3DbFree(db, zName); - break; - } - - /* Make sure the column name is unique. If the name is not unique, - ** append a integer to the name so that it becomes unique. - */ - nName = sqlite3Strlen30(zName); - for(j=cnt=0; j1 && sqlite3Isdigit(zName[k]); k--){} - if( zName[k]==':' ) nName = k; - zName[nName] = 0; - zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); - sqlite3DbFree(db, zName); - zName = zNewName; - j = -1; - if( zName==0 ) break; - } - } - pCol->zName = zName; - } - if( db->mallocFailed ){ - for(j=0; jdb; - NameContext sNC; - Column *pCol; - CollSeq *pColl; - int i; - Expr *p; - struct ExprList_item *a; - - assert( pSelect!=0 ); - assert( (pSelect->selFlags & SF_Resolved)!=0 ); - assert( nCol==pSelect->pEList->nExpr || db->mallocFailed ); - if( db->mallocFailed ) return; - memset(&sNC, 0, sizeof(sNC)); - sNC.pSrcList = pSelect->pSrc; - a = pSelect->pEList->a; - for(i=0, pCol=aCol; izType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0)); - pCol->affinity = sqlite3ExprAffinity(p); - if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE; - pColl = sqlite3ExprCollSeq(pParse, p); - if( pColl ){ - pCol->zColl = sqlite3DbStrDup(db, pColl->zName); - } - } -} - -/* -** Given a SELECT statement, generate a Table structure that describes -** the result set of that SELECT. -*/ -SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ - Table *pTab; - sqlite3 *db = pParse->db; - int savedFlags; - - savedFlags = db->flags; - db->flags &= ~SQLITE_FullColNames; - db->flags |= SQLITE_ShortColNames; - sqlite3SelectPrep(pParse, pSelect, 0); - if( pParse->nErr ) return 0; - while( pSelect->pPrior ) pSelect = pSelect->pPrior; - db->flags = savedFlags; - pTab = sqlite3DbMallocZero(db, sizeof(Table) ); - if( pTab==0 ){ - return 0; - } - /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside - ** is disabled */ - assert( db->lookaside.bEnabled==0 ); - pTab->nRef = 1; - pTab->zName = 0; - pTab->nRowEst = 1000000; - selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); - selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect); - pTab->iPKey = -1; - if( db->mallocFailed ){ - sqlite3DeleteTable(db, pTab); - return 0; - } - return pTab; -} - -/* -** Get a VDBE for the given parser context. Create a new one if necessary. -** If an error occurs, return NULL and leave a message in pParse. -*/ -SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ - Vdbe *v = pParse->pVdbe; - if( v==0 ){ - v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); -#ifndef SQLITE_OMIT_TRACE - if( v ){ - sqlite3VdbeAddOp0(v, OP_Trace); - } -#endif - } - return v; -} - - -/* -** Compute the iLimit and iOffset fields of the SELECT based on the -** pLimit and pOffset expressions. pLimit and pOffset hold the expressions -** that appear in the original SQL statement after the LIMIT and OFFSET -** keywords. Or NULL if those keywords are omitted. iLimit and iOffset -** are the integer memory register numbers for counters used to compute -** the limit and offset. If there is no limit and/or offset, then -** iLimit and iOffset are negative. -** -** This routine changes the values of iLimit and iOffset only if -** a limit or offset is defined by pLimit and pOffset. iLimit and -** iOffset should have been preset to appropriate default values -** (usually but not always -1) prior to calling this routine. -** Only if pLimit!=0 or pOffset!=0 do the limit registers get -** redefined. The UNION ALL operator uses this property to force -** the reuse of the same limit and offset registers across multiple -** SELECT statements. -*/ -static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ - Vdbe *v = 0; - int iLimit = 0; - int iOffset; - int addr1, n; - if( p->iLimit ) return; - - /* - ** "LIMIT -1" always shows all rows. There is some - ** contraversy about what the correct behavior should be. - ** The current implementation interprets "LIMIT 0" to mean - ** no rows. - */ - sqlite3ExprCacheClear(pParse); - assert( p->pOffset==0 || p->pLimit!=0 ); - if( p->pLimit ){ - p->iLimit = iLimit = ++pParse->nMem; - v = sqlite3GetVdbe(pParse); - if( NEVER(v==0) ) return; /* VDBE should have already been allocated */ - if( sqlite3ExprIsInteger(p->pLimit, &n) ){ - sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); - VdbeComment((v, "LIMIT counter")); - if( n==0 ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); - }else{ - if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n; - } - }else{ - sqlite3ExprCode(pParse, p->pLimit, iLimit); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); - VdbeComment((v, "LIMIT counter")); - sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); - } - if( p->pOffset ){ - p->iOffset = iOffset = ++pParse->nMem; - pParse->nMem++; /* Allocate an extra register for limit+offset */ - sqlite3ExprCode(pParse, p->pOffset, iOffset); - sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); - VdbeComment((v, "OFFSET counter")); - addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); - sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); - sqlite3VdbeJumpHere(v, addr1); - sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); - VdbeComment((v, "LIMIT+OFFSET")); - addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); - sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); - sqlite3VdbeJumpHere(v, addr1); - } - } -} - -#ifndef SQLITE_OMIT_COMPOUND_SELECT -/* -** Return the appropriate collating sequence for the iCol-th column of -** the result set for the compound-select statement "p". Return NULL if -** the column has no default collating sequence. -** -** The collating sequence for the compound select is taken from the -** left-most term of the select that has a collating sequence. -*/ -static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ - CollSeq *pRet; - if( p->pPrior ){ - pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); - }else{ - pRet = 0; - } - assert( iCol>=0 ); - if( pRet==0 && iColpEList->nExpr ){ - pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); - } - return pRet; -} -#endif /* SQLITE_OMIT_COMPOUND_SELECT */ - -/* Forward reference */ -static int multiSelectOrderBy( - Parse *pParse, /* Parsing context */ - Select *p, /* The right-most of SELECTs to be coded */ - SelectDest *pDest /* What to do with query results */ -); - - -#ifndef SQLITE_OMIT_COMPOUND_SELECT -/* -** This routine is called to process a compound query form from -** two or more separate queries using UNION, UNION ALL, EXCEPT, or -** INTERSECT -** -** "p" points to the right-most of the two queries. the query on the -** left is p->pPrior. The left query could also be a compound query -** in which case this routine will be called recursively. -** -** The results of the total query are to be written into a destination -** of type eDest with parameter iParm. -** -** Example 1: Consider a three-way compound SQL statement. -** -** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3 -** -** This statement is parsed up as follows: -** -** SELECT c FROM t3 -** | -** `-----> SELECT b FROM t2 -** | -** `------> SELECT a FROM t1 -** -** The arrows in the diagram above represent the Select.pPrior pointer. -** So if this routine is called with p equal to the t3 query, then -** pPrior will be the t2 query. p->op will be TK_UNION in this case. -** -** Notice that because of the way SQLite parses compound SELECTs, the -** individual selects always group from left to right. -*/ -static int multiSelect( - Parse *pParse, /* Parsing context */ - Select *p, /* The right-most of SELECTs to be coded */ - SelectDest *pDest /* What to do with query results */ -){ - int rc = SQLITE_OK; /* Success code from a subroutine */ - Select *pPrior; /* Another SELECT immediately to our left */ - Vdbe *v; /* Generate code to this VDBE */ - SelectDest dest; /* Alternative data destination */ - Select *pDelete = 0; /* Chain of simple selects to delete */ - sqlite3 *db; /* Database connection */ -#ifndef SQLITE_OMIT_EXPLAIN - int iSub1; /* EQP id of left-hand query */ - int iSub2; /* EQP id of right-hand query */ -#endif - - /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only - ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. - */ - assert( p && p->pPrior ); /* Calling function guarantees this much */ - db = pParse->db; - pPrior = p->pPrior; - assert( pPrior->pRightmost!=pPrior ); - assert( pPrior->pRightmost==p->pRightmost ); - dest = *pDest; - if( pPrior->pOrderBy ){ - sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", - selectOpName(p->op)); - rc = 1; - goto multi_select_end; - } - if( pPrior->pLimit ){ - sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", - selectOpName(p->op)); - rc = 1; - goto multi_select_end; - } - - v = sqlite3GetVdbe(pParse); - assert( v!=0 ); /* The VDBE already created by calling function */ - - /* Create the destination temporary table if necessary - */ - if( dest.eDest==SRT_EphemTab ){ - assert( p->pEList ); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr); - sqlite3VdbeChangeP5(v, BTREE_UNORDERED); - dest.eDest = SRT_Table; - } - - /* Make sure all SELECTs in the statement have the same number of elements - ** in their result sets. - */ - assert( p->pEList && pPrior->pEList ); - if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ - if( p->selFlags & SF_Values ){ - sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); - }else{ - sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" - " do not have the same number of result columns", selectOpName(p->op)); - } - rc = 1; - goto multi_select_end; - } - - /* Compound SELECTs that have an ORDER BY clause are handled separately. - */ - if( p->pOrderBy ){ - return multiSelectOrderBy(pParse, p, pDest); - } - - /* Generate code for the left and right SELECT statements. - */ - switch( p->op ){ - case TK_ALL: { - int addr = 0; - int nLimit; - assert( !pPrior->pLimit ); - pPrior->iLimit = p->iLimit; - pPrior->iOffset = p->iOffset; - pPrior->pLimit = p->pLimit; - pPrior->pOffset = p->pOffset; - explainSetInteger(iSub1, pParse->iNextSelectId); - rc = sqlite3Select(pParse, pPrior, &dest); - p->pLimit = 0; - p->pOffset = 0; - if( rc ){ - goto multi_select_end; - } - p->pPrior = 0; - p->iLimit = pPrior->iLimit; - p->iOffset = pPrior->iOffset; - if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); - VdbeComment((v, "Jump ahead if LIMIT reached")); - } - explainSetInteger(iSub2, pParse->iNextSelectId); - rc = sqlite3Select(pParse, p, &dest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->nSelectRow += pPrior->nSelectRow; - if( pPrior->pLimit - && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit) - && p->nSelectRow > (double)nLimit - ){ - p->nSelectRow = (double)nLimit; - } - if( addr ){ - sqlite3VdbeJumpHere(v, addr); - } - break; - } - case TK_EXCEPT: - case TK_UNION: { - int unionTab; /* Cursor number of the temporary table holding result */ - u8 op = 0; /* One of the SRT_ operations to apply to self */ - int priorOp; /* The SRT_ operation to apply to prior selects */ - Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ - int addr; - SelectDest uniondest; - - testcase( p->op==TK_EXCEPT ); - testcase( p->op==TK_UNION ); - priorOp = SRT_Union; - if( dest.eDest==priorOp && ALWAYS(!p->pLimit &&!p->pOffset) ){ - /* We can reuse a temporary table generated by a SELECT to our - ** right. - */ - assert( p->pRightmost!=p ); /* Can only happen for leftward elements - ** of a 3-way or more compound */ - assert( p->pLimit==0 ); /* Not allowed on leftward elements */ - assert( p->pOffset==0 ); /* Not allowed on leftward elements */ - unionTab = dest.iSDParm; - }else{ - /* We will need to create our own temporary table to hold the - ** intermediate results. - */ - unionTab = pParse->nTab++; - assert( p->pOrderBy==0 ); - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); - assert( p->addrOpenEphm[0] == -1 ); - p->addrOpenEphm[0] = addr; - p->pRightmost->selFlags |= SF_UsesEphemeral; - assert( p->pEList ); - } - - /* Code the SELECT statements to our left - */ - assert( !pPrior->pOrderBy ); - sqlite3SelectDestInit(&uniondest, priorOp, unionTab); - explainSetInteger(iSub1, pParse->iNextSelectId); - rc = sqlite3Select(pParse, pPrior, &uniondest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT statement - */ - if( p->op==TK_EXCEPT ){ - op = SRT_Except; - }else{ - assert( p->op==TK_UNION ); - op = SRT_Union; - } - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - pOffset = p->pOffset; - p->pOffset = 0; - uniondest.eDest = op; - explainSetInteger(iSub2, pParse->iNextSelectId); - rc = sqlite3Select(pParse, p, &uniondest); - testcase( rc!=SQLITE_OK ); - /* Query flattening in sqlite3Select() might refill p->pOrderBy. - ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ - sqlite3ExprListDelete(db, p->pOrderBy); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->pOrderBy = 0; - if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow; - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - p->pOffset = pOffset; - p->iLimit = 0; - p->iOffset = 0; - - /* Convert the data in the temporary table into whatever form - ** it is that we currently need. - */ - assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); - if( dest.eDest!=priorOp ){ - int iCont, iBreak, iStart; - assert( p->pEList ); - if( dest.eDest==SRT_Output ){ - Select *pFirst = p; - while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, 0, pFirst->pEList); - } - iBreak = sqlite3VdbeMakeLabel(v); - iCont = sqlite3VdbeMakeLabel(v); - computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); - iStart = sqlite3VdbeCurrentAddr(v); - selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, - 0, 0, &dest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); - sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); - } - break; - } - default: assert( p->op==TK_INTERSECT ); { - int tab1, tab2; - int iCont, iBreak, iStart; - Expr *pLimit, *pOffset; - int addr; - SelectDest intersectdest; - int r1; - - /* INTERSECT is different from the others since it requires - ** two temporary tables. Hence it has its own case. Begin - ** by allocating the tables we will need. - */ - tab1 = pParse->nTab++; - tab2 = pParse->nTab++; - assert( p->pOrderBy==0 ); - - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); - assert( p->addrOpenEphm[0] == -1 ); - p->addrOpenEphm[0] = addr; - p->pRightmost->selFlags |= SF_UsesEphemeral; - assert( p->pEList ); - - /* Code the SELECTs to our left into temporary table "tab1". - */ - sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); - explainSetInteger(iSub1, pParse->iNextSelectId); - rc = sqlite3Select(pParse, pPrior, &intersectdest); - if( rc ){ - goto multi_select_end; - } - - /* Code the current SELECT into temporary table "tab2" - */ - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); - assert( p->addrOpenEphm[1] == -1 ); - p->addrOpenEphm[1] = addr; - p->pPrior = 0; - pLimit = p->pLimit; - p->pLimit = 0; - pOffset = p->pOffset; - p->pOffset = 0; - intersectdest.iSDParm = tab2; - explainSetInteger(iSub2, pParse->iNextSelectId); - rc = sqlite3Select(pParse, p, &intersectdest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = pLimit; - p->pOffset = pOffset; - - /* Generate code to take the intersection of the two temporary - ** tables. - */ - assert( p->pEList ); - if( dest.eDest==SRT_Output ){ - Select *pFirst = p; - while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, 0, pFirst->pEList); - } - iBreak = sqlite3VdbeMakeLabel(v); - iCont = sqlite3VdbeMakeLabel(v); - computeLimitRegisters(pParse, p, iBreak); - sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); - r1 = sqlite3GetTempReg(pParse); - iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); - sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); - sqlite3ReleaseTempReg(pParse, r1); - selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, - 0, 0, &dest, iCont, iBreak); - sqlite3VdbeResolveLabel(v, iCont); - sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); - sqlite3VdbeResolveLabel(v, iBreak); - sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); - sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); - break; - } - } - - explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL); - - /* Compute collating sequences used by - ** temporary tables needed to implement the compound select. - ** Attach the KeyInfo structure to all temporary tables. - ** - ** This section is run by the right-most SELECT statement only. - ** SELECT statements to the left always skip this part. The right-most - ** SELECT might also skip this part if it has no ORDER BY clause and - ** no temp tables are required. - */ - if( p->selFlags & SF_UsesEphemeral ){ - int i; /* Loop counter */ - KeyInfo *pKeyInfo; /* Collating sequence for the result set */ - Select *pLoop; /* For looping through SELECT statements */ - CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ - int nCol; /* Number of columns in result set */ - - assert( p->pRightmost==p ); - nCol = p->pEList->nExpr; - pKeyInfo = sqlite3DbMallocZero(db, - sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1)); - if( !pKeyInfo ){ - rc = SQLITE_NOMEM; - goto multi_select_end; - } - - pKeyInfo->enc = ENC(db); - pKeyInfo->nField = (u16)nCol; - - for(i=0, apColl=pKeyInfo->aColl; ipDfltColl; - } - } - pKeyInfo->aSortOrder = (u8*)apColl; - - for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ - for(i=0; i<2; i++){ - int addr = pLoop->addrOpenEphm[i]; - if( addr<0 ){ - /* If [0] is unused then [1] is also unused. So we can - ** always safely abort as soon as the first unused slot is found */ - assert( pLoop->addrOpenEphm[1]<0 ); - break; - } - sqlite3VdbeChangeP2(v, addr, nCol); - sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO); - pLoop->addrOpenEphm[i] = -1; - } - } - sqlite3DbFree(db, pKeyInfo); - } - -multi_select_end: - pDest->iSdst = dest.iSdst; - pDest->nSdst = dest.nSdst; - sqlite3SelectDelete(db, pDelete); - return rc; -} -#endif /* SQLITE_OMIT_COMPOUND_SELECT */ - -/* -** Code an output subroutine for a coroutine implementation of a -** SELECT statment. -** -** The data to be output is contained in pIn->iSdst. There are -** pIn->nSdst columns to be output. pDest is where the output should -** be sent. -** -** regReturn is the number of the register holding the subroutine -** return address. -** -** If regPrev>0 then it is the first register in a vector that -** records the previous output. mem[regPrev] is a flag that is false -** if there has been no previous output. If regPrev>0 then code is -** generated to suppress duplicates. pKeyInfo is used for comparing -** keys. -** -** If the LIMIT found in p->iLimit is reached, jump immediately to -** iBreak. -*/ -static int generateOutputSubroutine( - Parse *pParse, /* Parsing context */ - Select *p, /* The SELECT statement */ - SelectDest *pIn, /* Coroutine supplying data */ - SelectDest *pDest, /* Where to send the data */ - int regReturn, /* The return address register */ - int regPrev, /* Previous result register. No uniqueness if 0 */ - KeyInfo *pKeyInfo, /* For comparing with previous entry */ - int p4type, /* The p4 type for pKeyInfo */ - int iBreak /* Jump here if we hit the LIMIT */ -){ - Vdbe *v = pParse->pVdbe; - int iContinue; - int addr; - - addr = sqlite3VdbeCurrentAddr(v); - iContinue = sqlite3VdbeMakeLabel(v); - - /* Suppress duplicates for UNION, EXCEPT, and INTERSECT - */ - if( regPrev ){ - int j1, j2; - j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); - j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, - (char*)pKeyInfo, p4type); - sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); - sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); - sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); - } - if( pParse->db->mallocFailed ) return 0; - - /* Suppress the first OFFSET entries if there is an OFFSET clause - */ - codeOffset(v, p, iContinue); - - switch( pDest->eDest ){ - /* Store the result as data using a unique key. - */ - case SRT_Table: - case SRT_EphemTab: { - int r1 = sqlite3GetTempReg(pParse); - int r2 = sqlite3GetTempReg(pParse); - testcase( pDest->eDest==SRT_Table ); - testcase( pDest->eDest==SRT_EphemTab ); - sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); - sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); - sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); - sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3ReleaseTempReg(pParse, r2); - sqlite3ReleaseTempReg(pParse, r1); - break; - } - -#ifndef SQLITE_OMIT_SUBQUERY - /* If we are creating a set for an "expr IN (SELECT ...)" construct, - ** then there should be a single item on the stack. Write this - ** item into the set table with bogus data. - */ - case SRT_Set: { - int r1; - assert( pIn->nSdst==1 ); - pDest->affSdst = - sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1); - sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1); - sqlite3ReleaseTempReg(pParse, r1); - break; - } - -#if 0 /* Never occurs on an ORDER BY query */ - /* If any row exist in the result set, record that fact and abort. - */ - case SRT_Exists: { - sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm); - /* The LIMIT clause will terminate the loop for us */ - break; - } -#endif - - /* If this is a scalar select that is part of an expression, then - ** store the results in the appropriate memory cell and break out - ** of the scan loop. - */ - case SRT_Mem: { - assert( pIn->nSdst==1 ); - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); - /* The LIMIT clause will jump out of the loop for us */ - break; - } -#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ - - /* The results are stored in a sequence of registers - ** starting at pDest->iSdst. Then the co-routine yields. - */ - case SRT_Coroutine: { - if( pDest->iSdst==0 ){ - pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst); - pDest->nSdst = pIn->nSdst; - } - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst); - sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); - break; - } - - /* If none of the above, then the result destination must be - ** SRT_Output. This routine is never called with any other - ** destination other than the ones handled above or SRT_Output. - ** - ** For SRT_Output, results are stored in a sequence of registers. - ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to - ** return the next row of result. - */ - default: { - assert( pDest->eDest==SRT_Output ); - sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); - sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); - break; - } - } - - /* Jump to the end of the loop if the LIMIT is reached. - */ - if( p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); - } - - /* Generate the subroutine return - */ - sqlite3VdbeResolveLabel(v, iContinue); - sqlite3VdbeAddOp1(v, OP_Return, regReturn); - - return addr; -} - -/* -** Alternative compound select code generator for cases when there -** is an ORDER BY clause. -** -** We assume a query of the following form: -** -** ORDER BY -** -** is one of UNION ALL, UNION, EXCEPT, or INTERSECT. The idea -** is to code both and with the ORDER BY clause as -** co-routines. Then run the co-routines in parallel and merge the results -** into the output. In addition to the two coroutines (called selectA and -** selectB) there are 7 subroutines: -** -** outA: Move the output of the selectA coroutine into the output -** of the compound query. -** -** outB: Move the output of the selectB coroutine into the output -** of the compound query. (Only generated for UNION and -** UNION ALL. EXCEPT and INSERTSECT never output a row that -** appears only in B.) -** -** AltB: Called when there is data from both coroutines and AB. -** -** EofA: Called when data is exhausted from selectA. -** -** EofB: Called when data is exhausted from selectB. -** -** The implementation of the latter five subroutines depend on which -** is used: -** -** -** UNION ALL UNION EXCEPT INTERSECT -** ------------- ----------------- -------------- ----------------- -** AltB: outA, nextA outA, nextA outA, nextA nextA -** -** AeqB: outA, nextA nextA nextA outA, nextA -** -** AgtB: outB, nextB outB, nextB nextB nextB -** -** EofA: outB, nextB outB, nextB halt halt -** -** EofB: outA, nextA outA, nextA outA, nextA halt -** -** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA -** causes an immediate jump to EofA and an EOF on B following nextB causes -** an immediate jump to EofB. Within EofA and EofB, and EOF on entry or -** following nextX causes a jump to the end of the select processing. -** -** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled -** within the output subroutine. The regPrev register set holds the previously -** output value. A comparison is made against this value and the output -** is skipped if the next results would be the same as the previous. -** -** The implementation plan is to implement the two coroutines and seven -** subroutines first, then put the control logic at the bottom. Like this: -** -** goto Init -** coA: coroutine for left query (A) -** coB: coroutine for right query (B) -** outA: output one row of A -** outB: output one row of B (UNION and UNION ALL only) -** EofA: ... -** EofB: ... -** AltB: ... -** AeqB: ... -** AgtB: ... -** Init: initialize coroutine registers -** yield coA -** if eof(A) goto EofA -** yield coB -** if eof(B) goto EofB -** Cmpr: Compare A, B -** Jump AltB, AeqB, AgtB -** End: ... -** -** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not -** actually called using Gosub and they do not Return. EofA and EofB loop -** until all data is exhausted then jump to the "end" labe. AltB, AeqB, -** and AgtB jump to either L2 or to one of EofA or EofB. -*/ -#ifndef SQLITE_OMIT_COMPOUND_SELECT -static int multiSelectOrderBy( - Parse *pParse, /* Parsing context */ - Select *p, /* The right-most of SELECTs to be coded */ - SelectDest *pDest /* What to do with query results */ -){ - int i, j; /* Loop counters */ - Select *pPrior; /* Another SELECT immediately to our left */ - Vdbe *v; /* Generate code to this VDBE */ - SelectDest destA; /* Destination for coroutine A */ - SelectDest destB; /* Destination for coroutine B */ - int regAddrA; /* Address register for select-A coroutine */ - int regEofA; /* Flag to indicate when select-A is complete */ - int regAddrB; /* Address register for select-B coroutine */ - int regEofB; /* Flag to indicate when select-B is complete */ - int addrSelectA; /* Address of the select-A coroutine */ - int addrSelectB; /* Address of the select-B coroutine */ - int regOutA; /* Address register for the output-A subroutine */ - int regOutB; /* Address register for the output-B subroutine */ - int addrOutA; /* Address of the output-A subroutine */ - int addrOutB = 0; /* Address of the output-B subroutine */ - int addrEofA; /* Address of the select-A-exhausted subroutine */ - int addrEofB; /* Address of the select-B-exhausted subroutine */ - int addrAltB; /* Address of the AB subroutine */ - int regLimitA; /* Limit register for select-A */ - int regLimitB; /* Limit register for select-A */ - int regPrev; /* A range of registers to hold previous output */ - int savedLimit; /* Saved value of p->iLimit */ - int savedOffset; /* Saved value of p->iOffset */ - int labelCmpr; /* Label for the start of the merge algorithm */ - int labelEnd; /* Label for the end of the overall SELECT stmt */ - int j1; /* Jump instructions that get retargetted */ - int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ - KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */ - KeyInfo *pKeyMerge; /* Comparison information for merging rows */ - sqlite3 *db; /* Database connection */ - ExprList *pOrderBy; /* The ORDER BY clause */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - int *aPermute; /* Mapping from ORDER BY terms to result set columns */ -#ifndef SQLITE_OMIT_EXPLAIN - int iSub1; /* EQP id of left-hand query */ - int iSub2; /* EQP id of right-hand query */ -#endif - - assert( p->pOrderBy!=0 ); - assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ - db = pParse->db; - v = pParse->pVdbe; - assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */ - labelEnd = sqlite3VdbeMakeLabel(v); - labelCmpr = sqlite3VdbeMakeLabel(v); - - - /* Patch up the ORDER BY clause - */ - op = p->op; - pPrior = p->pPrior; - assert( pPrior->pOrderBy==0 ); - pOrderBy = p->pOrderBy; - assert( pOrderBy ); - nOrderBy = pOrderBy->nExpr; - - /* For operators other than UNION ALL we have to make sure that - ** the ORDER BY clause covers every term of the result set. Add - ** terms to the ORDER BY clause as necessary. - */ - if( op!=TK_ALL ){ - for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){ - struct ExprList_item *pItem; - for(j=0, pItem=pOrderBy->a; jiOrderByCol>0 ); - if( pItem->iOrderByCol==i ) break; - } - if( j==nOrderBy ){ - Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); - if( pNew==0 ) return SQLITE_NOMEM; - pNew->flags |= EP_IntValue; - pNew->u.iValue = i; - pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); - if( pOrderBy ) pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i; - } - } - } - - /* Compute the comparison permutation and keyinfo that is used with - ** the permutation used to determine if the next - ** row of results comes from selectA or selectB. Also add explicit - ** collations to the ORDER BY clause terms so that when the subqueries - ** to the right and the left are evaluated, they use the correct - ** collation. - */ - aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy); - if( aPermute ){ - struct ExprList_item *pItem; - for(i=0, pItem=pOrderBy->a; iiOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr ); - aPermute[i] = pItem->iOrderByCol - 1; - } - pKeyMerge = - sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1)); - if( pKeyMerge ){ - pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy]; - pKeyMerge->nField = (u16)nOrderBy; - pKeyMerge->enc = ENC(db); - for(i=0; ia[i].pExpr; - if( pTerm->flags & EP_Collate ){ - pColl = sqlite3ExprCollSeq(pParse, pTerm); - }else{ - pColl = multiSelectCollSeq(pParse, p, aPermute[i]); - if( pColl==0 ) pColl = db->pDfltColl; - pOrderBy->a[i].pExpr = - sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); - } - pKeyMerge->aColl[i] = pColl; - pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; - } - } - }else{ - pKeyMerge = 0; - } - - /* Reattach the ORDER BY clause to the query. - */ - p->pOrderBy = pOrderBy; - pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); - - /* Allocate a range of temporary registers and the KeyInfo needed - ** for the logic that removes duplicate result rows when the - ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). - */ - if( op==TK_ALL ){ - regPrev = 0; - }else{ - int nExpr = p->pEList->nExpr; - assert( nOrderBy>=nExpr || db->mallocFailed ); - regPrev = pParse->nMem+1; - pParse->nMem += nExpr+1; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); - pKeyDup = sqlite3DbMallocZero(db, - sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) ); - if( pKeyDup ){ - pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr]; - pKeyDup->nField = (u16)nExpr; - pKeyDup->enc = ENC(db); - for(i=0; iaColl[i] = multiSelectCollSeq(pParse, p, i); - pKeyDup->aSortOrder[i] = 0; - } - } - } - - /* Separate the left and the right query from one another - */ - p->pPrior = 0; - sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); - if( pPrior->pPrior==0 ){ - sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); - } - - /* Compute the limit registers */ - computeLimitRegisters(pParse, p, labelEnd); - if( p->iLimit && op==TK_ALL ){ - regLimitA = ++pParse->nMem; - regLimitB = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit, - regLimitA); - sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB); - }else{ - regLimitA = regLimitB = 0; - } - sqlite3ExprDelete(db, p->pLimit); - p->pLimit = 0; - sqlite3ExprDelete(db, p->pOffset); - p->pOffset = 0; - - regAddrA = ++pParse->nMem; - regEofA = ++pParse->nMem; - regAddrB = ++pParse->nMem; - regEofB = ++pParse->nMem; - regOutA = ++pParse->nMem; - regOutB = ++pParse->nMem; - sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); - sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); - - /* Jump past the various subroutines and coroutines to the main - ** merge loop - */ - j1 = sqlite3VdbeAddOp0(v, OP_Goto); - addrSelectA = sqlite3VdbeCurrentAddr(v); - - - /* Generate a coroutine to evaluate the SELECT statement to the - ** left of the compound operator - the "A" select. - */ - VdbeNoopComment((v, "Begin coroutine for left SELECT")); - pPrior->iLimit = regLimitA; - explainSetInteger(iSub1, pParse->iNextSelectId); - sqlite3Select(pParse, pPrior, &destA); - sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); - VdbeNoopComment((v, "End coroutine for left SELECT")); - - /* Generate a coroutine to evaluate the SELECT statement on - ** the right - the "B" select - */ - addrSelectB = sqlite3VdbeCurrentAddr(v); - VdbeNoopComment((v, "Begin coroutine for right SELECT")); - savedLimit = p->iLimit; - savedOffset = p->iOffset; - p->iLimit = regLimitB; - p->iOffset = 0; - explainSetInteger(iSub2, pParse->iNextSelectId); - sqlite3Select(pParse, p, &destB); - p->iLimit = savedLimit; - p->iOffset = savedOffset; - sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); - VdbeNoopComment((v, "End coroutine for right SELECT")); - - /* Generate a subroutine that outputs the current row of the A - ** select as the next output row of the compound select. - */ - VdbeNoopComment((v, "Output routine for A")); - addrOutA = generateOutputSubroutine(pParse, - p, &destA, pDest, regOutA, - regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd); - - /* Generate a subroutine that outputs the current row of the B - ** select as the next output row of the compound select. - */ - if( op==TK_ALL || op==TK_UNION ){ - VdbeNoopComment((v, "Output routine for B")); - addrOutB = generateOutputSubroutine(pParse, - p, &destB, pDest, regOutB, - regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd); - } - - /* Generate a subroutine to run when the results from select A - ** are exhausted and only data in select B remains. - */ - VdbeNoopComment((v, "eof-A subroutine")); - if( op==TK_EXCEPT || op==TK_INTERSECT ){ - addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd); - }else{ - addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd); - sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA); - p->nSelectRow += pPrior->nSelectRow; - } - - /* Generate a subroutine to run when the results from select B - ** are exhausted and only data in select A remains. - */ - if( op==TK_INTERSECT ){ - addrEofB = addrEofA; - if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; - }else{ - VdbeNoopComment((v, "eof-B subroutine")); - addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd); - sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB); - } - - /* Generate code to handle the case of AB - */ - VdbeNoopComment((v, "A-gt-B subroutine")); - addrAgtB = sqlite3VdbeCurrentAddr(v); - if( op==TK_ALL || op==TK_UNION ){ - sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - } - sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); - sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); - sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); - - /* This code runs once to initialize everything. - */ - sqlite3VdbeJumpHere(v, j1); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB); - sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA); - sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB); - sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); - sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); - - /* Implement the main merge loop - */ - sqlite3VdbeResolveLabel(v, labelCmpr); - sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); - sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, - (char*)pKeyMerge, P4_KEYINFO_HANDOFF); - sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); - sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); - - /* Jump to the this point in order to terminate the query. - */ - sqlite3VdbeResolveLabel(v, labelEnd); - - /* Set the number of output columns - */ - if( pDest->eDest==SRT_Output ){ - Select *pFirst = pPrior; - while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, 0, pFirst->pEList); - } - - /* Reassembly the compound query so that it will be freed correctly - ** by the calling function */ - if( p->pPrior ){ - sqlite3SelectDelete(db, p->pPrior); - } - p->pPrior = pPrior; - - /*** TBD: Insert subroutine calls to close cursors on incomplete - **** subqueries ****/ - explainComposite(pParse, p->op, iSub1, iSub2, 0); - return SQLITE_OK; -} -#endif - -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) -/* Forward Declarations */ -static void substExprList(sqlite3*, ExprList*, int, ExprList*); -static void substSelect(sqlite3*, Select *, int, ExprList *); - -/* -** Scan through the expression pExpr. Replace every reference to -** a column in table number iTable with a copy of the iColumn-th -** entry in pEList. (But leave references to the ROWID column -** unchanged.) -** -** This routine is part of the flattening procedure. A subquery -** whose result set is defined by pEList appears as entry in the -** FROM clause of a SELECT such that the VDBE cursor assigned to that -** FORM clause entry is iTable. This routine make the necessary -** changes to pExpr so that it refers directly to the source table -** of the subquery rather the result set of the subquery. -*/ -static Expr *substExpr( - sqlite3 *db, /* Report malloc errors to this connection */ - Expr *pExpr, /* Expr in which substitution occurs */ - int iTable, /* Table to be substituted */ - ExprList *pEList /* Substitute expressions */ -){ - if( pExpr==0 ) return 0; - if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ - if( pExpr->iColumn<0 ){ - pExpr->op = TK_NULL; - }else{ - Expr *pNew; - assert( pEList!=0 && pExpr->iColumnnExpr ); - assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); - sqlite3ExprDelete(db, pExpr); - pExpr = pNew; - } - }else{ - pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); - pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - substSelect(db, pExpr->x.pSelect, iTable, pEList); - }else{ - substExprList(db, pExpr->x.pList, iTable, pEList); - } - } - return pExpr; -} -static void substExprList( - sqlite3 *db, /* Report malloc errors here */ - ExprList *pList, /* List to scan and in which to make substitutes */ - int iTable, /* Table to be substituted */ - ExprList *pEList /* Substitute values */ -){ - int i; - if( pList==0 ) return; - for(i=0; inExpr; i++){ - pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList); - } -} -static void substSelect( - sqlite3 *db, /* Report malloc errors here */ - Select *p, /* SELECT statement in which to make substitutions */ - int iTable, /* Table to be replaced */ - ExprList *pEList /* Substitute values */ -){ - SrcList *pSrc; - struct SrcList_item *pItem; - int i; - if( !p ) return; - substExprList(db, p->pEList, iTable, pEList); - substExprList(db, p->pGroupBy, iTable, pEList); - substExprList(db, p->pOrderBy, iTable, pEList); - p->pHaving = substExpr(db, p->pHaving, iTable, pEList); - p->pWhere = substExpr(db, p->pWhere, iTable, pEList); - substSelect(db, p->pPrior, iTable, pEList); - pSrc = p->pSrc; - assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */ - if( ALWAYS(pSrc) ){ - for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - substSelect(db, pItem->pSelect, iTable, pEList); - } - } -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) -/* -** This routine attempts to flatten subqueries as a performance optimization. -** This routine returns 1 if it makes changes and 0 if no flattening occurs. -** -** To understand the concept of flattening, consider the following -** query: -** -** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5 -** -** The default way of implementing this query is to execute the -** subquery first and store the results in a temporary table, then -** run the outer query on that temporary table. This requires two -** passes over the data. Furthermore, because the temporary table -** has no indices, the WHERE clause on the outer query cannot be -** optimized. -** -** This routine attempts to rewrite queries such as the above into -** a single flat select, like this: -** -** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 -** -** The code generated for this simpification gives the same result -** but only has to scan the data once. And because indices might -** exist on the table t1, a complete scan of the data might be -** avoided. -** -** Flattening is only attempted if all of the following are true: -** -** (1) The subquery and the outer query do not both use aggregates. -** -** (2) The subquery is not an aggregate or the outer query is not a join. -** -** (3) The subquery is not the right operand of a left outer join -** (Originally ticket #306. Strengthened by ticket #3300) -** -** (4) The subquery is not DISTINCT. -** -** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT -** sub-queries that were excluded from this optimization. Restriction -** (4) has since been expanded to exclude all DISTINCT subqueries. -** -** (6) The subquery does not use aggregates or the outer query is not -** DISTINCT. -** -** (7) The subquery has a FROM clause. TODO: For subqueries without -** A FROM clause, consider adding a FROM close with the special -** table sqlite_once that consists of a single row containing a -** single NULL. -** -** (8) The subquery does not use LIMIT or the outer query is not a join. -** -** (9) The subquery does not use LIMIT or the outer query does not use -** aggregates. -** -** (10) The subquery does not use aggregates or the outer query does not -** use LIMIT. -** -** (11) The subquery and the outer query do not both have ORDER BY clauses. -** -** (**) Not implemented. Subsumed into restriction (3). Was previously -** a separate restriction deriving from ticket #350. -** -** (13) The subquery and outer query do not both use LIMIT. -** -** (14) The subquery does not use OFFSET. -** -** (15) The outer query is not part of a compound select or the -** subquery does not have a LIMIT clause. -** (See ticket #2339 and ticket [02a8e81d44]). -** -** (16) The outer query is not an aggregate or the subquery does -** not contain ORDER BY. (Ticket #2942) This used to not matter -** until we introduced the group_concat() function. -** -** (17) The sub-query is not a compound select, or it is a UNION ALL -** compound clause made up entirely of non-aggregate queries, and -** the parent query: -** -** * is not itself part of a compound select, -** * is not an aggregate or DISTINCT query, and -** * is not a join -** -** The parent and sub-query may contain WHERE clauses. Subject to -** rules (11), (13) and (14), they may also contain ORDER BY, -** LIMIT and OFFSET clauses. The subquery cannot use any compound -** operator other than UNION ALL because all the other compound -** operators have an implied DISTINCT which is disallowed by -** restriction (4). -** -** Also, each component of the sub-query must return the same number -** of result columns. This is actually a requirement for any compound -** SELECT statement, but all the code here does is make sure that no -** such (illegal) sub-query is flattened. The caller will detect the -** syntax error and return a detailed message. -** -** (18) If the sub-query is a compound select, then all terms of the -** ORDER by clause of the parent must be simple references to -** columns of the sub-query. -** -** (19) The subquery does not use LIMIT or the outer query does not -** have a WHERE clause. -** -** (20) If the sub-query is a compound select, then it must not use -** an ORDER BY clause. Ticket #3773. We could relax this constraint -** somewhat by saying that the terms of the ORDER BY clause must -** appear as unmodified result columns in the outer query. But we -** have other optimizations in mind to deal with that case. -** -** (21) The subquery does not use LIMIT or the outer query is not -** DISTINCT. (See ticket [752e1646fc]). -** -** In this routine, the "p" parameter is a pointer to the outer query. -** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query -** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. -** -** If flattening is not attempted, this routine is a no-op and returns 0. -** If flattening is attempted this routine returns 1. -** -** All of the expression analysis must occur on both the outer query and -** the subquery before this routine runs. -*/ -static int flattenSubquery( - Parse *pParse, /* Parsing context */ - Select *p, /* The parent or outer SELECT statement */ - int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ - int isAgg, /* True if outer SELECT uses aggregate functions */ - int subqueryIsAgg /* True if the subquery uses aggregate functions */ -){ - const char *zSavedAuthContext = pParse->zAuthContext; - Select *pParent; - Select *pSub; /* The inner query or "subquery" */ - Select *pSub1; /* Pointer to the rightmost select in sub-query */ - SrcList *pSrc; /* The FROM clause of the outer query */ - SrcList *pSubSrc; /* The FROM clause of the subquery */ - ExprList *pList; /* The result set of the outer query */ - int iParent; /* VDBE cursor number of the pSub result set temp table */ - int i; /* Loop counter */ - Expr *pWhere; /* The WHERE clause */ - struct SrcList_item *pSubitem; /* The subquery */ - sqlite3 *db = pParse->db; - - /* Check to see if flattening is permitted. Return 0 if not. - */ - assert( p!=0 ); - assert( p->pPrior==0 ); /* Unable to flatten compound queries */ - if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0; - pSrc = p->pSrc; - assert( pSrc && iFrom>=0 && iFromnSrc ); - pSubitem = &pSrc->a[iFrom]; - iParent = pSubitem->iCursor; - pSub = pSubitem->pSelect; - assert( pSub!=0 ); - if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ - if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ - pSubSrc = pSub->pSrc; - assert( pSubSrc ); - /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, - ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET - ** because they could be computed at compile-time. But when LIMIT and OFFSET - ** became arbitrary expressions, we were forced to add restrictions (13) - ** and (14). */ - if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ - if( pSub->pOffset ) return 0; /* Restriction (14) */ - if( p->pRightmost && pSub->pLimit ){ - return 0; /* Restriction (15) */ - } - if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ - if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */ - if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){ - return 0; /* Restrictions (8)(9) */ - } - if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){ - return 0; /* Restriction (6) */ - } - if( p->pOrderBy && pSub->pOrderBy ){ - return 0; /* Restriction (11) */ - } - if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */ - if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */ - if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ - return 0; /* Restriction (21) */ - } - - /* OBSOLETE COMMENT 1: - ** Restriction 3: If the subquery is a join, make sure the subquery is - ** not used as the right operand of an outer join. Examples of why this - ** is not allowed: - ** - ** t1 LEFT OUTER JOIN (t2 JOIN t3) - ** - ** If we flatten the above, we would get - ** - ** (t1 LEFT OUTER JOIN t2) JOIN t3 - ** - ** which is not at all the same thing. - ** - ** OBSOLETE COMMENT 2: - ** Restriction 12: If the subquery is the right operand of a left outer - ** join, make sure the subquery has no WHERE clause. - ** An examples of why this is not allowed: - ** - ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0) - ** - ** If we flatten the above, we would get - ** - ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0 - ** - ** But the t2.x>0 test will always fail on a NULL row of t2, which - ** effectively converts the OUTER JOIN into an INNER JOIN. - ** - ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE: - ** Ticket #3300 shows that flattening the right term of a LEFT JOIN - ** is fraught with danger. Best to avoid the whole thing. If the - ** subquery is the right term of a LEFT JOIN, then do not flatten. - */ - if( (pSubitem->jointype & JT_OUTER)!=0 ){ - return 0; - } - - /* Restriction 17: If the sub-query is a compound SELECT, then it must - ** use only the UNION ALL operator. And none of the simple select queries - ** that make up the compound SELECT are allowed to be aggregate or distinct - ** queries. - */ - if( pSub->pPrior ){ - if( pSub->pOrderBy ){ - return 0; /* Restriction 20 */ - } - if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){ - return 0; - } - for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){ - testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); - testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); - assert( pSub->pSrc!=0 ); - if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 - || (pSub1->pPrior && pSub1->op!=TK_ALL) - || pSub1->pSrc->nSrc<1 - || pSub->pEList->nExpr!=pSub1->pEList->nExpr - ){ - return 0; - } - testcase( pSub1->pSrc->nSrc>1 ); - } - - /* Restriction 18. */ - if( p->pOrderBy ){ - int ii; - for(ii=0; iipOrderBy->nExpr; ii++){ - if( p->pOrderBy->a[ii].iOrderByCol==0 ) return 0; - } - } - } - - /***** If we reach this point, flattening is permitted. *****/ - - /* Authorize the subquery */ - pParse->zAuthContext = pSubitem->zName; - TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); - testcase( i==SQLITE_DENY ); - pParse->zAuthContext = zSavedAuthContext; - - /* If the sub-query is a compound SELECT statement, then (by restrictions - ** 17 and 18 above) it must be a UNION ALL and the parent query must - ** be of the form: - ** - ** SELECT FROM () - ** - ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block - ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or - ** OFFSET clauses and joins them to the left-hand-side of the original - ** using UNION ALL operators. In this case N is the number of simple - ** select statements in the compound sub-query. - ** - ** Example: - ** - ** SELECT a+1 FROM ( - ** SELECT x FROM tab - ** UNION ALL - ** SELECT y FROM tab - ** UNION ALL - ** SELECT abs(z*2) FROM tab2 - ** ) WHERE a!=5 ORDER BY 1 - ** - ** Transformed into: - ** - ** SELECT x+1 FROM tab WHERE x+1!=5 - ** UNION ALL - ** SELECT y+1 FROM tab WHERE y+1!=5 - ** UNION ALL - ** SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5 - ** ORDER BY 1 - ** - ** We call this the "compound-subquery flattening". - */ - for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){ - Select *pNew; - ExprList *pOrderBy = p->pOrderBy; - Expr *pLimit = p->pLimit; - Expr *pOffset = p->pOffset; - Select *pPrior = p->pPrior; - p->pOrderBy = 0; - p->pSrc = 0; - p->pPrior = 0; - p->pLimit = 0; - p->pOffset = 0; - pNew = sqlite3SelectDup(db, p, 0); - p->pOffset = pOffset; - p->pLimit = pLimit; - p->pOrderBy = pOrderBy; - p->pSrc = pSrc; - p->op = TK_ALL; - p->pRightmost = 0; - if( pNew==0 ){ - pNew = pPrior; - }else{ - pNew->pPrior = pPrior; - pNew->pRightmost = 0; - } - p->pPrior = pNew; - if( db->mallocFailed ) return 1; - } - - /* Begin flattening the iFrom-th entry of the FROM clause - ** in the outer query. - */ - pSub = pSub1 = pSubitem->pSelect; - - /* Delete the transient table structure associated with the - ** subquery - */ - sqlite3DbFree(db, pSubitem->zDatabase); - sqlite3DbFree(db, pSubitem->zName); - sqlite3DbFree(db, pSubitem->zAlias); - pSubitem->zDatabase = 0; - pSubitem->zName = 0; - pSubitem->zAlias = 0; - pSubitem->pSelect = 0; - - /* Defer deleting the Table object associated with the - ** subquery until code generation is - ** complete, since there may still exist Expr.pTab entries that - ** refer to the subquery even after flattening. Ticket #3346. - ** - ** pSubitem->pTab is always non-NULL by test restrictions and tests above. - */ - if( ALWAYS(pSubitem->pTab!=0) ){ - Table *pTabToDel = pSubitem->pTab; - if( pTabToDel->nRef==1 ){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - pTabToDel->pNextZombie = pToplevel->pZombieTab; - pToplevel->pZombieTab = pTabToDel; - }else{ - pTabToDel->nRef--; - } - pSubitem->pTab = 0; - } - - /* The following loop runs once for each term in a compound-subquery - ** flattening (as described above). If we are doing a different kind - ** of flattening - a flattening other than a compound-subquery flattening - - ** then this loop only runs once. - ** - ** This loop moves all of the FROM elements of the subquery into the - ** the FROM clause of the outer query. Before doing this, remember - ** the cursor number for the original outer query FROM element in - ** iParent. The iParent cursor will never be used. Subsequent code - ** will scan expressions looking for iParent references and replace - ** those references with expressions that resolve to the subquery FROM - ** elements we are now copying in. - */ - for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){ - int nSubSrc; - u8 jointype = 0; - pSubSrc = pSub->pSrc; /* FROM clause of subquery */ - nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ - pSrc = pParent->pSrc; /* FROM clause of the outer query */ - - if( pSrc ){ - assert( pParent==p ); /* First time through the loop */ - jointype = pSubitem->jointype; - }else{ - assert( pParent!=p ); /* 2nd and subsequent times through the loop */ - pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); - if( pSrc==0 ){ - assert( db->mallocFailed ); - break; - } - } - - /* The subquery uses a single slot of the FROM clause of the outer - ** query. If the subquery has more than one element in its FROM clause, - ** then expand the outer query to make space for it to hold all elements - ** of the subquery. - ** - ** Example: - ** - ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB; - ** - ** The outer query has 3 slots in its FROM clause. One slot of the - ** outer query (the middle slot) is used by the subquery. The next - ** block of code will expand the out query to 4 slots. The middle - ** slot is expanded to two slots in order to make space for the - ** two elements in the FROM clause of the subquery. - */ - if( nSubSrc>1 ){ - pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1); - if( db->mallocFailed ){ - break; - } - } - - /* Transfer the FROM clause terms from the subquery into the - ** outer query. - */ - for(i=0; ia[i+iFrom].pUsing); - pSrc->a[i+iFrom] = pSubSrc->a[i]; - memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); - } - pSrc->a[iFrom].jointype = jointype; - - /* Now begin substituting subquery result set expressions for - ** references to the iParent in the outer query. - ** - ** Example: - ** - ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; - ** \ \_____________ subquery __________/ / - ** \_____________________ outer query ______________________________/ - ** - ** We look at every expression in the outer query and every place we see - ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". - */ - pList = pParent->pEList; - for(i=0; inExpr; i++){ - if( pList->a[i].zName==0 ){ - char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); - sqlite3Dequote(zName); - pList->a[i].zName = zName; - } - } - substExprList(db, pParent->pEList, iParent, pSub->pEList); - if( isAgg ){ - substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); - pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); - } - if( pSub->pOrderBy ){ - assert( pParent->pOrderBy==0 ); - pParent->pOrderBy = pSub->pOrderBy; - pSub->pOrderBy = 0; - }else if( pParent->pOrderBy ){ - substExprList(db, pParent->pOrderBy, iParent, pSub->pEList); - } - if( pSub->pWhere ){ - pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); - }else{ - pWhere = 0; - } - if( subqueryIsAgg ){ - assert( pParent->pHaving==0 ); - pParent->pHaving = pParent->pWhere; - pParent->pWhere = pWhere; - pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); - pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, - sqlite3ExprDup(db, pSub->pHaving, 0)); - assert( pParent->pGroupBy==0 ); - pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); - }else{ - pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList); - pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); - } - - /* The flattened query is distinct if either the inner or the - ** outer query is distinct. - */ - pParent->selFlags |= pSub->selFlags & SF_Distinct; - - /* - ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; - ** - ** One is tempted to try to add a and b to combine the limits. But this - ** does not work if either limit is negative. - */ - if( pSub->pLimit ){ - pParent->pLimit = pSub->pLimit; - pSub->pLimit = 0; - } - } - - /* Finially, delete what is left of the subquery and return - ** success. - */ - sqlite3SelectDelete(db, pSub1); - - return 1; -} -#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ - -/* -** Based on the contents of the AggInfo structure indicated by the first -** argument, this function checks if the following are true: -** -** * the query contains just a single aggregate function, -** * the aggregate function is either min() or max(), and -** * the argument to the aggregate function is a column value. -** -** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX -** is returned as appropriate. Also, *ppMinMax is set to point to the -** list of arguments passed to the aggregate before returning. -** -** Or, if the conditions above are not met, *ppMinMax is set to 0 and -** WHERE_ORDERBY_NORMAL is returned. -*/ -static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ - int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ - - *ppMinMax = 0; - if( pAggInfo->nFunc==1 ){ - Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ - ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ - - assert( pExpr->op==TK_AGG_FUNCTION ); - if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ - const char *zFunc = pExpr->u.zToken; - if( sqlite3StrICmp(zFunc, "min")==0 ){ - eRet = WHERE_ORDERBY_MIN; - *ppMinMax = pEList; - }else if( sqlite3StrICmp(zFunc, "max")==0 ){ - eRet = WHERE_ORDERBY_MAX; - *ppMinMax = pEList; - } - } - } - - assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); - return eRet; -} - -/* -** The select statement passed as the first argument is an aggregate query. -** The second argment is the associated aggregate-info object. This -** function tests if the SELECT is of the form: -** -** SELECT count(*) FROM -** -** where table is a database table, not a sub-select or view. If the query -** does match this pattern, then a pointer to the Table object representing -** is returned. Otherwise, 0 is returned. -*/ -static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ - Table *pTab; - Expr *pExpr; - - assert( !p->pGroupBy ); - - if( p->pWhere || p->pEList->nExpr!=1 - || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect - ){ - return 0; - } - pTab = p->pSrc->a[0].pTab; - pExpr = p->pEList->a[0].pExpr; - assert( pTab && !pTab->pSelect && pExpr ); - - if( IsVirtual(pTab) ) return 0; - if( pExpr->op!=TK_AGG_FUNCTION ) return 0; - if( NEVER(pAggInfo->nFunc==0) ) return 0; - if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0; - if( pExpr->flags&EP_Distinct ) return 0; - - return pTab; -} - -/* -** If the source-list item passed as an argument was augmented with an -** INDEXED BY clause, then try to locate the specified index. If there -** was such a clause and the named index cannot be found, return -** SQLITE_ERROR and leave an error in pParse. Otherwise, populate -** pFrom->pIndex and return SQLITE_OK. -*/ -SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){ - if( pFrom->pTab && pFrom->zIndex ){ - Table *pTab = pFrom->pTab; - char *zIndex = pFrom->zIndex; - Index *pIdx; - for(pIdx=pTab->pIndex; - pIdx && sqlite3StrICmp(pIdx->zName, zIndex); - pIdx=pIdx->pNext - ); - if( !pIdx ){ - sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0); - pParse->checkSchema = 1; - return SQLITE_ERROR; - } - pFrom->pIndex = pIdx; - } - return SQLITE_OK; -} -/* -** Detect compound SELECT statements that use an ORDER BY clause with -** an alternative collating sequence. -** -** SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ... -** -** These are rewritten as a subquery: -** -** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2) -** ORDER BY ... COLLATE ... -** -** This transformation is necessary because the multiSelectOrderBy() routine -** above that generates the code for a compound SELECT with an ORDER BY clause -** uses a merge algorithm that requires the same collating sequence on the -** result columns as on the ORDER BY clause. See ticket -** http://www.sqlite.org/src/info/6709574d2a -** -** This transformation is only needed for EXCEPT, INTERSECT, and UNION. -** The UNION ALL operator works fine with multiSelectOrderBy() even when -** there are COLLATE terms in the ORDER BY. -*/ -static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ - int i; - Select *pNew; - Select *pX; - sqlite3 *db; - struct ExprList_item *a; - SrcList *pNewSrc; - Parse *pParse; - Token dummy; - - if( p->pPrior==0 ) return WRC_Continue; - if( p->pOrderBy==0 ) return WRC_Continue; - for(pX=p; pX && (pX->op==TK_ALL || pX->op==TK_SELECT); pX=pX->pPrior){} - if( pX==0 ) return WRC_Continue; - a = p->pOrderBy->a; - for(i=p->pOrderBy->nExpr-1; i>=0; i--){ - if( a[i].pExpr->flags & EP_Collate ) break; - } - if( i<0 ) return WRC_Continue; - - /* If we reach this point, that means the transformation is required. */ - - pParse = pWalker->pParse; - db = pParse->db; - pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); - if( pNew==0 ) return WRC_Abort; - memset(&dummy, 0, sizeof(dummy)); - pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0); - if( pNewSrc==0 ) return WRC_Abort; - *pNew = *p; - p->pSrc = pNewSrc; - p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ALL, 0)); - p->op = TK_SELECT; - p->pWhere = 0; - pNew->pGroupBy = 0; - pNew->pHaving = 0; - pNew->pOrderBy = 0; - p->pPrior = 0; - pNew->pLimit = 0; - pNew->pOffset = 0; - return WRC_Continue; -} - -/* -** This routine is a Walker callback for "expanding" a SELECT statement. -** "Expanding" means to do the following: -** -** (1) Make sure VDBE cursor numbers have been assigned to every -** element of the FROM clause. -** -** (2) Fill in the pTabList->a[].pTab fields in the SrcList that -** defines FROM clause. When views appear in the FROM clause, -** fill pTabList->a[].pSelect with a copy of the SELECT statement -** that implements the view. A copy is made of the view's SELECT -** statement so that we can freely modify or delete that statement -** without worrying about messing up the presistent representation -** of the view. -** -** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword -** on joins and the ON and USING clause of joins. -** -** (4) Scan the list of columns in the result set (pEList) looking -** for instances of the "*" operator or the TABLE.* operator. -** If found, expand each "*" to be every column in every table -** and TABLE.* to be every column in TABLE. -** -*/ -static int selectExpander(Walker *pWalker, Select *p){ - Parse *pParse = pWalker->pParse; - int i, j, k; - SrcList *pTabList; - ExprList *pEList; - struct SrcList_item *pFrom; - sqlite3 *db = pParse->db; - Expr *pE, *pRight, *pExpr; - u16 selFlags = p->selFlags; - - p->selFlags |= SF_Expanded; - if( db->mallocFailed ){ - return WRC_Abort; - } - if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){ - return WRC_Prune; - } - pTabList = p->pSrc; - pEList = p->pEList; - - /* Make sure cursor numbers have been assigned to all entries in - ** the FROM clause of the SELECT statement. - */ - sqlite3SrcListAssignCursors(pParse, pTabList); - - /* Look up every table named in the FROM clause of the select. If - ** an entry of the FROM clause is a subquery instead of a table or view, - ** then create a transient table structure to describe the subquery. - */ - for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab; - if( pFrom->pTab!=0 ){ - /* This statement has already been prepared. There is no need - ** to go further. */ - assert( i==0 ); - return WRC_Prune; - } - if( pFrom->zName==0 ){ -#ifndef SQLITE_OMIT_SUBQUERY - Select *pSel = pFrom->pSelect; - /* A sub-query in the FROM clause of a SELECT */ - assert( pSel!=0 ); - assert( pFrom->pTab==0 ); - sqlite3WalkSelect(pWalker, pSel); - pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); - if( pTab==0 ) return WRC_Abort; - pTab->nRef = 1; - pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab); - while( pSel->pPrior ){ pSel = pSel->pPrior; } - selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); - pTab->iPKey = -1; - pTab->nRowEst = 1000000; - pTab->tabFlags |= TF_Ephemeral; -#endif - }else{ - /* An ordinary table or view name in the FROM clause */ - assert( pFrom->pTab==0 ); - pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); - if( pTab==0 ) return WRC_Abort; - if( pTab->nRef==0xffff ){ - sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535", - pTab->zName); - pFrom->pTab = 0; - return WRC_Abort; - } - pTab->nRef++; -#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) - if( pTab->pSelect || IsVirtual(pTab) ){ - /* We reach here if the named table is a really a view */ - if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; - assert( pFrom->pSelect==0 ); - pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); - sqlite3WalkSelect(pWalker, pFrom->pSelect); - } -#endif - } - - /* Locate the index named by the INDEXED BY clause, if any. */ - if( sqlite3IndexedByLookup(pParse, pFrom) ){ - return WRC_Abort; - } - } - - /* Process NATURAL keywords, and ON and USING clauses of joins. - */ - if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){ - return WRC_Abort; - } - - /* For every "*" that occurs in the column list, insert the names of - ** all columns in all tables. And for every TABLE.* insert the names - ** of all columns in TABLE. The parser inserted a special expression - ** with the TK_ALL operator for each "*" that it found in the column list. - ** The following code just has to locate the TK_ALL expressions and expand - ** each one to the list of all columns in all tables. - ** - ** The first loop just checks to see if there are any "*" operators - ** that need expanding. - */ - for(k=0; knExpr; k++){ - pE = pEList->a[k].pExpr; - if( pE->op==TK_ALL ) break; - assert( pE->op!=TK_DOT || pE->pRight!=0 ); - assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); - if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; - } - if( knExpr ){ - /* - ** If we get here it means the result set contains one or more "*" - ** operators that need to be expanded. Loop through each expression - ** in the result set and expand them one by one. - */ - struct ExprList_item *a = pEList->a; - ExprList *pNew = 0; - int flags = pParse->db->flags; - int longNames = (flags & SQLITE_FullColNames)!=0 - && (flags & SQLITE_ShortColNames)==0; - - /* When processing FROM-clause subqueries, it is always the case - ** that full_column_names=OFF and short_column_names=ON. The - ** sqlite3ResultSetOfSelect() routine makes it so. */ - assert( (p->selFlags & SF_NestedFrom)==0 - || ((flags & SQLITE_FullColNames)==0 && - (flags & SQLITE_ShortColNames)!=0) ); - - for(k=0; knExpr; k++){ - pE = a[k].pExpr; - pRight = pE->pRight; - assert( pE->op!=TK_DOT || pRight!=0 ); - if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ - /* This particular expression does not need to be expanded. - */ - pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); - if( pNew ){ - pNew->a[pNew->nExpr-1].zName = a[k].zName; - pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan; - a[k].zName = 0; - a[k].zSpan = 0; - } - a[k].pExpr = 0; - }else{ - /* This expression is a "*" or a "TABLE.*" and needs to be - ** expanded. */ - int tableSeen = 0; /* Set to 1 when TABLE matches */ - char *zTName = 0; /* text of name of TABLE */ - if( pE->op==TK_DOT ){ - assert( pE->pLeft!=0 ); - assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); - zTName = pE->pLeft->u.zToken; - } - for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab = pFrom->pTab; - Select *pSub = pFrom->pSelect; - char *zTabName = pFrom->zAlias; - const char *zSchemaName = 0; - int iDb; - if( zTabName==0 ){ - zTabName = pTab->zName; - } - if( db->mallocFailed ) break; - if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ - pSub = 0; - if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ - continue; - } - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; - } - for(j=0; jnCol; j++){ - char *zName = pTab->aCol[j].zName; - char *zColname; /* The computed column name */ - char *zToFree; /* Malloced string that needs to be freed */ - Token sColname; /* Computed column name as a token */ - - assert( zName ); - if( zTName && pSub - && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 - ){ - continue; - } - - /* If a column is marked as 'hidden' (currently only possible - ** for virtual tables), do not include it in the expanded - ** result-set list. - */ - if( IsHiddenColumn(&pTab->aCol[j]) ){ - assert(IsVirtual(pTab)); - continue; - } - tableSeen = 1; - - if( i>0 && zTName==0 ){ - if( (pFrom->jointype & JT_NATURAL)!=0 - && tableAndColumnIndex(pTabList, i, zName, 0, 0) - ){ - /* In a NATURAL join, omit the join columns from the - ** table to the right of the join */ - continue; - } - if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){ - /* In a join with a USING clause, omit columns in the - ** using clause from the table on the right. */ - continue; - } - } - pRight = sqlite3Expr(db, TK_ID, zName); - zColname = zName; - zToFree = 0; - if( longNames || pTabList->nSrc>1 ){ - Expr *pLeft; - pLeft = sqlite3Expr(db, TK_ID, zTabName); - pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - if( zSchemaName ){ - pLeft = sqlite3Expr(db, TK_ID, zSchemaName); - pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0); - } - if( longNames ){ - zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); - zToFree = zColname; - } - }else{ - pExpr = pRight; - } - pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); - sColname.z = zColname; - sColname.n = sqlite3Strlen30(zColname); - sqlite3ExprListSetName(pParse, pNew, &sColname, 0); - if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ - struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; - if( pSub ){ - pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); - testcase( pX->zSpan==0 ); - }else{ - pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s", - zSchemaName, zTabName, zColname); - testcase( pX->zSpan==0 ); - } - pX->bSpanIsTab = 1; - } - sqlite3DbFree(db, zToFree); - } - } - if( !tableSeen ){ - if( zTName ){ - sqlite3ErrorMsg(pParse, "no such table: %s", zTName); - }else{ - sqlite3ErrorMsg(pParse, "no tables specified"); - } - } - } - } - sqlite3ExprListDelete(db, pEList); - p->pEList = pNew; - } -#if SQLITE_MAX_COLUMN - if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many columns in result set"); - } -#endif - return WRC_Continue; -} - -/* -** No-op routine for the parse-tree walker. -** -** When this routine is the Walker.xExprCallback then expression trees -** are walked without any actions being taken at each node. Presumably, -** when this routine is used for Walker.xExprCallback then -** Walker.xSelectCallback is set to do something useful for every -** subquery in the parser tree. -*/ -static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ - UNUSED_PARAMETER2(NotUsed, NotUsed2); - return WRC_Continue; -} - -/* -** This routine "expands" a SELECT statement and all of its subqueries. -** For additional information on what it means to "expand" a SELECT -** statement, see the comment on the selectExpand worker callback above. -** -** Expanding a SELECT statement is the first step in processing a -** SELECT statement. The SELECT statement must be expanded before -** name resolution is performed. -** -** If anything goes wrong, an error message is written into pParse. -** The calling function can detect the problem by looking at pParse->nErr -** and/or pParse->db->mallocFailed. -*/ -static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ - Walker w; - memset(&w, 0, sizeof(w)); - w.xSelectCallback = convertCompoundSelectToSubquery; - w.xExprCallback = exprWalkNoop; - w.pParse = pParse; - sqlite3WalkSelect(&w, pSelect); - w.xSelectCallback = selectExpander; - sqlite3WalkSelect(&w, pSelect); -} - - -#ifndef SQLITE_OMIT_SUBQUERY -/* -** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() -** interface. -** -** For each FROM-clause subquery, add Column.zType and Column.zColl -** information to the Table structure that represents the result set -** of that subquery. -** -** The Table structure that represents the result set was constructed -** by selectExpander() but the type and collation information was omitted -** at that point because identifiers had not yet been resolved. This -** routine is called after identifier resolution. -*/ -static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ - Parse *pParse; - int i; - SrcList *pTabList; - struct SrcList_item *pFrom; - - assert( p->selFlags & SF_Resolved ); - if( (p->selFlags & SF_HasTypeInfo)==0 ){ - p->selFlags |= SF_HasTypeInfo; - pParse = pWalker->pParse; - pTabList = p->pSrc; - for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab = pFrom->pTab; - if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ - /* A sub-query in the FROM clause of a SELECT */ - Select *pSel = pFrom->pSelect; - assert( pSel ); - while( pSel->pPrior ) pSel = pSel->pPrior; - selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel); - } - } - } - return WRC_Continue; -} -#endif - - -/* -** This routine adds datatype and collating sequence information to -** the Table structures of all FROM-clause subqueries in a -** SELECT statement. -** -** Use this routine after name resolution. -*/ -static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ -#ifndef SQLITE_OMIT_SUBQUERY - Walker w; - memset(&w, 0, sizeof(w)); - w.xSelectCallback = selectAddSubqueryTypeInfo; - w.xExprCallback = exprWalkNoop; - w.pParse = pParse; - w.bSelectDepthFirst = 1; - sqlite3WalkSelect(&w, pSelect); -#endif -} - - -/* -** This routine sets up a SELECT statement for processing. The -** following is accomplished: -** -** * VDBE Cursor numbers are assigned to all FROM-clause terms. -** * Ephemeral Table objects are created for all FROM-clause subqueries. -** * ON and USING clauses are shifted into WHERE statements -** * Wildcards "*" and "TABLE.*" in result sets are expanded. -** * Identifiers in expression are matched to tables. -** -** This routine acts recursively on all subqueries within the SELECT. -*/ -SQLITE_PRIVATE void sqlite3SelectPrep( - Parse *pParse, /* The parser context */ - Select *p, /* The SELECT statement being coded. */ - NameContext *pOuterNC /* Name context for container */ -){ - sqlite3 *db; - if( NEVER(p==0) ) return; - db = pParse->db; - if( db->mallocFailed ) return; - if( p->selFlags & SF_HasTypeInfo ) return; - sqlite3SelectExpand(pParse, p); - if( pParse->nErr || db->mallocFailed ) return; - sqlite3ResolveSelectNames(pParse, p, pOuterNC); - if( pParse->nErr || db->mallocFailed ) return; - sqlite3SelectAddTypeInfo(pParse, p); -} - -/* -** Reset the aggregate accumulator. -** -** The aggregate accumulator is a set of memory cells that hold -** intermediate results while calculating an aggregate. This -** routine generates code that stores NULLs in all of those memory -** cells. -*/ -static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ - Vdbe *v = pParse->pVdbe; - int i; - struct AggInfo_func *pFunc; - if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ - return; - } - for(i=0; inColumn; i++){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pAggInfo->aCol[i].iMem); - } - for(pFunc=pAggInfo->aFunc, i=0; inFunc; i++, pFunc++){ - sqlite3VdbeAddOp2(v, OP_Null, 0, pFunc->iMem); - if( pFunc->iDistinct>=0 ){ - Expr *pE = pFunc->pExpr; - assert( !ExprHasProperty(pE, EP_xIsSelect) ); - if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){ - sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " - "argument"); - pFunc->iDistinct = -1; - }else{ - KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList); - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, - (char*)pKeyInfo, P4_KEYINFO_HANDOFF); - } - } - } -} - -/* -** Invoke the OP_AggFinalize opcode for every aggregate function -** in the AggInfo structure. -*/ -static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ - Vdbe *v = pParse->pVdbe; - int i; - struct AggInfo_func *pF; - for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ - ExprList *pList = pF->pExpr->x.pList; - assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); - sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0, - (void*)pF->pFunc, P4_FUNCDEF); - } -} - -/* -** Update the accumulator memory cells for an aggregate based on -** the current cursor position. -*/ -static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ - Vdbe *v = pParse->pVdbe; - int i; - int regHit = 0; - int addrHitTest = 0; - struct AggInfo_func *pF; - struct AggInfo_col *pC; - - pAggInfo->directMode = 1; - sqlite3ExprCacheClear(pParse); - for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ - int nArg; - int addrNext = 0; - int regAgg; - ExprList *pList = pF->pExpr->x.pList; - assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); - if( pList ){ - nArg = pList->nExpr; - regAgg = sqlite3GetTempRange(pParse, nArg); - sqlite3ExprCodeExprList(pParse, pList, regAgg, 1); - }else{ - nArg = 0; - regAgg = 0; - } - if( pF->iDistinct>=0 ){ - addrNext = sqlite3VdbeMakeLabel(v); - assert( nArg==1 ); - codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); - } - if( pF->pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ - CollSeq *pColl = 0; - struct ExprList_item *pItem; - int j; - assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */ - for(j=0, pItem=pList->a; !pColl && jpExpr); - } - if( !pColl ){ - pColl = pParse->db->pDfltColl; - } - if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; - sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); - } - sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem, - (void*)pF->pFunc, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u8)nArg); - sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); - sqlite3ReleaseTempRange(pParse, regAgg, nArg); - if( addrNext ){ - sqlite3VdbeResolveLabel(v, addrNext); - sqlite3ExprCacheClear(pParse); - } - } - - /* Before populating the accumulator registers, clear the column cache. - ** Otherwise, if any of the required column values are already present - ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value - ** to pC->iMem. But by the time the value is used, the original register - ** may have been used, invalidating the underlying buffer holding the - ** text or blob value. See ticket [883034dcb5]. - ** - ** Another solution would be to change the OP_SCopy used to copy cached - ** values to an OP_Copy. - */ - if( regHit ){ - addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); - } - sqlite3ExprCacheClear(pParse); - for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ - sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); - } - pAggInfo->directMode = 0; - sqlite3ExprCacheClear(pParse); - if( addrHitTest ){ - sqlite3VdbeJumpHere(v, addrHitTest); - } -} - -/* -** Add a single OP_Explain instruction to the VDBE to explain a simple -** count(*) query ("SELECT count(*) FROM pTab"). -*/ -#ifndef SQLITE_OMIT_EXPLAIN -static void explainSimpleCount( - Parse *pParse, /* Parse context */ - Table *pTab, /* Table being queried */ - Index *pIdx /* Index used to optimize scan, or NULL */ -){ - if( pParse->explain==2 ){ - char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s %s%s(~%d rows)", - pTab->zName, - pIdx ? "USING COVERING INDEX " : "", - pIdx ? pIdx->zName : "", - pTab->nRowEst - ); - sqlite3VdbeAddOp4( - pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC - ); - } -} -#else -# define explainSimpleCount(a,b,c) -#endif - -/* -** Generate code for the SELECT statement given in the p argument. -** -** The results are distributed in various ways depending on the -** contents of the SelectDest structure pointed to by argument pDest -** as follows: -** -** pDest->eDest Result -** ------------ ------------------------------------------- -** SRT_Output Generate a row of output (using the OP_ResultRow -** opcode) for each row in the result set. -** -** SRT_Mem Only valid if the result is a single column. -** Store the first column of the first result row -** in register pDest->iSDParm then abandon the rest -** of the query. This destination implies "LIMIT 1". -** -** SRT_Set The result must be a single column. Store each -** row of result as the key in table pDest->iSDParm. -** Apply the affinity pDest->affSdst before storing -** results. Used to implement "IN (SELECT ...)". -** -** SRT_Union Store results as a key in a temporary table -** identified by pDest->iSDParm. -** -** SRT_Except Remove results from the temporary table pDest->iSDParm. -** -** SRT_Table Store results in temporary table pDest->iSDParm. -** This is like SRT_EphemTab except that the table -** is assumed to already be open. -** -** SRT_EphemTab Create an temporary table pDest->iSDParm and store -** the result there. The cursor is left open after -** returning. This is like SRT_Table except that -** this destination uses OP_OpenEphemeral to create -** the table first. -** -** SRT_Coroutine Generate a co-routine that returns a new row of -** results each time it is invoked. The entry point -** of the co-routine is stored in register pDest->iSDParm. -** -** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result -** set is not empty. -** -** SRT_Discard Throw the results away. This is used by SELECT -** statements within triggers whose only purpose is -** the side-effects of functions. -** -** This routine returns the number of errors. If any errors are -** encountered, then an appropriate error message is left in -** pParse->zErrMsg. -** -** This routine does NOT free the Select structure passed in. The -** calling function needs to do that. -*/ -SQLITE_PRIVATE int sqlite3Select( - Parse *pParse, /* The parser context */ - Select *p, /* The SELECT statement being coded. */ - SelectDest *pDest /* What to do with the query results */ -){ - int i, j; /* Loop counters */ - WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ - Vdbe *v; /* The virtual machine under construction */ - int isAgg; /* True for select lists like "count(*)" */ - ExprList *pEList; /* List of columns to extract. */ - SrcList *pTabList; /* List of tables to select from */ - Expr *pWhere; /* The WHERE clause. May be NULL */ - ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ - ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ - Expr *pHaving; /* The HAVING clause. May be NULL */ - int rc = 1; /* Value to return from this function */ - int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */ - DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */ - AggInfo sAggInfo; /* Information used by aggregate queries */ - int iEnd; /* Address of the end of the query */ - sqlite3 *db; /* The database connection */ - -#ifndef SQLITE_OMIT_EXPLAIN - int iRestoreSelectId = pParse->iSelectId; - pParse->iSelectId = pParse->iNextSelectId++; -#endif - - db = pParse->db; - if( p==0 || db->mallocFailed || pParse->nErr ){ - return 1; - } - if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; - memset(&sAggInfo, 0, sizeof(sAggInfo)); - - if( IgnorableOrderby(pDest) ){ - assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || - pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard); - /* If ORDER BY makes no difference in the output then neither does - ** DISTINCT so it can be removed too. */ - sqlite3ExprListDelete(db, p->pOrderBy); - p->pOrderBy = 0; - p->selFlags &= ~SF_Distinct; - } - sqlite3SelectPrep(pParse, p, 0); - pOrderBy = p->pOrderBy; - pTabList = p->pSrc; - pEList = p->pEList; - if( pParse->nErr || db->mallocFailed ){ - goto select_end; - } - isAgg = (p->selFlags & SF_Aggregate)!=0; - assert( pEList!=0 ); - - /* Begin generating code. - */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto select_end; - - /* If writing to memory or generating a set - ** only a single column may be output. - */ -#ifndef SQLITE_OMIT_SUBQUERY - if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ - goto select_end; - } -#endif - - /* Generate code for all sub-queries in the FROM clause - */ -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) - for(i=0; !p->pPrior && inSrc; i++){ - struct SrcList_item *pItem = &pTabList->a[i]; - SelectDest dest; - Select *pSub = pItem->pSelect; - int isAggSub; - - if( pSub==0 ) continue; - - /* Sometimes the code for a subquery will be generated more than - ** once, if the subquery is part of the WHERE clause in a LEFT JOIN, - ** for example. In that case, do not regenerate the code to manifest - ** a view or the co-routine to implement a view. The first instance - ** is sufficient, though the subroutine to manifest the view does need - ** to be invoked again. */ - if( pItem->addrFillSub ){ - if( pItem->viaCoroutine==0 ){ - sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); - } - continue; - } - - /* Increment Parse.nHeight by the height of the largest expression - ** tree refered to by this, the parent select. The child select - ** may contain expression trees of at most - ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit - ** more conservative than necessary, but much easier than enforcing - ** an exact limit. - */ - pParse->nHeight += sqlite3SelectExprHeight(p); - - isAggSub = (pSub->selFlags & SF_Aggregate)!=0; - if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ - /* This subquery can be absorbed into its parent. */ - if( isAggSub ){ - isAgg = 1; - p->selFlags |= SF_Aggregate; - } - i = -1; - }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0 - && OptimizationEnabled(db, SQLITE_SubqCoroutine) - ){ - /* Implement a co-routine that will return a single row of the result - ** set on each invocation. - */ - int addrTop; - int addrEof; - pItem->regReturn = ++pParse->nMem; - addrEof = ++pParse->nMem; - /* Before coding the OP_Goto to jump to the start of the main routine, - ** ensure that the jump to the verify-schema routine has already - ** been coded. Otherwise, the verify-schema would likely be coded as - ** part of the co-routine. If the main routine then accessed the - ** database before invoking the co-routine for the first time (for - ** example to initialize a LIMIT register from a sub-select), it would - ** be doing so without having verified the schema version and obtained - ** the required db locks. See ticket d6b36be38. */ - sqlite3CodeVerifySchema(pParse, -1); - sqlite3VdbeAddOp0(v, OP_Goto); - addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor); - sqlite3VdbeChangeP5(v, 1); - VdbeComment((v, "coroutine for %s", pItem->pTab->zName)); - pItem->addrFillSub = addrTop; - sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof); - sqlite3VdbeChangeP5(v, 1); - sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); - explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); - sqlite3Select(pParse, pSub, &dest); - pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; - pItem->viaCoroutine = 1; - sqlite3VdbeChangeP2(v, addrTop, dest.iSdst); - sqlite3VdbeChangeP3(v, addrTop, dest.nSdst); - sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof); - sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn); - VdbeComment((v, "end %s", pItem->pTab->zName)); - sqlite3VdbeJumpHere(v, addrTop-1); - sqlite3ClearTempRegCache(pParse); - }else{ - /* Generate a subroutine that will fill an ephemeral table with - ** the content of this subquery. pItem->addrFillSub will point - ** to the address of the generated subroutine. pItem->regReturn - ** is a register allocated to hold the subroutine return address - */ - int topAddr; - int onceAddr = 0; - int retAddr; - assert( pItem->addrFillSub==0 ); - pItem->regReturn = ++pParse->nMem; - topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); - pItem->addrFillSub = topAddr+1; - VdbeNoopComment((v, "materialize %s", pItem->pTab->zName)); - if( pItem->isCorrelated==0 ){ - /* If the subquery is not correlated and if we are not inside of - ** a trigger, then we only need to compute the value of the subquery - ** once. */ - onceAddr = sqlite3CodeOnce(pParse); - } - sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); - explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); - sqlite3Select(pParse, pSub, &dest); - pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; - if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); - retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); - VdbeComment((v, "end %s", pItem->pTab->zName)); - sqlite3VdbeChangeP1(v, topAddr, retAddr); - sqlite3ClearTempRegCache(pParse); - } - if( /*pParse->nErr ||*/ db->mallocFailed ){ - goto select_end; - } - pParse->nHeight -= sqlite3SelectExprHeight(p); - pTabList = p->pSrc; - if( !IgnorableOrderby(pDest) ){ - pOrderBy = p->pOrderBy; - } - } - pEList = p->pEList; -#endif - pWhere = p->pWhere; - pGroupBy = p->pGroupBy; - pHaving = p->pHaving; - sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; - -#ifndef SQLITE_OMIT_COMPOUND_SELECT - /* If there is are a sequence of queries, do the earlier ones first. - */ - if( p->pPrior ){ - if( p->pRightmost==0 ){ - Select *pLoop, *pRight = 0; - int cnt = 0; - int mxSelect; - for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){ - pLoop->pRightmost = p; - pLoop->pNext = pRight; - pRight = pLoop; - } - mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT]; - if( mxSelect && cnt>mxSelect ){ - sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); - goto select_end; - } - } - rc = multiSelect(pParse, p, pDest); - explainSetInteger(pParse->iSelectId, iRestoreSelectId); - return rc; - } -#endif - - /* If there is both a GROUP BY and an ORDER BY clause and they are - ** identical, then disable the ORDER BY clause since the GROUP BY - ** will cause elements to come out in the correct order. This is - ** an optimization - the correct answer should result regardless. - ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER - ** to disable this optimization for testing purposes. - */ - if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0 - && OptimizationEnabled(db, SQLITE_GroupByOrder) ){ - pOrderBy = 0; - } - - /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and - ** if the select-list is the same as the ORDER BY list, then this query - ** can be rewritten as a GROUP BY. In other words, this: - ** - ** SELECT DISTINCT xyz FROM ... ORDER BY xyz - ** - ** is transformed to: - ** - ** SELECT xyz FROM ... GROUP BY xyz - ** - ** The second form is preferred as a single index (or temp-table) may be - ** used for both the ORDER BY and DISTINCT processing. As originally - ** written the query must use a temp-table for at least one of the ORDER - ** BY and DISTINCT, and an index or separate temp-table for the other. - */ - if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct - && sqlite3ExprListCompare(pOrderBy, p->pEList)==0 - ){ - p->selFlags &= ~SF_Distinct; - p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); - pGroupBy = p->pGroupBy; - pOrderBy = 0; - /* Notice that even thought SF_Distinct has been cleared from p->selFlags, - ** the sDistinct.isTnct is still set. Hence, isTnct represents the - ** original setting of the SF_Distinct flag, not the current setting */ - assert( sDistinct.isTnct ); - } - - /* If there is an ORDER BY clause, then this sorting - ** index might end up being unused if the data can be - ** extracted in pre-sorted order. If that is the case, then the - ** OP_OpenEphemeral instruction will be changed to an OP_Noop once - ** we figure out that the sorting index is not needed. The addrSortIndex - ** variable is used to facilitate that change. - */ - if( pOrderBy ){ - KeyInfo *pKeyInfo; - pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); - pOrderBy->iECursor = pParse->nTab++; - p->addrOpenEphm[2] = addrSortIndex = - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - pOrderBy->iECursor, pOrderBy->nExpr+2, 0, - (char*)pKeyInfo, P4_KEYINFO_HANDOFF); - }else{ - addrSortIndex = -1; - } - - /* If the output is destined for a temporary table, open that table. - */ - if( pDest->eDest==SRT_EphemTab ){ - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr); - } - - /* Set the limiter. - */ - iEnd = sqlite3VdbeMakeLabel(v); - p->nSelectRow = (double)LARGEST_INT64; - computeLimitRegisters(pParse, p, iEnd); - if( p->iLimit==0 && addrSortIndex>=0 ){ - sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen; - p->selFlags |= SF_UseSorter; - } - - /* Open a virtual index to use for the distinct set. - */ - if( p->selFlags & SF_Distinct ){ - sDistinct.tabTnct = pParse->nTab++; - sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, - sDistinct.tabTnct, 0, 0, - (char*)keyInfoFromExprList(pParse, p->pEList), - P4_KEYINFO_HANDOFF); - sqlite3VdbeChangeP5(v, BTREE_UNORDERED); - sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; - }else{ - sDistinct.eTnctType = WHERE_DISTINCT_NOOP; - } - - if( !isAgg && pGroupBy==0 ){ - /* No aggregate functions and no GROUP BY clause */ - ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0); - - /* Begin the database scan. */ - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0); - if( pWInfo==0 ) goto select_end; - if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut; - if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct; - if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0; - - /* If sorting index that was created by a prior OP_OpenEphemeral - ** instruction ended up not being needed, then change the OP_OpenEphemeral - ** into an OP_Noop. - */ - if( addrSortIndex>=0 && pOrderBy==0 ){ - sqlite3VdbeChangeToNoop(v, addrSortIndex); - p->addrOpenEphm[2] = -1; - } - - /* Use the standard inner loop. */ - selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest, - pWInfo->iContinue, pWInfo->iBreak); - - /* End the database scan loop. - */ - sqlite3WhereEnd(pWInfo); - }else{ - /* This case when there exist aggregate functions or a GROUP BY clause - ** or both */ - NameContext sNC; /* Name context for processing aggregate information */ - int iAMem; /* First Mem address for storing current GROUP BY */ - int iBMem; /* First Mem address for previous GROUP BY */ - int iUseFlag; /* Mem address holding flag indicating that at least - ** one row of the input to the aggregator has been - ** processed */ - int iAbortFlag; /* Mem address which causes query abort if positive */ - int groupBySort; /* Rows come from source in GROUP BY order */ - int addrEnd; /* End of processing for this SELECT */ - int sortPTab = 0; /* Pseudotable used to decode sorting results */ - int sortOut = 0; /* Output register from the sorter */ - - /* Remove any and all aliases between the result set and the - ** GROUP BY clause. - */ - if( pGroupBy ){ - int k; /* Loop counter */ - struct ExprList_item *pItem; /* For looping over expression in a list */ - - for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){ - pItem->iAlias = 0; - } - for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){ - pItem->iAlias = 0; - } - if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100; - }else{ - p->nSelectRow = (double)1; - } - - - /* Create a label to jump to when we want to abort the query */ - addrEnd = sqlite3VdbeMakeLabel(v); - - /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in - ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the - ** SELECT statement. - */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pSrcList = pTabList; - sNC.pAggInfo = &sAggInfo; - sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; - sAggInfo.pGroupBy = pGroupBy; - sqlite3ExprAnalyzeAggList(&sNC, pEList); - sqlite3ExprAnalyzeAggList(&sNC, pOrderBy); - if( pHaving ){ - sqlite3ExprAnalyzeAggregates(&sNC, pHaving); - } - sAggInfo.nAccumulator = sAggInfo.nColumn; - for(i=0; ix.pList); - sNC.ncFlags &= ~NC_InAggFunc; - } - if( db->mallocFailed ) goto select_end; - - /* Processing for aggregates with GROUP BY is very different and - ** much more complex than aggregates without a GROUP BY. - */ - if( pGroupBy ){ - KeyInfo *pKeyInfo; /* Keying information for the group by clause */ - int j1; /* A-vs-B comparision jump */ - int addrOutputRow; /* Start of subroutine that outputs a result row */ - int regOutputRow; /* Return address register for output subroutine */ - int addrSetAbort; /* Set the abort flag and return */ - int addrTopOfLoop; /* Top of the input loop */ - int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ - int addrReset; /* Subroutine for resetting the accumulator */ - int regReset; /* Return address register for reset subroutine */ - - /* If there is a GROUP BY clause we might need a sorting index to - ** implement it. Allocate that sorting index now. If it turns out - ** that we do not need it after all, the OP_SorterOpen instruction - ** will be converted into a Noop. - */ - sAggInfo.sortingIdx = pParse->nTab++; - pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); - addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, - sAggInfo.sortingIdx, sAggInfo.nSortingColumn, - 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF); - - /* Initialize memory locations used by GROUP BY aggregate processing - */ - iUseFlag = ++pParse->nMem; - iAbortFlag = ++pParse->nMem; - regOutputRow = ++pParse->nMem; - addrOutputRow = sqlite3VdbeMakeLabel(v); - regReset = ++pParse->nMem; - addrReset = sqlite3VdbeMakeLabel(v); - iAMem = pParse->nMem + 1; - pParse->nMem += pGroupBy->nExpr; - iBMem = pParse->nMem + 1; - pParse->nMem += pGroupBy->nExpr; - sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); - VdbeComment((v, "clear abort flag")); - sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); - VdbeComment((v, "indicate accumulator empty")); - sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1); - - /* Begin a loop that will extract all source rows in GROUP BY order. - ** This might involve two separate loops with an OP_Sort in between, or - ** it might be a single loop that uses an index to extract information - ** in the right order to begin with. - */ - sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0); - if( pWInfo==0 ) goto select_end; - if( pWInfo->nOBSat==pGroupBy->nExpr ){ - /* The optimizer is able to deliver rows in group by order so - ** we do not have to sort. The OP_OpenEphemeral table will be - ** cancelled later because we still need to use the pKeyInfo - */ - groupBySort = 0; - }else{ - /* Rows are coming out in undetermined order. We have to push - ** each row into a sorting index, terminate the first loop, - ** then loop over the sorting index in order to get the output - ** in sorted order - */ - int regBase; - int regRecord; - int nCol; - int nGroupBy; - - explainTempTable(pParse, - (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ? - "DISTINCT" : "GROUP BY"); - - groupBySort = 1; - nGroupBy = pGroupBy->nExpr; - nCol = nGroupBy + 1; - j = nGroupBy+1; - for(i=0; i=j ){ - nCol++; - j++; - } - } - regBase = sqlite3GetTempRange(pParse, nCol); - sqlite3ExprCacheClear(pParse); - sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0); - sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); - j = nGroupBy+1; - for(i=0; iiSorterColumn>=j ){ - int r1 = j + regBase; - int r2; - - r2 = sqlite3ExprCodeGetColumn(pParse, - pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0); - if( r1!=r2 ){ - sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); - } - j++; - } - } - regRecord = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); - sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord); - sqlite3ReleaseTempReg(pParse, regRecord); - sqlite3ReleaseTempRange(pParse, regBase, nCol); - sqlite3WhereEnd(pWInfo); - sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++; - sortOut = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); - sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); - VdbeComment((v, "GROUP BY sort")); - sAggInfo.useSortingIdx = 1; - sqlite3ExprCacheClear(pParse); - } - - /* Evaluate the current GROUP BY terms and store in b0, b1, b2... - ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) - ** Then compare the current GROUP BY terms against the GROUP BY terms - ** from the previous row currently stored in a0, a1, a2... - */ - addrTopOfLoop = sqlite3VdbeCurrentAddr(v); - sqlite3ExprCacheClear(pParse); - if( groupBySort ){ - sqlite3VdbeAddOp2(v, OP_SorterData, sAggInfo.sortingIdx, sortOut); - } - for(j=0; jnExpr; j++){ - if( groupBySort ){ - sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j); - if( j==0 ) sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE); - }else{ - sAggInfo.directMode = 1; - sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); - } - } - sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, - (char*)pKeyInfo, P4_KEYINFO); - j1 = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); - - /* Generate code that runs whenever the GROUP BY changes. - ** Changes in the GROUP BY are detected by the previous code - ** block. If there were no changes, this block is skipped. - ** - ** This code copies current group by terms in b0,b1,b2,... - ** over to a0,a1,a2. It then calls the output subroutine - ** and resets the aggregate accumulator registers in preparation - ** for the next GROUP BY batch. - */ - sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); - sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); - VdbeComment((v, "output one row")); - sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); - VdbeComment((v, "check abort flag")); - sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - VdbeComment((v, "reset accumulator")); - - /* Update the aggregate accumulators based on the content of - ** the current row - */ - sqlite3VdbeJumpHere(v, j1); - updateAccumulator(pParse, &sAggInfo); - sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); - VdbeComment((v, "indicate data in accumulator")); - - /* End of the loop - */ - if( groupBySort ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); - }else{ - sqlite3WhereEnd(pWInfo); - sqlite3VdbeChangeToNoop(v, addrSortingIdx); - } - - /* Output the final row of result - */ - sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); - VdbeComment((v, "output final row")); - - /* Jump over the subroutines - */ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd); - - /* Generate a subroutine that outputs a single row of the result - ** set. This subroutine first looks at the iUseFlag. If iUseFlag - ** is less than or equal to zero, the subroutine is a no-op. If - ** the processing calls for the query to abort, this subroutine - ** increments the iAbortFlag memory location before returning in - ** order to signal the caller to abort. - */ - addrSetAbort = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag); - VdbeComment((v, "set abort flag")); - sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - sqlite3VdbeResolveLabel(v, addrOutputRow); - addrOutputRow = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); - VdbeComment((v, "Groupby result generator entry point")); - sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - finalizeAggFunctions(pParse, &sAggInfo); - sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, - &sDistinct, pDest, - addrOutputRow+1, addrSetAbort); - sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - VdbeComment((v, "end groupby result generator")); - - /* Generate a subroutine that will reset the group-by accumulator - */ - sqlite3VdbeResolveLabel(v, addrReset); - resetAccumulator(pParse, &sAggInfo); - sqlite3VdbeAddOp1(v, OP_Return, regReset); - - } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */ - else { - ExprList *pDel = 0; -#ifndef SQLITE_OMIT_BTREECOUNT - Table *pTab; - if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){ - /* If isSimpleCount() returns a pointer to a Table structure, then - ** the SQL statement is of the form: - ** - ** SELECT count(*) FROM - ** - ** where the Table structure returned represents table . - ** - ** This statement is so common that it is optimized specially. The - ** OP_Count instruction is executed either on the intkey table that - ** contains the data for table or on one of its indexes. It - ** is better to execute the op on an index, as indexes are almost - ** always spread across less pages than their corresponding tables. - */ - const int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */ - Index *pIdx; /* Iterator variable */ - KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */ - Index *pBest = 0; /* Best index found so far */ - int iRoot = pTab->tnum; /* Root page of scanned b-tree */ - - sqlite3CodeVerifySchema(pParse, iDb); - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - - /* Search for the index that has the least amount of columns. If - ** there is such an index, and it has less columns than the table - ** does, then we can assume that it consumes less space on disk and - ** will therefore be cheaper to scan to determine the query result. - ** In this case set iRoot to the root page number of the index b-tree - ** and pKeyInfo to the KeyInfo structure required to navigate the - ** index. - ** - ** (2011-04-15) Do not do a full scan of an unordered index. - ** - ** In practice the KeyInfo structure will not be used. It is only - ** passed to keep OP_OpenRead happy. - */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumnnColumn) ){ - pBest = pIdx; - } - } - if( pBest && pBest->nColumnnCol ){ - iRoot = pBest->tnum; - pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest); - } - - /* Open a read-only cursor, execute the OP_Count, close the cursor. */ - sqlite3VdbeAddOp3(v, OP_OpenRead, iCsr, iRoot, iDb); - if( pKeyInfo ){ - sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF); - } - sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem); - sqlite3VdbeAddOp1(v, OP_Close, iCsr); - explainSimpleCount(pParse, pTab, pBest); - }else -#endif /* SQLITE_OMIT_BTREECOUNT */ - { - /* Check if the query is of one of the following forms: - ** - ** SELECT min(x) FROM ... - ** SELECT max(x) FROM ... - ** - ** If it is, then ask the code in where.c to attempt to sort results - ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause. - ** If where.c is able to produce results sorted in this order, then - ** add vdbe code to break out of the processing loop after the - ** first iteration (since the first iteration of the loop is - ** guaranteed to operate on the row with the minimum or maximum - ** value of x, the only row required). - ** - ** A special flag must be passed to sqlite3WhereBegin() to slightly - ** modify behavior as follows: - ** - ** + If the query is a "SELECT min(x)", then the loop coded by - ** where.c should not iterate over any values with a NULL value - ** for x. - ** - ** + The optimizer code in where.c (the thing that decides which - ** index or indices to use) should place a different priority on - ** satisfying the 'ORDER BY' clause than it does in other cases. - ** Refer to code and comments in where.c for details. - */ - ExprList *pMinMax = 0; - u8 flag = WHERE_ORDERBY_NORMAL; - - assert( p->pGroupBy==0 ); - assert( flag==0 ); - if( p->pHaving==0 ){ - flag = minMaxQuery(&sAggInfo, &pMinMax); - } - assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); - - if( flag ){ - pMinMax = sqlite3ExprListDup(db, pMinMax, 0); - pDel = pMinMax; - if( pMinMax && !db->mallocFailed ){ - pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; - pMinMax->a[0].pExpr->op = TK_COLUMN; - } - } - - /* This case runs if the aggregate has no GROUP BY clause. The - ** processing is much simpler since there is only a single row - ** of output. - */ - resetAccumulator(pParse, &sAggInfo); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0); - if( pWInfo==0 ){ - sqlite3ExprListDelete(db, pDel); - goto select_end; - } - updateAccumulator(pParse, &sAggInfo); - assert( pMinMax==0 || pMinMax->nExpr==1 ); - if( pWInfo->nOBSat>0 ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak); - VdbeComment((v, "%s() by index", - (flag==WHERE_ORDERBY_MIN?"min":"max"))); - } - sqlite3WhereEnd(pWInfo); - finalizeAggFunctions(pParse, &sAggInfo); - } - - pOrderBy = 0; - sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0, - pDest, addrEnd, addrEnd); - sqlite3ExprListDelete(db, pDel); - } - sqlite3VdbeResolveLabel(v, addrEnd); - - } /* endif aggregate query */ - - if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){ - explainTempTable(pParse, "DISTINCT"); - } - - /* If there is an ORDER BY clause, then we need to sort the results - ** and send them to the callback one by one. - */ - if( pOrderBy ){ - explainTempTable(pParse, "ORDER BY"); - generateSortTail(pParse, p, v, pEList->nExpr, pDest); - } - - /* Jump here to skip this query - */ - sqlite3VdbeResolveLabel(v, iEnd); - - /* The SELECT was successfully coded. Set the return code to 0 - ** to indicate no errors. - */ - rc = 0; - - /* Control jumps to here if an error is encountered above, or upon - ** successful coding of the SELECT. - */ -select_end: - explainSetInteger(pParse->iSelectId, iRestoreSelectId); - - /* Identify column names if results of the SELECT are to be output. - */ - if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){ - generateColumnNames(pParse, pTabList, pEList); - } - - sqlite3DbFree(db, sAggInfo.aCol); - sqlite3DbFree(db, sAggInfo.aFunc); - return rc; -} - -#if defined(SQLITE_ENABLE_TREE_EXPLAIN) -/* -** Generate a human-readable description of a the Select object. -*/ -static void explainOneSelect(Vdbe *pVdbe, Select *p){ - sqlite3ExplainPrintf(pVdbe, "SELECT "); - if( p->selFlags & (SF_Distinct|SF_Aggregate) ){ - if( p->selFlags & SF_Distinct ){ - sqlite3ExplainPrintf(pVdbe, "DISTINCT "); - } - if( p->selFlags & SF_Aggregate ){ - sqlite3ExplainPrintf(pVdbe, "agg_flag "); - } - sqlite3ExplainNL(pVdbe); - sqlite3ExplainPrintf(pVdbe, " "); - } - sqlite3ExplainExprList(pVdbe, p->pEList); - sqlite3ExplainNL(pVdbe); - if( p->pSrc && p->pSrc->nSrc ){ - int i; - sqlite3ExplainPrintf(pVdbe, "FROM "); - sqlite3ExplainPush(pVdbe); - for(i=0; ipSrc->nSrc; i++){ - struct SrcList_item *pItem = &p->pSrc->a[i]; - sqlite3ExplainPrintf(pVdbe, "{%d,*} = ", pItem->iCursor); - if( pItem->pSelect ){ - sqlite3ExplainSelect(pVdbe, pItem->pSelect); - if( pItem->pTab ){ - sqlite3ExplainPrintf(pVdbe, " (tabname=%s)", pItem->pTab->zName); - } - }else if( pItem->zName ){ - sqlite3ExplainPrintf(pVdbe, "%s", pItem->zName); - } - if( pItem->zAlias ){ - sqlite3ExplainPrintf(pVdbe, " (AS %s)", pItem->zAlias); - } - if( pItem->jointype & JT_LEFT ){ - sqlite3ExplainPrintf(pVdbe, " LEFT-JOIN"); - } - sqlite3ExplainNL(pVdbe); - } - sqlite3ExplainPop(pVdbe); - } - if( p->pWhere ){ - sqlite3ExplainPrintf(pVdbe, "WHERE "); - sqlite3ExplainExpr(pVdbe, p->pWhere); - sqlite3ExplainNL(pVdbe); - } - if( p->pGroupBy ){ - sqlite3ExplainPrintf(pVdbe, "GROUPBY "); - sqlite3ExplainExprList(pVdbe, p->pGroupBy); - sqlite3ExplainNL(pVdbe); - } - if( p->pHaving ){ - sqlite3ExplainPrintf(pVdbe, "HAVING "); - sqlite3ExplainExpr(pVdbe, p->pHaving); - sqlite3ExplainNL(pVdbe); - } - if( p->pOrderBy ){ - sqlite3ExplainPrintf(pVdbe, "ORDERBY "); - sqlite3ExplainExprList(pVdbe, p->pOrderBy); - sqlite3ExplainNL(pVdbe); - } - if( p->pLimit ){ - sqlite3ExplainPrintf(pVdbe, "LIMIT "); - sqlite3ExplainExpr(pVdbe, p->pLimit); - sqlite3ExplainNL(pVdbe); - } - if( p->pOffset ){ - sqlite3ExplainPrintf(pVdbe, "OFFSET "); - sqlite3ExplainExpr(pVdbe, p->pOffset); - sqlite3ExplainNL(pVdbe); - } -} -SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){ - if( p==0 ){ - sqlite3ExplainPrintf(pVdbe, "(null-select)"); - return; - } - while( p->pPrior ){ - p->pPrior->pNext = p; - p = p->pPrior; - } - sqlite3ExplainPush(pVdbe); - while( p ){ - explainOneSelect(pVdbe, p); - p = p->pNext; - if( p==0 ) break; - sqlite3ExplainNL(pVdbe); - sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op)); - } - sqlite3ExplainPrintf(pVdbe, "END"); - sqlite3ExplainPop(pVdbe); -} - -/* End of the structure debug printing code -*****************************************************************************/ -#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */ - -/************** End of select.c **********************************************/ -/************** Begin file table.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains the sqlite3_get_table() and sqlite3_free_table() -** interface routines. These are just wrappers around the main -** interface routine of sqlite3_exec(). -** -** These routines are in a separate files so that they will not be linked -** if they are not used. -*/ -/* #include */ -/* #include */ - -#ifndef SQLITE_OMIT_GET_TABLE - -/* -** This structure is used to pass data from sqlite3_get_table() through -** to the callback function is uses to build the result. -*/ -typedef struct TabResult { - char **azResult; /* Accumulated output */ - char *zErrMsg; /* Error message text, if an error occurs */ - int nAlloc; /* Slots allocated for azResult[] */ - int nRow; /* Number of rows in the result */ - int nColumn; /* Number of columns in the result */ - int nData; /* Slots used in azResult[]. (nRow+1)*nColumn */ - int rc; /* Return code from sqlite3_exec() */ -} TabResult; - -/* -** This routine is called once for each row in the result table. Its job -** is to fill in the TabResult structure appropriately, allocating new -** memory as necessary. -*/ -static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ - TabResult *p = (TabResult*)pArg; /* Result accumulator */ - int need; /* Slots needed in p->azResult[] */ - int i; /* Loop counter */ - char *z; /* A single column of result */ - - /* Make sure there is enough space in p->azResult to hold everything - ** we need to remember from this invocation of the callback. - */ - if( p->nRow==0 && argv!=0 ){ - need = nCol*2; - }else{ - need = nCol; - } - if( p->nData + need > p->nAlloc ){ - char **azNew; - p->nAlloc = p->nAlloc*2 + need; - azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc ); - if( azNew==0 ) goto malloc_failed; - p->azResult = azNew; - } - - /* If this is the first row, then generate an extra row containing - ** the names of all columns. - */ - if( p->nRow==0 ){ - p->nColumn = nCol; - for(i=0; iazResult[p->nData++] = z; - } - }else if( p->nColumn!=nCol ){ - sqlite3_free(p->zErrMsg); - p->zErrMsg = sqlite3_mprintf( - "sqlite3_get_table() called with two or more incompatible queries" - ); - p->rc = SQLITE_ERROR; - return 1; - } - - /* Copy over the row data - */ - if( argv!=0 ){ - for(i=0; iazResult[p->nData++] = z; - } - p->nRow++; - } - return 0; - -malloc_failed: - p->rc = SQLITE_NOMEM; - return 1; -} - -/* -** Query the database. But instead of invoking a callback for each row, -** malloc() for space to hold the result and return the entire results -** at the conclusion of the call. -** -** The result that is written to ***pazResult is held in memory obtained -** from malloc(). But the caller cannot free this memory directly. -** Instead, the entire table should be passed to sqlite3_free_table() when -** the calling procedure is finished using it. -*/ -SQLITE_API int sqlite3_get_table( - sqlite3 *db, /* The database on which the SQL executes */ - const char *zSql, /* The SQL to be executed */ - char ***pazResult, /* Write the result table here */ - int *pnRow, /* Write the number of rows in the result here */ - int *pnColumn, /* Write the number of columns of result here */ - char **pzErrMsg /* Write error messages here */ -){ - int rc; - TabResult res; - - *pazResult = 0; - if( pnColumn ) *pnColumn = 0; - if( pnRow ) *pnRow = 0; - if( pzErrMsg ) *pzErrMsg = 0; - res.zErrMsg = 0; - res.nRow = 0; - res.nColumn = 0; - res.nData = 1; - res.nAlloc = 20; - res.rc = SQLITE_OK; - res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc ); - if( res.azResult==0 ){ - db->errCode = SQLITE_NOMEM; - return SQLITE_NOMEM; - } - res.azResult[0] = 0; - rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); - assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); - res.azResult[0] = SQLITE_INT_TO_PTR(res.nData); - if( (rc&0xff)==SQLITE_ABORT ){ - sqlite3_free_table(&res.azResult[1]); - if( res.zErrMsg ){ - if( pzErrMsg ){ - sqlite3_free(*pzErrMsg); - *pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg); - } - sqlite3_free(res.zErrMsg); - } - db->errCode = res.rc; /* Assume 32-bit assignment is atomic */ - return res.rc; - } - sqlite3_free(res.zErrMsg); - if( rc!=SQLITE_OK ){ - sqlite3_free_table(&res.azResult[1]); - return rc; - } - if( res.nAlloc>res.nData ){ - char **azNew; - azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData ); - if( azNew==0 ){ - sqlite3_free_table(&res.azResult[1]); - db->errCode = SQLITE_NOMEM; - return SQLITE_NOMEM; - } - res.azResult = azNew; - } - *pazResult = &res.azResult[1]; - if( pnColumn ) *pnColumn = res.nColumn; - if( pnRow ) *pnRow = res.nRow; - return rc; -} - -/* -** This routine frees the space the sqlite3_get_table() malloced. -*/ -SQLITE_API void sqlite3_free_table( - char **azResult /* Result returned from from sqlite3_get_table() */ -){ - if( azResult ){ - int i, n; - azResult--; - assert( azResult!=0 ); - n = SQLITE_PTR_TO_INT(azResult[0]); - for(i=1; ipNext; - - sqlite3ExprDelete(db, pTmp->pWhere); - sqlite3ExprListDelete(db, pTmp->pExprList); - sqlite3SelectDelete(db, pTmp->pSelect); - sqlite3IdListDelete(db, pTmp->pIdList); - - sqlite3DbFree(db, pTmp); - } -} - -/* -** Given table pTab, return a list of all the triggers attached to -** the table. The list is connected by Trigger.pNext pointers. -** -** All of the triggers on pTab that are in the same database as pTab -** are already attached to pTab->pTrigger. But there might be additional -** triggers on pTab in the TEMP schema. This routine prepends all -** TEMP triggers on pTab to the beginning of the pTab->pTrigger list -** and returns the combined list. -** -** To state it another way: This routine returns a list of all triggers -** that fire off of pTab. The list will include any TEMP triggers on -** pTab as well as the triggers lised in pTab->pTrigger. -*/ -SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ - Schema * const pTmpSchema = pParse->db->aDb[1].pSchema; - Trigger *pList = 0; /* List of triggers to return */ - - if( pParse->disableTriggers ){ - return 0; - } - - if( pTmpSchema!=pTab->pSchema ){ - HashElem *p; - assert( sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) ); - for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){ - Trigger *pTrig = (Trigger *)sqliteHashData(p); - if( pTrig->pTabSchema==pTab->pSchema - && 0==sqlite3StrICmp(pTrig->table, pTab->zName) - ){ - pTrig->pNext = (pList ? pList : pTab->pTrigger); - pList = pTrig; - } - } - } - - return (pList ? pList : pTab->pTrigger); -} - -/* -** This is called by the parser when it sees a CREATE TRIGGER statement -** up to the point of the BEGIN before the trigger actions. A Trigger -** structure is generated based on the information available and stored -** in pParse->pNewTrigger. After the trigger actions have been parsed, the -** sqlite3FinishTrigger() function is called to complete the trigger -** construction process. -*/ -SQLITE_PRIVATE void sqlite3BeginTrigger( - Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ - Token *pName1, /* The name of the trigger */ - Token *pName2, /* The name of the trigger */ - int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ - int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ - IdList *pColumns, /* column list if this is an UPDATE OF trigger */ - SrcList *pTableName,/* The name of the table/view the trigger applies to */ - Expr *pWhen, /* WHEN clause */ - int isTemp, /* True if the TEMPORARY keyword is present */ - int noErr /* Suppress errors if the trigger already exists */ -){ - Trigger *pTrigger = 0; /* The new trigger */ - Table *pTab; /* Table that the trigger fires off of */ - char *zName = 0; /* Name of the trigger */ - sqlite3 *db = pParse->db; /* The database connection */ - int iDb; /* The database to store the trigger in */ - Token *pName; /* The unqualified db name */ - DbFixer sFix; /* State vector for the DB fixer */ - int iTabDb; /* Index of the database holding pTab */ - - assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ - assert( pName2!=0 ); - assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE ); - assert( op>0 && op<0xff ); - if( isTemp ){ - /* If TEMP was specified, then the trigger name may not be qualified. */ - if( pName2->n>0 ){ - sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); - goto trigger_cleanup; - } - iDb = 1; - pName = pName1; - }else{ - /* Figure out the db that the trigger will be created in */ - iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); - if( iDb<0 ){ - goto trigger_cleanup; - } - } - if( !pTableName || db->mallocFailed ){ - goto trigger_cleanup; - } - - /* A long-standing parser bug is that this syntax was allowed: - ** - ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab .... - ** ^^^^^^^^ - ** - ** To maintain backwards compatibility, ignore the database - ** name on pTableName if we are reparsing our of SQLITE_MASTER. - */ - if( db->init.busy && iDb!=1 ){ - sqlite3DbFree(db, pTableName->a[0].zDatabase); - pTableName->a[0].zDatabase = 0; - } - - /* If the trigger name was unqualified, and the table is a temp table, - ** then set iDb to 1 to create the trigger in the temporary database. - ** If sqlite3SrcListLookup() returns 0, indicating the table does not - ** exist, the error is caught by the block below. - */ - pTab = sqlite3SrcListLookup(pParse, pTableName); - if( db->init.busy==0 && pName2->n==0 && pTab - && pTab->pSchema==db->aDb[1].pSchema ){ - iDb = 1; - } - - /* Ensure the table name matches database name and that the table exists */ - if( db->mallocFailed ) goto trigger_cleanup; - assert( pTableName->nSrc==1 ); - if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && - sqlite3FixSrcList(&sFix, pTableName) ){ - goto trigger_cleanup; - } - pTab = sqlite3SrcListLookup(pParse, pTableName); - if( !pTab ){ - /* The table does not exist. */ - if( db->init.iDb==1 ){ - /* Ticket #3810. - ** Normally, whenever a table is dropped, all associated triggers are - ** dropped too. But if a TEMP trigger is created on a non-TEMP table - ** and the table is dropped by a different database connection, the - ** trigger is not visible to the database connection that does the - ** drop so the trigger cannot be dropped. This results in an - ** "orphaned trigger" - a trigger whose associated table is missing. - */ - db->init.orphanTrigger = 1; - } - goto trigger_cleanup; - } - if( IsVirtual(pTab) ){ - sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); - goto trigger_cleanup; - } - - /* Check that the trigger name is not reserved and that no trigger of the - ** specified name exists */ - zName = sqlite3NameFromToken(db, pName); - if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ - goto trigger_cleanup; - } - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), - zName, sqlite3Strlen30(zName)) ){ - if( !noErr ){ - sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); - }else{ - assert( !db->init.busy ); - sqlite3CodeVerifySchema(pParse, iDb); - } - goto trigger_cleanup; - } - - /* Do not create a trigger on a system table */ - if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ - sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); - pParse->nErr++; - goto trigger_cleanup; - } - - /* INSTEAD of triggers are only for views and views only support INSTEAD - ** of triggers. - */ - if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ - sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", - (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); - goto trigger_cleanup; - } - if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ - sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" - " trigger on table: %S", pTableName, 0); - goto trigger_cleanup; - } - iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); - -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int code = SQLITE_CREATE_TRIGGER; - const char *zDb = db->aDb[iTabDb].zName; - const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; - if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; - if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ - goto trigger_cleanup; - } - if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ - goto trigger_cleanup; - } - } -#endif - - /* INSTEAD OF triggers can only appear on views and BEFORE triggers - ** cannot appear on views. So we might as well translate every - ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code - ** elsewhere. - */ - if (tr_tm == TK_INSTEAD){ - tr_tm = TK_BEFORE; - } - - /* Build the Trigger object */ - pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); - if( pTrigger==0 ) goto trigger_cleanup; - pTrigger->zName = zName; - zName = 0; - pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); - pTrigger->pSchema = db->aDb[iDb].pSchema; - pTrigger->pTabSchema = pTab->pSchema; - pTrigger->op = (u8)op; - pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; - pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); - pTrigger->pColumns = sqlite3IdListDup(db, pColumns); - assert( pParse->pNewTrigger==0 ); - pParse->pNewTrigger = pTrigger; - -trigger_cleanup: - sqlite3DbFree(db, zName); - sqlite3SrcListDelete(db, pTableName); - sqlite3IdListDelete(db, pColumns); - sqlite3ExprDelete(db, pWhen); - if( !pParse->pNewTrigger ){ - sqlite3DeleteTrigger(db, pTrigger); - }else{ - assert( pParse->pNewTrigger==pTrigger ); - } -} - -/* -** This routine is called after all of the trigger actions have been parsed -** in order to complete the process of building the trigger. -*/ -SQLITE_PRIVATE void sqlite3FinishTrigger( - Parse *pParse, /* Parser context */ - TriggerStep *pStepList, /* The triggered program */ - Token *pAll /* Token that describes the complete CREATE TRIGGER */ -){ - Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ - char *zName; /* Name of trigger */ - sqlite3 *db = pParse->db; /* The database */ - DbFixer sFix; /* Fixer object */ - int iDb; /* Database containing the trigger */ - Token nameToken; /* Trigger name for error reporting */ - - pParse->pNewTrigger = 0; - if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; - zName = pTrig->zName; - iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); - pTrig->step_list = pStepList; - while( pStepList ){ - pStepList->pTrig = pTrig; - pStepList = pStepList->pNext; - } - nameToken.z = pTrig->zName; - nameToken.n = sqlite3Strlen30(nameToken.z); - if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) - && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ - goto triggerfinish_cleanup; - } - - /* if we are not initializing, - ** build the sqlite_master entry - */ - if( !db->init.busy ){ - Vdbe *v; - char *z; - - /* Make an entry in the sqlite_master table */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto triggerfinish_cleanup; - sqlite3BeginWriteOperation(pParse, 0, iDb); - z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); - sqlite3NestedParse(pParse, - "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName, - pTrig->table, z); - sqlite3DbFree(db, z); - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddParseSchemaOp(v, iDb, - sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName)); - } - - if( db->init.busy ){ - Trigger *pLink = pTrig; - Hash *pHash = &db->aDb[iDb].pSchema->trigHash; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig); - if( pTrig ){ - db->mallocFailed = 1; - }else if( pLink->pSchema==pLink->pTabSchema ){ - Table *pTab; - int n = sqlite3Strlen30(pLink->table); - pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n); - assert( pTab!=0 ); - pLink->pNext = pTab->pTrigger; - pTab->pTrigger = pLink; - } - } - -triggerfinish_cleanup: - sqlite3DeleteTrigger(db, pTrig); - assert( !pParse->pNewTrigger ); - sqlite3DeleteTriggerStep(db, pStepList); -} - -/* -** Turn a SELECT statement (that the pSelect parameter points to) into -** a trigger step. Return a pointer to a TriggerStep structure. -** -** The parser calls this routine when it finds a SELECT statement in -** body of a TRIGGER. -*/ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ - TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); - if( pTriggerStep==0 ) { - sqlite3SelectDelete(db, pSelect); - return 0; - } - pTriggerStep->op = TK_SELECT; - pTriggerStep->pSelect = pSelect; - pTriggerStep->orconf = OE_Default; - return pTriggerStep; -} - -/* -** Allocate space to hold a new trigger step. The allocated space -** holds both the TriggerStep object and the TriggerStep.target.z string. -** -** If an OOM error occurs, NULL is returned and db->mallocFailed is set. -*/ -static TriggerStep *triggerStepAllocate( - sqlite3 *db, /* Database connection */ - u8 op, /* Trigger opcode */ - Token *pName /* The target name */ -){ - TriggerStep *pTriggerStep; - - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n); - if( pTriggerStep ){ - char *z = (char*)&pTriggerStep[1]; - memcpy(z, pName->z, pName->n); - pTriggerStep->target.z = z; - pTriggerStep->target.n = pName->n; - pTriggerStep->op = op; - } - return pTriggerStep; -} - -/* -** Build a trigger step out of an INSERT statement. Return a pointer -** to the new trigger step. -** -** The parser calls this routine when it sees an INSERT inside the -** body of a trigger. -*/ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( - sqlite3 *db, /* The database connection */ - Token *pTableName, /* Name of the table into which we insert */ - IdList *pColumn, /* List of columns in pTableName to insert into */ - ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ - Select *pSelect, /* A SELECT statement that supplies values */ - u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ -){ - TriggerStep *pTriggerStep; - - assert(pEList == 0 || pSelect == 0); - assert(pEList != 0 || pSelect != 0 || db->mallocFailed); - - pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); - if( pTriggerStep ){ - pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); - pTriggerStep->pIdList = pColumn; - pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); - pTriggerStep->orconf = orconf; - }else{ - sqlite3IdListDelete(db, pColumn); - } - sqlite3ExprListDelete(db, pEList); - sqlite3SelectDelete(db, pSelect); - - return pTriggerStep; -} - -/* -** Construct a trigger step that implements an UPDATE statement and return -** a pointer to that trigger step. The parser calls this routine when it -** sees an UPDATE statement inside the body of a CREATE TRIGGER. -*/ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( - sqlite3 *db, /* The database connection */ - Token *pTableName, /* Name of the table to be updated */ - ExprList *pEList, /* The SET clause: list of column and new values */ - Expr *pWhere, /* The WHERE clause */ - u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ -){ - TriggerStep *pTriggerStep; - - pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); - if( pTriggerStep ){ - pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); - pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - pTriggerStep->orconf = orconf; - } - sqlite3ExprListDelete(db, pEList); - sqlite3ExprDelete(db, pWhere); - return pTriggerStep; -} - -/* -** Construct a trigger step that implements a DELETE statement and return -** a pointer to that trigger step. The parser calls this routine when it -** sees a DELETE statement inside the body of a CREATE TRIGGER. -*/ -SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( - sqlite3 *db, /* Database connection */ - Token *pTableName, /* The table from which rows are deleted */ - Expr *pWhere /* The WHERE clause */ -){ - TriggerStep *pTriggerStep; - - pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); - if( pTriggerStep ){ - pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - pTriggerStep->orconf = OE_Default; - } - sqlite3ExprDelete(db, pWhere); - return pTriggerStep; -} - -/* -** Recursively delete a Trigger structure -*/ -SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ - if( pTrigger==0 ) return; - sqlite3DeleteTriggerStep(db, pTrigger->step_list); - sqlite3DbFree(db, pTrigger->zName); - sqlite3DbFree(db, pTrigger->table); - sqlite3ExprDelete(db, pTrigger->pWhen); - sqlite3IdListDelete(db, pTrigger->pColumns); - sqlite3DbFree(db, pTrigger); -} - -/* -** This function is called to drop a trigger from the database schema. -** -** This may be called directly from the parser and therefore identifies -** the trigger by name. The sqlite3DropTriggerPtr() routine does the -** same job as this routine except it takes a pointer to the trigger -** instead of the trigger name. -**/ -SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ - Trigger *pTrigger = 0; - int i; - const char *zDb; - const char *zName; - int nName; - sqlite3 *db = pParse->db; - - if( db->mallocFailed ) goto drop_trigger_cleanup; - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ - goto drop_trigger_cleanup; - } - - assert( pName->nSrc==1 ); - zDb = pName->a[0].zDatabase; - zName = pName->a[0].zName; - nName = sqlite3Strlen30(zName); - assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); - for(i=OMIT_TEMPDB; inDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); - if( pTrigger ) break; - } - if( !pTrigger ){ - if( !noErr ){ - sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); - }else{ - sqlite3CodeVerifyNamedSchema(pParse, zDb); - } - pParse->checkSchema = 1; - goto drop_trigger_cleanup; - } - sqlite3DropTriggerPtr(pParse, pTrigger); - -drop_trigger_cleanup: - sqlite3SrcListDelete(db, pName); -} - -/* -** Return a pointer to the Table structure for the table that a trigger -** is set on. -*/ -static Table *tableOfTrigger(Trigger *pTrigger){ - int n = sqlite3Strlen30(pTrigger->table); - return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); -} - - -/* -** Drop a trigger given a pointer to that trigger. -*/ -SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ - Table *pTable; - Vdbe *v; - sqlite3 *db = pParse->db; - int iDb; - - iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); - assert( iDb>=0 && iDbnDb ); - pTable = tableOfTrigger(pTrigger); - assert( pTable ); - assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int code = SQLITE_DROP_TRIGGER; - const char *zDb = db->aDb[iDb].zName; - const char *zTab = SCHEMA_TABLE(iDb); - if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; - if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || - sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ - return; - } - } -#endif - - /* Generate code to destroy the database record of the trigger. - */ - assert( pTable!=0 ); - if( (v = sqlite3GetVdbe(pParse))!=0 ){ - int base; - static const VdbeOpList dropTrigger[] = { - { OP_Rewind, 0, ADDR(9), 0}, - { OP_String8, 0, 1, 0}, /* 1 */ - { OP_Column, 0, 1, 2}, - { OP_Ne, 2, ADDR(8), 1}, - { OP_String8, 0, 1, 0}, /* 4: "trigger" */ - { OP_Column, 0, 0, 2}, - { OP_Ne, 2, ADDR(8), 1}, - { OP_Delete, 0, 0, 0}, - { OP_Next, 0, ADDR(1), 0}, /* 8 */ - }; - - sqlite3BeginWriteOperation(pParse, 0, iDb); - sqlite3OpenMasterTable(pParse, iDb); - base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); - sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT); - sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); - sqlite3ChangeCookie(pParse, iDb); - sqlite3VdbeAddOp2(v, OP_Close, 0, 0); - sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); - if( pParse->nMem<3 ){ - pParse->nMem = 3; - } - } -} - -/* -** Remove a trigger from the hash tables of the sqlite* pointer. -*/ -SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ - Trigger *pTrigger; - Hash *pHash; - - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pHash = &(db->aDb[iDb].pSchema->trigHash); - pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0); - if( ALWAYS(pTrigger) ){ - if( pTrigger->pSchema==pTrigger->pTabSchema ){ - Table *pTab = tableOfTrigger(pTrigger); - Trigger **pp; - for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); - *pp = (*pp)->pNext; - } - sqlite3DeleteTrigger(db, pTrigger); - db->flags |= SQLITE_InternChanges; - } -} - -/* -** pEList is the SET clause of an UPDATE statement. Each entry -** in pEList is of the format =. If any of the entries -** in pEList have an which matches an identifier in pIdList, -** then return TRUE. If pIdList==NULL, then it is considered a -** wildcard that matches anything. Likewise if pEList==NULL then -** it matches anything so always return true. Return false only -** if there is no match. -*/ -static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){ - int e; - if( pIdList==0 || NEVER(pEList==0) ) return 1; - for(e=0; enExpr; e++){ - if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; - } - return 0; -} - -/* -** Return a list of all triggers on table pTab if there exists at least -** one trigger that must be fired when an operation of type 'op' is -** performed on the table, and, if that operation is an UPDATE, if at -** least one of the columns in pChanges is being modified. -*/ -SQLITE_PRIVATE Trigger *sqlite3TriggersExist( - Parse *pParse, /* Parse context */ - Table *pTab, /* The table the contains the triggers */ - int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ - ExprList *pChanges, /* Columns that change in an UPDATE statement */ - int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ -){ - int mask = 0; - Trigger *pList = 0; - Trigger *p; - - if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){ - pList = sqlite3TriggerList(pParse, pTab); - } - assert( pList==0 || IsVirtual(pTab)==0 ); - for(p=pList; p; p=p->pNext){ - if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){ - mask |= p->tr_tm; - } - } - if( pMask ){ - *pMask = mask; - } - return (mask ? pList : 0); -} - -/* -** Convert the pStep->target token into a SrcList and return a pointer -** to that SrcList. -** -** This routine adds a specific database name, if needed, to the target when -** forming the SrcList. This prevents a trigger in one database from -** referring to a target in another database. An exception is when the -** trigger is in TEMP in which case it can refer to any other database it -** wants. -*/ -static SrcList *targetSrcList( - Parse *pParse, /* The parsing context */ - TriggerStep *pStep /* The trigger containing the target token */ -){ - int iDb; /* Index of the database to use */ - SrcList *pSrc; /* SrcList to be returned */ - - pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); - if( pSrc ){ - assert( pSrc->nSrc>0 ); - assert( pSrc->a!=0 ); - iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); - if( iDb==0 || iDb>=2 ){ - sqlite3 *db = pParse->db; - assert( iDbdb->nDb ); - pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); - } - } - return pSrc; -} - -/* -** Generate VDBE code for the statements inside the body of a single -** trigger. -*/ -static int codeTriggerProgram( - Parse *pParse, /* The parser context */ - TriggerStep *pStepList, /* List of statements inside the trigger body */ - int orconf /* Conflict algorithm. (OE_Abort, etc) */ -){ - TriggerStep *pStep; - Vdbe *v = pParse->pVdbe; - sqlite3 *db = pParse->db; - - assert( pParse->pTriggerTab && pParse->pToplevel ); - assert( pStepList ); - assert( v!=0 ); - for(pStep=pStepList; pStep; pStep=pStep->pNext){ - /* Figure out the ON CONFLICT policy that will be used for this step - ** of the trigger program. If the statement that caused this trigger - ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use - ** the ON CONFLICT policy that was specified as part of the trigger - ** step statement. Example: - ** - ** CREATE TRIGGER AFTER INSERT ON t1 BEGIN; - ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b); - ** END; - ** - ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy - ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy - */ - pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; - - /* Clear the cookieGoto flag. When coding triggers, the cookieGoto - ** variable is used as a flag to indicate to sqlite3ExprCodeConstants() - ** that it is not safe to refactor constants (this happens after the - ** start of the first loop in the SQL statement is coded - at that - ** point code may be conditionally executed, so it is no longer safe to - ** initialize constant register values). */ - assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 ); - pParse->cookieGoto = 0; - - switch( pStep->op ){ - case TK_UPDATE: { - sqlite3Update(pParse, - targetSrcList(pParse, pStep), - sqlite3ExprListDup(db, pStep->pExprList, 0), - sqlite3ExprDup(db, pStep->pWhere, 0), - pParse->eOrconf - ); - break; - } - case TK_INSERT: { - sqlite3Insert(pParse, - targetSrcList(pParse, pStep), - sqlite3ExprListDup(db, pStep->pExprList, 0), - sqlite3SelectDup(db, pStep->pSelect, 0), - sqlite3IdListDup(db, pStep->pIdList), - pParse->eOrconf - ); - break; - } - case TK_DELETE: { - sqlite3DeleteFrom(pParse, - targetSrcList(pParse, pStep), - sqlite3ExprDup(db, pStep->pWhere, 0) - ); - break; - } - default: assert( pStep->op==TK_SELECT ); { - SelectDest sDest; - Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0); - sqlite3SelectDestInit(&sDest, SRT_Discard, 0); - sqlite3Select(pParse, pSelect, &sDest); - sqlite3SelectDelete(db, pSelect); - break; - } - } - if( pStep->op!=TK_SELECT ){ - sqlite3VdbeAddOp0(v, OP_ResetCount); - } - } - - return 0; -} - -#ifdef SQLITE_DEBUG -/* -** This function is used to add VdbeComment() annotations to a VDBE -** program. It is not used in production code, only for debugging. -*/ -static const char *onErrorText(int onError){ - switch( onError ){ - case OE_Abort: return "abort"; - case OE_Rollback: return "rollback"; - case OE_Fail: return "fail"; - case OE_Replace: return "replace"; - case OE_Ignore: return "ignore"; - case OE_Default: return "default"; - } - return "n/a"; -} -#endif - -/* -** Parse context structure pFrom has just been used to create a sub-vdbe -** (trigger program). If an error has occurred, transfer error information -** from pFrom to pTo. -*/ -static void transferParseError(Parse *pTo, Parse *pFrom){ - assert( pFrom->zErrMsg==0 || pFrom->nErr ); - assert( pTo->zErrMsg==0 || pTo->nErr ); - if( pTo->nErr==0 ){ - pTo->zErrMsg = pFrom->zErrMsg; - pTo->nErr = pFrom->nErr; - }else{ - sqlite3DbFree(pFrom->db, pFrom->zErrMsg); - } -} - -/* -** Create and populate a new TriggerPrg object with a sub-program -** implementing trigger pTrigger with ON CONFLICT policy orconf. -*/ -static TriggerPrg *codeRowTrigger( - Parse *pParse, /* Current parse context */ - Trigger *pTrigger, /* Trigger to code */ - Table *pTab, /* The table pTrigger is attached to */ - int orconf /* ON CONFLICT policy to code trigger program with */ -){ - Parse *pTop = sqlite3ParseToplevel(pParse); - sqlite3 *db = pParse->db; /* Database handle */ - TriggerPrg *pPrg; /* Value to return */ - Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */ - Vdbe *v; /* Temporary VM */ - NameContext sNC; /* Name context for sub-vdbe */ - SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ - Parse *pSubParse; /* Parse context for sub-vdbe */ - int iEndTrigger = 0; /* Label to jump to if WHEN is false */ - - assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); - assert( pTop->pVdbe ); - - /* Allocate the TriggerPrg and SubProgram objects. To ensure that they - ** are freed if an error occurs, link them into the Parse.pTriggerPrg - ** list of the top-level Parse object sooner rather than later. */ - pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg)); - if( !pPrg ) return 0; - pPrg->pNext = pTop->pTriggerPrg; - pTop->pTriggerPrg = pPrg; - pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); - if( !pProgram ) return 0; - sqlite3VdbeLinkSubProgram(pTop->pVdbe, pProgram); - pPrg->pTrigger = pTrigger; - pPrg->orconf = orconf; - pPrg->aColmask[0] = 0xffffffff; - pPrg->aColmask[1] = 0xffffffff; - - /* Allocate and populate a new Parse context to use for coding the - ** trigger sub-program. */ - pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); - if( !pSubParse ) return 0; - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pSubParse; - pSubParse->db = db; - pSubParse->pTriggerTab = pTab; - pSubParse->pToplevel = pTop; - pSubParse->zAuthContext = pTrigger->zName; - pSubParse->eTriggerOp = pTrigger->op; - pSubParse->nQueryLoop = pParse->nQueryLoop; - - v = sqlite3GetVdbe(pSubParse); - if( v ){ - VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", - pTrigger->zName, onErrorText(orconf), - (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"), - (pTrigger->op==TK_UPDATE ? "UPDATE" : ""), - (pTrigger->op==TK_INSERT ? "INSERT" : ""), - (pTrigger->op==TK_DELETE ? "DELETE" : ""), - pTab->zName - )); -#ifndef SQLITE_OMIT_TRACE - sqlite3VdbeChangeP4(v, -1, - sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC - ); -#endif - - /* If one was specified, code the WHEN clause. If it evaluates to false - ** (or NULL) the sub-vdbe is immediately halted by jumping to the - ** OP_Halt inserted at the end of the program. */ - if( pTrigger->pWhen ){ - pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0); - if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) - && db->mallocFailed==0 - ){ - iEndTrigger = sqlite3VdbeMakeLabel(v); - sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); - } - sqlite3ExprDelete(db, pWhen); - } - - /* Code the trigger program into the sub-vdbe. */ - codeTriggerProgram(pSubParse, pTrigger->step_list, orconf); - - /* Insert an OP_Halt at the end of the sub-program. */ - if( iEndTrigger ){ - sqlite3VdbeResolveLabel(v, iEndTrigger); - } - sqlite3VdbeAddOp0(v, OP_Halt); - VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); - - transferParseError(pParse, pSubParse); - if( db->mallocFailed==0 ){ - pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); - } - pProgram->nMem = pSubParse->nMem; - pProgram->nCsr = pSubParse->nTab; - pProgram->nOnce = pSubParse->nOnce; - pProgram->token = (void *)pTrigger; - pPrg->aColmask[0] = pSubParse->oldmask; - pPrg->aColmask[1] = pSubParse->newmask; - sqlite3VdbeDelete(v); - } - - assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); - assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); - sqlite3StackFree(db, pSubParse); - - return pPrg; -} - -/* -** Return a pointer to a TriggerPrg object containing the sub-program for -** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such -** TriggerPrg object exists, a new object is allocated and populated before -** being returned. -*/ -static TriggerPrg *getRowTrigger( - Parse *pParse, /* Current parse context */ - Trigger *pTrigger, /* Trigger to code */ - Table *pTab, /* The table trigger pTrigger is attached to */ - int orconf /* ON CONFLICT algorithm. */ -){ - Parse *pRoot = sqlite3ParseToplevel(pParse); - TriggerPrg *pPrg; - - assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); - - /* It may be that this trigger has already been coded (or is in the - ** process of being coded). If this is the case, then an entry with - ** a matching TriggerPrg.pTrigger field will be present somewhere - ** in the Parse.pTriggerPrg list. Search for such an entry. */ - for(pPrg=pRoot->pTriggerPrg; - pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); - pPrg=pPrg->pNext - ); - - /* If an existing TriggerPrg could not be located, create a new one. */ - if( !pPrg ){ - pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf); - } - - return pPrg; -} - -/* -** Generate code for the trigger program associated with trigger p on -** table pTab. The reg, orconf and ignoreJump parameters passed to this -** function are the same as those described in the header function for -** sqlite3CodeRowTrigger() -*/ -SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect( - Parse *pParse, /* Parse context */ - Trigger *p, /* Trigger to code */ - Table *pTab, /* The table to code triggers from */ - int reg, /* Reg array containing OLD.* and NEW.* values */ - int orconf, /* ON CONFLICT policy */ - int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ -){ - Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ - TriggerPrg *pPrg; - pPrg = getRowTrigger(pParse, p, pTab, orconf); - assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); - - /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program - ** is a pointer to the sub-vdbe containing the trigger program. */ - if( pPrg ){ - int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers)); - - sqlite3VdbeAddOp3(v, OP_Program, reg, ignoreJump, ++pParse->nMem); - sqlite3VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM); - VdbeComment( - (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf))); - - /* Set the P5 operand of the OP_Program instruction to non-zero if - ** recursive invocation of this trigger program is disallowed. Recursive - ** invocation is disallowed if (a) the sub-program is really a trigger, - ** not a foreign key action, and (b) the flag to enable recursive triggers - ** is clear. */ - sqlite3VdbeChangeP5(v, (u8)bRecursive); - } -} - -/* -** This is called to code the required FOR EACH ROW triggers for an operation -** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE) -** is given by the op paramater. The tr_tm parameter determines whether the -** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then -** parameter pChanges is passed the list of columns being modified. -** -** If there are no triggers that fire at the specified time for the specified -** operation on pTab, this function is a no-op. -** -** The reg argument is the address of the first in an array of registers -** that contain the values substituted for the new.* and old.* references -** in the trigger program. If N is the number of columns in table pTab -** (a copy of pTab->nCol), then registers are populated as follows: -** -** Register Contains -** ------------------------------------------------------ -** reg+0 OLD.rowid -** reg+1 OLD.* value of left-most column of pTab -** ... ... -** reg+N OLD.* value of right-most column of pTab -** reg+N+1 NEW.rowid -** reg+N+2 OLD.* value of left-most column of pTab -** ... ... -** reg+N+N+1 NEW.* value of right-most column of pTab -** -** For ON DELETE triggers, the registers containing the NEW.* values will -** never be accessed by the trigger program, so they are not allocated or -** populated by the caller (there is no data to populate them with anyway). -** Similarly, for ON INSERT triggers the values stored in the OLD.* registers -** are never accessed, and so are not allocated by the caller. So, for an -** ON INSERT trigger, the value passed to this function as parameter reg -** is not a readable register, although registers (reg+N) through -** (reg+N+N+1) are. -** -** Parameter orconf is the default conflict resolution algorithm for the -** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump -** is the instruction that control should jump to if a trigger program -** raises an IGNORE exception. -*/ -SQLITE_PRIVATE void sqlite3CodeRowTrigger( - Parse *pParse, /* Parse context */ - Trigger *pTrigger, /* List of triggers on table pTab */ - int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ - ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ - int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ - Table *pTab, /* The table to code triggers from */ - int reg, /* The first in an array of registers (see above) */ - int orconf, /* ON CONFLICT policy */ - int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ -){ - Trigger *p; /* Used to iterate through pTrigger list */ - - assert( op==TK_UPDATE || op==TK_INSERT || op==TK_DELETE ); - assert( tr_tm==TRIGGER_BEFORE || tr_tm==TRIGGER_AFTER ); - assert( (op==TK_UPDATE)==(pChanges!=0) ); - - for(p=pTrigger; p; p=p->pNext){ - - /* Sanity checking: The schema for the trigger and for the table are - ** always defined. The trigger must be in the same schema as the table - ** or else it must be a TEMP trigger. */ - assert( p->pSchema!=0 ); - assert( p->pTabSchema!=0 ); - assert( p->pSchema==p->pTabSchema - || p->pSchema==pParse->db->aDb[1].pSchema ); - - /* Determine whether we should code this trigger */ - if( p->op==op - && p->tr_tm==tr_tm - && checkColumnOverlap(p->pColumns, pChanges) - ){ - sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump); - } - } -} - -/* -** Triggers may access values stored in the old.* or new.* pseudo-table. -** This function returns a 32-bit bitmask indicating which columns of the -** old.* or new.* tables actually are used by triggers. This information -** may be used by the caller, for example, to avoid having to load the entire -** old.* record into memory when executing an UPDATE or DELETE command. -** -** Bit 0 of the returned mask is set if the left-most column of the -** table may be accessed using an [old|new].reference. Bit 1 is set if -** the second leftmost column value is required, and so on. If there -** are more than 32 columns in the table, and at least one of the columns -** with an index greater than 32 may be accessed, 0xffffffff is returned. -** -** It is not possible to determine if the old.rowid or new.rowid column is -** accessed by triggers. The caller must always assume that it is. -** -** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned -** applies to the old.* table. If 1, the new.* table. -** -** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE -** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only -** included in the returned mask if the TRIGGER_BEFORE bit is set in the -** tr_tm parameter. Similarly, values accessed by AFTER triggers are only -** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm. -*/ -SQLITE_PRIVATE u32 sqlite3TriggerColmask( - Parse *pParse, /* Parse context */ - Trigger *pTrigger, /* List of triggers on table pTab */ - ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ - int isNew, /* 1 for new.* ref mask, 0 for old.* ref mask */ - int tr_tm, /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ - Table *pTab, /* The table to code triggers from */ - int orconf /* Default ON CONFLICT policy for trigger steps */ -){ - const int op = pChanges ? TK_UPDATE : TK_DELETE; - u32 mask = 0; - Trigger *p; - - assert( isNew==1 || isNew==0 ); - for(p=pTrigger; p; p=p->pNext){ - if( p->op==op && (tr_tm&p->tr_tm) - && checkColumnOverlap(p->pColumns,pChanges) - ){ - TriggerPrg *pPrg; - pPrg = getRowTrigger(pParse, p, pTab, orconf); - if( pPrg ){ - mask |= pPrg->aColmask[isNew]; - } - } - } - - return mask; -} - -#endif /* !defined(SQLITE_OMIT_TRIGGER) */ - -/************** End of trigger.c *********************************************/ -/************** Begin file update.c ******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains C code routines that are called by the parser -** to handle UPDATE statements. -*/ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* Forward declaration */ -static void updateVirtualTable( - Parse *pParse, /* The parsing context */ - SrcList *pSrc, /* The virtual table to be modified */ - Table *pTab, /* The virtual table */ - ExprList *pChanges, /* The columns to change in the UPDATE statement */ - Expr *pRowidExpr, /* Expression used to recompute the rowid */ - int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ - Expr *pWhere, /* WHERE clause of the UPDATE statement */ - int onError /* ON CONFLICT strategy */ -); -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/* -** The most recently coded instruction was an OP_Column to retrieve the -** i-th column of table pTab. This routine sets the P4 parameter of the -** OP_Column to the default value, if any. -** -** The default value of a column is specified by a DEFAULT clause in the -** column definition. This was either supplied by the user when the table -** was created, or added later to the table definition by an ALTER TABLE -** command. If the latter, then the row-records in the table btree on disk -** may not contain a value for the column and the default value, taken -** from the P4 parameter of the OP_Column instruction, is returned instead. -** If the former, then all row-records are guaranteed to include a value -** for the column and the P4 value is not required. -** -** Column definitions created by an ALTER TABLE command may only have -** literal default values specified: a number, null or a string. (If a more -** complicated default expression value was provided, it is evaluated -** when the ALTER TABLE is executed and one of the literal values written -** into the sqlite_master table.) -** -** Therefore, the P4 parameter is only required if the default value for -** the column is a literal number, string or null. The sqlite3ValueFromExpr() -** function is capable of transforming these types of expressions into -** sqlite3_value objects. -** -** If parameter iReg is not negative, code an OP_RealAffinity instruction -** on register iReg. This is used when an equivalent integer value is -** stored in place of an 8-byte floating point value in order to save -** space. -*/ -SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ - assert( pTab!=0 ); - if( !pTab->pSelect ){ - sqlite3_value *pValue; - u8 enc = ENC(sqlite3VdbeDb(v)); - Column *pCol = &pTab->aCol[i]; - VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); - assert( inCol ); - sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, - pCol->affinity, &pValue); - if( pValue ){ - sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM); - } -#ifndef SQLITE_OMIT_FLOATING_POINT - if( iReg>=0 && pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); - } -#endif - } -} - -/* -** Process an UPDATE statement. -** -** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; -** \_______/ \________/ \______/ \________________/ -* onError pTabList pChanges pWhere -*/ -SQLITE_PRIVATE void sqlite3Update( - Parse *pParse, /* The parser context */ - SrcList *pTabList, /* The table in which we should change things */ - ExprList *pChanges, /* Things to be changed */ - Expr *pWhere, /* The WHERE clause. May be null */ - int onError /* How to handle constraint errors */ -){ - int i, j; /* Loop counters */ - Table *pTab; /* The table to be updated */ - int addr = 0; /* VDBE instruction address of the start of the loop */ - WhereInfo *pWInfo; /* Information about the WHERE clause */ - Vdbe *v; /* The virtual database engine */ - Index *pIdx; /* For looping over indices */ - int nIdx; /* Number of indices that need updating */ - int iCur; /* VDBE Cursor number of pTab */ - sqlite3 *db; /* The database structure */ - int *aRegIdx = 0; /* One register assigned to each index to be updated */ - int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the - ** an expression for the i-th column of the table. - ** aXRef[i]==-1 if the i-th column is not changed. */ - int chngRowid; /* True if the record number is being changed */ - Expr *pRowidExpr = 0; /* Expression defining the new record number */ - int openAll = 0; /* True if all indices need to be opened */ - AuthContext sContext; /* The authorization context */ - NameContext sNC; /* The name-context to resolve expressions in */ - int iDb; /* Database containing the table being updated */ - int okOnePass; /* True for one-pass algorithm without the FIFO */ - int hasFK; /* True if foreign key processing is required */ - -#ifndef SQLITE_OMIT_TRIGGER - int isView; /* True when updating a view (INSTEAD OF trigger) */ - Trigger *pTrigger; /* List of triggers on pTab, if required */ - int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ -#endif - int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ - - /* Register Allocations */ - int regRowCount = 0; /* A count of rows changed */ - int regOldRowid; /* The old rowid */ - int regNewRowid; /* The new rowid */ - int regNew; /* Content of the NEW.* table in triggers */ - int regOld = 0; /* Content of OLD.* table in triggers */ - int regRowSet = 0; /* Rowset of rows to be updated */ - - memset(&sContext, 0, sizeof(sContext)); - db = pParse->db; - if( pParse->nErr || db->mallocFailed ){ - goto update_cleanup; - } - assert( pTabList->nSrc==1 ); - - /* Locate the table which we want to update. - */ - pTab = sqlite3SrcListLookup(pParse, pTabList); - if( pTab==0 ) goto update_cleanup; - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - - /* Figure out if we have any triggers and if the table being - ** updated is a view. - */ -#ifndef SQLITE_OMIT_TRIGGER - pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); - isView = pTab->pSelect!=0; - assert( pTrigger || tmask==0 ); -#else -# define pTrigger 0 -# define isView 0 -# define tmask 0 -#endif -#ifdef SQLITE_OMIT_VIEW -# undef isView -# define isView 0 -#endif - - if( sqlite3ViewGetColumnNames(pParse, pTab) ){ - goto update_cleanup; - } - if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ - goto update_cleanup; - } - aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); - if( aXRef==0 ) goto update_cleanup; - for(i=0; inCol; i++) aXRef[i] = -1; - - /* Allocate a cursors for the main database table and for all indices. - ** The index cursors might not be used, but if they are used they - ** need to occur right after the database cursor. So go ahead and - ** allocate enough space, just in case. - */ - pTabList->a[0].iCursor = iCur = pParse->nTab++; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - pParse->nTab++; - } - - /* Initialize the name-context */ - memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pParse; - sNC.pSrcList = pTabList; - - /* Resolve the column names in all the expressions of the - ** of the UPDATE statement. Also find the column index - ** for each column to be updated in the pChanges array. For each - ** column to be updated, make sure we have authorization to change - ** that column. - */ - chngRowid = 0; - for(i=0; inExpr; i++){ - if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){ - goto update_cleanup; - } - for(j=0; jnCol; j++){ - if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){ - if( j==pTab->iPKey ){ - chngRowid = 1; - pRowidExpr = pChanges->a[i].pExpr; - } - aXRef[j] = i; - break; - } - } - if( j>=pTab->nCol ){ - if( sqlite3IsRowid(pChanges->a[i].zName) ){ - j = -1; - chngRowid = 1; - pRowidExpr = pChanges->a[i].pExpr; - }else{ - sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); - pParse->checkSchema = 1; - goto update_cleanup; - } - } -#ifndef SQLITE_OMIT_AUTHORIZATION - { - int rc; - rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, - j<0 ? "ROWID" : pTab->aCol[j].zName, - db->aDb[iDb].zName); - if( rc==SQLITE_DENY ){ - goto update_cleanup; - }else if( rc==SQLITE_IGNORE ){ - aXRef[j] = -1; - } - } -#endif - } - - hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngRowid); - - /* Allocate memory for the array aRegIdx[]. There is one entry in the - ** array for each index associated with table being updated. Fill in - ** the value with a register number for indices that are to be used - ** and with zero for unused indices. - */ - for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} - if( nIdx>0 ){ - aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx ); - if( aRegIdx==0 ) goto update_cleanup; - } - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - int reg; - if( hasFK || chngRowid ){ - reg = ++pParse->nMem; - }else{ - reg = 0; - for(i=0; inColumn; i++){ - if( aXRef[pIdx->aiColumn[i]]>=0 ){ - reg = ++pParse->nMem; - break; - } - } - } - aRegIdx[j] = reg; - } - - /* Begin generating code. */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto update_cleanup; - if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, 1, iDb); - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Virtual tables must be handled separately */ - if( IsVirtual(pTab) ){ - updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, - pWhere, onError); - pWhere = 0; - pTabList = 0; - goto update_cleanup; - } -#endif - - /* Allocate required registers. */ - regRowSet = ++pParse->nMem; - regOldRowid = regNewRowid = ++pParse->nMem; - if( pTrigger || hasFK ){ - regOld = pParse->nMem + 1; - pParse->nMem += pTab->nCol; - } - if( chngRowid || pTrigger || hasFK ){ - regNewRowid = ++pParse->nMem; - } - regNew = pParse->nMem + 1; - pParse->nMem += pTab->nCol; - - /* Start the view context. */ - if( isView ){ - sqlite3AuthContextPush(pParse, &sContext, pTab->zName); - } - - /* If we are trying to update a view, realize that view into - ** a ephemeral table. - */ -#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) - if( isView ){ - sqlite3MaterializeView(pParse, pTab, pWhere, iCur); - } -#endif - - /* Resolve the column names in all the expressions in the - ** WHERE clause. - */ - if( sqlite3ResolveExprNames(&sNC, pWhere) ){ - goto update_cleanup; - } - - /* Begin the database scan - */ - sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); - pWInfo = sqlite3WhereBegin( - pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0 - ); - if( pWInfo==0 ) goto update_cleanup; - okOnePass = pWInfo->okOnePass; - - /* Remember the rowid of every item to be updated. - */ - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid); - if( !okOnePass ){ - sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); - } - - /* End the database scan loop. - */ - sqlite3WhereEnd(pWInfo); - - /* Initialize the count of updated rows - */ - if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ - regRowCount = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); - } - - if( !isView ){ - /* - ** Open every index that needs updating. Note that if any - ** index could potentially invoke a REPLACE conflict resolution - ** action, then we need to open all indices because we might need - ** to be deleting some records. - */ - if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); - if( onError==OE_Replace ){ - openAll = 1; - }else{ - openAll = 0; - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->onError==OE_Replace ){ - openAll = 1; - break; - } - } - } - for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - assert( aRegIdx ); - if( openAll || aRegIdx[i]>0 ){ - KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); - sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb, - (char*)pKey, P4_KEYINFO_HANDOFF); - assert( pParse->nTab>iCur+i+1 ); - } - } - } - - /* Top of the update loop */ - if( okOnePass ){ - int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid); - addr = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, a1); - }else{ - addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid); - } - - /* Make cursor iCur point to the record that is being updated. If - ** this record does not exist for some reason (deleted by a trigger, - ** for example, then jump to the next iteration of the RowSet loop. */ - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); - - /* If the record number will change, set register regNewRowid to - ** contain the new value. If the record number is not being modified, - ** then regNewRowid is the same register as regOldRowid, which is - ** already populated. */ - assert( chngRowid || pTrigger || hasFK || regOldRowid==regNewRowid ); - if( chngRowid ){ - sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); - sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); - } - - /* If there are triggers on this table, populate an array of registers - ** with the required old.* column data. */ - if( hasFK || pTrigger ){ - u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0); - oldmask |= sqlite3TriggerColmask(pParse, - pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError - ); - for(i=0; inCol; i++){ - if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<nCol-1); - for(i=0; inCol; i++){ - if( i==pTab->iPKey ){ - /*sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);*/ - }else{ - j = aXRef[i]; - if( j>=0 ){ - sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); - }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<nCol); - sqlite3TableAffinityStr(v, pTab); - sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_BEFORE, pTab, regOldRowid, onError, addr); - - /* The row-trigger may have deleted the row being updated. In this - ** case, jump to the next row. No updates or AFTER triggers are - ** required. This behavior - what happens when the row being updated - ** is deleted or renamed by a BEFORE trigger - is left undefined in the - ** documentation. - */ - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); - - /* If it did not delete it, the row-trigger may still have modified - ** some of the columns of the row being updated. Load the values for - ** all columns not modified by the update statement into their - ** registers in case this has happened. - */ - for(i=0; inCol; i++){ - if( aXRef[i]<0 && i!=pTab->iPKey ){ - sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); - sqlite3ColumnDefault(v, pTab, i, regNew+i); - } - } - } - - if( !isView ){ - int j1; /* Address of jump instruction */ - - /* Do constraint checks. */ - sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid, - aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0); - - /* Do FK constraint checks. */ - if( hasFK ){ - sqlite3FkCheck(pParse, pTab, regOldRowid, 0); - } - - /* Delete the index entries associated with the current record. */ - j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid); - sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx); - - /* If changing the record number, delete the old record. */ - if( hasFK || chngRowid ){ - sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0); - } - sqlite3VdbeJumpHere(v, j1); - - if( hasFK ){ - sqlite3FkCheck(pParse, pTab, 0, regNewRowid); - } - - /* Insert the new index entries and the new record. */ - sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0); - - /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to - ** handle rows (possibly in other tables) that refer via a foreign key - ** to the row just updated. */ - if( hasFK ){ - sqlite3FkActions(pParse, pTab, pChanges, regOldRowid); - } - } - - /* Increment the row counter - */ - if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ - sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); - } - - sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, - TRIGGER_AFTER, pTab, regOldRowid, onError, addr); - - /* Repeat the above with the next record to be updated, until - ** all record selected by the WHERE clause have been updated. - */ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); - sqlite3VdbeJumpHere(v, addr); - - /* Close all tables */ - for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - assert( aRegIdx ); - if( openAll || aRegIdx[i]>0 ){ - sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0); - } - } - sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); - - /* Update the sqlite_sequence table by storing the content of the - ** maximum rowid counter values recorded while inserting into - ** autoincrement tables. - */ - if( pParse->nested==0 && pParse->pTriggerTab==0 ){ - sqlite3AutoincrementEnd(pParse); - } - - /* - ** Return the number of rows that were changed. If this routine is - ** generating code because of a call to sqlite3NestedParse(), do not - ** invoke the callback function. - */ - if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){ - sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); - } - -update_cleanup: - sqlite3AuthContextPop(&sContext); - sqlite3DbFree(db, aRegIdx); - sqlite3DbFree(db, aXRef); - sqlite3SrcListDelete(db, pTabList); - sqlite3ExprListDelete(db, pChanges); - sqlite3ExprDelete(db, pWhere); - return; -} -/* Make sure "isView" and other macros defined above are undefined. Otherwise -** thely may interfere with compilation of other functions in this file -** (or in another file, if this file becomes part of the amalgamation). */ -#ifdef isView - #undef isView -#endif -#ifdef pTrigger - #undef pTrigger -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Generate code for an UPDATE of a virtual table. -** -** The strategy is that we create an ephemerial table that contains -** for each row to be changed: -** -** (A) The original rowid of that row. -** (B) The revised rowid for the row. (note1) -** (C) The content of every column in the row. -** -** Then we loop over this ephemeral table and for each row in -** the ephermeral table call VUpdate. -** -** When finished, drop the ephemeral table. -** -** (note1) Actually, if we know in advance that (A) is always the same -** as (B) we only store (A), then duplicate (A) when pulling -** it out of the ephemeral table before calling VUpdate. -*/ -static void updateVirtualTable( - Parse *pParse, /* The parsing context */ - SrcList *pSrc, /* The virtual table to be modified */ - Table *pTab, /* The virtual table */ - ExprList *pChanges, /* The columns to change in the UPDATE statement */ - Expr *pRowid, /* Expression used to recompute the rowid */ - int *aXRef, /* Mapping from columns of pTab to entries in pChanges */ - Expr *pWhere, /* WHERE clause of the UPDATE statement */ - int onError /* ON CONFLICT strategy */ -){ - Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */ - ExprList *pEList = 0; /* The result set of the SELECT statement */ - Select *pSelect = 0; /* The SELECT statement */ - Expr *pExpr; /* Temporary expression */ - int ephemTab; /* Table holding the result of the SELECT */ - int i; /* Loop counter */ - int addr; /* Address of top of loop */ - int iReg; /* First register in set passed to OP_VUpdate */ - sqlite3 *db = pParse->db; /* Database connection */ - const char *pVTab = (const char*)sqlite3GetVTable(db, pTab); - SelectDest dest; - - /* Construct the SELECT statement that will find the new values for - ** all updated rows. - */ - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_")); - if( pRowid ){ - pEList = sqlite3ExprListAppend(pParse, pEList, - sqlite3ExprDup(db, pRowid, 0)); - } - assert( pTab->iPKey<0 ); - for(i=0; inCol; i++){ - if( aXRef[i]>=0 ){ - pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0); - }else{ - pExpr = sqlite3Expr(db, TK_ID, pTab->aCol[i].zName); - } - pEList = sqlite3ExprListAppend(pParse, pEList, pExpr); - } - pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0); - - /* Create the ephemeral table into which the update results will - ** be stored. - */ - assert( v ); - ephemTab = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0)); - sqlite3VdbeChangeP5(v, BTREE_UNORDERED); - - /* fill the ephemeral table - */ - sqlite3SelectDestInit(&dest, SRT_Table, ephemTab); - sqlite3Select(pParse, pSelect, &dest); - - /* Generate code to scan the ephemeral table and call VUpdate. */ - iReg = ++pParse->nMem; - pParse->nMem += pTab->nCol+1; - addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, 0, iReg); - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1); - for(i=0; inCol; i++){ - sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i); - } - sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); - sqlite3MayAbort(pParse); - sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); - sqlite3VdbeJumpHere(v, addr); - sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); - - /* Cleanup */ - sqlite3SelectDelete(db, pSelect); -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/************** End of update.c **********************************************/ -/************** Begin file vacuum.c ******************************************/ -/* -** 2003 April 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to implement the VACUUM command. -** -** Most of the code in this file may be omitted by defining the -** SQLITE_OMIT_VACUUM macro. -*/ - -#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) -/* -** Finalize a prepared statement. If there was an error, store the -** text of the error message in *pzErrMsg. Return the result code. -*/ -static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){ - int rc; - rc = sqlite3VdbeFinalize((Vdbe*)pStmt); - if( rc ){ - sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); - } - return rc; -} - -/* -** Execute zSql on database db. Return an error code. -*/ -static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ - sqlite3_stmt *pStmt; - VVA_ONLY( int rc; ) - if( !zSql ){ - return SQLITE_NOMEM; - } - if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ - sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db)); - return sqlite3_errcode(db); - } - VVA_ONLY( rc = ) sqlite3_step(pStmt); - assert( rc!=SQLITE_ROW || (db->flags&SQLITE_CountRows) ); - return vacuumFinalize(db, pStmt, pzErrMsg); -} - -/* -** Execute zSql on database db. The statement returns exactly -** one column. Execute this as SQL on the same database. -*/ -static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ - sqlite3_stmt *pStmt; - int rc; - - rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0)); - if( rc!=SQLITE_OK ){ - vacuumFinalize(db, pStmt, pzErrMsg); - return rc; - } - } - - return vacuumFinalize(db, pStmt, pzErrMsg); -} - -/* -** The non-standard VACUUM command is used to clean up the database, -** collapse free space, etc. It is modelled after the VACUUM command -** in PostgreSQL. -** -** In version 1.0.x of SQLite, the VACUUM command would call -** gdbm_reorganize() on all the database tables. But beginning -** with 2.0.0, SQLite no longer uses GDBM so this command has -** become a no-op. -*/ -SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){ - Vdbe *v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); - sqlite3VdbeUsesBtree(v, 0); - } - return; -} - -/* -** This routine implements the OP_Vacuum opcode of the VDBE. -*/ -SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ - int rc = SQLITE_OK; /* Return code from service routines */ - Btree *pMain; /* The database being vacuumed */ - Btree *pTemp; /* The temporary database we vacuum into */ - char *zSql = 0; /* SQL statements */ - int saved_flags; /* Saved value of the db->flags */ - int saved_nChange; /* Saved value of db->nChange */ - int saved_nTotalChange; /* Saved value of db->nTotalChange */ - void (*saved_xTrace)(void*,const char*); /* Saved db->xTrace */ - Db *pDb = 0; /* Database to detach at end of vacuum */ - int isMemDb; /* True if vacuuming a :memory: database */ - int nRes; /* Bytes of reserved space at the end of each page */ - int nDb; /* Number of attached databases */ - - if( !db->autoCommit ){ - sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); - return SQLITE_ERROR; - } - if( db->activeVdbeCnt>1 ){ - sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress"); - return SQLITE_ERROR; - } - - /* Save the current value of the database flags so that it can be - ** restored before returning. Then set the writable-schema flag, and - ** disable CHECK and foreign key constraints. */ - saved_flags = db->flags; - saved_nChange = db->nChange; - saved_nTotalChange = db->nTotalChange; - saved_xTrace = db->xTrace; - db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin; - db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); - db->xTrace = 0; - - pMain = db->aDb[0].pBt; - isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); - - /* Attach the temporary database as 'vacuum_db'. The synchronous pragma - ** can be set to 'off' for this file, as it is not recovered if a crash - ** occurs anyway. The integrity of the database is maintained by a - ** (possibly synchronous) transaction opened on the main database before - ** sqlite3BtreeCopyFile() is called. - ** - ** An optimisation would be to use a non-journaled pager. - ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but - ** that actually made the VACUUM run slower. Very little journalling - ** actually occurs when doing a vacuum since the vacuum_db is initially - ** empty. Only the journal header is written. Apparently it takes more - ** time to parse and run the PRAGMA to turn journalling off than it does - ** to write the journal header file. - */ - nDb = db->nDb; - if( sqlite3TempInMemory(db) ){ - zSql = "ATTACH ':memory:' AS vacuum_db;"; - }else{ - zSql = "ATTACH '' AS vacuum_db;"; - } - rc = execSql(db, pzErrMsg, zSql); - if( db->nDb>nDb ){ - pDb = &db->aDb[db->nDb-1]; - assert( strcmp(pDb->zName,"vacuum_db")==0 ); - } - if( rc!=SQLITE_OK ) goto end_of_vacuum; - pTemp = db->aDb[db->nDb-1].pBt; - - /* The call to execSql() to attach the temp database has left the file - ** locked (as there was more than one active statement when the transaction - ** to read the schema was concluded. Unlock it here so that this doesn't - ** cause problems for the call to BtreeSetPageSize() below. */ - sqlite3BtreeCommit(pTemp); - - nRes = sqlite3BtreeGetReserve(pMain); - - /* A VACUUM cannot change the pagesize of an encrypted database. */ -#ifdef SQLITE_HAS_CODEC - if( db->nextPagesize ){ - extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); - int nKey; - char *zKey; - sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - if( nKey ) db->nextPagesize = 0; - } -#endif - - rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - /* Begin a transaction and take an exclusive lock on the main database - ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, - ** to ensure that we do not try to change the page-size on a WAL database. - */ - rc = execSql(db, pzErrMsg, "BEGIN;"); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = sqlite3BtreeBeginTrans(pMain, 2); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - /* Do not attempt to change the page size for a WAL database */ - if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) - ==PAGER_JOURNALMODE_WAL ){ - db->nextPagesize = 0; - } - - if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0) - || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0)) - || NEVER(db->mallocFailed) - ){ - rc = SQLITE_NOMEM; - goto end_of_vacuum; - } - -#ifndef SQLITE_OMIT_AUTOVACUUM - sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : - sqlite3BtreeGetAutoVacuum(pMain)); -#endif - - /* Query the schema of the main database. Create a mirror schema - ** in the temporary database. - */ - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " - " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" - " AND rootpage>0" - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" - " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " - " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - /* Loop through the tables in the main database. For each, do - ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy - ** the contents to the temporary database. - */ - rc = execExecSql(db, pzErrMsg, - "SELECT 'INSERT INTO vacuum_db.' || quote(name) " - "|| ' SELECT * FROM main.' || quote(name) || ';'" - "FROM main.sqlite_master " - "WHERE type = 'table' AND name!='sqlite_sequence' " - " AND rootpage>0" - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - /* Copy over the sequence table - */ - rc = execExecSql(db, pzErrMsg, - "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " - "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, pzErrMsg, - "SELECT 'INSERT INTO vacuum_db.' || quote(name) " - "|| ' SELECT * FROM main.' || quote(name) || ';' " - "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - - - /* Copy the triggers, views, and virtual tables from the main database - ** over to the temporary database. None of these objects has any - ** associated storage, so all we have to do is copy their entries - ** from the SQLITE_MASTER table. - */ - rc = execSql(db, pzErrMsg, - "INSERT INTO vacuum_db.sqlite_master " - " SELECT type, name, tbl_name, rootpage, sql" - " FROM main.sqlite_master" - " WHERE type='view' OR type='trigger'" - " OR (type='table' AND rootpage=0)" - ); - if( rc ) goto end_of_vacuum; - - /* At this point, there is a write transaction open on both the - ** vacuum database and the main database. Assuming no error occurs, - ** both transactions are closed by this block - the main database - ** transaction by sqlite3BtreeCopyFile() and the other by an explicit - ** call to sqlite3BtreeCommit(). - */ - { - u32 meta; - int i; - - /* This array determines which meta meta values are preserved in the - ** vacuum. Even entries are the meta value number and odd entries - ** are an increment to apply to the meta value after the vacuum. - ** The increment is used to increase the schema cookie so that other - ** connections to the same database will know to reread the schema. - */ - static const unsigned char aCopy[] = { - BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ - BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ - BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ - BTREE_USER_VERSION, 0, /* Preserve the user version */ - BTREE_APPLICATION_ID, 0, /* Preserve the application id */ - }; - - assert( 1==sqlite3BtreeIsInTrans(pTemp) ); - assert( 1==sqlite3BtreeIsInTrans(pMain) ); - - /* Copy Btree meta values */ - for(i=0; iflags */ - db->flags = saved_flags; - db->nChange = saved_nChange; - db->nTotalChange = saved_nTotalChange; - db->xTrace = saved_xTrace; - sqlite3BtreeSetPageSize(pMain, -1, -1, 1); - - /* Currently there is an SQL level transaction open on the vacuum - ** database. No locks are held on any other files (since the main file - ** was committed at the btree level). So it safe to end the transaction - ** by manually setting the autoCommit flag to true and detaching the - ** vacuum database. The vacuum_db journal file is deleted when the pager - ** is closed by the DETACH. - */ - db->autoCommit = 1; - - if( pDb ){ - sqlite3BtreeClose(pDb->pBt); - pDb->pBt = 0; - pDb->pSchema = 0; - } - - /* This both clears the schemas and reduces the size of the db->aDb[] - ** array. */ - sqlite3ResetAllSchemasOfConnection(db); - - return rc; -} - -#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ - -/************** End of vacuum.c **********************************************/ -/************** Begin file vtab.c ********************************************/ -/* -** 2006 June 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code used to help implement virtual tables. -*/ -#ifndef SQLITE_OMIT_VIRTUALTABLE - -/* -** Before a virtual table xCreate() or xConnect() method is invoked, the -** sqlite3.pVtabCtx member variable is set to point to an instance of -** this struct allocated on the stack. It is used by the implementation of -** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which -** are invoked only from within xCreate and xConnect methods. -*/ -struct VtabCtx { - VTable *pVTable; /* The virtual table being constructed */ - Table *pTab; /* The Table object to which the virtual table belongs */ -}; - -/* -** The actual function that does the work of creating a new module. -** This function implements the sqlite3_create_module() and -** sqlite3_create_module_v2() interfaces. -*/ -static int createModule( - sqlite3 *db, /* Database in which module is registered */ - const char *zName, /* Name assigned to this module */ - const sqlite3_module *pModule, /* The definition of the module */ - void *pAux, /* Context pointer for xCreate/xConnect */ - void (*xDestroy)(void *) /* Module destructor function */ -){ - int rc = SQLITE_OK; - int nName; - - sqlite3_mutex_enter(db->mutex); - nName = sqlite3Strlen30(zName); - if( sqlite3HashFind(&db->aModule, zName, nName) ){ - rc = SQLITE_MISUSE_BKPT; - }else{ - Module *pMod; - pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); - if( pMod ){ - Module *pDel; - char *zCopy = (char *)(&pMod[1]); - memcpy(zCopy, zName, nName+1); - pMod->zName = zCopy; - pMod->pModule = pModule; - pMod->pAux = pAux; - pMod->xDestroy = xDestroy; - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod); - assert( pDel==0 || pDel==pMod ); - if( pDel ){ - db->mallocFailed = 1; - sqlite3DbFree(db, pDel); - } - } - } - rc = sqlite3ApiExit(db, rc); - if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); - - sqlite3_mutex_leave(db->mutex); - return rc; -} - - -/* -** External API function used to create a new virtual-table module. -*/ -SQLITE_API int sqlite3_create_module( - sqlite3 *db, /* Database in which module is registered */ - const char *zName, /* Name assigned to this module */ - const sqlite3_module *pModule, /* The definition of the module */ - void *pAux /* Context pointer for xCreate/xConnect */ -){ - return createModule(db, zName, pModule, pAux, 0); -} - -/* -** External API function used to create a new virtual-table module. -*/ -SQLITE_API int sqlite3_create_module_v2( - sqlite3 *db, /* Database in which module is registered */ - const char *zName, /* Name assigned to this module */ - const sqlite3_module *pModule, /* The definition of the module */ - void *pAux, /* Context pointer for xCreate/xConnect */ - void (*xDestroy)(void *) /* Module destructor function */ -){ - return createModule(db, zName, pModule, pAux, xDestroy); -} - -/* -** Lock the virtual table so that it cannot be disconnected. -** Locks nest. Every lock should have a corresponding unlock. -** If an unlock is omitted, resources leaks will occur. -** -** If a disconnect is attempted while a virtual table is locked, -** the disconnect is deferred until all locks have been removed. -*/ -SQLITE_PRIVATE void sqlite3VtabLock(VTable *pVTab){ - pVTab->nRef++; -} - - -/* -** pTab is a pointer to a Table structure representing a virtual-table. -** Return a pointer to the VTable object used by connection db to access -** this virtual-table, if one has been created, or NULL otherwise. -*/ -SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){ - VTable *pVtab; - assert( IsVirtual(pTab) ); - for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); - return pVtab; -} - -/* -** Decrement the ref-count on a virtual table object. When the ref-count -** reaches zero, call the xDisconnect() method to delete the object. -*/ -SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *pVTab){ - sqlite3 *db = pVTab->db; - - assert( db ); - assert( pVTab->nRef>0 ); - assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE ); - - pVTab->nRef--; - if( pVTab->nRef==0 ){ - sqlite3_vtab *p = pVTab->pVtab; - if( p ){ - p->pModule->xDisconnect(p); - } - sqlite3DbFree(db, pVTab); - } -} - -/* -** Table p is a virtual table. This function moves all elements in the -** p->pVTable list to the sqlite3.pDisconnect lists of their associated -** database connections to be disconnected at the next opportunity. -** Except, if argument db is not NULL, then the entry associated with -** connection db is left in the p->pVTable list. -*/ -static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ - VTable *pRet = 0; - VTable *pVTable = p->pVTable; - p->pVTable = 0; - - /* Assert that the mutex (if any) associated with the BtShared database - ** that contains table p is held by the caller. See header comments - ** above function sqlite3VtabUnlockList() for an explanation of why - ** this makes it safe to access the sqlite3.pDisconnect list of any - ** database connection that may have an entry in the p->pVTable list. - */ - assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); - - while( pVTable ){ - sqlite3 *db2 = pVTable->db; - VTable *pNext = pVTable->pNext; - assert( db2 ); - if( db2==db ){ - pRet = pVTable; - p->pVTable = pRet; - pRet->pNext = 0; - }else{ - pVTable->pNext = db2->pDisconnect; - db2->pDisconnect = pVTable; - } - pVTable = pNext; - } - - assert( !db || pRet ); - return pRet; -} - -/* -** Table *p is a virtual table. This function removes the VTable object -** for table *p associated with database connection db from the linked -** list in p->pVTab. It also decrements the VTable ref count. This is -** used when closing database connection db to free all of its VTable -** objects without disturbing the rest of the Schema object (which may -** be being used by other shared-cache connections). -*/ -SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){ - VTable **ppVTab; - - assert( IsVirtual(p) ); - assert( sqlite3BtreeHoldsAllMutexes(db) ); - assert( sqlite3_mutex_held(db->mutex) ); - - for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){ - if( (*ppVTab)->db==db ){ - VTable *pVTab = *ppVTab; - *ppVTab = pVTab->pNext; - sqlite3VtabUnlock(pVTab); - break; - } - } -} - - -/* -** Disconnect all the virtual table objects in the sqlite3.pDisconnect list. -** -** This function may only be called when the mutexes associated with all -** shared b-tree databases opened using connection db are held by the -** caller. This is done to protect the sqlite3.pDisconnect list. The -** sqlite3.pDisconnect list is accessed only as follows: -** -** 1) By this function. In this case, all BtShared mutexes and the mutex -** associated with the database handle itself must be held. -** -** 2) By function vtabDisconnectAll(), when it adds a VTable entry to -** the sqlite3.pDisconnect list. In this case either the BtShared mutex -** associated with the database the virtual table is stored in is held -** or, if the virtual table is stored in a non-sharable database, then -** the database handle mutex is held. -** -** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously -** by multiple threads. It is thread-safe. -*/ -SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){ - VTable *p = db->pDisconnect; - db->pDisconnect = 0; - - assert( sqlite3BtreeHoldsAllMutexes(db) ); - assert( sqlite3_mutex_held(db->mutex) ); - - if( p ){ - sqlite3ExpirePreparedStatements(db); - do { - VTable *pNext = p->pNext; - sqlite3VtabUnlock(p); - p = pNext; - }while( p ); - } -} - -/* -** Clear any and all virtual-table information from the Table record. -** This routine is called, for example, just before deleting the Table -** record. -** -** Since it is a virtual-table, the Table structure contains a pointer -** to the head of a linked list of VTable structures. Each VTable -** structure is associated with a single sqlite3* user of the schema. -** The reference count of the VTable structure associated with database -** connection db is decremented immediately (which may lead to the -** structure being xDisconnected and free). Any other VTable structures -** in the list are moved to the sqlite3.pDisconnect list of the associated -** database connection. -*/ -SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){ - if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); - if( p->azModuleArg ){ - int i; - for(i=0; inModuleArg; i++){ - if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]); - } - sqlite3DbFree(db, p->azModuleArg); - } -} - -/* -** Add a new module argument to pTable->azModuleArg[]. -** The string is not copied - the pointer is stored. The -** string will be freed automatically when the table is -** deleted. -*/ -static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ - int i = pTable->nModuleArg++; - int nBytes = sizeof(char *)*(1+pTable->nModuleArg); - char **azModuleArg; - azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); - if( azModuleArg==0 ){ - int j; - for(j=0; jazModuleArg[j]); - } - sqlite3DbFree(db, zArg); - sqlite3DbFree(db, pTable->azModuleArg); - pTable->nModuleArg = 0; - }else{ - azModuleArg[i] = zArg; - azModuleArg[i+1] = 0; - } - pTable->azModuleArg = azModuleArg; -} - -/* -** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE -** statement. The module name has been parsed, but the optional list -** of parameters that follow the module name are still pending. -*/ -SQLITE_PRIVATE void sqlite3VtabBeginParse( - Parse *pParse, /* Parsing context */ - Token *pName1, /* Name of new table, or database name */ - Token *pName2, /* Name of new table or NULL */ - Token *pModuleName, /* Name of the module for the virtual table */ - int ifNotExists /* No error if the table already exists */ -){ - int iDb; /* The database the table is being created in */ - Table *pTable; /* The new virtual table */ - sqlite3 *db; /* Database connection */ - - sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists); - pTable = pParse->pNewTable; - if( pTable==0 ) return; - assert( 0==pTable->pIndex ); - - db = pParse->db; - iDb = sqlite3SchemaToIndex(db, pTable->pSchema); - assert( iDb>=0 ); - - pTable->tabFlags |= TF_Virtual; - pTable->nModuleArg = 0; - addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); - addModuleArgument(db, pTable, 0); - addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); - pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z); - -#ifndef SQLITE_OMIT_AUTHORIZATION - /* Creating a virtual table invokes the authorization callback twice. - ** The first invocation, to obtain permission to INSERT a row into the - ** sqlite_master table, has already been made by sqlite3StartTable(). - ** The second call, to obtain permission to create the table, is made now. - */ - if( pTable->azModuleArg ){ - sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, - pTable->azModuleArg[0], pParse->db->aDb[iDb].zName); - } -#endif -} - -/* -** This routine takes the module argument that has been accumulating -** in pParse->zArg[] and appends it to the list of arguments on the -** virtual table currently under construction in pParse->pTable. -*/ -static void addArgumentToVtab(Parse *pParse){ - if( pParse->sArg.z && pParse->pNewTable ){ - const char *z = (const char*)pParse->sArg.z; - int n = pParse->sArg.n; - sqlite3 *db = pParse->db; - addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); - } -} - -/* -** The parser calls this routine after the CREATE VIRTUAL TABLE statement -** has been completely parsed. -*/ -SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ - Table *pTab = pParse->pNewTable; /* The table being constructed */ - sqlite3 *db = pParse->db; /* The database connection */ - - if( pTab==0 ) return; - addArgumentToVtab(pParse); - pParse->sArg.z = 0; - if( pTab->nModuleArg<1 ) return; - - /* If the CREATE VIRTUAL TABLE statement is being entered for the - ** first time (in other words if the virtual table is actually being - ** created now instead of just being read out of sqlite_master) then - ** do additional initialization work and store the statement text - ** in the sqlite_master table. - */ - if( !db->init.busy ){ - char *zStmt; - char *zWhere; - int iDb; - Vdbe *v; - - /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ - if( pEnd ){ - pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n; - } - zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken); - - /* A slot for the record has already been allocated in the - ** SQLITE_MASTER table. We just need to update that slot with all - ** the information we've collected. - ** - ** The VM register number pParse->regRowid holds the rowid of an - ** entry in the sqlite_master table tht was created for this vtab - ** by sqlite3StartTable(). - */ - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - sqlite3NestedParse(pParse, - "UPDATE %Q.%s " - "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " - "WHERE rowid=#%d", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), - pTab->zName, - pTab->zName, - zStmt, - pParse->regRowid - ); - sqlite3DbFree(db, zStmt); - v = sqlite3GetVdbe(pParse); - sqlite3ChangeCookie(pParse, iDb); - - sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); - zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); - sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); - sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, - pTab->zName, sqlite3Strlen30(pTab->zName) + 1); - } - - /* If we are rereading the sqlite_master table create the in-memory - ** record of the table. The xConnect() method is not called until - ** the first time the virtual table is used in an SQL statement. This - ** allows a schema that contains virtual tables to be loaded before - ** the required virtual table implementations are registered. */ - else { - Table *pOld; - Schema *pSchema = pTab->pSchema; - const char *zName = pTab->zName; - int nName = sqlite3Strlen30(zName); - assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); - pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); - if( pOld ){ - db->mallocFailed = 1; - assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ - return; - } - pParse->pNewTable = 0; - } -} - -/* -** The parser calls this routine when it sees the first token -** of an argument to the module name in a CREATE VIRTUAL TABLE statement. -*/ -SQLITE_PRIVATE void sqlite3VtabArgInit(Parse *pParse){ - addArgumentToVtab(pParse); - pParse->sArg.z = 0; - pParse->sArg.n = 0; -} - -/* -** The parser calls this routine for each token after the first token -** in an argument to the module name in a CREATE VIRTUAL TABLE statement. -*/ -SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse *pParse, Token *p){ - Token *pArg = &pParse->sArg; - if( pArg->z==0 ){ - pArg->z = p->z; - pArg->n = p->n; - }else{ - assert(pArg->z < p->z); - pArg->n = (int)(&p->z[p->n] - pArg->z); - } -} - -/* -** Invoke a virtual table constructor (either xCreate or xConnect). The -** pointer to the function to invoke is passed as the fourth parameter -** to this procedure. -*/ -static int vtabCallConstructor( - sqlite3 *db, - Table *pTab, - Module *pMod, - int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), - char **pzErr -){ - VtabCtx sCtx, *pPriorCtx; - VTable *pVTable; - int rc; - const char *const*azArg = (const char *const*)pTab->azModuleArg; - int nArg = pTab->nModuleArg; - char *zErr = 0; - char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); - int iDb; - - if( !zModuleName ){ - return SQLITE_NOMEM; - } - - pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); - if( !pVTable ){ - sqlite3DbFree(db, zModuleName); - return SQLITE_NOMEM; - } - pVTable->db = db; - pVTable->pMod = pMod; - - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pTab->azModuleArg[1] = db->aDb[iDb].zName; - - /* Invoke the virtual table constructor */ - assert( &db->pVtabCtx ); - assert( xConstruct ); - sCtx.pTab = pTab; - sCtx.pVTable = pVTable; - pPriorCtx = db->pVtabCtx; - db->pVtabCtx = &sCtx; - rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - db->pVtabCtx = pPriorCtx; - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; - - if( SQLITE_OK!=rc ){ - if( zErr==0 ){ - *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); - }else { - *pzErr = sqlite3MPrintf(db, "%s", zErr); - sqlite3_free(zErr); - } - sqlite3DbFree(db, pVTable); - }else if( ALWAYS(pVTable->pVtab) ){ - /* Justification of ALWAYS(): A correct vtab constructor must allocate - ** the sqlite3_vtab object if successful. */ - pVTable->pVtab->pModule = pMod->pModule; - pVTable->nRef = 1; - if( sCtx.pTab ){ - const char *zFormat = "vtable constructor did not declare schema: %s"; - *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); - sqlite3VtabUnlock(pVTable); - rc = SQLITE_ERROR; - }else{ - int iCol; - /* If everything went according to plan, link the new VTable structure - ** into the linked list headed by pTab->pVTable. Then loop through the - ** columns of the table to see if any of them contain the token "hidden". - ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from - ** the type string. */ - pVTable->pNext = pTab->pVTable; - pTab->pVTable = pVTable; - - for(iCol=0; iColnCol; iCol++){ - char *zType = pTab->aCol[iCol].zType; - int nType; - int i = 0; - if( !zType ) continue; - nType = sqlite3Strlen30(zType); - if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ - for(i=0; i0 ){ - assert(zType[i-1]==' '); - zType[i-1] = '\0'; - } - pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN; - } - } - } - } - - sqlite3DbFree(db, zModuleName); - return rc; -} - -/* -** This function is invoked by the parser to call the xConnect() method -** of the virtual table pTab. If an error occurs, an error code is returned -** and an error left in pParse. -** -** This call is a no-op if table pTab is not a virtual table. -*/ -SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ - sqlite3 *db = pParse->db; - const char *zMod; - Module *pMod; - int rc; - - assert( pTab ); - if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){ - return SQLITE_OK; - } - - /* Locate the required virtual table module */ - zMod = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); - - if( !pMod ){ - const char *zModule = pTab->azModuleArg[0]; - sqlite3ErrorMsg(pParse, "no such module: %s", zModule); - rc = SQLITE_ERROR; - }else{ - char *zErr = 0; - rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); - if( rc!=SQLITE_OK ){ - sqlite3ErrorMsg(pParse, "%s", zErr); - } - sqlite3DbFree(db, zErr); - } - - return rc; -} -/* -** Grow the db->aVTrans[] array so that there is room for at least one -** more v-table. Return SQLITE_NOMEM if a malloc fails, or SQLITE_OK otherwise. -*/ -static int growVTrans(sqlite3 *db){ - const int ARRAY_INCR = 5; - - /* Grow the sqlite3.aVTrans array if required */ - if( (db->nVTrans%ARRAY_INCR)==0 ){ - VTable **aVTrans; - int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); - aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); - if( !aVTrans ){ - return SQLITE_NOMEM; - } - memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); - db->aVTrans = aVTrans; - } - - return SQLITE_OK; -} - -/* -** Add the virtual table pVTab to the array sqlite3.aVTrans[]. Space should -** have already been reserved using growVTrans(). -*/ -static void addToVTrans(sqlite3 *db, VTable *pVTab){ - /* Add pVtab to the end of sqlite3.aVTrans */ - db->aVTrans[db->nVTrans++] = pVTab; - sqlite3VtabLock(pVTab); -} - -/* -** This function is invoked by the vdbe to call the xCreate method -** of the virtual table named zTab in database iDb. -** -** If an error occurs, *pzErr is set to point an an English language -** description of the error and an SQLITE_XXX error code is returned. -** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. -*/ -SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ - int rc = SQLITE_OK; - Table *pTab; - Module *pMod; - const char *zMod; - - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); - assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); - - /* Locate the required virtual table module */ - zMod = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); - - /* If the module has been registered and includes a Create method, - ** invoke it now. If the module has not been registered, return an - ** error. Otherwise, do nothing. - */ - if( !pMod ){ - *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); - rc = SQLITE_ERROR; - }else{ - rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); - } - - /* Justification of ALWAYS(): The xConstructor method is required to - ** create a valid sqlite3_vtab if it returns SQLITE_OK. */ - if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){ - rc = growVTrans(db); - if( rc==SQLITE_OK ){ - addToVTrans(db, sqlite3GetVTable(db, pTab)); - } - } - - return rc; -} - -/* -** This function is used to set the schema of a virtual table. It is only -** valid to call this function from within the xCreate() or xConnect() of a -** virtual table module. -*/ -SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ - Parse *pParse; - - int rc = SQLITE_OK; - Table *pTab; - char *zErr = 0; - - sqlite3_mutex_enter(db->mutex); - if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){ - sqlite3Error(db, SQLITE_MISUSE, 0); - sqlite3_mutex_leave(db->mutex); - return SQLITE_MISUSE_BKPT; - } - assert( (pTab->tabFlags & TF_Virtual)!=0 ); - - pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); - if( pParse==0 ){ - rc = SQLITE_NOMEM; - }else{ - pParse->declareVtab = 1; - pParse->db = db; - pParse->nQueryLoop = 1; - - if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) - && pParse->pNewTable - && !db->mallocFailed - && !pParse->pNewTable->pSelect - && (pParse->pNewTable->tabFlags & TF_Virtual)==0 - ){ - if( !pTab->aCol ){ - pTab->aCol = pParse->pNewTable->aCol; - pTab->nCol = pParse->pNewTable->nCol; - pParse->pNewTable->nCol = 0; - pParse->pNewTable->aCol = 0; - } - db->pVtabCtx->pTab = 0; - }else{ - sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); - sqlite3DbFree(db, zErr); - rc = SQLITE_ERROR; - } - pParse->declareVtab = 0; - - if( pParse->pVdbe ){ - sqlite3VdbeFinalize(pParse->pVdbe); - } - sqlite3DeleteTable(db, pParse->pNewTable); - sqlite3StackFree(db, pParse); - } - - assert( (rc&0xff)==rc ); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** This function is invoked by the vdbe to call the xDestroy method -** of the virtual table named zTab in database iDb. This occurs -** when a DROP TABLE is mentioned. -** -** This call is a no-op if zTab is not a virtual table. -*/ -SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ - int rc = SQLITE_OK; - Table *pTab; - - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); - if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ - VTable *p = vtabDisconnectAll(db, pTab); - - assert( rc==SQLITE_OK ); - rc = p->pMod->pModule->xDestroy(p->pVtab); - - /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ - if( rc==SQLITE_OK ){ - assert( pTab->pVTable==p && p->pNext==0 ); - p->pVtab = 0; - pTab->pVTable = 0; - sqlite3VtabUnlock(p); - } - } - - return rc; -} - -/* -** This function invokes either the xRollback or xCommit method -** of each of the virtual tables in the sqlite3.aVTrans array. The method -** called is identified by the second argument, "offset", which is -** the offset of the method to call in the sqlite3_module structure. -** -** The array is cleared after invoking the callbacks. -*/ -static void callFinaliser(sqlite3 *db, int offset){ - int i; - if( db->aVTrans ){ - for(i=0; inVTrans; i++){ - VTable *pVTab = db->aVTrans[i]; - sqlite3_vtab *p = pVTab->pVtab; - if( p ){ - int (*x)(sqlite3_vtab *); - x = *(int (**)(sqlite3_vtab *))((char *)p->pModule + offset); - if( x ) x(p); - } - pVTab->iSavepoint = 0; - sqlite3VtabUnlock(pVTab); - } - sqlite3DbFree(db, db->aVTrans); - db->nVTrans = 0; - db->aVTrans = 0; - } -} - -/* -** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans -** array. Return the error code for the first error that occurs, or -** SQLITE_OK if all xSync operations are successful. -** -** Set *pzErrmsg to point to a buffer that should be released using -** sqlite3DbFree() containing an error message, if one is available. -*/ -SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ - int i; - int rc = SQLITE_OK; - VTable **aVTrans = db->aVTrans; - - db->aVTrans = 0; - for(i=0; rc==SQLITE_OK && inVTrans; i++){ - int (*x)(sqlite3_vtab *); - sqlite3_vtab *pVtab = aVTrans[i]->pVtab; - if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ - rc = x(pVtab); - sqlite3DbFree(db, *pzErrmsg); - *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg); - sqlite3_free(pVtab->zErrMsg); - } - } - db->aVTrans = aVTrans; - return rc; -} - -/* -** Invoke the xRollback method of all virtual tables in the -** sqlite3.aVTrans array. Then clear the array itself. -*/ -SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){ - callFinaliser(db, offsetof(sqlite3_module,xRollback)); - return SQLITE_OK; -} - -/* -** Invoke the xCommit method of all virtual tables in the -** sqlite3.aVTrans array. Then clear the array itself. -*/ -SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db){ - callFinaliser(db, offsetof(sqlite3_module,xCommit)); - return SQLITE_OK; -} - -/* -** If the virtual table pVtab supports the transaction interface -** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is -** not currently open, invoke the xBegin method now. -** -** If the xBegin call is successful, place the sqlite3_vtab pointer -** in the sqlite3.aVTrans array. -*/ -SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ - int rc = SQLITE_OK; - const sqlite3_module *pModule; - - /* Special case: If db->aVTrans is NULL and db->nVTrans is greater - ** than zero, then this function is being called from within a - ** virtual module xSync() callback. It is illegal to write to - ** virtual module tables in this case, so return SQLITE_LOCKED. - */ - if( sqlite3VtabInSync(db) ){ - return SQLITE_LOCKED; - } - if( !pVTab ){ - return SQLITE_OK; - } - pModule = pVTab->pVtab->pModule; - - if( pModule->xBegin ){ - int i; - - /* If pVtab is already in the aVTrans array, return early */ - for(i=0; inVTrans; i++){ - if( db->aVTrans[i]==pVTab ){ - return SQLITE_OK; - } - } - - /* Invoke the xBegin method. If successful, add the vtab to the - ** sqlite3.aVTrans[] array. */ - rc = growVTrans(db); - if( rc==SQLITE_OK ){ - rc = pModule->xBegin(pVTab->pVtab); - if( rc==SQLITE_OK ){ - addToVTrans(db, pVTab); - } - } - } - return rc; -} - -/* -** Invoke either the xSavepoint, xRollbackTo or xRelease method of all -** virtual tables that currently have an open transaction. Pass iSavepoint -** as the second argument to the virtual table method invoked. -** -** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is -** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is -** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with -** an open transaction is invoked. -** -** If any virtual table method returns an error code other than SQLITE_OK, -** processing is abandoned and the error returned to the caller of this -** function immediately. If all calls to virtual table methods are successful, -** SQLITE_OK is returned. -*/ -SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){ - int rc = SQLITE_OK; - - assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN ); - assert( iSavepoint>=0 ); - if( db->aVTrans ){ - int i; - for(i=0; rc==SQLITE_OK && inVTrans; i++){ - VTable *pVTab = db->aVTrans[i]; - const sqlite3_module *pMod = pVTab->pMod->pModule; - if( pVTab->pVtab && pMod->iVersion>=2 ){ - int (*xMethod)(sqlite3_vtab *, int); - switch( op ){ - case SAVEPOINT_BEGIN: - xMethod = pMod->xSavepoint; - pVTab->iSavepoint = iSavepoint+1; - break; - case SAVEPOINT_ROLLBACK: - xMethod = pMod->xRollbackTo; - break; - default: - xMethod = pMod->xRelease; - break; - } - if( xMethod && pVTab->iSavepoint>iSavepoint ){ - rc = xMethod(pVTab->pVtab, iSavepoint); - } - } - } - } - return rc; -} - -/* -** The first parameter (pDef) is a function implementation. The -** second parameter (pExpr) is the first argument to this function. -** If pExpr is a column in a virtual table, then let the virtual -** table implementation have an opportunity to overload the function. -** -** This routine is used to allow virtual table implementations to -** overload MATCH, LIKE, GLOB, and REGEXP operators. -** -** Return either the pDef argument (indicating no change) or a -** new FuncDef structure that is marked as ephemeral using the -** SQLITE_FUNC_EPHEM flag. -*/ -SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction( - sqlite3 *db, /* Database connection for reporting malloc problems */ - FuncDef *pDef, /* Function to possibly overload */ - int nArg, /* Number of arguments to the function */ - Expr *pExpr /* First argument to the function */ -){ - Table *pTab; - sqlite3_vtab *pVtab; - sqlite3_module *pMod; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**) = 0; - void *pArg = 0; - FuncDef *pNew; - int rc = 0; - char *zLowerName; - unsigned char *z; - - - /* Check to see the left operand is a column in a virtual table */ - if( NEVER(pExpr==0) ) return pDef; - if( pExpr->op!=TK_COLUMN ) return pDef; - pTab = pExpr->pTab; - if( NEVER(pTab==0) ) return pDef; - if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef; - pVtab = sqlite3GetVTable(db, pTab)->pVtab; - assert( pVtab!=0 ); - assert( pVtab->pModule!=0 ); - pMod = (sqlite3_module *)pVtab->pModule; - if( pMod->xFindFunction==0 ) return pDef; - - /* Call the xFindFunction method on the virtual table implementation - ** to see if the implementation wants to overload this function - */ - zLowerName = sqlite3DbStrDup(db, pDef->zName); - if( zLowerName ){ - for(z=(unsigned char*)zLowerName; *z; z++){ - *z = sqlite3UpperToLower[*z]; - } - rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg); - sqlite3DbFree(db, zLowerName); - } - if( rc==0 ){ - return pDef; - } - - /* Create a new ephemeral function definition for the overloaded - ** function */ - pNew = sqlite3DbMallocZero(db, sizeof(*pNew) - + sqlite3Strlen30(pDef->zName) + 1); - if( pNew==0 ){ - return pDef; - } - *pNew = *pDef; - pNew->zName = (char *)&pNew[1]; - memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1); - pNew->xFunc = xFunc; - pNew->pUserData = pArg; - pNew->flags |= SQLITE_FUNC_EPHEM; - return pNew; -} - -/* -** Make sure virtual table pTab is contained in the pParse->apVirtualLock[] -** array so that an OP_VBegin will get generated for it. Add pTab to the -** array if it is missing. If pTab is already in the array, this routine -** is a no-op. -*/ -SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ - Parse *pToplevel = sqlite3ParseToplevel(pParse); - int i, n; - Table **apVtabLock; - - assert( IsVirtual(pTab) ); - for(i=0; inVtabLock; i++){ - if( pTab==pToplevel->apVtabLock[i] ) return; - } - n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); - apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n); - if( apVtabLock ){ - pToplevel->apVtabLock = apVtabLock; - pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; - }else{ - pToplevel->db->mallocFailed = 1; - } -} - -/* -** Return the ON CONFLICT resolution mode in effect for the virtual -** table update operation currently in progress. -** -** The results of this routine are undefined unless it is called from -** within an xUpdate method. -*/ -SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){ - static const unsigned char aMap[] = { - SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE - }; - assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 ); - assert( OE_Ignore==4 && OE_Replace==5 ); - assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 ); - return (int)aMap[db->vtabOnConflict-1]; -} - -/* -** Call from within the xCreate() or xConnect() methods to provide -** the SQLite core with additional information about the behavior -** of the virtual table being implemented. -*/ -SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ - va_list ap; - int rc = SQLITE_OK; - - sqlite3_mutex_enter(db->mutex); - - va_start(ap, op); - switch( op ){ - case SQLITE_VTAB_CONSTRAINT_SUPPORT: { - VtabCtx *p = db->pVtabCtx; - if( !p ){ - rc = SQLITE_MISUSE_BKPT; - }else{ - assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 ); - p->pVTable->bConstraint = (u8)va_arg(ap, int); - } - break; - } - default: - rc = SQLITE_MISUSE_BKPT; - break; - } - va_end(ap); - - if( rc!=SQLITE_OK ) sqlite3Error(db, rc, 0); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/************** End of vtab.c ************************************************/ -/************** Begin file where.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This module contains C code that generates VDBE code used to process -** the WHERE clause of SQL statements. This module is responsible for -** generating the code that loops through a table looking for applicable -** rows. Indices are selected and used to speed the search when doing -** so is applicable. Because this module is responsible for selecting -** indices, you might also think of this module as the "query optimizer". -*/ - - -/* -** Trace output macros -*/ -#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) -/***/ int sqlite3WhereTrace = 0; -#endif -#if defined(SQLITE_DEBUG) \ - && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) -# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X -#else -# define WHERETRACE(X) -#endif - -/* Forward reference -*/ -typedef struct WhereClause WhereClause; -typedef struct WhereMaskSet WhereMaskSet; -typedef struct WhereOrInfo WhereOrInfo; -typedef struct WhereAndInfo WhereAndInfo; -typedef struct WhereCost WhereCost; - -/* -** The query generator uses an array of instances of this structure to -** help it analyze the subexpressions of the WHERE clause. Each WHERE -** clause subexpression is separated from the others by AND operators, -** usually, or sometimes subexpressions separated by OR. -** -** All WhereTerms are collected into a single WhereClause structure. -** The following identity holds: -** -** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm -** -** When a term is of the form: -** -** X -** -** where X is a column name and is one of certain operators, -** then WhereTerm.leftCursor and WhereTerm.u.leftColumn record the -** cursor number and column number for X. WhereTerm.eOperator records -** the using a bitmask encoding defined by WO_xxx below. The -** use of a bitmask encoding for the operator allows us to search -** quickly for terms that match any of several different operators. -** -** A WhereTerm might also be two or more subterms connected by OR: -** -** (t1.X ) OR (t1.Y ) OR .... -** -** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR -** and the WhereTerm.u.pOrInfo field points to auxiliary information that -** is collected about the -** -** If a term in the WHERE clause does not match either of the two previous -** categories, then eOperator==0. The WhereTerm.pExpr field is still set -** to the original subexpression content and wtFlags is set up appropriately -** but no other fields in the WhereTerm object are meaningful. -** -** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers, -** but they do so indirectly. A single WhereMaskSet structure translates -** cursor number into bits and the translated bit is stored in the prereq -** fields. The translation is used in order to maximize the number of -** bits that will fit in a Bitmask. The VDBE cursor numbers might be -** spread out over the non-negative integers. For example, the cursor -** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The WhereMaskSet -** translates these sparse cursor numbers into consecutive integers -** beginning with 0 in order to make the best possible use of the available -** bits in the Bitmask. So, in the example above, the cursor numbers -** would be mapped into integers 0 through 7. -** -** The number of terms in a join is limited by the number of bits -** in prereqRight and prereqAll. The default is 64 bits, hence SQLite -** is only able to process joins with 64 or fewer tables. -*/ -typedef struct WhereTerm WhereTerm; -struct WhereTerm { - Expr *pExpr; /* Pointer to the subexpression that is this term */ - int iParent; /* Disable pWC->a[iParent] when this term disabled */ - int leftCursor; /* Cursor number of X in "X " */ - union { - int leftColumn; /* Column number of X in "X " */ - WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ - WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ - } u; - u16 eOperator; /* A WO_xx value describing */ - u8 wtFlags; /* TERM_xxx bit flags. See below */ - u8 nChild; /* Number of children that must disable us */ - WhereClause *pWC; /* The clause this term is part of */ - Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ - Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ -}; - -/* -** Allowed values of WhereTerm.wtFlags -*/ -#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */ -#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */ -#define TERM_CODED 0x04 /* This term is already coded */ -#define TERM_COPIED 0x08 /* Has a child */ -#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */ -#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */ -#define TERM_OR_OK 0x40 /* Used during OR-clause processing */ -#ifdef SQLITE_ENABLE_STAT3 -# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */ -#else -# define TERM_VNULL 0x00 /* Disabled if not using stat3 */ -#endif - -/* -** An instance of the following structure holds all information about a -** WHERE clause. Mostly this is a container for one or more WhereTerms. -** -** Explanation of pOuter: For a WHERE clause of the form -** -** a AND ((b AND c) OR (d AND e)) AND f -** -** There are separate WhereClause objects for the whole clause and for -** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the -** subclauses points to the WhereClause object for the whole clause. -*/ -struct WhereClause { - Parse *pParse; /* The parser context */ - WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */ - WhereClause *pOuter; /* Outer conjunction */ - u8 op; /* Split operator. TK_AND or TK_OR */ - u16 wctrlFlags; /* Might include WHERE_AND_ONLY */ - int nTerm; /* Number of terms */ - int nSlot; /* Number of entries in a[] */ - WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ -#if defined(SQLITE_SMALL_STACK) - WhereTerm aStatic[1]; /* Initial static space for a[] */ -#else - WhereTerm aStatic[8]; /* Initial static space for a[] */ -#endif -}; - -/* -** A WhereTerm with eOperator==WO_OR has its u.pOrInfo pointer set to -** a dynamically allocated instance of the following structure. -*/ -struct WhereOrInfo { - WhereClause wc; /* Decomposition into subterms */ - Bitmask indexable; /* Bitmask of all indexable tables in the clause */ -}; - -/* -** A WhereTerm with eOperator==WO_AND has its u.pAndInfo pointer set to -** a dynamically allocated instance of the following structure. -*/ -struct WhereAndInfo { - WhereClause wc; /* The subexpression broken out */ -}; - -/* -** An instance of the following structure keeps track of a mapping -** between VDBE cursor numbers and bits of the bitmasks in WhereTerm. -** -** The VDBE cursor numbers are small integers contained in -** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE -** clause, the cursor numbers might not begin with 0 and they might -** contain gaps in the numbering sequence. But we want to make maximum -** use of the bits in our bitmasks. This structure provides a mapping -** from the sparse cursor numbers into consecutive integers beginning -** with 0. -** -** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask -** corresponds VDBE cursor number B. The A-th bit of a bitmask is 1<3, 5->1, 8->2, 29->0, -** 57->5, 73->4. Or one of 719 other combinations might be used. It -** does not really matter. What is important is that sparse cursor -** numbers all get mapped into bit numbers that begin with 0 and contain -** no gaps. -*/ -struct WhereMaskSet { - int n; /* Number of assigned cursor values */ - int ix[BMS]; /* Cursor assigned to each bit */ -}; - -/* -** A WhereCost object records a lookup strategy and the estimated -** cost of pursuing that strategy. -*/ -struct WhereCost { - WherePlan plan; /* The lookup strategy */ - double rCost; /* Overall cost of pursuing this search strategy */ - Bitmask used; /* Bitmask of cursors used by this plan */ -}; - -/* -** Bitmasks for the operators that indices are able to exploit. An -** OR-ed combination of these values can be used when searching for -** terms in the where clause. -*/ -#define WO_IN 0x001 -#define WO_EQ 0x002 -#define WO_LT (WO_EQ<<(TK_LT-TK_EQ)) -#define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) -#define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) -#define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) -#define WO_MATCH 0x040 -#define WO_ISNULL 0x080 -#define WO_OR 0x100 /* Two or more OR-connected terms */ -#define WO_AND 0x200 /* Two or more AND-connected terms */ -#define WO_EQUIV 0x400 /* Of the form A==B, both columns */ -#define WO_NOOP 0x800 /* This term does not restrict search space */ - -#define WO_ALL 0xfff /* Mask of all possible WO_* values */ -#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ - -/* -** Value for wsFlags returned by bestIndex() and stored in -** WhereLevel.wsFlags. These flags determine which search -** strategies are appropriate. -** -** The least significant 12 bits is reserved as a mask for WO_ values above. -** The WhereLevel.wsFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL. -** But if the table is the right table of a left join, WhereLevel.wsFlags -** is set to WO_IN|WO_EQ. The WhereLevel.wsFlags field can then be used as -** the "op" parameter to findTerm when we are resolving equality constraints. -** ISNULL constraints will then not be used on the right table of a left -** join. Tickets #2177 and #2189. -*/ -#define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */ -#define WHERE_ROWID_RANGE 0x00002000 /* rowidEXPR */ -#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ -#define WHERE_COLUMN_RANGE 0x00020000 /* xEXPR */ -#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ -#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ -#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ -#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ -#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */ -#define WHERE_TOP_LIMIT 0x00100000 /* xEXPR or x>=EXPR constraint */ -#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and xrCostrCost ) return 1; - if( pProbe->rCost>pBaseline->rCost ) return 0; - if( pProbe->plan.nOBSat>pBaseline->plan.nOBSat ) return 1; - if( pProbe->plan.nRowplan.nRow ) return 1; - return 0; -} - -/* -** Initialize a preallocated WhereClause structure. -*/ -static void whereClauseInit( - WhereClause *pWC, /* The WhereClause to be initialized */ - Parse *pParse, /* The parsing context */ - WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmasks */ - u16 wctrlFlags /* Might include WHERE_AND_ONLY */ -){ - pWC->pParse = pParse; - pWC->pMaskSet = pMaskSet; - pWC->pOuter = 0; - pWC->nTerm = 0; - pWC->nSlot = ArraySize(pWC->aStatic); - pWC->a = pWC->aStatic; - pWC->wctrlFlags = wctrlFlags; -} - -/* Forward reference */ -static void whereClauseClear(WhereClause*); - -/* -** Deallocate all memory associated with a WhereOrInfo object. -*/ -static void whereOrInfoDelete(sqlite3 *db, WhereOrInfo *p){ - whereClauseClear(&p->wc); - sqlite3DbFree(db, p); -} - -/* -** Deallocate all memory associated with a WhereAndInfo object. -*/ -static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){ - whereClauseClear(&p->wc); - sqlite3DbFree(db, p); -} - -/* -** Deallocate a WhereClause structure. The WhereClause structure -** itself is not freed. This routine is the inverse of whereClauseInit(). -*/ -static void whereClauseClear(WhereClause *pWC){ - int i; - WhereTerm *a; - sqlite3 *db = pWC->pParse->db; - for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ - if( a->wtFlags & TERM_DYNAMIC ){ - sqlite3ExprDelete(db, a->pExpr); - } - if( a->wtFlags & TERM_ORINFO ){ - whereOrInfoDelete(db, a->u.pOrInfo); - }else if( a->wtFlags & TERM_ANDINFO ){ - whereAndInfoDelete(db, a->u.pAndInfo); - } - } - if( pWC->a!=pWC->aStatic ){ - sqlite3DbFree(db, pWC->a); - } -} - -/* -** Add a single new WhereTerm entry to the WhereClause object pWC. -** The new WhereTerm object is constructed from Expr p and with wtFlags. -** The index in pWC->a[] of the new WhereTerm is returned on success. -** 0 is returned if the new WhereTerm could not be added due to a memory -** allocation error. The memory allocation failure will be recorded in -** the db->mallocFailed flag so that higher-level functions can detect it. -** -** This routine will increase the size of the pWC->a[] array as necessary. -** -** If the wtFlags argument includes TERM_DYNAMIC, then responsibility -** for freeing the expression p is assumed by the WhereClause object pWC. -** This is true even if this routine fails to allocate a new WhereTerm. -** -** WARNING: This routine might reallocate the space used to store -** WhereTerms. All pointers to WhereTerms should be invalidated after -** calling this routine. Such pointers may be reinitialized by referencing -** the pWC->a[] array. -*/ -static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ - WhereTerm *pTerm; - int idx; - testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */ - if( pWC->nTerm>=pWC->nSlot ){ - WhereTerm *pOld = pWC->a; - sqlite3 *db = pWC->pParse->db; - pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); - if( pWC->a==0 ){ - if( wtFlags & TERM_DYNAMIC ){ - sqlite3ExprDelete(db, p); - } - pWC->a = pOld; - return 0; - } - memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); - if( pOld!=pWC->aStatic ){ - sqlite3DbFree(db, pOld); - } - pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); - } - pTerm = &pWC->a[idx = pWC->nTerm++]; - pTerm->pExpr = sqlite3ExprSkipCollate(p); - pTerm->wtFlags = wtFlags; - pTerm->pWC = pWC; - pTerm->iParent = -1; - return idx; -} - -/* -** This routine identifies subexpressions in the WHERE clause where -** each subexpression is separated by the AND operator or some other -** operator specified in the op parameter. The WhereClause structure -** is filled with pointers to subexpressions. For example: -** -** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22) -** \________/ \_______________/ \________________/ -** slot[0] slot[1] slot[2] -** -** The original WHERE clause in pExpr is unaltered. All this routine -** does is make slot[] entries point to substructure within pExpr. -** -** In the previous sentence and in the diagram, "slot[]" refers to -** the WhereClause.a[] array. The slot[] array grows as needed to contain -** all terms of the WHERE clause. -*/ -static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){ - pWC->op = (u8)op; - if( pExpr==0 ) return; - if( pExpr->op!=op ){ - whereClauseInsert(pWC, pExpr, 0); - }else{ - whereSplit(pWC, pExpr->pLeft, op); - whereSplit(pWC, pExpr->pRight, op); - } -} - -/* -** Initialize an expression mask set (a WhereMaskSet object) -*/ -#define initMaskSet(P) memset(P, 0, sizeof(*P)) - -/* -** Return the bitmask for the given cursor number. Return 0 if -** iCursor is not in the set. -*/ -static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){ - int i; - assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); - for(i=0; in; i++){ - if( pMaskSet->ix[i]==iCursor ){ - return ((Bitmask)1)<ix[] -** array will never overflow. -*/ -static void createMask(WhereMaskSet *pMaskSet, int iCursor){ - assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); - pMaskSet->ix[pMaskSet->n++] = iCursor; -} - -/* -** This routine walks (recursively) an expression tree and generates -** a bitmask indicating which tables are used in that expression -** tree. -** -** In order for this routine to work, the calling function must have -** previously invoked sqlite3ResolveExprNames() on the expression. See -** the header comment on that routine for additional information. -** The sqlite3ResolveExprNames() routines looks for column names and -** sets their opcodes to TK_COLUMN and their Expr.iTable fields to -** the VDBE cursor number of the table. This routine just has to -** translate the cursor numbers into bitmask values and OR all -** the bitmasks together. -*/ -static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*); -static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*); -static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){ - Bitmask mask = 0; - if( p==0 ) return 0; - if( p->op==TK_COLUMN ){ - mask = getMask(pMaskSet, p->iTable); - return mask; - } - mask = exprTableUsage(pMaskSet, p->pRight); - mask |= exprTableUsage(pMaskSet, p->pLeft); - if( ExprHasProperty(p, EP_xIsSelect) ){ - mask |= exprSelectTableUsage(pMaskSet, p->x.pSelect); - }else{ - mask |= exprListTableUsage(pMaskSet, p->x.pList); - } - return mask; -} -static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){ - int i; - Bitmask mask = 0; - if( pList ){ - for(i=0; inExpr; i++){ - mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr); - } - } - return mask; -} -static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){ - Bitmask mask = 0; - while( pS ){ - SrcList *pSrc = pS->pSrc; - mask |= exprListTableUsage(pMaskSet, pS->pEList); - mask |= exprListTableUsage(pMaskSet, pS->pGroupBy); - mask |= exprListTableUsage(pMaskSet, pS->pOrderBy); - mask |= exprTableUsage(pMaskSet, pS->pWhere); - mask |= exprTableUsage(pMaskSet, pS->pHaving); - if( ALWAYS(pSrc!=0) ){ - int i; - for(i=0; inSrc; i++){ - mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect); - mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn); - } - } - pS = pS->pPrior; - } - return mask; -} - -/* -** Return TRUE if the given operator is one of the operators that is -** allowed for an indexable WHERE clause term. The allowed operators are -** "=", "<", ">", "<=", ">=", and "IN". -** -** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be -** of one of the following forms: column = expression column > expression -** column >= expression column < expression column <= expression -** expression = column expression > column expression >= column -** expression < column expression <= column column IN -** (expression-list) column IN (subquery) column IS NULL -*/ -static int allowedOp(int op){ - assert( TK_GT>TK_EQ && TK_GTTK_EQ && TK_LTTK_EQ && TK_LE=TK_EQ && op<=TK_GE) || op==TK_ISNULL; -} - -/* -** Swap two objects of type TYPE. -*/ -#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} - -/* -** Commute a comparison operator. Expressions of the form "X op Y" -** are converted into "Y op X". -** -** If left/right precedence rules come into play when determining the -** collating -** side of the comparison, it remains associated with the same side after -** the commutation. So "Y collate NOCASE op X" becomes -** "X op Y". This is because any collation sequence on -** the left hand side of a comparison overrides any collation sequence -** attached to the right. For the same reason the EP_Collate flag -** is not commuted. -*/ -static void exprCommute(Parse *pParse, Expr *pExpr){ - u16 expRight = (pExpr->pRight->flags & EP_Collate); - u16 expLeft = (pExpr->pLeft->flags & EP_Collate); - assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); - if( expRight==expLeft ){ - /* Either X and Y both have COLLATE operator or neither do */ - if( expRight ){ - /* Both X and Y have COLLATE operators. Make sure X is always - ** used by clearing the EP_Collate flag from Y. */ - pExpr->pRight->flags &= ~EP_Collate; - }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ - /* Neither X nor Y have COLLATE operators, but X has a non-default - ** collating sequence. So add the EP_Collate marker on X to cause - ** it to be searched first. */ - pExpr->pLeft->flags |= EP_Collate; - } - } - SWAP(Expr*,pExpr->pRight,pExpr->pLeft); - if( pExpr->op>=TK_GT ){ - assert( TK_LT==TK_GT+2 ); - assert( TK_GE==TK_LE+2 ); - assert( TK_GT>TK_EQ ); - assert( TK_GTop>=TK_GT && pExpr->op<=TK_GE ); - pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; - } -} - -/* -** Translate from TK_xx operator to WO_xx bitmask. -*/ -static u16 operatorMask(int op){ - u16 c; - assert( allowedOp(op) ); - if( op==TK_IN ){ - c = WO_IN; - }else if( op==TK_ISNULL ){ - c = WO_ISNULL; - }else{ - assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff ); - c = (u16)(WO_EQ<<(op-TK_EQ)); - } - assert( op!=TK_ISNULL || c==WO_ISNULL ); - assert( op!=TK_IN || c==WO_IN ); - assert( op!=TK_EQ || c==WO_EQ ); - assert( op!=TK_LT || c==WO_LT ); - assert( op!=TK_LE || c==WO_LE ); - assert( op!=TK_GT || c==WO_GT ); - assert( op!=TK_GE || c==WO_GE ); - return c; -} - -/* -** Search for a term in the WHERE clause that is of the form "X " -** where X is a reference to the iColumn of table iCur and is one of -** the WO_xx operator codes specified by the op parameter. -** Return a pointer to the term. Return 0 if not found. -** -** The term returned might by Y= if there is another constraint in -** the WHERE clause that specifies that X=Y. Any such constraints will be -** identified by the WO_EQUIV bit in the pTerm->eOperator field. The -** aEquiv[] array holds X and all its equivalents, with each SQL variable -** taking up two slots in aEquiv[]. The first slot is for the cursor number -** and the second is for the column number. There are 22 slots in aEquiv[] -** so that means we can look for X plus up to 10 other equivalent values. -** Hence a search for X will return if X=A1 and A1=A2 and A2=A3 -** and ... and A9=A10 and A10=. -** -** If there are multiple terms in the WHERE clause of the form "X " -** then try for the one with no dependencies on - in other words where -** is a constant expression of some kind. Only return entries of -** the form "X Y" where Y is a column in another table if no terms of -** the form "X " exist. If no terms with a constant RHS -** exist, try to return a term that does not use WO_EQUIV. -*/ -static WhereTerm *findTerm( - WhereClause *pWC, /* The WHERE clause to be searched */ - int iCur, /* Cursor number of LHS */ - int iColumn, /* Column number of LHS */ - Bitmask notReady, /* RHS must not overlap with this mask */ - u32 op, /* Mask of WO_xx values describing operator */ - Index *pIdx /* Must be compatible with this index, if not NULL */ -){ - WhereTerm *pTerm; /* Term being examined as possible result */ - WhereTerm *pResult = 0; /* The answer to return */ - WhereClause *pWCOrig = pWC; /* Original pWC value */ - int j, k; /* Loop counters */ - Expr *pX; /* Pointer to an expression */ - Parse *pParse; /* Parsing context */ - int iOrigCol = iColumn; /* Original value of iColumn */ - int nEquiv = 2; /* Number of entires in aEquiv[] */ - int iEquiv = 2; /* Number of entries of aEquiv[] processed so far */ - int aEquiv[22]; /* iCur,iColumn and up to 10 other equivalents */ - - assert( iCur>=0 ); - aEquiv[0] = iCur; - aEquiv[1] = iColumn; - for(;;){ - for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){ - for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){ - if( pTerm->leftCursor==iCur - && pTerm->u.leftColumn==iColumn - ){ - if( (pTerm->prereqRight & notReady)==0 - && (pTerm->eOperator & op & WO_ALL)!=0 - ){ - if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){ - CollSeq *pColl; - char idxaff; - - pX = pTerm->pExpr; - pParse = pWC->pParse; - idxaff = pIdx->pTable->aCol[iOrigCol].affinity; - if( !sqlite3IndexAffinityOk(pX, idxaff) ){ - continue; - } - - /* Figure out the collation sequence required from an index for - ** it to be useful for optimising expression pX. Store this - ** value in variable pColl. - */ - assert(pX->pLeft); - pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight); - if( pColl==0 ) pColl = pParse->db->pDfltColl; - - for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){ - if( NEVER(j>=pIdx->nColumn) ) return 0; - } - if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){ - continue; - } - } - if( pTerm->prereqRight==0 && (pTerm->eOperator&WO_EQ)!=0 ){ - pResult = pTerm; - goto findTerm_success; - }else if( pResult==0 ){ - pResult = pTerm; - } - } - if( (pTerm->eOperator & WO_EQUIV)!=0 - && nEquivpExpr->pRight); - assert( pX->op==TK_COLUMN ); - for(j=0; jiTable && aEquiv[j+1]==pX->iColumn ) break; - } - if( j==nEquiv ){ - aEquiv[j] = pX->iTable; - aEquiv[j+1] = pX->iColumn; - nEquiv += 2; - } - } - } - } - } - if( iEquiv>=nEquiv ) break; - iCur = aEquiv[iEquiv++]; - iColumn = aEquiv[iEquiv++]; - } -findTerm_success: - return pResult; -} - -/* Forward reference */ -static void exprAnalyze(SrcList*, WhereClause*, int); - -/* -** Call exprAnalyze on all terms in a WHERE clause. -** -** -*/ -static void exprAnalyzeAll( - SrcList *pTabList, /* the FROM clause */ - WhereClause *pWC /* the WHERE clause to be analyzed */ -){ - int i; - for(i=pWC->nTerm-1; i>=0; i--){ - exprAnalyze(pTabList, pWC, i); - } -} - -#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION -/* -** Check to see if the given expression is a LIKE or GLOB operator that -** can be optimized using inequality constraints. Return TRUE if it is -** so and false if not. -** -** In order for the operator to be optimizible, the RHS must be a string -** literal that does not begin with a wildcard. -*/ -static int isLikeOrGlob( - Parse *pParse, /* Parsing and code generating context */ - Expr *pExpr, /* Test this expression */ - Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */ - int *pisComplete, /* True if the only wildcard is % in the last character */ - int *pnoCase /* True if uppercase is equivalent to lowercase */ -){ - const char *z = 0; /* String on RHS of LIKE operator */ - Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ - ExprList *pList; /* List of operands to the LIKE operator */ - int c; /* One character in z[] */ - int cnt; /* Number of non-wildcard prefix characters */ - char wc[3]; /* Wildcard characters */ - sqlite3 *db = pParse->db; /* Database connection */ - sqlite3_value *pVal = 0; - int op; /* Opcode of pRight */ - - if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){ - return 0; - } -#ifdef SQLITE_EBCDIC - if( *pnoCase ) return 0; -#endif - pList = pExpr->x.pList; - pLeft = pList->a[1].pExpr; - if( pLeft->op!=TK_COLUMN - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) - ){ - /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must - ** be the name of an indexed column with TEXT affinity. */ - return 0; - } - assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ - - pRight = pList->a[0].pExpr; - op = pRight->op; - if( op==TK_REGISTER ){ - op = pRight->op2; - } - if( op==TK_VARIABLE ){ - Vdbe *pReprepare = pParse->pReprepare; - int iCol = pRight->iColumn; - pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE); - if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){ - z = (char *)sqlite3_value_text(pVal); - } - sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); - assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); - }else if( op==TK_STRING ){ - z = pRight->u.zToken; - } - if( z ){ - cnt = 0; - while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ - cnt++; - } - if( cnt!=0 && 255!=(u8)z[cnt-1] ){ - Expr *pPrefix; - *pisComplete = c==wc[0] && z[cnt+1]==0; - pPrefix = sqlite3Expr(db, TK_STRING, z); - if( pPrefix ) pPrefix->u.zToken[cnt] = 0; - *ppPrefix = pPrefix; - if( op==TK_VARIABLE ){ - Vdbe *v = pParse->pVdbe; - sqlite3VdbeSetVarmask(v, pRight->iColumn); - if( *pisComplete && pRight->u.zToken[1] ){ - /* If the rhs of the LIKE expression is a variable, and the current - ** value of the variable means there is no need to invoke the LIKE - ** function, then no OP_Variable will be added to the program. - ** This causes problems for the sqlite3_bind_parameter_name() - ** API. To workaround them, add a dummy OP_Variable here. - */ - int r1 = sqlite3GetTempReg(pParse); - sqlite3ExprCodeTarget(pParse, pRight, r1); - sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0); - sqlite3ReleaseTempReg(pParse, r1); - } - } - }else{ - z = 0; - } - } - - sqlite3ValueFree(pVal); - return (z!=0); -} -#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ - - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Check to see if the given expression is of the form -** -** column MATCH expr -** -** If it is then return TRUE. If not, return FALSE. -*/ -static int isMatchOfColumn( - Expr *pExpr /* Test this expression */ -){ - ExprList *pList; - - if( pExpr->op!=TK_FUNCTION ){ - return 0; - } - if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){ - return 0; - } - pList = pExpr->x.pList; - if( pList->nExpr!=2 ){ - return 0; - } - if( pList->a[1].pExpr->op != TK_COLUMN ){ - return 0; - } - return 1; -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/* -** If the pBase expression originated in the ON or USING clause of -** a join, then transfer the appropriate markings over to derived. -*/ -static void transferJoinMarkings(Expr *pDerived, Expr *pBase){ - pDerived->flags |= pBase->flags & EP_FromJoin; - pDerived->iRightJoinTable = pBase->iRightJoinTable; -} - -#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) -/* -** Analyze a term that consists of two or more OR-connected -** subterms. So in: -** -** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13) -** ^^^^^^^^^^^^^^^^^^^^ -** -** This routine analyzes terms such as the middle term in the above example. -** A WhereOrTerm object is computed and attached to the term under -** analysis, regardless of the outcome of the analysis. Hence: -** -** WhereTerm.wtFlags |= TERM_ORINFO -** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object -** -** The term being analyzed must have two or more of OR-connected subterms. -** A single subterm might be a set of AND-connected sub-subterms. -** Examples of terms under analysis: -** -** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5 -** (B) x=expr1 OR expr2=x OR x=expr3 -** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) -** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') -** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) -** -** CASE 1: -** -** If all subterms are of the form T.C=expr for some single column of C and -** a single table T (as shown in example B above) then create a new virtual -** term that is an equivalent IN expression. In other words, if the term -** being analyzed is: -** -** x = expr1 OR expr2 = x OR x = expr3 -** -** then create a new virtual term like this: -** -** x IN (expr1,expr2,expr3) -** -** CASE 2: -** -** If all subterms are indexable by a single table T, then set -** -** WhereTerm.eOperator = WO_OR -** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T -** -** A subterm is "indexable" if it is of the form -** "T.C " where C is any column of table T and -** is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN". -** A subterm is also indexable if it is an AND of two or more -** subsubterms at least one of which is indexable. Indexable AND -** subterms have their eOperator set to WO_AND and they have -** u.pAndInfo set to a dynamically allocated WhereAndTerm object. -** -** From another point of view, "indexable" means that the subterm could -** potentially be used with an index if an appropriate index exists. -** This analysis does not consider whether or not the index exists; that -** is something the bestIndex() routine will determine. This analysis -** only looks at whether subterms appropriate for indexing exist. -** -** All examples A through E above all satisfy case 2. But if a term -** also statisfies case 1 (such as B) we know that the optimizer will -** always prefer case 1, so in that case we pretend that case 2 is not -** satisfied. -** -** It might be the case that multiple tables are indexable. For example, -** (E) above is indexable on tables P, Q, and R. -** -** Terms that satisfy case 2 are candidates for lookup by using -** separate indices to find rowids for each subterm and composing -** the union of all rowids using a RowSet object. This is similar -** to "bitmap indices" in other database engines. -** -** OTHERWISE: -** -** If neither case 1 nor case 2 apply, then leave the eOperator set to -** zero. This term is not useful for search. -*/ -static void exprAnalyzeOrTerm( - SrcList *pSrc, /* the FROM clause */ - WhereClause *pWC, /* the complete WHERE clause */ - int idxTerm /* Index of the OR-term to be analyzed */ -){ - Parse *pParse = pWC->pParse; /* Parser context */ - sqlite3 *db = pParse->db; /* Database connection */ - WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */ - Expr *pExpr = pTerm->pExpr; /* The expression of the term */ - WhereMaskSet *pMaskSet = pWC->pMaskSet; /* Table use masks */ - int i; /* Loop counters */ - WhereClause *pOrWc; /* Breakup of pTerm into subterms */ - WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */ - WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */ - Bitmask chngToIN; /* Tables that might satisfy case 1 */ - Bitmask indexable; /* Tables that are indexable, satisfying case 2 */ - - /* - ** Break the OR clause into its separate subterms. The subterms are - ** stored in a WhereClause structure containing within the WhereOrInfo - ** object that is attached to the original OR clause term. - */ - assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 ); - assert( pExpr->op==TK_OR ); - pTerm->u.pOrInfo = pOrInfo = sqlite3DbMallocZero(db, sizeof(*pOrInfo)); - if( pOrInfo==0 ) return; - pTerm->wtFlags |= TERM_ORINFO; - pOrWc = &pOrInfo->wc; - whereClauseInit(pOrWc, pWC->pParse, pMaskSet, pWC->wctrlFlags); - whereSplit(pOrWc, pExpr, TK_OR); - exprAnalyzeAll(pSrc, pOrWc); - if( db->mallocFailed ) return; - assert( pOrWc->nTerm>=2 ); - - /* - ** Compute the set of tables that might satisfy cases 1 or 2. - */ - indexable = ~(Bitmask)0; - chngToIN = ~(Bitmask)0; - for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ - if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ - WhereAndInfo *pAndInfo; - assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); - chngToIN = 0; - pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); - if( pAndInfo ){ - WhereClause *pAndWC; - WhereTerm *pAndTerm; - int j; - Bitmask b = 0; - pOrTerm->u.pAndInfo = pAndInfo; - pOrTerm->wtFlags |= TERM_ANDINFO; - pOrTerm->eOperator = WO_AND; - pAndWC = &pAndInfo->wc; - whereClauseInit(pAndWC, pWC->pParse, pMaskSet, pWC->wctrlFlags); - whereSplit(pAndWC, pOrTerm->pExpr, TK_AND); - exprAnalyzeAll(pSrc, pAndWC); - pAndWC->pOuter = pWC; - testcase( db->mallocFailed ); - if( !db->mallocFailed ){ - for(j=0, pAndTerm=pAndWC->a; jnTerm; j++, pAndTerm++){ - assert( pAndTerm->pExpr ); - if( allowedOp(pAndTerm->pExpr->op) ){ - b |= getMask(pMaskSet, pAndTerm->leftCursor); - } - } - } - indexable &= b; - } - }else if( pOrTerm->wtFlags & TERM_COPIED ){ - /* Skip this term for now. We revisit it when we process the - ** corresponding TERM_VIRTUAL term */ - }else{ - Bitmask b; - b = getMask(pMaskSet, pOrTerm->leftCursor); - if( pOrTerm->wtFlags & TERM_VIRTUAL ){ - WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; - b |= getMask(pMaskSet, pOther->leftCursor); - } - indexable &= b; - if( (pOrTerm->eOperator & WO_EQ)==0 ){ - chngToIN = 0; - }else{ - chngToIN &= b; - } - } - } - - /* - ** Record the set of tables that satisfy case 2. The set might be - ** empty. - */ - pOrInfo->indexable = indexable; - pTerm->eOperator = indexable==0 ? 0 : WO_OR; - - /* - ** chngToIN holds a set of tables that *might* satisfy case 1. But - ** we have to do some additional checking to see if case 1 really - ** is satisfied. - ** - ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means - ** that there is no possibility of transforming the OR clause into an - ** IN operator because one or more terms in the OR clause contain - ** something other than == on a column in the single table. The 1-bit - ** case means that every term of the OR clause is of the form - ** "table.column=expr" for some single table. The one bit that is set - ** will correspond to the common table. We still need to check to make - ** sure the same column is used on all terms. The 2-bit case is when - ** the all terms are of the form "table1.column=table2.column". It - ** might be possible to form an IN operator with either table1.column - ** or table2.column as the LHS if either is common to every term of - ** the OR clause. - ** - ** Note that terms of the form "table.column1=table.column2" (the - ** same table on both sizes of the ==) cannot be optimized. - */ - if( chngToIN ){ - int okToChngToIN = 0; /* True if the conversion to IN is valid */ - int iColumn = -1; /* Column index on lhs of IN operator */ - int iCursor = -1; /* Table cursor common to all terms */ - int j = 0; /* Loop counter */ - - /* Search for a table and column that appears on one side or the - ** other of the == operator in every subterm. That table and column - ** will be recorded in iCursor and iColumn. There might not be any - ** such table and column. Set okToChngToIN if an appropriate table - ** and column is found but leave okToChngToIN false if not found. - */ - for(j=0; j<2 && !okToChngToIN; j++){ - pOrTerm = pOrWc->a; - for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ - assert( pOrTerm->eOperator & WO_EQ ); - pOrTerm->wtFlags &= ~TERM_OR_OK; - if( pOrTerm->leftCursor==iCursor ){ - /* This is the 2-bit case and we are on the second iteration and - ** current term is from the first iteration. So skip this term. */ - assert( j==1 ); - continue; - } - if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){ - /* This term must be of the form t1.a==t2.b where t2 is in the - ** chngToIN set but t1 is not. This term will be either preceeded - ** or follwed by an inverted copy (t2.b==t1.a). Skip this term - ** and use its inversion. */ - testcase( pOrTerm->wtFlags & TERM_COPIED ); - testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); - assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) ); - continue; - } - iColumn = pOrTerm->u.leftColumn; - iCursor = pOrTerm->leftCursor; - break; - } - if( i<0 ){ - /* No candidate table+column was found. This can only occur - ** on the second iteration */ - assert( j==1 ); - assert( IsPowerOfTwo(chngToIN) ); - assert( chngToIN==getMask(pMaskSet, iCursor) ); - break; - } - testcase( j==1 ); - - /* We have found a candidate table and column. Check to see if that - ** table and column is common to every term in the OR clause */ - okToChngToIN = 1; - for(; i>=0 && okToChngToIN; i--, pOrTerm++){ - assert( pOrTerm->eOperator & WO_EQ ); - if( pOrTerm->leftCursor!=iCursor ){ - pOrTerm->wtFlags &= ~TERM_OR_OK; - }else if( pOrTerm->u.leftColumn!=iColumn ){ - okToChngToIN = 0; - }else{ - int affLeft, affRight; - /* If the right-hand side is also a column, then the affinities - ** of both right and left sides must be such that no type - ** conversions are required on the right. (Ticket #2249) - */ - affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight); - affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft); - if( affRight!=0 && affRight!=affLeft ){ - okToChngToIN = 0; - }else{ - pOrTerm->wtFlags |= TERM_OR_OK; - } - } - } - } - - /* At this point, okToChngToIN is true if original pTerm satisfies - ** case 1. In that case, construct a new virtual term that is - ** pTerm converted into an IN operator. - ** - ** EV: R-00211-15100 - */ - if( okToChngToIN ){ - Expr *pDup; /* A transient duplicate expression */ - ExprList *pList = 0; /* The RHS of the IN operator */ - Expr *pLeft = 0; /* The LHS of the IN operator */ - Expr *pNew; /* The complete IN operator */ - - for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ - if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; - assert( pOrTerm->eOperator & WO_EQ ); - assert( pOrTerm->leftCursor==iCursor ); - assert( pOrTerm->u.leftColumn==iColumn ); - pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); - pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup); - pLeft = pOrTerm->pExpr->pLeft; - } - assert( pLeft!=0 ); - pDup = sqlite3ExprDup(db, pLeft, 0); - pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0); - if( pNew ){ - int idxNew; - transferJoinMarkings(pNew, pExpr); - assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - pNew->x.pList = pList; - idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - exprAnalyze(pSrc, pWC, idxNew); - pTerm = &pWC->a[idxTerm]; - pWC->a[idxNew].iParent = idxTerm; - pTerm->nChild = 1; - }else{ - sqlite3ExprListDelete(db, pList); - } - pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ - } - } -} -#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ - -/* -** The input to this routine is an WhereTerm structure with only the -** "pExpr" field filled in. The job of this routine is to analyze the -** subexpression and populate all the other fields of the WhereTerm -** structure. -** -** If the expression is of the form " X" it gets commuted -** to the standard form of "X ". -** -** If the expression is of the form "X Y" where both X and Y are -** columns, then the original expression is unchanged and a new virtual -** term of the form "Y X" is added to the WHERE clause and -** analyzed separately. The original term is marked with TERM_COPIED -** and the new term is marked with TERM_DYNAMIC (because it's pExpr -** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it -** is a commuted copy of a prior term.) The original term has nChild=1 -** and the copy has idxParent set to the index of the original term. -*/ -static void exprAnalyze( - SrcList *pSrc, /* the FROM clause */ - WhereClause *pWC, /* the WHERE clause */ - int idxTerm /* Index of the term to be analyzed */ -){ - WhereTerm *pTerm; /* The term to be analyzed */ - WhereMaskSet *pMaskSet; /* Set of table index masks */ - Expr *pExpr; /* The expression to be analyzed */ - Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ - Bitmask prereqAll; /* Prerequesites of pExpr */ - Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ - Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ - int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ - int noCase = 0; /* LIKE/GLOB distinguishes case */ - int op; /* Top-level operator. pExpr->op */ - Parse *pParse = pWC->pParse; /* Parsing context */ - sqlite3 *db = pParse->db; /* Database connection */ - - if( db->mallocFailed ){ - return; - } - pTerm = &pWC->a[idxTerm]; - pMaskSet = pWC->pMaskSet; - pExpr = pTerm->pExpr; - assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); - prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); - op = pExpr->op; - if( op==TK_IN ){ - assert( pExpr->pRight==0 ); - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect); - }else{ - pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->x.pList); - } - }else if( op==TK_ISNULL ){ - pTerm->prereqRight = 0; - }else{ - pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); - } - prereqAll = exprTableUsage(pMaskSet, pExpr); - if( ExprHasProperty(pExpr, EP_FromJoin) ){ - Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable); - prereqAll |= x; - extraRight = x-1; /* ON clause terms may not be used with an index - ** on left table of a LEFT JOIN. Ticket #3015 */ - } - pTerm->prereqAll = prereqAll; - pTerm->leftCursor = -1; - pTerm->iParent = -1; - pTerm->eOperator = 0; - if( allowedOp(op) ){ - Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); - Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); - u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; - if( pLeft->op==TK_COLUMN ){ - pTerm->leftCursor = pLeft->iTable; - pTerm->u.leftColumn = pLeft->iColumn; - pTerm->eOperator = operatorMask(op) & opMask; - } - if( pRight && pRight->op==TK_COLUMN ){ - WhereTerm *pNew; - Expr *pDup; - u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ - if( pTerm->leftCursor>=0 ){ - int idxNew; - pDup = sqlite3ExprDup(db, pExpr, 0); - if( db->mallocFailed ){ - sqlite3ExprDelete(db, pDup); - return; - } - idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); - if( idxNew==0 ) return; - pNew = &pWC->a[idxNew]; - pNew->iParent = idxTerm; - pTerm = &pWC->a[idxTerm]; - pTerm->nChild = 1; - pTerm->wtFlags |= TERM_COPIED; - if( pExpr->op==TK_EQ - && !ExprHasProperty(pExpr, EP_FromJoin) - && OptimizationEnabled(db, SQLITE_Transitive) - ){ - pTerm->eOperator |= WO_EQUIV; - eExtraOp = WO_EQUIV; - } - }else{ - pDup = pExpr; - pNew = pTerm; - } - exprCommute(pParse, pDup); - pLeft = sqlite3ExprSkipCollate(pDup->pLeft); - pNew->leftCursor = pLeft->iTable; - pNew->u.leftColumn = pLeft->iColumn; - testcase( (prereqLeft | extraRight) != prereqLeft ); - pNew->prereqRight = prereqLeft | extraRight; - pNew->prereqAll = prereqAll; - pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; - } - } - -#ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION - /* If a term is the BETWEEN operator, create two new virtual terms - ** that define the range that the BETWEEN implements. For example: - ** - ** a BETWEEN b AND c - ** - ** is converted into: - ** - ** (a BETWEEN b AND c) AND (a>=b) AND (a<=c) - ** - ** The two new terms are added onto the end of the WhereClause object. - ** The new terms are "dynamic" and are children of the original BETWEEN - ** term. That means that if the BETWEEN term is coded, the children are - ** skipped. Or, if the children are satisfied by an index, the original - ** BETWEEN term is skipped. - */ - else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){ - ExprList *pList = pExpr->x.pList; - int i; - static const u8 ops[] = {TK_GE, TK_LE}; - assert( pList!=0 ); - assert( pList->nExpr==2 ); - for(i=0; i<2; i++){ - Expr *pNewExpr; - int idxNew; - pNewExpr = sqlite3PExpr(pParse, ops[i], - sqlite3ExprDup(db, pExpr->pLeft, 0), - sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0); - idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - exprAnalyze(pSrc, pWC, idxNew); - pTerm = &pWC->a[idxTerm]; - pWC->a[idxNew].iParent = idxTerm; - } - pTerm->nChild = 2; - } -#endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */ - -#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) - /* Analyze a term that is composed of two or more subterms connected by - ** an OR operator. - */ - else if( pExpr->op==TK_OR ){ - assert( pWC->op==TK_AND ); - exprAnalyzeOrTerm(pSrc, pWC, idxTerm); - pTerm = &pWC->a[idxTerm]; - } -#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ - -#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION - /* Add constraints to reduce the search space on a LIKE or GLOB - ** operator. - ** - ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints - ** - ** x>='abc' AND x<'abd' AND x LIKE 'abc%' - ** - ** The last character of the prefix "abc" is incremented to form the - ** termination condition "abd". - */ - if( pWC->op==TK_AND - && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase) - ){ - Expr *pLeft; /* LHS of LIKE/GLOB operator */ - Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ - Expr *pNewExpr1; - Expr *pNewExpr2; - int idxNew1; - int idxNew2; - Token sCollSeqName; /* Name of collating sequence */ - - pLeft = pExpr->x.pList->a[1].pExpr; - pStr2 = sqlite3ExprDup(db, pStr1, 0); - if( !db->mallocFailed ){ - u8 c, *pC; /* Last character before the first wildcard */ - pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; - c = *pC; - if( noCase ){ - /* The point is to increment the last character before the first - ** wildcard. But if we increment '@', that will push it into the - ** alphabetic range where case conversions will mess up the - ** inequality. To avoid this, make sure to also run the full - ** LIKE on all candidate expressions by clearing the isComplete flag - */ - if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */ - - - c = sqlite3UpperToLower[c]; - } - *pC = c + 1; - } - sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; - sCollSeqName.n = 6; - pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); - pNewExpr1 = sqlite3PExpr(pParse, TK_GE, - sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), - pStr1, 0); - idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew1==0 ); - exprAnalyze(pSrc, pWC, idxNew1); - pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); - pNewExpr2 = sqlite3PExpr(pParse, TK_LT, - sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), - pStr2, 0); - idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew2==0 ); - exprAnalyze(pSrc, pWC, idxNew2); - pTerm = &pWC->a[idxTerm]; - if( isComplete ){ - pWC->a[idxNew1].iParent = idxTerm; - pWC->a[idxNew2].iParent = idxTerm; - pTerm->nChild = 2; - } - } -#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE - /* Add a WO_MATCH auxiliary term to the constraint set if the - ** current expression is of the form: column MATCH expr. - ** This information is used by the xBestIndex methods of - ** virtual tables. The native query optimizer does not attempt - ** to do anything with MATCH functions. - */ - if( isMatchOfColumn(pExpr) ){ - int idxNew; - Expr *pRight, *pLeft; - WhereTerm *pNewTerm; - Bitmask prereqColumn, prereqExpr; - - pRight = pExpr->x.pList->a[0].pExpr; - pLeft = pExpr->x.pList->a[1].pExpr; - prereqExpr = exprTableUsage(pMaskSet, pRight); - prereqColumn = exprTableUsage(pMaskSet, pLeft); - if( (prereqExpr & prereqColumn)==0 ){ - Expr *pNewExpr; - pNewExpr = sqlite3PExpr(pParse, TK_MATCH, - 0, sqlite3ExprDup(db, pRight, 0), 0); - idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - pNewTerm = &pWC->a[idxNew]; - pNewTerm->prereqRight = prereqExpr; - pNewTerm->leftCursor = pLeft->iTable; - pNewTerm->u.leftColumn = pLeft->iColumn; - pNewTerm->eOperator = WO_MATCH; - pNewTerm->iParent = idxTerm; - pTerm = &pWC->a[idxTerm]; - pTerm->nChild = 1; - pTerm->wtFlags |= TERM_COPIED; - pNewTerm->prereqAll = pTerm->prereqAll; - } - } -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifdef SQLITE_ENABLE_STAT3 - /* When sqlite_stat3 histogram data is available an operator of the - ** form "x IS NOT NULL" can sometimes be evaluated more efficiently - ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a - ** virtual term of that form. - ** - ** Note that the virtual term must be tagged with TERM_VNULL. This - ** TERM_VNULL tag will suppress the not-null check at the beginning - ** of the loop. Without the TERM_VNULL flag, the not-null check at - ** the start of the loop will prevent any results from being returned. - */ - if( pExpr->op==TK_NOTNULL - && pExpr->pLeft->op==TK_COLUMN - && pExpr->pLeft->iColumn>=0 - ){ - Expr *pNewExpr; - Expr *pLeft = pExpr->pLeft; - int idxNew; - WhereTerm *pNewTerm; - - pNewExpr = sqlite3PExpr(pParse, TK_GT, - sqlite3ExprDup(db, pLeft, 0), - sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); - - idxNew = whereClauseInsert(pWC, pNewExpr, - TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); - if( idxNew ){ - pNewTerm = &pWC->a[idxNew]; - pNewTerm->prereqRight = 0; - pNewTerm->leftCursor = pLeft->iTable; - pNewTerm->u.leftColumn = pLeft->iColumn; - pNewTerm->eOperator = WO_GT; - pNewTerm->iParent = idxTerm; - pTerm = &pWC->a[idxTerm]; - pTerm->nChild = 1; - pTerm->wtFlags |= TERM_COPIED; - pNewTerm->prereqAll = pTerm->prereqAll; - } - } -#endif /* SQLITE_ENABLE_STAT */ - - /* Prevent ON clause terms of a LEFT JOIN from being used to drive - ** an index for tables to the left of the join. - */ - pTerm->prereqRight |= extraRight; -} - -/* -** This function searches the expression list passed as the second argument -** for an expression of type TK_COLUMN that refers to the same column and -** uses the same collation sequence as the iCol'th column of index pIdx. -** Argument iBase is the cursor number used for the table that pIdx refers -** to. -** -** If such an expression is found, its index in pList->a[] is returned. If -** no expression is found, -1 is returned. -*/ -static int findIndexCol( - Parse *pParse, /* Parse context */ - ExprList *pList, /* Expression list to search */ - int iBase, /* Cursor for table associated with pIdx */ - Index *pIdx, /* Index to match column of */ - int iCol /* Column of index to match */ -){ - int i; - const char *zColl = pIdx->azColl[iCol]; - - for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); - if( p->op==TK_COLUMN - && p->iColumn==pIdx->aiColumn[iCol] - && p->iTable==iBase - ){ - CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); - if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ - return i; - } - } - } - - return -1; -} - -/* -** This routine determines if pIdx can be used to assist in processing a -** DISTINCT qualifier. In other words, it tests whether or not using this -** index for the outer loop guarantees that rows with equal values for -** all expressions in the pDistinct list are delivered grouped together. -** -** For example, the query -** -** SELECT DISTINCT a, b, c FROM tbl WHERE a = ? -** -** can benefit from any index on columns "b" and "c". -*/ -static int isDistinctIndex( - Parse *pParse, /* Parsing context */ - WhereClause *pWC, /* The WHERE clause */ - Index *pIdx, /* The index being considered */ - int base, /* Cursor number for the table pIdx is on */ - ExprList *pDistinct, /* The DISTINCT expressions */ - int nEqCol /* Number of index columns with == */ -){ - Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */ - int i; /* Iterator variable */ - - assert( pDistinct!=0 ); - if( pIdx->zName==0 || pDistinct->nExpr>=BMS ) return 0; - testcase( pDistinct->nExpr==BMS-1 ); - - /* Loop through all the expressions in the distinct list. If any of them - ** are not simple column references, return early. Otherwise, test if the - ** WHERE clause contains a "col=X" clause. If it does, the expression - ** can be ignored. If it does not, and the column does not belong to the - ** same table as index pIdx, return early. Finally, if there is no - ** matching "col=X" expression and the column is on the same table as pIdx, - ** set the corresponding bit in variable mask. - */ - for(i=0; inExpr; i++){ - WhereTerm *pTerm; - Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); - if( p->op!=TK_COLUMN ) return 0; - pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); - if( pTerm ){ - Expr *pX = pTerm->pExpr; - CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); - CollSeq *p2 = sqlite3ExprCollSeq(pParse, p); - if( p1==p2 ) continue; - } - if( p->iTable!=base ) return 0; - mask |= (((Bitmask)1) << i); - } - - for(i=nEqCol; mask && inColumn; i++){ - int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i); - if( iExpr<0 ) break; - mask &= ~(((Bitmask)1) << iExpr); - } - - return (mask==0); -} - - -/* -** Return true if the DISTINCT expression-list passed as the third argument -** is redundant. A DISTINCT list is redundant if the database contains a -** UNIQUE index that guarantees that the result of the query will be distinct -** anyway. -*/ -static int isDistinctRedundant( - Parse *pParse, - SrcList *pTabList, - WhereClause *pWC, - ExprList *pDistinct -){ - Table *pTab; - Index *pIdx; - int i; - int iBase; - - /* If there is more than one table or sub-select in the FROM clause of - ** this query, then it will not be possible to show that the DISTINCT - ** clause is redundant. */ - if( pTabList->nSrc!=1 ) return 0; - iBase = pTabList->a[0].iCursor; - pTab = pTabList->a[0].pTab; - - /* If any of the expressions is an IPK column on table iBase, then return - ** true. Note: The (p->iTable==iBase) part of this test may be false if the - ** current SELECT is a correlated sub-query. - */ - for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); - if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; - } - - /* Loop through all indices on the table, checking each to see if it makes - ** the DISTINCT qualifier redundant. It does so if: - ** - ** 1. The index is itself UNIQUE, and - ** - ** 2. All of the columns in the index are either part of the pDistinct - ** list, or else the WHERE clause contains a term of the form "col=X", - ** where X is a constant value. The collation sequences of the - ** comparison and select-list expressions must match those of the index. - ** - ** 3. All of those index columns for which the WHERE clause does not - ** contain a "col=X" term are subject to a NOT NULL constraint. - */ - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->onError==OE_None ) continue; - for(i=0; inColumn; i++){ - int iCol = pIdx->aiColumn[i]; - if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){ - int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i); - if( iIdxCol<0 || pTab->aCol[pIdx->aiColumn[i]].notNull==0 ){ - break; - } - } - } - if( i==pIdx->nColumn ){ - /* This index implies that the DISTINCT qualifier is redundant. */ - return 1; - } - } - - return 0; -} - -/* -** Prepare a crude estimate of the logarithm of the input value. -** The results need not be exact. This is only used for estimating -** the total cost of performing operations with O(logN) or O(NlogN) -** complexity. Because N is just a guess, it is no great tragedy if -** logN is a little off. -*/ -static double estLog(double N){ - double logN = 1; - double x = 10; - while( N>x ){ - logN += 1; - x *= 10; - } - return logN; -} - -/* -** Two routines for printing the content of an sqlite3_index_info -** structure. Used for testing and debugging only. If neither -** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines -** are no-ops. -*/ -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG) -static void TRACE_IDX_INPUTS(sqlite3_index_info *p){ - int i; - if( !sqlite3WhereTrace ) return; - for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", - i, - p->aConstraint[i].iColumn, - p->aConstraint[i].iTermOffset, - p->aConstraint[i].op, - p->aConstraint[i].usable); - } - for(i=0; inOrderBy; i++){ - sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", - i, - p->aOrderBy[i].iColumn, - p->aOrderBy[i].desc); - } -} -static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){ - int i; - if( !sqlite3WhereTrace ) return; - for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", - i, - p->aConstraintUsage[i].argvIndex, - p->aConstraintUsage[i].omit); - } - sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum); - sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr); - sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); - sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); -} -#else -#define TRACE_IDX_INPUTS(A) -#define TRACE_IDX_OUTPUTS(A) -#endif - -/* -** Required because bestIndex() is called by bestOrClauseIndex() -*/ -static void bestIndex(WhereBestIdx*); - -/* -** This routine attempts to find an scanning strategy that can be used -** to optimize an 'OR' expression that is part of a WHERE clause. -** -** The table associated with FROM clause term pSrc may be either a -** regular B-Tree table or a virtual table. -*/ -static void bestOrClauseIndex(WhereBestIdx *p){ -#ifndef SQLITE_OMIT_OR_OPTIMIZATION - WhereClause *pWC = p->pWC; /* The WHERE clause */ - struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ - const int iCur = pSrc->iCursor; /* The cursor of the table */ - const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */ - WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - - /* The OR-clause optimization is disallowed if the INDEXED BY or - ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */ - if( pSrc->notIndexed || pSrc->pIndex!=0 ){ - return; - } - if( pWC->wctrlFlags & WHERE_AND_ONLY ){ - return; - } - - /* Search the WHERE clause terms for a usable WO_OR term. */ - for(pTerm=pWC->a; pTermeOperator & WO_OR)!=0 - && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0 - && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 - ){ - WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; - WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; - WhereTerm *pOrTerm; - int flags = WHERE_MULTI_OR; - double rTotal = 0; - double nRow = 0; - Bitmask used = 0; - WhereBestIdx sBOI; - - sBOI = *p; - sBOI.pOrderBy = 0; - sBOI.pDistinct = 0; - sBOI.ppIdxInfo = 0; - for(pOrTerm=pOrWC->a; pOrTerma), (pTerm - pWC->a) - )); - if( (pOrTerm->eOperator& WO_AND)!=0 ){ - sBOI.pWC = &pOrTerm->u.pAndInfo->wc; - bestIndex(&sBOI); - }else if( pOrTerm->leftCursor==iCur ){ - WhereClause tempWC; - tempWC.pParse = pWC->pParse; - tempWC.pMaskSet = pWC->pMaskSet; - tempWC.pOuter = pWC; - tempWC.op = TK_AND; - tempWC.a = pOrTerm; - tempWC.wctrlFlags = 0; - tempWC.nTerm = 1; - sBOI.pWC = &tempWC; - bestIndex(&sBOI); - }else{ - continue; - } - rTotal += sBOI.cost.rCost; - nRow += sBOI.cost.plan.nRow; - used |= sBOI.cost.used; - if( rTotal>=p->cost.rCost ) break; - } - - /* If there is an ORDER BY clause, increase the scan cost to account - ** for the cost of the sort. */ - if( p->pOrderBy!=0 ){ - WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n", - rTotal, rTotal+nRow*estLog(nRow))); - rTotal += nRow*estLog(nRow); - } - - /* If the cost of scanning using this OR term for optimization is - ** less than the current cost stored in pCost, replace the contents - ** of pCost. */ - WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow)); - if( rTotalcost.rCost ){ - p->cost.rCost = rTotal; - p->cost.used = used; - p->cost.plan.nRow = nRow; - p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0; - p->cost.plan.wsFlags = flags; - p->cost.plan.u.pTerm = pTerm; - } - } - } -#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ -} - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX -/* -** Return TRUE if the WHERE clause term pTerm is of a form where it -** could be used with an index to access pSrc, assuming an appropriate -** index existed. -*/ -static int termCanDriveIndex( - WhereTerm *pTerm, /* WHERE clause term to check */ - struct SrcList_item *pSrc, /* Table we are trying to access */ - Bitmask notReady /* Tables in outer loops of the join */ -){ - char aff; - if( pTerm->leftCursor!=pSrc->iCursor ) return 0; - if( (pTerm->eOperator & WO_EQ)==0 ) return 0; - if( (pTerm->prereqRight & notReady)!=0 ) return 0; - aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; - if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; - return 1; -} -#endif - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX -/* -** If the query plan for pSrc specified in pCost is a full table scan -** and indexing is allows (if there is no NOT INDEXED clause) and it -** possible to construct a transient index that would perform better -** than a full table scan even when the cost of constructing the index -** is taken into account, then alter the query plan to use the -** transient index. -*/ -static void bestAutomaticIndex(WhereBestIdx *p){ - Parse *pParse = p->pParse; /* The parsing context */ - WhereClause *pWC = p->pWC; /* The WHERE clause */ - struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ - double nTableRow; /* Rows in the input table */ - double logN; /* log(nTableRow) */ - double costTempIdx; /* per-query cost of the transient index */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - WhereTerm *pWCEnd; /* End of pWC->a[] */ - Table *pTable; /* Table tht might be indexed */ - - if( pParse->nQueryLoop<=(double)1 ){ - /* There is no point in building an automatic index for a single scan */ - return; - } - if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){ - /* Automatic indices are disabled at run-time */ - return; - } - if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 - && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0 - ){ - /* We already have some kind of index in use for this query. */ - return; - } - if( pSrc->viaCoroutine ){ - /* Cannot index a co-routine */ - return; - } - if( pSrc->notIndexed ){ - /* The NOT INDEXED clause appears in the SQL. */ - return; - } - if( pSrc->isCorrelated ){ - /* The source is a correlated sub-query. No point in indexing it. */ - return; - } - - assert( pParse->nQueryLoop >= (double)1 ); - pTable = pSrc->pTab; - nTableRow = pTable->nRowEst; - logN = estLog(nTableRow); - costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1); - if( costTempIdx>=p->cost.rCost ){ - /* The cost of creating the transient table would be greater than - ** doing the full table scan */ - return; - } - - /* Search for any equality comparison term */ - pWCEnd = &pWC->a[pWC->nTerm]; - for(pTerm=pWC->a; pTermnotReady) ){ - WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n", - p->cost.rCost, costTempIdx)); - p->cost.rCost = costTempIdx; - p->cost.plan.nRow = logN + 1; - p->cost.plan.wsFlags = WHERE_TEMP_INDEX; - p->cost.used = pTerm->prereqRight; - break; - } - } -} -#else -# define bestAutomaticIndex(A) /* no-op */ -#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - - -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX -/* -** Generate code to construct the Index object for an automatic index -** and to set up the WhereLevel object pLevel so that the code generator -** makes use of the automatic index. -*/ -static void constructAutomaticIndex( - Parse *pParse, /* The parsing context */ - WhereClause *pWC, /* The WHERE clause */ - struct SrcList_item *pSrc, /* The FROM clause term to get the next index */ - Bitmask notReady, /* Mask of cursors that are not available */ - WhereLevel *pLevel /* Write new index here */ -){ - int nColumn; /* Number of columns in the constructed index */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ - WhereTerm *pWCEnd; /* End of pWC->a[] */ - int nByte; /* Byte of memory needed for pIdx */ - Index *pIdx; /* Object describing the transient index */ - Vdbe *v; /* Prepared statement under construction */ - int addrInit; /* Address of the initialization bypass jump */ - Table *pTable; /* The table being indexed */ - KeyInfo *pKeyinfo; /* Key information for the index */ - int addrTop; /* Top of the index fill loop */ - int regRecord; /* Register holding an index record */ - int n; /* Column counter */ - int i; /* Loop counter */ - int mxBitCol; /* Maximum column in pSrc->colUsed */ - CollSeq *pColl; /* Collating sequence to on a column */ - Bitmask idxCols; /* Bitmap of columns used for indexing */ - Bitmask extraCols; /* Bitmap of additional columns */ - - /* Generate code to skip over the creation and initialization of the - ** transient index on 2nd and subsequent iterations of the loop. */ - v = pParse->pVdbe; - assert( v!=0 ); - addrInit = sqlite3CodeOnce(pParse); - - /* Count the number of columns that will be added to the index - ** and used to match WHERE clause constraints */ - nColumn = 0; - pTable = pSrc->pTab; - pWCEnd = &pWC->a[pWC->nTerm]; - idxCols = 0; - for(pTerm=pWC->a; pTermu.leftColumn; - Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<0 ); - pLevel->plan.nEq = nColumn; - - /* Count the number of additional columns needed to create a - ** covering index. A "covering index" is an index that contains all - ** columns that are needed by the query. With a covering index, the - ** original table never needs to be accessed. Automatic indices must - ** be a covering index because the index will not be updated if the - ** original table changes and the index and table cannot both be used - ** if they go out of sync. - */ - extraCols = pSrc->colUsed & (~idxCols | (((Bitmask)1)<<(BMS-1))); - mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol; - testcase( pTable->nCol==BMS-1 ); - testcase( pTable->nCol==BMS-2 ); - for(i=0; icolUsed & (((Bitmask)1)<<(BMS-1)) ){ - nColumn += pTable->nCol - BMS + 1; - } - pLevel->plan.wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WO_EQ; - - /* Construct the Index object to describe this index */ - nByte = sizeof(Index); - nByte += nColumn*sizeof(int); /* Index.aiColumn */ - nByte += nColumn*sizeof(char*); /* Index.azColl */ - nByte += nColumn; /* Index.aSortOrder */ - pIdx = sqlite3DbMallocZero(pParse->db, nByte); - if( pIdx==0 ) return; - pLevel->plan.u.pIdx = pIdx; - pIdx->azColl = (char**)&pIdx[1]; - pIdx->aiColumn = (int*)&pIdx->azColl[nColumn]; - pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn]; - pIdx->zName = "auto-index"; - pIdx->nColumn = nColumn; - pIdx->pTable = pTable; - n = 0; - idxCols = 0; - for(pTerm=pWC->a; pTermu.leftColumn; - Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<pExpr; - idxCols |= cMask; - pIdx->aiColumn[n] = pTerm->u.leftColumn; - pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); - pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY"; - n++; - } - } - } - assert( (u32)n==pLevel->plan.nEq ); - - /* Add additional columns needed to make the automatic index into - ** a covering index */ - for(i=0; iaiColumn[n] = i; - pIdx->azColl[n] = "BINARY"; - n++; - } - } - if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){ - for(i=BMS-1; inCol; i++){ - pIdx->aiColumn[n] = i; - pIdx->azColl[n] = "BINARY"; - n++; - } - } - assert( n==nColumn ); - - /* Create the automatic index */ - pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx); - assert( pLevel->iIdxCur>=0 ); - sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0, - (char*)pKeyinfo, P4_KEYINFO_HANDOFF); - VdbeComment((v, "for %s", pTable->zName)); - - /* Fill the automatic index with content */ - addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); - regRecord = sqlite3GetTempReg(pParse); - sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); - sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); - sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); - sqlite3VdbeJumpHere(v, addrTop); - sqlite3ReleaseTempReg(pParse, regRecord); - - /* Jump here when skipping the initialization */ - sqlite3VdbeJumpHere(v, addrInit); -} -#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ - -#ifndef SQLITE_OMIT_VIRTUALTABLE -/* -** Allocate and populate an sqlite3_index_info structure. It is the -** responsibility of the caller to eventually release the structure -** by passing the pointer returned by this function to sqlite3_free(). -*/ -static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){ - Parse *pParse = p->pParse; - WhereClause *pWC = p->pWC; - struct SrcList_item *pSrc = p->pSrc; - ExprList *pOrderBy = p->pOrderBy; - int i, j; - int nTerm; - struct sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_orderby *pIdxOrderBy; - struct sqlite3_index_constraint_usage *pUsage; - WhereTerm *pTerm; - int nOrderBy; - sqlite3_index_info *pIdxInfo; - - WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName)); - - /* Count the number of possible WHERE clause constraints referring - ** to this virtual table */ - for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - if( pTerm->leftCursor != pSrc->iCursor ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_ISNULL ); - if( pTerm->eOperator & (WO_ISNULL) ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - nTerm++; - } - - /* If the ORDER BY clause contains only columns in the current - ** virtual table then allocate space for the aOrderBy part of - ** the sqlite3_index_info structure. - */ - nOrderBy = 0; - if( pOrderBy ){ - int n = pOrderBy->nExpr; - for(i=0; ia[i].pExpr; - if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; - } - if( i==n){ - nOrderBy = n; - } - } - - /* Allocate the sqlite3_index_info structure - */ - pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) - + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm - + sizeof(*pIdxOrderBy)*nOrderBy ); - if( pIdxInfo==0 ){ - sqlite3ErrorMsg(pParse, "out of memory"); - /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - return 0; - } - - /* Initialize the structure. The sqlite3_index_info structure contains - ** many fields that are declared "const" to prevent xBestIndex from - ** changing them. We have to do some funky casting in order to - ** initialize those fields. - */ - pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; - pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; - pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; - *(int*)&pIdxInfo->nConstraint = nTerm; - *(int*)&pIdxInfo->nOrderBy = nOrderBy; - *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; - *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; - *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = - pUsage; - - for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - u8 op; - if( pTerm->leftCursor != pSrc->iCursor ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_ISNULL ); - if( pTerm->eOperator & (WO_ISNULL) ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - pIdxCons[j].iColumn = pTerm->u.leftColumn; - pIdxCons[j].iTermOffset = i; - op = (u8)pTerm->eOperator & WO_ALL; - if( op==WO_IN ) op = WO_EQ; - pIdxCons[j].op = op; - /* The direct assignment in the previous line is possible only because - ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The - ** following asserts verify this fact. */ - assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); - assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); - assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); - assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); - assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); - assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); - assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); - j++; - } - for(i=0; ia[i].pExpr; - pIdxOrderBy[i].iColumn = pExpr->iColumn; - pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; - } - - return pIdxInfo; -} - -/* -** The table object reference passed as the second argument to this function -** must represent a virtual table. This function invokes the xBestIndex() -** method of the virtual table with the sqlite3_index_info pointer passed -** as the argument. -** -** If an error occurs, pParse is populated with an error message and a -** non-zero value is returned. Otherwise, 0 is returned and the output -** part of the sqlite3_index_info structure is left populated. -** -** Whether or not an error is returned, it is the responsibility of the -** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates -** that this is required. -*/ -static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ - sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; - int i; - int rc; - - WHERETRACE(("xBestIndex for %s\n", pTab->zName)); - TRACE_IDX_INPUTS(p); - rc = pVtab->pModule->xBestIndex(pVtab, p); - TRACE_IDX_OUTPUTS(p); - - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ){ - pParse->db->mallocFailed = 1; - }else if( !pVtab->zErrMsg ){ - sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); - }else{ - sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); - } - } - sqlite3_free(pVtab->zErrMsg); - pVtab->zErrMsg = 0; - - for(i=0; inConstraint; i++){ - if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ - sqlite3ErrorMsg(pParse, - "table %s: xBestIndex returned an invalid plan", pTab->zName); - } - } - - return pParse->nErr; -} - - -/* -** Compute the best index for a virtual table. -** -** The best index is computed by the xBestIndex method of the virtual -** table module. This routine is really just a wrapper that sets up -** the sqlite3_index_info structure that is used to communicate with -** xBestIndex. -** -** In a join, this routine might be called multiple times for the -** same virtual table. The sqlite3_index_info structure is created -** and initialized on the first invocation and reused on all subsequent -** invocations. The sqlite3_index_info structure is also used when -** code is generated to access the virtual table. The whereInfoDelete() -** routine takes care of freeing the sqlite3_index_info structure after -** everybody has finished with it. -*/ -static void bestVirtualIndex(WhereBestIdx *p){ - Parse *pParse = p->pParse; /* The parsing context */ - WhereClause *pWC = p->pWC; /* The WHERE clause */ - struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ - Table *pTab = pSrc->pTab; - sqlite3_index_info *pIdxInfo; - struct sqlite3_index_constraint *pIdxCons; - struct sqlite3_index_constraint_usage *pUsage; - WhereTerm *pTerm; - int i, j; - int nOrderBy; - int bAllowIN; /* Allow IN optimizations */ - double rCost; - - /* Make sure wsFlags is initialized to some sane value. Otherwise, if the - ** malloc in allocateIndexInfo() fails and this function returns leaving - ** wsFlags in an uninitialized state, the caller may behave unpredictably. - */ - memset(&p->cost, 0, sizeof(p->cost)); - p->cost.plan.wsFlags = WHERE_VIRTUALTABLE; - - /* If the sqlite3_index_info structure has not been previously - ** allocated and initialized, then allocate and initialize it now. - */ - pIdxInfo = *p->ppIdxInfo; - if( pIdxInfo==0 ){ - *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p); - } - if( pIdxInfo==0 ){ - return; - } - - /* At this point, the sqlite3_index_info structure that pIdxInfo points - ** to will have been initialized, either during the current invocation or - ** during some prior invocation. Now we just have to customize the - ** details of pIdxInfo for the current invocation and pass it to - ** xBestIndex. - */ - - /* The module name must be defined. Also, by this point there must - ** be a pointer to an sqlite3_vtab structure. Otherwise - ** sqlite3ViewGetColumnNames() would have picked up the error. - */ - assert( pTab->azModuleArg && pTab->azModuleArg[0] ); - assert( sqlite3GetVTable(pParse->db, pTab) ); - - /* Try once or twice. On the first attempt, allow IN optimizations. - ** If an IN optimization is accepted by the virtual table xBestIndex - ** method, but the pInfo->aConstrainUsage.omit flag is not set, then - ** the query will not work because it might allow duplicate rows in - ** output. In that case, run the xBestIndex method a second time - ** without the IN constraints. Usually this loop only runs once. - ** The loop will exit using a "break" statement. - */ - for(bAllowIN=1; 1; bAllowIN--){ - assert( bAllowIN==0 || bAllowIN==1 ); - - /* Set the aConstraint[].usable fields and initialize all - ** output variables to zero. - ** - ** aConstraint[].usable is true for constraints where the right-hand - ** side contains only references to tables to the left of the current - ** table. In other words, if the constraint is of the form: - ** - ** column = expr - ** - ** and we are evaluating a join, then the constraint on column is - ** only valid if all tables referenced in expr occur to the left - ** of the table containing column. - ** - ** The aConstraints[] array contains entries for all constraints - ** on the current table. That way we only have to compute it once - ** even though we might try to pick the best index multiple times. - ** For each attempt at picking an index, the order of tables in the - ** join might be different so we have to recompute the usable flag - ** each time. - */ - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; - pUsage = pIdxInfo->aConstraintUsage; - for(i=0; inConstraint; i++, pIdxCons++){ - j = pIdxCons->iTermOffset; - pTerm = &pWC->a[j]; - if( (pTerm->prereqRight&p->notReady)==0 - && (bAllowIN || (pTerm->eOperator & WO_IN)==0) - ){ - pIdxCons->usable = 1; - }else{ - pIdxCons->usable = 0; - } - } - memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); - if( pIdxInfo->needToFreeIdxStr ){ - sqlite3_free(pIdxInfo->idxStr); - } - pIdxInfo->idxStr = 0; - pIdxInfo->idxNum = 0; - pIdxInfo->needToFreeIdxStr = 0; - pIdxInfo->orderByConsumed = 0; - /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ - pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); - nOrderBy = pIdxInfo->nOrderBy; - if( !p->pOrderBy ){ - pIdxInfo->nOrderBy = 0; - } - - if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ - return; - } - - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; - for(i=0; inConstraint; i++, pIdxCons++){ - if( pUsage[i].argvIndex>0 ){ - j = pIdxCons->iTermOffset; - pTerm = &pWC->a[j]; - p->cost.used |= pTerm->prereqRight; - if( (pTerm->eOperator & WO_IN)!=0 ){ - if( pUsage[i].omit==0 ){ - /* Do not attempt to use an IN constraint if the virtual table - ** says that the equivalent EQ constraint cannot be safely omitted. - ** If we do attempt to use such a constraint, some rows might be - ** repeated in the output. */ - break; - } - /* A virtual table that is constrained by an IN clause may not - ** consume the ORDER BY clause because (1) the order of IN terms - ** is not necessarily related to the order of output terms and - ** (2) Multiple outputs from a single IN value will not merge - ** together. */ - pIdxInfo->orderByConsumed = 0; - } - } - } - if( i>=pIdxInfo->nConstraint ) break; - } - - /* The orderByConsumed signal is only valid if all outer loops collectively - ** generate just a single row of output. - */ - if( pIdxInfo->orderByConsumed ){ - for(i=0; ii; i++){ - if( (p->aLevel[i].plan.wsFlags & WHERE_UNIQUE)==0 ){ - pIdxInfo->orderByConsumed = 0; - } - } - } - - /* If there is an ORDER BY clause, and the selected virtual table index - ** does not satisfy it, increase the cost of the scan accordingly. This - ** matches the processing for non-virtual tables in bestBtreeIndex(). - */ - rCost = pIdxInfo->estimatedCost; - if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){ - rCost += estLog(rCost)*rCost; - } - - /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the - ** inital value of lowestCost in this loop. If it is, then the - ** (costcost.rCost = (SQLITE_BIG_DBL/((double)2)); - }else{ - p->cost.rCost = rCost; - } - p->cost.plan.u.pVtabIdx = pIdxInfo; - if( pIdxInfo->orderByConsumed ){ - p->cost.plan.wsFlags |= WHERE_ORDERED; - p->cost.plan.nOBSat = nOrderBy; - }else{ - p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0; - } - p->cost.plan.nEq = 0; - pIdxInfo->nOrderBy = nOrderBy; - - /* Try to find a more efficient access pattern by using multiple indexes - ** to optimize an OR expression within the WHERE clause. - */ - bestOrClauseIndex(p); -} -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - -#ifdef SQLITE_ENABLE_STAT3 -/* -** Estimate the location of a particular key among all keys in an -** index. Store the results in aStat as follows: -** -** aStat[0] Est. number of rows less than pVal -** aStat[1] Est. number of rows equal to pVal -** -** Return SQLITE_OK on success. -*/ -static int whereKeyStats( - Parse *pParse, /* Database connection */ - Index *pIdx, /* Index to consider domain of */ - sqlite3_value *pVal, /* Value to consider */ - int roundUp, /* Round up if true. Round down if false */ - tRowcnt *aStat /* OUT: stats written here */ -){ - tRowcnt n; - IndexSample *aSample; - int i, eType; - int isEq = 0; - i64 v; - double r, rS; - - assert( roundUp==0 || roundUp==1 ); - assert( pIdx->nSample>0 ); - if( pVal==0 ) return SQLITE_ERROR; - n = pIdx->aiRowEst[0]; - aSample = pIdx->aSample; - eType = sqlite3_value_type(pVal); - - if( eType==SQLITE_INTEGER ){ - v = sqlite3_value_int64(pVal); - r = (i64)v; - for(i=0; inSample; i++){ - if( aSample[i].eType==SQLITE_NULL ) continue; - if( aSample[i].eType>=SQLITE_TEXT ) break; - if( aSample[i].eType==SQLITE_INTEGER ){ - if( aSample[i].u.i>=v ){ - isEq = aSample[i].u.i==v; - break; - } - }else{ - assert( aSample[i].eType==SQLITE_FLOAT ); - if( aSample[i].u.r>=r ){ - isEq = aSample[i].u.r==r; - break; - } - } - } - }else if( eType==SQLITE_FLOAT ){ - r = sqlite3_value_double(pVal); - for(i=0; inSample; i++){ - if( aSample[i].eType==SQLITE_NULL ) continue; - if( aSample[i].eType>=SQLITE_TEXT ) break; - if( aSample[i].eType==SQLITE_FLOAT ){ - rS = aSample[i].u.r; - }else{ - rS = aSample[i].u.i; - } - if( rS>=r ){ - isEq = rS==r; - break; - } - } - }else if( eType==SQLITE_NULL ){ - i = 0; - if( aSample[0].eType==SQLITE_NULL ) isEq = 1; - }else{ - assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); - for(i=0; inSample; i++){ - if( aSample[i].eType==SQLITE_TEXT || aSample[i].eType==SQLITE_BLOB ){ - break; - } - } - if( inSample ){ - sqlite3 *db = pParse->db; - CollSeq *pColl; - const u8 *z; - if( eType==SQLITE_BLOB ){ - z = (const u8 *)sqlite3_value_blob(pVal); - pColl = db->pDfltColl; - assert( pColl->enc==SQLITE_UTF8 ); - }else{ - pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl); - if( pColl==0 ){ - return SQLITE_ERROR; - } - z = (const u8 *)sqlite3ValueText(pVal, pColl->enc); - if( !z ){ - return SQLITE_NOMEM; - } - assert( z && pColl && pColl->xCmp ); - } - n = sqlite3ValueBytes(pVal, pColl->enc); - - for(; inSample; i++){ - int c; - int eSampletype = aSample[i].eType; - if( eSampletypeenc!=SQLITE_UTF8 ){ - int nSample; - char *zSample = sqlite3Utf8to16( - db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample - ); - if( !zSample ){ - assert( db->mallocFailed ); - return SQLITE_NOMEM; - } - c = pColl->xCmp(pColl->pUser, nSample, zSample, n, z); - sqlite3DbFree(db, zSample); - }else -#endif - { - c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z); - } - if( c>=0 ){ - if( c==0 ) isEq = 1; - break; - } - } - } - } - - /* At this point, aSample[i] is the first sample that is greater than - ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less - ** than pVal. If aSample[i]==pVal, then isEq==1. - */ - if( isEq ){ - assert( inSample ); - aStat[0] = aSample[i].nLt; - aStat[1] = aSample[i].nEq; - }else{ - tRowcnt iLower, iUpper, iGap; - if( i==0 ){ - iLower = 0; - iUpper = aSample[0].nLt; - }else{ - iUpper = i>=pIdx->nSample ? n : aSample[i].nLt; - iLower = aSample[i-1].nEq + aSample[i-1].nLt; - } - aStat[1] = pIdx->avgEq; - if( iLower>=iUpper ){ - iGap = 0; - }else{ - iGap = iUpper - iLower; - } - if( roundUp ){ - iGap = (iGap*2)/3; - }else{ - iGap = iGap/3; - } - aStat[0] = iLower + iGap; - } - return SQLITE_OK; -} -#endif /* SQLITE_ENABLE_STAT3 */ - -/* -** If expression pExpr represents a literal value, set *pp to point to -** an sqlite3_value structure containing the same value, with affinity -** aff applied to it, before returning. It is the responsibility of the -** caller to eventually release this structure by passing it to -** sqlite3ValueFree(). -** -** If the current parse is a recompile (sqlite3Reprepare()) and pExpr -** is an SQL variable that currently has a non-NULL value bound to it, -** create an sqlite3_value structure containing this value, again with -** affinity aff applied to it, instead. -** -** If neither of the above apply, set *pp to NULL. -** -** If an error occurs, return an error code. Otherwise, SQLITE_OK. -*/ -#ifdef SQLITE_ENABLE_STAT3 -static int valueFromExpr( - Parse *pParse, - Expr *pExpr, - u8 aff, - sqlite3_value **pp -){ - if( pExpr->op==TK_VARIABLE - || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE) - ){ - int iVar = pExpr->iColumn; - sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); - *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff); - return SQLITE_OK; - } - return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp); -} -#endif - -/* -** This function is used to estimate the number of rows that will be visited -** by scanning an index for a range of values. The range may have an upper -** bound, a lower bound, or both. The WHERE clause terms that set the upper -** and lower bounds are represented by pLower and pUpper respectively. For -** example, assuming that index p is on t1(a): -** -** ... FROM t1 WHERE a > ? AND a < ? ... -** |_____| |_____| -** | | -** pLower pUpper -** -** If either of the upper or lower bound is not present, then NULL is passed in -** place of the corresponding WhereTerm. -** -** The nEq parameter is passed the index of the index column subject to the -** range constraint. Or, equivalently, the number of equality constraints -** optimized by the proposed index scan. For example, assuming index p is -** on t1(a, b), and the SQL query is: -** -** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... -** -** then nEq should be passed the value 1 (as the range restricted column, -** b, is the second left-most column of the index). Or, if the query is: -** -** ... FROM t1 WHERE a > ? AND a < ? ... -** -** then nEq should be passed 0. -** -** The returned value is an integer divisor to reduce the estimated -** search space. A return value of 1 means that range constraints are -** no help at all. A return value of 2 means range constraints are -** expected to reduce the search space by half. And so forth... -** -** In the absence of sqlite_stat3 ANALYZE data, each range inequality -** reduces the search space by a factor of 4. Hence a single constraint (x>?) -** results in a return of 4 and a range constraint (x>? AND xaCol[] of the range-compared column */ - WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ - WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ - double *pRangeDiv /* OUT: Reduce search space by this divisor */ -){ - int rc = SQLITE_OK; - -#ifdef SQLITE_ENABLE_STAT3 - - if( nEq==0 && p->nSample ){ - sqlite3_value *pRangeVal; - tRowcnt iLower = 0; - tRowcnt iUpper = p->aiRowEst[0]; - tRowcnt a[2]; - u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; - - if( pLower ){ - Expr *pExpr = pLower->pExpr->pRight; - rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); - assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 ); - if( rc==SQLITE_OK - && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK - ){ - iLower = a[0]; - if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1]; - } - sqlite3ValueFree(pRangeVal); - } - if( rc==SQLITE_OK && pUpper ){ - Expr *pExpr = pUpper->pExpr->pRight; - rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); - assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); - if( rc==SQLITE_OK - && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK - ){ - iUpper = a[0]; - if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1]; - } - sqlite3ValueFree(pRangeVal); - } - if( rc==SQLITE_OK ){ - if( iUpper<=iLower ){ - *pRangeDiv = (double)p->aiRowEst[0]; - }else{ - *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower); - } - WHERETRACE(("range scan regions: %u..%u div=%g\n", - (u32)iLower, (u32)iUpper, *pRangeDiv)); - return SQLITE_OK; - } - } -#else - UNUSED_PARAMETER(pParse); - UNUSED_PARAMETER(p); - UNUSED_PARAMETER(nEq); -#endif - assert( pLower || pUpper ); - *pRangeDiv = (double)1; - if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4; - if( pUpper ) *pRangeDiv *= (double)4; - return rc; -} - -#ifdef SQLITE_ENABLE_STAT3 -/* -** Estimate the number of rows that will be returned based on -** an equality constraint x=VALUE and where that VALUE occurs in -** the histogram data. This only works when x is the left-most -** column of an index and sqlite_stat3 histogram data is available -** for that index. When pExpr==NULL that means the constraint is -** "x IS NULL" instead of "x=VALUE". -** -** Write the estimated row count into *pnRow and return SQLITE_OK. -** If unable to make an estimate, leave *pnRow unchanged and return -** non-zero. -** -** This routine can fail if it is unable to load a collating sequence -** required for string comparison, or if unable to allocate memory -** for a UTF conversion required for comparison. The error is stored -** in the pParse structure. -*/ -static int whereEqualScanEst( - Parse *pParse, /* Parsing & code generating context */ - Index *p, /* The index whose left-most column is pTerm */ - Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ - double *pnRow /* Write the revised row estimate here */ -){ - sqlite3_value *pRhs = 0; /* VALUE on right-hand side of pTerm */ - u8 aff; /* Column affinity */ - int rc; /* Subfunction return code */ - tRowcnt a[2]; /* Statistics */ - - assert( p->aSample!=0 ); - assert( p->nSample>0 ); - aff = p->pTable->aCol[p->aiColumn[0]].affinity; - if( pExpr ){ - rc = valueFromExpr(pParse, pExpr, aff, &pRhs); - if( rc ) goto whereEqualScanEst_cancel; - }else{ - pRhs = sqlite3ValueNew(pParse->db); - } - if( pRhs==0 ) return SQLITE_NOTFOUND; - rc = whereKeyStats(pParse, p, pRhs, 0, a); - if( rc==SQLITE_OK ){ - WHERETRACE(("equality scan regions: %d\n", (int)a[1])); - *pnRow = a[1]; - } -whereEqualScanEst_cancel: - sqlite3ValueFree(pRhs); - return rc; -} -#endif /* defined(SQLITE_ENABLE_STAT3) */ - -#ifdef SQLITE_ENABLE_STAT3 -/* -** Estimate the number of rows that will be returned based on -** an IN constraint where the right-hand side of the IN operator -** is a list of values. Example: -** -** WHERE x IN (1,2,3,4) -** -** Write the estimated row count into *pnRow and return SQLITE_OK. -** If unable to make an estimate, leave *pnRow unchanged and return -** non-zero. -** -** This routine can fail if it is unable to load a collating sequence -** required for string comparison, or if unable to allocate memory -** for a UTF conversion required for comparison. The error is stored -** in the pParse structure. -*/ -static int whereInScanEst( - Parse *pParse, /* Parsing & code generating context */ - Index *p, /* The index whose left-most column is pTerm */ - ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ - double *pnRow /* Write the revised row estimate here */ -){ - int rc = SQLITE_OK; /* Subfunction return code */ - double nEst; /* Number of rows for a single term */ - double nRowEst = (double)0; /* New estimate of the number of rows */ - int i; /* Loop counter */ - - assert( p->aSample!=0 ); - for(i=0; rc==SQLITE_OK && inExpr; i++){ - nEst = p->aiRowEst[0]; - rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst); - nRowEst += nEst; - } - if( rc==SQLITE_OK ){ - if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; - *pnRow = nRowEst; - WHERETRACE(("IN row estimate: est=%g\n", nRowEst)); - } - return rc; -} -#endif /* defined(SQLITE_ENABLE_STAT3) */ - -/* -** Check to see if column iCol of the table with cursor iTab will appear -** in sorted order according to the current query plan. -** -** Return values: -** -** 0 iCol is not ordered -** 1 iCol has only a single value -** 2 iCol is in ASC order -** 3 iCol is in DESC order -*/ -static int isOrderedColumn( - WhereBestIdx *p, - int iTab, - int iCol -){ - int i, j; - WhereLevel *pLevel = &p->aLevel[p->i-1]; - Index *pIdx; - u8 sortOrder; - for(i=p->i-1; i>=0; i--, pLevel--){ - if( pLevel->iTabCur!=iTab ) continue; - if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){ - return 1; - } - assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 ); - if( (pIdx = pLevel->plan.u.pIdx)!=0 ){ - if( iCol<0 ){ - sortOrder = 0; - testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); - }else{ - int n = pIdx->nColumn; - for(j=0; jaiColumn[j] ) break; - } - if( j>=n ) return 0; - sortOrder = pIdx->aSortOrder[j]; - testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); - } - }else{ - if( iCol!=(-1) ) return 0; - sortOrder = 0; - testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ); - } - if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){ - assert( sortOrder==0 || sortOrder==1 ); - testcase( sortOrder==1 ); - sortOrder = 1 - sortOrder; - } - return sortOrder+2; - } - return 0; -} - -/* -** This routine decides if pIdx can be used to satisfy the ORDER BY -** clause, either in whole or in part. The return value is the -** cumulative number of terms in the ORDER BY clause that are satisfied -** by the index pIdx and other indices in outer loops. -** -** The table being queried has a cursor number of "base". pIdx is the -** index that is postulated for use to access the table. -** -** The *pbRev value is set to 0 order 1 depending on whether or not -** pIdx should be run in the forward order or in reverse order. -*/ -static int isSortingIndex( - WhereBestIdx *p, /* Best index search context */ - Index *pIdx, /* The index we are testing */ - int base, /* Cursor number for the table to be sorted */ - int *pbRev, /* Set to 1 for reverse-order scan of pIdx */ - int *pbObUnique /* ORDER BY column values will different in every row */ -){ - int i; /* Number of pIdx terms used */ - int j; /* Number of ORDER BY terms satisfied */ - int sortOrder = 2; /* 0: forward. 1: backward. 2: unknown */ - int nTerm; /* Number of ORDER BY terms */ - struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */ - Table *pTab = pIdx->pTable; /* Table that owns index pIdx */ - ExprList *pOrderBy; /* The ORDER BY clause */ - Parse *pParse = p->pParse; /* Parser context */ - sqlite3 *db = pParse->db; /* Database connection */ - int nPriorSat; /* ORDER BY terms satisfied by outer loops */ - int seenRowid = 0; /* True if an ORDER BY rowid term is seen */ - int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */ - int outerObUnique; /* Outer loops generate different values in - ** every row for the ORDER BY columns */ - - if( p->i==0 ){ - nPriorSat = 0; - outerObUnique = 1; - }else{ - u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags; - nPriorSat = p->aLevel[p->i-1].plan.nOBSat; - if( (wsFlags & WHERE_ORDERED)==0 ){ - /* This loop cannot be ordered unless the next outer loop is - ** also ordered */ - return nPriorSat; - } - if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){ - /* Only look at the outer-most loop if the OrderByIdxJoin - ** optimization is disabled */ - return nPriorSat; - } - testcase( wsFlags & WHERE_OB_UNIQUE ); - testcase( wsFlags & WHERE_ALL_UNIQUE ); - outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0; - } - pOrderBy = p->pOrderBy; - assert( pOrderBy!=0 ); - if( pIdx->bUnordered ){ - /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot - ** be used for sorting */ - return nPriorSat; - } - nTerm = pOrderBy->nExpr; - uniqueNotNull = pIdx->onError!=OE_None; - assert( nTerm>0 ); - - /* Argument pIdx must either point to a 'real' named index structure, - ** or an index structure allocated on the stack by bestBtreeIndex() to - ** represent the rowid index that is part of every table. */ - assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) ); - - /* Match terms of the ORDER BY clause against columns of - ** the index. - ** - ** Note that indices have pIdx->nColumn regular columns plus - ** one additional column containing the rowid. The rowid column - ** of the index is also allowed to match against the ORDER BY - ** clause. - */ - j = nPriorSat; - for(i=0,pOBItem=&pOrderBy->a[j]; jnColumn; i++){ - Expr *pOBExpr; /* The expression of the ORDER BY pOBItem */ - CollSeq *pColl; /* The collating sequence of pOBExpr */ - int termSortOrder; /* Sort order for this term */ - int iColumn; /* The i-th column of the index. -1 for rowid */ - int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */ - int isEq; /* Subject to an == or IS NULL constraint */ - int isMatch; /* ORDER BY term matches the index term */ - const char *zColl; /* Name of collating sequence for i-th index term */ - WhereTerm *pConstraint; /* A constraint in the WHERE clause */ - - /* If the next term of the ORDER BY clause refers to anything other than - ** a column in the "base" table, then this index will not be of any - ** further use in handling the ORDER BY. */ - pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr); - if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ - break; - } - - /* Find column number and collating sequence for the next entry - ** in the index */ - if( pIdx->zName && inColumn ){ - iColumn = pIdx->aiColumn[i]; - if( iColumn==pIdx->pTable->iPKey ){ - iColumn = -1; - } - iSortOrder = pIdx->aSortOrder[i]; - zColl = pIdx->azColl[i]; - assert( zColl!=0 ); - }else{ - iColumn = -1; - iSortOrder = 0; - zColl = 0; - } - - /* Check to see if the column number and collating sequence of the - ** index match the column number and collating sequence of the ORDER BY - ** clause entry. Set isMatch to 1 if they both match. */ - if( pOBExpr->iColumn==iColumn ){ - if( zColl ){ - pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr); - if( !pColl ) pColl = db->pDfltColl; - isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; - }else{ - isMatch = 1; - } - }else{ - isMatch = 0; - } - - /* termSortOrder is 0 or 1 for whether or not the access loop should - ** run forward or backwards (respectively) in order to satisfy this - ** term of the ORDER BY clause. */ - assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 ); - assert( iSortOrder==0 || iSortOrder==1 ); - termSortOrder = iSortOrder ^ pOBItem->sortOrder; - - /* If X is the column in the index and ORDER BY clause, check to see - ** if there are any X= or X IS NULL constraints in the WHERE clause. */ - pConstraint = findTerm(p->pWC, base, iColumn, p->notReady, - WO_EQ|WO_ISNULL|WO_IN, pIdx); - if( pConstraint==0 ){ - isEq = 0; - }else if( (pConstraint->eOperator & WO_IN)!=0 ){ - isEq = 0; - }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){ - uniqueNotNull = 0; - isEq = 1; /* "X IS NULL" means X has only a single value */ - }else if( pConstraint->prereqRight==0 ){ - isEq = 1; /* Constraint "X=constant" means X has only a single value */ - }else{ - Expr *pRight = pConstraint->pExpr->pRight; - if( pRight->op==TK_COLUMN ){ - WHERETRACE((" .. isOrderedColumn(tab=%d,col=%d)", - pRight->iTable, pRight->iColumn)); - isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn); - WHERETRACE((" -> isEq=%d\n", isEq)); - - /* If the constraint is of the form X=Y where Y is an ordered value - ** in an outer loop, then make sure the sort order of Y matches the - ** sort order required for X. */ - if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){ - testcase( isEq==2 ); - testcase( isEq==3 ); - break; - } - }else{ - isEq = 0; /* "X=expr" places no ordering constraints on X */ - } - } - if( !isMatch ){ - if( isEq==0 ){ - break; - }else{ - continue; - } - }else if( isEq!=1 ){ - if( sortOrder==2 ){ - sortOrder = termSortOrder; - }else if( termSortOrder!=sortOrder ){ - break; - } - } - j++; - pOBItem++; - if( iColumn<0 ){ - seenRowid = 1; - break; - }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){ - testcase( isEq==0 ); - testcase( isEq==2 ); - testcase( isEq==3 ); - uniqueNotNull = 0; - } - } - if( seenRowid ){ - uniqueNotNull = 1; - }else if( uniqueNotNull==0 || inColumn ){ - uniqueNotNull = 0; - } - - /* If we have not found at least one ORDER BY term that matches the - ** index, then show no progress. */ - if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat; - - /* Either the outer queries must generate rows where there are no two - ** rows with the same values in all ORDER BY columns, or else this - ** loop must generate just a single row of output. Example: Suppose - ** the outer loops generate A=1 and A=1, and this loop generates B=3 - ** and B=4. Then without the following test, ORDER BY A,B would - ** generate the wrong order output: 1,3 1,4 1,3 1,4 - */ - if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat; - *pbObUnique = uniqueNotNull; - - /* Return the necessary scan order back to the caller */ - *pbRev = sortOrder & 1; - - /* If there was an "ORDER BY rowid" term that matched, or it is only - ** possible for a single row from this table to match, then skip over - ** any additional ORDER BY terms dealing with this table. - */ - if( uniqueNotNull ){ - /* Advance j over additional ORDER BY terms associated with base */ - WhereMaskSet *pMS = p->pWC->pMaskSet; - Bitmask m = ~getMask(pMS, base); - while( ja[j].pExpr)&m)==0 ){ - j++; - } - } - return j; -} - -/* -** Find the best query plan for accessing a particular table. Write the -** best query plan and its cost into the p->cost. -** -** The lowest cost plan wins. The cost is an estimate of the amount of -** CPU and disk I/O needed to process the requested result. -** Factors that influence cost include: -** -** * The estimated number of rows that will be retrieved. (The -** fewer the better.) -** -** * Whether or not sorting must occur. -** -** * Whether or not there must be separate lookups in the -** index and in the main table. -** -** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in -** the SQL statement, then this function only considers plans using the -** named index. If no such plan is found, then the returned cost is -** SQLITE_BIG_DBL. If a plan is found that uses the named index, -** then the cost is calculated in the usual way. -** -** If a NOT INDEXED clause was attached to the table -** in the SELECT statement, then no indexes are considered. However, the -** selected plan may still take advantage of the built-in rowid primary key -** index. -*/ -static void bestBtreeIndex(WhereBestIdx *p){ - Parse *pParse = p->pParse; /* The parsing context */ - WhereClause *pWC = p->pWC; /* The WHERE clause */ - struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ - int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ - Index *pProbe; /* An index we are evaluating */ - Index *pIdx; /* Copy of pProbe, or zero for IPK index */ - int eqTermMask; /* Current mask of valid equality operators */ - int idxEqTermMask; /* Index mask of valid equality operators */ - Index sPk; /* A fake index object for the primary key */ - tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ - int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ - int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ - int nPriorSat; /* ORDER BY terms satisfied by outer loops */ - int nOrderBy; /* Number of ORDER BY terms */ - char bSortInit; /* Initializer for bSort in inner loop */ - char bDistInit; /* Initializer for bDist in inner loop */ - - - /* Initialize the cost to a worst-case value */ - memset(&p->cost, 0, sizeof(p->cost)); - p->cost.rCost = SQLITE_BIG_DBL; - - /* If the pSrc table is the right table of a LEFT JOIN then we may not - ** use an index to satisfy IS NULL constraints on that table. This is - ** because columns might end up being NULL if the table does not match - - ** a circumstance which the index cannot help us discover. Ticket #2177. - */ - if( pSrc->jointype & JT_LEFT ){ - idxEqTermMask = WO_EQ|WO_IN; - }else{ - idxEqTermMask = WO_EQ|WO_IN|WO_ISNULL; - } - - if( pSrc->pIndex ){ - /* An INDEXED BY clause specifies a particular index to use */ - pIdx = pProbe = pSrc->pIndex; - wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE); - eqTermMask = idxEqTermMask; - }else{ - /* There is no INDEXED BY clause. Create a fake Index object in local - ** variable sPk to represent the rowid primary key index. Make this - ** fake index the first in a chain of Index objects with all of the real - ** indices to follow */ - Index *pFirst; /* First of real indices on the table */ - memset(&sPk, 0, sizeof(Index)); - sPk.nColumn = 1; - sPk.aiColumn = &aiColumnPk; - sPk.aiRowEst = aiRowEstPk; - sPk.onError = OE_Replace; - sPk.pTable = pSrc->pTab; - aiRowEstPk[0] = pSrc->pTab->nRowEst; - aiRowEstPk[1] = 1; - pFirst = pSrc->pTab->pIndex; - if( pSrc->notIndexed==0 ){ - /* The real indices of the table are only considered if the - ** NOT INDEXED qualifier is omitted from the FROM clause */ - sPk.pNext = pFirst; - } - pProbe = &sPk; - wsFlagMask = ~( - WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE - ); - eqTermMask = WO_EQ|WO_IN; - pIdx = 0; - } - - nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; - if( p->i ){ - nPriorSat = p->aLevel[p->i-1].plan.nOBSat; - bSortInit = nPriorSat0; - bDistInit = p->pDistinct!=0; - } - - /* Loop over all indices looking for the best one to use - */ - for(; pProbe; pIdx=pProbe=pProbe->pNext){ - const tRowcnt * const aiRowEst = pProbe->aiRowEst; - WhereCost pc; /* Cost of using pProbe */ - double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ - - /* The following variables are populated based on the properties of - ** index being evaluated. They are then used to determine the expected - ** cost and number of rows returned. - ** - ** pc.plan.nEq: - ** Number of equality terms that can be implemented using the index. - ** In other words, the number of initial fields in the index that - ** are used in == or IN or NOT NULL constraints of the WHERE clause. - ** - ** nInMul: - ** The "in-multiplier". This is an estimate of how many seek operations - ** SQLite must perform on the index in question. For example, if the - ** WHERE clause is: - ** - ** WHERE a IN (1, 2, 3) AND b IN (4, 5, 6) - ** - ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is - ** set to 9. Given the same schema and either of the following WHERE - ** clauses: - ** - ** WHERE a = 1 - ** WHERE a >= 2 - ** - ** nInMul is set to 1. - ** - ** If there exists a WHERE term of the form "x IN (SELECT ...)", then - ** the sub-select is assumed to return 25 rows for the purposes of - ** determining nInMul. - ** - ** bInEst: - ** Set to true if there was at least one "x IN (SELECT ...)" term used - ** in determining the value of nInMul. Note that the RHS of the - ** IN operator must be a SELECT, not a value list, for this variable - ** to be true. - ** - ** rangeDiv: - ** An estimate of a divisor by which to reduce the search space due - ** to inequality constraints. In the absence of sqlite_stat3 ANALYZE - ** data, a single inequality reduces the search space to 1/4rd its - ** original size (rangeDiv==4). Two inequalities reduce the search - ** space to 1/16th of its original size (rangeDiv==16). - ** - ** bSort: - ** Boolean. True if there is an ORDER BY clause that will require an - ** external sort (i.e. scanning the index being evaluated will not - ** correctly order records). - ** - ** bDist: - ** Boolean. True if there is a DISTINCT clause that will require an - ** external btree. - ** - ** bLookup: - ** Boolean. True if a table lookup is required for each index entry - ** visited. In other words, true if this is not a covering index. - ** This is always false for the rowid primary key index of a table. - ** For other indexes, it is true unless all the columns of the table - ** used by the SELECT statement are present in the index (such an - ** index is sometimes described as a covering index). - ** For example, given the index on (a, b), the second of the following - ** two queries requires table b-tree lookups in order to find the value - ** of column c, but the first does not because columns a and b are - ** both available in the index. - ** - ** SELECT a, b FROM tbl WHERE a = 1; - ** SELECT a, b, c FROM tbl WHERE a = 1; - */ - int bInEst = 0; /* True if "x IN (SELECT...)" seen */ - int nInMul = 1; /* Number of distinct equalities to lookup */ - double rangeDiv = (double)1; /* Estimated reduction in search space */ - int nBound = 0; /* Number of range constraints seen */ - char bSort = bSortInit; /* True if external sort required */ - char bDist = bDistInit; /* True if index cannot help with DISTINCT */ - char bLookup = 0; /* True if not a covering index */ - WhereTerm *pTerm; /* A single term of the WHERE clause */ -#ifdef SQLITE_ENABLE_STAT3 - WhereTerm *pFirstTerm = 0; /* First term matching the index */ -#endif - - WHERETRACE(( - " %s(%s):\n", - pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") - )); - memset(&pc, 0, sizeof(pc)); - pc.plan.nOBSat = nPriorSat; - - /* Determine the values of pc.plan.nEq and nInMul */ - for(pc.plan.nEq=0; pc.plan.nEqnColumn; pc.plan.nEq++){ - int j = pProbe->aiColumn[pc.plan.nEq]; - pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); - if( pTerm==0 ) break; - pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ); - testcase( pTerm->pWC!=pWC ); - if( pTerm->eOperator & WO_IN ){ - Expr *pExpr = pTerm->pExpr; - pc.plan.wsFlags |= WHERE_COLUMN_IN; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */ - nInMul *= 25; - bInEst = 1; - }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ - /* "x IN (value, value, ...)" */ - nInMul *= pExpr->x.pList->nExpr; - } - }else if( pTerm->eOperator & WO_ISNULL ){ - pc.plan.wsFlags |= WHERE_COLUMN_NULL; - } -#ifdef SQLITE_ENABLE_STAT3 - if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm; -#endif - pc.used |= pTerm->prereqRight; - } - - /* If the index being considered is UNIQUE, and there is an equality - ** constraint for all columns in the index, then this search will find - ** at most a single row. In this case set the WHERE_UNIQUE flag to - ** indicate this to the caller. - ** - ** Otherwise, if the search may find more than one row, test to see if - ** there is a range constraint on indexed column (pc.plan.nEq+1) that - ** can be optimized using the index. - */ - if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){ - testcase( pc.plan.wsFlags & WHERE_COLUMN_IN ); - testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL ); - if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){ - pc.plan.wsFlags |= WHERE_UNIQUE; - if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){ - pc.plan.wsFlags |= WHERE_ALL_UNIQUE; - } - } - }else if( pProbe->bUnordered==0 ){ - int j; - j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]); - if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){ - WhereTerm *pTop, *pBtm; - pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx); - pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx); - whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv); - if( pTop ){ - nBound = 1; - pc.plan.wsFlags |= WHERE_TOP_LIMIT; - pc.used |= pTop->prereqRight; - testcase( pTop->pWC!=pWC ); - } - if( pBtm ){ - nBound++; - pc.plan.wsFlags |= WHERE_BTM_LIMIT; - pc.used |= pBtm->prereqRight; - testcase( pBtm->pWC!=pWC ); - } - pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE); - } - } - - /* If there is an ORDER BY clause and the index being considered will - ** naturally scan rows in the required order, set the appropriate flags - ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but - ** the index will scan rows in a different order, set the bSort - ** variable. */ - if( bSort && (pSrc->jointype & JT_LEFT)==0 ){ - int bRev = 2; - int bObUnique = 0; - WHERETRACE((" --> before isSortIndex: nPriorSat=%d\n",nPriorSat)); - pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique); - WHERETRACE((" --> after isSortIndex: bRev=%d bObU=%d nOBSat=%d\n", - bRev, bObUnique, pc.plan.nOBSat)); - if( nPriorSatpDistinct, pc.plan.nEq) - && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0 - ){ - bDist = 0; - pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT; - } - - /* If currently calculating the cost of using an index (not the IPK - ** index), determine if all required column data may be obtained without - ** using the main table (i.e. if the index is a covering - ** index for this query). If it is, set the WHERE_IDX_ONLY flag in - ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true. */ - if( pIdx ){ - Bitmask m = pSrc->colUsed; - int j; - for(j=0; jnColumn; j++){ - int x = pIdx->aiColumn[j]; - if( xaiRowEst[0] ){ - pc.plan.nRow = aiRowEst[0]/2; - nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]); - } - -#ifdef SQLITE_ENABLE_STAT3 - /* If the constraint is of the form x=VALUE or x IN (E1,E2,...) - ** and we do not think that values of x are unique and if histogram - ** data is available for column x, then it might be possible - ** to get a better estimate on the number of rows based on - ** VALUE and how common that value is according to the histogram. - */ - if( pc.plan.nRow>(double)1 && pc.plan.nEq==1 - && pFirstTerm!=0 && aiRowEst[1]>1 ){ - assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 ); - if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){ - testcase( pFirstTerm->eOperator & WO_EQ ); - testcase( pFirstTerm->eOperator & WO_EQUIV ); - testcase( pFirstTerm->eOperator & WO_ISNULL ); - whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, - &pc.plan.nRow); - }else if( bInEst==0 ){ - assert( pFirstTerm->eOperator & WO_IN ); - whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, - &pc.plan.nRow); - } - } -#endif /* SQLITE_ENABLE_STAT3 */ - - /* Adjust the number of output rows and downward to reflect rows - ** that are excluded by range constraints. - */ - pc.plan.nRow = pc.plan.nRow/rangeDiv; - if( pc.plan.nRow<1 ) pc.plan.nRow = 1; - - /* Experiments run on real SQLite databases show that the time needed - ** to do a binary search to locate a row in a table or index is roughly - ** log10(N) times the time to move from one row to the next row within - ** a table or index. The actual times can vary, with the size of - ** records being an important factor. Both moves and searches are - ** slower with larger records, presumably because fewer records fit - ** on one page and hence more pages have to be fetched. - ** - ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do - ** not give us data on the relative sizes of table and index records. - ** So this computation assumes table records are about twice as big - ** as index records - */ - if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE)) - ==WHERE_IDX_ONLY - && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 - && sqlite3GlobalConfig.bUseCis - && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan) - ){ - /* This index is not useful for indexing, but it is a covering index. - ** A full-scan of the index might be a little faster than a full-scan - ** of the table, so give this case a cost slightly less than a table - ** scan. */ - pc.rCost = aiRowEst[0]*3 + pProbe->nColumn; - pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE; - }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ - /* The cost of a full table scan is a number of move operations equal - ** to the number of rows in the table. - ** - ** We add an additional 4x penalty to full table scans. This causes - ** the cost function to err on the side of choosing an index over - ** choosing a full scan. This 4x full-scan penalty is an arguable - ** decision and one which we expect to revisit in the future. But - ** it seems to be working well enough at the moment. - */ - pc.rCost = aiRowEst[0]*4; - pc.plan.wsFlags &= ~WHERE_IDX_ONLY; - if( pIdx ){ - pc.plan.wsFlags &= ~WHERE_ORDERED; - pc.plan.nOBSat = nPriorSat; - } - }else{ - log10N = estLog(aiRowEst[0]); - pc.rCost = pc.plan.nRow; - if( pIdx ){ - if( bLookup ){ - /* For an index lookup followed by a table lookup: - ** nInMul index searches to find the start of each index range - ** + nRow steps through the index - ** + nRow table searches to lookup the table entry using the rowid - */ - pc.rCost += (nInMul + pc.plan.nRow)*log10N; - }else{ - /* For a covering index: - ** nInMul index searches to find the initial entry - ** + nRow steps through the index - */ - pc.rCost += nInMul*log10N; - } - }else{ - /* For a rowid primary key lookup: - ** nInMult table searches to find the initial entry for each range - ** + nRow steps through the table - */ - pc.rCost += nInMul*log10N; - } - } - - /* Add in the estimated cost of sorting the result. Actual experimental - ** measurements of sorting performance in SQLite show that sorting time - ** adds C*N*log10(N) to the cost, where N is the number of rows to be - ** sorted and C is a factor between 1.95 and 4.3. We will split the - ** difference and select C of 3.0. - */ - if( bSort ){ - double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy); - m *= (double)(pc.plan.nOBSat ? 2 : 3); - pc.rCost += pc.plan.nRow*m; - } - if( bDist ){ - pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3; - } - - /**** Cost of using this index has now been computed ****/ - - /* If there are additional constraints on this table that cannot - ** be used with the current index, but which might lower the number - ** of output rows, adjust the nRow value accordingly. This only - ** matters if the current index is the least costly, so do not bother - ** with this step if we already know this index will not be chosen. - ** Also, never reduce the output row count below 2 using this step. - ** - ** It is critical that the notValid mask be used here instead of - ** the notReady mask. When computing an "optimal" index, the notReady - ** mask will only have one bit set - the bit for the current table. - ** The notValid mask, on the other hand, always has all bits set for - ** tables that are not in outer loops. If notReady is used here instead - ** of notValid, then a optimal index that depends on inner joins loops - ** might be selected even when there exists an optimal index that has - ** no such dependency. - */ - if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){ - int k; /* Loop counter */ - int nSkipEq = pc.plan.nEq; /* Number of == constraints to skip */ - int nSkipRange = nBound; /* Number of < constraints to skip */ - Bitmask thisTab; /* Bitmap for pSrc */ - - thisTab = getMask(pWC->pMaskSet, iCur); - for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){ - if( pTerm->wtFlags & TERM_VIRTUAL ) continue; - if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue; - if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){ - if( nSkipEq ){ - /* Ignore the first pc.plan.nEq equality matches since the index - ** has already accounted for these */ - nSkipEq--; - }else{ - /* Assume each additional equality match reduces the result - ** set size by a factor of 10 */ - pc.plan.nRow /= 10; - } - }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){ - if( nSkipRange ){ - /* Ignore the first nSkipRange range constraints since the index - ** has already accounted for these */ - nSkipRange--; - }else{ - /* Assume each additional range constraint reduces the result - ** set size by a factor of 3. Indexed range constraints reduce - ** the search space by a larger factor: 4. We make indexed range - ** more selective intentionally because of the subjective - ** observation that indexed range constraints really are more - ** selective in practice, on average. */ - pc.plan.nRow /= 3; - } - }else if( (pTerm->eOperator & WO_NOOP)==0 ){ - /* Any other expression lowers the output row count by half */ - pc.plan.nRow /= 2; - } - } - if( pc.plan.nRow<2 ) pc.plan.nRow = 2; - } - - - WHERETRACE(( - " nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n" - " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n" - " used=0x%llx nOBSat=%d\n", - pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags, - p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used, - pc.plan.nOBSat - )); - - /* If this index is the best we have seen so far, then record this - ** index and its cost in the p->cost structure. - */ - if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){ - p->cost = pc; - p->cost.plan.wsFlags &= wsFlagMask; - p->cost.plan.u.pIdx = pIdx; - } - - /* If there was an INDEXED BY clause, then only that one index is - ** considered. */ - if( pSrc->pIndex ) break; - - /* Reset masks for the next index in the loop */ - wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE); - eqTermMask = idxEqTermMask; - } - - /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag - ** is set, then reverse the order that the index will be scanned - ** in. This is used for application testing, to help find cases - ** where application behavior depends on the (undefined) order that - ** SQLite outputs rows in in the absence of an ORDER BY clause. */ - if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){ - p->cost.plan.wsFlags |= WHERE_REVERSE; - } - - assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 ); - assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 ); - assert( pSrc->pIndex==0 - || p->cost.plan.u.pIdx==0 - || p->cost.plan.u.pIdx==pSrc->pIndex - ); - - WHERETRACE((" best index is %s cost=%.1f\n", - p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk", - p->cost.rCost)); - - bestOrClauseIndex(p); - bestAutomaticIndex(p); - p->cost.plan.wsFlags |= eqTermMask; -} - -/* -** Find the query plan for accessing table pSrc->pTab. Write the -** best query plan and its cost into the WhereCost object supplied -** as the last parameter. This function may calculate the cost of -** both real and virtual table scans. -** -** This function does not take ORDER BY or DISTINCT into account. Nor -** does it remember the virtual table query plan. All it does is compute -** the cost while determining if an OR optimization is applicable. The -** details will be reconsidered later if the optimization is found to be -** applicable. -*/ -static void bestIndex(WhereBestIdx *p){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(p->pSrc->pTab) ){ - sqlite3_index_info *pIdxInfo = 0; - p->ppIdxInfo = &pIdxInfo; - bestVirtualIndex(p); - assert( pIdxInfo!=0 || p->pParse->db->mallocFailed ); - if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){ - sqlite3_free(pIdxInfo->idxStr); - } - sqlite3DbFree(p->pParse->db, pIdxInfo); - }else -#endif - { - bestBtreeIndex(p); - } -} - -/* -** Disable a term in the WHERE clause. Except, do not disable the term -** if it controls a LEFT OUTER JOIN and it did not originate in the ON -** or USING clause of that join. -** -** Consider the term t2.z='ok' in the following queries: -** -** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok' -** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok' -** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok' -** -** The t2.z='ok' is disabled in the in (2) because it originates -** in the ON clause. The term is disabled in (3) because it is not part -** of a LEFT OUTER JOIN. In (1), the term is not disabled. -** -** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are -** completely satisfied by indices. -** -** Disabling a term causes that term to not be tested in the inner loop -** of the join. Disabling is an optimization. When terms are satisfied -** by indices, we disable them to prevent redundant tests in the inner -** loop. We would get the correct results if nothing were ever disabled, -** but joins might run a little slower. The trick is to disable as much -** as we can without disabling too much. If we disabled in (1), we'd get -** the wrong answer. See ticket #813. -*/ -static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ - if( pTerm - && (pTerm->wtFlags & TERM_CODED)==0 - && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) - ){ - pTerm->wtFlags |= TERM_CODED; - if( pTerm->iParent>=0 ){ - WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent]; - if( (--pOther->nChild)==0 ){ - disableTerm(pLevel, pOther); - } - } - } -} - -/* -** Code an OP_Affinity opcode to apply the column affinity string zAff -** to the n registers starting at base. -** -** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the -** beginning and end of zAff are ignored. If all entries in zAff are -** SQLITE_AFF_NONE, then no code gets generated. -** -** This routine makes its own copy of zAff so that the caller is free -** to modify zAff after this routine returns. -*/ -static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){ - Vdbe *v = pParse->pVdbe; - if( zAff==0 ){ - assert( pParse->db->mallocFailed ); - return; - } - assert( v!=0 ); - - /* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning - ** and end of the affinity string. - */ - while( n>0 && zAff[0]==SQLITE_AFF_NONE ){ - n--; - base++; - zAff++; - } - while( n>1 && zAff[n-1]==SQLITE_AFF_NONE ){ - n--; - } - - /* Code the OP_Affinity opcode if there is anything left to do. */ - if( n>0 ){ - sqlite3VdbeAddOp2(v, OP_Affinity, base, n); - sqlite3VdbeChangeP4(v, -1, zAff, n); - sqlite3ExprCacheAffinityChange(pParse, base, n); - } -} - - -/* -** Generate code for a single equality term of the WHERE clause. An equality -** term can be either X=expr or X IN (...). pTerm is the term to be -** coded. -** -** The current value for the constraint is left in register iReg. -** -** For a constraint of the form X=expr, the expression is evaluated and its -** result is left on the stack. For constraints of the form X IN (...) -** this routine sets up a loop that will iterate over all values of X. -*/ -static int codeEqualityTerm( - Parse *pParse, /* The parsing context */ - WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ - WhereLevel *pLevel, /* The level of the FROM clause we are working on */ - int iEq, /* Index of the equality term within this level */ - int iTarget /* Attempt to leave results in this register */ -){ - Expr *pX = pTerm->pExpr; - Vdbe *v = pParse->pVdbe; - int iReg; /* Register holding results */ - - assert( iTarget>0 ); - if( pX->op==TK_EQ ){ - iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); - }else if( pX->op==TK_ISNULL ){ - iReg = iTarget; - sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); -#ifndef SQLITE_OMIT_SUBQUERY - }else{ - int eType; - int iTab; - struct InLoop *pIn; - u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0; - - if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 - && pLevel->plan.u.pIdx->aSortOrder[iEq] - ){ - testcase( iEq==0 ); - testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 ); - testcase( iEq>0 && iEq+1plan.u.pIdx->nColumn ); - testcase( bRev ); - bRev = !bRev; - } - assert( pX->op==TK_IN ); - iReg = iTarget; - eType = sqlite3FindInIndex(pParse, pX, 0); - if( eType==IN_INDEX_INDEX_DESC ){ - testcase( bRev ); - bRev = !bRev; - } - iTab = pX->iTable; - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); - assert( pLevel->plan.wsFlags & WHERE_IN_ABLE ); - if( pLevel->u.in.nIn==0 ){ - pLevel->addrNxt = sqlite3VdbeMakeLabel(v); - } - pLevel->u.in.nIn++; - pLevel->u.in.aInLoop = - sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, - sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); - pIn = pLevel->u.in.aInLoop; - if( pIn ){ - pIn += pLevel->u.in.nIn - 1; - pIn->iCur = iTab; - if( eType==IN_INDEX_ROWID ){ - pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg); - }else{ - pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); - } - pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next; - sqlite3VdbeAddOp1(v, OP_IsNull, iReg); - }else{ - pLevel->u.in.nIn = 0; - } -#endif - } - disableTerm(pLevel, pTerm); - return iReg; -} - -/* -** Generate code that will evaluate all == and IN constraints for an -** index. -** -** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c). -** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10 -** The index has as many as three equality constraints, but in this -** example, the third "c" value is an inequality. So only two -** constraints are coded. This routine will generate code to evaluate -** a==5 and b IN (1,2,3). The current values for a and b will be stored -** in consecutive registers and the index of the first register is returned. -** -** In the example above nEq==2. But this subroutine works for any value -** of nEq including 0. If nEq==0, this routine is nearly a no-op. -** The only thing it does is allocate the pLevel->iMem memory cell and -** compute the affinity string. -** -** This routine always allocates at least one memory cell and returns -** the index of that memory cell. The code that -** calls this routine will use that memory cell to store the termination -** key value of the loop. If one or more IN operators appear, then -** this routine allocates an additional nEq memory cells for internal -** use. -** -** Before returning, *pzAff is set to point to a buffer containing a -** copy of the column affinity string of the index allocated using -** sqlite3DbMalloc(). Except, entries in the copy of the string associated -** with equality constraints that use NONE affinity are set to -** SQLITE_AFF_NONE. This is to deal with SQL such as the following: -** -** CREATE TABLE t1(a TEXT PRIMARY KEY, b); -** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b; -** -** In the example above, the index on t1(a) has TEXT affinity. But since -** the right hand side of the equality constraint (t2.b) has NONE affinity, -** no conversion should be attempted before using a t2.b value as part of -** a key to search the index. Hence the first byte in the returned affinity -** string in this example would be set to SQLITE_AFF_NONE. -*/ -static int codeAllEqualityTerms( - Parse *pParse, /* Parsing context */ - WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ - WhereClause *pWC, /* The WHERE clause */ - Bitmask notReady, /* Which parts of FROM have not yet been coded */ - int nExtraReg, /* Number of extra registers to allocate */ - char **pzAff /* OUT: Set to point to affinity string */ -){ - int nEq = pLevel->plan.nEq; /* The number of == or IN constraints to code */ - Vdbe *v = pParse->pVdbe; /* The vm under construction */ - Index *pIdx; /* The index being used for this loop */ - int iCur = pLevel->iTabCur; /* The cursor of the table */ - WhereTerm *pTerm; /* A single constraint term */ - int j; /* Loop counter */ - int regBase; /* Base register */ - int nReg; /* Number of registers to allocate */ - char *zAff; /* Affinity string to return */ - - /* This module is only called on query plans that use an index. */ - assert( pLevel->plan.wsFlags & WHERE_INDEXED ); - pIdx = pLevel->plan.u.pIdx; - - /* Figure out how many memory cells we will need then allocate them. - */ - regBase = pParse->nMem + 1; - nReg = pLevel->plan.nEq + nExtraReg; - pParse->nMem += nReg; - - zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx)); - if( !zAff ){ - pParse->db->mallocFailed = 1; - } - - /* Evaluate the equality constraints - */ - assert( pIdx->nColumn>=nEq ); - for(j=0; jaiColumn[j]; - pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx); - if( pTerm==0 ) break; - /* The following true for indices with redundant columns. - ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ - testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); - testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j); - if( r1!=regBase+j ){ - if( nReg==1 ){ - sqlite3ReleaseTempReg(pParse, regBase); - regBase = r1; - }else{ - sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); - } - } - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_IN ); - if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ - Expr *pRight = pTerm->pExpr->pRight; - sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk); - if( zAff ){ - if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){ - zAff[j] = SQLITE_AFF_NONE; - } - if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){ - zAff[j] = SQLITE_AFF_NONE; - } - } - } - } - *pzAff = zAff; - return regBase; -} - -#ifndef SQLITE_OMIT_EXPLAIN -/* -** This routine is a helper for explainIndexRange() below -** -** pStr holds the text of an expression that we are building up one term -** at a time. This routine adds a new term to the end of the expression. -** Terms are separated by AND so add the "AND" text for second and subsequent -** terms only. -*/ -static void explainAppendTerm( - StrAccum *pStr, /* The text expression being built */ - int iTerm, /* Index of this term. First is zero */ - const char *zColumn, /* Name of the column */ - const char *zOp /* Name of the operator */ -){ - if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5); - sqlite3StrAccumAppend(pStr, zColumn, -1); - sqlite3StrAccumAppend(pStr, zOp, 1); - sqlite3StrAccumAppend(pStr, "?", 1); -} - -/* -** Argument pLevel describes a strategy for scanning table pTab. This -** function returns a pointer to a string buffer containing a description -** of the subset of table rows scanned by the strategy in the form of an -** SQL expression. Or, if all rows are scanned, NULL is returned. -** -** For example, if the query: -** -** SELECT * FROM t1 WHERE a=1 AND b>2; -** -** is run and there is an index on (a, b), then this function returns a -** string similar to: -** -** "a=? AND b>?" -** -** The returned pointer points to memory obtained from sqlite3DbMalloc(). -** It is the responsibility of the caller to free the buffer when it is -** no longer required. -*/ -static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){ - WherePlan *pPlan = &pLevel->plan; - Index *pIndex = pPlan->u.pIdx; - int nEq = pPlan->nEq; - int i, j; - Column *aCol = pTab->aCol; - int *aiColumn = pIndex->aiColumn; - StrAccum txt; - - if( nEq==0 && (pPlan->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){ - return 0; - } - sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH); - txt.db = db; - sqlite3StrAccumAppend(&txt, " (", 2); - for(i=0; i"); - } - if( pPlan->wsFlags&WHERE_TOP_LIMIT ){ - char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName; - explainAppendTerm(&txt, i, z, "<"); - } - sqlite3StrAccumAppend(&txt, ")", 1); - return sqlite3StrAccumFinish(&txt); -} - -/* -** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN -** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single -** record is added to the output to describe the table scan strategy in -** pLevel. -*/ -static void explainOneScan( - Parse *pParse, /* Parse context */ - SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ - int iLevel, /* Value for "level" column of output */ - int iFrom, /* Value for "from" column of output */ - u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ -){ - if( pParse->explain==2 ){ - u32 flags = pLevel->plan.wsFlags; - struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; - Vdbe *v = pParse->pVdbe; /* VM being constructed */ - sqlite3 *db = pParse->db; /* Database handle */ - char *zMsg; /* Text to add to EQP output */ - sqlite3_int64 nRow; /* Expected number of rows visited by scan */ - int iId = pParse->iSelectId; /* Select id (left-most output column) */ - int isSearch; /* True for a SEARCH. False for SCAN. */ - - if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return; - - isSearch = (pLevel->plan.nEq>0) - || (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 - || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); - - zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN"); - if( pItem->pSelect ){ - zMsg = sqlite3MAppendf(db, zMsg, "%s SUBQUERY %d", zMsg,pItem->iSelectId); - }else{ - zMsg = sqlite3MAppendf(db, zMsg, "%s TABLE %s", zMsg, pItem->zName); - } - - if( pItem->zAlias ){ - zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); - } - if( (flags & WHERE_INDEXED)!=0 ){ - char *zWhere = explainIndexRange(db, pLevel, pItem->pTab); - zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg, - ((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""), - ((flags & WHERE_IDX_ONLY)?"COVERING ":""), - ((flags & WHERE_TEMP_INDEX)?"":" "), - ((flags & WHERE_TEMP_INDEX)?"": pLevel->plan.u.pIdx->zName), - zWhere - ); - sqlite3DbFree(db, zWhere); - }else if( flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){ - zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg); - - if( flags&WHERE_ROWID_EQ ){ - zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg); - }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ - zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid?)", zMsg); - }else if( flags&WHERE_TOP_LIMIT ){ - zMsg = sqlite3MAppendf(db, zMsg, "%s (rowidplan.u.pVtabIdx; - zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg, - pVtabIdx->idxNum, pVtabIdx->idxStr); - } -#endif - if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){ - testcase( wctrlFlags & WHERE_ORDERBY_MIN ); - nRow = 1; - }else{ - nRow = (sqlite3_int64)pLevel->plan.nRow; - } - zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow); - sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC); - } -} -#else -# define explainOneScan(u,v,w,x,y,z) -#endif /* SQLITE_OMIT_EXPLAIN */ - - -/* -** Generate code for the start of the iLevel-th loop in the WHERE clause -** implementation described by pWInfo. -*/ -static Bitmask codeOneLoopStart( - WhereInfo *pWInfo, /* Complete information about the WHERE clause */ - int iLevel, /* Which level of pWInfo->a[] should be coded */ - u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ - Bitmask notReady /* Which tables are currently available */ -){ - int j, k; /* Loop counters */ - int iCur; /* The VDBE cursor for the table */ - int addrNxt; /* Where to jump to continue with the next IN case */ - int omitTable; /* True if we use the index only */ - int bRev; /* True if we need to scan in reverse order */ - WhereLevel *pLevel; /* The where level to be coded */ - WhereClause *pWC; /* Decomposition of the entire WHERE clause */ - WhereTerm *pTerm; /* A WHERE clause term */ - Parse *pParse; /* Parsing context */ - Vdbe *v; /* The prepared stmt under constructions */ - struct SrcList_item *pTabItem; /* FROM clause term being coded */ - int addrBrk; /* Jump here to break out of the loop */ - int addrCont; /* Jump here to continue with next cycle */ - int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ - int iReleaseReg = 0; /* Temp register to free before returning */ - Bitmask newNotReady; /* Return value */ - - pParse = pWInfo->pParse; - v = pParse->pVdbe; - pWC = pWInfo->pWC; - pLevel = &pWInfo->a[iLevel]; - pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; - iCur = pTabItem->iCursor; - bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0; - omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0 - && (wctrlFlags & WHERE_FORCE_TABLE)==0; - VdbeNoopComment((v, "Begin Join Loop %d", iLevel)); - - /* Create labels for the "break" and "continue" instructions - ** for the current loop. Jump to addrBrk to break out of a loop. - ** Jump to cont to go immediately to the next iteration of the - ** loop. - ** - ** When there is an IN operator, we also have a "addrNxt" label that - ** means to continue with the next IN value combination. When - ** there are no IN operators in the constraints, the "addrNxt" label - ** is the same as "addrBrk". - */ - addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v); - addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v); - - /* If this is the right table of a LEFT OUTER JOIN, allocate and - ** initialize a memory cell that records if this table matches any - ** row of the left table of the join. - */ - if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ - pLevel->iLeftJoin = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); - VdbeComment((v, "init LEFT JOIN no-match flag")); - } - - /* Special case of a FROM clause subquery implemented as a co-routine */ - if( pTabItem->viaCoroutine ){ - int regYield = pTabItem->regReturn; - sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield); - pLevel->p2 = sqlite3VdbeAddOp1(v, OP_Yield, regYield); - VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName)); - sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk); - pLevel->op = OP_Goto; - }else - -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ - /* Case 0: The table is a virtual-table. Use the VFilter and VNext - ** to access the data. - */ - int iReg; /* P3 Value for OP_VFilter */ - int addrNotFound; - sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; - int nConstraint = pVtabIdx->nConstraint; - struct sqlite3_index_constraint_usage *aUsage = - pVtabIdx->aConstraintUsage; - const struct sqlite3_index_constraint *aConstraint = - pVtabIdx->aConstraint; - - sqlite3ExprCachePush(pParse); - iReg = sqlite3GetTempRange(pParse, nConstraint+2); - addrNotFound = pLevel->addrBrk; - for(j=1; j<=nConstraint; j++){ - for(k=0; ka[aConstraint[k].iTermOffset]; - if( pTerm->eOperator & WO_IN ){ - codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget); - addrNotFound = pLevel->addrNxt; - }else{ - sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); - } - break; - } - } - if( k==nConstraint ) break; - } - sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); - sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); - sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr, - pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); - pVtabIdx->needToFreeIdxStr = 0; - for(j=0; ja[iTerm]); - } - } - pLevel->op = OP_VNext; - pLevel->p1 = iCur; - pLevel->p2 = sqlite3VdbeCurrentAddr(v); - sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); - sqlite3ExprCachePop(pParse, 1); - }else -#endif /* SQLITE_OMIT_VIRTUALTABLE */ - - if( pLevel->plan.wsFlags & WHERE_ROWID_EQ ){ - /* Case 1: We can directly reference a single row using an - ** equality comparison against the ROWID field. Or - ** we reference multiple rows using a "rowid IN (...)" - ** construct. - */ - iReleaseReg = sqlite3GetTempReg(pParse); - pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0); - assert( pTerm!=0 ); - assert( pTerm->pExpr!=0 ); - assert( omitTable==0 ); - testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg); - addrNxt = pLevel->addrNxt; - sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); - sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); - sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); - VdbeComment((v, "pk")); - pLevel->op = OP_Noop; - }else if( pLevel->plan.wsFlags & WHERE_ROWID_RANGE ){ - /* Case 2: We have an inequality comparison against the ROWID field. - */ - int testOp = OP_Noop; - int start; - int memEndValue = 0; - WhereTerm *pStart, *pEnd; - - assert( omitTable==0 ); - pStart = findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0); - pEnd = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0); - if( bRev ){ - pTerm = pStart; - pStart = pEnd; - pEnd = pTerm; - } - if( pStart ){ - Expr *pX; /* The expression that defines the start bound */ - int r1, rTemp; /* Registers for holding the start boundary */ - - /* The following constant maps TK_xx codes into corresponding - ** seek opcodes. It depends on a particular ordering of TK_xx - */ - const u8 aMoveOp[] = { - /* TK_GT */ OP_SeekGt, - /* TK_LE */ OP_SeekLe, - /* TK_LT */ OP_SeekLt, - /* TK_GE */ OP_SeekGe - }; - assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ - assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ - assert( TK_GE==TK_GT+3 ); /* ... is correcct. */ - - testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - pX = pStart->pExpr; - assert( pX!=0 ); - assert( pStart->leftCursor==iCur ); - r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); - sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); - VdbeComment((v, "pk")); - sqlite3ExprCacheAffinityChange(pParse, r1, 1); - sqlite3ReleaseTempReg(pParse, rTemp); - disableTerm(pLevel, pStart); - }else{ - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); - } - if( pEnd ){ - Expr *pX; - pX = pEnd->pExpr; - assert( pX!=0 ); - assert( pEnd->leftCursor==iCur ); - testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - memEndValue = ++pParse->nMem; - sqlite3ExprCode(pParse, pX->pRight, memEndValue); - if( pX->op==TK_LT || pX->op==TK_GT ){ - testOp = bRev ? OP_Le : OP_Ge; - }else{ - testOp = bRev ? OP_Lt : OP_Gt; - } - disableTerm(pLevel, pEnd); - } - start = sqlite3VdbeCurrentAddr(v); - pLevel->op = bRev ? OP_Prev : OP_Next; - pLevel->p1 = iCur; - pLevel->p2 = start; - if( pStart==0 && pEnd==0 ){ - pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; - }else{ - assert( pLevel->p5==0 ); - } - if( testOp!=OP_Noop ){ - iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); - sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); - sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); - sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); - } - }else if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){ - /* Case 3: A scan using an index. - ** - ** The WHERE clause may contain zero or more equality - ** terms ("==" or "IN" operators) that refer to the N - ** left-most columns of the index. It may also contain - ** inequality constraints (>, <, >= or <=) on the indexed - ** column that immediately follows the N equalities. Only - ** the right-most column can be an inequality - the rest must - ** use the "==" and "IN" operators. For example, if the - ** index is on (x,y,z), then the following clauses are all - ** optimized: - ** - ** x=5 - ** x=5 AND y=10 - ** x=5 AND y<10 - ** x=5 AND y>5 AND y<10 - ** x=5 AND y=5 AND z<=10 - ** - ** The z<10 term of the following cannot be used, only - ** the x=5 term: - ** - ** x=5 AND z<10 - ** - ** N may be zero if there are inequality constraints. - ** If there are no inequality constraints, then N is at - ** least one. - ** - ** This case is also used when there are no WHERE clause - ** constraints but an index is selected anyway, in order - ** to force the output order to conform to an ORDER BY. - */ - static const u8 aStartOp[] = { - 0, - 0, - OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ - OP_Last, /* 3: (!start_constraints && startEq && bRev) */ - OP_SeekGt, /* 4: (start_constraints && !startEq && !bRev) */ - OP_SeekLt, /* 5: (start_constraints && !startEq && bRev) */ - OP_SeekGe, /* 6: (start_constraints && startEq && !bRev) */ - OP_SeekLe /* 7: (start_constraints && startEq && bRev) */ - }; - static const u8 aEndOp[] = { - OP_Noop, /* 0: (!end_constraints) */ - OP_IdxGE, /* 1: (end_constraints && !bRev) */ - OP_IdxLT /* 2: (end_constraints && bRev) */ - }; - int nEq = pLevel->plan.nEq; /* Number of == or IN terms */ - int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ - int regBase; /* Base register holding constraint values */ - int r1; /* Temp register */ - WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ - WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ - int startEq; /* True if range start uses ==, >= or <= */ - int endEq; /* True if range end uses ==, >= or <= */ - int start_constraints; /* Start of range is constrained */ - int nConstraint; /* Number of constraint terms */ - Index *pIdx; /* The index we will be using */ - int iIdxCur; /* The VDBE cursor for the index */ - int nExtraReg = 0; /* Number of extra registers needed */ - int op; /* Instruction opcode */ - char *zStartAff; /* Affinity for start of range constraint */ - char *zEndAff; /* Affinity for end of range constraint */ - - pIdx = pLevel->plan.u.pIdx; - iIdxCur = pLevel->iIdxCur; - k = (nEq==pIdx->nColumn ? -1 : pIdx->aiColumn[nEq]); - - /* If this loop satisfies a sort order (pOrderBy) request that - ** was passed to this function to implement a "SELECT min(x) ..." - ** query, then the caller will only allow the loop to run for - ** a single iteration. This means that the first row returned - ** should not have a NULL value stored in 'x'. If column 'x' is - ** the first one after the nEq equality constraints in the index, - ** this requires some special handling. - */ - if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0 - && (pLevel->plan.wsFlags&WHERE_ORDERED) - && (pIdx->nColumn>nEq) - ){ - /* assert( pOrderBy->nExpr==1 ); */ - /* assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); */ - isMinQuery = 1; - nExtraReg = 1; - } - - /* Find any inequality constraint terms for the start and end - ** of the range. - */ - if( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ){ - pRangeEnd = findTerm(pWC, iCur, k, notReady, (WO_LT|WO_LE), pIdx); - nExtraReg = 1; - } - if( pLevel->plan.wsFlags & WHERE_BTM_LIMIT ){ - pRangeStart = findTerm(pWC, iCur, k, notReady, (WO_GT|WO_GE), pIdx); - nExtraReg = 1; - } - - /* Generate code to evaluate all constraint terms using == or IN - ** and store the values of those terms in an array of registers - ** starting at regBase. - */ - regBase = codeAllEqualityTerms( - pParse, pLevel, pWC, notReady, nExtraReg, &zStartAff - ); - zEndAff = sqlite3DbStrDup(pParse->db, zStartAff); - addrNxt = pLevel->addrNxt; - - /* If we are doing a reverse order scan on an ascending index, or - ** a forward order scan on a descending index, interchange the - ** start and end terms (pRangeStart and pRangeEnd). - */ - if( (nEqnColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) - || (bRev && pIdx->nColumn==nEq) - ){ - SWAP(WhereTerm *, pRangeEnd, pRangeStart); - } - - testcase( pRangeStart && pRangeStart->eOperator & WO_LE ); - testcase( pRangeStart && pRangeStart->eOperator & WO_GE ); - testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE ); - testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE ); - startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE); - endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE); - start_constraints = pRangeStart || nEq>0; - - /* Seek the index cursor to the start of the range. */ - nConstraint = nEq; - if( pRangeStart ){ - Expr *pRight = pRangeStart->pExpr->pRight; - sqlite3ExprCode(pParse, pRight, regBase+nEq); - if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){ - sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); - } - if( zStartAff ){ - if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){ - /* Since the comparison is to be performed with no conversions - ** applied to the operands, set the affinity to apply to pRight to - ** SQLITE_AFF_NONE. */ - zStartAff[nEq] = SQLITE_AFF_NONE; - } - if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){ - zStartAff[nEq] = SQLITE_AFF_NONE; - } - } - nConstraint++; - testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - }else if( isMinQuery ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - nConstraint++; - startEq = 0; - start_constraints = 1; - } - codeApplyAffinity(pParse, regBase, nConstraint, zStartAff); - op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; - assert( op!=0 ); - testcase( op==OP_Rewind ); - testcase( op==OP_Last ); - testcase( op==OP_SeekGt ); - testcase( op==OP_SeekGe ); - testcase( op==OP_SeekLe ); - testcase( op==OP_SeekLt ); - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - - /* Load the value for the inequality constraint at the end of the - ** range (if any). - */ - nConstraint = nEq; - if( pRangeEnd ){ - Expr *pRight = pRangeEnd->pExpr->pRight; - sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); - sqlite3ExprCode(pParse, pRight, regBase+nEq); - if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){ - sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); - } - if( zEndAff ){ - if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){ - /* Since the comparison is to be performed with no conversions - ** applied to the operands, set the affinity to apply to pRight to - ** SQLITE_AFF_NONE. */ - zEndAff[nEq] = SQLITE_AFF_NONE; - } - if( sqlite3ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){ - zEndAff[nEq] = SQLITE_AFF_NONE; - } - } - codeApplyAffinity(pParse, regBase, nEq+1, zEndAff); - nConstraint++; - testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ - } - sqlite3DbFree(pParse->db, zStartAff); - sqlite3DbFree(pParse->db, zEndAff); - - /* Top of the loop body */ - pLevel->p2 = sqlite3VdbeCurrentAddr(v); - - /* Check if the index cursor is past the end of the range. */ - op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)]; - testcase( op==OP_Noop ); - testcase( op==OP_IdxGE ); - testcase( op==OP_IdxLT ); - if( op!=OP_Noop ){ - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); - sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0); - } - - /* If there are inequality constraints, check that the value - ** of the table column that the inequality contrains is not NULL. - ** If it is, jump to the next iteration of the loop. - */ - r1 = sqlite3GetTempReg(pParse); - testcase( pLevel->plan.wsFlags & WHERE_BTM_LIMIT ); - testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ); - if( (pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){ - sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1); - sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont); - } - sqlite3ReleaseTempReg(pParse, r1); - - /* Seek the table cursor, if required */ - disableTerm(pLevel, pRangeStart); - disableTerm(pLevel, pRangeEnd); - if( !omitTable ){ - iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); - sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); - sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */ - } - - /* Record the instruction used to terminate the loop. Disable - ** WHERE clause terms made redundant by the index range scan. - */ - if( pLevel->plan.wsFlags & WHERE_UNIQUE ){ - pLevel->op = OP_Noop; - }else if( bRev ){ - pLevel->op = OP_Prev; - }else{ - pLevel->op = OP_Next; - } - pLevel->p1 = iIdxCur; - if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){ - pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; - }else{ - assert( pLevel->p5==0 ); - } - }else - -#ifndef SQLITE_OMIT_OR_OPTIMIZATION - if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){ - /* Case 4: Two or more separately indexed terms connected by OR - ** - ** Example: - ** - ** CREATE TABLE t1(a,b,c,d); - ** CREATE INDEX i1 ON t1(a); - ** CREATE INDEX i2 ON t1(b); - ** CREATE INDEX i3 ON t1(c); - ** - ** SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13) - ** - ** In the example, there are three indexed terms connected by OR. - ** The top of the loop looks like this: - ** - ** Null 1 # Zero the rowset in reg 1 - ** - ** Then, for each indexed term, the following. The arguments to - ** RowSetTest are such that the rowid of the current row is inserted - ** into the RowSet. If it is already present, control skips the - ** Gosub opcode and jumps straight to the code generated by WhereEnd(). - ** - ** sqlite3WhereBegin() - ** RowSetTest # Insert rowid into rowset - ** Gosub 2 A - ** sqlite3WhereEnd() - ** - ** Following the above, code to terminate the loop. Label A, the target - ** of the Gosub above, jumps to the instruction right after the Goto. - ** - ** Null 1 # Zero the rowset in reg 1 - ** Goto B # The loop is finished. - ** - ** A: # Return data, whatever. - ** - ** Return 2 # Jump back to the Gosub - ** - ** B: - ** - */ - WhereClause *pOrWc; /* The OR-clause broken out into subterms */ - SrcList *pOrTab; /* Shortened table list or OR-clause generation */ - Index *pCov = 0; /* Potential covering index (or NULL) */ - int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */ - - int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */ - int regRowset = 0; /* Register for RowSet object */ - int regRowid = 0; /* Register holding rowid */ - int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */ - int iRetInit; /* Address of regReturn init */ - int untestedTerms = 0; /* Some terms not completely tested */ - int ii; /* Loop counter */ - Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ - - pTerm = pLevel->plan.u.pTerm; - assert( pTerm!=0 ); - assert( pTerm->eOperator & WO_OR ); - assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); - pOrWc = &pTerm->u.pOrInfo->wc; - pLevel->op = OP_Return; - pLevel->p1 = regReturn; - - /* Set up a new SrcList in pOrTab containing the table being scanned - ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. - ** This becomes the SrcList in the recursive call to sqlite3WhereBegin(). - */ - if( pWInfo->nLevel>1 ){ - int nNotReady; /* The number of notReady tables */ - struct SrcList_item *origSrc; /* Original list of tables */ - nNotReady = pWInfo->nLevel - iLevel - 1; - pOrTab = sqlite3StackAllocRaw(pParse->db, - sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0])); - if( pOrTab==0 ) return notReady; - pOrTab->nAlloc = (i16)(nNotReady + 1); - pOrTab->nSrc = pOrTab->nAlloc; - memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem)); - origSrc = pWInfo->pTabList->a; - for(k=1; k<=nNotReady; k++){ - memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k])); - } - }else{ - pOrTab = pWInfo->pTabList; - } - - /* Initialize the rowset register to contain NULL. An SQL NULL is - ** equivalent to an empty rowset. - ** - ** Also initialize regReturn to contain the address of the instruction - ** immediately following the OP_Return at the bottom of the loop. This - ** is required in a few obscure LEFT JOIN cases where control jumps - ** over the top of the loop into the body of it. In this case the - ** correct response for the end-of-loop code (the OP_Return) is to - ** fall through to the next instruction, just as an OP_Next does if - ** called on an uninitialized cursor. - */ - if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ - regRowset = ++pParse->nMem; - regRowid = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); - } - iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); - - /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y - ** Then for every term xN, evaluate as the subexpression: xN AND z - ** That way, terms in y that are factored into the disjunction will - ** be picked up by the recursive calls to sqlite3WhereBegin() below. - ** - ** Actually, each subexpression is converted to "xN AND w" where w is - ** the "interesting" terms of z - terms that did not originate in the - ** ON or USING clause of a LEFT JOIN, and terms that are usable as - ** indices. - ** - ** This optimization also only applies if the (x1 OR x2 OR ...) term - ** is not contained in the ON clause of a LEFT JOIN. - ** See ticket http://www.sqlite.org/src/info/f2369304e4 - */ - if( pWC->nTerm>1 ){ - int iTerm; - for(iTerm=0; iTermnTerm; iTerm++){ - Expr *pExpr = pWC->a[iTerm].pExpr; - if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; - if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue; - if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; - pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); - pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr); - } - if( pAndExpr ){ - pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); - } - } - - for(ii=0; iinTerm; ii++){ - WhereTerm *pOrTerm = &pOrWc->a[ii]; - if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ - WhereInfo *pSubWInfo; /* Info for single OR-term scan */ - Expr *pOrExpr = pOrTerm->pExpr; - if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ - pAndExpr->pLeft = pOrExpr; - pOrExpr = pAndExpr; - } - /* Loop through table entries that match term pOrTerm. */ - pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, - WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY | - WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur); - assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed ); - if( pSubWInfo ){ - WhereLevel *pLvl; - explainOneScan( - pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 - ); - if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ - int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); - int r; - r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, - regRowid, 0); - sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, - sqlite3VdbeCurrentAddr(v)+2, r, iSet); - } - sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); - - /* The pSubWInfo->untestedTerms flag means that this OR term - ** contained one or more AND term from a notReady table. The - ** terms from the notReady table could not be tested and will - ** need to be tested later. - */ - if( pSubWInfo->untestedTerms ) untestedTerms = 1; - - /* If all of the OR-connected terms are optimized using the same - ** index, and the index is opened using the same cursor number - ** by each call to sqlite3WhereBegin() made by this loop, it may - ** be possible to use that index as a covering index. - ** - ** If the call to sqlite3WhereBegin() above resulted in a scan that - ** uses an index, and this is either the first OR-connected term - ** processed or the index is the same as that used by all previous - ** terms, set pCov to the candidate covering index. Otherwise, set - ** pCov to NULL to indicate that no candidate covering index will - ** be available. - */ - pLvl = &pSubWInfo->a[0]; - if( (pLvl->plan.wsFlags & WHERE_INDEXED)!=0 - && (pLvl->plan.wsFlags & WHERE_TEMP_INDEX)==0 - && (ii==0 || pLvl->plan.u.pIdx==pCov) - ){ - assert( pLvl->iIdxCur==iCovCur ); - pCov = pLvl->plan.u.pIdx; - }else{ - pCov = 0; - } - - /* Finish the loop through table entries that match term pOrTerm. */ - sqlite3WhereEnd(pSubWInfo); - } - } - } - pLevel->u.pCovidx = pCov; - if( pCov ) pLevel->iIdxCur = iCovCur; - if( pAndExpr ){ - pAndExpr->pLeft = 0; - sqlite3ExprDelete(pParse->db, pAndExpr); - } - sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); - sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); - sqlite3VdbeResolveLabel(v, iLoopBody); - - if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab); - if( !untestedTerms ) disableTerm(pLevel, pTerm); - }else -#endif /* SQLITE_OMIT_OR_OPTIMIZATION */ - - { - /* Case 5: There is no usable index. We must do a complete - ** scan of the entire table. - */ - static const u8 aStep[] = { OP_Next, OP_Prev }; - static const u8 aStart[] = { OP_Rewind, OP_Last }; - assert( bRev==0 || bRev==1 ); - assert( omitTable==0 ); - pLevel->op = aStep[bRev]; - pLevel->p1 = iCur; - pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); - pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; - } - newNotReady = notReady & ~getMask(pWC->pMaskSet, iCur); - - /* Insert code to test every subexpression that can be completely - ** computed using the current set of tables. - ** - ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through - ** the use of indices become tests that are evaluated against each row of - ** the relevant input tables. - */ - for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ - Expr *pE; - testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */ - testcase( pTerm->wtFlags & TERM_CODED ); - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & newNotReady)!=0 ){ - testcase( pWInfo->untestedTerms==0 - && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ); - pWInfo->untestedTerms = 1; - continue; - } - pE = pTerm->pExpr; - assert( pE!=0 ); - if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ - continue; - } - sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); - pTerm->wtFlags |= TERM_CODED; - } - - /* Insert code to test for implied constraints based on transitivity - ** of the "==" operator. - ** - ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123" - ** and we are coding the t1 loop and the t2 loop has not yet coded, - ** then we cannot use the "t1.a=t2.b" constraint, but we can code - ** the implied "t1.a=123" constraint. - */ - for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ - Expr *pE; - WhereTerm *pAlt; - Expr sEq; - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue; - if( pTerm->leftCursor!=iCur ) continue; - pE = pTerm->pExpr; - assert( !ExprHasProperty(pE, EP_FromJoin) ); - assert( (pTerm->prereqRight & newNotReady)!=0 ); - pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); - if( pAlt==0 ) continue; - if( pAlt->wtFlags & (TERM_CODED) ) continue; - VdbeNoopComment((v, "begin transitive constraint")); - sEq = *pAlt->pExpr; - sEq.pLeft = pE->pLeft; - sqlite3ExprIfFalse(pParse, &sEq, addrCont, SQLITE_JUMPIFNULL); - } - - /* For a LEFT OUTER JOIN, generate code that will record the fact that - ** at least one row of the right table has matched the left table. - */ - if( pLevel->iLeftJoin ){ - pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); - VdbeComment((v, "record LEFT JOIN hit")); - sqlite3ExprCacheClear(pParse); - for(pTerm=pWC->a, j=0; jnTerm; j++, pTerm++){ - testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */ - testcase( pTerm->wtFlags & TERM_CODED ); - if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & newNotReady)!=0 ){ - assert( pWInfo->untestedTerms ); - continue; - } - assert( pTerm->pExpr ); - sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); - pTerm->wtFlags |= TERM_CODED; - } - } - sqlite3ReleaseTempReg(pParse, iReleaseReg); - - return newNotReady; -} - -#if defined(SQLITE_TEST) -/* -** The following variable holds a text description of query plan generated -** by the most recent call to sqlite3WhereBegin(). Each call to WhereBegin -** overwrites the previous. This information is used for testing and -** analysis only. -*/ -SQLITE_API char sqlite3_query_plan[BMS*2*40]; /* Text of the join */ -static int nQPlan = 0; /* Next free slow in _query_plan[] */ - -#endif /* SQLITE_TEST */ - - -/* -** Free a WhereInfo structure -*/ -static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ - if( ALWAYS(pWInfo) ){ - int i; - for(i=0; inLevel; i++){ - sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo; - if( pInfo ){ - /* assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); */ - if( pInfo->needToFreeIdxStr ){ - sqlite3_free(pInfo->idxStr); - } - sqlite3DbFree(db, pInfo); - } - if( pWInfo->a[i].plan.wsFlags & WHERE_TEMP_INDEX ){ - Index *pIdx = pWInfo->a[i].plan.u.pIdx; - if( pIdx ){ - sqlite3DbFree(db, pIdx->zColAff); - sqlite3DbFree(db, pIdx); - } - } - } - whereClauseClear(pWInfo->pWC); - sqlite3DbFree(db, pWInfo); - } -} - - -/* -** Generate the beginning of the loop used for WHERE clause processing. -** The return value is a pointer to an opaque structure that contains -** information needed to terminate the loop. Later, the calling routine -** should invoke sqlite3WhereEnd() with the return value of this function -** in order to complete the WHERE clause processing. -** -** If an error occurs, this routine returns NULL. -** -** The basic idea is to do a nested loop, one loop for each table in -** the FROM clause of a select. (INSERT and UPDATE statements are the -** same as a SELECT with only a single table in the FROM clause.) For -** example, if the SQL is this: -** -** SELECT * FROM t1, t2, t3 WHERE ...; -** -** Then the code generated is conceptually like the following: -** -** foreach row1 in t1 do \ Code generated -** foreach row2 in t2 do |-- by sqlite3WhereBegin() -** foreach row3 in t3 do / -** ... -** end \ Code generated -** end |-- by sqlite3WhereEnd() -** end / -** -** Note that the loops might not be nested in the order in which they -** appear in the FROM clause if a different order is better able to make -** use of indices. Note also that when the IN operator appears in -** the WHERE clause, it might result in additional nested loops for -** scanning through all values on the right-hand side of the IN. -** -** There are Btree cursors associated with each table. t1 uses cursor -** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor. -** And so forth. This routine generates code to open those VDBE cursors -** and sqlite3WhereEnd() generates the code to close them. -** -** The code that sqlite3WhereBegin() generates leaves the cursors named -** in pTabList pointing at their appropriate entries. The [...] code -** can use OP_Column and OP_Rowid opcodes on these cursors to extract -** data from the various tables of the loop. -** -** If the WHERE clause is empty, the foreach loops must each scan their -** entire tables. Thus a three-way join is an O(N^3) operation. But if -** the tables have indices and there are terms in the WHERE clause that -** refer to those indices, a complete table scan can be avoided and the -** code will run much faster. Most of the work of this routine is checking -** to see if there are indices that can be used to speed up the loop. -** -** Terms of the WHERE clause are also used to limit which rows actually -** make it to the "..." in the middle of the loop. After each "foreach", -** terms of the WHERE clause that use only terms in that loop and outer -** loops are evaluated and if false a jump is made around all subsequent -** inner loops (or around the "..." if the test occurs within the inner- -** most loop) -** -** OUTER JOINS -** -** An outer join of tables t1 and t2 is conceptally coded as follows: -** -** foreach row1 in t1 do -** flag = 0 -** foreach row2 in t2 do -** start: -** ... -** flag = 1 -** end -** if flag==0 then -** move the row2 cursor to a null row -** goto start -** fi -** end -** -** ORDER BY CLAUSE PROCESSING -** -** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement, -** if there is one. If there is no ORDER BY clause or if this routine -** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. -** -** If an index can be used so that the natural output order of the table -** scan is correct for the ORDER BY clause, then that index is used and -** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr. This -** is an optimization that prevents an unnecessary sort of the result set -** if an index appropriate for the ORDER BY clause already exists. -** -** If the where clause loops cannot be arranged to provide the correct -** output order, then WhereInfo.nOBSat is 0. -*/ -SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( - Parse *pParse, /* The parser context */ - SrcList *pTabList, /* A list of all tables to be scanned */ - Expr *pWhere, /* The WHERE clause */ - ExprList *pOrderBy, /* An ORDER BY clause, or NULL */ - ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */ - u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ - int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */ -){ - int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ - int nTabList; /* Number of elements in pTabList */ - WhereInfo *pWInfo; /* Will become the return value of this function */ - Vdbe *v = pParse->pVdbe; /* The virtual database engine */ - Bitmask notReady; /* Cursors that are not yet positioned */ - WhereBestIdx sWBI; /* Best index search context */ - WhereMaskSet *pMaskSet; /* The expression mask set */ - WhereLevel *pLevel; /* A single level in pWInfo->a[] */ - int iFrom; /* First unused FROM clause element */ - int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */ - int ii; /* Loop counter */ - sqlite3 *db; /* Database connection */ - - - /* Variable initialization */ - memset(&sWBI, 0, sizeof(sWBI)); - sWBI.pParse = pParse; - - /* The number of tables in the FROM clause is limited by the number of - ** bits in a Bitmask - */ - testcase( pTabList->nSrc==BMS ); - if( pTabList->nSrc>BMS ){ - sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS); - return 0; - } - - /* This function normally generates a nested loop for all tables in - ** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should - ** only generate code for the first table in pTabList and assume that - ** any cursors associated with subsequent tables are uninitialized. - */ - nTabList = (wctrlFlags & WHERE_ONETABLE_ONLY) ? 1 : pTabList->nSrc; - - /* Allocate and initialize the WhereInfo structure that will become the - ** return value. A single allocation is used to store the WhereInfo - ** struct, the contents of WhereInfo.a[], the WhereClause structure - ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte - ** field (type Bitmask) it must be aligned on an 8-byte boundary on - ** some architectures. Hence the ROUND8() below. - */ - db = pParse->db; - nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); - pWInfo = sqlite3DbMallocZero(db, - nByteWInfo + - sizeof(WhereClause) + - sizeof(WhereMaskSet) - ); - if( db->mallocFailed ){ - sqlite3DbFree(db, pWInfo); - pWInfo = 0; - goto whereBeginError; - } - pWInfo->nLevel = nTabList; - pWInfo->pParse = pParse; - pWInfo->pTabList = pTabList; - pWInfo->iBreak = sqlite3VdbeMakeLabel(v); - pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo]; - pWInfo->wctrlFlags = wctrlFlags; - pWInfo->savedNQueryLoop = pParse->nQueryLoop; - pMaskSet = (WhereMaskSet*)&sWBI.pWC[1]; - sWBI.aLevel = pWInfo->a; - - /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via - ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ - if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0; - - /* Split the WHERE clause into separate subexpressions where each - ** subexpression is separated by an AND operator. - */ - initMaskSet(pMaskSet); - whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags); - sqlite3ExprCodeConstants(pParse, pWhere); - whereSplit(sWBI.pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */ - - /* Special case: a WHERE clause that is constant. Evaluate the - ** expression and either jump over all of the code or fall thru. - */ - if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ - sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); - pWhere = 0; - } - - /* Assign a bit from the bitmask to every term in the FROM clause. - ** - ** When assigning bitmask values to FROM clause cursors, it must be - ** the case that if X is the bitmask for the N-th FROM clause term then - ** the bitmask for all FROM clause terms to the left of the N-th term - ** is (X-1). An expression from the ON clause of a LEFT JOIN can use - ** its Expr.iRightJoinTable value to find the bitmask of the right table - ** of the join. Subtracting one from the right table bitmask gives a - ** bitmask for all tables to the left of the join. Knowing the bitmask - ** for all tables to the left of a left join is important. Ticket #3015. - ** - ** Note that bitmasks are created for all pTabList->nSrc tables in - ** pTabList, not just the first nTabList tables. nTabList is normally - ** equal to pTabList->nSrc but might be shortened to 1 if the - ** WHERE_ONETABLE_ONLY flag is set. - */ - for(ii=0; iinSrc; ii++){ - createMask(pMaskSet, pTabList->a[ii].iCursor); - } -#ifndef NDEBUG - { - Bitmask toTheLeft = 0; - for(ii=0; iinSrc; ii++){ - Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor); - assert( (m-1)==toTheLeft ); - toTheLeft |= m; - } - } -#endif - - /* Analyze all of the subexpressions. Note that exprAnalyze() might - ** add new virtual terms onto the end of the WHERE clause. We do not - ** want to analyze these virtual terms, so start analyzing at the end - ** and work forward so that the added virtual terms are never processed. - */ - exprAnalyzeAll(pTabList, sWBI.pWC); - if( db->mallocFailed ){ - goto whereBeginError; - } - - /* Check if the DISTINCT qualifier, if there is one, is redundant. - ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to - ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT. - */ - if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){ - pDistinct = 0; - pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; - } - - /* Chose the best index to use for each table in the FROM clause. - ** - ** This loop fills in the following fields: - ** - ** pWInfo->a[].pIdx The index to use for this level of the loop. - ** pWInfo->a[].wsFlags WHERE_xxx flags associated with pIdx - ** pWInfo->a[].nEq The number of == and IN constraints - ** pWInfo->a[].iFrom Which term of the FROM clause is being coded - ** pWInfo->a[].iTabCur The VDBE cursor for the database table - ** pWInfo->a[].iIdxCur The VDBE cursor for the index - ** pWInfo->a[].pTerm When wsFlags==WO_OR, the OR-clause term - ** - ** This loop also figures out the nesting order of tables in the FROM - ** clause. - */ - sWBI.notValid = ~(Bitmask)0; - sWBI.pOrderBy = pOrderBy; - sWBI.n = nTabList; - sWBI.pDistinct = pDistinct; - andFlags = ~0; - WHERETRACE(("*** Optimizer Start ***\n")); - for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.ia[j]; jiCursor); - if( (m & sWBI.notValid)==0 ){ - if( j==iFrom ) iFrom++; - continue; - } - if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break; - if( ++ckOptimal ) break; - if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break; - } - } - assert( ckOptimal==0 || ckOptimal==1 ); - - for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){ - for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; jiFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){ - /* This break and one like it in the ckOptimal computation loop - ** above prevent table reordering across LEFT and CROSS JOINs. - ** The LEFT JOIN case is necessary for correctness. The prohibition - ** against reordering across a CROSS JOIN is an SQLite feature that - ** allows the developer to control table reordering */ - break; - } - m = getMask(pMaskSet, sWBI.pSrc->iCursor); - if( (m & sWBI.notValid)==0 ){ - assert( j>iFrom ); - continue; - } - sWBI.notReady = (isOptimal ? m : sWBI.notValid); - if( sWBI.pSrc->pIndex==0 ) nUnconstrained++; - - WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n", - j, sWBI.pSrc->pTab->zName, isOptimal)); - assert( sWBI.pSrc->pTab ); -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(sWBI.pSrc->pTab) ){ - sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo; - bestVirtualIndex(&sWBI); - }else -#endif - { - bestBtreeIndex(&sWBI); - } - assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 ); - - /* If an INDEXED BY clause is present, then the plan must use that - ** index if it uses any index at all */ - assert( sWBI.pSrc->pIndex==0 - || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 - || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex ); - - if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ - notIndexed |= m; - } - if( isOptimal ){ - pWInfo->a[j].rOptCost = sWBI.cost.rCost; - }else if( ckOptimal ){ - /* If two or more tables have nearly the same outer loop cost, but - ** very different inner loop (optimal) cost, we want to choose - ** for the outer loop that table which benefits the least from - ** being in the inner loop. The following code scales the - ** outer loop cost estimate to accomplish that. */ - WHERETRACE((" scaling cost from %.1f to %.1f\n", - sWBI.cost.rCost, - sWBI.cost.rCost/pWInfo->a[j].rOptCost)); - sWBI.cost.rCost /= pWInfo->a[j].rOptCost; - } - - /* Conditions under which this table becomes the best so far: - ** - ** (1) The table must not depend on other tables that have not - ** yet run. (In other words, it must not depend on tables - ** in inner loops.) - ** - ** (2) (This rule was removed on 2012-11-09. The scaling of the - ** cost using the optimal scan cost made this rule obsolete.) - ** - ** (3) All tables have an INDEXED BY clause or this table lacks an - ** INDEXED BY clause or this table uses the specific - ** index specified by its INDEXED BY clause. This rule ensures - ** that a best-so-far is always selected even if an impossible - ** combination of INDEXED BY clauses are given. The error - ** will be detected and relayed back to the application later. - ** The NEVER() comes about because rule (2) above prevents - ** An indexable full-table-scan from reaching rule (3). - ** - ** (4) The plan cost must be lower than prior plans, where "cost" - ** is defined by the compareCost() function above. - */ - if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */ - && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */ - || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) - && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */ - ){ - WHERETRACE((" === table %d (%s) is best so far\n" - " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n", - j, sWBI.pSrc->pTab->zName, - sWBI.cost.rCost, sWBI.cost.plan.nRow, - sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags)); - bestPlan = sWBI.cost; - bestJ = j; - } - - /* In a join like "w JOIN x LEFT JOIN y JOIN z" make sure that - ** table y (and not table z) is always the next inner loop inside - ** of table x. */ - if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break; - } - } - assert( bestJ>=0 ); - assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) ); - assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 ); - testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 ); - testcase( bestJ>iFrom && bestJa[bestJ+1].jointype & JT_LEFT)!=0 ); - WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n" - " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n", - bestJ, pTabList->a[bestJ].pTab->zName, - pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow, - bestPlan.plan.nOBSat, bestPlan.plan.wsFlags)); - if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){ - assert( pWInfo->eDistinct==0 ); - pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; - } - andFlags &= bestPlan.plan.wsFlags; - pLevel->plan = bestPlan.plan; - pLevel->iTabCur = pTabList->a[bestJ].iCursor; - testcase( bestPlan.plan.wsFlags & WHERE_INDEXED ); - testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX ); - if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){ - if( (wctrlFlags & WHERE_ONETABLE_ONLY) - && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0 - ){ - pLevel->iIdxCur = iIdxCur; - }else{ - pLevel->iIdxCur = pParse->nTab++; - } - }else{ - pLevel->iIdxCur = -1; - } - sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor); - pLevel->iFrom = (u8)bestJ; - if( bestPlan.plan.nRow>=(double)1 ){ - pParse->nQueryLoop *= bestPlan.plan.nRow; - } - - /* Check that if the table scanned by this loop iteration had an - ** INDEXED BY clause attached to it, that the named index is being - ** used for the scan. If not, then query compilation has failed. - ** Return an error. - */ - pIdx = pTabList->a[bestJ].pIndex; - if( pIdx ){ - if( (bestPlan.plan.wsFlags & WHERE_INDEXED)==0 ){ - sqlite3ErrorMsg(pParse, "cannot use index: %s", pIdx->zName); - goto whereBeginError; - }else{ - /* If an INDEXED BY clause is used, the bestIndex() function is - ** guaranteed to find the index specified in the INDEXED BY clause - ** if it find an index at all. */ - assert( bestPlan.plan.u.pIdx==pIdx ); - } - } - } - WHERETRACE(("*** Optimizer Finished ***\n")); - if( pParse->nErr || db->mallocFailed ){ - goto whereBeginError; - } - if( nTabList ){ - pLevel--; - pWInfo->nOBSat = pLevel->plan.nOBSat; - }else{ - pWInfo->nOBSat = 0; - } - - /* If the total query only selects a single row, then the ORDER BY - ** clause is irrelevant. - */ - if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){ - assert( nTabList==0 || (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ); - pWInfo->nOBSat = pOrderBy->nExpr; - } - - /* If the caller is an UPDATE or DELETE statement that is requesting - ** to use a one-pass algorithm, determine if this is appropriate. - ** The one-pass algorithm only works if the WHERE clause constraints - ** the statement to update a single row. - */ - assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); - if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){ - pWInfo->okOnePass = 1; - pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY; - } - - /* Open all tables in the pTabList and any indices selected for - ** searching those tables. - */ - sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ - notReady = ~(Bitmask)0; - pWInfo->nRowOut = (double)1; - for(ii=0, pLevel=pWInfo->a; iia[pLevel->iFrom]; - pTab = pTabItem->pTab; - pWInfo->nRowOut *= pLevel->plan.nRow; - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ - /* Do nothing */ - }else -#ifndef SQLITE_OMIT_VIRTUALTABLE - if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ - const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); - int iCur = pTabItem->iCursor; - sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); - }else if( IsVirtual(pTab) ){ - /* noop */ - }else -#endif - if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 - && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ - int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; - sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); - testcase( pTab->nCol==BMS-1 ); - testcase( pTab->nCol==BMS ); - if( !pWInfo->okOnePass && pTab->nColcolUsed; - int n = 0; - for(; b; b=b>>1, n++){} - sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1, - SQLITE_INT_TO_PTR(n), P4_INT32); - assert( n<=pTab->nCol ); - } - }else{ - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); - } -#ifndef SQLITE_OMIT_AUTOMATIC_INDEX - if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){ - constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel); - }else -#endif - if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){ - Index *pIx = pLevel->plan.u.pIdx; - KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); - int iIndexCur = pLevel->iIdxCur; - assert( pIx->pSchema==pTab->pSchema ); - assert( iIndexCur>=0 ); - sqlite3VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb, - (char*)pKey, P4_KEYINFO_HANDOFF); - VdbeComment((v, "%s", pIx->zName)); - } - sqlite3CodeVerifySchema(pParse, iDb); - notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor); - } - pWInfo->iTop = sqlite3VdbeCurrentAddr(v); - if( db->mallocFailed ) goto whereBeginError; - - /* Generate the code to do the search. Each iteration of the for - ** loop below generates code for a single nested loop of the VM - ** program. - */ - notReady = ~(Bitmask)0; - for(ii=0; iia[ii]; - explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags); - notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady); - pWInfo->iContinue = pLevel->addrCont; - } - -#ifdef SQLITE_TEST /* For testing and debugging use only */ - /* Record in the query plan information about the current table - ** and the index used to access it (if any). If the table itself - ** is not used, its name is just '{}'. If no index is used - ** the index is listed as "{}". If the primary key is used the - ** index name is '*'. - */ - for(ii=0; iia[ii]; - w = pLevel->plan.wsFlags; - pTabItem = &pTabList->a[pLevel->iFrom]; - z = pTabItem->zAlias; - if( z==0 ) z = pTabItem->pTab->zName; - n = sqlite3Strlen30(z); - if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){ - if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){ - memcpy(&sqlite3_query_plan[nQPlan], "{}", 2); - nQPlan += 2; - }else{ - memcpy(&sqlite3_query_plan[nQPlan], z, n); - nQPlan += n; - } - sqlite3_query_plan[nQPlan++] = ' '; - } - testcase( w & WHERE_ROWID_EQ ); - testcase( w & WHERE_ROWID_RANGE ); - if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){ - memcpy(&sqlite3_query_plan[nQPlan], "* ", 2); - nQPlan += 2; - }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){ - n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName); - if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){ - memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n); - nQPlan += n; - sqlite3_query_plan[nQPlan++] = ' '; - } - }else{ - memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3); - nQPlan += 3; - } - } - while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){ - sqlite3_query_plan[--nQPlan] = 0; - } - sqlite3_query_plan[nQPlan] = 0; - nQPlan = 0; -#endif /* SQLITE_TEST // Testing and debugging use only */ - - /* Record the continuation address in the WhereInfo structure. Then - ** clean up and return. - */ - return pWInfo; - - /* Jump here if malloc fails */ -whereBeginError: - if( pWInfo ){ - pParse->nQueryLoop = pWInfo->savedNQueryLoop; - whereInfoFree(db, pWInfo); - } - return 0; -} - -/* -** Generate the end of the WHERE loop. See comments on -** sqlite3WhereBegin() for additional information. -*/ -SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ - Parse *pParse = pWInfo->pParse; - Vdbe *v = pParse->pVdbe; - int i; - WhereLevel *pLevel; - SrcList *pTabList = pWInfo->pTabList; - sqlite3 *db = pParse->db; - - /* Generate loop termination code. - */ - sqlite3ExprCacheClear(pParse); - for(i=pWInfo->nLevel-1; i>=0; i--){ - pLevel = &pWInfo->a[i]; - sqlite3VdbeResolveLabel(v, pLevel->addrCont); - if( pLevel->op!=OP_Noop ){ - sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2); - sqlite3VdbeChangeP5(v, pLevel->p5); - } - if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ - struct InLoop *pIn; - int j; - sqlite3VdbeResolveLabel(v, pLevel->addrNxt); - for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ - sqlite3VdbeJumpHere(v, pIn->addrInTop+1); - sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); - sqlite3VdbeJumpHere(v, pIn->addrInTop-1); - } - sqlite3DbFree(db, pLevel->u.in.aInLoop); - } - sqlite3VdbeResolveLabel(v, pLevel->addrBrk); - if( pLevel->iLeftJoin ){ - int addr; - addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); - assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 - || (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ); - if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){ - sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); - } - if( pLevel->iIdxCur>=0 ){ - sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); - } - if( pLevel->op==OP_Return ){ - sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); - }else{ - sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst); - } - sqlite3VdbeJumpHere(v, addr); - } - } - - /* The "break" point is here, just past the end of the outer loop. - ** Set it. - */ - sqlite3VdbeResolveLabel(v, pWInfo->iBreak); - - /* Close all of the cursors that were opened by sqlite3WhereBegin. - */ - assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc ); - for(i=0, pLevel=pWInfo->a; inLevel; i++, pLevel++){ - Index *pIdx = 0; - struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom]; - Table *pTab = pTabItem->pTab; - assert( pTab!=0 ); - if( (pTab->tabFlags & TF_Ephemeral)==0 - && pTab->pSelect==0 - && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 - ){ - int ws = pLevel->plan.wsFlags; - if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){ - sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); - } - if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_TEMP_INDEX)==0 ){ - sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); - } - } - - /* If this scan uses an index, make code substitutions to read data - ** from the index in preference to the table. Sometimes, this means - ** the table need never be read from. This is a performance boost, - ** as the vdbe level waits until the table is read before actually - ** seeking the table cursor to the record corresponding to the current - ** position in the index. - ** - ** Calls to the code generator in between sqlite3WhereBegin and - ** sqlite3WhereEnd will have created code that references the table - ** directly. This loop scans all that code looking for opcodes - ** that reference the table and converts them into opcodes that - ** reference the index. - */ - if( pLevel->plan.wsFlags & WHERE_INDEXED ){ - pIdx = pLevel->plan.u.pIdx; - }else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){ - pIdx = pLevel->u.pCovidx; - } - if( pIdx && !db->mallocFailed){ - int k, j, last; - VdbeOp *pOp; - - pOp = sqlite3VdbeGetOp(v, pWInfo->iTop); - last = sqlite3VdbeCurrentAddr(v); - for(k=pWInfo->iTop; kp1!=pLevel->iTabCur ) continue; - if( pOp->opcode==OP_Column ){ - for(j=0; jnColumn; j++){ - if( pOp->p2==pIdx->aiColumn[j] ){ - pOp->p2 = j; - pOp->p1 = pLevel->iIdxCur; - break; - } - } - assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 - || jnColumn ); - }else if( pOp->opcode==OP_Rowid ){ - pOp->p1 = pLevel->iIdxCur; - pOp->opcode = OP_IdxRowid; - } - } - } - } - - /* Final cleanup - */ - pParse->nQueryLoop = pWInfo->savedNQueryLoop; - whereInfoFree(db, pWInfo); - return; -} - -/************** End of where.c ***********************************************/ -/************** Begin file parse.c *******************************************/ -/* Driver template for the LEMON parser generator. -** The author disclaims copyright to this source code. -** -** This version of "lempar.c" is modified, slightly, for use by SQLite. -** The only modifications are the addition of a couple of NEVER() -** macros to disable tests that are needed in the case of a general -** LALR(1) grammar but which are always false in the -** specific grammar used by SQLite. -*/ -/* First off, code is included that follows the "include" declaration -** in the input grammar file. */ -/* #include */ - - -/* -** Disable all error recovery processing in the parser push-down -** automaton. -*/ -#define YYNOERRORRECOVERY 1 - -/* -** Make yytestcase() the same as testcase() -*/ -#define yytestcase(X) testcase(X) - -/* -** An instance of this structure holds information about the -** LIMIT clause of a SELECT statement. -*/ -struct LimitVal { - Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ - Expr *pOffset; /* The OFFSET expression. NULL if there is none */ -}; - -/* -** An instance of this structure is used to store the LIKE, -** GLOB, NOT LIKE, and NOT GLOB operators. -*/ -struct LikeOp { - Token eOperator; /* "like" or "glob" or "regexp" */ - int bNot; /* True if the NOT keyword is present */ -}; - -/* -** An instance of the following structure describes the event of a -** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, -** TK_DELETE, or TK_INSTEAD. If the event is of the form -** -** UPDATE ON (a,b,c) -** -** Then the "b" IdList records the list "a,b,c". -*/ -struct TrigEvent { int a; IdList * b; }; - -/* -** An instance of this structure holds the ATTACH key and the key type. -*/ -struct AttachKey { int type; Token key; }; - -/* -** One or more VALUES claues -*/ -struct ValueList { - ExprList *pList; - Select *pSelect; -}; - - - /* This is a utility routine used to set the ExprSpan.zStart and - ** ExprSpan.zEnd values of pOut so that the span covers the complete - ** range of text beginning with pStart and going to the end of pEnd. - */ - static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){ - pOut->zStart = pStart->z; - pOut->zEnd = &pEnd->z[pEnd->n]; - } - - /* Construct a new Expr object from a single identifier. Use the - ** new Expr to populate pOut. Set the span of pOut to be the identifier - ** that created the expression. - */ - static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token *pValue){ - pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, pValue); - pOut->zStart = pValue->z; - pOut->zEnd = &pValue->z[pValue->n]; - } - - /* This routine constructs a binary expression node out of two ExprSpan - ** objects and uses the result to populate a new ExprSpan object. - */ - static void spanBinaryExpr( - ExprSpan *pOut, /* Write the result here */ - Parse *pParse, /* The parsing context. Errors accumulate here */ - int op, /* The binary operation */ - ExprSpan *pLeft, /* The left operand */ - ExprSpan *pRight /* The right operand */ - ){ - pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); - pOut->zStart = pLeft->zStart; - pOut->zEnd = pRight->zEnd; - } - - /* Construct an expression node for a unary postfix operator - */ - static void spanUnaryPostfix( - ExprSpan *pOut, /* Write the new expression node here */ - Parse *pParse, /* Parsing context to record errors */ - int op, /* The operator */ - ExprSpan *pOperand, /* The operand */ - Token *pPostOp /* The operand token for setting the span */ - ){ - pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); - pOut->zStart = pOperand->zStart; - pOut->zEnd = &pPostOp->z[pPostOp->n]; - } - - /* A routine to convert a binary TK_IS or TK_ISNOT expression into a - ** unary TK_ISNULL or TK_NOTNULL expression. */ - static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ - sqlite3 *db = pParse->db; - if( db->mallocFailed==0 && pY->op==TK_NULL ){ - pA->op = (u8)op; - sqlite3ExprDelete(db, pA->pRight); - pA->pRight = 0; - } - } - - /* Construct an expression node for a unary prefix operator - */ - static void spanUnaryPrefix( - ExprSpan *pOut, /* Write the new expression node here */ - Parse *pParse, /* Parsing context to record errors */ - int op, /* The operator */ - ExprSpan *pOperand, /* The operand */ - Token *pPreOp /* The operand token for setting the span */ - ){ - pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); - pOut->zStart = pPreOp->z; - pOut->zEnd = pOperand->zEnd; - } -/* Next is all token values, in a form suitable for use by makeheaders. -** This section will be null unless lemon is run with the -m switch. -*/ -/* -** These constants (all generated automatically by the parser generator) -** specify the various kinds of tokens (terminals) that the parser -** understands. -** -** Each symbol here is a terminal symbol in the grammar. -*/ -/* Make sure the INTERFACE macro is defined. -*/ -#ifndef INTERFACE -# define INTERFACE 1 -#endif -/* The next thing included is series of defines which control -** various aspects of the generated parser. -** YYCODETYPE is the data type used for storing terminal -** and nonterminal numbers. "unsigned char" is -** used if there are fewer than 250 terminals -** and nonterminals. "int" is used otherwise. -** YYNOCODE is a number of type YYCODETYPE which corresponds -** to no legal terminal or nonterminal number. This -** number is used to fill in empty slots of the hash -** table. -** YYFALLBACK If defined, this indicates that one or more tokens -** have fall-back values which should be used if the -** original value of the token will not parse. -** YYACTIONTYPE is the data type used for storing terminal -** and nonterminal numbers. "unsigned char" is -** used if there are fewer than 250 rules and -** states combined. "int" is used otherwise. -** sqlite3ParserTOKENTYPE is the data type used for minor tokens given -** directly to the parser from the tokenizer. -** YYMINORTYPE is the data type used for all minor tokens. -** This is typically a union of many types, one of -** which is sqlite3ParserTOKENTYPE. The entry in the union -** for base tokens is called "yy0". -** YYSTACKDEPTH is the maximum depth of the parser's stack. If -** zero the stack is dynamically sized using realloc() -** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument -** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument -** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser -** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser -** YYNSTATE the combined number of states. -** YYNRULE the number of rules in the grammar -** YYERRORSYMBOL is the code number of the error symbol. If not -** defined, then do no error processing. -*/ -#define YYCODETYPE unsigned char -#define YYNOCODE 251 -#define YYACTIONTYPE unsigned short int -#define YYWILDCARD 67 -#define sqlite3ParserTOKENTYPE Token -typedef union { - int yyinit; - sqlite3ParserTOKENTYPE yy0; - struct LimitVal yy64; - Expr* yy122; - Select* yy159; - IdList* yy180; - struct {int value; int mask;} yy207; - u8 yy258; - u16 yy305; - struct LikeOp yy318; - TriggerStep* yy327; - ExprSpan yy342; - SrcList* yy347; - int yy392; - struct TrigEvent yy410; - ExprList* yy442; - struct ValueList yy487; -} YYMINORTYPE; -#ifndef YYSTACKDEPTH -#define YYSTACKDEPTH 100 -#endif -#define sqlite3ParserARG_SDECL Parse *pParse; -#define sqlite3ParserARG_PDECL ,Parse *pParse -#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse -#define sqlite3ParserARG_STORE yypParser->pParse = pParse -#define YYNSTATE 627 -#define YYNRULE 327 -#define YYFALLBACK 1 -#define YY_NO_ACTION (YYNSTATE+YYNRULE+2) -#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) -#define YY_ERROR_ACTION (YYNSTATE+YYNRULE) - -/* The yyzerominor constant is used to initialize instances of -** YYMINORTYPE objects to zero. */ -static const YYMINORTYPE yyzerominor = { 0 }; - -/* Define the yytestcase() macro to be a no-op if is not already defined -** otherwise. -** -** Applications can choose to define yytestcase() in the %include section -** to a macro that can assist in verifying code coverage. For production -** code the yytestcase() macro should be turned off. But it is useful -** for testing. -*/ -#ifndef yytestcase -# define yytestcase(X) -#endif - - -/* Next are the tables used to determine what action to take based on the -** current state and lookahead token. These tables are used to implement -** functions that take a state number and lookahead value and return an -** action integer. -** -** Suppose the action integer is N. Then the action is determined as -** follows -** -** 0 <= N < YYNSTATE Shift N. That is, push the lookahead -** token onto the stack and goto state N. -** -** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. -** -** N == YYNSTATE+YYNRULE A syntax error has occurred. -** -** N == YYNSTATE+YYNRULE+1 The parser accepts its input. -** -** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused -** slots in the yy_action[] table. -** -** The action table is constructed as a single large table named yy_action[]. -** Given state S and lookahead X, the action is computed as -** -** yy_action[ yy_shift_ofst[S] + X ] -** -** If the index value yy_shift_ofst[S]+X is out of range or if the value -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] -** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that yy_default[S] should be used instead. -** -** The formula above is for computing the action when the lookahead is -** a terminal symbol. If the lookahead is a non-terminal (as occurs after -** a reduce action) then the yy_reduce_ofst[] array is used in place of -** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of -** YY_SHIFT_USE_DFLT. -** -** The following are the tables generated in this section: -** -** yy_action[] A single table containing all actions. -** yy_lookahead[] A table containing the lookahead for each entry in -** yy_action. Used to detect hash collisions. -** yy_shift_ofst[] For each state, the offset into yy_action for -** shifting terminals. -** yy_reduce_ofst[] For each state, the offset into yy_action for -** shifting non-terminals after a reduce. -** yy_default[] Default action for each state. -*/ -#define YY_ACTTAB_COUNT (1564) -static const YYACTIONTYPE yy_action[] = { - /* 0 */ 309, 955, 184, 417, 2, 171, 624, 594, 56, 56, - /* 10 */ 56, 56, 49, 54, 54, 54, 54, 53, 53, 52, - /* 20 */ 52, 52, 51, 233, 620, 619, 298, 620, 619, 234, - /* 30 */ 587, 581, 56, 56, 56, 56, 19, 54, 54, 54, - /* 40 */ 54, 53, 53, 52, 52, 52, 51, 233, 605, 57, - /* 50 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56, - /* 60 */ 56, 56, 541, 54, 54, 54, 54, 53, 53, 52, - /* 70 */ 52, 52, 51, 233, 309, 594, 325, 196, 195, 194, - /* 80 */ 33, 54, 54, 54, 54, 53, 53, 52, 52, 52, - /* 90 */ 51, 233, 617, 616, 165, 617, 616, 380, 377, 376, - /* 100 */ 407, 532, 576, 576, 587, 581, 303, 422, 375, 59, - /* 110 */ 53, 53, 52, 52, 52, 51, 233, 50, 47, 146, - /* 120 */ 574, 545, 65, 57, 58, 48, 579, 578, 580, 580, - /* 130 */ 55, 55, 56, 56, 56, 56, 213, 54, 54, 54, - /* 140 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 223, - /* 150 */ 539, 420, 170, 176, 138, 280, 383, 275, 382, 168, - /* 160 */ 489, 551, 409, 668, 620, 619, 271, 438, 409, 438, - /* 170 */ 550, 604, 67, 482, 507, 618, 599, 412, 587, 581, - /* 180 */ 600, 483, 618, 412, 618, 598, 91, 439, 440, 439, - /* 190 */ 335, 598, 73, 669, 222, 266, 480, 57, 58, 48, - /* 200 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56, - /* 210 */ 670, 54, 54, 54, 54, 53, 53, 52, 52, 52, - /* 220 */ 51, 233, 309, 279, 232, 231, 1, 132, 200, 385, - /* 230 */ 620, 619, 617, 616, 278, 435, 289, 563, 175, 262, - /* 240 */ 409, 264, 437, 497, 436, 166, 441, 568, 336, 568, - /* 250 */ 201, 537, 587, 581, 599, 412, 165, 594, 600, 380, - /* 260 */ 377, 376, 597, 598, 92, 523, 618, 569, 569, 592, - /* 270 */ 375, 57, 58, 48, 579, 578, 580, 580, 55, 55, - /* 280 */ 56, 56, 56, 56, 597, 54, 54, 54, 54, 53, - /* 290 */ 53, 52, 52, 52, 51, 233, 309, 463, 617, 616, - /* 300 */ 590, 590, 590, 174, 272, 396, 409, 272, 409, 548, - /* 310 */ 397, 620, 619, 68, 326, 620, 619, 620, 619, 618, - /* 320 */ 546, 412, 618, 412, 471, 594, 587, 581, 472, 598, - /* 330 */ 92, 598, 92, 52, 52, 52, 51, 233, 513, 512, - /* 340 */ 206, 322, 363, 464, 221, 57, 58, 48, 579, 578, - /* 350 */ 580, 580, 55, 55, 56, 56, 56, 56, 529, 54, - /* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233, - /* 370 */ 309, 396, 409, 396, 597, 372, 386, 530, 347, 617, - /* 380 */ 616, 575, 202, 617, 616, 617, 616, 412, 620, 619, - /* 390 */ 145, 255, 346, 254, 577, 598, 74, 351, 45, 489, - /* 400 */ 587, 581, 235, 189, 464, 544, 167, 296, 187, 469, - /* 410 */ 479, 67, 62, 39, 618, 546, 597, 345, 573, 57, - /* 420 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56, - /* 430 */ 56, 56, 6, 54, 54, 54, 54, 53, 53, 52, - /* 440 */ 52, 52, 51, 233, 309, 562, 558, 407, 528, 576, - /* 450 */ 576, 344, 255, 346, 254, 182, 617, 616, 503, 504, - /* 460 */ 314, 409, 557, 235, 166, 271, 409, 352, 564, 181, - /* 470 */ 407, 546, 576, 576, 587, 581, 412, 537, 556, 561, - /* 480 */ 517, 412, 618, 249, 598, 16, 7, 36, 467, 598, - /* 490 */ 92, 516, 618, 57, 58, 48, 579, 578, 580, 580, - /* 500 */ 55, 55, 56, 56, 56, 56, 541, 54, 54, 54, - /* 510 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 327, - /* 520 */ 572, 571, 525, 558, 560, 394, 871, 246, 409, 248, - /* 530 */ 171, 392, 594, 219, 407, 409, 576, 576, 502, 557, - /* 540 */ 364, 145, 510, 412, 407, 229, 576, 576, 587, 581, - /* 550 */ 412, 598, 92, 381, 269, 556, 166, 400, 598, 69, - /* 560 */ 501, 419, 945, 199, 945, 198, 546, 57, 58, 48, - /* 570 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56, - /* 580 */ 568, 54, 54, 54, 54, 53, 53, 52, 52, 52, - /* 590 */ 51, 233, 309, 317, 419, 944, 508, 944, 308, 597, - /* 600 */ 594, 565, 490, 212, 173, 247, 423, 615, 614, 613, - /* 610 */ 323, 197, 143, 405, 572, 571, 489, 66, 50, 47, - /* 620 */ 146, 594, 587, 581, 232, 231, 559, 427, 67, 555, - /* 630 */ 15, 618, 186, 543, 303, 421, 35, 206, 432, 423, - /* 640 */ 552, 57, 58, 48, 579, 578, 580, 580, 55, 55, - /* 650 */ 56, 56, 56, 56, 205, 54, 54, 54, 54, 53, - /* 660 */ 53, 52, 52, 52, 51, 233, 309, 569, 569, 260, - /* 670 */ 268, 597, 12, 373, 568, 166, 409, 313, 409, 420, - /* 680 */ 409, 473, 473, 365, 618, 50, 47, 146, 597, 594, - /* 690 */ 468, 412, 166, 412, 351, 412, 587, 581, 32, 598, - /* 700 */ 94, 598, 97, 598, 95, 627, 625, 329, 142, 50, - /* 710 */ 47, 146, 333, 349, 358, 57, 58, 48, 579, 578, - /* 720 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54, - /* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233, - /* 740 */ 309, 409, 388, 412, 409, 22, 565, 404, 212, 362, - /* 750 */ 389, 598, 104, 359, 409, 156, 412, 409, 603, 412, - /* 760 */ 537, 331, 569, 569, 598, 103, 493, 598, 105, 412, - /* 770 */ 587, 581, 412, 260, 549, 618, 11, 598, 106, 521, - /* 780 */ 598, 133, 169, 457, 456, 170, 35, 601, 618, 57, - /* 790 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56, - /* 800 */ 56, 56, 409, 54, 54, 54, 54, 53, 53, 52, - /* 810 */ 52, 52, 51, 233, 309, 409, 259, 412, 409, 50, - /* 820 */ 47, 146, 357, 318, 355, 598, 134, 527, 352, 337, - /* 830 */ 412, 409, 356, 412, 357, 409, 357, 618, 598, 98, - /* 840 */ 129, 598, 102, 618, 587, 581, 412, 21, 235, 618, - /* 850 */ 412, 618, 211, 143, 598, 101, 30, 167, 598, 93, - /* 860 */ 350, 535, 203, 57, 58, 48, 579, 578, 580, 580, - /* 870 */ 55, 55, 56, 56, 56, 56, 409, 54, 54, 54, - /* 880 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 409, - /* 890 */ 526, 412, 409, 425, 215, 305, 597, 551, 141, 598, - /* 900 */ 100, 40, 409, 38, 412, 409, 550, 412, 409, 228, - /* 910 */ 220, 314, 598, 77, 500, 598, 96, 412, 587, 581, - /* 920 */ 412, 338, 253, 412, 218, 598, 137, 379, 598, 136, - /* 930 */ 28, 598, 135, 270, 715, 210, 481, 57, 58, 48, - /* 940 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56, - /* 950 */ 409, 54, 54, 54, 54, 53, 53, 52, 52, 52, - /* 960 */ 51, 233, 309, 409, 272, 412, 409, 315, 147, 597, - /* 970 */ 272, 626, 2, 598, 76, 209, 409, 127, 412, 618, - /* 980 */ 126, 412, 409, 621, 235, 618, 598, 90, 374, 598, - /* 990 */ 89, 412, 587, 581, 27, 260, 350, 412, 618, 598, - /* 1000 */ 75, 321, 541, 541, 125, 598, 88, 320, 278, 597, - /* 1010 */ 618, 57, 46, 48, 579, 578, 580, 580, 55, 55, - /* 1020 */ 56, 56, 56, 56, 409, 54, 54, 54, 54, 53, - /* 1030 */ 53, 52, 52, 52, 51, 233, 309, 409, 450, 412, - /* 1040 */ 164, 284, 282, 272, 609, 424, 304, 598, 87, 370, - /* 1050 */ 409, 477, 412, 409, 608, 409, 607, 602, 618, 618, - /* 1060 */ 598, 99, 586, 585, 122, 412, 587, 581, 412, 618, - /* 1070 */ 412, 618, 618, 598, 86, 366, 598, 17, 598, 85, - /* 1080 */ 319, 185, 519, 518, 583, 582, 58, 48, 579, 578, - /* 1090 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54, - /* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233, - /* 1110 */ 309, 584, 409, 412, 409, 260, 260, 260, 408, 591, - /* 1120 */ 474, 598, 84, 170, 409, 466, 518, 412, 121, 412, - /* 1130 */ 618, 618, 618, 618, 618, 598, 83, 598, 72, 412, - /* 1140 */ 587, 581, 51, 233, 625, 329, 470, 598, 71, 257, - /* 1150 */ 159, 120, 14, 462, 157, 158, 117, 260, 448, 447, - /* 1160 */ 446, 48, 579, 578, 580, 580, 55, 55, 56, 56, - /* 1170 */ 56, 56, 618, 54, 54, 54, 54, 53, 53, 52, - /* 1180 */ 52, 52, 51, 233, 44, 403, 260, 3, 409, 459, - /* 1190 */ 260, 413, 619, 118, 398, 10, 25, 24, 554, 348, - /* 1200 */ 217, 618, 406, 412, 409, 618, 4, 44, 403, 618, - /* 1210 */ 3, 598, 82, 618, 413, 619, 455, 542, 115, 412, - /* 1220 */ 538, 401, 536, 274, 506, 406, 251, 598, 81, 216, - /* 1230 */ 273, 563, 618, 243, 453, 618, 154, 618, 618, 618, - /* 1240 */ 449, 416, 623, 110, 401, 618, 409, 236, 64, 123, - /* 1250 */ 487, 41, 42, 531, 563, 204, 409, 267, 43, 411, - /* 1260 */ 410, 412, 265, 592, 108, 618, 107, 434, 332, 598, - /* 1270 */ 80, 412, 618, 263, 41, 42, 443, 618, 409, 598, - /* 1280 */ 70, 43, 411, 410, 433, 261, 592, 149, 618, 597, - /* 1290 */ 256, 237, 188, 412, 590, 590, 590, 589, 588, 13, - /* 1300 */ 618, 598, 18, 328, 235, 618, 44, 403, 360, 3, - /* 1310 */ 418, 461, 339, 413, 619, 227, 124, 590, 590, 590, - /* 1320 */ 589, 588, 13, 618, 406, 409, 618, 409, 139, 34, - /* 1330 */ 403, 387, 3, 148, 622, 312, 413, 619, 311, 330, - /* 1340 */ 412, 460, 412, 401, 180, 353, 412, 406, 598, 79, - /* 1350 */ 598, 78, 250, 563, 598, 9, 618, 612, 611, 610, - /* 1360 */ 618, 8, 452, 442, 242, 415, 401, 618, 239, 235, - /* 1370 */ 179, 238, 428, 41, 42, 288, 563, 618, 618, 618, - /* 1380 */ 43, 411, 410, 618, 144, 592, 618, 618, 177, 61, - /* 1390 */ 618, 596, 391, 620, 619, 287, 41, 42, 414, 618, - /* 1400 */ 293, 30, 393, 43, 411, 410, 292, 618, 592, 31, - /* 1410 */ 618, 395, 291, 60, 230, 37, 590, 590, 590, 589, - /* 1420 */ 588, 13, 214, 553, 183, 290, 172, 301, 300, 299, - /* 1430 */ 178, 297, 595, 563, 451, 29, 285, 390, 540, 590, - /* 1440 */ 590, 590, 589, 588, 13, 283, 520, 534, 150, 533, - /* 1450 */ 241, 281, 384, 192, 191, 324, 515, 514, 276, 240, - /* 1460 */ 510, 523, 307, 511, 128, 592, 509, 225, 226, 486, - /* 1470 */ 485, 224, 152, 491, 464, 306, 484, 163, 153, 371, - /* 1480 */ 478, 151, 162, 258, 369, 161, 367, 208, 475, 476, - /* 1490 */ 26, 160, 465, 140, 361, 131, 590, 590, 590, 116, - /* 1500 */ 119, 454, 343, 155, 114, 342, 113, 112, 445, 111, - /* 1510 */ 130, 109, 431, 316, 426, 430, 23, 429, 20, 606, - /* 1520 */ 190, 507, 255, 341, 244, 63, 294, 593, 310, 570, - /* 1530 */ 277, 402, 354, 235, 567, 496, 495, 492, 494, 302, - /* 1540 */ 458, 378, 286, 245, 566, 5, 252, 547, 193, 444, - /* 1550 */ 233, 340, 207, 524, 368, 505, 334, 522, 499, 399, - /* 1560 */ 295, 498, 956, 488, -}; -static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 19, 142, 143, 144, 145, 24, 1, 26, 77, 78, - /* 10 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - /* 20 */ 89, 90, 91, 92, 26, 27, 15, 26, 27, 197, - /* 30 */ 49, 50, 77, 78, 79, 80, 204, 82, 83, 84, - /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 23, 68, - /* 50 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 60 */ 79, 80, 166, 82, 83, 84, 85, 86, 87, 88, - /* 70 */ 89, 90, 91, 92, 19, 94, 19, 105, 106, 107, - /* 80 */ 25, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 90 */ 91, 92, 94, 95, 96, 94, 95, 99, 100, 101, - /* 100 */ 112, 205, 114, 115, 49, 50, 22, 23, 110, 54, - /* 110 */ 86, 87, 88, 89, 90, 91, 92, 221, 222, 223, - /* 120 */ 23, 120, 25, 68, 69, 70, 71, 72, 73, 74, - /* 130 */ 75, 76, 77, 78, 79, 80, 22, 82, 83, 84, - /* 140 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 92, - /* 150 */ 23, 67, 25, 96, 97, 98, 99, 100, 101, 102, - /* 160 */ 150, 32, 150, 118, 26, 27, 109, 150, 150, 150, - /* 170 */ 41, 161, 162, 180, 181, 165, 113, 165, 49, 50, - /* 180 */ 117, 188, 165, 165, 165, 173, 174, 170, 171, 170, - /* 190 */ 171, 173, 174, 118, 184, 16, 186, 68, 69, 70, - /* 200 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 210 */ 118, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 220 */ 91, 92, 19, 98, 86, 87, 22, 24, 160, 88, - /* 230 */ 26, 27, 94, 95, 109, 97, 224, 66, 118, 60, - /* 240 */ 150, 62, 104, 23, 106, 25, 229, 230, 229, 230, - /* 250 */ 160, 150, 49, 50, 113, 165, 96, 26, 117, 99, - /* 260 */ 100, 101, 194, 173, 174, 94, 165, 129, 130, 98, - /* 270 */ 110, 68, 69, 70, 71, 72, 73, 74, 75, 76, - /* 280 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86, - /* 290 */ 87, 88, 89, 90, 91, 92, 19, 11, 94, 95, - /* 300 */ 129, 130, 131, 118, 150, 215, 150, 150, 150, 25, - /* 310 */ 220, 26, 27, 22, 213, 26, 27, 26, 27, 165, - /* 320 */ 25, 165, 165, 165, 30, 94, 49, 50, 34, 173, - /* 330 */ 174, 173, 174, 88, 89, 90, 91, 92, 7, 8, - /* 340 */ 160, 187, 48, 57, 187, 68, 69, 70, 71, 72, - /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 23, 82, - /* 360 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 370 */ 19, 215, 150, 215, 194, 19, 220, 88, 220, 94, - /* 380 */ 95, 23, 160, 94, 95, 94, 95, 165, 26, 27, - /* 390 */ 95, 105, 106, 107, 113, 173, 174, 217, 22, 150, - /* 400 */ 49, 50, 116, 119, 57, 120, 50, 158, 22, 21, - /* 410 */ 161, 162, 232, 136, 165, 120, 194, 237, 23, 68, - /* 420 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 430 */ 79, 80, 22, 82, 83, 84, 85, 86, 87, 88, - /* 440 */ 89, 90, 91, 92, 19, 23, 12, 112, 23, 114, - /* 450 */ 115, 63, 105, 106, 107, 23, 94, 95, 97, 98, - /* 460 */ 104, 150, 28, 116, 25, 109, 150, 150, 23, 23, - /* 470 */ 112, 25, 114, 115, 49, 50, 165, 150, 44, 11, - /* 480 */ 46, 165, 165, 16, 173, 174, 76, 136, 100, 173, - /* 490 */ 174, 57, 165, 68, 69, 70, 71, 72, 73, 74, - /* 500 */ 75, 76, 77, 78, 79, 80, 166, 82, 83, 84, - /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 169, - /* 520 */ 170, 171, 23, 12, 23, 214, 138, 60, 150, 62, - /* 530 */ 24, 215, 26, 216, 112, 150, 114, 115, 36, 28, - /* 540 */ 213, 95, 103, 165, 112, 205, 114, 115, 49, 50, - /* 550 */ 165, 173, 174, 51, 23, 44, 25, 46, 173, 174, - /* 560 */ 58, 22, 23, 22, 25, 160, 120, 68, 69, 70, - /* 570 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 580 */ 230, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 590 */ 91, 92, 19, 215, 22, 23, 23, 25, 163, 194, - /* 600 */ 94, 166, 167, 168, 25, 138, 67, 7, 8, 9, - /* 610 */ 108, 206, 207, 169, 170, 171, 150, 22, 221, 222, - /* 620 */ 223, 26, 49, 50, 86, 87, 23, 161, 162, 23, - /* 630 */ 22, 165, 24, 120, 22, 23, 25, 160, 241, 67, - /* 640 */ 176, 68, 69, 70, 71, 72, 73, 74, 75, 76, - /* 650 */ 77, 78, 79, 80, 160, 82, 83, 84, 85, 86, - /* 660 */ 87, 88, 89, 90, 91, 92, 19, 129, 130, 150, - /* 670 */ 23, 194, 35, 23, 230, 25, 150, 155, 150, 67, - /* 680 */ 150, 105, 106, 107, 165, 221, 222, 223, 194, 94, - /* 690 */ 23, 165, 25, 165, 217, 165, 49, 50, 25, 173, - /* 700 */ 174, 173, 174, 173, 174, 0, 1, 2, 118, 221, - /* 710 */ 222, 223, 193, 219, 237, 68, 69, 70, 71, 72, - /* 720 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82, - /* 730 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 740 */ 19, 150, 19, 165, 150, 24, 166, 167, 168, 227, - /* 750 */ 27, 173, 174, 231, 150, 25, 165, 150, 172, 165, - /* 760 */ 150, 242, 129, 130, 173, 174, 180, 173, 174, 165, - /* 770 */ 49, 50, 165, 150, 176, 165, 35, 173, 174, 165, - /* 780 */ 173, 174, 35, 23, 23, 25, 25, 173, 165, 68, - /* 790 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 800 */ 79, 80, 150, 82, 83, 84, 85, 86, 87, 88, - /* 810 */ 89, 90, 91, 92, 19, 150, 193, 165, 150, 221, - /* 820 */ 222, 223, 150, 213, 19, 173, 174, 23, 150, 97, - /* 830 */ 165, 150, 27, 165, 150, 150, 150, 165, 173, 174, - /* 840 */ 22, 173, 174, 165, 49, 50, 165, 52, 116, 165, - /* 850 */ 165, 165, 206, 207, 173, 174, 126, 50, 173, 174, - /* 860 */ 128, 27, 160, 68, 69, 70, 71, 72, 73, 74, - /* 870 */ 75, 76, 77, 78, 79, 80, 150, 82, 83, 84, - /* 880 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 150, - /* 890 */ 23, 165, 150, 23, 216, 25, 194, 32, 39, 173, - /* 900 */ 174, 135, 150, 137, 165, 150, 41, 165, 150, 52, - /* 910 */ 238, 104, 173, 174, 29, 173, 174, 165, 49, 50, - /* 920 */ 165, 219, 238, 165, 238, 173, 174, 52, 173, 174, - /* 930 */ 22, 173, 174, 23, 23, 160, 25, 68, 69, 70, - /* 940 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 950 */ 150, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 960 */ 91, 92, 19, 150, 150, 165, 150, 245, 246, 194, - /* 970 */ 150, 144, 145, 173, 174, 160, 150, 22, 165, 165, - /* 980 */ 22, 165, 150, 150, 116, 165, 173, 174, 52, 173, - /* 990 */ 174, 165, 49, 50, 22, 150, 128, 165, 165, 173, - /* 1000 */ 174, 187, 166, 166, 22, 173, 174, 187, 109, 194, - /* 1010 */ 165, 68, 69, 70, 71, 72, 73, 74, 75, 76, - /* 1020 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86, - /* 1030 */ 87, 88, 89, 90, 91, 92, 19, 150, 193, 165, - /* 1040 */ 102, 205, 205, 150, 150, 247, 248, 173, 174, 19, - /* 1050 */ 150, 20, 165, 150, 150, 150, 150, 150, 165, 165, - /* 1060 */ 173, 174, 49, 50, 104, 165, 49, 50, 165, 165, - /* 1070 */ 165, 165, 165, 173, 174, 43, 173, 174, 173, 174, - /* 1080 */ 187, 24, 190, 191, 71, 72, 69, 70, 71, 72, - /* 1090 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82, - /* 1100 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 1110 */ 19, 98, 150, 165, 150, 150, 150, 150, 150, 150, - /* 1120 */ 59, 173, 174, 25, 150, 190, 191, 165, 53, 165, - /* 1130 */ 165, 165, 165, 165, 165, 173, 174, 173, 174, 165, - /* 1140 */ 49, 50, 91, 92, 1, 2, 53, 173, 174, 138, - /* 1150 */ 104, 22, 5, 1, 35, 118, 127, 150, 193, 193, - /* 1160 */ 193, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 1170 */ 79, 80, 165, 82, 83, 84, 85, 86, 87, 88, - /* 1180 */ 89, 90, 91, 92, 19, 20, 150, 22, 150, 27, - /* 1190 */ 150, 26, 27, 108, 150, 22, 76, 76, 150, 25, - /* 1200 */ 193, 165, 37, 165, 150, 165, 22, 19, 20, 165, - /* 1210 */ 22, 173, 174, 165, 26, 27, 23, 150, 119, 165, - /* 1220 */ 150, 56, 150, 150, 150, 37, 16, 173, 174, 193, - /* 1230 */ 150, 66, 165, 193, 1, 165, 121, 165, 165, 165, - /* 1240 */ 20, 146, 147, 119, 56, 165, 150, 152, 16, 154, - /* 1250 */ 150, 86, 87, 88, 66, 160, 150, 150, 93, 94, - /* 1260 */ 95, 165, 150, 98, 108, 165, 127, 23, 65, 173, - /* 1270 */ 174, 165, 165, 150, 86, 87, 128, 165, 150, 173, - /* 1280 */ 174, 93, 94, 95, 23, 150, 98, 15, 165, 194, - /* 1290 */ 150, 140, 22, 165, 129, 130, 131, 132, 133, 134, - /* 1300 */ 165, 173, 174, 3, 116, 165, 19, 20, 150, 22, - /* 1310 */ 4, 150, 217, 26, 27, 179, 179, 129, 130, 131, - /* 1320 */ 132, 133, 134, 165, 37, 150, 165, 150, 164, 19, - /* 1330 */ 20, 150, 22, 246, 149, 249, 26, 27, 249, 244, - /* 1340 */ 165, 150, 165, 56, 6, 150, 165, 37, 173, 174, - /* 1350 */ 173, 174, 150, 66, 173, 174, 165, 149, 149, 13, - /* 1360 */ 165, 25, 150, 150, 150, 149, 56, 165, 150, 116, - /* 1370 */ 151, 150, 150, 86, 87, 150, 66, 165, 165, 165, - /* 1380 */ 93, 94, 95, 165, 150, 98, 165, 165, 151, 22, - /* 1390 */ 165, 194, 150, 26, 27, 150, 86, 87, 159, 165, - /* 1400 */ 199, 126, 123, 93, 94, 95, 200, 165, 98, 124, - /* 1410 */ 165, 122, 201, 125, 225, 135, 129, 130, 131, 132, - /* 1420 */ 133, 134, 5, 157, 157, 202, 118, 10, 11, 12, - /* 1430 */ 13, 14, 203, 66, 17, 104, 210, 121, 211, 129, - /* 1440 */ 130, 131, 132, 133, 134, 210, 175, 211, 31, 211, - /* 1450 */ 33, 210, 104, 86, 87, 47, 175, 183, 175, 42, - /* 1460 */ 103, 94, 178, 177, 22, 98, 175, 92, 228, 175, - /* 1470 */ 175, 228, 55, 183, 57, 178, 175, 156, 61, 18, - /* 1480 */ 157, 64, 156, 235, 157, 156, 45, 157, 236, 157, - /* 1490 */ 135, 156, 189, 68, 157, 218, 129, 130, 131, 22, - /* 1500 */ 189, 199, 157, 156, 192, 18, 192, 192, 199, 192, - /* 1510 */ 218, 189, 40, 157, 38, 157, 240, 157, 240, 153, - /* 1520 */ 196, 181, 105, 106, 107, 243, 198, 166, 111, 230, - /* 1530 */ 176, 226, 239, 116, 230, 176, 166, 166, 176, 148, - /* 1540 */ 199, 177, 209, 209, 166, 196, 239, 208, 185, 199, - /* 1550 */ 92, 209, 233, 173, 234, 182, 139, 173, 182, 191, - /* 1560 */ 195, 182, 250, 186, -}; -#define YY_SHIFT_USE_DFLT (-70) -#define YY_SHIFT_COUNT (416) -#define YY_SHIFT_MIN (-69) -#define YY_SHIFT_MAX (1487) -static const short yy_shift_ofst[] = { - /* 0 */ 1143, 1188, 1417, 1188, 1287, 1287, 138, 138, -2, -19, - /* 10 */ 1287, 1287, 1287, 1287, 347, 362, 129, 129, 795, 1165, - /* 20 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, - /* 30 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, - /* 40 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287, - /* 50 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, - /* 60 */ 1287, 1287, 286, 362, 362, 538, 538, 231, 1253, 55, - /* 70 */ 721, 647, 573, 499, 425, 351, 277, 203, 869, 869, - /* 80 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, - /* 90 */ 869, 869, 869, 943, 869, 1017, 1091, 1091, -69, -45, - /* 100 */ -45, -45, -45, -45, -1, 24, 245, 362, 362, 362, - /* 110 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, - /* 120 */ 362, 362, 362, 388, 356, 362, 362, 362, 362, 362, - /* 130 */ 732, 868, 231, 1051, 1458, -70, -70, -70, 1367, 57, - /* 140 */ 434, 434, 289, 291, 285, 1, 204, 572, 539, 362, - /* 150 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, - /* 160 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, - /* 170 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, - /* 180 */ 362, 506, 506, 506, 705, 1253, 1253, 1253, -70, -70, - /* 190 */ -70, 171, 171, 160, 502, 502, 502, 446, 432, 511, - /* 200 */ 422, 358, 335, -12, -12, -12, -12, 576, 294, -12, - /* 210 */ -12, 295, 595, 141, 600, 730, 723, 723, 805, 730, - /* 220 */ 805, 439, 911, 231, 865, 231, 865, 807, 865, 723, - /* 230 */ 766, 633, 633, 231, 284, 63, 608, 1476, 1308, 1308, - /* 240 */ 1472, 1472, 1308, 1477, 1425, 1275, 1487, 1487, 1487, 1487, - /* 250 */ 1308, 1461, 1275, 1477, 1425, 1425, 1308, 1461, 1355, 1441, - /* 260 */ 1308, 1308, 1461, 1308, 1461, 1308, 1461, 1442, 1348, 1348, - /* 270 */ 1348, 1408, 1375, 1375, 1442, 1348, 1357, 1348, 1408, 1348, - /* 280 */ 1348, 1316, 1331, 1316, 1331, 1316, 1331, 1308, 1308, 1280, - /* 290 */ 1288, 1289, 1285, 1279, 1275, 1253, 1336, 1346, 1346, 1338, - /* 300 */ 1338, 1338, 1338, -70, -70, -70, -70, -70, -70, 1013, - /* 310 */ 467, 612, 84, 179, -28, 870, 410, 761, 760, 667, - /* 320 */ 650, 531, 220, 361, 331, 125, 127, 97, 1306, 1300, - /* 330 */ 1270, 1151, 1272, 1203, 1232, 1261, 1244, 1148, 1174, 1139, - /* 340 */ 1156, 1124, 1220, 1115, 1210, 1233, 1099, 1193, 1184, 1174, - /* 350 */ 1173, 1029, 1121, 1120, 1085, 1162, 1119, 1037, 1152, 1147, - /* 360 */ 1129, 1046, 1011, 1093, 1098, 1075, 1061, 1032, 960, 1057, - /* 370 */ 1031, 1030, 899, 938, 982, 936, 972, 958, 910, 955, - /* 380 */ 875, 885, 908, 857, 859, 867, 804, 590, 834, 747, - /* 390 */ 818, 513, 611, 741, 673, 637, 611, 606, 603, 579, - /* 400 */ 501, 541, 468, 386, 445, 395, 376, 281, 185, 120, - /* 410 */ 92, 75, 45, 114, 25, 11, 5, -}; -#define YY_REDUCE_USE_DFLT (-169) -#define YY_REDUCE_COUNT (308) -#define YY_REDUCE_MIN (-168) -#define YY_REDUCE_MAX (1391) -static const short yy_reduce_ofst[] = { - /* 0 */ -141, 90, 1095, 222, 158, 156, 19, 17, 10, -104, - /* 10 */ 378, 316, 311, 12, 180, 249, 598, 464, 397, 1181, - /* 20 */ 1177, 1175, 1128, 1106, 1096, 1054, 1038, 974, 964, 962, - /* 30 */ 948, 905, 903, 900, 887, 874, 832, 826, 816, 813, - /* 40 */ 800, 758, 755, 752, 742, 739, 726, 685, 681, 668, - /* 50 */ 665, 652, 607, 604, 594, 591, 578, 530, 528, 526, - /* 60 */ 385, 18, 477, 466, 519, 444, 350, 435, 405, 488, - /* 70 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, - /* 80 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, - /* 90 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, - /* 100 */ 488, 488, 488, 488, 488, 488, 488, 1040, 678, 1036, - /* 110 */ 1007, 967, 966, 965, 845, 686, 610, 684, 317, 672, - /* 120 */ 893, 327, 623, 522, -7, 820, 814, 157, 154, 101, - /* 130 */ 702, 494, 580, 488, 488, 488, 488, 488, 614, 586, - /* 140 */ 935, 892, 968, 1245, 1242, 1234, 1225, 798, 798, 1222, - /* 150 */ 1221, 1218, 1214, 1213, 1212, 1202, 1195, 1191, 1161, 1158, - /* 160 */ 1140, 1135, 1123, 1112, 1107, 1100, 1080, 1074, 1073, 1072, - /* 170 */ 1070, 1067, 1048, 1044, 969, 968, 907, 906, 904, 894, - /* 180 */ 833, 837, 836, 340, 827, 815, 775, 68, 722, 646, - /* 190 */ -168, 1384, 1380, 1377, 1379, 1376, 1373, 1339, 1365, 1368, - /* 200 */ 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1320, 1319, 1365, - /* 210 */ 1365, 1339, 1378, 1349, 1391, 1350, 1342, 1334, 1307, 1341, - /* 220 */ 1293, 1364, 1363, 1371, 1362, 1370, 1359, 1340, 1354, 1333, - /* 230 */ 1305, 1304, 1299, 1361, 1328, 1324, 1366, 1282, 1360, 1358, - /* 240 */ 1278, 1276, 1356, 1292, 1322, 1309, 1317, 1315, 1314, 1312, - /* 250 */ 1345, 1347, 1302, 1277, 1311, 1303, 1337, 1335, 1252, 1248, - /* 260 */ 1332, 1330, 1329, 1327, 1326, 1323, 1321, 1297, 1301, 1295, - /* 270 */ 1294, 1290, 1243, 1240, 1284, 1291, 1286, 1283, 1274, 1281, - /* 280 */ 1271, 1238, 1241, 1236, 1235, 1227, 1226, 1267, 1266, 1189, - /* 290 */ 1229, 1223, 1211, 1206, 1201, 1197, 1239, 1237, 1219, 1216, - /* 300 */ 1209, 1208, 1185, 1089, 1086, 1087, 1137, 1136, 1164, -}; -static const YYACTIONTYPE yy_default[] = { - /* 0 */ 632, 866, 954, 954, 866, 866, 954, 954, 954, 756, - /* 10 */ 954, 954, 954, 864, 954, 954, 784, 784, 928, 954, - /* 20 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 30 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 40 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 50 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 60 */ 954, 954, 954, 954, 954, 954, 954, 671, 760, 790, - /* 70 */ 954, 954, 954, 954, 954, 954, 954, 954, 927, 929, - /* 80 */ 798, 797, 907, 771, 795, 788, 792, 867, 860, 861, - /* 90 */ 859, 863, 868, 954, 791, 827, 844, 826, 838, 843, - /* 100 */ 850, 842, 839, 829, 828, 830, 831, 954, 954, 954, - /* 110 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 120 */ 954, 954, 954, 658, 725, 954, 954, 954, 954, 954, - /* 130 */ 954, 954, 954, 832, 833, 847, 846, 845, 954, 663, - /* 140 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 150 */ 934, 932, 954, 879, 954, 954, 954, 954, 954, 954, - /* 160 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 170 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 180 */ 638, 756, 756, 756, 632, 954, 954, 954, 946, 760, - /* 190 */ 750, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 200 */ 954, 954, 954, 800, 739, 917, 919, 954, 900, 737, - /* 210 */ 660, 758, 673, 748, 640, 794, 773, 773, 912, 794, - /* 220 */ 912, 696, 719, 954, 784, 954, 784, 693, 784, 773, - /* 230 */ 862, 954, 954, 954, 757, 748, 954, 939, 764, 764, - /* 240 */ 931, 931, 764, 806, 729, 794, 736, 736, 736, 736, - /* 250 */ 764, 655, 794, 806, 729, 729, 764, 655, 906, 904, - /* 260 */ 764, 764, 655, 764, 655, 764, 655, 872, 727, 727, - /* 270 */ 727, 711, 876, 876, 872, 727, 696, 727, 711, 727, - /* 280 */ 727, 777, 772, 777, 772, 777, 772, 764, 764, 954, - /* 290 */ 789, 778, 787, 785, 794, 954, 714, 648, 648, 637, - /* 300 */ 637, 637, 637, 951, 951, 946, 698, 698, 681, 954, - /* 310 */ 954, 954, 954, 954, 954, 954, 881, 954, 954, 954, - /* 320 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 633, - /* 330 */ 941, 954, 954, 938, 954, 954, 954, 954, 799, 954, - /* 340 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 916, - /* 350 */ 954, 954, 954, 954, 954, 954, 954, 910, 954, 954, - /* 360 */ 954, 954, 954, 954, 903, 902, 954, 954, 954, 954, - /* 370 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 380 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, - /* 390 */ 954, 954, 786, 954, 779, 954, 865, 954, 954, 954, - /* 400 */ 954, 954, 954, 954, 954, 954, 954, 742, 815, 954, - /* 410 */ 814, 818, 813, 665, 954, 646, 954, 629, 634, 950, - /* 420 */ 953, 952, 949, 948, 947, 942, 940, 937, 936, 935, - /* 430 */ 933, 930, 926, 885, 883, 890, 889, 888, 887, 886, - /* 440 */ 884, 882, 880, 801, 796, 793, 925, 878, 738, 735, - /* 450 */ 734, 654, 943, 909, 918, 805, 804, 807, 915, 914, - /* 460 */ 913, 911, 908, 895, 803, 802, 730, 870, 869, 657, - /* 470 */ 899, 898, 897, 901, 905, 896, 766, 656, 653, 662, - /* 480 */ 717, 718, 726, 724, 723, 722, 721, 720, 716, 664, - /* 490 */ 672, 710, 695, 694, 875, 877, 874, 873, 703, 702, - /* 500 */ 708, 707, 706, 705, 704, 701, 700, 699, 692, 691, - /* 510 */ 697, 690, 713, 712, 709, 689, 733, 732, 731, 728, - /* 520 */ 688, 687, 686, 818, 685, 684, 824, 823, 811, 854, - /* 530 */ 753, 752, 751, 763, 762, 775, 774, 809, 808, 776, - /* 540 */ 761, 755, 754, 770, 769, 768, 767, 759, 749, 781, - /* 550 */ 783, 782, 780, 856, 765, 853, 924, 923, 922, 921, - /* 560 */ 920, 858, 857, 825, 822, 676, 677, 893, 892, 894, - /* 570 */ 891, 679, 678, 675, 674, 855, 744, 743, 851, 848, - /* 580 */ 840, 836, 852, 849, 841, 837, 835, 834, 820, 819, - /* 590 */ 817, 816, 812, 821, 667, 745, 741, 740, 810, 747, - /* 600 */ 746, 683, 682, 680, 661, 659, 652, 650, 649, 651, - /* 610 */ 647, 645, 644, 643, 642, 641, 670, 669, 668, 666, - /* 620 */ 665, 639, 636, 635, 631, 630, 628, -}; - -/* The next table maps tokens into fallback tokens. If a construct -** like the following: -** -** %fallback ID X Y Z. -** -** appears in the grammar, then ID becomes a fallback token for X, Y, -** and Z. Whenever one of the tokens X, Y, or Z is input to the parser -** but it does not parse, the type of the token is changed to ID and -** the parse is retried before an error is thrown. -*/ -#ifdef YYFALLBACK -static const YYCODETYPE yyFallback[] = { - 0, /* $ => nothing */ - 0, /* SEMI => nothing */ - 26, /* EXPLAIN => ID */ - 26, /* QUERY => ID */ - 26, /* PLAN => ID */ - 26, /* BEGIN => ID */ - 0, /* TRANSACTION => nothing */ - 26, /* DEFERRED => ID */ - 26, /* IMMEDIATE => ID */ - 26, /* EXCLUSIVE => ID */ - 0, /* COMMIT => nothing */ - 26, /* END => ID */ - 26, /* ROLLBACK => ID */ - 26, /* SAVEPOINT => ID */ - 26, /* RELEASE => ID */ - 0, /* TO => nothing */ - 0, /* TABLE => nothing */ - 0, /* CREATE => nothing */ - 26, /* IF => ID */ - 0, /* NOT => nothing */ - 0, /* EXISTS => nothing */ - 26, /* TEMP => ID */ - 0, /* LP => nothing */ - 0, /* RP => nothing */ - 0, /* AS => nothing */ - 0, /* COMMA => nothing */ - 0, /* ID => nothing */ - 0, /* INDEXED => nothing */ - 26, /* ABORT => ID */ - 26, /* ACTION => ID */ - 26, /* AFTER => ID */ - 26, /* ANALYZE => ID */ - 26, /* ASC => ID */ - 26, /* ATTACH => ID */ - 26, /* BEFORE => ID */ - 26, /* BY => ID */ - 26, /* CASCADE => ID */ - 26, /* CAST => ID */ - 26, /* COLUMNKW => ID */ - 26, /* CONFLICT => ID */ - 26, /* DATABASE => ID */ - 26, /* DESC => ID */ - 26, /* DETACH => ID */ - 26, /* EACH => ID */ - 26, /* FAIL => ID */ - 26, /* FOR => ID */ - 26, /* IGNORE => ID */ - 26, /* INITIALLY => ID */ - 26, /* INSTEAD => ID */ - 26, /* LIKE_KW => ID */ - 26, /* MATCH => ID */ - 26, /* NO => ID */ - 26, /* KEY => ID */ - 26, /* OF => ID */ - 26, /* OFFSET => ID */ - 26, /* PRAGMA => ID */ - 26, /* RAISE => ID */ - 26, /* REPLACE => ID */ - 26, /* RESTRICT => ID */ - 26, /* ROW => ID */ - 26, /* TRIGGER => ID */ - 26, /* VACUUM => ID */ - 26, /* VIEW => ID */ - 26, /* VIRTUAL => ID */ - 26, /* REINDEX => ID */ - 26, /* RENAME => ID */ - 26, /* CTIME_KW => ID */ -}; -#endif /* YYFALLBACK */ - -/* The following structure represents a single element of the -** parser's stack. Information stored includes: -** -** + The state number for the parser at this level of the stack. -** -** + The value of the token stored at this level of the stack. -** (In other words, the "major" token.) -** -** + The semantic value stored at this level of the stack. This is -** the information used by the action routines in the grammar. -** It is sometimes called the "minor" token. -*/ -struct yyStackEntry { - YYACTIONTYPE stateno; /* The state-number */ - YYCODETYPE major; /* The major token value. This is the code - ** number for the token at this stack level */ - YYMINORTYPE minor; /* The user-supplied minor token value. This - ** is the value of the token */ -}; -typedef struct yyStackEntry yyStackEntry; - -/* The state of the parser is completely contained in an instance of -** the following structure */ -struct yyParser { - int yyidx; /* Index of top element in stack */ -#ifdef YYTRACKMAXSTACKDEPTH - int yyidxMax; /* Maximum value of yyidx */ -#endif - int yyerrcnt; /* Shifts left before out of the error */ - sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ -#if YYSTACKDEPTH<=0 - int yystksz; /* Current side of the stack */ - yyStackEntry *yystack; /* The parser's stack */ -#else - yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ -#endif -}; -typedef struct yyParser yyParser; - -#ifndef NDEBUG -/* #include */ -static FILE *yyTraceFILE = 0; -static char *yyTracePrompt = 0; -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* -** Turn parser tracing on by giving a stream to which to write the trace -** and a prompt to preface each trace message. Tracing is turned off -** by making either argument NULL -** -** Inputs: -**
    -**
  • A FILE* to which trace output should be written. -** If NULL, then tracing is turned off. -**
  • A prefix string written at the beginning of every -** line of trace output. If NULL, then tracing is -** turned off. -**
-** -** Outputs: -** None. -*/ -SQLITE_PRIVATE void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){ - yyTraceFILE = TraceFILE; - yyTracePrompt = zTracePrompt; - if( yyTraceFILE==0 ) yyTracePrompt = 0; - else if( yyTracePrompt==0 ) yyTraceFILE = 0; -} -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* For tracing shifts, the names of all terminals and nonterminals -** are required. The following table supplies these names */ -static const char *const yyTokenName[] = { - "$", "SEMI", "EXPLAIN", "QUERY", - "PLAN", "BEGIN", "TRANSACTION", "DEFERRED", - "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END", - "ROLLBACK", "SAVEPOINT", "RELEASE", "TO", - "TABLE", "CREATE", "IF", "NOT", - "EXISTS", "TEMP", "LP", "RP", - "AS", "COMMA", "ID", "INDEXED", - "ABORT", "ACTION", "AFTER", "ANALYZE", - "ASC", "ATTACH", "BEFORE", "BY", - "CASCADE", "CAST", "COLUMNKW", "CONFLICT", - "DATABASE", "DESC", "DETACH", "EACH", - "FAIL", "FOR", "IGNORE", "INITIALLY", - "INSTEAD", "LIKE_KW", "MATCH", "NO", - "KEY", "OF", "OFFSET", "PRAGMA", - "RAISE", "REPLACE", "RESTRICT", "ROW", - "TRIGGER", "VACUUM", "VIEW", "VIRTUAL", - "REINDEX", "RENAME", "CTIME_KW", "ANY", - "OR", "AND", "IS", "BETWEEN", - "IN", "ISNULL", "NOTNULL", "NE", - "EQ", "GT", "LE", "LT", - "GE", "ESCAPE", "BITAND", "BITOR", - "LSHIFT", "RSHIFT", "PLUS", "MINUS", - "STAR", "SLASH", "REM", "CONCAT", - "COLLATE", "BITNOT", "STRING", "JOIN_KW", - "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY", - "UNIQUE", "CHECK", "REFERENCES", "AUTOINCR", - "ON", "INSERT", "DELETE", "UPDATE", - "SET", "DEFERRABLE", "FOREIGN", "DROP", - "UNION", "ALL", "EXCEPT", "INTERSECT", - "SELECT", "DISTINCT", "DOT", "FROM", - "JOIN", "USING", "ORDER", "GROUP", - "HAVING", "LIMIT", "WHERE", "INTO", - "VALUES", "INTEGER", "FLOAT", "BLOB", - "REGISTER", "VARIABLE", "CASE", "WHEN", - "THEN", "ELSE", "INDEX", "ALTER", - "ADD", "error", "input", "cmdlist", - "ecmd", "explain", "cmdx", "cmd", - "transtype", "trans_opt", "nm", "savepoint_opt", - "create_table", "create_table_args", "createkw", "temp", - "ifnotexists", "dbnm", "columnlist", "conslist_opt", - "select", "column", "columnid", "type", - "carglist", "id", "ids", "typetoken", - "typename", "signed", "plus_num", "minus_num", - "ccons", "term", "expr", "onconf", - "sortorder", "autoinc", "idxlist_opt", "refargs", - "defer_subclause", "refarg", "refact", "init_deferred_pred_opt", - "conslist", "tconscomma", "tcons", "idxlist", - "defer_subclause_opt", "orconf", "resolvetype", "raisetype", - "ifexists", "fullname", "oneselect", "multiselect_op", - "distinct", "selcollist", "from", "where_opt", - "groupby_opt", "having_opt", "orderby_opt", "limit_opt", - "sclp", "as", "seltablist", "stl_prefix", - "joinop", "indexed_opt", "on_opt", "using_opt", - "joinop2", "inscollist", "sortlist", "nexprlist", - "setlist", "insert_cmd", "inscollist_opt", "valuelist", - "exprlist", "likeop", "between_op", "in_op", - "case_operand", "case_exprlist", "case_else", "uniqueflag", - "collate", "nmnum", "number", "trigger_decl", - "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", - "when_clause", "trigger_cmd", "trnm", "tridxby", - "database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt", - "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken", - "lp", "anylist", -}; -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* For tracing reduce actions, the names of all rules are required. -*/ -static const char *const yyRuleName[] = { - /* 0 */ "input ::= cmdlist", - /* 1 */ "cmdlist ::= cmdlist ecmd", - /* 2 */ "cmdlist ::= ecmd", - /* 3 */ "ecmd ::= SEMI", - /* 4 */ "ecmd ::= explain cmdx SEMI", - /* 5 */ "explain ::=", - /* 6 */ "explain ::= EXPLAIN", - /* 7 */ "explain ::= EXPLAIN QUERY PLAN", - /* 8 */ "cmdx ::= cmd", - /* 9 */ "cmd ::= BEGIN transtype trans_opt", - /* 10 */ "trans_opt ::=", - /* 11 */ "trans_opt ::= TRANSACTION", - /* 12 */ "trans_opt ::= TRANSACTION nm", - /* 13 */ "transtype ::=", - /* 14 */ "transtype ::= DEFERRED", - /* 15 */ "transtype ::= IMMEDIATE", - /* 16 */ "transtype ::= EXCLUSIVE", - /* 17 */ "cmd ::= COMMIT trans_opt", - /* 18 */ "cmd ::= END trans_opt", - /* 19 */ "cmd ::= ROLLBACK trans_opt", - /* 20 */ "savepoint_opt ::= SAVEPOINT", - /* 21 */ "savepoint_opt ::=", - /* 22 */ "cmd ::= SAVEPOINT nm", - /* 23 */ "cmd ::= RELEASE savepoint_opt nm", - /* 24 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm", - /* 25 */ "cmd ::= create_table create_table_args", - /* 26 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm", - /* 27 */ "createkw ::= CREATE", - /* 28 */ "ifnotexists ::=", - /* 29 */ "ifnotexists ::= IF NOT EXISTS", - /* 30 */ "temp ::= TEMP", - /* 31 */ "temp ::=", - /* 32 */ "create_table_args ::= LP columnlist conslist_opt RP", - /* 33 */ "create_table_args ::= AS select", - /* 34 */ "columnlist ::= columnlist COMMA column", - /* 35 */ "columnlist ::= column", - /* 36 */ "column ::= columnid type carglist", - /* 37 */ "columnid ::= nm", - /* 38 */ "id ::= ID", - /* 39 */ "id ::= INDEXED", - /* 40 */ "ids ::= ID|STRING", - /* 41 */ "nm ::= id", - /* 42 */ "nm ::= STRING", - /* 43 */ "nm ::= JOIN_KW", - /* 44 */ "type ::=", - /* 45 */ "type ::= typetoken", - /* 46 */ "typetoken ::= typename", - /* 47 */ "typetoken ::= typename LP signed RP", - /* 48 */ "typetoken ::= typename LP signed COMMA signed RP", - /* 49 */ "typename ::= ids", - /* 50 */ "typename ::= typename ids", - /* 51 */ "signed ::= plus_num", - /* 52 */ "signed ::= minus_num", - /* 53 */ "carglist ::= carglist ccons", - /* 54 */ "carglist ::=", - /* 55 */ "ccons ::= CONSTRAINT nm", - /* 56 */ "ccons ::= DEFAULT term", - /* 57 */ "ccons ::= DEFAULT LP expr RP", - /* 58 */ "ccons ::= DEFAULT PLUS term", - /* 59 */ "ccons ::= DEFAULT MINUS term", - /* 60 */ "ccons ::= DEFAULT id", - /* 61 */ "ccons ::= NULL onconf", - /* 62 */ "ccons ::= NOT NULL onconf", - /* 63 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", - /* 64 */ "ccons ::= UNIQUE onconf", - /* 65 */ "ccons ::= CHECK LP expr RP", - /* 66 */ "ccons ::= REFERENCES nm idxlist_opt refargs", - /* 67 */ "ccons ::= defer_subclause", - /* 68 */ "ccons ::= COLLATE ids", - /* 69 */ "autoinc ::=", - /* 70 */ "autoinc ::= AUTOINCR", - /* 71 */ "refargs ::=", - /* 72 */ "refargs ::= refargs refarg", - /* 73 */ "refarg ::= MATCH nm", - /* 74 */ "refarg ::= ON INSERT refact", - /* 75 */ "refarg ::= ON DELETE refact", - /* 76 */ "refarg ::= ON UPDATE refact", - /* 77 */ "refact ::= SET NULL", - /* 78 */ "refact ::= SET DEFAULT", - /* 79 */ "refact ::= CASCADE", - /* 80 */ "refact ::= RESTRICT", - /* 81 */ "refact ::= NO ACTION", - /* 82 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 83 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 84 */ "init_deferred_pred_opt ::=", - /* 85 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 86 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 87 */ "conslist_opt ::=", - /* 88 */ "conslist_opt ::= COMMA conslist", - /* 89 */ "conslist ::= conslist tconscomma tcons", - /* 90 */ "conslist ::= tcons", - /* 91 */ "tconscomma ::= COMMA", - /* 92 */ "tconscomma ::=", - /* 93 */ "tcons ::= CONSTRAINT nm", - /* 94 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", - /* 95 */ "tcons ::= UNIQUE LP idxlist RP onconf", - /* 96 */ "tcons ::= CHECK LP expr RP onconf", - /* 97 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", - /* 98 */ "defer_subclause_opt ::=", - /* 99 */ "defer_subclause_opt ::= defer_subclause", - /* 100 */ "onconf ::=", - /* 101 */ "onconf ::= ON CONFLICT resolvetype", - /* 102 */ "orconf ::=", - /* 103 */ "orconf ::= OR resolvetype", - /* 104 */ "resolvetype ::= raisetype", - /* 105 */ "resolvetype ::= IGNORE", - /* 106 */ "resolvetype ::= REPLACE", - /* 107 */ "cmd ::= DROP TABLE ifexists fullname", - /* 108 */ "ifexists ::= IF EXISTS", - /* 109 */ "ifexists ::=", - /* 110 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select", - /* 111 */ "cmd ::= DROP VIEW ifexists fullname", - /* 112 */ "cmd ::= select", - /* 113 */ "select ::= oneselect", - /* 114 */ "select ::= select multiselect_op oneselect", - /* 115 */ "multiselect_op ::= UNION", - /* 116 */ "multiselect_op ::= UNION ALL", - /* 117 */ "multiselect_op ::= EXCEPT|INTERSECT", - /* 118 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 119 */ "distinct ::= DISTINCT", - /* 120 */ "distinct ::= ALL", - /* 121 */ "distinct ::=", - /* 122 */ "sclp ::= selcollist COMMA", - /* 123 */ "sclp ::=", - /* 124 */ "selcollist ::= sclp expr as", - /* 125 */ "selcollist ::= sclp STAR", - /* 126 */ "selcollist ::= sclp nm DOT STAR", - /* 127 */ "as ::= AS nm", - /* 128 */ "as ::= ids", - /* 129 */ "as ::=", - /* 130 */ "from ::=", - /* 131 */ "from ::= FROM seltablist", - /* 132 */ "stl_prefix ::= seltablist joinop", - /* 133 */ "stl_prefix ::=", - /* 134 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", - /* 135 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", - /* 136 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", - /* 137 */ "dbnm ::=", - /* 138 */ "dbnm ::= DOT nm", - /* 139 */ "fullname ::= nm dbnm", - /* 140 */ "joinop ::= COMMA|JOIN", - /* 141 */ "joinop ::= JOIN_KW JOIN", - /* 142 */ "joinop ::= JOIN_KW nm JOIN", - /* 143 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 144 */ "on_opt ::= ON expr", - /* 145 */ "on_opt ::=", - /* 146 */ "indexed_opt ::=", - /* 147 */ "indexed_opt ::= INDEXED BY nm", - /* 148 */ "indexed_opt ::= NOT INDEXED", - /* 149 */ "using_opt ::= USING LP inscollist RP", - /* 150 */ "using_opt ::=", - /* 151 */ "orderby_opt ::=", - /* 152 */ "orderby_opt ::= ORDER BY sortlist", - /* 153 */ "sortlist ::= sortlist COMMA expr sortorder", - /* 154 */ "sortlist ::= expr sortorder", - /* 155 */ "sortorder ::= ASC", - /* 156 */ "sortorder ::= DESC", - /* 157 */ "sortorder ::=", - /* 158 */ "groupby_opt ::=", - /* 159 */ "groupby_opt ::= GROUP BY nexprlist", - /* 160 */ "having_opt ::=", - /* 161 */ "having_opt ::= HAVING expr", - /* 162 */ "limit_opt ::=", - /* 163 */ "limit_opt ::= LIMIT expr", - /* 164 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 165 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 166 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt", - /* 167 */ "where_opt ::=", - /* 168 */ "where_opt ::= WHERE expr", - /* 169 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt", - /* 170 */ "setlist ::= setlist COMMA nm EQ expr", - /* 171 */ "setlist ::= nm EQ expr", - /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist", - /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", - /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES", - /* 175 */ "insert_cmd ::= INSERT orconf", - /* 176 */ "insert_cmd ::= REPLACE", - /* 177 */ "valuelist ::= VALUES LP nexprlist RP", - /* 178 */ "valuelist ::= valuelist COMMA LP exprlist RP", - /* 179 */ "inscollist_opt ::=", - /* 180 */ "inscollist_opt ::= LP inscollist RP", - /* 181 */ "inscollist ::= inscollist COMMA nm", - /* 182 */ "inscollist ::= nm", - /* 183 */ "expr ::= term", - /* 184 */ "expr ::= LP expr RP", - /* 185 */ "term ::= NULL", - /* 186 */ "expr ::= id", - /* 187 */ "expr ::= JOIN_KW", - /* 188 */ "expr ::= nm DOT nm", - /* 189 */ "expr ::= nm DOT nm DOT nm", - /* 190 */ "term ::= INTEGER|FLOAT|BLOB", - /* 191 */ "term ::= STRING", - /* 192 */ "expr ::= REGISTER", - /* 193 */ "expr ::= VARIABLE", - /* 194 */ "expr ::= expr COLLATE ids", - /* 195 */ "expr ::= CAST LP expr AS typetoken RP", - /* 196 */ "expr ::= ID LP distinct exprlist RP", - /* 197 */ "expr ::= ID LP STAR RP", - /* 198 */ "term ::= CTIME_KW", - /* 199 */ "expr ::= expr AND expr", - /* 200 */ "expr ::= expr OR expr", - /* 201 */ "expr ::= expr LT|GT|GE|LE expr", - /* 202 */ "expr ::= expr EQ|NE expr", - /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 204 */ "expr ::= expr PLUS|MINUS expr", - /* 205 */ "expr ::= expr STAR|SLASH|REM expr", - /* 206 */ "expr ::= expr CONCAT expr", - /* 207 */ "likeop ::= LIKE_KW", - /* 208 */ "likeop ::= NOT LIKE_KW", - /* 209 */ "likeop ::= MATCH", - /* 210 */ "likeop ::= NOT MATCH", - /* 211 */ "expr ::= expr likeop expr", - /* 212 */ "expr ::= expr likeop expr ESCAPE expr", - /* 213 */ "expr ::= expr ISNULL|NOTNULL", - /* 214 */ "expr ::= expr NOT NULL", - /* 215 */ "expr ::= expr IS expr", - /* 216 */ "expr ::= expr IS NOT expr", - /* 217 */ "expr ::= NOT expr", - /* 218 */ "expr ::= BITNOT expr", - /* 219 */ "expr ::= MINUS expr", - /* 220 */ "expr ::= PLUS expr", - /* 221 */ "between_op ::= BETWEEN", - /* 222 */ "between_op ::= NOT BETWEEN", - /* 223 */ "expr ::= expr between_op expr AND expr", - /* 224 */ "in_op ::= IN", - /* 225 */ "in_op ::= NOT IN", - /* 226 */ "expr ::= expr in_op LP exprlist RP", - /* 227 */ "expr ::= LP select RP", - /* 228 */ "expr ::= expr in_op LP select RP", - /* 229 */ "expr ::= expr in_op nm dbnm", - /* 230 */ "expr ::= EXISTS LP select RP", - /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 233 */ "case_exprlist ::= WHEN expr THEN expr", - /* 234 */ "case_else ::= ELSE expr", - /* 235 */ "case_else ::=", - /* 236 */ "case_operand ::= expr", - /* 237 */ "case_operand ::=", - /* 238 */ "exprlist ::= nexprlist", - /* 239 */ "exprlist ::=", - /* 240 */ "nexprlist ::= nexprlist COMMA expr", - /* 241 */ "nexprlist ::= expr", - /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP", - /* 243 */ "uniqueflag ::= UNIQUE", - /* 244 */ "uniqueflag ::=", - /* 245 */ "idxlist_opt ::=", - /* 246 */ "idxlist_opt ::= LP idxlist RP", - /* 247 */ "idxlist ::= idxlist COMMA nm collate sortorder", - /* 248 */ "idxlist ::= nm collate sortorder", - /* 249 */ "collate ::=", - /* 250 */ "collate ::= COLLATE ids", - /* 251 */ "cmd ::= DROP INDEX ifexists fullname", - /* 252 */ "cmd ::= VACUUM", - /* 253 */ "cmd ::= VACUUM nm", - /* 254 */ "cmd ::= PRAGMA nm dbnm", - /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 256 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 258 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 259 */ "nmnum ::= plus_num", - /* 260 */ "nmnum ::= nm", - /* 261 */ "nmnum ::= ON", - /* 262 */ "nmnum ::= DELETE", - /* 263 */ "nmnum ::= DEFAULT", - /* 264 */ "plus_num ::= PLUS number", - /* 265 */ "plus_num ::= number", - /* 266 */ "minus_num ::= MINUS number", - /* 267 */ "number ::= INTEGER|FLOAT", - /* 268 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 269 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 270 */ "trigger_time ::= BEFORE", - /* 271 */ "trigger_time ::= AFTER", - /* 272 */ "trigger_time ::= INSTEAD OF", - /* 273 */ "trigger_time ::=", - /* 274 */ "trigger_event ::= DELETE|INSERT", - /* 275 */ "trigger_event ::= UPDATE", - /* 276 */ "trigger_event ::= UPDATE OF inscollist", - /* 277 */ "foreach_clause ::=", - /* 278 */ "foreach_clause ::= FOR EACH ROW", - /* 279 */ "when_clause ::=", - /* 280 */ "when_clause ::= WHEN expr", - /* 281 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 283 */ "trnm ::= nm", - /* 284 */ "trnm ::= nm DOT nm", - /* 285 */ "tridxby ::=", - /* 286 */ "tridxby ::= INDEXED BY nm", - /* 287 */ "tridxby ::= NOT INDEXED", - /* 288 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 289 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist", - /* 290 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select", - /* 291 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 292 */ "trigger_cmd ::= select", - /* 293 */ "expr ::= RAISE LP IGNORE RP", - /* 294 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 295 */ "raisetype ::= ROLLBACK", - /* 296 */ "raisetype ::= ABORT", - /* 297 */ "raisetype ::= FAIL", - /* 298 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 299 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 300 */ "cmd ::= DETACH database_kw_opt expr", - /* 301 */ "key_opt ::=", - /* 302 */ "key_opt ::= KEY expr", - /* 303 */ "database_kw_opt ::= DATABASE", - /* 304 */ "database_kw_opt ::=", - /* 305 */ "cmd ::= REINDEX", - /* 306 */ "cmd ::= REINDEX nm dbnm", - /* 307 */ "cmd ::= ANALYZE", - /* 308 */ "cmd ::= ANALYZE nm dbnm", - /* 309 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 310 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 311 */ "add_column_fullname ::= fullname", - /* 312 */ "kwcolumn_opt ::=", - /* 313 */ "kwcolumn_opt ::= COLUMNKW", - /* 314 */ "cmd ::= create_vtab", - /* 315 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 316 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 317 */ "vtabarglist ::= vtabarg", - /* 318 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 319 */ "vtabarg ::=", - /* 320 */ "vtabarg ::= vtabarg vtabargtoken", - /* 321 */ "vtabargtoken ::= ANY", - /* 322 */ "vtabargtoken ::= lp anylist RP", - /* 323 */ "lp ::= LP", - /* 324 */ "anylist ::=", - /* 325 */ "anylist ::= anylist LP anylist RP", - /* 326 */ "anylist ::= anylist ANY", -}; -#endif /* NDEBUG */ - - -#if YYSTACKDEPTH<=0 -/* -** Try to increase the size of the parser stack. -*/ -static void yyGrowStack(yyParser *p){ - int newSize; - yyStackEntry *pNew; - - newSize = p->yystksz*2 + 100; - pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); - if( pNew ){ - p->yystack = pNew; - p->yystksz = newSize; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", - yyTracePrompt, p->yystksz); - } -#endif - } -} -#endif - -/* -** This function allocates a new parser. -** The only argument is a pointer to a function which works like -** malloc. -** -** Inputs: -** A pointer to the function used to allocate memory. -** -** Outputs: -** A pointer to a parser. This pointer is used in subsequent calls -** to sqlite3Parser and sqlite3ParserFree. -*/ -SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(size_t)){ - yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); - if( pParser ){ - pParser->yyidx = -1; -#ifdef YYTRACKMAXSTACKDEPTH - pParser->yyidxMax = 0; -#endif -#if YYSTACKDEPTH<=0 - pParser->yystack = NULL; - pParser->yystksz = 0; - yyGrowStack(pParser); -#endif - } - return pParser; -} - -/* The following function deletes the value associated with a -** symbol. The symbol can be either a terminal or nonterminal. -** "yymajor" is the symbol code, and "yypminor" is a pointer to -** the value. -*/ -static void yy_destructor( - yyParser *yypParser, /* The parser */ - YYCODETYPE yymajor, /* Type code for object to destroy */ - YYMINORTYPE *yypminor /* The object to be destroyed */ -){ - sqlite3ParserARG_FETCH; - switch( yymajor ){ - /* Here is inserted the actions which take place when a - ** terminal or non-terminal is destroyed. This can happen - ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is - ** being destroyed before it is finished parsing. - ** - ** Note: during a reduce, the only symbols destroyed are those - ** which appear on the RHS of the rule, but which are not used - ** inside the C code. - */ - case 160: /* select */ - case 194: /* oneselect */ -{ -sqlite3SelectDelete(pParse->db, (yypminor->yy159)); -} - break; - case 173: /* term */ - case 174: /* expr */ -{ -sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr); -} - break; - case 178: /* idxlist_opt */ - case 187: /* idxlist */ - case 197: /* selcollist */ - case 200: /* groupby_opt */ - case 202: /* orderby_opt */ - case 204: /* sclp */ - case 214: /* sortlist */ - case 215: /* nexprlist */ - case 216: /* setlist */ - case 220: /* exprlist */ - case 225: /* case_exprlist */ -{ -sqlite3ExprListDelete(pParse->db, (yypminor->yy442)); -} - break; - case 193: /* fullname */ - case 198: /* from */ - case 206: /* seltablist */ - case 207: /* stl_prefix */ -{ -sqlite3SrcListDelete(pParse->db, (yypminor->yy347)); -} - break; - case 199: /* where_opt */ - case 201: /* having_opt */ - case 210: /* on_opt */ - case 224: /* case_operand */ - case 226: /* case_else */ - case 236: /* when_clause */ - case 241: /* key_opt */ -{ -sqlite3ExprDelete(pParse->db, (yypminor->yy122)); -} - break; - case 211: /* using_opt */ - case 213: /* inscollist */ - case 218: /* inscollist_opt */ -{ -sqlite3IdListDelete(pParse->db, (yypminor->yy180)); -} - break; - case 219: /* valuelist */ -{ - - sqlite3ExprListDelete(pParse->db, (yypminor->yy487).pList); - sqlite3SelectDelete(pParse->db, (yypminor->yy487).pSelect); - -} - break; - case 232: /* trigger_cmd_list */ - case 237: /* trigger_cmd */ -{ -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy327)); -} - break; - case 234: /* trigger_event */ -{ -sqlite3IdListDelete(pParse->db, (yypminor->yy410).b); -} - break; - default: break; /* If no destructor action specified: do nothing */ - } -} - -/* -** Pop the parser's stack once. -** -** If there is a destructor routine associated with the token which -** is popped from the stack, then call it. -** -** Return the major token number for the symbol popped. -*/ -static int yy_pop_parser_stack(yyParser *pParser){ - YYCODETYPE yymajor; - yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; - - /* There is no mechanism by which the parser stack can be popped below - ** empty in SQLite. */ - if( NEVER(pParser->yyidx<0) ) return 0; -#ifndef NDEBUG - if( yyTraceFILE && pParser->yyidx>=0 ){ - fprintf(yyTraceFILE,"%sPopping %s\n", - yyTracePrompt, - yyTokenName[yytos->major]); - } -#endif - yymajor = yytos->major; - yy_destructor(pParser, yymajor, &yytos->minor); - pParser->yyidx--; - return yymajor; -} - -/* -** Deallocate and destroy a parser. Destructors are all called for -** all stack elements before shutting the parser down. -** -** Inputs: -**
    -**
  • A pointer to the parser. This should be a pointer -** obtained from sqlite3ParserAlloc. -**
  • A pointer to a function used to reclaim memory obtained -** from malloc. -**
-*/ -SQLITE_PRIVATE void sqlite3ParserFree( - void *p, /* The parser to be deleted */ - void (*freeProc)(void*) /* Function used to reclaim memory */ -){ - yyParser *pParser = (yyParser*)p; - /* In SQLite, we never try to destroy a parser that was not successfully - ** created in the first place. */ - if( NEVER(pParser==0) ) return; - while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); -#if YYSTACKDEPTH<=0 - free(pParser->yystack); -#endif - (*freeProc)((void*)pParser); -} - -/* -** Return the peak depth of the stack for a parser. -*/ -#ifdef YYTRACKMAXSTACKDEPTH -SQLITE_PRIVATE int sqlite3ParserStackPeak(void *p){ - yyParser *pParser = (yyParser*)p; - return pParser->yyidxMax; -} -#endif - -/* -** Find the appropriate action for a parser given the terminal -** look-ahead token iLookAhead. -** -** If the look-ahead token is YYNOCODE, then check to see if the action is -** independent of the look-ahead. If it is, return the action, otherwise -** return YY_NO_ACTION. -*/ -static int yy_find_shift_action( - yyParser *pParser, /* The parser */ - YYCODETYPE iLookAhead /* The look-ahead token */ -){ - int i; - int stateno = pParser->yystack[pParser->yyidx].stateno; - - if( stateno>YY_SHIFT_COUNT - || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ - return yy_default[stateno]; - } - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ -#ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - return yy_find_shift_action(pParser, iFallback); - } -#endif -#ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; - } - } -#endif /* YYWILDCARD */ - } - return yy_default[stateno]; - }else{ - return yy_action[i]; - } -} - -/* -** Find the appropriate action for a parser given the non-terminal -** look-ahead token iLookAhead. -** -** If the look-ahead token is YYNOCODE, then check to see if the action is -** independent of the look-ahead. If it is, return the action, otherwise -** return YY_NO_ACTION. -*/ -static int yy_find_reduce_action( - int stateno, /* Current state number */ - YYCODETYPE iLookAhead /* The look-ahead token */ -){ - int i; -#ifdef YYERRORSYMBOL - if( stateno>YY_REDUCE_COUNT ){ - return yy_default[stateno]; - } -#else - assert( stateno<=YY_REDUCE_COUNT ); -#endif - i = yy_reduce_ofst[stateno]; - assert( i!=YY_REDUCE_USE_DFLT ); - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; -#ifdef YYERRORSYMBOL - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - return yy_default[stateno]; - } -#else - assert( i>=0 && iyyidx--; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will execute if the parser - ** stack every overflows */ - - UNUSED_PARAMETER(yypMinor); /* Silence some compiler warnings */ - sqlite3ErrorMsg(pParse, "parser stack overflow"); - sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ -} - -/* -** Perform a shift action. -*/ -static void yy_shift( - yyParser *yypParser, /* The parser to be shifted */ - int yyNewState, /* The new state to shift in */ - int yyMajor, /* The major token to shift in */ - YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */ -){ - yyStackEntry *yytos; - yypParser->yyidx++; -#ifdef YYTRACKMAXSTACKDEPTH - if( yypParser->yyidx>yypParser->yyidxMax ){ - yypParser->yyidxMax = yypParser->yyidx; - } -#endif -#if YYSTACKDEPTH>0 - if( yypParser->yyidx>=YYSTACKDEPTH ){ - yyStackOverflow(yypParser, yypMinor); - return; - } -#else - if( yypParser->yyidx>=yypParser->yystksz ){ - yyGrowStack(yypParser); - if( yypParser->yyidx>=yypParser->yystksz ){ - yyStackOverflow(yypParser, yypMinor); - return; - } - } -#endif - yytos = &yypParser->yystack[yypParser->yyidx]; - yytos->stateno = (YYACTIONTYPE)yyNewState; - yytos->major = (YYCODETYPE)yyMajor; - yytos->minor = *yypMinor; -#ifndef NDEBUG - if( yyTraceFILE && yypParser->yyidx>0 ){ - int i; - fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); - fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); - for(i=1; i<=yypParser->yyidx; i++) - fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); - fprintf(yyTraceFILE,"\n"); - } -#endif -} - -/* The following table contains information about every rule that -** is used during the reduce. -*/ -static const struct { - YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ - unsigned char nrhs; /* Number of right-hand side symbols in the rule */ -} yyRuleInfo[] = { - { 142, 1 }, - { 143, 2 }, - { 143, 1 }, - { 144, 1 }, - { 144, 3 }, - { 145, 0 }, - { 145, 1 }, - { 145, 3 }, - { 146, 1 }, - { 147, 3 }, - { 149, 0 }, - { 149, 1 }, - { 149, 2 }, - { 148, 0 }, - { 148, 1 }, - { 148, 1 }, - { 148, 1 }, - { 147, 2 }, - { 147, 2 }, - { 147, 2 }, - { 151, 1 }, - { 151, 0 }, - { 147, 2 }, - { 147, 3 }, - { 147, 5 }, - { 147, 2 }, - { 152, 6 }, - { 154, 1 }, - { 156, 0 }, - { 156, 3 }, - { 155, 1 }, - { 155, 0 }, - { 153, 4 }, - { 153, 2 }, - { 158, 3 }, - { 158, 1 }, - { 161, 3 }, - { 162, 1 }, - { 165, 1 }, - { 165, 1 }, - { 166, 1 }, - { 150, 1 }, - { 150, 1 }, - { 150, 1 }, - { 163, 0 }, - { 163, 1 }, - { 167, 1 }, - { 167, 4 }, - { 167, 6 }, - { 168, 1 }, - { 168, 2 }, - { 169, 1 }, - { 169, 1 }, - { 164, 2 }, - { 164, 0 }, - { 172, 2 }, - { 172, 2 }, - { 172, 4 }, - { 172, 3 }, - { 172, 3 }, - { 172, 2 }, - { 172, 2 }, - { 172, 3 }, - { 172, 5 }, - { 172, 2 }, - { 172, 4 }, - { 172, 4 }, - { 172, 1 }, - { 172, 2 }, - { 177, 0 }, - { 177, 1 }, - { 179, 0 }, - { 179, 2 }, - { 181, 2 }, - { 181, 3 }, - { 181, 3 }, - { 181, 3 }, - { 182, 2 }, - { 182, 2 }, - { 182, 1 }, - { 182, 1 }, - { 182, 2 }, - { 180, 3 }, - { 180, 2 }, - { 183, 0 }, - { 183, 2 }, - { 183, 2 }, - { 159, 0 }, - { 159, 2 }, - { 184, 3 }, - { 184, 1 }, - { 185, 1 }, - { 185, 0 }, - { 186, 2 }, - { 186, 7 }, - { 186, 5 }, - { 186, 5 }, - { 186, 10 }, - { 188, 0 }, - { 188, 1 }, - { 175, 0 }, - { 175, 3 }, - { 189, 0 }, - { 189, 2 }, - { 190, 1 }, - { 190, 1 }, - { 190, 1 }, - { 147, 4 }, - { 192, 2 }, - { 192, 0 }, - { 147, 8 }, - { 147, 4 }, - { 147, 1 }, - { 160, 1 }, - { 160, 3 }, - { 195, 1 }, - { 195, 2 }, - { 195, 1 }, - { 194, 9 }, - { 196, 1 }, - { 196, 1 }, - { 196, 0 }, - { 204, 2 }, - { 204, 0 }, - { 197, 3 }, - { 197, 2 }, - { 197, 4 }, - { 205, 2 }, - { 205, 1 }, - { 205, 0 }, - { 198, 0 }, - { 198, 2 }, - { 207, 2 }, - { 207, 0 }, - { 206, 7 }, - { 206, 7 }, - { 206, 7 }, - { 157, 0 }, - { 157, 2 }, - { 193, 2 }, - { 208, 1 }, - { 208, 2 }, - { 208, 3 }, - { 208, 4 }, - { 210, 2 }, - { 210, 0 }, - { 209, 0 }, - { 209, 3 }, - { 209, 2 }, - { 211, 4 }, - { 211, 0 }, - { 202, 0 }, - { 202, 3 }, - { 214, 4 }, - { 214, 2 }, - { 176, 1 }, - { 176, 1 }, - { 176, 0 }, - { 200, 0 }, - { 200, 3 }, - { 201, 0 }, - { 201, 2 }, - { 203, 0 }, - { 203, 2 }, - { 203, 4 }, - { 203, 4 }, - { 147, 5 }, - { 199, 0 }, - { 199, 2 }, - { 147, 7 }, - { 216, 5 }, - { 216, 3 }, - { 147, 5 }, - { 147, 5 }, - { 147, 6 }, - { 217, 2 }, - { 217, 1 }, - { 219, 4 }, - { 219, 5 }, - { 218, 0 }, - { 218, 3 }, - { 213, 3 }, - { 213, 1 }, - { 174, 1 }, - { 174, 3 }, - { 173, 1 }, - { 174, 1 }, - { 174, 1 }, - { 174, 3 }, - { 174, 5 }, - { 173, 1 }, - { 173, 1 }, - { 174, 1 }, - { 174, 1 }, - { 174, 3 }, - { 174, 6 }, - { 174, 5 }, - { 174, 4 }, - { 173, 1 }, - { 174, 3 }, - { 174, 3 }, - { 174, 3 }, - { 174, 3 }, - { 174, 3 }, - { 174, 3 }, - { 174, 3 }, - { 174, 3 }, - { 221, 1 }, - { 221, 2 }, - { 221, 1 }, - { 221, 2 }, - { 174, 3 }, - { 174, 5 }, - { 174, 2 }, - { 174, 3 }, - { 174, 3 }, - { 174, 4 }, - { 174, 2 }, - { 174, 2 }, - { 174, 2 }, - { 174, 2 }, - { 222, 1 }, - { 222, 2 }, - { 174, 5 }, - { 223, 1 }, - { 223, 2 }, - { 174, 5 }, - { 174, 3 }, - { 174, 5 }, - { 174, 4 }, - { 174, 4 }, - { 174, 5 }, - { 225, 5 }, - { 225, 4 }, - { 226, 2 }, - { 226, 0 }, - { 224, 1 }, - { 224, 0 }, - { 220, 1 }, - { 220, 0 }, - { 215, 3 }, - { 215, 1 }, - { 147, 11 }, - { 227, 1 }, - { 227, 0 }, - { 178, 0 }, - { 178, 3 }, - { 187, 5 }, - { 187, 3 }, - { 228, 0 }, - { 228, 2 }, - { 147, 4 }, - { 147, 1 }, - { 147, 2 }, - { 147, 3 }, - { 147, 5 }, - { 147, 6 }, - { 147, 5 }, - { 147, 6 }, - { 229, 1 }, - { 229, 1 }, - { 229, 1 }, - { 229, 1 }, - { 229, 1 }, - { 170, 2 }, - { 170, 1 }, - { 171, 2 }, - { 230, 1 }, - { 147, 5 }, - { 231, 11 }, - { 233, 1 }, - { 233, 1 }, - { 233, 2 }, - { 233, 0 }, - { 234, 1 }, - { 234, 1 }, - { 234, 3 }, - { 235, 0 }, - { 235, 3 }, - { 236, 0 }, - { 236, 2 }, - { 232, 3 }, - { 232, 2 }, - { 238, 1 }, - { 238, 3 }, - { 239, 0 }, - { 239, 3 }, - { 239, 2 }, - { 237, 7 }, - { 237, 5 }, - { 237, 5 }, - { 237, 5 }, - { 237, 1 }, - { 174, 4 }, - { 174, 6 }, - { 191, 1 }, - { 191, 1 }, - { 191, 1 }, - { 147, 4 }, - { 147, 6 }, - { 147, 3 }, - { 241, 0 }, - { 241, 2 }, - { 240, 1 }, - { 240, 0 }, - { 147, 1 }, - { 147, 3 }, - { 147, 1 }, - { 147, 3 }, - { 147, 6 }, - { 147, 6 }, - { 242, 1 }, - { 243, 0 }, - { 243, 1 }, - { 147, 1 }, - { 147, 4 }, - { 244, 8 }, - { 245, 1 }, - { 245, 3 }, - { 246, 0 }, - { 246, 2 }, - { 247, 1 }, - { 247, 3 }, - { 248, 1 }, - { 249, 0 }, - { 249, 4 }, - { 249, 2 }, -}; - -static void yy_accept(yyParser*); /* Forward Declaration */ - -/* -** Perform a reduce action and the shift that must immediately -** follow the reduce. -*/ -static void yy_reduce( - yyParser *yypParser, /* The parser */ - int yyruleno /* Number of the rule by which to reduce */ -){ - int yygoto; /* The next state */ - int yyact; /* The next action */ - YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ - yyStackEntry *yymsp; /* The top of the parser's stack */ - int yysize; /* Amount to pop the stack */ - sqlite3ParserARG_FETCH; - yymsp = &yypParser->yystack[yypParser->yyidx]; -#ifndef NDEBUG - if( yyTraceFILE && yyruleno>=0 - && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ - fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, - yyRuleName[yyruleno]); - } -#endif /* NDEBUG */ - - /* Silence complaints from purify about yygotominor being uninitialized - ** in some cases when it is copied into the stack after the following - ** switch. yygotominor is uninitialized when a rule reduces that does - ** not set the value of its left-hand side nonterminal. Leaving the - ** value of the nonterminal uninitialized is utterly harmless as long - ** as the value is never used. So really the only thing this code - ** accomplishes is to quieten purify. - ** - ** 2007-01-16: The wireshark project (www.wireshark.org) reports that - ** without this code, their parser segfaults. I'm not sure what there - ** parser is doing to make this happen. This is the second bug report - ** from wireshark this week. Clearly they are stressing Lemon in ways - ** that it has not been previously stressed... (SQLite ticket #2172) - */ - /*memset(&yygotominor, 0, sizeof(yygotominor));*/ - yygotominor = yyzerominor; - - - switch( yyruleno ){ - /* Beginning here are the reduction cases. A typical example - ** follows: - ** case 0: - ** #line - ** { ... } // User supplied code - ** #line - ** break; - */ - case 5: /* explain ::= */ -{ sqlite3BeginParse(pParse, 0); } - break; - case 6: /* explain ::= EXPLAIN */ -{ sqlite3BeginParse(pParse, 1); } - break; - case 7: /* explain ::= EXPLAIN QUERY PLAN */ -{ sqlite3BeginParse(pParse, 2); } - break; - case 8: /* cmdx ::= cmd */ -{ sqlite3FinishCoding(pParse); } - break; - case 9: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy392);} - break; - case 13: /* transtype ::= */ -{yygotominor.yy392 = TK_DEFERRED;} - break; - case 14: /* transtype ::= DEFERRED */ - case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15); - case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16); - case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115); - case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117); -{yygotominor.yy392 = yymsp[0].major;} - break; - case 17: /* cmd ::= COMMIT trans_opt */ - case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18); -{sqlite3CommitTransaction(pParse);} - break; - case 19: /* cmd ::= ROLLBACK trans_opt */ -{sqlite3RollbackTransaction(pParse);} - break; - case 22: /* cmd ::= SAVEPOINT nm */ -{ - sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0); -} - break; - case 23: /* cmd ::= RELEASE savepoint_opt nm */ -{ - sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0); -} - break; - case 24: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ -{ - sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0); -} - break; - case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ -{ - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy392,0,0,yymsp[-2].minor.yy392); -} - break; - case 27: /* createkw ::= CREATE */ -{ - pParse->db->lookaside.bEnabled = 0; - yygotominor.yy0 = yymsp[0].minor.yy0; -} - break; - case 28: /* ifnotexists ::= */ - case 31: /* temp ::= */ yytestcase(yyruleno==31); - case 69: /* autoinc ::= */ yytestcase(yyruleno==69); - case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); - case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); - case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); - case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); - case 109: /* ifexists ::= */ yytestcase(yyruleno==109); - case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); - case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); -{yygotominor.yy392 = 0;} - break; - case 29: /* ifnotexists ::= IF NOT EXISTS */ - case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); - case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); - case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); - case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); - case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); - case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); -{yygotominor.yy392 = 1;} - break; - case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ -{ - sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0); -} - break; - case 33: /* create_table_args ::= AS select */ -{ - sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy159); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159); -} - break; - case 36: /* column ::= columnid type carglist */ -{ - yygotominor.yy0.z = yymsp[-2].minor.yy0.z; - yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n; -} - break; - case 37: /* columnid ::= nm */ -{ - sqlite3AddColumn(pParse,&yymsp[0].minor.yy0); - yygotominor.yy0 = yymsp[0].minor.yy0; - pParse->constraintName.n = 0; -} - break; - case 38: /* id ::= ID */ - case 39: /* id ::= INDEXED */ yytestcase(yyruleno==39); - case 40: /* ids ::= ID|STRING */ yytestcase(yyruleno==40); - case 41: /* nm ::= id */ yytestcase(yyruleno==41); - case 42: /* nm ::= STRING */ yytestcase(yyruleno==42); - case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43); - case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46); - case 49: /* typename ::= ids */ yytestcase(yyruleno==49); - case 127: /* as ::= AS nm */ yytestcase(yyruleno==127); - case 128: /* as ::= ids */ yytestcase(yyruleno==128); - case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138); - case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147); - case 250: /* collate ::= COLLATE ids */ yytestcase(yyruleno==250); - case 259: /* nmnum ::= plus_num */ yytestcase(yyruleno==259); - case 260: /* nmnum ::= nm */ yytestcase(yyruleno==260); - case 261: /* nmnum ::= ON */ yytestcase(yyruleno==261); - case 262: /* nmnum ::= DELETE */ yytestcase(yyruleno==262); - case 263: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==263); - case 264: /* plus_num ::= PLUS number */ yytestcase(yyruleno==264); - case 265: /* plus_num ::= number */ yytestcase(yyruleno==265); - case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266); - case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267); - case 283: /* trnm ::= nm */ yytestcase(yyruleno==283); -{yygotominor.yy0 = yymsp[0].minor.yy0;} - break; - case 45: /* type ::= typetoken */ -{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);} - break; - case 47: /* typetoken ::= typename LP signed RP */ -{ - yygotominor.yy0.z = yymsp[-3].minor.yy0.z; - yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z); -} - break; - case 48: /* typetoken ::= typename LP signed COMMA signed RP */ -{ - yygotominor.yy0.z = yymsp[-5].minor.yy0.z; - yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z); -} - break; - case 50: /* typename ::= typename ids */ -{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);} - break; - case 55: /* ccons ::= CONSTRAINT nm */ - case 93: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93); -{pParse->constraintName = yymsp[0].minor.yy0;} - break; - case 56: /* ccons ::= DEFAULT term */ - case 58: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==58); -{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);} - break; - case 57: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy342);} - break; - case 59: /* ccons ::= DEFAULT MINUS term */ -{ - ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy342.pExpr, 0, 0); - v.zStart = yymsp[-1].minor.yy0.z; - v.zEnd = yymsp[0].minor.yy342.zEnd; - sqlite3AddDefaultValue(pParse,&v); -} - break; - case 60: /* ccons ::= DEFAULT id */ -{ - ExprSpan v; - spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0); - sqlite3AddDefaultValue(pParse,&v); -} - break; - case 62: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy392);} - break; - case 63: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy392,yymsp[0].minor.yy392,yymsp[-2].minor.yy392);} - break; - case 64: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy392,0,0,0,0);} - break; - case 65: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy342.pExpr);} - break; - case 66: /* ccons ::= REFERENCES nm idxlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy442,yymsp[0].minor.yy392);} - break; - case 67: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy392);} - break; - case 68: /* ccons ::= COLLATE ids */ -{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} - break; - case 71: /* refargs ::= */ -{ yygotominor.yy392 = OE_None*0x0101; /* EV: R-19803-45884 */} - break; - case 72: /* refargs ::= refargs refarg */ -{ yygotominor.yy392 = (yymsp[-1].minor.yy392 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; } - break; - case 73: /* refarg ::= MATCH nm */ - case 74: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==74); -{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; } - break; - case 75: /* refarg ::= ON DELETE refact */ -{ yygotominor.yy207.value = yymsp[0].minor.yy392; yygotominor.yy207.mask = 0x0000ff; } - break; - case 76: /* refarg ::= ON UPDATE refact */ -{ yygotominor.yy207.value = yymsp[0].minor.yy392<<8; yygotominor.yy207.mask = 0x00ff00; } - break; - case 77: /* refact ::= SET NULL */ -{ yygotominor.yy392 = OE_SetNull; /* EV: R-33326-45252 */} - break; - case 78: /* refact ::= SET DEFAULT */ -{ yygotominor.yy392 = OE_SetDflt; /* EV: R-33326-45252 */} - break; - case 79: /* refact ::= CASCADE */ -{ yygotominor.yy392 = OE_Cascade; /* EV: R-33326-45252 */} - break; - case 80: /* refact ::= RESTRICT */ -{ yygotominor.yy392 = OE_Restrict; /* EV: R-33326-45252 */} - break; - case 81: /* refact ::= NO ACTION */ -{ yygotominor.yy392 = OE_None; /* EV: R-33326-45252 */} - break; - case 83: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99); - case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101); - case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104); -{yygotominor.yy392 = yymsp[0].minor.yy392;} - break; - case 87: /* conslist_opt ::= */ -{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;} - break; - case 88: /* conslist_opt ::= COMMA conslist */ -{yygotominor.yy0 = yymsp[-1].minor.yy0;} - break; - case 91: /* tconscomma ::= COMMA */ -{pParse->constraintName.n = 0;} - break; - case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);} - break; - case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);} - break; - case 96: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);} - break; - case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */ -{ - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392); -} - break; - case 100: /* onconf ::= */ -{yygotominor.yy392 = OE_Default;} - break; - case 102: /* orconf ::= */ -{yygotominor.yy258 = OE_Default;} - break; - case 103: /* orconf ::= OR resolvetype */ -{yygotominor.yy258 = (u8)yymsp[0].minor.yy392;} - break; - case 105: /* resolvetype ::= IGNORE */ -{yygotominor.yy392 = OE_Ignore;} - break; - case 106: /* resolvetype ::= REPLACE */ -{yygotominor.yy392 = OE_Replace;} - break; - case 107: /* cmd ::= DROP TABLE ifexists fullname */ -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392); -} - break; - case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */ -{ - sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392); -} - break; - case 111: /* cmd ::= DROP VIEW ifexists fullname */ -{ - sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392); -} - break; - case 112: /* cmd ::= select */ -{ - SelectDest dest = {SRT_Output, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy159, &dest); - sqlite3ExplainBegin(pParse->pVdbe); - sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159); - sqlite3ExplainFinish(pParse->pVdbe); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159); -} - break; - case 113: /* select ::= oneselect */ -{yygotominor.yy159 = yymsp[0].minor.yy159;} - break; - case 114: /* select ::= select multiselect_op oneselect */ -{ - if( yymsp[0].minor.yy159 ){ - yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392; - yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159; - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159); - } - yygotominor.yy159 = yymsp[0].minor.yy159; -} - break; - case 116: /* multiselect_op ::= UNION ALL */ -{yygotominor.yy392 = TK_ALL;} - break; - case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ -{ - yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); -} - break; - case 119: /* distinct ::= DISTINCT */ -{yygotominor.yy305 = SF_Distinct;} - break; - case 120: /* distinct ::= ALL */ - case 121: /* distinct ::= */ yytestcase(yyruleno==121); -{yygotominor.yy305 = 0;} - break; - case 122: /* sclp ::= selcollist COMMA */ - case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); -{yygotominor.yy442 = yymsp[-1].minor.yy442;} - break; - case 123: /* sclp ::= */ - case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151); - case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158); - case 239: /* exprlist ::= */ yytestcase(yyruleno==239); - case 245: /* idxlist_opt ::= */ yytestcase(yyruleno==245); -{yygotominor.yy442 = 0;} - break; - case 124: /* selcollist ::= sclp expr as */ -{ - yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342); -} - break; - case 125: /* selcollist ::= sclp STAR */ -{ - Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0); - yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p); -} - break; - case 126: /* selcollist ::= sclp nm DOT STAR */ -{ - Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0); - Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); - Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot); -} - break; - case 129: /* as ::= */ -{yygotominor.yy0.n = 0;} - break; - case 130: /* from ::= */ -{yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));} - break; - case 131: /* from ::= FROM seltablist */ -{ - yygotominor.yy347 = yymsp[0].minor.yy347; - sqlite3SrcListShiftJoinType(yygotominor.yy347); -} - break; - case 132: /* stl_prefix ::= seltablist joinop */ -{ - yygotominor.yy347 = yymsp[-1].minor.yy347; - if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392; -} - break; - case 133: /* stl_prefix ::= */ -{yygotominor.yy347 = 0;} - break; - case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ -{ - yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); - sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0); -} - break; - case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ -{ - yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); - } - break; - case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ -{ - if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ - yygotominor.yy347 = yymsp[-4].minor.yy347; - }else if( yymsp[-4].minor.yy347->nSrc==1 ){ - yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); - if( yygotominor.yy347 ){ - struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1]; - struct SrcList_item *pOld = yymsp[-4].minor.yy347->a; - pNew->zName = pOld->zName; - pNew->zDatabase = pOld->zDatabase; - pNew->pSelect = pOld->pSelect; - pOld->zName = pOld->zDatabase = 0; - pOld->pSelect = 0; - } - sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347); - }else{ - Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0); - yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); - } - } - break; - case 137: /* dbnm ::= */ - case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146); -{yygotominor.yy0.z=0; yygotominor.yy0.n=0;} - break; - case 139: /* fullname ::= nm dbnm */ -{yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} - break; - case 140: /* joinop ::= COMMA|JOIN */ -{ yygotominor.yy392 = JT_INNER; } - break; - case 141: /* joinop ::= JOIN_KW JOIN */ -{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } - break; - case 142: /* joinop ::= JOIN_KW nm JOIN */ -{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } - break; - case 143: /* joinop ::= JOIN_KW nm nm JOIN */ -{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } - break; - case 144: /* on_opt ::= ON expr */ - case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161); - case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168); - case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234); - case 236: /* case_operand ::= expr */ yytestcase(yyruleno==236); -{yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;} - break; - case 145: /* on_opt ::= */ - case 160: /* having_opt ::= */ yytestcase(yyruleno==160); - case 167: /* where_opt ::= */ yytestcase(yyruleno==167); - case 235: /* case_else ::= */ yytestcase(yyruleno==235); - case 237: /* case_operand ::= */ yytestcase(yyruleno==237); -{yygotominor.yy122 = 0;} - break; - case 148: /* indexed_opt ::= NOT INDEXED */ -{yygotominor.yy0.z=0; yygotominor.yy0.n=1;} - break; - case 149: /* using_opt ::= USING LP inscollist RP */ - case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180); -{yygotominor.yy180 = yymsp[-1].minor.yy180;} - break; - case 150: /* using_opt ::= */ - case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179); -{yygotominor.yy180 = 0;} - break; - case 152: /* orderby_opt ::= ORDER BY sortlist */ - case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159); - case 238: /* exprlist ::= nexprlist */ yytestcase(yyruleno==238); -{yygotominor.yy442 = yymsp[0].minor.yy442;} - break; - case 153: /* sortlist ::= sortlist COMMA expr sortorder */ -{ - yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr); - if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; -} - break; - case 154: /* sortlist ::= expr sortorder */ -{ - yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr); - if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392; -} - break; - case 155: /* sortorder ::= ASC */ - case 157: /* sortorder ::= */ yytestcase(yyruleno==157); -{yygotominor.yy392 = SQLITE_SO_ASC;} - break; - case 156: /* sortorder ::= DESC */ -{yygotominor.yy392 = SQLITE_SO_DESC;} - break; - case 162: /* limit_opt ::= */ -{yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;} - break; - case 163: /* limit_opt ::= LIMIT expr */ -{yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;} - break; - case 164: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;} - break; - case 165: /* limit_opt ::= LIMIT expr COMMA expr */ -{yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;} - break; - case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */ -{ - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122); -} - break; - case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */ -{ - sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list"); - sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258); -} - break; - case 170: /* setlist ::= setlist COMMA nm EQ expr */ -{ - yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr); - sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); -} - break; - case 171: /* setlist ::= nm EQ expr */ -{ - yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr); - sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); -} - break; - case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */ -{sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);} - break; - case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */ -{sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);} - break; - case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */ -{sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);} - break; - case 175: /* insert_cmd ::= INSERT orconf */ -{yygotominor.yy258 = yymsp[0].minor.yy258;} - break; - case 176: /* insert_cmd ::= REPLACE */ -{yygotominor.yy258 = OE_Replace;} - break; - case 177: /* valuelist ::= VALUES LP nexprlist RP */ -{ - yygotominor.yy487.pList = yymsp[-1].minor.yy442; - yygotominor.yy487.pSelect = 0; -} - break; - case 178: /* valuelist ::= valuelist COMMA LP exprlist RP */ -{ - Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0); - if( yymsp[-4].minor.yy487.pList ){ - yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0); - yymsp[-4].minor.yy487.pList = 0; - } - yygotominor.yy487.pList = 0; - if( yymsp[-4].minor.yy487.pSelect==0 || pRight==0 ){ - sqlite3SelectDelete(pParse->db, pRight); - sqlite3SelectDelete(pParse->db, yymsp[-4].minor.yy487.pSelect); - yygotominor.yy487.pSelect = 0; - }else{ - pRight->op = TK_ALL; - pRight->pPrior = yymsp[-4].minor.yy487.pSelect; - pRight->selFlags |= SF_Values; - pRight->pPrior->selFlags |= SF_Values; - yygotominor.yy487.pSelect = pRight; - } -} - break; - case 181: /* inscollist ::= inscollist COMMA nm */ -{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);} - break; - case 182: /* inscollist ::= nm */ -{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} - break; - case 183: /* expr ::= term */ -{yygotominor.yy342 = yymsp[0].minor.yy342;} - break; - case 184: /* expr ::= LP expr RP */ -{yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);} - break; - case 185: /* term ::= NULL */ - case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190); - case 191: /* term ::= STRING */ yytestcase(yyruleno==191); -{spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);} - break; - case 186: /* expr ::= id */ - case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187); -{spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);} - break; - case 188: /* expr ::= nm DOT nm */ -{ - Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); - Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); - spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); -} - break; - case 189: /* expr ::= nm DOT nm DOT nm */ -{ - Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); - Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); - Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); - Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); - spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); -} - break; - case 192: /* expr ::= REGISTER */ -{ - /* When doing a nested parse, one can include terms in an expression - ** that look like this: #1 #2 ... These terms refer to registers - ** in the virtual machine. #N is the N-th register. */ - if( pParse->nested==0 ){ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0); - yygotominor.yy342.pExpr = 0; - }else{ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0); - if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable); - } - spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); -} - break; - case 193: /* expr ::= VARIABLE */ -{ - spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr); - spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); -} - break; - case 194: /* expr ::= expr COLLATE ids */ -{ - yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); - yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; - yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; -} - break; - case 195: /* expr ::= CAST LP expr AS typetoken RP */ -{ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0); - spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); -} - break; - case 196: /* expr ::= ID LP distinct exprlist RP */ -{ - if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ - sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); - } - yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); - spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->flags |= EP_Distinct; - } -} - break; - case 197: /* expr ::= ID LP STAR RP */ -{ - yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); - spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); -} - break; - case 198: /* term ::= CTIME_KW */ -{ - /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are - ** treated as functions that return constants */ - yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0); - if( yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->op = TK_CONST_FUNC; - } - spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); -} - break; - case 199: /* expr ::= expr AND expr */ - case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200); - case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201); - case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202); - case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203); - case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204); - case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205); - case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206); -{spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);} - break; - case 207: /* likeop ::= LIKE_KW */ - case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209); -{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 0;} - break; - case 208: /* likeop ::= NOT LIKE_KW */ - case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210); -{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 1;} - break; - case 211: /* expr ::= expr likeop expr */ -{ - ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr); - yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator); - if( yymsp[-1].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); - yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; - yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; - if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc; -} - break; - case 212: /* expr ::= expr likeop expr ESCAPE expr */ -{ - ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr); - yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator); - if( yymsp[-3].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); - yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart; - yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; - if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc; -} - break; - case 213: /* expr ::= expr ISNULL|NOTNULL */ -{spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);} - break; - case 214: /* expr ::= expr NOT NULL */ -{spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);} - break; - case 215: /* expr ::= expr IS expr */ -{ - spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL); -} - break; - case 216: /* expr ::= expr IS NOT expr */ -{ - spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL); -} - break; - case 217: /* expr ::= NOT expr */ - case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218); -{spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);} - break; - case 219: /* expr ::= MINUS expr */ -{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);} - break; - case 220: /* expr ::= PLUS expr */ -{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);} - break; - case 223: /* expr ::= expr between_op expr AND expr */ -{ - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr); - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0); - if( yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->x.pList = pList; - }else{ - sqlite3ExprListDelete(pParse->db, pList); - } - if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); - yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart; - yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; -} - break; - case 226: /* expr ::= expr in_op LP exprlist RP */ -{ - if( yymsp[-1].minor.yy442==0 ){ - /* Expressions of the form - ** - ** expr1 IN () - ** expr1 NOT IN () - ** - ** simplify to constants 0 (false) and 1 (true), respectively, - ** regardless of the value of expr1. - */ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy392]); - sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy342.pExpr); - }else{ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0); - if( yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->x.pList = yymsp[-1].minor.yy442; - sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); - }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy442); - } - if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); - } - yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart; - yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; - } - break; - case 227: /* expr ::= LP select RP */ -{ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); - if( yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159; - ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); - } - yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z; - yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; - } - break; - case 228: /* expr ::= expr in_op LP select RP */ -{ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0); - if( yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159; - ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); - } - if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); - yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart; - yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; - } - break; - case 229: /* expr ::= expr in_op nm dbnm */ -{ - SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0); - if( yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); - }else{ - sqlite3SrcListDelete(pParse->db, pSrc); - } - if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); - yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart; - yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]; - } - break; - case 230: /* expr ::= EXISTS LP select RP */ -{ - Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); - if( p ){ - p->x.pSelect = yymsp[-1].minor.yy159; - ExprSetProperty(p, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, p); - }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); - } - yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z; - yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; - } - break; - case 231: /* expr ::= CASE case_operand case_exprlist case_else END */ -{ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0); - if( yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442; - sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); - }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy442); - } - yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z; - yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; -} - break; - case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ -{ - yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr); - yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr); -} - break; - case 233: /* case_exprlist ::= WHEN expr THEN expr */ -{ - yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); - yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr); -} - break; - case 240: /* nexprlist ::= nexprlist COMMA expr */ -{yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);} - break; - case 241: /* nexprlist ::= expr */ -{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);} - break; - case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */ -{ - sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, - sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392, - &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392); -} - break; - case 243: /* uniqueflag ::= UNIQUE */ - case 296: /* raisetype ::= ABORT */ yytestcase(yyruleno==296); -{yygotominor.yy392 = OE_Abort;} - break; - case 244: /* uniqueflag ::= */ -{yygotominor.yy392 = OE_None;} - break; - case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ -{ - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); - yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); - sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); - sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); - if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; -} - break; - case 248: /* idxlist ::= nm collate sortorder */ -{ - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); - yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); - sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); - sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); - if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; -} - break; - case 249: /* collate ::= */ -{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;} - break; - case 251: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);} - break; - case 252: /* cmd ::= VACUUM */ - case 253: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==253); -{sqlite3Vacuum(pParse);} - break; - case 254: /* cmd ::= PRAGMA nm dbnm */ -{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} - break; - case 255: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} - break; - case 256: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ -{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} - break; - case 257: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} - break; - case 258: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ -{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} - break; - case 268: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ -{ - Token all; - all.z = yymsp[-3].minor.yy0.z; - all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all); -} - break; - case 269: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ -{ - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392); - yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); -} - break; - case 270: /* trigger_time ::= BEFORE */ - case 273: /* trigger_time ::= */ yytestcase(yyruleno==273); -{ yygotominor.yy392 = TK_BEFORE; } - break; - case 271: /* trigger_time ::= AFTER */ -{ yygotominor.yy392 = TK_AFTER; } - break; - case 272: /* trigger_time ::= INSTEAD OF */ -{ yygotominor.yy392 = TK_INSTEAD;} - break; - case 274: /* trigger_event ::= DELETE|INSERT */ - case 275: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==275); -{yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;} - break; - case 276: /* trigger_event ::= UPDATE OF inscollist */ -{yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;} - break; - case 279: /* when_clause ::= */ - case 301: /* key_opt ::= */ yytestcase(yyruleno==301); -{ yygotominor.yy122 = 0; } - break; - case 280: /* when_clause ::= WHEN expr */ - case 302: /* key_opt ::= KEY expr */ yytestcase(yyruleno==302); -{ yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; } - break; - case 281: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ -{ - assert( yymsp[-2].minor.yy327!=0 ); - yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327; - yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327; - yygotominor.yy327 = yymsp[-2].minor.yy327; -} - break; - case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */ -{ - assert( yymsp[-1].minor.yy327!=0 ); - yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327; - yygotominor.yy327 = yymsp[-1].minor.yy327; -} - break; - case 284: /* trnm ::= nm DOT nm */ -{ - yygotominor.yy0 = yymsp[0].minor.yy0; - sqlite3ErrorMsg(pParse, - "qualified table names are not allowed on INSERT, UPDATE, and DELETE " - "statements within triggers"); -} - break; - case 286: /* tridxby ::= INDEXED BY nm */ -{ - sqlite3ErrorMsg(pParse, - "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " - "within triggers"); -} - break; - case 287: /* tridxby ::= NOT INDEXED */ -{ - sqlite3ErrorMsg(pParse, - "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " - "within triggers"); -} - break; - case 288: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ -{ yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); } - break; - case 289: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */ -{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);} - break; - case 290: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */ -{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);} - break; - case 291: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ -{yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);} - break; - case 292: /* trigger_cmd ::= select */ -{yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); } - break; - case 293: /* expr ::= RAISE LP IGNORE RP */ -{ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); - if( yygotominor.yy342.pExpr ){ - yygotominor.yy342.pExpr->affinity = OE_Ignore; - } - yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z; - yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; -} - break; - case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */ -{ - yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); - if( yygotominor.yy342.pExpr ) { - yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392; - } - yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z; - yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; -} - break; - case 295: /* raisetype ::= ROLLBACK */ -{yygotominor.yy392 = OE_Rollback;} - break; - case 297: /* raisetype ::= FAIL */ -{yygotominor.yy392 = OE_Fail;} - break; - case 298: /* cmd ::= DROP TRIGGER ifexists fullname */ -{ - sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392); -} - break; - case 299: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ -{ - sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122); -} - break; - case 300: /* cmd ::= DETACH database_kw_opt expr */ -{ - sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr); -} - break; - case 305: /* cmd ::= REINDEX */ -{sqlite3Reindex(pParse, 0, 0);} - break; - case 306: /* cmd ::= REINDEX nm dbnm */ -{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} - break; - case 307: /* cmd ::= ANALYZE */ -{sqlite3Analyze(pParse, 0, 0);} - break; - case 308: /* cmd ::= ANALYZE nm dbnm */ -{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} - break; - case 309: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ -{ - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0); -} - break; - case 310: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ -{ - sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); -} - break; - case 311: /* add_column_fullname ::= fullname */ -{ - pParse->db->lookaside.bEnabled = 0; - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347); -} - break; - case 314: /* cmd ::= create_vtab */ -{sqlite3VtabFinishParse(pParse,0);} - break; - case 315: /* cmd ::= create_vtab LP vtabarglist RP */ -{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} - break; - case 316: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ -{ - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392); -} - break; - case 319: /* vtabarg ::= */ -{sqlite3VtabArgInit(pParse);} - break; - case 321: /* vtabargtoken ::= ANY */ - case 322: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==322); - case 323: /* lp ::= LP */ yytestcase(yyruleno==323); -{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} - break; - default: - /* (0) input ::= cmdlist */ yytestcase(yyruleno==0); - /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1); - /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2); - /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3); - /* (4) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==4); - /* (10) trans_opt ::= */ yytestcase(yyruleno==10); - /* (11) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==11); - /* (12) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==12); - /* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20); - /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21); - /* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25); - /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34); - /* (35) columnlist ::= column */ yytestcase(yyruleno==35); - /* (44) type ::= */ yytestcase(yyruleno==44); - /* (51) signed ::= plus_num */ yytestcase(yyruleno==51); - /* (52) signed ::= minus_num */ yytestcase(yyruleno==52); - /* (53) carglist ::= carglist ccons */ yytestcase(yyruleno==53); - /* (54) carglist ::= */ yytestcase(yyruleno==54); - /* (61) ccons ::= NULL onconf */ yytestcase(yyruleno==61); - /* (89) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==89); - /* (90) conslist ::= tcons */ yytestcase(yyruleno==90); - /* (92) tconscomma ::= */ yytestcase(yyruleno==92); - /* (277) foreach_clause ::= */ yytestcase(yyruleno==277); - /* (278) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==278); - /* (285) tridxby ::= */ yytestcase(yyruleno==285); - /* (303) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==303); - /* (304) database_kw_opt ::= */ yytestcase(yyruleno==304); - /* (312) kwcolumn_opt ::= */ yytestcase(yyruleno==312); - /* (313) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==313); - /* (317) vtabarglist ::= vtabarg */ yytestcase(yyruleno==317); - /* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318); - /* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320); - /* (324) anylist ::= */ yytestcase(yyruleno==324); - /* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325); - /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326); - break; - }; - assert( yyruleno>=0 && yyrulenoyyidx -= yysize; - yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); - if( yyact < YYNSTATE ){ -#ifdef NDEBUG - /* If we are not debugging and the reduce action popped at least - ** one element off the stack, then we can push the new element back - ** onto the stack here, and skip the stack overflow test in yy_shift(). - ** That gives a significant speed improvement. */ - if( yysize ){ - yypParser->yyidx++; - yymsp -= yysize-1; - yymsp->stateno = (YYACTIONTYPE)yyact; - yymsp->major = (YYCODETYPE)yygoto; - yymsp->minor = yygotominor; - }else -#endif - { - yy_shift(yypParser,yyact,yygoto,&yygotominor); - } - }else{ - assert( yyact == YYNSTATE + YYNRULE + 1 ); - yy_accept(yypParser); - } -} - -/* -** The following code executes when the parse fails -*/ -#ifndef YYNOERRORRECOVERY -static void yy_parse_failed( - yyParser *yypParser /* The parser */ -){ - sqlite3ParserARG_FETCH; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will be executed whenever the - ** parser fails */ - sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} -#endif /* YYNOERRORRECOVERY */ - -/* -** The following code executes when a syntax error first occurs. -*/ -static void yy_syntax_error( - yyParser *yypParser, /* The parser */ - int yymajor, /* The major type of the error token */ - YYMINORTYPE yyminor /* The minor type of the error token */ -){ - sqlite3ParserARG_FETCH; -#define TOKEN (yyminor.yy0) - - UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ - assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ - sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); - sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} - -/* -** The following is executed when the parser accepts -*/ -static void yy_accept( - yyParser *yypParser /* The parser */ -){ - sqlite3ParserARG_FETCH; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will be executed whenever the - ** parser accepts */ - sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} - -/* The main parser program. -** The first argument is a pointer to a structure obtained from -** "sqlite3ParserAlloc" which describes the current state of the parser. -** The second argument is the major token number. The third is -** the minor token. The fourth optional argument is whatever the -** user wants (and specified in the grammar) and is available for -** use by the action routines. -** -** Inputs: -**
    -**
  • A pointer to the parser (an opaque structure.) -**
  • The major token number. -**
  • The minor token number. -**
  • An option argument of a grammar-specified type. -**
-** -** Outputs: -** None. -*/ -SQLITE_PRIVATE void sqlite3Parser( - void *yyp, /* The parser */ - int yymajor, /* The major token code number */ - sqlite3ParserTOKENTYPE yyminor /* The value for the token */ - sqlite3ParserARG_PDECL /* Optional %extra_argument parameter */ -){ - YYMINORTYPE yyminorunion; - int yyact; /* The parser action. */ -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) - int yyendofinput; /* True if we are at the end of input */ -#endif -#ifdef YYERRORSYMBOL - int yyerrorhit = 0; /* True if yymajor has invoked an error */ -#endif - yyParser *yypParser; /* The parser */ - - /* (re)initialize the parser, if necessary */ - yypParser = (yyParser*)yyp; - if( yypParser->yyidx<0 ){ -#if YYSTACKDEPTH<=0 - if( yypParser->yystksz <=0 ){ - /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/ - yyminorunion = yyzerominor; - yyStackOverflow(yypParser, &yyminorunion); - return; - } -#endif - yypParser->yyidx = 0; - yypParser->yyerrcnt = -1; - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; - } - yyminorunion.yy0 = yyminor; -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) - yyendofinput = (yymajor==0); -#endif - sqlite3ParserARG_STORE; - -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); - } -#endif - - do{ - yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); - if( yyactyyerrcnt--; - yymajor = YYNOCODE; - }else if( yyact < YYNSTATE + YYNRULE ){ - yy_reduce(yypParser,yyact-YYNSTATE); - }else{ - assert( yyact == YY_ERROR_ACTION ); -#ifdef YYERRORSYMBOL - int yymx; -#endif -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); - } -#endif -#ifdef YYERRORSYMBOL - /* A syntax error has occurred. - ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". - ** - ** This is what we do if the grammar does define ERROR: - ** - ** * Call the %syntax_error function. - ** - ** * Begin popping the stack until we enter a state where - ** it is legal to shift the error symbol, then shift - ** the error symbol. - ** - ** * Set the error count to three. - ** - ** * Begin accepting and shifting new tokens. No new error - ** processing will occur until three tokens have been - ** shifted successfully. - ** - */ - if( yypParser->yyerrcnt<0 ){ - yy_syntax_error(yypParser,yymajor,yyminorunion); - } - yymx = yypParser->yystack[yypParser->yyidx].major; - if( yymx==YYERRORSYMBOL || yyerrorhit ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sDiscard input token %s\n", - yyTracePrompt,yyTokenName[yymajor]); - } -#endif - yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion); - yymajor = YYNOCODE; - }else{ - while( - yypParser->yyidx >= 0 && - yymx != YYERRORSYMBOL && - (yyact = yy_find_reduce_action( - yypParser->yystack[yypParser->yyidx].stateno, - YYERRORSYMBOL)) >= YYNSTATE - ){ - yy_pop_parser_stack(yypParser); - } - if( yypParser->yyidx < 0 || yymajor==0 ){ - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yy_parse_failed(yypParser); - yymajor = YYNOCODE; - }else if( yymx!=YYERRORSYMBOL ){ - YYMINORTYPE u2; - u2.YYERRSYMDT = 0; - yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); - } - } - yypParser->yyerrcnt = 3; - yyerrorhit = 1; -#elif defined(YYNOERRORRECOVERY) - /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to - ** do any kind of error recovery. Instead, simply invoke the syntax - ** error routine and continue going as if nothing had happened. - ** - ** Applications can set this macro (for example inside %include) if - ** they intend to abandon the parse upon the first syntax error seen. - */ - yy_syntax_error(yypParser,yymajor,yyminorunion); - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yymajor = YYNOCODE; - -#else /* YYERRORSYMBOL is not defined */ - /* This is what we do if the grammar does not define ERROR: - ** - ** * Report an error message, and throw away the input token. - ** - ** * If the input token is $, then fail the parse. - ** - ** As before, subsequent error messages are suppressed until - ** three input tokens have been successfully shifted. - */ - if( yypParser->yyerrcnt<=0 ){ - yy_syntax_error(yypParser,yymajor,yyminorunion); - } - yypParser->yyerrcnt = 3; - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - if( yyendofinput ){ - yy_parse_failed(yypParser); - } - yymajor = YYNOCODE; -#endif - } - }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); - return; -} - -/************** End of parse.c ***********************************************/ -/************** Begin file tokenize.c ****************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** An tokenizer for SQL -** -** This file contains C code that splits an SQL input string up into -** individual tokens and sends those tokens one-by-one over to the -** parser for analysis. -*/ -/* #include */ - -/* -** The charMap() macro maps alphabetic characters into their -** lower-case ASCII equivalent. On ASCII machines, this is just -** an upper-to-lower case map. On EBCDIC machines we also need -** to adjust the encoding. Only alphabetic characters and underscores -** need to be translated. -*/ -#ifdef SQLITE_ASCII -# define charMap(X) sqlite3UpperToLower[(unsigned char)X] -#endif -#ifdef SQLITE_EBCDIC -# define charMap(X) ebcdicToAscii[(unsigned char)X] -const unsigned char ebcdicToAscii[] = { -/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */ - 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */ - 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */ - 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */ - 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */ -}; -#endif - -/* -** The sqlite3KeywordCode function looks up an identifier to determine if -** it is a keyword. If it is a keyword, the token code of that keyword is -** returned. If the input is not a keyword, TK_ID is returned. -** -** The implementation of this routine was generated by a program, -** mkkeywordhash.h, located in the tool subdirectory of the distribution. -** The output of the mkkeywordhash.c program is written into a file -** named keywordhash.h and then included into this source file by -** the #include below. -*/ -/************** Include keywordhash.h in the middle of tokenize.c ************/ -/************** Begin file keywordhash.h *************************************/ -/***** This file contains automatically generated code ****** -** -** The code in this file has been automatically generated by -** -** sqlite/tool/mkkeywordhash.c -** -** The code in this file implements a function that determines whether -** or not a given identifier is really an SQL keyword. The same thing -** might be implemented more directly using a hand-written hash table. -** But by using this automatically generated code, the size of the code -** is substantially reduced. This is important for embedded applications -** on platforms with limited memory. -*/ -/* Hash score: 175 */ -static int keywordCode(const char *z, int n){ - /* zText[] encodes 811 bytes of keywords in 541 bytes */ - /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ - /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ - /* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */ - /* UNIQUERYATTACHAVINGROUPDATEBEGINNERELEASEBETWEENOTNULLIKE */ - /* CASCADELETECASECOLLATECREATECURRENT_DATEDETACHIMMEDIATEJOIN */ - /* SERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHENWHERENAME */ - /* AFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */ - /* CURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOBYIF */ - /* ISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUMVIEW */ - /* INITIALLY */ - static const char zText[540] = { - 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H', - 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G', - 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A', - 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F', - 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N', - 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I', - 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E', - 'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E', - 'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T', - 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q', - 'U','E','R','Y','A','T','T','A','C','H','A','V','I','N','G','R','O','U', - 'P','D','A','T','E','B','E','G','I','N','N','E','R','E','L','E','A','S', - 'E','B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C', - 'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L', - 'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D', - 'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E', - 'J','O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A', - 'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U', - 'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W', - 'H','E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C', - 'E','A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R', - 'E','M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M', - 'M','I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U', - 'R','R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M', - 'A','R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T', - 'D','R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L', - 'O','B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S', - 'T','R','I','C','T','O','U','T','E','R','I','G','H','T','R','O','L','L', - 'B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N','G','V', - 'A','C','U','U','M','V','I','E','W','I','N','I','T','I','A','L','L','Y', - }; - static const unsigned char aHash[127] = { - 72, 101, 114, 70, 0, 45, 0, 0, 78, 0, 73, 0, 0, - 42, 12, 74, 15, 0, 113, 81, 50, 108, 0, 19, 0, 0, - 118, 0, 116, 111, 0, 22, 89, 0, 9, 0, 0, 66, 67, - 0, 65, 6, 0, 48, 86, 98, 0, 115, 97, 0, 0, 44, - 0, 99, 24, 0, 17, 0, 119, 49, 23, 0, 5, 106, 25, - 92, 0, 0, 121, 102, 56, 120, 53, 28, 51, 0, 87, 0, - 96, 26, 0, 95, 0, 0, 0, 91, 88, 93, 84, 105, 14, - 39, 104, 0, 77, 0, 18, 85, 107, 32, 0, 117, 76, 109, - 58, 46, 80, 0, 0, 90, 40, 0, 112, 0, 36, 0, 0, - 29, 0, 82, 59, 60, 0, 20, 57, 0, 52, - }; - static const unsigned char aNext[121] = { - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, - 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 43, 3, 47, - 0, 0, 0, 0, 30, 0, 54, 0, 38, 0, 0, 0, 1, - 62, 0, 0, 63, 0, 41, 0, 0, 0, 0, 0, 0, 0, - 61, 0, 0, 0, 0, 31, 55, 16, 34, 10, 0, 0, 0, - 0, 0, 0, 0, 11, 68, 75, 0, 8, 0, 100, 94, 0, - 103, 0, 83, 0, 71, 0, 0, 110, 27, 37, 69, 79, 0, - 35, 64, 0, 0, - }; - static const unsigned char aLen[121] = { - 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6, - 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6, - 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, - 4, 6, 2, 3, 9, 4, 2, 6, 5, 6, 6, 5, 6, - 5, 5, 7, 7, 7, 3, 2, 4, 4, 7, 3, 6, 4, - 7, 6, 12, 6, 9, 4, 6, 5, 4, 7, 6, 5, 6, - 7, 5, 4, 5, 6, 5, 7, 3, 7, 13, 2, 2, 4, - 6, 6, 8, 5, 17, 12, 7, 8, 8, 2, 4, 4, 4, - 4, 4, 2, 2, 6, 5, 8, 5, 5, 8, 3, 5, 5, - 6, 4, 9, 3, - }; - static const unsigned short int aOffset[121] = { - 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33, - 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81, - 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, - 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 189, 194, 197, - 203, 206, 210, 217, 223, 223, 223, 226, 229, 233, 234, 238, 244, - 248, 255, 261, 273, 279, 288, 290, 296, 301, 303, 310, 315, 320, - 326, 332, 337, 341, 344, 350, 354, 361, 363, 370, 372, 374, 383, - 387, 393, 399, 407, 412, 412, 428, 435, 442, 443, 450, 454, 458, - 462, 466, 469, 471, 473, 479, 483, 491, 495, 500, 508, 511, 516, - 521, 527, 531, 536, - }; - static const unsigned char aCode[121] = { - TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, - TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, - TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, - TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE, - TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE, - TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW, - TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT, - TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO, - TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP, - TK_OR, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING, - TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE, - TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, - TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, - TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, - TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, - TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, - TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, - TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, - TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, - TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, - TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, - TK_LIKE_KW, TK_BY, TK_IF, TK_ISNULL, TK_ORDER, - TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW, - TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY, - TK_ALL, - }; - int h, i; - if( n<2 ) return TK_ID; - h = ((charMap(z[0])*4) ^ - (charMap(z[n-1])*3) ^ - n) % 127; - for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){ - if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){ - testcase( i==0 ); /* REINDEX */ - testcase( i==1 ); /* INDEXED */ - testcase( i==2 ); /* INDEX */ - testcase( i==3 ); /* DESC */ - testcase( i==4 ); /* ESCAPE */ - testcase( i==5 ); /* EACH */ - testcase( i==6 ); /* CHECK */ - testcase( i==7 ); /* KEY */ - testcase( i==8 ); /* BEFORE */ - testcase( i==9 ); /* FOREIGN */ - testcase( i==10 ); /* FOR */ - testcase( i==11 ); /* IGNORE */ - testcase( i==12 ); /* REGEXP */ - testcase( i==13 ); /* EXPLAIN */ - testcase( i==14 ); /* INSTEAD */ - testcase( i==15 ); /* ADD */ - testcase( i==16 ); /* DATABASE */ - testcase( i==17 ); /* AS */ - testcase( i==18 ); /* SELECT */ - testcase( i==19 ); /* TABLE */ - testcase( i==20 ); /* LEFT */ - testcase( i==21 ); /* THEN */ - testcase( i==22 ); /* END */ - testcase( i==23 ); /* DEFERRABLE */ - testcase( i==24 ); /* ELSE */ - testcase( i==25 ); /* EXCEPT */ - testcase( i==26 ); /* TRANSACTION */ - testcase( i==27 ); /* ACTION */ - testcase( i==28 ); /* ON */ - testcase( i==29 ); /* NATURAL */ - testcase( i==30 ); /* ALTER */ - testcase( i==31 ); /* RAISE */ - testcase( i==32 ); /* EXCLUSIVE */ - testcase( i==33 ); /* EXISTS */ - testcase( i==34 ); /* SAVEPOINT */ - testcase( i==35 ); /* INTERSECT */ - testcase( i==36 ); /* TRIGGER */ - testcase( i==37 ); /* REFERENCES */ - testcase( i==38 ); /* CONSTRAINT */ - testcase( i==39 ); /* INTO */ - testcase( i==40 ); /* OFFSET */ - testcase( i==41 ); /* OF */ - testcase( i==42 ); /* SET */ - testcase( i==43 ); /* TEMPORARY */ - testcase( i==44 ); /* TEMP */ - testcase( i==45 ); /* OR */ - testcase( i==46 ); /* UNIQUE */ - testcase( i==47 ); /* QUERY */ - testcase( i==48 ); /* ATTACH */ - testcase( i==49 ); /* HAVING */ - testcase( i==50 ); /* GROUP */ - testcase( i==51 ); /* UPDATE */ - testcase( i==52 ); /* BEGIN */ - testcase( i==53 ); /* INNER */ - testcase( i==54 ); /* RELEASE */ - testcase( i==55 ); /* BETWEEN */ - testcase( i==56 ); /* NOTNULL */ - testcase( i==57 ); /* NOT */ - testcase( i==58 ); /* NO */ - testcase( i==59 ); /* NULL */ - testcase( i==60 ); /* LIKE */ - testcase( i==61 ); /* CASCADE */ - testcase( i==62 ); /* ASC */ - testcase( i==63 ); /* DELETE */ - testcase( i==64 ); /* CASE */ - testcase( i==65 ); /* COLLATE */ - testcase( i==66 ); /* CREATE */ - testcase( i==67 ); /* CURRENT_DATE */ - testcase( i==68 ); /* DETACH */ - testcase( i==69 ); /* IMMEDIATE */ - testcase( i==70 ); /* JOIN */ - testcase( i==71 ); /* INSERT */ - testcase( i==72 ); /* MATCH */ - testcase( i==73 ); /* PLAN */ - testcase( i==74 ); /* ANALYZE */ - testcase( i==75 ); /* PRAGMA */ - testcase( i==76 ); /* ABORT */ - testcase( i==77 ); /* VALUES */ - testcase( i==78 ); /* VIRTUAL */ - testcase( i==79 ); /* LIMIT */ - testcase( i==80 ); /* WHEN */ - testcase( i==81 ); /* WHERE */ - testcase( i==82 ); /* RENAME */ - testcase( i==83 ); /* AFTER */ - testcase( i==84 ); /* REPLACE */ - testcase( i==85 ); /* AND */ - testcase( i==86 ); /* DEFAULT */ - testcase( i==87 ); /* AUTOINCREMENT */ - testcase( i==88 ); /* TO */ - testcase( i==89 ); /* IN */ - testcase( i==90 ); /* CAST */ - testcase( i==91 ); /* COLUMN */ - testcase( i==92 ); /* COMMIT */ - testcase( i==93 ); /* CONFLICT */ - testcase( i==94 ); /* CROSS */ - testcase( i==95 ); /* CURRENT_TIMESTAMP */ - testcase( i==96 ); /* CURRENT_TIME */ - testcase( i==97 ); /* PRIMARY */ - testcase( i==98 ); /* DEFERRED */ - testcase( i==99 ); /* DISTINCT */ - testcase( i==100 ); /* IS */ - testcase( i==101 ); /* DROP */ - testcase( i==102 ); /* FAIL */ - testcase( i==103 ); /* FROM */ - testcase( i==104 ); /* FULL */ - testcase( i==105 ); /* GLOB */ - testcase( i==106 ); /* BY */ - testcase( i==107 ); /* IF */ - testcase( i==108 ); /* ISNULL */ - testcase( i==109 ); /* ORDER */ - testcase( i==110 ); /* RESTRICT */ - testcase( i==111 ); /* OUTER */ - testcase( i==112 ); /* RIGHT */ - testcase( i==113 ); /* ROLLBACK */ - testcase( i==114 ); /* ROW */ - testcase( i==115 ); /* UNION */ - testcase( i==116 ); /* USING */ - testcase( i==117 ); /* VACUUM */ - testcase( i==118 ); /* VIEW */ - testcase( i==119 ); /* INITIALLY */ - testcase( i==120 ); /* ALL */ - return aCode[i]; - } - } - return TK_ID; -} -SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ - return keywordCode((char*)z, n); -} -#define SQLITE_N_KEYWORD 121 - -/************** End of keywordhash.h *****************************************/ -/************** Continuing where we left off in tokenize.c *******************/ - - -/* -** If X is a character that can be used in an identifier then -** IdChar(X) will be true. Otherwise it is false. -** -** For ASCII, any character with the high-order bit set is -** allowed in an identifier. For 7-bit characters, -** sqlite3IsIdChar[X] must be 1. -** -** For EBCDIC, the rules are more complex but have the same -** end result. -** -** Ticket #1066. the SQL standard does not allow '$' in the -** middle of identfiers. But many SQL implementations do. -** SQLite will allow '$' in identifiers for compatibility. -** But the feature is undocumented. -*/ -#ifdef SQLITE_ASCII -#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) -#endif -#ifdef SQLITE_EBCDIC -SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[] = { -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */ - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */ - 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */ - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */ -}; -#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) -#endif - - -/* -** Return the length of the token that begins at z[0]. -** Store the token type in *tokenType before returning. -*/ -SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ - int i, c; - switch( *z ){ - case ' ': case '\t': case '\n': case '\f': case '\r': { - testcase( z[0]==' ' ); - testcase( z[0]=='\t' ); - testcase( z[0]=='\n' ); - testcase( z[0]=='\f' ); - testcase( z[0]=='\r' ); - for(i=1; sqlite3Isspace(z[i]); i++){} - *tokenType = TK_SPACE; - return i; - } - case '-': { - if( z[1]=='-' ){ - /* IMP: R-50417-27976 -- syntax diagram for comments */ - for(i=2; (c=z[i])!=0 && c!='\n'; i++){} - *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ - return i; - } - *tokenType = TK_MINUS; - return 1; - } - case '(': { - *tokenType = TK_LP; - return 1; - } - case ')': { - *tokenType = TK_RP; - return 1; - } - case ';': { - *tokenType = TK_SEMI; - return 1; - } - case '+': { - *tokenType = TK_PLUS; - return 1; - } - case '*': { - *tokenType = TK_STAR; - return 1; - } - case '/': { - if( z[1]!='*' || z[2]==0 ){ - *tokenType = TK_SLASH; - return 1; - } - /* IMP: R-50417-27976 -- syntax diagram for comments */ - for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} - if( c ) i++; - *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ - return i; - } - case '%': { - *tokenType = TK_REM; - return 1; - } - case '=': { - *tokenType = TK_EQ; - return 1 + (z[1]=='='); - } - case '<': { - if( (c=z[1])=='=' ){ - *tokenType = TK_LE; - return 2; - }else if( c=='>' ){ - *tokenType = TK_NE; - return 2; - }else if( c=='<' ){ - *tokenType = TK_LSHIFT; - return 2; - }else{ - *tokenType = TK_LT; - return 1; - } - } - case '>': { - if( (c=z[1])=='=' ){ - *tokenType = TK_GE; - return 2; - }else if( c=='>' ){ - *tokenType = TK_RSHIFT; - return 2; - }else{ - *tokenType = TK_GT; - return 1; - } - } - case '!': { - if( z[1]!='=' ){ - *tokenType = TK_ILLEGAL; - return 2; - }else{ - *tokenType = TK_NE; - return 2; - } - } - case '|': { - if( z[1]!='|' ){ - *tokenType = TK_BITOR; - return 1; - }else{ - *tokenType = TK_CONCAT; - return 2; - } - } - case ',': { - *tokenType = TK_COMMA; - return 1; - } - case '&': { - *tokenType = TK_BITAND; - return 1; - } - case '~': { - *tokenType = TK_BITNOT; - return 1; - } - case '`': - case '\'': - case '"': { - int delim = z[0]; - testcase( delim=='`' ); - testcase( delim=='\'' ); - testcase( delim=='"' ); - for(i=1; (c=z[i])!=0; i++){ - if( c==delim ){ - if( z[i+1]==delim ){ - i++; - }else{ - break; - } - } - } - if( c=='\'' ){ - *tokenType = TK_STRING; - return i+1; - }else if( c!=0 ){ - *tokenType = TK_ID; - return i+1; - }else{ - *tokenType = TK_ILLEGAL; - return i; - } - } - case '.': { -#ifndef SQLITE_OMIT_FLOATING_POINT - if( !sqlite3Isdigit(z[1]) ) -#endif - { - *tokenType = TK_DOT; - return 1; - } - /* If the next character is a digit, this is a floating point - ** number that begins with ".". Fall thru into the next case */ - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); - testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); - testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); - testcase( z[0]=='9' ); - *tokenType = TK_INTEGER; - for(i=0; sqlite3Isdigit(z[i]); i++){} -#ifndef SQLITE_OMIT_FLOATING_POINT - if( z[i]=='.' ){ - i++; - while( sqlite3Isdigit(z[i]) ){ i++; } - *tokenType = TK_FLOAT; - } - if( (z[i]=='e' || z[i]=='E') && - ( sqlite3Isdigit(z[i+1]) - || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2])) - ) - ){ - i += 2; - while( sqlite3Isdigit(z[i]) ){ i++; } - *tokenType = TK_FLOAT; - } -#endif - while( IdChar(z[i]) ){ - *tokenType = TK_ILLEGAL; - i++; - } - return i; - } - case '[': { - for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} - *tokenType = c==']' ? TK_ID : TK_ILLEGAL; - return i; - } - case '?': { - *tokenType = TK_VARIABLE; - for(i=1; sqlite3Isdigit(z[i]); i++){} - return i; - } - case '#': { - for(i=1; sqlite3Isdigit(z[i]); i++){} - if( i>1 ){ - /* Parameters of the form #NNN (where NNN is a number) are used - ** internally by sqlite3NestedParse. */ - *tokenType = TK_REGISTER; - return i; - } - /* Fall through into the next case if the '#' is not followed by - ** a digit. Try to match #AAAA where AAAA is a parameter name. */ - } -#ifndef SQLITE_OMIT_TCL_VARIABLE - case '$': -#endif - case '@': /* For compatibility with MS SQL Server */ - case ':': { - int n = 0; - testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' ); - *tokenType = TK_VARIABLE; - for(i=1; (c=z[i])!=0; i++){ - if( IdChar(c) ){ - n++; -#ifndef SQLITE_OMIT_TCL_VARIABLE - }else if( c=='(' && n>0 ){ - do{ - i++; - }while( (c=z[i])!=0 && !sqlite3Isspace(c) && c!=')' ); - if( c==')' ){ - i++; - }else{ - *tokenType = TK_ILLEGAL; - } - break; - }else if( c==':' && z[i+1]==':' ){ - i++; -#endif - }else{ - break; - } - } - if( n==0 ) *tokenType = TK_ILLEGAL; - return i; - } -#ifndef SQLITE_OMIT_BLOB_LITERAL - case 'x': case 'X': { - testcase( z[0]=='x' ); testcase( z[0]=='X' ); - if( z[1]=='\'' ){ - *tokenType = TK_BLOB; - for(i=2; sqlite3Isxdigit(z[i]); i++){} - if( z[i]!='\'' || i%2 ){ - *tokenType = TK_ILLEGAL; - while( z[i] && z[i]!='\'' ){ i++; } - } - if( z[i] ) i++; - return i; - } - /* Otherwise fall through to the next case */ - } -#endif - default: { - if( !IdChar(*z) ){ - break; - } - for(i=1; IdChar(z[i]); i++){} - *tokenType = keywordCode((char*)z, i); - return i; - } - } - *tokenType = TK_ILLEGAL; - return 1; -} - -/* -** Run the parser on the given SQL string. The parser structure is -** passed in. An SQLITE_ status code is returned. If an error occurs -** then an and attempt is made to write an error message into -** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that -** error message. -*/ -SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ - int nErr = 0; /* Number of errors encountered */ - int i; /* Loop counter */ - void *pEngine; /* The LEMON-generated LALR(1) parser */ - int tokenType; /* type of the next token */ - int lastTokenParsed = -1; /* type of the previous token */ - u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ - sqlite3 *db = pParse->db; /* The database connection */ - int mxSqlLen; /* Max length of an SQL string */ - - - mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; - if( db->activeVdbeCnt==0 ){ - db->u1.isInterrupted = 0; - } - pParse->rc = SQLITE_OK; - pParse->zTail = zSql; - i = 0; - assert( pzErrMsg!=0 ); - pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc); - if( pEngine==0 ){ - db->mallocFailed = 1; - return SQLITE_NOMEM; - } - assert( pParse->pNewTable==0 ); - assert( pParse->pNewTrigger==0 ); - assert( pParse->nVar==0 ); - assert( pParse->nzVar==0 ); - assert( pParse->azVar==0 ); - enableLookaside = db->lookaside.bEnabled; - if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; - while( !db->mallocFailed && zSql[i]!=0 ){ - assert( i>=0 ); - pParse->sLastToken.z = &zSql[i]; - pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); - i += pParse->sLastToken.n; - if( i>mxSqlLen ){ - pParse->rc = SQLITE_TOOBIG; - break; - } - switch( tokenType ){ - case TK_SPACE: { - if( db->u1.isInterrupted ){ - sqlite3ErrorMsg(pParse, "interrupt"); - pParse->rc = SQLITE_INTERRUPT; - goto abort_parse; - } - break; - } - case TK_ILLEGAL: { - sqlite3DbFree(db, *pzErrMsg); - *pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"", - &pParse->sLastToken); - nErr++; - goto abort_parse; - } - case TK_SEMI: { - pParse->zTail = &zSql[i]; - /* Fall thru into the default case */ - } - default: { - sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); - lastTokenParsed = tokenType; - if( pParse->rc!=SQLITE_OK ){ - goto abort_parse; - } - break; - } - } - } -abort_parse: - if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ - if( lastTokenParsed!=TK_SEMI ){ - sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); - pParse->zTail = &zSql[i]; - } - sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); - } -#ifdef YYTRACKMAXSTACKDEPTH - sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, - sqlite3ParserStackPeak(pEngine) - ); -#endif /* YYDEBUG */ - sqlite3ParserFree(pEngine, sqlite3_free); - db->lookaside.bEnabled = enableLookaside; - if( db->mallocFailed ){ - pParse->rc = SQLITE_NOMEM; - } - if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ - sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc)); - } - assert( pzErrMsg!=0 ); - if( pParse->zErrMsg ){ - *pzErrMsg = pParse->zErrMsg; - sqlite3_log(pParse->rc, "%s", *pzErrMsg); - pParse->zErrMsg = 0; - nErr++; - } - if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ - sqlite3VdbeDelete(pParse->pVdbe); - pParse->pVdbe = 0; - } -#ifndef SQLITE_OMIT_SHARED_CACHE - if( pParse->nested==0 ){ - sqlite3DbFree(db, pParse->aTableLock); - pParse->aTableLock = 0; - pParse->nTableLock = 0; - } -#endif -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3_free(pParse->apVtabLock); -#endif - - if( !IN_DECLARE_VTAB ){ - /* If the pParse->declareVtab flag is set, do not delete any table - ** structure built up in pParse->pNewTable. The calling code (see vtab.c) - ** will take responsibility for freeing the Table structure. - */ - sqlite3DeleteTable(db, pParse->pNewTable); - } - - sqlite3DeleteTrigger(db, pParse->pNewTrigger); - for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]); - sqlite3DbFree(db, pParse->azVar); - sqlite3DbFree(db, pParse->aAlias); - while( pParse->pAinc ){ - AutoincInfo *p = pParse->pAinc; - pParse->pAinc = p->pNext; - sqlite3DbFree(db, p); - } - while( pParse->pZombieTab ){ - Table *p = pParse->pZombieTab; - pParse->pZombieTab = p->pNextZombie; - sqlite3DeleteTable(db, p); - } - if( nErr>0 && pParse->rc==SQLITE_OK ){ - pParse->rc = SQLITE_ERROR; - } - return nErr; -} - -/************** End of tokenize.c ********************************************/ -/************** Begin file complete.c ****************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** An tokenizer for SQL -** -** This file contains C code that implements the sqlite3_complete() API. -** This code used to be part of the tokenizer.c source file. But by -** separating it out, the code will be automatically omitted from -** static links that do not use it. -*/ -#ifndef SQLITE_OMIT_COMPLETE - -/* -** This is defined in tokenize.c. We just have to import the definition. -*/ -#ifndef SQLITE_AMALGAMATION -#ifdef SQLITE_ASCII -#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) -#endif -#ifdef SQLITE_EBCDIC -SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[]; -#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) -#endif -#endif /* SQLITE_AMALGAMATION */ - - -/* -** Token types used by the sqlite3_complete() routine. See the header -** comments on that procedure for additional information. -*/ -#define tkSEMI 0 -#define tkWS 1 -#define tkOTHER 2 -#ifndef SQLITE_OMIT_TRIGGER -#define tkEXPLAIN 3 -#define tkCREATE 4 -#define tkTEMP 5 -#define tkTRIGGER 6 -#define tkEND 7 -#endif - -/* -** Return TRUE if the given SQL string ends in a semicolon. -** -** Special handling is require for CREATE TRIGGER statements. -** Whenever the CREATE TRIGGER keywords are seen, the statement -** must end with ";END;". -** -** This implementation uses a state machine with 8 states: -** -** (0) INVALID We have not yet seen a non-whitespace character. -** -** (1) START At the beginning or end of an SQL statement. This routine -** returns 1 if it ends in the START state and 0 if it ends -** in any other state. -** -** (2) NORMAL We are in the middle of statement which ends with a single -** semicolon. -** -** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of -** a statement. -** -** (4) CREATE The keyword CREATE has been seen at the beginning of a -** statement, possibly preceeded by EXPLAIN and/or followed by -** TEMP or TEMPORARY -** -** (5) TRIGGER We are in the middle of a trigger definition that must be -** ended by a semicolon, the keyword END, and another semicolon. -** -** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at -** the end of a trigger definition. -** -** (7) END We've seen the ";END" of the ";END;" that occurs at the end -** of a trigger difinition. -** -** Transitions between states above are determined by tokens extracted -** from the input. The following tokens are significant: -** -** (0) tkSEMI A semicolon. -** (1) tkWS Whitespace. -** (2) tkOTHER Any other SQL token. -** (3) tkEXPLAIN The "explain" keyword. -** (4) tkCREATE The "create" keyword. -** (5) tkTEMP The "temp" or "temporary" keyword. -** (6) tkTRIGGER The "trigger" keyword. -** (7) tkEND The "end" keyword. -** -** Whitespace never causes a state transition and is always ignored. -** This means that a SQL string of all whitespace is invalid. -** -** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed -** to recognize the end of a trigger can be omitted. All we have to do -** is look for a semicolon that is not part of an string or comment. -*/ -SQLITE_API int sqlite3_complete(const char *zSql){ - u8 state = 0; /* Current state, using numbers defined in header comment */ - u8 token; /* Value of the next token */ - -#ifndef SQLITE_OMIT_TRIGGER - /* A complex statement machine used to detect the end of a CREATE TRIGGER - ** statement. This is the normal case. - */ - static const u8 trans[8][8] = { - /* Token: */ - /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ - /* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, }, - /* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, }, - /* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, }, - /* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, }, - /* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, }, - /* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, }, - /* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, }, - /* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, }, - }; -#else - /* If triggers are not supported by this compile then the statement machine - ** used to detect the end of a statement is much simplier - */ - static const u8 trans[3][3] = { - /* Token: */ - /* State: ** SEMI WS OTHER */ - /* 0 INVALID: */ { 1, 0, 2, }, - /* 1 START: */ { 1, 1, 2, }, - /* 2 NORMAL: */ { 1, 2, 2, }, - }; -#endif /* SQLITE_OMIT_TRIGGER */ - - while( *zSql ){ - switch( *zSql ){ - case ';': { /* A semicolon */ - token = tkSEMI; - break; - } - case ' ': - case '\r': - case '\t': - case '\n': - case '\f': { /* White space is ignored */ - token = tkWS; - break; - } - case '/': { /* C-style comments */ - if( zSql[1]!='*' ){ - token = tkOTHER; - break; - } - zSql += 2; - while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } - if( zSql[0]==0 ) return 0; - zSql++; - token = tkWS; - break; - } - case '-': { /* SQL-style comments from "--" to end of line */ - if( zSql[1]!='-' ){ - token = tkOTHER; - break; - } - while( *zSql && *zSql!='\n' ){ zSql++; } - if( *zSql==0 ) return state==1; - token = tkWS; - break; - } - case '[': { /* Microsoft-style identifiers in [...] */ - zSql++; - while( *zSql && *zSql!=']' ){ zSql++; } - if( *zSql==0 ) return 0; - token = tkOTHER; - break; - } - case '`': /* Grave-accent quoted symbols used by MySQL */ - case '"': /* single- and double-quoted strings */ - case '\'': { - int c = *zSql; - zSql++; - while( *zSql && *zSql!=c ){ zSql++; } - if( *zSql==0 ) return 0; - token = tkOTHER; - break; - } - default: { -#ifdef SQLITE_EBCDIC - unsigned char c; -#endif - if( IdChar((u8)*zSql) ){ - /* Keywords and unquoted identifiers */ - int nId; - for(nId=1; IdChar(zSql[nId]); nId++){} -#ifdef SQLITE_OMIT_TRIGGER - token = tkOTHER; -#else - switch( *zSql ){ - case 'c': case 'C': { - if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){ - token = tkCREATE; - }else{ - token = tkOTHER; - } - break; - } - case 't': case 'T': { - if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){ - token = tkTRIGGER; - }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){ - token = tkTEMP; - }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){ - token = tkTEMP; - }else{ - token = tkOTHER; - } - break; - } - case 'e': case 'E': { - if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){ - token = tkEND; - }else -#ifndef SQLITE_OMIT_EXPLAIN - if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ - token = tkEXPLAIN; - }else -#endif - { - token = tkOTHER; - } - break; - } - default: { - token = tkOTHER; - break; - } - } -#endif /* SQLITE_OMIT_TRIGGER */ - zSql += nId-1; - }else{ - /* Operators and special symbols */ - token = tkOTHER; - } - break; - } - } - state = trans[state][token]; - zSql++; - } - return state==1; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** This routine is the same as the sqlite3_complete() routine described -** above, except that the parameter is required to be UTF-16 encoded, not -** UTF-8. -*/ -SQLITE_API int sqlite3_complete16(const void *zSql){ - sqlite3_value *pVal; - char const *zSql8; - int rc = SQLITE_NOMEM; - -#ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ) return rc; -#endif - pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); - if( zSql8 ){ - rc = sqlite3_complete(zSql8); - }else{ - rc = SQLITE_NOMEM; - } - sqlite3ValueFree(pVal); - return sqlite3ApiExit(0, rc); -} -#endif /* SQLITE_OMIT_UTF16 */ -#endif /* SQLITE_OMIT_COMPLETE */ - -/************** End of complete.c ********************************************/ -/************** Begin file main.c ********************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Main file for the SQLite library. The routines in this file -** implement the programmer interface to the library. Routines in -** other files are for internal use by SQLite and should not be -** accessed by users of the library. -*/ - -#ifdef SQLITE_ENABLE_FTS3 -/************** Include fts3.h in the middle of main.c ***********************/ -/************** Begin file fts3.h ********************************************/ -/* -** 2006 Oct 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file is used by programs that want to link against the -** FTS3 library. All it does is declare the sqlite3Fts3Init() interface. -*/ - -#if 0 -extern "C" { -#endif /* __cplusplus */ - -SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db); - -#if 0 -} /* extern "C" */ -#endif /* __cplusplus */ - -/************** End of fts3.h ************************************************/ -/************** Continuing where we left off in main.c ***********************/ -#endif -#ifdef SQLITE_ENABLE_RTREE -/************** Include rtree.h in the middle of main.c **********************/ -/************** Begin file rtree.h *******************************************/ -/* -** 2008 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file is used by programs that want to link against the -** RTREE library. All it does is declare the sqlite3RtreeInit() interface. -*/ - -#if 0 -extern "C" { -#endif /* __cplusplus */ - -SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db); - -#if 0 -} /* extern "C" */ -#endif /* __cplusplus */ - -/************** End of rtree.h ***********************************************/ -/************** Continuing where we left off in main.c ***********************/ -#endif -#ifdef SQLITE_ENABLE_ICU -/************** Include sqliteicu.h in the middle of main.c ******************/ -/************** Begin file sqliteicu.h ***************************************/ -/* -** 2008 May 26 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This header file is used by programs that want to link against the -** ICU extension. All it does is declare the sqlite3IcuInit() interface. -*/ - -#if 0 -extern "C" { -#endif /* __cplusplus */ - -SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db); - -#if 0 -} /* extern "C" */ -#endif /* __cplusplus */ - - -/************** End of sqliteicu.h *******************************************/ -/************** Continuing where we left off in main.c ***********************/ -#endif - -#ifndef SQLITE_AMALGAMATION -/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant -** contains the text of SQLITE_VERSION macro. -*/ -SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; -#endif - -/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns -** a pointer to the to the sqlite3_version[] string constant. -*/ -SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } - -/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a -** pointer to a string constant whose value is the same as the -** SQLITE_SOURCE_ID C preprocessor macro. -*/ -SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } - -/* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function -** returns an integer equal to SQLITE_VERSION_NUMBER. -*/ -SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } - -/* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns -** zero if and only if SQLite was compiled with mutexing code omitted due to -** the SQLITE_THREADSAFE compile-time option being set to 0. -*/ -SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } - -#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) -/* -** If the following function pointer is not NULL and if -** SQLITE_ENABLE_IOTRACE is enabled, then messages describing -** I/O active are written using this function. These messages -** are intended for debugging activity only. -*/ -SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; -#endif - -/* -** If the following global variable points to a string which is the -** name of a directory, then that directory will be used to store -** temporary files. -** -** See also the "PRAGMA temp_store_directory" SQL command. -*/ -SQLITE_API char *sqlite3_temp_directory = 0; - -/* -** If the following global variable points to a string which is the -** name of a directory, then that directory will be used to store -** all database files specified with a relative pathname. -** -** See also the "PRAGMA data_store_directory" SQL command. -*/ -SQLITE_API char *sqlite3_data_directory = 0; - -/* -** Initialize SQLite. -** -** This routine must be called to initialize the memory allocation, -** VFS, and mutex subsystems prior to doing any serious work with -** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT -** this routine will be called automatically by key routines such as -** sqlite3_open(). -** -** This routine is a no-op except on its very first call for the process, -** or for the first call after a call to sqlite3_shutdown. -** -** The first thread to call this routine runs the initialization to -** completion. If subsequent threads call this routine before the first -** thread has finished the initialization process, then the subsequent -** threads must block until the first thread finishes with the initialization. -** -** The first thread might call this routine recursively. Recursive -** calls to this routine should not block, of course. Otherwise the -** initialization process would never complete. -** -** Let X be the first thread to enter this routine. Let Y be some other -** thread. Then while the initial invocation of this routine by X is -** incomplete, it is required that: -** -** * Calls to this routine from Y must block until the outer-most -** call by X completes. -** -** * Recursive calls to this routine from thread X return immediately -** without blocking. -*/ -SQLITE_API int sqlite3_initialize(void){ - MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ - int rc; /* Result code */ - -#ifdef SQLITE_OMIT_WSD - rc = sqlite3_wsd_init(4096, 24); - if( rc!=SQLITE_OK ){ - return rc; - } -#endif - - /* If SQLite is already completely initialized, then this call - ** to sqlite3_initialize() should be a no-op. But the initialization - ** must be complete. So isInit must not be set until the very end - ** of this routine. - */ - if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; - -#ifdef SQLITE_ENABLE_SQLLOG - { - extern void sqlite3_init_sqllog(void); - sqlite3_init_sqllog(); - } -#endif - - /* Make sure the mutex subsystem is initialized. If unable to - ** initialize the mutex subsystem, return early with the error. - ** If the system is so sick that we are unable to allocate a mutex, - ** there is not much SQLite is going to be able to do. - ** - ** The mutex subsystem must take care of serializing its own - ** initialization. - */ - rc = sqlite3MutexInit(); - if( rc ) return rc; - - /* Initialize the malloc() system and the recursive pInitMutex mutex. - ** This operation is protected by the STATIC_MASTER mutex. Note that - ** MutexAlloc() is called for a static mutex prior to initializing the - ** malloc subsystem - this implies that the allocation of a static - ** mutex must not require support from the malloc subsystem. - */ - MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) - sqlite3_mutex_enter(pMaster); - sqlite3GlobalConfig.isMutexInit = 1; - if( !sqlite3GlobalConfig.isMallocInit ){ - rc = sqlite3MallocInit(); - } - if( rc==SQLITE_OK ){ - sqlite3GlobalConfig.isMallocInit = 1; - if( !sqlite3GlobalConfig.pInitMutex ){ - sqlite3GlobalConfig.pInitMutex = - sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); - if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){ - rc = SQLITE_NOMEM; - } - } - } - if( rc==SQLITE_OK ){ - sqlite3GlobalConfig.nRefInitMutex++; - } - sqlite3_mutex_leave(pMaster); - - /* If rc is not SQLITE_OK at this point, then either the malloc - ** subsystem could not be initialized or the system failed to allocate - ** the pInitMutex mutex. Return an error in either case. */ - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Do the rest of the initialization under the recursive mutex so - ** that we will be able to handle recursive calls into - ** sqlite3_initialize(). The recursive calls normally come through - ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other - ** recursive calls might also be possible. - ** - ** IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls - ** to the xInit method, so the xInit method need not be threadsafe. - ** - ** The following mutex is what serializes access to the appdef pcache xInit - ** methods. The sqlite3_pcache_methods.xInit() all is embedded in the - ** call to sqlite3PcacheInitialize(). - */ - sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex); - if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); - sqlite3GlobalConfig.inProgress = 1; - memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); - sqlite3RegisterGlobalFunctions(); - if( sqlite3GlobalConfig.isPCacheInit==0 ){ - rc = sqlite3PcacheInitialize(); - } - if( rc==SQLITE_OK ){ - sqlite3GlobalConfig.isPCacheInit = 1; - rc = sqlite3OsInit(); - } - if( rc==SQLITE_OK ){ - sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, - sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); - sqlite3GlobalConfig.isInit = 1; - } - sqlite3GlobalConfig.inProgress = 0; - } - sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex); - - /* Go back under the static mutex and clean up the recursive - ** mutex to prevent a resource leak. - */ - sqlite3_mutex_enter(pMaster); - sqlite3GlobalConfig.nRefInitMutex--; - if( sqlite3GlobalConfig.nRefInitMutex<=0 ){ - assert( sqlite3GlobalConfig.nRefInitMutex==0 ); - sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex); - sqlite3GlobalConfig.pInitMutex = 0; - } - sqlite3_mutex_leave(pMaster); - - /* The following is just a sanity check to make sure SQLite has - ** been compiled correctly. It is important to run this code, but - ** we don't want to run it too often and soak up CPU cycles for no - ** reason. So we run it once during initialization. - */ -#ifndef NDEBUG -#ifndef SQLITE_OMIT_FLOATING_POINT - /* This section of code's only "output" is via assert() statements. */ - if ( rc==SQLITE_OK ){ - u64 x = (((u64)1)<<63)-1; - double y; - assert(sizeof(x)==8); - assert(sizeof(x)==sizeof(y)); - memcpy(&y, &x, 8); - assert( sqlite3IsNaN(y) ); - } -#endif -#endif - - /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT - ** compile-time option. - */ -#ifdef SQLITE_EXTRA_INIT - if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){ - int SQLITE_EXTRA_INIT(const char*); - rc = SQLITE_EXTRA_INIT(0); - } -#endif - - return rc; -} - -/* -** Undo the effects of sqlite3_initialize(). Must not be called while -** there are outstanding database connections or memory allocations or -** while any part of SQLite is otherwise in use in any thread. This -** routine is not threadsafe. But it is safe to invoke this routine -** on when SQLite is already shut down. If SQLite is already shut down -** when this routine is invoked, then this routine is a harmless no-op. -*/ -SQLITE_API int sqlite3_shutdown(void){ - if( sqlite3GlobalConfig.isInit ){ -#ifdef SQLITE_EXTRA_SHUTDOWN - void SQLITE_EXTRA_SHUTDOWN(void); - SQLITE_EXTRA_SHUTDOWN(); -#endif - sqlite3_os_end(); - sqlite3_reset_auto_extension(); - sqlite3GlobalConfig.isInit = 0; - } - if( sqlite3GlobalConfig.isPCacheInit ){ - sqlite3PcacheShutdown(); - sqlite3GlobalConfig.isPCacheInit = 0; - } - if( sqlite3GlobalConfig.isMallocInit ){ - sqlite3MallocEnd(); - sqlite3GlobalConfig.isMallocInit = 0; - -#ifndef SQLITE_OMIT_SHUTDOWN_DIRECTORIES - /* The heap subsystem has now been shutdown and these values are supposed - ** to be NULL or point to memory that was obtained from sqlite3_malloc(), - ** which would rely on that heap subsystem; therefore, make sure these - ** values cannot refer to heap memory that was just invalidated when the - ** heap subsystem was shutdown. This is only done if the current call to - ** this function resulted in the heap subsystem actually being shutdown. - */ - sqlite3_data_directory = 0; - sqlite3_temp_directory = 0; -#endif - } - if( sqlite3GlobalConfig.isMutexInit ){ - sqlite3MutexEnd(); - sqlite3GlobalConfig.isMutexInit = 0; - } - - return SQLITE_OK; -} - -/* -** This API allows applications to modify the global configuration of -** the SQLite library at run-time. -** -** This routine should only be called when there are no outstanding -** database connections or memory allocations. This routine is not -** threadsafe. Failure to heed these warnings can lead to unpredictable -** behavior. -*/ -SQLITE_API int sqlite3_config(int op, ...){ - va_list ap; - int rc = SQLITE_OK; - - /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while - ** the SQLite library is in use. */ - if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; - - va_start(ap, op); - switch( op ){ - - /* Mutex configuration options are only available in a threadsafe - ** compile. - */ -#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 - case SQLITE_CONFIG_SINGLETHREAD: { - /* Disable all mutexing */ - sqlite3GlobalConfig.bCoreMutex = 0; - sqlite3GlobalConfig.bFullMutex = 0; - break; - } - case SQLITE_CONFIG_MULTITHREAD: { - /* Disable mutexing of database connections */ - /* Enable mutexing of core data structures */ - sqlite3GlobalConfig.bCoreMutex = 1; - sqlite3GlobalConfig.bFullMutex = 0; - break; - } - case SQLITE_CONFIG_SERIALIZED: { - /* Enable all mutexing */ - sqlite3GlobalConfig.bCoreMutex = 1; - sqlite3GlobalConfig.bFullMutex = 1; - break; - } - case SQLITE_CONFIG_MUTEX: { - /* Specify an alternative mutex implementation */ - sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*); - break; - } - case SQLITE_CONFIG_GETMUTEX: { - /* Retrieve the current mutex implementation */ - *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex; - break; - } -#endif - - - case SQLITE_CONFIG_MALLOC: { - /* Specify an alternative malloc implementation */ - sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*); - break; - } - case SQLITE_CONFIG_GETMALLOC: { - /* Retrieve the current malloc() implementation */ - if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); - *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; - break; - } - case SQLITE_CONFIG_MEMSTATUS: { - /* Enable or disable the malloc status collection */ - sqlite3GlobalConfig.bMemstat = va_arg(ap, int); - break; - } - case SQLITE_CONFIG_SCRATCH: { - /* Designate a buffer for scratch memory space */ - sqlite3GlobalConfig.pScratch = va_arg(ap, void*); - sqlite3GlobalConfig.szScratch = va_arg(ap, int); - sqlite3GlobalConfig.nScratch = va_arg(ap, int); - break; - } - case SQLITE_CONFIG_PAGECACHE: { - /* Designate a buffer for page cache memory space */ - sqlite3GlobalConfig.pPage = va_arg(ap, void*); - sqlite3GlobalConfig.szPage = va_arg(ap, int); - sqlite3GlobalConfig.nPage = va_arg(ap, int); - break; - } - - case SQLITE_CONFIG_PCACHE: { - /* no-op */ - break; - } - case SQLITE_CONFIG_GETPCACHE: { - /* now an error */ - rc = SQLITE_ERROR; - break; - } - - case SQLITE_CONFIG_PCACHE2: { - /* Specify an alternative page cache implementation */ - sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*); - break; - } - case SQLITE_CONFIG_GETPCACHE2: { - if( sqlite3GlobalConfig.pcache2.xInit==0 ){ - sqlite3PCacheSetDefault(); - } - *va_arg(ap, sqlite3_pcache_methods2*) = sqlite3GlobalConfig.pcache2; - break; - } - -#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) - case SQLITE_CONFIG_HEAP: { - /* Designate a buffer for heap memory space */ - sqlite3GlobalConfig.pHeap = va_arg(ap, void*); - sqlite3GlobalConfig.nHeap = va_arg(ap, int); - sqlite3GlobalConfig.mnReq = va_arg(ap, int); - - if( sqlite3GlobalConfig.mnReq<1 ){ - sqlite3GlobalConfig.mnReq = 1; - }else if( sqlite3GlobalConfig.mnReq>(1<<12) ){ - /* cap min request size at 2^12 */ - sqlite3GlobalConfig.mnReq = (1<<12); - } - - if( sqlite3GlobalConfig.pHeap==0 ){ - /* If the heap pointer is NULL, then restore the malloc implementation - ** back to NULL pointers too. This will cause the malloc to go - ** back to its default implementation when sqlite3_initialize() is - ** run. - */ - memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m)); - }else{ - /* The heap pointer is not NULL, then install one of the - ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor - ** ENABLE_MEMSYS5 is defined, return an error. - */ -#ifdef SQLITE_ENABLE_MEMSYS3 - sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3(); -#endif -#ifdef SQLITE_ENABLE_MEMSYS5 - sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5(); -#endif - } - break; - } -#endif - - case SQLITE_CONFIG_LOOKASIDE: { - sqlite3GlobalConfig.szLookaside = va_arg(ap, int); - sqlite3GlobalConfig.nLookaside = va_arg(ap, int); - break; - } - - /* Record a pointer to the logger funcction and its first argument. - ** The default is NULL. Logging is disabled if the function pointer is - ** NULL. - */ - case SQLITE_CONFIG_LOG: { - /* MSVC is picky about pulling func ptrs from va lists. - ** http://support.microsoft.com/kb/47961 - ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); - */ - typedef void(*LOGFUNC_t)(void*,int,const char*); - sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t); - sqlite3GlobalConfig.pLogArg = va_arg(ap, void*); - break; - } - - case SQLITE_CONFIG_URI: { - sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); - break; - } - - case SQLITE_CONFIG_COVERING_INDEX_SCAN: { - sqlite3GlobalConfig.bUseCis = va_arg(ap, int); - break; - } - -#ifdef SQLITE_ENABLE_SQLLOG - case SQLITE_CONFIG_SQLLOG: { - typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int); - sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t); - sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *); - break; - } -#endif - - case SQLITE_CONFIG_MMAP_SIZE: { - sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64); - sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64); - if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){ - mxMmap = SQLITE_MAX_MMAP_SIZE; - } - sqlite3GlobalConfig.mxMmap = mxMmap; - if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE; - if( szMmap>mxMmap) szMmap = mxMmap; - sqlite3GlobalConfig.szMmap = szMmap; - break; - } - - default: { - rc = SQLITE_ERROR; - break; - } - } - va_end(ap); - return rc; -} - -/* -** Set up the lookaside buffers for a database connection. -** Return SQLITE_OK on success. -** If lookaside is already active, return SQLITE_BUSY. -** -** The sz parameter is the number of bytes in each lookaside slot. -** The cnt parameter is the number of slots. If pStart is NULL the -** space for the lookaside memory is obtained from sqlite3_malloc(). -** If pStart is not NULL then it is sz*cnt bytes of memory to use for -** the lookaside memory. -*/ -static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ - void *pStart; - if( db->lookaside.nOut ){ - return SQLITE_BUSY; - } - /* Free any existing lookaside buffer for this handle before - ** allocating a new one so we don't have to have space for - ** both at the same time. - */ - if( db->lookaside.bMalloced ){ - sqlite3_free(db->lookaside.pStart); - } - /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger - ** than a pointer to be useful. - */ - sz = ROUNDDOWN8(sz); /* IMP: R-33038-09382 */ - if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0; - if( cnt<0 ) cnt = 0; - if( sz==0 || cnt==0 ){ - sz = 0; - pStart = 0; - }else if( pBuf==0 ){ - sqlite3BeginBenignMalloc(); - pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */ - sqlite3EndBenignMalloc(); - if( pStart ) cnt = sqlite3MallocSize(pStart)/sz; - }else{ - pStart = pBuf; - } - db->lookaside.pStart = pStart; - db->lookaside.pFree = 0; - db->lookaside.sz = (u16)sz; - if( pStart ){ - int i; - LookasideSlot *p; - assert( sz > (int)sizeof(LookasideSlot*) ); - p = (LookasideSlot*)pStart; - for(i=cnt-1; i>=0; i--){ - p->pNext = db->lookaside.pFree; - db->lookaside.pFree = p; - p = (LookasideSlot*)&((u8*)p)[sz]; - } - db->lookaside.pEnd = p; - db->lookaside.bEnabled = 1; - db->lookaside.bMalloced = pBuf==0 ?1:0; - }else{ - db->lookaside.pEnd = 0; - db->lookaside.bEnabled = 0; - db->lookaside.bMalloced = 0; - } - return SQLITE_OK; -} - -/* -** Return the mutex associated with a database connection. -*/ -SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){ - return db->mutex; -} - -/* -** Free up as much memory as we can from the given database -** connection. -*/ -SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){ - int i; - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - Pager *pPager = sqlite3BtreePager(pBt); - sqlite3PagerShrink(pPager); - } - } - sqlite3BtreeLeaveAll(db); - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -/* -** Configuration settings for an individual database connection -*/ -SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ - va_list ap; - int rc; - va_start(ap, op); - switch( op ){ - case SQLITE_DBCONFIG_LOOKASIDE: { - void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */ - int sz = va_arg(ap, int); /* IMP: R-47871-25994 */ - int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */ - rc = setupLookaside(db, pBuf, sz, cnt); - break; - } - default: { - static const struct { - int op; /* The opcode */ - u32 mask; /* Mask of the bit in sqlite3.flags to set/clear */ - } aFlagOp[] = { - { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, - { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, - }; - unsigned int i; - rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ - for(i=0; iflags; - if( onoff>0 ){ - db->flags |= aFlagOp[i].mask; - }else if( onoff==0 ){ - db->flags &= ~aFlagOp[i].mask; - } - if( oldFlags!=db->flags ){ - sqlite3ExpirePreparedStatements(db); - } - if( pRes ){ - *pRes = (db->flags & aFlagOp[i].mask)!=0; - } - rc = SQLITE_OK; - break; - } - } - break; - } - } - va_end(ap); - return rc; -} - - -/* -** Return true if the buffer z[0..n-1] contains all spaces. -*/ -static int allSpaces(const char *z, int n){ - while( n>0 && z[n-1]==' ' ){ n--; } - return n==0; -} - -/* -** This is the default collating function named "BINARY" which is always -** available. -** -** If the padFlag argument is not NULL then space padding at the end -** of strings is ignored. This implements the RTRIM collation. -*/ -static int binCollFunc( - void *padFlag, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 -){ - int rc, n; - n = nKey1lastRowid; -} - -/* -** Return the number of changes in the most recent call to sqlite3_exec(). -*/ -SQLITE_API int sqlite3_changes(sqlite3 *db){ - return db->nChange; -} - -/* -** Return the number of changes since the database handle was opened. -*/ -SQLITE_API int sqlite3_total_changes(sqlite3 *db){ - return db->nTotalChange; -} - -/* -** Close all open savepoints. This function only manipulates fields of the -** database handle object, it does not close any savepoints that may be open -** at the b-tree/pager level. -*/ -SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *db){ - while( db->pSavepoint ){ - Savepoint *pTmp = db->pSavepoint; - db->pSavepoint = pTmp->pNext; - sqlite3DbFree(db, pTmp); - } - db->nSavepoint = 0; - db->nStatement = 0; - db->isTransactionSavepoint = 0; -} - -/* -** Invoke the destructor function associated with FuncDef p, if any. Except, -** if this is not the last copy of the function, do not invoke it. Multiple -** copies of a single function are created when create_function() is called -** with SQLITE_ANY as the encoding. -*/ -static void functionDestroy(sqlite3 *db, FuncDef *p){ - FuncDestructor *pDestructor = p->pDestructor; - if( pDestructor ){ - pDestructor->nRef--; - if( pDestructor->nRef==0 ){ - pDestructor->xDestroy(pDestructor->pUserData); - sqlite3DbFree(db, pDestructor); - } - } -} - -/* -** Disconnect all sqlite3_vtab objects that belong to database connection -** db. This is called when db is being closed. -*/ -static void disconnectAllVtab(sqlite3 *db){ -#ifndef SQLITE_OMIT_VIRTUALTABLE - int i; - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Schema *pSchema = db->aDb[i].pSchema; - if( db->aDb[i].pSchema ){ - HashElem *p; - for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ - Table *pTab = (Table *)sqliteHashData(p); - if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); - } - } - } - sqlite3BtreeLeaveAll(db); -#else - UNUSED_PARAMETER(db); -#endif -} - -/* -** Return TRUE if database connection db has unfinalized prepared -** statements or unfinished sqlite3_backup objects. -*/ -static int connectionIsBusy(sqlite3 *db){ - int j; - assert( sqlite3_mutex_held(db->mutex) ); - if( db->pVdbe ) return 1; - for(j=0; jnDb; j++){ - Btree *pBt = db->aDb[j].pBt; - if( pBt && sqlite3BtreeIsInBackup(pBt) ) return 1; - } - return 0; -} - -/* -** Close an existing SQLite database -*/ -static int sqlite3Close(sqlite3 *db, int forceZombie){ - if( !db ){ - return SQLITE_OK; - } - if( !sqlite3SafetyCheckSickOrOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - sqlite3_mutex_enter(db->mutex); - - /* Force xDisconnect calls on all virtual tables */ - disconnectAllVtab(db); - - /* If a transaction is open, the disconnectAllVtab() call above - ** will not have called the xDisconnect() method on any virtual - ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() - ** call will do so. We need to do this before the check for active - ** SQL statements below, as the v-table implementation may be storing - ** some prepared statements internally. - */ - sqlite3VtabRollback(db); - - /* Legacy behavior (sqlite3_close() behavior) is to return - ** SQLITE_BUSY if the connection can not be closed immediately. - */ - if( !forceZombie && connectionIsBusy(db) ){ - sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " - "statements or unfinished backups"); - sqlite3_mutex_leave(db->mutex); - return SQLITE_BUSY; - } - -#ifdef SQLITE_ENABLE_SQLLOG - if( sqlite3GlobalConfig.xSqllog ){ - /* Closing the handle. Fourth parameter is passed the value 2. */ - sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2); - } -#endif - - /* Convert the connection into a zombie and then close it. - */ - db->magic = SQLITE_MAGIC_ZOMBIE; - sqlite3LeaveMutexAndCloseZombie(db); - return SQLITE_OK; -} - -/* -** Two variations on the public interface for closing a database -** connection. The sqlite3_close() version returns SQLITE_BUSY and -** leaves the connection option if there are unfinalized prepared -** statements or unfinished sqlite3_backups. The sqlite3_close_v2() -** version forces the connection to become a zombie if there are -** unclosed resources, and arranges for deallocation when the last -** prepare statement or sqlite3_backup closes. -*/ -SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); } -SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); } - - -/* -** Close the mutex on database connection db. -** -** Furthermore, if database connection db is a zombie (meaning that there -** has been a prior call to sqlite3_close(db) or sqlite3_close_v2(db)) and -** every sqlite3_stmt has now been finalized and every sqlite3_backup has -** finished, then free all resources. -*/ -SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ - HashElem *i; /* Hash table iterator */ - int j; - - /* If there are outstanding sqlite3_stmt or sqlite3_backup objects - ** or if the connection has not yet been closed by sqlite3_close_v2(), - ** then just leave the mutex and return. - */ - if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){ - sqlite3_mutex_leave(db->mutex); - return; - } - - /* If we reach this point, it means that the database connection has - ** closed all sqlite3_stmt and sqlite3_backup objects and has been - ** passed to sqlite3_close (meaning that it is a zombie). Therefore, - ** go ahead and free all resources. - */ - - /* If a transaction is open, roll it back. This also ensures that if - ** any database schemas have been modified by an uncommitted transaction - ** they are reset. And that the required b-tree mutex is held to make - ** the pager rollback and schema reset an atomic operation. */ - sqlite3RollbackAll(db, SQLITE_OK); - - /* Free any outstanding Savepoint structures. */ - sqlite3CloseSavepoints(db); - - /* Close all database connections */ - for(j=0; jnDb; j++){ - struct Db *pDb = &db->aDb[j]; - if( pDb->pBt ){ - sqlite3BtreeClose(pDb->pBt); - pDb->pBt = 0; - if( j!=1 ){ - pDb->pSchema = 0; - } - } - } - /* Clear the TEMP schema separately and last */ - if( db->aDb[1].pSchema ){ - sqlite3SchemaClear(db->aDb[1].pSchema); - } - sqlite3VtabUnlockList(db); - - /* Free up the array of auxiliary databases */ - sqlite3CollapseDatabaseArray(db); - assert( db->nDb<=2 ); - assert( db->aDb==db->aDbStatic ); - - /* Tell the code in notify.c that the connection no longer holds any - ** locks and does not require any further unlock-notify callbacks. - */ - sqlite3ConnectionClosed(db); - - for(j=0; jaFunc.a); j++){ - FuncDef *pNext, *pHash, *p; - for(p=db->aFunc.a[j]; p; p=pHash){ - pHash = p->pHash; - while( p ){ - functionDestroy(db, p); - pNext = p->pNext; - sqlite3DbFree(db, p); - p = pNext; - } - } - } - for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ - CollSeq *pColl = (CollSeq *)sqliteHashData(i); - /* Invoke any destructors registered for collation sequence user data. */ - for(j=0; j<3; j++){ - if( pColl[j].xDel ){ - pColl[j].xDel(pColl[j].pUser); - } - } - sqlite3DbFree(db, pColl); - } - sqlite3HashClear(&db->aCollSeq); -#ifndef SQLITE_OMIT_VIRTUALTABLE - for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ - Module *pMod = (Module *)sqliteHashData(i); - if( pMod->xDestroy ){ - pMod->xDestroy(pMod->pAux); - } - sqlite3DbFree(db, pMod); - } - sqlite3HashClear(&db->aModule); -#endif - - sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ - if( db->pErr ){ - sqlite3ValueFree(db->pErr); - } - sqlite3CloseExtensions(db); - - db->magic = SQLITE_MAGIC_ERROR; - - /* The temp-database schema is allocated differently from the other schema - ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). - ** So it needs to be freed here. Todo: Why not roll the temp schema into - ** the same sqliteMalloc() as the one that allocates the database - ** structure? - */ - sqlite3DbFree(db, db->aDb[1].pSchema); - sqlite3_mutex_leave(db->mutex); - db->magic = SQLITE_MAGIC_CLOSED; - sqlite3_mutex_free(db->mutex); - assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */ - if( db->lookaside.bMalloced ){ - sqlite3_free(db->lookaside.pStart); - } - sqlite3_free(db); -} - -/* -** Rollback all database files. If tripCode is not SQLITE_OK, then -** any open cursors are invalidated ("tripped" - as in "tripping a circuit -** breaker") and made to return tripCode if there are any further -** attempts to use that cursor. -*/ -SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ - int i; - int inTrans = 0; - assert( sqlite3_mutex_held(db->mutex) ); - sqlite3BeginBenignMalloc(); - - /* Obtain all b-tree mutexes before making any calls to BtreeRollback(). - ** This is important in case the transaction being rolled back has - ** modified the database schema. If the b-tree mutexes are not taken - ** here, then another shared-cache connection might sneak in between - ** the database rollback and schema reset, which can cause false - ** corruption reports in some cases. */ - sqlite3BtreeEnterAll(db); - - for(i=0; inDb; i++){ - Btree *p = db->aDb[i].pBt; - if( p ){ - if( sqlite3BtreeIsInTrans(p) ){ - inTrans = 1; - } - sqlite3BtreeRollback(p, tripCode); - db->aDb[i].inTrans = 0; - } - } - sqlite3VtabRollback(db); - sqlite3EndBenignMalloc(); - - if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){ - sqlite3ExpirePreparedStatements(db); - sqlite3ResetAllSchemasOfConnection(db); - } - sqlite3BtreeLeaveAll(db); - - /* Any deferred constraint violations have now been resolved. */ - db->nDeferredCons = 0; - - /* If one has been configured, invoke the rollback-hook callback */ - if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ - db->xRollbackCallback(db->pRollbackArg); - } -} - -/* -** Return a static string containing the name corresponding to the error code -** specified in the argument. -*/ -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \ - defined(SQLITE_DEBUG_OS_TRACE) -SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ - const char *zName = 0; - int i, origRc = rc; - for(i=0; i<2 && zName==0; i++, rc &= 0xff){ - switch( rc ){ - case SQLITE_OK: zName = "SQLITE_OK"; break; - case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; - case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; - case SQLITE_PERM: zName = "SQLITE_PERM"; break; - case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; - case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break; - case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; - case SQLITE_BUSY_RECOVERY: zName = "SQLITE_BUSY_RECOVERY"; break; - case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; - case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break; - case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; - case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; - case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; - case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; - case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; - case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; - case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; - case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; - case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break; - case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break; - case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break; - case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break; - case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break; - case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break; - case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break; - case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break; - case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break; - case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break; - case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break; - case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break; - case SQLITE_IOERR_CHECKRESERVEDLOCK: - zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; - case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break; - case SQLITE_IOERR_CLOSE: zName = "SQLITE_IOERR_CLOSE"; break; - case SQLITE_IOERR_DIR_CLOSE: zName = "SQLITE_IOERR_DIR_CLOSE"; break; - case SQLITE_IOERR_SHMOPEN: zName = "SQLITE_IOERR_SHMOPEN"; break; - case SQLITE_IOERR_SHMSIZE: zName = "SQLITE_IOERR_SHMSIZE"; break; - case SQLITE_IOERR_SHMLOCK: zName = "SQLITE_IOERR_SHMLOCK"; break; - case SQLITE_IOERR_SHMMAP: zName = "SQLITE_IOERR_SHMMAP"; break; - case SQLITE_IOERR_SEEK: zName = "SQLITE_IOERR_SEEK"; break; - case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break; - case SQLITE_IOERR_MMAP: zName = "SQLITE_IOERR_MMAP"; break; - case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break; - case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break; - case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break; - case SQLITE_FULL: zName = "SQLITE_FULL"; break; - case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break; - case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break; - case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break; - case SQLITE_CANTOPEN_FULLPATH: zName = "SQLITE_CANTOPEN_FULLPATH"; break; - case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break; - case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break; - case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break; - case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break; - case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break; - case SQLITE_CONSTRAINT_UNIQUE: zName = "SQLITE_CONSTRAINT_UNIQUE"; break; - case SQLITE_CONSTRAINT_TRIGGER: zName = "SQLITE_CONSTRAINT_TRIGGER";break; - case SQLITE_CONSTRAINT_FOREIGNKEY: - zName = "SQLITE_CONSTRAINT_FOREIGNKEY"; break; - case SQLITE_CONSTRAINT_CHECK: zName = "SQLITE_CONSTRAINT_CHECK"; break; - case SQLITE_CONSTRAINT_PRIMARYKEY: - zName = "SQLITE_CONSTRAINT_PRIMARYKEY"; break; - case SQLITE_CONSTRAINT_NOTNULL: zName = "SQLITE_CONSTRAINT_NOTNULL";break; - case SQLITE_CONSTRAINT_COMMITHOOK: - zName = "SQLITE_CONSTRAINT_COMMITHOOK"; break; - case SQLITE_CONSTRAINT_VTAB: zName = "SQLITE_CONSTRAINT_VTAB"; break; - case SQLITE_CONSTRAINT_FUNCTION: - zName = "SQLITE_CONSTRAINT_FUNCTION"; break; - case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break; - case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break; - case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break; - case SQLITE_AUTH: zName = "SQLITE_AUTH"; break; - case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break; - case SQLITE_RANGE: zName = "SQLITE_RANGE"; break; - case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break; - case SQLITE_ROW: zName = "SQLITE_ROW"; break; - case SQLITE_NOTICE: zName = "SQLITE_NOTICE"; break; - case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break; - case SQLITE_NOTICE_RECOVER_ROLLBACK: - zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break; - case SQLITE_WARNING: zName = "SQLITE_WARNING"; break; - case SQLITE_DONE: zName = "SQLITE_DONE"; break; - } - } - if( zName==0 ){ - static char zBuf[50]; - sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_UNKNOWN(%d)", origRc); - zName = zBuf; - } - return zName; -} -#endif - -/* -** Return a static string that describes the kind of error specified in the -** argument. -*/ -SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ - static const char* const aMsg[] = { - /* SQLITE_OK */ "not an error", - /* SQLITE_ERROR */ "SQL logic error or missing database", - /* SQLITE_INTERNAL */ 0, - /* SQLITE_PERM */ "access permission denied", - /* SQLITE_ABORT */ "callback requested query abort", - /* SQLITE_BUSY */ "database is locked", - /* SQLITE_LOCKED */ "database table is locked", - /* SQLITE_NOMEM */ "out of memory", - /* SQLITE_READONLY */ "attempt to write a readonly database", - /* SQLITE_INTERRUPT */ "interrupted", - /* SQLITE_IOERR */ "disk I/O error", - /* SQLITE_CORRUPT */ "database disk image is malformed", - /* SQLITE_NOTFOUND */ "unknown operation", - /* SQLITE_FULL */ "database or disk is full", - /* SQLITE_CANTOPEN */ "unable to open database file", - /* SQLITE_PROTOCOL */ "locking protocol", - /* SQLITE_EMPTY */ "table contains no data", - /* SQLITE_SCHEMA */ "database schema has changed", - /* SQLITE_TOOBIG */ "string or blob too big", - /* SQLITE_CONSTRAINT */ "constraint failed", - /* SQLITE_MISMATCH */ "datatype mismatch", - /* SQLITE_MISUSE */ "library routine called out of sequence", - /* SQLITE_NOLFS */ "large file support is disabled", - /* SQLITE_AUTH */ "authorization denied", - /* SQLITE_FORMAT */ "auxiliary database format error", - /* SQLITE_RANGE */ "bind or column index out of range", - /* SQLITE_NOTADB */ "file is encrypted or is not a database", - }; - const char *zErr = "unknown error"; - switch( rc ){ - case SQLITE_ABORT_ROLLBACK: { - zErr = "abort due to ROLLBACK"; - break; - } - default: { - rc &= 0xff; - if( ALWAYS(rc>=0) && rcbusyTimeout; - int delay, prior; - - assert( count>=0 ); - if( count < NDELAY ){ - delay = delays[count]; - prior = totals[count]; - }else{ - delay = delays[NDELAY-1]; - prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); - } - if( prior + delay > timeout ){ - delay = timeout - prior; - if( delay<=0 ) return 0; - } - sqlite3OsSleep(db->pVfs, delay*1000); - return 1; -#else - sqlite3 *db = (sqlite3 *)ptr; - int timeout = ((sqlite3 *)ptr)->busyTimeout; - if( (count+1)*1000 > timeout ){ - return 0; - } - sqlite3OsSleep(db->pVfs, 1000000); - return 1; -#endif -} - -/* -** Invoke the given busy handler. -** -** This routine is called when an operation failed with a lock. -** If this routine returns non-zero, the lock is retried. If it -** returns 0, the operation aborts with an SQLITE_BUSY error. -*/ -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ - int rc; - if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0; - rc = p->xFunc(p->pArg, p->nBusy); - if( rc==0 ){ - p->nBusy = -1; - }else{ - p->nBusy++; - } - return rc; -} - -/* -** This routine sets the busy callback for an Sqlite database to the -** given callback function with the given argument. -*/ -SQLITE_API int sqlite3_busy_handler( - sqlite3 *db, - int (*xBusy)(void*,int), - void *pArg -){ - sqlite3_mutex_enter(db->mutex); - db->busyHandler.xFunc = xBusy; - db->busyHandler.pArg = pArg; - db->busyHandler.nBusy = 0; - db->busyTimeout = 0; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK -/* -** This routine sets the progress callback for an Sqlite database to the -** given callback function with the given argument. The progress callback will -** be invoked every nOps opcodes. -*/ -SQLITE_API void sqlite3_progress_handler( - sqlite3 *db, - int nOps, - int (*xProgress)(void*), - void *pArg -){ - sqlite3_mutex_enter(db->mutex); - if( nOps>0 ){ - db->xProgress = xProgress; - db->nProgressOps = nOps; - db->pProgressArg = pArg; - }else{ - db->xProgress = 0; - db->nProgressOps = 0; - db->pProgressArg = 0; - } - sqlite3_mutex_leave(db->mutex); -} -#endif - - -/* -** This routine installs a default busy handler that waits for the -** specified number of milliseconds before returning 0. -*/ -SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ - if( ms>0 ){ - sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); - db->busyTimeout = ms; - }else{ - sqlite3_busy_handler(db, 0, 0); - } - return SQLITE_OK; -} - -/* -** Cause any pending operation to stop at its earliest opportunity. -*/ -SQLITE_API void sqlite3_interrupt(sqlite3 *db){ - db->u1.isInterrupted = 1; -} - - -/* -** This function is exactly the same as sqlite3_create_function(), except -** that it is designed to be called by internal code. The difference is -** that if a malloc() fails in sqlite3_create_function(), an error code -** is returned and the mallocFailed flag cleared. -*/ -SQLITE_PRIVATE int sqlite3CreateFunc( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int enc, - void *pUserData, - void (*xFunc)(sqlite3_context*,int,sqlite3_value **), - void (*xStep)(sqlite3_context*,int,sqlite3_value **), - void (*xFinal)(sqlite3_context*), - FuncDestructor *pDestructor -){ - FuncDef *p; - int nName; - - assert( sqlite3_mutex_held(db->mutex) ); - if( zFunctionName==0 || - (xFunc && (xFinal || xStep)) || - (!xFunc && (xFinal && !xStep)) || - (!xFunc && (!xFinal && xStep)) || - (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || - (255<(nName = sqlite3Strlen30( zFunctionName))) ){ - return SQLITE_MISUSE_BKPT; - } - -#ifndef SQLITE_OMIT_UTF16 - /* If SQLITE_UTF16 is specified as the encoding type, transform this - ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the - ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. - ** - ** If SQLITE_ANY is specified, add three versions of the function - ** to the hash table. - */ - if( enc==SQLITE_UTF16 ){ - enc = SQLITE_UTF16NATIVE; - }else if( enc==SQLITE_ANY ){ - int rc; - rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, - pUserData, xFunc, xStep, xFinal, pDestructor); - if( rc==SQLITE_OK ){ - rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, - pUserData, xFunc, xStep, xFinal, pDestructor); - } - if( rc!=SQLITE_OK ){ - return rc; - } - enc = SQLITE_UTF16BE; - } -#else - enc = SQLITE_UTF8; -#endif - - /* Check if an existing function is being overridden or deleted. If so, - ** and there are active VMs, then return SQLITE_BUSY. If a function - ** is being overridden/deleted but there are no active VMs, allow the - ** operation to continue but invalidate all precompiled statements. - */ - p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); - if( p && p->iPrefEnc==enc && p->nArg==nArg ){ - if( db->activeVdbeCnt ){ - sqlite3Error(db, SQLITE_BUSY, - "unable to delete/modify user-function due to active statements"); - assert( !db->mallocFailed ); - return SQLITE_BUSY; - }else{ - sqlite3ExpirePreparedStatements(db); - } - } - - p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1); - assert(p || db->mallocFailed); - if( !p ){ - return SQLITE_NOMEM; - } - - /* If an older version of the function with a configured destructor is - ** being replaced invoke the destructor function here. */ - functionDestroy(db, p); - - if( pDestructor ){ - pDestructor->nRef++; - } - p->pDestructor = pDestructor; - p->flags = 0; - p->xFunc = xFunc; - p->xStep = xStep; - p->xFinalize = xFinal; - p->pUserData = pUserData; - p->nArg = (u16)nArg; - return SQLITE_OK; -} - -/* -** Create new user functions. -*/ -SQLITE_API int sqlite3_create_function( - sqlite3 *db, - const char *zFunc, - int nArg, - int enc, - void *p, - void (*xFunc)(sqlite3_context*,int,sqlite3_value **), - void (*xStep)(sqlite3_context*,int,sqlite3_value **), - void (*xFinal)(sqlite3_context*) -){ - return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xFunc, xStep, - xFinal, 0); -} - -SQLITE_API int sqlite3_create_function_v2( - sqlite3 *db, - const char *zFunc, - int nArg, - int enc, - void *p, - void (*xFunc)(sqlite3_context*,int,sqlite3_value **), - void (*xStep)(sqlite3_context*,int,sqlite3_value **), - void (*xFinal)(sqlite3_context*), - void (*xDestroy)(void *) -){ - int rc = SQLITE_ERROR; - FuncDestructor *pArg = 0; - sqlite3_mutex_enter(db->mutex); - if( xDestroy ){ - pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); - if( !pArg ){ - xDestroy(p); - goto out; - } - pArg->xDestroy = xDestroy; - pArg->pUserData = p; - } - rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xFunc, xStep, xFinal, pArg); - if( pArg && pArg->nRef==0 ){ - assert( rc!=SQLITE_OK ); - xDestroy(p); - sqlite3DbFree(db, pArg); - } - - out: - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -#ifndef SQLITE_OMIT_UTF16 -SQLITE_API int sqlite3_create_function16( - sqlite3 *db, - const void *zFunctionName, - int nArg, - int eTextRep, - void *p, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -){ - int rc; - char *zFunc8; - sqlite3_mutex_enter(db->mutex); - assert( !db->mallocFailed ); - zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); - rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal,0); - sqlite3DbFree(db, zFunc8); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} -#endif - - -/* -** Declare that a function has been overloaded by a virtual table. -** -** If the function already exists as a regular global function, then -** this routine is a no-op. If the function does not exist, then create -** a new one that always throws a run-time error. -** -** When virtual tables intend to provide an overloaded function, they -** should call this routine to make sure the global function exists. -** A global function must exist in order for name resolution to work -** properly. -*/ -SQLITE_API int sqlite3_overload_function( - sqlite3 *db, - const char *zName, - int nArg -){ - int nName = sqlite3Strlen30(zName); - int rc = SQLITE_OK; - sqlite3_mutex_enter(db->mutex); - if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ - rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, - 0, sqlite3InvalidFunction, 0, 0, 0); - } - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -#ifndef SQLITE_OMIT_TRACE -/* -** Register a trace function. The pArg from the previously registered trace -** is returned. -** -** A NULL trace function means that no tracing is executes. A non-NULL -** trace is a pointer to a function that is invoked at the start of each -** SQL statement. -*/ -SQLITE_API void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ - void *pOld; - sqlite3_mutex_enter(db->mutex); - pOld = db->pTraceArg; - db->xTrace = xTrace; - db->pTraceArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pOld; -} -/* -** Register a profile function. The pArg from the previously registered -** profile function is returned. -** -** A NULL profile function means that no profiling is executes. A non-NULL -** profile is a pointer to a function that is invoked at the conclusion of -** each SQL statement that is run. -*/ -SQLITE_API void *sqlite3_profile( - sqlite3 *db, - void (*xProfile)(void*,const char*,sqlite_uint64), - void *pArg -){ - void *pOld; - sqlite3_mutex_enter(db->mutex); - pOld = db->pProfileArg; - db->xProfile = xProfile; - db->pProfileArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pOld; -} -#endif /* SQLITE_OMIT_TRACE */ - -/* -** Register a function to be invoked when a transaction commits. -** If the invoked function returns non-zero, then the commit becomes a -** rollback. -*/ -SQLITE_API void *sqlite3_commit_hook( - sqlite3 *db, /* Attach the hook to this database */ - int (*xCallback)(void*), /* Function to invoke on each commit */ - void *pArg /* Argument to the function */ -){ - void *pOld; - sqlite3_mutex_enter(db->mutex); - pOld = db->pCommitArg; - db->xCommitCallback = xCallback; - db->pCommitArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pOld; -} - -/* -** Register a callback to be invoked each time a row is updated, -** inserted or deleted using this database connection. -*/ -SQLITE_API void *sqlite3_update_hook( - sqlite3 *db, /* Attach the hook to this database */ - void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), - void *pArg /* Argument to the function */ -){ - void *pRet; - sqlite3_mutex_enter(db->mutex); - pRet = db->pUpdateArg; - db->xUpdateCallback = xCallback; - db->pUpdateArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pRet; -} - -/* -** Register a callback to be invoked each time a transaction is rolled -** back by this database connection. -*/ -SQLITE_API void *sqlite3_rollback_hook( - sqlite3 *db, /* Attach the hook to this database */ - void (*xCallback)(void*), /* Callback function */ - void *pArg /* Argument to the function */ -){ - void *pRet; - sqlite3_mutex_enter(db->mutex); - pRet = db->pRollbackArg; - db->xRollbackCallback = xCallback; - db->pRollbackArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pRet; -} - -#ifndef SQLITE_OMIT_WAL -/* -** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). -** Invoke sqlite3_wal_checkpoint if the number of frames in the log file -** is greater than sqlite3.pWalArg cast to an integer (the value configured by -** wal_autocheckpoint()). -*/ -SQLITE_PRIVATE int sqlite3WalDefaultHook( - void *pClientData, /* Argument */ - sqlite3 *db, /* Connection */ - const char *zDb, /* Database */ - int nFrame /* Size of WAL */ -){ - if( nFrame>=SQLITE_PTR_TO_INT(pClientData) ){ - sqlite3BeginBenignMalloc(); - sqlite3_wal_checkpoint(db, zDb); - sqlite3EndBenignMalloc(); - } - return SQLITE_OK; -} -#endif /* SQLITE_OMIT_WAL */ - -/* -** Configure an sqlite3_wal_hook() callback to automatically checkpoint -** a database after committing a transaction if there are nFrame or -** more frames in the log file. Passing zero or a negative value as the -** nFrame parameter disables automatic checkpoints entirely. -** -** The callback registered by this function replaces any existing callback -** registered using sqlite3_wal_hook(). Likewise, registering a callback -** using sqlite3_wal_hook() disables the automatic checkpoint mechanism -** configured by this function. -*/ -SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ -#ifdef SQLITE_OMIT_WAL - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(nFrame); -#else - if( nFrame>0 ){ - sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame)); - }else{ - sqlite3_wal_hook(db, 0, 0); - } -#endif - return SQLITE_OK; -} - -/* -** Register a callback to be invoked each time a transaction is written -** into the write-ahead-log by this database connection. -*/ -SQLITE_API void *sqlite3_wal_hook( - sqlite3 *db, /* Attach the hook to this db handle */ - int(*xCallback)(void *, sqlite3*, const char*, int), - void *pArg /* First argument passed to xCallback() */ -){ -#ifndef SQLITE_OMIT_WAL - void *pRet; - sqlite3_mutex_enter(db->mutex); - pRet = db->pWalArg; - db->xWalCallback = xCallback; - db->pWalArg = pArg; - sqlite3_mutex_leave(db->mutex); - return pRet; -#else - return 0; -#endif -} - -/* -** Checkpoint database zDb. -*/ -SQLITE_API int sqlite3_wal_checkpoint_v2( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of attached database (or NULL) */ - int eMode, /* SQLITE_CHECKPOINT_* value */ - int *pnLog, /* OUT: Size of WAL log in frames */ - int *pnCkpt /* OUT: Total number of frames checkpointed */ -){ -#ifdef SQLITE_OMIT_WAL - return SQLITE_OK; -#else - int rc; /* Return code */ - int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */ - - /* Initialize the output variables to -1 in case an error occurs. */ - if( pnLog ) *pnLog = -1; - if( pnCkpt ) *pnCkpt = -1; - - assert( SQLITE_CHECKPOINT_FULL>SQLITE_CHECKPOINT_PASSIVE ); - assert( SQLITE_CHECKPOINT_FULLSQLITE_CHECKPOINT_RESTART ){ - return SQLITE_MISUSE; - } - - sqlite3_mutex_enter(db->mutex); - if( zDb && zDb[0] ){ - iDb = sqlite3FindDbName(db, zDb); - } - if( iDb<0 ){ - rc = SQLITE_ERROR; - sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb); - }else{ - rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); - sqlite3Error(db, rc, 0); - } - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -#endif -} - - -/* -** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points -** to contains a zero-length string, all attached databases are -** checkpointed. -*/ -SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ - return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0); -} - -#ifndef SQLITE_OMIT_WAL -/* -** Run a checkpoint on database iDb. This is a no-op if database iDb is -** not currently open in WAL mode. -** -** If a transaction is open on the database being checkpointed, this -** function returns SQLITE_LOCKED and a checkpoint is not attempted. If -** an error occurs while running the checkpoint, an SQLite error code is -** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK. -** -** The mutex on database handle db should be held by the caller. The mutex -** associated with the specific b-tree being checkpointed is taken by -** this function while the checkpoint is running. -** -** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are -** checkpointed. If an error is encountered it is returned immediately - -** no attempt is made to checkpoint any remaining databases. -** -** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. -*/ -SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){ - int rc = SQLITE_OK; /* Return code */ - int i; /* Used to iterate through attached dbs */ - int bBusy = 0; /* True if SQLITE_BUSY has been encountered */ - - assert( sqlite3_mutex_held(db->mutex) ); - assert( !pnLog || *pnLog==-1 ); - assert( !pnCkpt || *pnCkpt==-1 ); - - for(i=0; inDb && rc==SQLITE_OK; i++){ - if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){ - rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt); - pnLog = 0; - pnCkpt = 0; - if( rc==SQLITE_BUSY ){ - bBusy = 1; - rc = SQLITE_OK; - } - } - } - - return (rc==SQLITE_OK && bBusy) ? SQLITE_BUSY : rc; -} -#endif /* SQLITE_OMIT_WAL */ - -/* -** This function returns true if main-memory should be used instead of -** a temporary file for transient pager files and statement journals. -** The value returned depends on the value of db->temp_store (runtime -** parameter) and the compile time value of SQLITE_TEMP_STORE. The -** following table describes the relationship between these two values -** and this functions return value. -** -** SQLITE_TEMP_STORE db->temp_store Location of temporary database -** ----------------- -------------- ------------------------------ -** 0 any file (return 0) -** 1 1 file (return 0) -** 1 2 memory (return 1) -** 1 0 file (return 0) -** 2 1 file (return 0) -** 2 2 memory (return 1) -** 2 0 memory (return 1) -** 3 any memory (return 1) -*/ -SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){ -#if SQLITE_TEMP_STORE==1 - return ( db->temp_store==2 ); -#endif -#if SQLITE_TEMP_STORE==2 - return ( db->temp_store!=1 ); -#endif -#if SQLITE_TEMP_STORE==3 - return 1; -#endif -#if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3 - return 0; -#endif -} - -/* -** Return UTF-8 encoded English language explanation of the most recent -** error. -*/ -SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ - const char *z; - if( !db ){ - return sqlite3ErrStr(SQLITE_NOMEM); - } - if( !sqlite3SafetyCheckSickOrOk(db) ){ - return sqlite3ErrStr(SQLITE_MISUSE_BKPT); - } - sqlite3_mutex_enter(db->mutex); - if( db->mallocFailed ){ - z = sqlite3ErrStr(SQLITE_NOMEM); - }else{ - z = (char*)sqlite3_value_text(db->pErr); - assert( !db->mallocFailed ); - if( z==0 ){ - z = sqlite3ErrStr(db->errCode); - } - } - sqlite3_mutex_leave(db->mutex); - return z; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Return UTF-16 encoded English language explanation of the most recent -** error. -*/ -SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ - static const u16 outOfMem[] = { - 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0 - }; - static const u16 misuse[] = { - 'l', 'i', 'b', 'r', 'a', 'r', 'y', ' ', - 'r', 'o', 'u', 't', 'i', 'n', 'e', ' ', - 'c', 'a', 'l', 'l', 'e', 'd', ' ', - 'o', 'u', 't', ' ', - 'o', 'f', ' ', - 's', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 0 - }; - - const void *z; - if( !db ){ - return (void *)outOfMem; - } - if( !sqlite3SafetyCheckSickOrOk(db) ){ - return (void *)misuse; - } - sqlite3_mutex_enter(db->mutex); - if( db->mallocFailed ){ - z = (void *)outOfMem; - }else{ - z = sqlite3_value_text16(db->pErr); - if( z==0 ){ - sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), - SQLITE_UTF8, SQLITE_STATIC); - z = sqlite3_value_text16(db->pErr); - } - /* A malloc() may have failed within the call to sqlite3_value_text16() - ** above. If this is the case, then the db->mallocFailed flag needs to - ** be cleared before returning. Do this directly, instead of via - ** sqlite3ApiExit(), to avoid setting the database handle error message. - */ - db->mallocFailed = 0; - } - sqlite3_mutex_leave(db->mutex); - return z; -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Return the most recent error code generated by an SQLite routine. If NULL is -** passed to this function, we assume a malloc() failed during sqlite3_open(). -*/ -SQLITE_API int sqlite3_errcode(sqlite3 *db){ - if( db && !sqlite3SafetyCheckSickOrOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - if( !db || db->mallocFailed ){ - return SQLITE_NOMEM; - } - return db->errCode & db->errMask; -} -SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){ - if( db && !sqlite3SafetyCheckSickOrOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - if( !db || db->mallocFailed ){ - return SQLITE_NOMEM; - } - return db->errCode; -} - -/* -** Return a string that describes the kind of error specified in the -** argument. For now, this simply calls the internal sqlite3ErrStr() -** function. -*/ -SQLITE_API const char *sqlite3_errstr(int rc){ - return sqlite3ErrStr(rc); -} - -/* -** Create a new collating function for database "db". The name is zName -** and the encoding is enc. -*/ -static int createCollation( - sqlite3* db, - const char *zName, - u8 enc, - void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDel)(void*) -){ - CollSeq *pColl; - int enc2; - int nName = sqlite3Strlen30(zName); - - assert( sqlite3_mutex_held(db->mutex) ); - - /* If SQLITE_UTF16 is specified as the encoding type, transform this - ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the - ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. - */ - enc2 = enc; - testcase( enc2==SQLITE_UTF16 ); - testcase( enc2==SQLITE_UTF16_ALIGNED ); - if( enc2==SQLITE_UTF16 || enc2==SQLITE_UTF16_ALIGNED ){ - enc2 = SQLITE_UTF16NATIVE; - } - if( enc2SQLITE_UTF16BE ){ - return SQLITE_MISUSE_BKPT; - } - - /* Check if this call is removing or replacing an existing collation - ** sequence. If so, and there are active VMs, return busy. If there - ** are no active VMs, invalidate any pre-compiled statements. - */ - pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); - if( pColl && pColl->xCmp ){ - if( db->activeVdbeCnt ){ - sqlite3Error(db, SQLITE_BUSY, - "unable to delete/modify collation sequence due to active statements"); - return SQLITE_BUSY; - } - sqlite3ExpirePreparedStatements(db); - - /* If collation sequence pColl was created directly by a call to - ** sqlite3_create_collation, and not generated by synthCollSeq(), - ** then any copies made by synthCollSeq() need to be invalidated. - ** Also, collation destructor - CollSeq.xDel() - function may need - ** to be called. - */ - if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ - CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, nName); - int j; - for(j=0; j<3; j++){ - CollSeq *p = &aColl[j]; - if( p->enc==pColl->enc ){ - if( p->xDel ){ - p->xDel(p->pUser); - } - p->xCmp = 0; - } - } - } - } - - pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1); - if( pColl==0 ) return SQLITE_NOMEM; - pColl->xCmp = xCompare; - pColl->pUser = pCtx; - pColl->xDel = xDel; - pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED)); - sqlite3Error(db, SQLITE_OK, 0); - return SQLITE_OK; -} - - -/* -** This array defines hard upper bounds on limit values. The -** initializer must be kept in sync with the SQLITE_LIMIT_* -** #defines in sqlite3.h. -*/ -static const int aHardLimit[] = { - SQLITE_MAX_LENGTH, - SQLITE_MAX_SQL_LENGTH, - SQLITE_MAX_COLUMN, - SQLITE_MAX_EXPR_DEPTH, - SQLITE_MAX_COMPOUND_SELECT, - SQLITE_MAX_VDBE_OP, - SQLITE_MAX_FUNCTION_ARG, - SQLITE_MAX_ATTACHED, - SQLITE_MAX_LIKE_PATTERN_LENGTH, - SQLITE_MAX_VARIABLE_NUMBER, - SQLITE_MAX_TRIGGER_DEPTH, -}; - -/* -** Make sure the hard limits are set to reasonable values -*/ -#if SQLITE_MAX_LENGTH<100 -# error SQLITE_MAX_LENGTH must be at least 100 -#endif -#if SQLITE_MAX_SQL_LENGTH<100 -# error SQLITE_MAX_SQL_LENGTH must be at least 100 -#endif -#if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH -# error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH -#endif -#if SQLITE_MAX_COMPOUND_SELECT<2 -# error SQLITE_MAX_COMPOUND_SELECT must be at least 2 -#endif -#if SQLITE_MAX_VDBE_OP<40 -# error SQLITE_MAX_VDBE_OP must be at least 40 -#endif -#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000 -# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000 -#endif -#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>62 -# error SQLITE_MAX_ATTACHED must be between 0 and 62 -#endif -#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1 -# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1 -#endif -#if SQLITE_MAX_COLUMN>32767 -# error SQLITE_MAX_COLUMN must not exceed 32767 -#endif -#if SQLITE_MAX_TRIGGER_DEPTH<1 -# error SQLITE_MAX_TRIGGER_DEPTH must be at least 1 -#endif - - -/* -** Change the value of a limit. Report the old value. -** If an invalid limit index is supplied, report -1. -** Make no changes but still report the old value if the -** new limit is negative. -** -** A new lower limit does not shrink existing constructs. -** It merely prevents new constructs that exceed the limit -** from forming. -*/ -SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ - int oldLimit; - - - /* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE_LIMIT_NAME - ** there is a hard upper bound set at compile-time by a C preprocessor - ** macro called SQLITE_MAX_NAME. (The "_LIMIT_" in the name is changed to - ** "_MAX_".) - */ - assert( aHardLimit[SQLITE_LIMIT_LENGTH]==SQLITE_MAX_LENGTH ); - assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH ); - assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN ); - assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH ); - assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT); - assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP ); - assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG ); - assert( aHardLimit[SQLITE_LIMIT_ATTACHED]==SQLITE_MAX_ATTACHED ); - assert( aHardLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]== - SQLITE_MAX_LIKE_PATTERN_LENGTH ); - assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER); - assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH ); - assert( SQLITE_LIMIT_TRIGGER_DEPTH==(SQLITE_N_LIMIT-1) ); - - - if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ - return -1; - } - oldLimit = db->aLimit[limitId]; - if( newLimit>=0 ){ /* IMP: R-52476-28732 */ - if( newLimit>aHardLimit[limitId] ){ - newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ - } - db->aLimit[limitId] = newLimit; - } - return oldLimit; /* IMP: R-53341-35419 */ -} - -/* -** This function is used to parse both URIs and non-URI filenames passed by the -** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database -** URIs specified as part of ATTACH statements. -** -** The first argument to this function is the name of the VFS to use (or -** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx" -** query parameter. The second argument contains the URI (or non-URI filename) -** itself. When this function is called the *pFlags variable should contain -** the default flags to open the database handle with. The value stored in -** *pFlags may be updated before returning if the URI filename contains -** "cache=xxx" or "mode=xxx" query parameters. -** -** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to -** the VFS that should be used to open the database file. *pzFile is set to -** point to a buffer containing the name of the file to open. It is the -** responsibility of the caller to eventually call sqlite3_free() to release -** this buffer. -** -** If an error occurs, then an SQLite error code is returned and *pzErrMsg -** may be set to point to a buffer containing an English language error -** message. It is the responsibility of the caller to eventually release -** this buffer by calling sqlite3_free(). -*/ -SQLITE_PRIVATE int sqlite3ParseUri( - const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */ - const char *zUri, /* Nul-terminated URI to parse */ - unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */ - sqlite3_vfs **ppVfs, /* OUT: VFS to use */ - char **pzFile, /* OUT: Filename component of URI */ - char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */ -){ - int rc = SQLITE_OK; - unsigned int flags = *pFlags; - const char *zVfs = zDefaultVfs; - char *zFile; - char c; - int nUri = sqlite3Strlen30(zUri); - - assert( *pzErrMsg==0 ); - - if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri) - && nUri>=5 && memcmp(zUri, "file:", 5)==0 - ){ - char *zOpt; - int eState; /* Parser state when parsing URI */ - int iIn; /* Input character index */ - int iOut = 0; /* Output character index */ - int nByte = nUri+2; /* Bytes of space to allocate */ - - /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen - ** method that there may be extra parameters following the file-name. */ - flags |= SQLITE_OPEN_URI; - - for(iIn=0; iIn=0 && octet<256 ); - if( octet==0 ){ - /* This branch is taken when "%00" appears within the URI. In this - ** case we ignore all text in the remainder of the path, name or - ** value currently being parsed. So ignore the current character - ** and skip to the next "?", "=" or "&", as appropriate. */ - while( (c = zUri[iIn])!=0 && c!='#' - && (eState!=0 || c!='?') - && (eState!=1 || (c!='=' && c!='&')) - && (eState!=2 || c!='&') - ){ - iIn++; - } - continue; - } - c = octet; - }else if( eState==1 && (c=='&' || c=='=') ){ - if( zFile[iOut-1]==0 ){ - /* An empty option name. Ignore this option altogether. */ - while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++; - continue; - } - if( c=='&' ){ - zFile[iOut++] = '\0'; - }else{ - eState = 2; - } - c = 0; - }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){ - c = 0; - eState = 1; - } - zFile[iOut++] = c; - } - if( eState==1 ) zFile[iOut++] = '\0'; - zFile[iOut++] = '\0'; - zFile[iOut++] = '\0'; - - /* Check if there were any options specified that should be interpreted - ** here. Options that are interpreted here include "vfs" and those that - ** correspond to flags that may be passed to the sqlite3_open_v2() - ** method. */ - zOpt = &zFile[sqlite3Strlen30(zFile)+1]; - while( zOpt[0] ){ - int nOpt = sqlite3Strlen30(zOpt); - char *zVal = &zOpt[nOpt+1]; - int nVal = sqlite3Strlen30(zVal); - - if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){ - zVfs = zVal; - }else{ - struct OpenMode { - const char *z; - int mode; - } *aMode = 0; - char *zModeType = 0; - int mask = 0; - int limit = 0; - - if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){ - static struct OpenMode aCacheMode[] = { - { "shared", SQLITE_OPEN_SHAREDCACHE }, - { "private", SQLITE_OPEN_PRIVATECACHE }, - { 0, 0 } - }; - - mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE; - aMode = aCacheMode; - limit = mask; - zModeType = "cache"; - } - if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){ - static struct OpenMode aOpenMode[] = { - { "ro", SQLITE_OPEN_READONLY }, - { "rw", SQLITE_OPEN_READWRITE }, - { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE }, - { "memory", SQLITE_OPEN_MEMORY }, - { 0, 0 } - }; - - mask = SQLITE_OPEN_READONLY | SQLITE_OPEN_READWRITE - | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY; - aMode = aOpenMode; - limit = mask & flags; - zModeType = "access"; - } - - if( aMode ){ - int i; - int mode = 0; - for(i=0; aMode[i].z; i++){ - const char *z = aMode[i].z; - if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){ - mode = aMode[i].mode; - break; - } - } - if( mode==0 ){ - *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal); - rc = SQLITE_ERROR; - goto parse_uri_out; - } - if( (mode & ~SQLITE_OPEN_MEMORY)>limit ){ - *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s", - zModeType, zVal); - rc = SQLITE_PERM; - goto parse_uri_out; - } - flags = (flags & ~mask) | mode; - } - } - - zOpt = &zVal[nVal+1]; - } - - }else{ - zFile = sqlite3_malloc(nUri+2); - if( !zFile ) return SQLITE_NOMEM; - memcpy(zFile, zUri, nUri); - zFile[nUri] = '\0'; - zFile[nUri+1] = '\0'; - flags &= ~SQLITE_OPEN_URI; - } - - *ppVfs = sqlite3_vfs_find(zVfs); - if( *ppVfs==0 ){ - *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs); - rc = SQLITE_ERROR; - } - parse_uri_out: - if( rc!=SQLITE_OK ){ - sqlite3_free(zFile); - zFile = 0; - } - *pFlags = flags; - *pzFile = zFile; - return rc; -} - - -/* -** This routine does the work of opening a database on behalf of -** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" -** is UTF-8 encoded. -*/ -static int openDatabase( - const char *zFilename, /* Database filename UTF-8 encoded */ - sqlite3 **ppDb, /* OUT: Returned database handle */ - unsigned int flags, /* Operational flags */ - const char *zVfs /* Name of the VFS to use */ -){ - sqlite3 *db; /* Store allocated handle here */ - int rc; /* Return code */ - int isThreadsafe; /* True for threadsafe connections */ - char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */ - char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */ - - *ppDb = 0; -#ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ) return rc; -#endif - - /* Only allow sensible combinations of bits in the flags argument. - ** Throw an error if any non-sense combination is used. If we - ** do not block illegal combinations here, it could trigger - ** assert() statements in deeper layers. Sensible combinations - ** are: - ** - ** 1: SQLITE_OPEN_READONLY - ** 2: SQLITE_OPEN_READWRITE - ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE - */ - assert( SQLITE_OPEN_READONLY == 0x01 ); - assert( SQLITE_OPEN_READWRITE == 0x02 ); - assert( SQLITE_OPEN_CREATE == 0x04 ); - testcase( (1<<(flags&7))==0x02 ); /* READONLY */ - testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ - testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ - if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT; - - if( sqlite3GlobalConfig.bCoreMutex==0 ){ - isThreadsafe = 0; - }else if( flags & SQLITE_OPEN_NOMUTEX ){ - isThreadsafe = 0; - }else if( flags & SQLITE_OPEN_FULLMUTEX ){ - isThreadsafe = 1; - }else{ - isThreadsafe = sqlite3GlobalConfig.bFullMutex; - } - if( flags & SQLITE_OPEN_PRIVATECACHE ){ - flags &= ~SQLITE_OPEN_SHAREDCACHE; - }else if( sqlite3GlobalConfig.sharedCacheEnabled ){ - flags |= SQLITE_OPEN_SHAREDCACHE; - } - - /* Remove harmful bits from the flags parameter - ** - ** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were - ** dealt with in the previous code block. Besides these, the only - ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY, - ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE, - ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask - ** off all other flags. - */ - flags &= ~( SQLITE_OPEN_DELETEONCLOSE | - SQLITE_OPEN_EXCLUSIVE | - SQLITE_OPEN_MAIN_DB | - SQLITE_OPEN_TEMP_DB | - SQLITE_OPEN_TRANSIENT_DB | - SQLITE_OPEN_MAIN_JOURNAL | - SQLITE_OPEN_TEMP_JOURNAL | - SQLITE_OPEN_SUBJOURNAL | - SQLITE_OPEN_MASTER_JOURNAL | - SQLITE_OPEN_NOMUTEX | - SQLITE_OPEN_FULLMUTEX | - SQLITE_OPEN_WAL - ); - - /* Allocate the sqlite data structure */ - db = sqlite3MallocZero( sizeof(sqlite3) ); - if( db==0 ) goto opendb_out; - if( isThreadsafe ){ - db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); - if( db->mutex==0 ){ - sqlite3_free(db); - db = 0; - goto opendb_out; - } - } - sqlite3_mutex_enter(db->mutex); - db->errMask = 0xff; - db->nDb = 2; - db->magic = SQLITE_MAGIC_BUSY; - db->aDb = db->aDbStatic; - - assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); - memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); - db->autoCommit = 1; - db->nextAutovac = -1; - db->szMmap = sqlite3GlobalConfig.szMmap; - db->nextPagesize = 0; - db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger -#if SQLITE_DEFAULT_FILE_FORMAT<4 - | SQLITE_LegacyFileFmt -#endif -#ifdef SQLITE_ENABLE_LOAD_EXTENSION - | SQLITE_LoadExtension -#endif -#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS - | SQLITE_RecTriggers -#endif -#if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS - | SQLITE_ForeignKeys -#endif - ; - sqlite3HashInit(&db->aCollSeq); -#ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3HashInit(&db->aModule); -#endif - - /* Add the default collation sequence BINARY. BINARY works for both UTF-8 - ** and UTF-16, so add a version for each to avoid any unnecessary - ** conversions. The only error that can occur here is a malloc() failure. - */ - createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0); - createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0); - createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0); - createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); - if( db->mallocFailed ){ - goto opendb_out; - } - db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0); - assert( db->pDfltColl!=0 ); - - /* Also add a UTF-8 case-insensitive collation sequence. */ - createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); - - /* Parse the filename/URI argument. */ - db->openFlags = flags; - rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; - sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg); - sqlite3_free(zErrMsg); - goto opendb_out; - } - - /* Open the backend database driver */ - rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, - flags | SQLITE_OPEN_MAIN_DB); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_IOERR_NOMEM ){ - rc = SQLITE_NOMEM; - } - sqlite3Error(db, rc, 0); - goto opendb_out; - } - db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); - db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); - - - /* The default safety_level for the main database is 'full'; for the temp - ** database it is 'NONE'. This matches the pager layer defaults. - */ - db->aDb[0].zName = "main"; - db->aDb[0].safety_level = 3; - db->aDb[1].zName = "temp"; - db->aDb[1].safety_level = 1; - - db->magic = SQLITE_MAGIC_OPEN; - if( db->mallocFailed ){ - goto opendb_out; - } - - /* Register all built-in functions, but do not attempt to read the - ** database schema yet. This is delayed until the first time the database - ** is accessed. - */ - sqlite3Error(db, SQLITE_OK, 0); - sqlite3RegisterBuiltinFunctions(db); - - /* Load automatic extensions - extensions that have been registered - ** using the sqlite3_automatic_extension() API. - */ - rc = sqlite3_errcode(db); - if( rc==SQLITE_OK ){ - sqlite3AutoLoadExtensions(db); - rc = sqlite3_errcode(db); - if( rc!=SQLITE_OK ){ - goto opendb_out; - } - } - -#ifdef SQLITE_ENABLE_FTS1 - if( !db->mallocFailed ){ - extern int sqlite3Fts1Init(sqlite3*); - rc = sqlite3Fts1Init(db); - } -#endif - -#ifdef SQLITE_ENABLE_FTS2 - if( !db->mallocFailed && rc==SQLITE_OK ){ - extern int sqlite3Fts2Init(sqlite3*); - rc = sqlite3Fts2Init(db); - } -#endif - -#ifdef SQLITE_ENABLE_FTS3 - if( !db->mallocFailed && rc==SQLITE_OK ){ - rc = sqlite3Fts3Init(db); - } -#endif - -#ifdef SQLITE_ENABLE_ICU - if( !db->mallocFailed && rc==SQLITE_OK ){ - rc = sqlite3IcuInit(db); - } -#endif - -#ifdef SQLITE_ENABLE_RTREE - if( !db->mallocFailed && rc==SQLITE_OK){ - rc = sqlite3RtreeInit(db); - } -#endif - - sqlite3Error(db, rc, 0); - - /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking - ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking - ** mode. Doing nothing at all also makes NORMAL the default. - */ -#ifdef SQLITE_DEFAULT_LOCKING_MODE - db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; - sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), - SQLITE_DEFAULT_LOCKING_MODE); -#endif - - /* Enable the lookaside-malloc subsystem */ - setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, - sqlite3GlobalConfig.nLookaside); - - sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT); - -opendb_out: - sqlite3_free(zOpen); - if( db ){ - assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); - sqlite3_mutex_leave(db->mutex); - } - rc = sqlite3_errcode(db); - assert( db!=0 || rc==SQLITE_NOMEM ); - if( rc==SQLITE_NOMEM ){ - sqlite3_close(db); - db = 0; - }else if( rc!=SQLITE_OK ){ - db->magic = SQLITE_MAGIC_SICK; - } - *ppDb = db; -#ifdef SQLITE_ENABLE_SQLLOG - if( sqlite3GlobalConfig.xSqllog ){ - /* Opening a db handle. Fourth parameter is passed 0. */ - void *pArg = sqlite3GlobalConfig.pSqllogArg; - sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); - } -#endif - return sqlite3ApiExit(0, rc); -} - -/* -** Open a new database handle. -*/ -SQLITE_API int sqlite3_open( - const char *zFilename, - sqlite3 **ppDb -){ - return openDatabase(zFilename, ppDb, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); -} -SQLITE_API int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -){ - return openDatabase(filename, ppDb, (unsigned int)flags, zVfs); -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Open a new database handle. -*/ -SQLITE_API int sqlite3_open16( - const void *zFilename, - sqlite3 **ppDb -){ - char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ - sqlite3_value *pVal; - int rc; - - assert( zFilename ); - assert( ppDb ); - *ppDb = 0; -#ifndef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ) return rc; -#endif - pVal = sqlite3ValueNew(0); - sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); - zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); - if( zFilename8 ){ - rc = openDatabase(zFilename8, ppDb, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); - assert( *ppDb || rc==SQLITE_NOMEM ); - if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ - ENC(*ppDb) = SQLITE_UTF16NATIVE; - } - }else{ - rc = SQLITE_NOMEM; - } - sqlite3ValueFree(pVal); - - return sqlite3ApiExit(0, rc); -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Register a new collation sequence with the database handle db. -*/ -SQLITE_API int sqlite3_create_collation( - sqlite3* db, - const char *zName, - int enc, - void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*) -){ - int rc; - sqlite3_mutex_enter(db->mutex); - assert( !db->mallocFailed ); - rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, 0); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Register a new collation sequence with the database handle db. -*/ -SQLITE_API int sqlite3_create_collation_v2( - sqlite3* db, - const char *zName, - int enc, - void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDel)(void*) -){ - int rc; - sqlite3_mutex_enter(db->mutex); - assert( !db->mallocFailed ); - rc = createCollation(db, zName, (u8)enc, pCtx, xCompare, xDel); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Register a new collation sequence with the database handle db. -*/ -SQLITE_API int sqlite3_create_collation16( - sqlite3* db, - const void *zName, - int enc, - void* pCtx, - int(*xCompare)(void*,int,const void*,int,const void*) -){ - int rc = SQLITE_OK; - char *zName8; - sqlite3_mutex_enter(db->mutex); - assert( !db->mallocFailed ); - zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE); - if( zName8 ){ - rc = createCollation(db, zName8, (u8)enc, pCtx, xCompare, 0); - sqlite3DbFree(db, zName8); - } - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} -#endif /* SQLITE_OMIT_UTF16 */ - -/* -** Register a collation sequence factory callback with the database handle -** db. Replace any previously installed collation sequence factory. -*/ -SQLITE_API int sqlite3_collation_needed( - sqlite3 *db, - void *pCollNeededArg, - void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) -){ - sqlite3_mutex_enter(db->mutex); - db->xCollNeeded = xCollNeeded; - db->xCollNeeded16 = 0; - db->pCollNeededArg = pCollNeededArg; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -#ifndef SQLITE_OMIT_UTF16 -/* -** Register a collation sequence factory callback with the database handle -** db. Replace any previously installed collation sequence factory. -*/ -SQLITE_API int sqlite3_collation_needed16( - sqlite3 *db, - void *pCollNeededArg, - void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) -){ - sqlite3_mutex_enter(db->mutex); - db->xCollNeeded = 0; - db->xCollNeeded16 = xCollNeeded16; - db->pCollNeededArg = pCollNeededArg; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} -#endif /* SQLITE_OMIT_UTF16 */ - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** This function is now an anachronism. It used to be used to recover from a -** malloc() failure, but SQLite now does this automatically. -*/ -SQLITE_API int sqlite3_global_recover(void){ - return SQLITE_OK; -} -#endif - -/* -** Test to see whether or not the database connection is in autocommit -** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on -** by default. Autocommit is disabled by a BEGIN statement and reenabled -** by the next COMMIT or ROLLBACK. -** -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** -*/ -SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){ - return db->autoCommit; -} - -/* -** The following routines are subtitutes for constants SQLITE_CORRUPT, -** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error -** constants. They server two purposes: -** -** 1. Serve as a convenient place to set a breakpoint in a debugger -** to detect when version error conditions occurs. -** -** 2. Invoke sqlite3_log() to provide the source code location where -** a low-level error is first detected. -*/ -SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_CORRUPT, - "database corruption at line %d of [%.10s]", - lineno, 20+sqlite3_sourceid()); - return SQLITE_CORRUPT; -} -SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_MISUSE, - "misuse at line %d of [%.10s]", - lineno, 20+sqlite3_sourceid()); - return SQLITE_MISUSE; -} -SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_CANTOPEN, - "cannot open file at line %d of [%.10s]", - lineno, 20+sqlite3_sourceid()); - return SQLITE_CANTOPEN; -} - - -#ifndef SQLITE_OMIT_DEPRECATED -/* -** This is a convenience routine that makes sure that all thread-specific -** data for this thread has been deallocated. -** -** SQLite no longer uses thread-specific data so this routine is now a -** no-op. It is retained for historical compatibility. -*/ -SQLITE_API void sqlite3_thread_cleanup(void){ -} -#endif - -/* -** Return meta information about a specific column of a database table. -** See comment in sqlite3.h (sqlite.h.in) for details. -*/ -#ifdef SQLITE_ENABLE_COLUMN_METADATA -SQLITE_API int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -){ - int rc; - char *zErrMsg = 0; - Table *pTab = 0; - Column *pCol = 0; - int iCol; - - char const *zDataType = 0; - char const *zCollSeq = 0; - int notnull = 0; - int primarykey = 0; - int autoinc = 0; - - /* Ensure the database schema has been loaded */ - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeEnterAll(db); - rc = sqlite3Init(db, &zErrMsg); - if( SQLITE_OK!=rc ){ - goto error_out; - } - - /* Locate the table in question */ - pTab = sqlite3FindTable(db, zTableName, zDbName); - if( !pTab || pTab->pSelect ){ - pTab = 0; - goto error_out; - } - - /* Find the column for which info is requested */ - if( sqlite3IsRowid(zColumnName) ){ - iCol = pTab->iPKey; - if( iCol>=0 ){ - pCol = &pTab->aCol[iCol]; - } - }else{ - for(iCol=0; iColnCol; iCol++){ - pCol = &pTab->aCol[iCol]; - if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ - break; - } - } - if( iCol==pTab->nCol ){ - pTab = 0; - goto error_out; - } - } - - /* The following block stores the meta information that will be returned - ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey - ** and autoinc. At this point there are two possibilities: - ** - ** 1. The specified column name was rowid", "oid" or "_rowid_" - ** and there is no explicitly declared IPK column. - ** - ** 2. The table is not a view and the column name identified an - ** explicitly declared column. Copy meta information from *pCol. - */ - if( pCol ){ - zDataType = pCol->zType; - zCollSeq = pCol->zColl; - notnull = pCol->notNull!=0; - primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; - autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0; - }else{ - zDataType = "INTEGER"; - primarykey = 1; - } - if( !zCollSeq ){ - zCollSeq = "BINARY"; - } - -error_out: - sqlite3BtreeLeaveAll(db); - - /* Whether the function call succeeded or failed, set the output parameters - ** to whatever their local counterparts contain. If an error did occur, - ** this has the effect of zeroing all output parameters. - */ - if( pzDataType ) *pzDataType = zDataType; - if( pzCollSeq ) *pzCollSeq = zCollSeq; - if( pNotNull ) *pNotNull = notnull; - if( pPrimaryKey ) *pPrimaryKey = primarykey; - if( pAutoinc ) *pAutoinc = autoinc; - - if( SQLITE_OK==rc && !pTab ){ - sqlite3DbFree(db, zErrMsg); - zErrMsg = sqlite3MPrintf(db, "no such table column: %s.%s", zTableName, - zColumnName); - rc = SQLITE_ERROR; - } - sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); - sqlite3DbFree(db, zErrMsg); - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} -#endif - -/* -** Sleep for a little while. Return the amount of time slept. -*/ -SQLITE_API int sqlite3_sleep(int ms){ - sqlite3_vfs *pVfs; - int rc; - pVfs = sqlite3_vfs_find(0); - if( pVfs==0 ) return 0; - - /* This function works in milliseconds, but the underlying OsSleep() - ** API uses microseconds. Hence the 1000's. - */ - rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000); - return rc; -} - -/* -** Enable or disable the extended result codes. -*/ -SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ - sqlite3_mutex_enter(db->mutex); - db->errMask = onoff ? 0xffffffff : 0xff; - sqlite3_mutex_leave(db->mutex); - return SQLITE_OK; -} - -/* -** Invoke the xFileControl method on a particular database. -*/ -SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ - int rc = SQLITE_ERROR; - Btree *pBtree; - - sqlite3_mutex_enter(db->mutex); - pBtree = sqlite3DbNameToBtree(db, zDbName); - if( pBtree ){ - Pager *pPager; - sqlite3_file *fd; - sqlite3BtreeEnter(pBtree); - pPager = sqlite3BtreePager(pBtree); - assert( pPager!=0 ); - fd = sqlite3PagerFile(pPager); - assert( fd!=0 ); - if( op==SQLITE_FCNTL_FILE_POINTER ){ - *(sqlite3_file**)pArg = fd; - rc = SQLITE_OK; - }else if( fd->pMethods ){ - rc = sqlite3OsFileControl(fd, op, pArg); - }else{ - rc = SQLITE_NOTFOUND; - } - sqlite3BtreeLeave(pBtree); - } - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** Interface to the testing logic. -*/ -SQLITE_API int sqlite3_test_control(int op, ...){ - int rc = 0; -#ifndef SQLITE_OMIT_BUILTIN_TEST - va_list ap; - va_start(ap, op); - switch( op ){ - - /* - ** Save the current state of the PRNG. - */ - case SQLITE_TESTCTRL_PRNG_SAVE: { - sqlite3PrngSaveState(); - break; - } - - /* - ** Restore the state of the PRNG to the last state saved using - ** PRNG_SAVE. If PRNG_SAVE has never before been called, then - ** this verb acts like PRNG_RESET. - */ - case SQLITE_TESTCTRL_PRNG_RESTORE: { - sqlite3PrngRestoreState(); - break; - } - - /* - ** Reset the PRNG back to its uninitialized state. The next call - ** to sqlite3_randomness() will reseed the PRNG using a single call - ** to the xRandomness method of the default VFS. - */ - case SQLITE_TESTCTRL_PRNG_RESET: { - sqlite3PrngResetState(); - break; - } - - /* - ** sqlite3_test_control(BITVEC_TEST, size, program) - ** - ** Run a test against a Bitvec object of size. The program argument - ** is an array of integers that defines the test. Return -1 on a - ** memory allocation error, 0 on success, or non-zero for an error. - ** See the sqlite3BitvecBuiltinTest() for additional information. - */ - case SQLITE_TESTCTRL_BITVEC_TEST: { - int sz = va_arg(ap, int); - int *aProg = va_arg(ap, int*); - rc = sqlite3BitvecBuiltinTest(sz, aProg); - break; - } - - /* - ** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd) - ** - ** Register hooks to call to indicate which malloc() failures - ** are benign. - */ - case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: { - typedef void (*void_function)(void); - void_function xBenignBegin; - void_function xBenignEnd; - xBenignBegin = va_arg(ap, void_function); - xBenignEnd = va_arg(ap, void_function); - sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd); - break; - } - - /* - ** sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, unsigned int X) - ** - ** Set the PENDING byte to the value in the argument, if X>0. - ** Make no changes if X==0. Return the value of the pending byte - ** as it existing before this routine was called. - ** - ** IMPORTANT: Changing the PENDING byte from 0x40000000 results in - ** an incompatible database file format. Changing the PENDING byte - ** while any database connection is open results in undefined and - ** dileterious behavior. - */ - case SQLITE_TESTCTRL_PENDING_BYTE: { - rc = PENDING_BYTE; -#ifndef SQLITE_OMIT_WSD - { - unsigned int newVal = va_arg(ap, unsigned int); - if( newVal ) sqlite3PendingByte = newVal; - } -#endif - break; - } - - /* - ** sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, int X) - ** - ** This action provides a run-time test to see whether or not - ** assert() was enabled at compile-time. If X is true and assert() - ** is enabled, then the return value is true. If X is true and - ** assert() is disabled, then the return value is zero. If X is - ** false and assert() is enabled, then the assertion fires and the - ** process aborts. If X is false and assert() is disabled, then the - ** return value is zero. - */ - case SQLITE_TESTCTRL_ASSERT: { - volatile int x = 0; - assert( (x = va_arg(ap,int))!=0 ); - rc = x; - break; - } - - - /* - ** sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, int X) - ** - ** This action provides a run-time test to see how the ALWAYS and - ** NEVER macros were defined at compile-time. - ** - ** The return value is ALWAYS(X). - ** - ** The recommended test is X==2. If the return value is 2, that means - ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the - ** default setting. If the return value is 1, then ALWAYS() is either - ** hard-coded to true or else it asserts if its argument is false. - ** The first behavior (hard-coded to true) is the case if - ** SQLITE_TESTCTRL_ASSERT shows that assert() is disabled and the second - ** behavior (assert if the argument to ALWAYS() is false) is the case if - ** SQLITE_TESTCTRL_ASSERT shows that assert() is enabled. - ** - ** The run-time test procedure might look something like this: - ** - ** if( sqlite3_test_control(SQLITE_TESTCTRL_ALWAYS, 2)==2 ){ - ** // ALWAYS() and NEVER() are no-op pass-through macros - ** }else if( sqlite3_test_control(SQLITE_TESTCTRL_ASSERT, 1) ){ - ** // ALWAYS(x) asserts that x is true. NEVER(x) asserts x is false. - ** }else{ - ** // ALWAYS(x) is a constant 1. NEVER(x) is a constant 0. - ** } - */ - case SQLITE_TESTCTRL_ALWAYS: { - int x = va_arg(ap,int); - rc = ALWAYS(x); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N) - ** - ** Set the nReserve size to N for the main database on the database - ** connection db. - */ - case SQLITE_TESTCTRL_RESERVE: { - sqlite3 *db = va_arg(ap, sqlite3*); - int x = va_arg(ap,int); - sqlite3_mutex_enter(db->mutex); - sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0); - sqlite3_mutex_leave(db->mutex); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N) - ** - ** Enable or disable various optimizations for testing purposes. The - ** argument N is a bitmask of optimizations to be disabled. For normal - ** operation N should be 0. The idea is that a test program (like the - ** SQL Logic Test or SLT test module) can run the same SQL multiple times - ** with various optimizations disabled to verify that the same answer - ** is obtained in every case. - */ - case SQLITE_TESTCTRL_OPTIMIZATIONS: { - sqlite3 *db = va_arg(ap, sqlite3*); - db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff); - break; - } - -#ifdef SQLITE_N_KEYWORD - /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) - ** - ** If zWord is a keyword recognized by the parser, then return the - ** number of keywords. Or if zWord is not a keyword, return 0. - ** - ** This test feature is only available in the amalgamation since - ** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite - ** is built using separate source files. - */ - case SQLITE_TESTCTRL_ISKEYWORD: { - const char *zWord = va_arg(ap, const char*); - int n = sqlite3Strlen30(zWord); - rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0; - break; - } -#endif - - /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree); - ** - ** Pass pFree into sqlite3ScratchFree(). - ** If sz>0 then allocate a scratch buffer into pNew. - */ - case SQLITE_TESTCTRL_SCRATCHMALLOC: { - void *pFree, **ppNew; - int sz; - sz = va_arg(ap, int); - ppNew = va_arg(ap, void**); - pFree = va_arg(ap, void*); - if( sz ) *ppNew = sqlite3ScratchMalloc(sz); - sqlite3ScratchFree(pFree); - break; - } - - /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); - ** - ** If parameter onoff is non-zero, configure the wrappers so that all - ** subsequent calls to localtime() and variants fail. If onoff is zero, - ** undo this setting. - */ - case SQLITE_TESTCTRL_LOCALTIME_FAULT: { - sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); - break; - } - -#if defined(SQLITE_ENABLE_TREE_EXPLAIN) - /* sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, - ** sqlite3_stmt*,const char**); - ** - ** If compiled with SQLITE_ENABLE_TREE_EXPLAIN, each sqlite3_stmt holds - ** a string that describes the optimized parse tree. This test-control - ** returns a pointer to that string. - */ - case SQLITE_TESTCTRL_EXPLAIN_STMT: { - sqlite3_stmt *pStmt = va_arg(ap, sqlite3_stmt*); - const char **pzRet = va_arg(ap, const char**); - *pzRet = sqlite3VdbeExplanation((Vdbe*)pStmt); - break; - } -#endif - - } - va_end(ap); -#endif /* SQLITE_OMIT_BUILTIN_TEST */ - return rc; -} - -/* -** This is a utility routine, useful to VFS implementations, that checks -** to see if a database file was a URI that contained a specific query -** parameter, and if so obtains the value of the query parameter. -** -** The zFilename argument is the filename pointer passed into the xOpen() -** method of a VFS implementation. The zParam argument is the name of the -** query parameter we seek. This routine returns the value of the zParam -** parameter if it exists. If the parameter does not exist, this routine -** returns a NULL pointer. -*/ -SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){ - if( zFilename==0 ) return 0; - zFilename += sqlite3Strlen30(zFilename) + 1; - while( zFilename[0] ){ - int x = strcmp(zFilename, zParam); - zFilename += sqlite3Strlen30(zFilename) + 1; - if( x==0 ) return zFilename; - zFilename += sqlite3Strlen30(zFilename) + 1; - } - return 0; -} - -/* -** Return a boolean value for a query parameter. -*/ -SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ - const char *z = sqlite3_uri_parameter(zFilename, zParam); - bDflt = bDflt!=0; - return z ? sqlite3GetBoolean(z, bDflt) : bDflt; -} - -/* -** Return a 64-bit integer value for a query parameter. -*/ -SQLITE_API sqlite3_int64 sqlite3_uri_int64( - const char *zFilename, /* Filename as passed to xOpen */ - const char *zParam, /* URI parameter sought */ - sqlite3_int64 bDflt /* return if parameter is missing */ -){ - const char *z = sqlite3_uri_parameter(zFilename, zParam); - sqlite3_int64 v; - if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){ - bDflt = v; - } - return bDflt; -} - -/* -** Return the Btree pointer identified by zDbName. Return NULL if not found. -*/ -SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ - int i; - for(i=0; inDb; i++){ - if( db->aDb[i].pBt - && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0) - ){ - return db->aDb[i].pBt; - } - } - return 0; -} - -/* -** Return the filename of the database associated with a database -** connection. -*/ -SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ - Btree *pBt = sqlite3DbNameToBtree(db, zDbName); - return pBt ? sqlite3BtreeGetFilename(pBt) : 0; -} - -/* -** Return 1 if database is read-only or 0 if read/write. Return -1 if -** no such database exists. -*/ -SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ - Btree *pBt = sqlite3DbNameToBtree(db, zDbName); - return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1; -} - -/************** End of main.c ************************************************/ -/************** Begin file notify.c ******************************************/ -/* -** 2009 March 3 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file contains the implementation of the sqlite3_unlock_notify() -** API method and its associated functionality. -*/ - -/* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */ -#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY - -/* -** Public interfaces: -** -** sqlite3ConnectionBlocked() -** sqlite3ConnectionUnlocked() -** sqlite3ConnectionClosed() -** sqlite3_unlock_notify() -*/ - -#define assertMutexHeld() \ - assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) ) - -/* -** Head of a linked list of all sqlite3 objects created by this process -** for which either sqlite3.pBlockingConnection or sqlite3.pUnlockConnection -** is not NULL. This variable may only accessed while the STATIC_MASTER -** mutex is held. -*/ -static sqlite3 *SQLITE_WSD sqlite3BlockedList = 0; - -#ifndef NDEBUG -/* -** This function is a complex assert() that verifies the following -** properties of the blocked connections list: -** -** 1) Each entry in the list has a non-NULL value for either -** pUnlockConnection or pBlockingConnection, or both. -** -** 2) All entries in the list that share a common value for -** xUnlockNotify are grouped together. -** -** 3) If the argument db is not NULL, then none of the entries in the -** blocked connections list have pUnlockConnection or pBlockingConnection -** set to db. This is used when closing connection db. -*/ -static void checkListProperties(sqlite3 *db){ - sqlite3 *p; - for(p=sqlite3BlockedList; p; p=p->pNextBlocked){ - int seen = 0; - sqlite3 *p2; - - /* Verify property (1) */ - assert( p->pUnlockConnection || p->pBlockingConnection ); - - /* Verify property (2) */ - for(p2=sqlite3BlockedList; p2!=p; p2=p2->pNextBlocked){ - if( p2->xUnlockNotify==p->xUnlockNotify ) seen = 1; - assert( p2->xUnlockNotify==p->xUnlockNotify || !seen ); - assert( db==0 || p->pUnlockConnection!=db ); - assert( db==0 || p->pBlockingConnection!=db ); - } - } -} -#else -# define checkListProperties(x) -#endif - -/* -** Remove connection db from the blocked connections list. If connection -** db is not currently a part of the list, this function is a no-op. -*/ -static void removeFromBlockedList(sqlite3 *db){ - sqlite3 **pp; - assertMutexHeld(); - for(pp=&sqlite3BlockedList; *pp; pp = &(*pp)->pNextBlocked){ - if( *pp==db ){ - *pp = (*pp)->pNextBlocked; - break; - } - } -} - -/* -** Add connection db to the blocked connections list. It is assumed -** that it is not already a part of the list. -*/ -static void addToBlockedList(sqlite3 *db){ - sqlite3 **pp; - assertMutexHeld(); - for( - pp=&sqlite3BlockedList; - *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify; - pp=&(*pp)->pNextBlocked - ); - db->pNextBlocked = *pp; - *pp = db; -} - -/* -** Obtain the STATIC_MASTER mutex. -*/ -static void enterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); - checkListProperties(0); -} - -/* -** Release the STATIC_MASTER mutex. -*/ -static void leaveMutex(void){ - assertMutexHeld(); - checkListProperties(0); - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); -} - -/* -** Register an unlock-notify callback. -** -** This is called after connection "db" has attempted some operation -** but has received an SQLITE_LOCKED error because another connection -** (call it pOther) in the same process was busy using the same shared -** cache. pOther is found by looking at db->pBlockingConnection. -** -** If there is no blocking connection, the callback is invoked immediately, -** before this routine returns. -** -** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate -** a deadlock. -** -** Otherwise, make arrangements to invoke xNotify when pOther drops -** its locks. -** -** Each call to this routine overrides any prior callbacks registered -** on the same "db". If xNotify==0 then any prior callbacks are immediately -** cancelled. -*/ -SQLITE_API int sqlite3_unlock_notify( - sqlite3 *db, - void (*xNotify)(void **, int), - void *pArg -){ - int rc = SQLITE_OK; - - sqlite3_mutex_enter(db->mutex); - enterMutex(); - - if( xNotify==0 ){ - removeFromBlockedList(db); - db->pBlockingConnection = 0; - db->pUnlockConnection = 0; - db->xUnlockNotify = 0; - db->pUnlockArg = 0; - }else if( 0==db->pBlockingConnection ){ - /* The blocking transaction has been concluded. Or there never was a - ** blocking transaction. In either case, invoke the notify callback - ** immediately. - */ - xNotify(&pArg, 1); - }else{ - sqlite3 *p; - - for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection){} - if( p ){ - rc = SQLITE_LOCKED; /* Deadlock detected. */ - }else{ - db->pUnlockConnection = db->pBlockingConnection; - db->xUnlockNotify = xNotify; - db->pUnlockArg = pArg; - removeFromBlockedList(db); - addToBlockedList(db); - } - } - - leaveMutex(); - assert( !db->mallocFailed ); - sqlite3Error(db, rc, (rc?"database is deadlocked":0)); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* -** This function is called while stepping or preparing a statement -** associated with connection db. The operation will return SQLITE_LOCKED -** to the user because it requires a lock that will not be available -** until connection pBlocker concludes its current transaction. -*/ -SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){ - enterMutex(); - if( db->pBlockingConnection==0 && db->pUnlockConnection==0 ){ - addToBlockedList(db); - } - db->pBlockingConnection = pBlocker; - leaveMutex(); -} - -/* -** This function is called when -** the transaction opened by database db has just finished. Locks held -** by database connection db have been released. -** -** This function loops through each entry in the blocked connections -** list and does the following: -** -** 1) If the sqlite3.pBlockingConnection member of a list entry is -** set to db, then set pBlockingConnection=0. -** -** 2) If the sqlite3.pUnlockConnection member of a list entry is -** set to db, then invoke the configured unlock-notify callback and -** set pUnlockConnection=0. -** -** 3) If the two steps above mean that pBlockingConnection==0 and -** pUnlockConnection==0, remove the entry from the blocked connections -** list. -*/ -SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db){ - void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */ - int nArg = 0; /* Number of entries in aArg[] */ - sqlite3 **pp; /* Iterator variable */ - void **aArg; /* Arguments to the unlock callback */ - void **aDyn = 0; /* Dynamically allocated space for aArg[] */ - void *aStatic[16]; /* Starter space for aArg[]. No malloc required */ - - aArg = aStatic; - enterMutex(); /* Enter STATIC_MASTER mutex */ - - /* This loop runs once for each entry in the blocked-connections list. */ - for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){ - sqlite3 *p = *pp; - - /* Step 1. */ - if( p->pBlockingConnection==db ){ - p->pBlockingConnection = 0; - } - - /* Step 2. */ - if( p->pUnlockConnection==db ){ - assert( p->xUnlockNotify ); - if( p->xUnlockNotify!=xUnlockNotify && nArg!=0 ){ - xUnlockNotify(aArg, nArg); - nArg = 0; - } - - sqlite3BeginBenignMalloc(); - assert( aArg==aDyn || (aDyn==0 && aArg==aStatic) ); - assert( nArg<=(int)ArraySize(aStatic) || aArg==aDyn ); - if( (!aDyn && nArg==(int)ArraySize(aStatic)) - || (aDyn && nArg==(int)(sqlite3MallocSize(aDyn)/sizeof(void*))) - ){ - /* The aArg[] array needs to grow. */ - void **pNew = (void **)sqlite3Malloc(nArg*sizeof(void *)*2); - if( pNew ){ - memcpy(pNew, aArg, nArg*sizeof(void *)); - sqlite3_free(aDyn); - aDyn = aArg = pNew; - }else{ - /* This occurs when the array of context pointers that need to - ** be passed to the unlock-notify callback is larger than the - ** aStatic[] array allocated on the stack and the attempt to - ** allocate a larger array from the heap has failed. - ** - ** This is a difficult situation to handle. Returning an error - ** code to the caller is insufficient, as even if an error code - ** is returned the transaction on connection db will still be - ** closed and the unlock-notify callbacks on blocked connections - ** will go unissued. This might cause the application to wait - ** indefinitely for an unlock-notify callback that will never - ** arrive. - ** - ** Instead, invoke the unlock-notify callback with the context - ** array already accumulated. We can then clear the array and - ** begin accumulating any further context pointers without - ** requiring any dynamic allocation. This is sub-optimal because - ** it means that instead of one callback with a large array of - ** context pointers the application will receive two or more - ** callbacks with smaller arrays of context pointers, which will - ** reduce the applications ability to prioritize multiple - ** connections. But it is the best that can be done under the - ** circumstances. - */ - xUnlockNotify(aArg, nArg); - nArg = 0; - } - } - sqlite3EndBenignMalloc(); - - aArg[nArg++] = p->pUnlockArg; - xUnlockNotify = p->xUnlockNotify; - p->pUnlockConnection = 0; - p->xUnlockNotify = 0; - p->pUnlockArg = 0; - } - - /* Step 3. */ - if( p->pBlockingConnection==0 && p->pUnlockConnection==0 ){ - /* Remove connection p from the blocked connections list. */ - *pp = p->pNextBlocked; - p->pNextBlocked = 0; - }else{ - pp = &p->pNextBlocked; - } - } - - if( nArg!=0 ){ - xUnlockNotify(aArg, nArg); - } - sqlite3_free(aDyn); - leaveMutex(); /* Leave STATIC_MASTER mutex */ -} - -/* -** This is called when the database connection passed as an argument is -** being closed. The connection is removed from the blocked list. -*/ -SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ - sqlite3ConnectionUnlocked(db); - enterMutex(); - removeFromBlockedList(db); - checkListProperties(db); - leaveMutex(); -} -#endif - -/************** End of notify.c **********************************************/ -/************** Begin file fts3.c ********************************************/ -/* -** 2006 Oct 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This is an SQLite module implementing full-text search. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ - -/* The full-text index is stored in a series of b+tree (-like) -** structures called segments which map terms to doclists. The -** structures are like b+trees in layout, but are constructed from the -** bottom up in optimal fashion and are not updatable. Since trees -** are built from the bottom up, things will be described from the -** bottom up. -** -** -**** Varints **** -** The basic unit of encoding is a variable-length integer called a -** varint. We encode variable-length integers in little-endian order -** using seven bits * per byte as follows: -** -** KEY: -** A = 0xxxxxxx 7 bits of data and one flag bit -** B = 1xxxxxxx 7 bits of data and one flag bit -** -** 7 bits - A -** 14 bits - BA -** 21 bits - BBA -** and so on. -** -** This is similar in concept to how sqlite encodes "varints" but -** the encoding is not the same. SQLite varints are big-endian -** are are limited to 9 bytes in length whereas FTS3 varints are -** little-endian and can be up to 10 bytes in length (in theory). -** -** Example encodings: -** -** 1: 0x01 -** 127: 0x7f -** 128: 0x81 0x00 -** -** -**** Document lists **** -** A doclist (document list) holds a docid-sorted list of hits for a -** given term. Doclists hold docids and associated token positions. -** A docid is the unique integer identifier for a single document. -** A position is the index of a word within the document. The first -** word of the document has a position of 0. -** -** FTS3 used to optionally store character offsets using a compile-time -** option. But that functionality is no longer supported. -** -** A doclist is stored like this: -** -** array { -** varint docid; (delta from previous doclist) -** array { (position list for column 0) -** varint position; (2 more than the delta from previous position) -** } -** array { -** varint POS_COLUMN; (marks start of position list for new column) -** varint column; (index of new column) -** array { -** varint position; (2 more than the delta from previous position) -** } -** } -** varint POS_END; (marks end of positions for this document. -** } -** -** Here, array { X } means zero or more occurrences of X, adjacent in -** memory. A "position" is an index of a token in the token stream -** generated by the tokenizer. Note that POS_END and POS_COLUMN occur -** in the same logical place as the position element, and act as sentinals -** ending a position list array. POS_END is 0. POS_COLUMN is 1. -** The positions numbers are not stored literally but rather as two more -** than the difference from the prior position, or the just the position plus -** 2 for the first position. Example: -** -** label: A B C D E F G H I J K -** value: 123 5 9 1 1 14 35 0 234 72 0 -** -** The 123 value is the first docid. For column zero in this document -** there are two matches at positions 3 and 10 (5-2 and 9-2+3). The 1 -** at D signals the start of a new column; the 1 at E indicates that the -** new column is column number 1. There are two positions at 12 and 45 -** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The -** 234 at I is the delta to next docid (357). It has one position 70 -** (72-2) and then terminates with the 0 at K. -** -** A "position-list" is the list of positions for multiple columns for -** a single docid. A "column-list" is the set of positions for a single -** column. Hence, a position-list consists of one or more column-lists, -** a document record consists of a docid followed by a position-list and -** a doclist consists of one or more document records. -** -** A bare doclist omits the position information, becoming an -** array of varint-encoded docids. -** -**** Segment leaf nodes **** -** Segment leaf nodes store terms and doclists, ordered by term. Leaf -** nodes are written using LeafWriter, and read using LeafReader (to -** iterate through a single leaf node's data) and LeavesReader (to -** iterate through a segment's entire leaf layer). Leaf nodes have -** the format: -** -** varint iHeight; (height from leaf level, always 0) -** varint nTerm; (length of first term) -** char pTerm[nTerm]; (content of first term) -** varint nDoclist; (length of term's associated doclist) -** char pDoclist[nDoclist]; (content of doclist) -** array { -** (further terms are delta-encoded) -** varint nPrefix; (length of prefix shared with previous term) -** varint nSuffix; (length of unshared suffix) -** char pTermSuffix[nSuffix];(unshared suffix of next term) -** varint nDoclist; (length of term's associated doclist) -** char pDoclist[nDoclist]; (content of doclist) -** } -** -** Here, array { X } means zero or more occurrences of X, adjacent in -** memory. -** -** Leaf nodes are broken into blocks which are stored contiguously in -** the %_segments table in sorted order. This means that when the end -** of a node is reached, the next term is in the node with the next -** greater node id. -** -** New data is spilled to a new leaf node when the current node -** exceeds LEAF_MAX bytes (default 2048). New data which itself is -** larger than STANDALONE_MIN (default 1024) is placed in a standalone -** node (a leaf node with a single term and doclist). The goal of -** these settings is to pack together groups of small doclists while -** making it efficient to directly access large doclists. The -** assumption is that large doclists represent terms which are more -** likely to be query targets. -** -** TODO(shess) It may be useful for blocking decisions to be more -** dynamic. For instance, it may make more sense to have a 2.5k leaf -** node rather than splitting into 2k and .5k nodes. My intuition is -** that this might extend through 2x or 4x the pagesize. -** -** -**** Segment interior nodes **** -** Segment interior nodes store blockids for subtree nodes and terms -** to describe what data is stored by the each subtree. Interior -** nodes are written using InteriorWriter, and read using -** InteriorReader. InteriorWriters are created as needed when -** SegmentWriter creates new leaf nodes, or when an interior node -** itself grows too big and must be split. The format of interior -** nodes: -** -** varint iHeight; (height from leaf level, always >0) -** varint iBlockid; (block id of node's leftmost subtree) -** optional { -** varint nTerm; (length of first term) -** char pTerm[nTerm]; (content of first term) -** array { -** (further terms are delta-encoded) -** varint nPrefix; (length of shared prefix with previous term) -** varint nSuffix; (length of unshared suffix) -** char pTermSuffix[nSuffix]; (unshared suffix of next term) -** } -** } -** -** Here, optional { X } means an optional element, while array { X } -** means zero or more occurrences of X, adjacent in memory. -** -** An interior node encodes n terms separating n+1 subtrees. The -** subtree blocks are contiguous, so only the first subtree's blockid -** is encoded. The subtree at iBlockid will contain all terms less -** than the first term encoded (or all terms if no term is encoded). -** Otherwise, for terms greater than or equal to pTerm[i] but less -** than pTerm[i+1], the subtree for that term will be rooted at -** iBlockid+i. Interior nodes only store enough term data to -** distinguish adjacent children (if the rightmost term of the left -** child is "something", and the leftmost term of the right child is -** "wicked", only "w" is stored). -** -** New data is spilled to a new interior node at the same height when -** the current node exceeds INTERIOR_MAX bytes (default 2048). -** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing -** interior nodes and making the tree too skinny. The interior nodes -** at a given height are naturally tracked by interior nodes at -** height+1, and so on. -** -** -**** Segment directory **** -** The segment directory in table %_segdir stores meta-information for -** merging and deleting segments, and also the root node of the -** segment's tree. -** -** The root node is the top node of the segment's tree after encoding -** the entire segment, restricted to ROOT_MAX bytes (default 1024). -** This could be either a leaf node or an interior node. If the top -** node requires more than ROOT_MAX bytes, it is flushed to %_segments -** and a new root interior node is generated (which should always fit -** within ROOT_MAX because it only needs space for 2 varints, the -** height and the blockid of the previous root). -** -** The meta-information in the segment directory is: -** level - segment level (see below) -** idx - index within level -** - (level,idx uniquely identify a segment) -** start_block - first leaf node -** leaves_end_block - last leaf node -** end_block - last block (including interior nodes) -** root - contents of root node -** -** If the root node is a leaf node, then start_block, -** leaves_end_block, and end_block are all 0. -** -** -**** Segment merging **** -** To amortize update costs, segments are grouped into levels and -** merged in batches. Each increase in level represents exponentially -** more documents. -** -** New documents (actually, document updates) are tokenized and -** written individually (using LeafWriter) to a level 0 segment, with -** incrementing idx. When idx reaches MERGE_COUNT (default 16), all -** level 0 segments are merged into a single level 1 segment. Level 1 -** is populated like level 0, and eventually MERGE_COUNT level 1 -** segments are merged to a single level 2 segment (representing -** MERGE_COUNT^2 updates), and so on. -** -** A segment merge traverses all segments at a given level in -** parallel, performing a straightforward sorted merge. Since segment -** leaf nodes are written in to the %_segments table in order, this -** merge traverses the underlying sqlite disk structures efficiently. -** After the merge, all segment blocks from the merged level are -** deleted. -** -** MERGE_COUNT controls how often we merge segments. 16 seems to be -** somewhat of a sweet spot for insertion performance. 32 and 64 show -** very similar performance numbers to 16 on insertion, though they're -** a tiny bit slower (perhaps due to more overhead in merge-time -** sorting). 8 is about 20% slower than 16, 4 about 50% slower than -** 16, 2 about 66% slower than 16. -** -** At query time, high MERGE_COUNT increases the number of segments -** which need to be scanned and merged. For instance, with 100k docs -** inserted: -** -** MERGE_COUNT segments -** 16 25 -** 8 12 -** 4 10 -** 2 6 -** -** This appears to have only a moderate impact on queries for very -** frequent terms (which are somewhat dominated by segment merge -** costs), and infrequent and non-existent terms still seem to be fast -** even with many segments. -** -** TODO(shess) That said, it would be nice to have a better query-side -** argument for MERGE_COUNT of 16. Also, it is possible/likely that -** optimizations to things like doclist merging will swing the sweet -** spot around. -** -** -** -**** Handling of deletions and updates **** -** Since we're using a segmented structure, with no docid-oriented -** index into the term index, we clearly cannot simply update the term -** index when a document is deleted or updated. For deletions, we -** write an empty doclist (varint(docid) varint(POS_END)), for updates -** we simply write the new doclist. Segment merges overwrite older -** data for a particular docid with newer data, so deletes or updates -** will eventually overtake the earlier data and knock it out. The -** query logic likewise merges doclists so that newer data knocks out -** older data. -*/ - -/************** Include fts3Int.h in the middle of fts3.c ********************/ -/************** Begin file fts3Int.h *****************************************/ -/* -** 2009 Nov 12 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -*/ -#ifndef _FTSINT_H -#define _FTSINT_H - -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - -/* -** FTS4 is really an extension for FTS3. It is enabled using the -** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all -** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3. -*/ -#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3) -# define SQLITE_ENABLE_FTS3 -#endif - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* If not building as part of the core, include sqlite3ext.h. */ -#ifndef SQLITE_CORE -SQLITE_API extern const sqlite3_api_routines *sqlite3_api; -#endif - -/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ -/************** Begin file fts3_tokenizer.h **********************************/ -/* -** 2006 July 10 -** -** The author disclaims copyright to this source code. -** -************************************************************************* -** Defines the interface to tokenizers used by fulltext-search. There -** are three basic components: -** -** sqlite3_tokenizer_module is a singleton defining the tokenizer -** interface functions. This is essentially the class structure for -** tokenizers. -** -** sqlite3_tokenizer is used to define a particular tokenizer, perhaps -** including customization information defined at creation time. -** -** sqlite3_tokenizer_cursor is generated by a tokenizer to generate -** tokens from a particular input. -*/ -#ifndef _FTS3_TOKENIZER_H_ -#define _FTS3_TOKENIZER_H_ - -/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. -** If tokenizers are to be allowed to call sqlite3_*() functions, then -** we will need a way to register the API consistently. -*/ - -/* -** Structures used by the tokenizer interface. When a new tokenizer -** implementation is registered, the caller provides a pointer to -** an sqlite3_tokenizer_module containing pointers to the callback -** functions that make up an implementation. -** -** When an fts3 table is created, it passes any arguments passed to -** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the -** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer -** implementation. The xCreate() function in turn returns an -** sqlite3_tokenizer structure representing the specific tokenizer to -** be used for the fts3 table (customized by the tokenizer clause arguments). -** -** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() -** method is called. It returns an sqlite3_tokenizer_cursor object -** that may be used to tokenize a specific input buffer based on -** the tokenization rules supplied by a specific sqlite3_tokenizer -** object. -*/ -typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; -typedef struct sqlite3_tokenizer sqlite3_tokenizer; -typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; - -struct sqlite3_tokenizer_module { - - /* - ** Structure version. Should always be set to 0 or 1. - */ - int iVersion; - - /* - ** Create a new tokenizer. The values in the argv[] array are the - ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL - ** TABLE statement that created the fts3 table. For example, if - ** the following SQL is executed: - ** - ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) - ** - ** then argc is set to 2, and the argv[] array contains pointers - ** to the strings "arg1" and "arg2". - ** - ** This method should return either SQLITE_OK (0), or an SQLite error - ** code. If SQLITE_OK is returned, then *ppTokenizer should be set - ** to point at the newly created tokenizer structure. The generic - ** sqlite3_tokenizer.pModule variable should not be initialized by - ** this callback. The caller will do so. - */ - int (*xCreate)( - int argc, /* Size of argv array */ - const char *const*argv, /* Tokenizer argument strings */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ - ); - - /* - ** Destroy an existing tokenizer. The fts3 module calls this method - ** exactly once for each successful call to xCreate(). - */ - int (*xDestroy)(sqlite3_tokenizer *pTokenizer); - - /* - ** Create a tokenizer cursor to tokenize an input buffer. The caller - ** is responsible for ensuring that the input buffer remains valid - ** until the cursor is closed (using the xClose() method). - */ - int (*xOpen)( - sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ - const char *pInput, int nBytes, /* Input buffer */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ - ); - - /* - ** Destroy an existing tokenizer cursor. The fts3 module calls this - ** method exactly once for each successful call to xOpen(). - */ - int (*xClose)(sqlite3_tokenizer_cursor *pCursor); - - /* - ** Retrieve the next token from the tokenizer cursor pCursor. This - ** method should either return SQLITE_OK and set the values of the - ** "OUT" variables identified below, or SQLITE_DONE to indicate that - ** the end of the buffer has been reached, or an SQLite error code. - ** - ** *ppToken should be set to point at a buffer containing the - ** normalized version of the token (i.e. after any case-folding and/or - ** stemming has been performed). *pnBytes should be set to the length - ** of this buffer in bytes. The input text that generated the token is - ** identified by the byte offsets returned in *piStartOffset and - ** *piEndOffset. *piStartOffset should be set to the index of the first - ** byte of the token in the input buffer. *piEndOffset should be set - ** to the index of the first byte just past the end of the token in - ** the input buffer. - ** - ** The buffer *ppToken is set to point at is managed by the tokenizer - ** implementation. It is only required to be valid until the next call - ** to xNext() or xClose(). - */ - /* TODO(shess) current implementation requires pInput to be - ** nul-terminated. This should either be fixed, or pInput/nBytes - ** should be converted to zInput. - */ - int (*xNext)( - sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ - const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ - int *piStartOffset, /* OUT: Byte offset of token in input buffer */ - int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ - int *piPosition /* OUT: Number of tokens returned before this one */ - ); - - /*********************************************************************** - ** Methods below this point are only available if iVersion>=1. - */ - - /* - ** Configure the language id of a tokenizer cursor. - */ - int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid); -}; - -struct sqlite3_tokenizer { - const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ - /* Tokenizer implementations will typically add additional fields */ -}; - -struct sqlite3_tokenizer_cursor { - sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ - /* Tokenizer implementations will typically add additional fields */ -}; - -int fts3_global_term_cnt(int iTerm, int iCol); -int fts3_term_cnt(int iTerm, int iCol); - - -#endif /* _FTS3_TOKENIZER_H_ */ - -/************** End of fts3_tokenizer.h **************************************/ -/************** Continuing where we left off in fts3Int.h ********************/ -/************** Include fts3_hash.h in the middle of fts3Int.h ***************/ -/************** Begin file fts3_hash.h ***************************************/ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the header file for the generic hash-table implementation -** used in SQLite. We've modified it slightly to serve as a standalone -** hash table implementation for the full-text indexing module. -** -*/ -#ifndef _FTS3_HASH_H_ -#define _FTS3_HASH_H_ - -/* Forward declarations of structures. */ -typedef struct Fts3Hash Fts3Hash; -typedef struct Fts3HashElem Fts3HashElem; - -/* A complete hash table is an instance of the following structure. -** The internals of this structure are intended to be opaque -- client -** code should not attempt to access or modify the fields of this structure -** directly. Change this structure only by using the routines below. -** However, many of the "procedures" and "functions" for modifying and -** accessing this structure are really macros, so we can't really make -** this structure opaque. -*/ -struct Fts3Hash { - char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ - char copyKey; /* True if copy of key made on insert */ - int count; /* Number of entries in this table */ - Fts3HashElem *first; /* The first element of the array */ - int htsize; /* Number of buckets in the hash table */ - struct _fts3ht { /* the hash table */ - int count; /* Number of entries with this hash */ - Fts3HashElem *chain; /* Pointer to first entry with this hash */ - } *ht; -}; - -/* Each element in the hash table is an instance of the following -** structure. All elements are stored on a single doubly-linked list. -** -** Again, this structure is intended to be opaque, but it can't really -** be opaque because it is used by macros. -*/ -struct Fts3HashElem { - Fts3HashElem *next, *prev; /* Next and previous elements in the table */ - void *data; /* Data associated with this element */ - void *pKey; int nKey; /* Key associated with this element */ -}; - -/* -** There are 2 different modes of operation for a hash table: -** -** FTS3_HASH_STRING pKey points to a string that is nKey bytes long -** (including the null-terminator, if any). Case -** is respected in comparisons. -** -** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. -** memcmp() is used to compare keys. -** -** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. -*/ -#define FTS3_HASH_STRING 1 -#define FTS3_HASH_BINARY 2 - -/* -** Access routines. To delete, insert a NULL pointer. -*/ -SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey); -SQLITE_PRIVATE void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData); -SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey); -SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash*); -SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const void *, int); - -/* -** Shorthand for the functions above -*/ -#define fts3HashInit sqlite3Fts3HashInit -#define fts3HashInsert sqlite3Fts3HashInsert -#define fts3HashFind sqlite3Fts3HashFind -#define fts3HashClear sqlite3Fts3HashClear -#define fts3HashFindElem sqlite3Fts3HashFindElem - -/* -** Macros for looping over all elements of a hash table. The idiom is -** like this: -** -** Fts3Hash h; -** Fts3HashElem *p; -** ... -** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ -** SomeStructure *pData = fts3HashData(p); -** // do something with pData -** } -*/ -#define fts3HashFirst(H) ((H)->first) -#define fts3HashNext(E) ((E)->next) -#define fts3HashData(E) ((E)->data) -#define fts3HashKey(E) ((E)->pKey) -#define fts3HashKeysize(E) ((E)->nKey) - -/* -** Number of entries in a hash table -*/ -#define fts3HashCount(H) ((H)->count) - -#endif /* _FTS3_HASH_H_ */ - -/************** End of fts3_hash.h *******************************************/ -/************** Continuing where we left off in fts3Int.h ********************/ - -/* -** This constant controls how often segments are merged. Once there are -** FTS3_MERGE_COUNT segments of level N, they are merged into a single -** segment of level N+1. -*/ -#define FTS3_MERGE_COUNT 16 - -/* -** This is the maximum amount of data (in bytes) to store in the -** Fts3Table.pendingTerms hash table. Normally, the hash table is -** populated as documents are inserted/updated/deleted in a transaction -** and used to create a new segment when the transaction is committed. -** However if this limit is reached midway through a transaction, a new -** segment is created and the hash table cleared immediately. -*/ -#define FTS3_MAX_PENDING_DATA (1*1024*1024) - -/* -** Macro to return the number of elements in an array. SQLite has a -** similar macro called ArraySize(). Use a different name to avoid -** a collision when building an amalgamation with built-in FTS3. -*/ -#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0]))) - - -#ifndef MIN -# define MIN(x,y) ((x)<(y)?(x):(y)) -#endif -#ifndef MAX -# define MAX(x,y) ((x)>(y)?(x):(y)) -#endif - -/* -** Maximum length of a varint encoded integer. The varint format is different -** from that used by SQLite, so the maximum length is 10, not 9. -*/ -#define FTS3_VARINT_MAX 10 - -/* -** FTS4 virtual tables may maintain multiple indexes - one index of all terms -** in the document set and zero or more prefix indexes. All indexes are stored -** as one or more b+-trees in the %_segments and %_segdir tables. -** -** It is possible to determine which index a b+-tree belongs to based on the -** value stored in the "%_segdir.level" column. Given this value L, the index -** that the b+-tree belongs to is (L<<10). In other words, all b+-trees with -** level values between 0 and 1023 (inclusive) belong to index 0, all levels -** between 1024 and 2047 to index 1, and so on. -** -** It is considered impossible for an index to use more than 1024 levels. In -** theory though this may happen, but only after at least -** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables. -*/ -#define FTS3_SEGDIR_MAXLEVEL 1024 -#define FTS3_SEGDIR_MAXLEVEL_STR "1024" - -/* -** The testcase() macro is only used by the amalgamation. If undefined, -** make it a no-op. -*/ -#ifndef testcase -# define testcase(X) -#endif - -/* -** Terminator values for position-lists and column-lists. -*/ -#define POS_COLUMN (1) /* Column-list terminator */ -#define POS_END (0) /* Position-list terminator */ - -/* -** This section provides definitions to allow the -** FTS3 extension to be compiled outside of the -** amalgamation. -*/ -#ifndef SQLITE_AMALGAMATION -/* -** Macros indicating that conditional expressions are always true or -** false. -*/ -#ifdef SQLITE_COVERAGE_TEST -# define ALWAYS(x) (1) -# define NEVER(X) (0) -#else -# define ALWAYS(x) (x) -# define NEVER(x) (x) -#endif - -/* -** Internal types used by SQLite. -*/ -typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */ -typedef short int i16; /* 2-byte (or larger) signed integer */ -typedef unsigned int u32; /* 4-byte unsigned integer */ -typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */ -typedef sqlite3_int64 i64; /* 8-byte signed integer */ - -/* -** Macro used to suppress compiler warnings for unused parameters. -*/ -#define UNUSED_PARAMETER(x) (void)(x) - -/* -** Activate assert() only if SQLITE_TEST is enabled. -*/ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - -/* -** The TESTONLY macro is used to enclose variable declarations or -** other bits of code that are needed to support the arguments -** within testcase() and assert() macros. -*/ -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) -# define TESTONLY(X) X -#else -# define TESTONLY(X) -#endif - -#endif /* SQLITE_AMALGAMATION */ - -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3Fts3Corrupt(void); -# define FTS_CORRUPT_VTAB sqlite3Fts3Corrupt() -#else -# define FTS_CORRUPT_VTAB SQLITE_CORRUPT_VTAB -#endif - -typedef struct Fts3Table Fts3Table; -typedef struct Fts3Cursor Fts3Cursor; -typedef struct Fts3Expr Fts3Expr; -typedef struct Fts3Phrase Fts3Phrase; -typedef struct Fts3PhraseToken Fts3PhraseToken; - -typedef struct Fts3Doclist Fts3Doclist; -typedef struct Fts3SegFilter Fts3SegFilter; -typedef struct Fts3DeferredToken Fts3DeferredToken; -typedef struct Fts3SegReader Fts3SegReader; -typedef struct Fts3MultiSegReader Fts3MultiSegReader; - -/* -** A connection to a fulltext index is an instance of the following -** structure. The xCreate and xConnect methods create an instance -** of this structure and xDestroy and xDisconnect free that instance. -** All other methods receive a pointer to the structure as one of their -** arguments. -*/ -struct Fts3Table { - sqlite3_vtab base; /* Base class used by SQLite core */ - sqlite3 *db; /* The database connection */ - const char *zDb; /* logical database name */ - const char *zName; /* virtual table name */ - int nColumn; /* number of named columns in virtual table */ - char **azColumn; /* column names. malloced */ - sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ - char *zContentTbl; /* content=xxx option, or NULL */ - char *zLanguageid; /* languageid=xxx option, or NULL */ - u8 bAutoincrmerge; /* True if automerge=1 */ - u32 nLeafAdd; /* Number of leaf blocks added this trans */ - - /* Precompiled statements used by the implementation. Each of these - ** statements is run and reset within a single virtual table API call. - */ - sqlite3_stmt *aStmt[37]; - - char *zReadExprlist; - char *zWriteExprlist; - - int nNodeSize; /* Soft limit for node size */ - u8 bFts4; /* True for FTS4, false for FTS3 */ - u8 bHasStat; /* True if %_stat table exists */ - u8 bHasDocsize; /* True if %_docsize table exists */ - u8 bDescIdx; /* True if doclists are in reverse order */ - u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */ - int nPgsz; /* Page size for host database */ - char *zSegmentsTbl; /* Name of %_segments table */ - sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ - - /* - ** The following array of hash tables is used to buffer pending index - ** updates during transactions. All pending updates buffered at any one - ** time must share a common language-id (see the FTS4 langid= feature). - ** The current language id is stored in variable iPrevLangid. - ** - ** A single FTS4 table may have multiple full-text indexes. For each index - ** there is an entry in the aIndex[] array. Index 0 is an index of all the - ** terms that appear in the document set. Each subsequent index in aIndex[] - ** is an index of prefixes of a specific length. - ** - ** Variable nPendingData contains an estimate the memory consumed by the - ** pending data structures, including hash table overhead, but not including - ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash - ** tables are flushed to disk. Variable iPrevDocid is the docid of the most - ** recently inserted record. - */ - int nIndex; /* Size of aIndex[] */ - struct Fts3Index { - int nPrefix; /* Prefix length (0 for main terms index) */ - Fts3Hash hPending; /* Pending terms table for this index */ - } *aIndex; - int nMaxPendingData; /* Max pending data before flush to disk */ - int nPendingData; /* Current bytes of pending data */ - sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ - int iPrevLangid; /* Langid of recently inserted document */ - -#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) - /* State variables used for validating that the transaction control - ** methods of the virtual table are called at appropriate times. These - ** values do not contribute to FTS functionality; they are used for - ** verifying the operation of the SQLite core. - */ - int inTransaction; /* True after xBegin but before xCommit/xRollback */ - int mxSavepoint; /* Largest valid xSavepoint integer */ -#endif -}; - -/* -** When the core wants to read from the virtual table, it creates a -** virtual table cursor (an instance of the following structure) using -** the xOpen method. Cursors are destroyed using the xClose method. -*/ -struct Fts3Cursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - i16 eSearch; /* Search strategy (see below) */ - u8 isEof; /* True if at End Of Results */ - u8 isRequireSeek; /* True if must seek pStmt to %_content row */ - sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ - Fts3Expr *pExpr; /* Parsed MATCH query string */ - int iLangid; /* Language being queried for */ - int nPhrase; /* Number of matchable phrases in query */ - Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ - sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ - char *pNextId; /* Pointer into the body of aDoclist */ - char *aDoclist; /* List of docids for full-text queries */ - int nDoclist; /* Size of buffer at aDoclist */ - u8 bDesc; /* True to sort in descending order */ - int eEvalmode; /* An FTS3_EVAL_XX constant */ - int nRowAvg; /* Average size of database rows, in pages */ - sqlite3_int64 nDoc; /* Documents in table */ - - int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ - u32 *aMatchinfo; /* Information about most recent match */ - int nMatchinfo; /* Number of elements in aMatchinfo[] */ - char *zMatchinfo; /* Matchinfo specification */ -}; - -#define FTS3_EVAL_FILTER 0 -#define FTS3_EVAL_NEXT 1 -#define FTS3_EVAL_MATCHINFO 2 - -/* -** The Fts3Cursor.eSearch member is always set to one of the following. -** Actualy, Fts3Cursor.eSearch can be greater than or equal to -** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index -** of the column to be searched. For example, in -** -** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d); -** SELECT docid FROM ex1 WHERE b MATCH 'one two three'; -** -** Because the LHS of the MATCH operator is 2nd column "b", -** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a, -** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1" -** indicating that all columns should be searched, -** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4. -*/ -#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */ -#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */ -#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */ - - -struct Fts3Doclist { - char *aAll; /* Array containing doclist (or NULL) */ - int nAll; /* Size of a[] in bytes */ - char *pNextDocid; /* Pointer to next docid */ - - sqlite3_int64 iDocid; /* Current docid (if pList!=0) */ - int bFreeList; /* True if pList should be sqlite3_free()d */ - char *pList; /* Pointer to position list following iDocid */ - int nList; /* Length of position list */ -}; - -/* -** A "phrase" is a sequence of one or more tokens that must match in -** sequence. A single token is the base case and the most common case. -** For a sequence of tokens contained in double-quotes (i.e. "one two three") -** nToken will be the number of tokens in the string. -*/ -struct Fts3PhraseToken { - char *z; /* Text of the token */ - int n; /* Number of bytes in buffer z */ - int isPrefix; /* True if token ends with a "*" character */ - int bFirst; /* True if token must appear at position 0 */ - - /* Variables above this point are populated when the expression is - ** parsed (by code in fts3_expr.c). Below this point the variables are - ** used when evaluating the expression. */ - Fts3DeferredToken *pDeferred; /* Deferred token object for this token */ - Fts3MultiSegReader *pSegcsr; /* Segment-reader for this token */ -}; - -struct Fts3Phrase { - /* Cache of doclist for this phrase. */ - Fts3Doclist doclist; - int bIncr; /* True if doclist is loaded incrementally */ - int iDoclistToken; - - /* Variables below this point are populated by fts3_expr.c when parsing - ** a MATCH expression. Everything above is part of the evaluation phase. - */ - int nToken; /* Number of tokens in the phrase */ - int iColumn; /* Index of column this phrase must match */ - Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */ -}; - -/* -** A tree of these objects forms the RHS of a MATCH operator. -** -** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist -** points to a malloced buffer, size nDoclist bytes, containing the results -** of this phrase query in FTS3 doclist format. As usual, the initial -** "Length" field found in doclists stored on disk is omitted from this -** buffer. -** -** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global -** matchinfo data. If it is not NULL, it points to an array of size nCol*3, -** where nCol is the number of columns in the queried FTS table. The array -** is populated as follows: -** -** aMI[iCol*3 + 0] = Undefined -** aMI[iCol*3 + 1] = Number of occurrences -** aMI[iCol*3 + 2] = Number of rows containing at least one instance -** -** The aMI array is allocated using sqlite3_malloc(). It should be freed -** when the expression node is. -*/ -struct Fts3Expr { - int eType; /* One of the FTSQUERY_XXX values defined below */ - int nNear; /* Valid if eType==FTSQUERY_NEAR */ - Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */ - Fts3Expr *pLeft; /* Left operand */ - Fts3Expr *pRight; /* Right operand */ - Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */ - - /* The following are used by the fts3_eval.c module. */ - sqlite3_int64 iDocid; /* Current docid */ - u8 bEof; /* True this expression is at EOF already */ - u8 bStart; /* True if iDocid is valid */ - u8 bDeferred; /* True if this expression is entirely deferred */ - - u32 *aMI; -}; - -/* -** Candidate values for Fts3Query.eType. Note that the order of the first -** four values is in order of precedence when parsing expressions. For -** example, the following: -** -** "a OR b AND c NOT d NEAR e" -** -** is equivalent to: -** -** "a OR (b AND (c NOT (d NEAR e)))" -*/ -#define FTSQUERY_NEAR 1 -#define FTSQUERY_NOT 2 -#define FTSQUERY_AND 3 -#define FTSQUERY_OR 4 -#define FTSQUERY_PHRASE 5 - - -/* fts3_write.c */ -SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*); -SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *); -SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *); -SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); -SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64, - sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); -SQLITE_PRIVATE int sqlite3Fts3SegReaderPending( - Fts3Table*,int,const char*,int,int,Fts3SegReader**); -SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); -SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **); -SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); -SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*); - -SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); -SQLITE_PRIVATE int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); - -#ifndef SQLITE_DISABLE_FTS4_DEFERRED -SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *); -SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); -SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); -SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); -SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *); -#else -# define sqlite3Fts3FreeDeferredTokens(x) -# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK -# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK -# define sqlite3Fts3FreeDeferredDoclists(x) -# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK -#endif - -SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *); -SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *, int *); - -/* Special values interpreted by sqlite3SegReaderCursor() */ -#define FTS3_SEGCURSOR_PENDING -1 -#define FTS3_SEGCURSOR_ALL -2 - -SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Fts3SegFilter*); -SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *); -SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *); - -SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *, - int, int, int, const char *, int, int, int, Fts3MultiSegReader *); - -/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ -#define FTS3_SEGMENT_REQUIRE_POS 0x00000001 -#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002 -#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004 -#define FTS3_SEGMENT_PREFIX 0x00000008 -#define FTS3_SEGMENT_SCAN 0x00000010 -#define FTS3_SEGMENT_FIRST 0x00000020 - -/* Type passed as 4th argument to SegmentReaderIterate() */ -struct Fts3SegFilter { - const char *zTerm; - int nTerm; - int iCol; - int flags; -}; - -struct Fts3MultiSegReader { - /* Used internally by sqlite3Fts3SegReaderXXX() calls */ - Fts3SegReader **apSegment; /* Array of Fts3SegReader objects */ - int nSegment; /* Size of apSegment array */ - int nAdvance; /* How many seg-readers to advance */ - Fts3SegFilter *pFilter; /* Pointer to filter object */ - char *aBuffer; /* Buffer to merge doclists in */ - int nBuffer; /* Allocated size of aBuffer[] in bytes */ - - int iColFilter; /* If >=0, filter for this column */ - int bRestart; - - /* Used by fts3.c only. */ - int nCost; /* Cost of running iterator */ - int bLookup; /* True if a lookup of a single entry. */ - - /* Output values. Valid only after Fts3SegReaderStep() returns SQLITE_ROW. */ - char *zTerm; /* Pointer to term buffer */ - int nTerm; /* Size of zTerm in bytes */ - char *aDoclist; /* Pointer to doclist buffer */ - int nDoclist; /* Size of aDoclist[] in bytes */ -}; - -SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); - -/* fts3.c */ -SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); -SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); -SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); -SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); -SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); -SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*); -SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *); -SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *); -SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*); - -/* fts3_tokenizer.c */ -SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); -SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *); -SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *, - sqlite3_tokenizer **, char ** -); -SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char); - -/* fts3_snippet.c */ -SQLITE_PRIVATE void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*); -SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, - const char *, const char *, int, int -); -SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); - -/* fts3_expr.c */ -SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, - char **, int, int, int, const char *, int, Fts3Expr **, char ** -); -SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); -#ifdef SQLITE_TEST -SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); -SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); -#endif - -SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, - sqlite3_tokenizer_cursor ** -); - -/* fts3_aux.c */ -SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); - -SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *); - -SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart( - Fts3Table*, Fts3MultiSegReader*, int, const char*, int); -SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( - Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *); -SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); -SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); -SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); - -/* fts3_tokenize_vtab.c */ -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *); - -/* fts3_unicode2.c (functions generated by parsing unicode text files) */ -#ifdef SQLITE_ENABLE_FTS4_UNICODE61 -SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int); -SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int); -SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); -#endif - -#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ -#endif /* _FTSINT_H */ - -/************** End of fts3Int.h *********************************************/ -/************** Continuing where we left off in fts3.c ***********************/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) -# define SQLITE_CORE 1 -#endif - -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -#ifndef SQLITE_CORE - SQLITE_EXTENSION_INIT1 -#endif - -static int fts3EvalNext(Fts3Cursor *pCsr); -static int fts3EvalStart(Fts3Cursor *pCsr); -static int fts3TermSegReaderCursor( - Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); - -/* -** Write a 64-bit variable-length integer to memory starting at p[0]. -** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. -** The number of bytes written is returned. -*/ -SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ - unsigned char *q = (unsigned char *) p; - sqlite_uint64 vu = v; - do{ - *q++ = (unsigned char) ((vu & 0x7f) | 0x80); - vu >>= 7; - }while( vu!=0 ); - q[-1] &= 0x7f; /* turn off high bit in final byte */ - assert( q - (unsigned char *)p <= FTS3_VARINT_MAX ); - return (int) (q - (unsigned char *)p); -} - -/* -** Read a 64-bit variable-length integer from memory starting at p[0]. -** Return the number of bytes read, or 0 on error. -** The value is stored in *v. -*/ -SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){ - const unsigned char *q = (const unsigned char *) p; - sqlite_uint64 x = 0, y = 1; - while( (*q&0x80)==0x80 && q-(unsigned char *)p>= 7; - }while( v!=0 ); - return i; -} - -/* -** Convert an SQL-style quoted string into a normal string by removing -** the quote characters. The conversion is done in-place. If the -** input does not begin with a quote character, then this routine -** is a no-op. -** -** Examples: -** -** "abc" becomes abc -** 'xyz' becomes xyz -** [pqr] becomes pqr -** `mno` becomes mno -** -*/ -SQLITE_PRIVATE void sqlite3Fts3Dequote(char *z){ - char quote; /* Quote character (if any ) */ - - quote = z[0]; - if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ - int iIn = 1; /* Index of next byte to read from input */ - int iOut = 0; /* Index of next byte to write to output */ - - /* If the first byte was a '[', then the close-quote character is a ']' */ - if( quote=='[' ) quote = ']'; - - while( ALWAYS(z[iIn]) ){ - if( z[iIn]==quote ){ - if( z[iIn+1]!=quote ) break; - z[iOut++] = quote; - iIn += 2; - }else{ - z[iOut++] = z[iIn++]; - } - } - z[iOut] = '\0'; - } -} - -/* -** Read a single varint from the doclist at *pp and advance *pp to point -** to the first byte past the end of the varint. Add the value of the varint -** to *pVal. -*/ -static void fts3GetDeltaVarint(char **pp, sqlite3_int64 *pVal){ - sqlite3_int64 iVal; - *pp += sqlite3Fts3GetVarint(*pp, &iVal); - *pVal += iVal; -} - -/* -** When this function is called, *pp points to the first byte following a -** varint that is part of a doclist (or position-list, or any other list -** of varints). This function moves *pp to point to the start of that varint, -** and sets *pVal by the varint value. -** -** Argument pStart points to the first byte of the doclist that the -** varint is part of. -*/ -static void fts3GetReverseVarint( - char **pp, - char *pStart, - sqlite3_int64 *pVal -){ - sqlite3_int64 iVal; - char *p; - - /* Pointer p now points at the first byte past the varint we are - ** interested in. So, unless the doclist is corrupt, the 0x80 bit is - ** clear on character p[-1]. */ - for(p = (*pp)-2; p>=pStart && *p&0x80; p--); - p++; - *pp = p; - - sqlite3Fts3GetVarint(p, &iVal); - *pVal = iVal; -} - -/* -** The xDisconnect() virtual table method. -*/ -static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table *)pVtab; - int i; - - assert( p->nPendingData==0 ); - assert( p->pSegments==0 ); - - /* Free any prepared statements held */ - for(i=0; iaStmt); i++){ - sqlite3_finalize(p->aStmt[i]); - } - sqlite3_free(p->zSegmentsTbl); - sqlite3_free(p->zReadExprlist); - sqlite3_free(p->zWriteExprlist); - sqlite3_free(p->zContentTbl); - sqlite3_free(p->zLanguageid); - - /* Invoke the tokenizer destructor to free the tokenizer. */ - p->pTokenizer->pModule->xDestroy(p->pTokenizer); - - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Construct one or more SQL statements from the format string given -** and then evaluate those statements. The success code is written -** into *pRc. -** -** If *pRc is initially non-zero then this routine is a no-op. -*/ -static void fts3DbExec( - int *pRc, /* Success code */ - sqlite3 *db, /* Database in which to run SQL */ - const char *zFormat, /* Format string for SQL */ - ... /* Arguments to the format string */ -){ - va_list ap; - char *zSql; - if( *pRc ) return; - va_start(ap, zFormat); - zSql = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - if( zSql==0 ){ - *pRc = SQLITE_NOMEM; - }else{ - *pRc = sqlite3_exec(db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } -} - -/* -** The xDestroy() virtual table method. -*/ -static int fts3DestroyMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table *)pVtab; - int rc = SQLITE_OK; /* Return code */ - const char *zDb = p->zDb; /* Name of database (e.g. "main", "temp") */ - sqlite3 *db = p->db; /* Database handle */ - - /* Drop the shadow tables */ - if( p->zContentTbl==0 ){ - fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName); - } - fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName); - fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName); - fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName); - fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName); - - /* If everything has worked, invoke fts3DisconnectMethod() to free the - ** memory associated with the Fts3Table structure and return SQLITE_OK. - ** Otherwise, return an SQLite error code. - */ - return (rc==SQLITE_OK ? fts3DisconnectMethod(pVtab) : rc); -} - - -/* -** Invoke sqlite3_declare_vtab() to declare the schema for the FTS3 table -** passed as the first argument. This is done as part of the xConnect() -** and xCreate() methods. -** -** If *pRc is non-zero when this function is called, it is a no-op. -** Otherwise, if an error occurs, an SQLite error code is stored in *pRc -** before returning. -*/ -static void fts3DeclareVtab(int *pRc, Fts3Table *p){ - if( *pRc==SQLITE_OK ){ - int i; /* Iterator variable */ - int rc; /* Return code */ - char *zSql; /* SQL statement passed to declare_vtab() */ - char *zCols; /* List of user defined columns */ - const char *zLanguageid; - - zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid"); - sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - - /* Create a list of user columns for the virtual table */ - zCols = sqlite3_mprintf("%Q, ", p->azColumn[0]); - for(i=1; zCols && inColumn; i++){ - zCols = sqlite3_mprintf("%z%Q, ", zCols, p->azColumn[i]); - } - - /* Create the whole "CREATE TABLE" statement to pass to SQLite */ - zSql = sqlite3_mprintf( - "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)", - zCols, p->zName, zLanguageid - ); - if( !zCols || !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_declare_vtab(p->db, zSql); - } - - sqlite3_free(zSql); - sqlite3_free(zCols); - *pRc = rc; - } -} - -/* -** Create the %_stat table if it does not already exist. -*/ -SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){ - fts3DbExec(pRc, p->db, - "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'" - "(id INTEGER PRIMARY KEY, value BLOB);", - p->zDb, p->zName - ); - if( (*pRc)==SQLITE_OK ) p->bHasStat = 1; -} - -/* -** Create the backing store tables (%_content, %_segments and %_segdir) -** required by the FTS3 table passed as the only argument. This is done -** as part of the vtab xCreate() method. -** -** If the p->bHasDocsize boolean is true (indicating that this is an -** FTS4 table, not an FTS3 table) then also create the %_docsize and -** %_stat tables required by FTS4. -*/ -static int fts3CreateTables(Fts3Table *p){ - int rc = SQLITE_OK; /* Return code */ - int i; /* Iterator variable */ - sqlite3 *db = p->db; /* The database connection */ - - if( p->zContentTbl==0 ){ - const char *zLanguageid = p->zLanguageid; - char *zContentCols; /* Columns of %_content table */ - - /* Create a list of user columns for the content table */ - zContentCols = sqlite3_mprintf("docid INTEGER PRIMARY KEY"); - for(i=0; zContentCols && inColumn; i++){ - char *z = p->azColumn[i]; - zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); - } - if( zLanguageid && zContentCols ){ - zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid); - } - if( zContentCols==0 ) rc = SQLITE_NOMEM; - - /* Create the content table */ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_content'(%s)", - p->zDb, p->zName, zContentCols - ); - sqlite3_free(zContentCols); - } - - /* Create other tables */ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", - p->zDb, p->zName - ); - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_segdir'(" - "level INTEGER," - "idx INTEGER," - "start_block INTEGER," - "leaves_end_block INTEGER," - "end_block INTEGER," - "root BLOB," - "PRIMARY KEY(level, idx)" - ");", - p->zDb, p->zName - ); - if( p->bHasDocsize ){ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", - p->zDb, p->zName - ); - } - assert( p->bHasStat==p->bFts4 ); - if( p->bHasStat ){ - sqlite3Fts3CreateStatTable(&rc, p); - } - return rc; -} - -/* -** Store the current database page-size in bytes in p->nPgsz. -** -** If *pRc is non-zero when this function is called, it is a no-op. -** Otherwise, if an error occurs, an SQLite error code is stored in *pRc -** before returning. -*/ -static void fts3DatabasePageSize(int *pRc, Fts3Table *p){ - if( *pRc==SQLITE_OK ){ - int rc; /* Return code */ - char *zSql; /* SQL text "PRAGMA %Q.page_size" */ - sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */ - - zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_step(pStmt); - p->nPgsz = sqlite3_column_int(pStmt, 0); - rc = sqlite3_finalize(pStmt); - }else if( rc==SQLITE_AUTH ){ - p->nPgsz = 1024; - rc = SQLITE_OK; - } - } - assert( p->nPgsz>0 || rc!=SQLITE_OK ); - sqlite3_free(zSql); - *pRc = rc; - } -} - -/* -** "Special" FTS4 arguments are column specifications of the following form: -** -** = -** -** There may not be whitespace surrounding the "=" character. The -** term may be quoted, but the may not. -*/ -static int fts3IsSpecialColumn( - const char *z, - int *pnKey, - char **pzValue -){ - char *zValue; - const char *zCsr = z; - - while( *zCsr!='=' ){ - if( *zCsr=='\0' ) return 0; - zCsr++; - } - - *pnKey = (int)(zCsr-z); - zValue = sqlite3_mprintf("%s", &zCsr[1]); - if( zValue ){ - sqlite3Fts3Dequote(zValue); - } - *pzValue = zValue; - return 1; -} - -/* -** Append the output of a printf() style formatting to an existing string. -*/ -static void fts3Appendf( - int *pRc, /* IN/OUT: Error code */ - char **pz, /* IN/OUT: Pointer to string buffer */ - const char *zFormat, /* Printf format string to append */ - ... /* Arguments for printf format string */ -){ - if( *pRc==SQLITE_OK ){ - va_list ap; - char *z; - va_start(ap, zFormat); - z = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - if( z && *pz ){ - char *z2 = sqlite3_mprintf("%s%s", *pz, z); - sqlite3_free(z); - z = z2; - } - if( z==0 ) *pRc = SQLITE_NOMEM; - sqlite3_free(*pz); - *pz = z; - } -} - -/* -** Return a copy of input string zInput enclosed in double-quotes (") and -** with all double quote characters escaped. For example: -** -** fts3QuoteId("un \"zip\"") -> "un \"\"zip\"\"" -** -** The pointer returned points to memory obtained from sqlite3_malloc(). It -** is the callers responsibility to call sqlite3_free() to release this -** memory. -*/ -static char *fts3QuoteId(char const *zInput){ - int nRet; - char *zRet; - nRet = 2 + (int)strlen(zInput)*2 + 1; - zRet = sqlite3_malloc(nRet); - if( zRet ){ - int i; - char *z = zRet; - *(z++) = '"'; - for(i=0; zInput[i]; i++){ - if( zInput[i]=='"' ) *(z++) = '"'; - *(z++) = zInput[i]; - } - *(z++) = '"'; - *(z++) = '\0'; - } - return zRet; -} - -/* -** Return a list of comma separated SQL expressions and a FROM clause that -** could be used in a SELECT statement such as the following: -** -** SELECT FROM %_content AS x ... -** -** to return the docid, followed by each column of text data in order -** from left to write. If parameter zFunc is not NULL, then instead of -** being returned directly each column of text data is passed to an SQL -** function named zFunc first. For example, if zFunc is "unzip" and the -** table has the three user-defined columns "a", "b", and "c", the following -** string is returned: -** -** "docid, unzip(x.'a'), unzip(x.'b'), unzip(x.'c') FROM %_content AS x" -** -** The pointer returned points to a buffer allocated by sqlite3_malloc(). It -** is the responsibility of the caller to eventually free it. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and -** a NULL pointer is returned). Otherwise, if an OOM error is encountered -** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If -** no error occurs, *pRc is left unmodified. -*/ -static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){ - char *zRet = 0; - char *zFree = 0; - char *zFunction; - int i; - - if( p->zContentTbl==0 ){ - if( !zFunc ){ - zFunction = ""; - }else{ - zFree = zFunction = fts3QuoteId(zFunc); - } - fts3Appendf(pRc, &zRet, "docid"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", x.%Q", "langid"); - } - sqlite3_free(zFree); - }else{ - fts3Appendf(pRc, &zRet, "rowid"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid); - } - } - fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x", - p->zDb, - (p->zContentTbl ? p->zContentTbl : p->zName), - (p->zContentTbl ? "" : "_content") - ); - return zRet; -} - -/* -** Return a list of N comma separated question marks, where N is the number -** of columns in the %_content table (one for the docid plus one for each -** user-defined text column). -** -** If argument zFunc is not NULL, then all but the first question mark -** is preceded by zFunc and an open bracket, and followed by a closed -** bracket. For example, if zFunc is "zip" and the FTS3 table has three -** user-defined text columns, the following string is returned: -** -** "?, zip(?), zip(?), zip(?)" -** -** The pointer returned points to a buffer allocated by sqlite3_malloc(). It -** is the responsibility of the caller to eventually free it. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op (and -** a NULL pointer is returned). Otherwise, if an OOM error is encountered -** by this function, NULL is returned and *pRc is set to SQLITE_NOMEM. If -** no error occurs, *pRc is left unmodified. -*/ -static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){ - char *zRet = 0; - char *zFree = 0; - char *zFunction; - int i; - - if( !zFunc ){ - zFunction = ""; - }else{ - zFree = zFunction = fts3QuoteId(zFunc); - } - fts3Appendf(pRc, &zRet, "?"); - for(i=0; inColumn; i++){ - fts3Appendf(pRc, &zRet, ",%s(?)", zFunction); - } - if( p->zLanguageid ){ - fts3Appendf(pRc, &zRet, ", ?"); - } - sqlite3_free(zFree); - return zRet; -} - -/* -** This function interprets the string at (*pp) as a non-negative integer -** value. It reads the integer and sets *pnOut to the value read, then -** sets *pp to point to the byte immediately following the last byte of -** the integer value. -** -** Only decimal digits ('0'..'9') may be part of an integer value. -** -** If *pp does not being with a decimal digit SQLITE_ERROR is returned and -** the output value undefined. Otherwise SQLITE_OK is returned. -** -** This function is used when parsing the "prefix=" FTS4 parameter. -*/ -static int fts3GobbleInt(const char **pp, int *pnOut){ - const char *p; /* Iterator pointer */ - int nInt = 0; /* Output value */ - - for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ - nInt = nInt * 10 + (p[0] - '0'); - } - if( p==*pp ) return SQLITE_ERROR; - *pnOut = nInt; - *pp = p; - return SQLITE_OK; -} - -/* -** This function is called to allocate an array of Fts3Index structures -** representing the indexes maintained by the current FTS table. FTS tables -** always maintain the main "terms" index, but may also maintain one or -** more "prefix" indexes, depending on the value of the "prefix=" parameter -** (if any) specified as part of the CREATE VIRTUAL TABLE statement. -** -** Argument zParam is passed the value of the "prefix=" option if one was -** specified, or NULL otherwise. -** -** If no error occurs, SQLITE_OK is returned and *apIndex set to point to -** the allocated array. *pnIndex is set to the number of elements in the -** array. If an error does occur, an SQLite error code is returned. -** -** Regardless of whether or not an error is returned, it is the responsibility -** of the caller to call sqlite3_free() on the output array to free it. -*/ -static int fts3PrefixParameter( - const char *zParam, /* ABC in prefix=ABC parameter to parse */ - int *pnIndex, /* OUT: size of *apIndex[] array */ - struct Fts3Index **apIndex /* OUT: Array of indexes for this table */ -){ - struct Fts3Index *aIndex; /* Allocated array */ - int nIndex = 1; /* Number of entries in array */ - - if( zParam && zParam[0] ){ - const char *p; - nIndex++; - for(p=zParam; *p; p++){ - if( *p==',' ) nIndex++; - } - } - - aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); - *apIndex = aIndex; - *pnIndex = nIndex; - if( !aIndex ){ - return SQLITE_NOMEM; - } - - memset(aIndex, 0, sizeof(struct Fts3Index) * nIndex); - if( zParam ){ - const char *p = zParam; - int i; - for(i=1; i module name ("fts3" or "fts4") -** argv[1] -> database name -** argv[2] -> table name -** argv[...] -> "column name" and other module argument fields. -*/ -static int fts3InitVtab( - int isCreate, /* True for xCreate, false for xConnect */ - sqlite3 *db, /* The SQLite database connection */ - void *pAux, /* Hash table containing tokenizers */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ - char **pzErr /* Write any error message here */ -){ - Fts3Hash *pHash = (Fts3Hash *)pAux; - Fts3Table *p = 0; /* Pointer to allocated vtab */ - int rc = SQLITE_OK; /* Return code */ - int i; /* Iterator variable */ - int nByte; /* Size of allocation used for *p */ - int iCol; /* Column index */ - int nString = 0; /* Bytes required to hold all column names */ - int nCol = 0; /* Number of columns in the FTS table */ - char *zCsr; /* Space for holding column names */ - int nDb; /* Bytes required to hold database name */ - int nName; /* Bytes required to hold table name */ - int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */ - const char **aCol; /* Array of column names */ - sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ - - int nIndex; /* Size of aIndex[] array */ - struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ - - /* The results of parsing supported FTS4 key=value options: */ - int bNoDocsize = 0; /* True to omit %_docsize table */ - int bDescIdx = 0; /* True to store descending indexes */ - char *zPrefix = 0; /* Prefix parameter value (or NULL) */ - char *zCompress = 0; /* compress=? parameter (or NULL) */ - char *zUncompress = 0; /* uncompress=? parameter (or NULL) */ - char *zContent = 0; /* content=? parameter (or NULL) */ - char *zLanguageid = 0; /* languageid=? parameter (or NULL) */ - - assert( strlen(argv[0])==4 ); - assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4) - || (sqlite3_strnicmp(argv[0], "fts3", 4)==0 && !isFts4) - ); - - nDb = (int)strlen(argv[1]) + 1; - nName = (int)strlen(argv[2]) + 1; - - aCol = (const char **)sqlite3_malloc(sizeof(const char *) * (argc-2) ); - if( !aCol ) return SQLITE_NOMEM; - memset((void *)aCol, 0, sizeof(const char *) * (argc-2)); - - /* Loop through all of the arguments passed by the user to the FTS3/4 - ** module (i.e. all the column names and special arguments). This loop - ** does the following: - ** - ** + Figures out the number of columns the FTSX table will have, and - ** the number of bytes of space that must be allocated to store copies - ** of the column names. - ** - ** + If there is a tokenizer specification included in the arguments, - ** initializes the tokenizer pTokenizer. - */ - for(i=3; rc==SQLITE_OK && i8 - && 0==sqlite3_strnicmp(z, "tokenize", 8) - && 0==sqlite3Fts3IsIdChar(z[8]) - ){ - rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr); - } - - /* Check if it is an FTS4 special argument. */ - else if( isFts4 && fts3IsSpecialColumn(z, &nKey, &zVal) ){ - struct Fts4Option { - const char *zOpt; - int nOpt; - } aFts4Opt[] = { - { "matchinfo", 9 }, /* 0 -> MATCHINFO */ - { "prefix", 6 }, /* 1 -> PREFIX */ - { "compress", 8 }, /* 2 -> COMPRESS */ - { "uncompress", 10 }, /* 3 -> UNCOMPRESS */ - { "order", 5 }, /* 4 -> ORDER */ - { "content", 7 }, /* 5 -> CONTENT */ - { "languageid", 10 } /* 6 -> LANGUAGEID */ - }; - - int iOpt; - if( !zVal ){ - rc = SQLITE_NOMEM; - }else{ - for(iOpt=0; iOptnOpt && !sqlite3_strnicmp(z, pOp->zOpt, pOp->nOpt) ){ - break; - } - } - if( iOpt==SizeofArray(aFts4Opt) ){ - *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z); - rc = SQLITE_ERROR; - }else{ - switch( iOpt ){ - case 0: /* MATCHINFO */ - if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ - *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal); - rc = SQLITE_ERROR; - } - bNoDocsize = 1; - break; - - case 1: /* PREFIX */ - sqlite3_free(zPrefix); - zPrefix = zVal; - zVal = 0; - break; - - case 2: /* COMPRESS */ - sqlite3_free(zCompress); - zCompress = zVal; - zVal = 0; - break; - - case 3: /* UNCOMPRESS */ - sqlite3_free(zUncompress); - zUncompress = zVal; - zVal = 0; - break; - - case 4: /* ORDER */ - if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) - && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) - ){ - *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal); - rc = SQLITE_ERROR; - } - bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); - break; - - case 5: /* CONTENT */ - sqlite3_free(zContent); - zContent = zVal; - zVal = 0; - break; - - case 6: /* LANGUAGEID */ - assert( iOpt==6 ); - sqlite3_free(zLanguageid); - zLanguageid = zVal; - zVal = 0; - break; - } - } - sqlite3_free(zVal); - } - } - - /* Otherwise, the argument is a column name. */ - else { - nString += (int)(strlen(z) + 1); - aCol[nCol++] = z; - } - } - - /* If a content=xxx option was specified, the following: - ** - ** 1. Ignore any compress= and uncompress= options. - ** - ** 2. If no column names were specified as part of the CREATE VIRTUAL - ** TABLE statement, use all columns from the content table. - */ - if( rc==SQLITE_OK && zContent ){ - sqlite3_free(zCompress); - sqlite3_free(zUncompress); - zCompress = 0; - zUncompress = 0; - if( nCol==0 ){ - sqlite3_free((void*)aCol); - aCol = 0; - rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); - - /* If a languageid= option was specified, remove the language id - ** column from the aCol[] array. */ - if( rc==SQLITE_OK && zLanguageid ){ - int j; - for(j=0; jdb = db; - p->nColumn = nCol; - p->nPendingData = 0; - p->azColumn = (char **)&p[1]; - p->pTokenizer = pTokenizer; - p->nMaxPendingData = FTS3_MAX_PENDING_DATA; - p->bHasDocsize = (isFts4 && bNoDocsize==0); - p->bHasStat = isFts4; - p->bFts4 = isFts4; - p->bDescIdx = bDescIdx; - p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */ - p->zContentTbl = zContent; - p->zLanguageid = zLanguageid; - zContent = 0; - zLanguageid = 0; - TESTONLY( p->inTransaction = -1 ); - TESTONLY( p->mxSavepoint = -1 ); - - p->aIndex = (struct Fts3Index *)&p->azColumn[nCol]; - memcpy(p->aIndex, aIndex, sizeof(struct Fts3Index) * nIndex); - p->nIndex = nIndex; - for(i=0; iaIndex[i].hPending, FTS3_HASH_STRING, 1); - } - - /* Fill in the zName and zDb fields of the vtab structure. */ - zCsr = (char *)&p->aIndex[nIndex]; - p->zName = zCsr; - memcpy(zCsr, argv[2], nName); - zCsr += nName; - p->zDb = zCsr; - memcpy(zCsr, argv[1], nDb); - zCsr += nDb; - - /* Fill in the azColumn array */ - for(iCol=0; iColazColumn[iCol] = zCsr; - zCsr += n+1; - assert( zCsr <= &((char *)p)[nByte] ); - } - - if( (zCompress==0)!=(zUncompress==0) ){ - char const *zMiss = (zCompress==0 ? "compress" : "uncompress"); - rc = SQLITE_ERROR; - *pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss); - } - p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc); - p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); - if( rc!=SQLITE_OK ) goto fts3_init_out; - - /* If this is an xCreate call, create the underlying tables in the - ** database. TODO: For xConnect(), it could verify that said tables exist. - */ - if( isCreate ){ - rc = fts3CreateTables(p); - } - - /* Check to see if a legacy fts3 table has been "upgraded" by the - ** addition of a %_stat table so that it can use incremental merge. - */ - if( !isFts4 && !isCreate ){ - int rc2 = SQLITE_OK; - fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2", - p->zDb, p->zName); - if( rc2==SQLITE_OK ) p->bHasStat = 1; - } - - /* Figure out the page-size for the database. This is required in order to - ** estimate the cost of loading large doclists from the database. */ - fts3DatabasePageSize(&rc, p); - p->nNodeSize = p->nPgsz-35; - - /* Declare the table schema to SQLite. */ - fts3DeclareVtab(&rc, p); - -fts3_init_out: - sqlite3_free(zPrefix); - sqlite3_free(aIndex); - sqlite3_free(zCompress); - sqlite3_free(zUncompress); - sqlite3_free(zContent); - sqlite3_free(zLanguageid); - sqlite3_free((void *)aCol); - if( rc!=SQLITE_OK ){ - if( p ){ - fts3DisconnectMethod((sqlite3_vtab *)p); - }else if( pTokenizer ){ - pTokenizer->pModule->xDestroy(pTokenizer); - } - }else{ - assert( p->pSegments==0 ); - *ppVTab = &p->base; - } - return rc; -} - -/* -** The xConnect() and xCreate() methods for the virtual table. All the -** work is done in function fts3InitVtab(). -*/ -static int fts3ConnectMethod( - sqlite3 *db, /* Database connection */ - void *pAux, /* Pointer to tokenizer hash table */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - return fts3InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr); -} -static int fts3CreateMethod( - sqlite3 *db, /* Database connection */ - void *pAux, /* Pointer to tokenizer hash table */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr); -} - -/* -** Implementation of the xBestIndex method for FTS3 tables. There -** are three possible strategies, in order of preference: -** -** 1. Direct lookup by rowid or docid. -** 2. Full-text search using a MATCH operator on a non-docid column. -** 3. Linear scan of %_content table. -*/ -static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ - Fts3Table *p = (Fts3Table *)pVTab; - int i; /* Iterator variable */ - int iCons = -1; /* Index of constraint to use */ - int iLangidCons = -1; /* Index of langid=x constraint, if present */ - - /* By default use a full table scan. This is an expensive option, - ** so search through the constraints to see if a more efficient - ** strategy is possible. - */ - pInfo->idxNum = FTS3_FULLSCAN_SEARCH; - pInfo->estimatedCost = 500000; - for(i=0; inConstraint; i++){ - struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i]; - if( pCons->usable==0 ) continue; - - /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ - if( iCons<0 - && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ - && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 ) - ){ - pInfo->idxNum = FTS3_DOCID_SEARCH; - pInfo->estimatedCost = 1.0; - iCons = i; - } - - /* A MATCH constraint. Use a full-text search. - ** - ** If there is more than one MATCH constraint available, use the first - ** one encountered. If there is both a MATCH constraint and a direct - ** rowid/docid lookup, prefer the MATCH strategy. This is done even - ** though the rowid/docid lookup is faster than a MATCH query, selecting - ** it would lead to an "unable to use function MATCH in the requested - ** context" error. - */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH - && pCons->iColumn>=0 && pCons->iColumn<=p->nColumn - ){ - pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn; - pInfo->estimatedCost = 2.0; - iCons = i; - } - - /* Equality constraint on the langid column */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ - && pCons->iColumn==p->nColumn + 2 - ){ - iLangidCons = i; - } - } - - if( iCons>=0 ){ - pInfo->aConstraintUsage[iCons].argvIndex = 1; - pInfo->aConstraintUsage[iCons].omit = 1; - } - if( iLangidCons>=0 ){ - pInfo->aConstraintUsage[iLangidCons].argvIndex = 2; - } - - /* Regardless of the strategy selected, FTS can deliver rows in rowid (or - ** docid) order. Both ascending and descending are possible. - */ - if( pInfo->nOrderBy==1 ){ - struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0]; - if( pOrder->iColumn<0 || pOrder->iColumn==p->nColumn+1 ){ - if( pOrder->desc ){ - pInfo->idxStr = "DESC"; - }else{ - pInfo->idxStr = "ASC"; - } - pInfo->orderByConsumed = 1; - } - } - - assert( p->pSegments==0 ); - return SQLITE_OK; -} - -/* -** Implementation of xOpen method. -*/ -static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - sqlite3_vtab_cursor *pCsr; /* Allocated cursor */ - - UNUSED_PARAMETER(pVTab); - - /* Allocate a buffer large enough for an Fts3Cursor structure. If the - ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, - ** if the allocation fails, return SQLITE_NOMEM. - */ - *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor)); - if( !pCsr ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(Fts3Cursor)); - return SQLITE_OK; -} - -/* -** Close the cursor. For additional information see the documentation -** on the xClose method of the virtual table interface. -*/ -static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - sqlite3_finalize(pCsr->pStmt); - sqlite3Fts3ExprFree(pCsr->pExpr); - sqlite3Fts3FreeDeferredTokens(pCsr); - sqlite3_free(pCsr->aDoclist); - sqlite3_free(pCsr->aMatchinfo); - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then -** compose and prepare an SQL statement of the form: -** -** "SELECT FROM %_content WHERE rowid = ?" -** -** (or the equivalent for a content=xxx table) and set pCsr->pStmt to -** it. If an error occurs, return an SQLite error code. -** -** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK. -*/ -static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){ - int rc = SQLITE_OK; - if( pCsr->pStmt==0 ){ - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - char *zSql; - zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); - if( !zSql ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); - sqlite3_free(zSql); - } - *ppStmt = pCsr->pStmt; - return rc; -} - -/* -** Position the pCsr->pStmt statement so that it is on the row -** of the %_content table that contains the last match. Return -** SQLITE_OK on success. -*/ -static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){ - int rc = SQLITE_OK; - if( pCsr->isRequireSeek ){ - sqlite3_stmt *pStmt = 0; - - rc = fts3CursorSeekStmt(pCsr, &pStmt); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); - pCsr->isRequireSeek = 0; - if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ - return SQLITE_OK; - }else{ - rc = sqlite3_reset(pCsr->pStmt); - if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){ - /* If no row was found and no error has occurred, then the %_content - ** table is missing a row that is present in the full-text index. - ** The data structures are corrupt. */ - rc = FTS_CORRUPT_VTAB; - pCsr->isEof = 1; - } - } - } - } - - if( rc!=SQLITE_OK && pContext ){ - sqlite3_result_error_code(pContext, rc); - } - return rc; -} - -/* -** This function is used to process a single interior node when searching -** a b-tree for a term or term prefix. The node data is passed to this -** function via the zNode/nNode parameters. The term to search for is -** passed in zTerm/nTerm. -** -** If piFirst is not NULL, then this function sets *piFirst to the blockid -** of the child node that heads the sub-tree that may contain the term. -** -** If piLast is not NULL, then *piLast is set to the right-most child node -** that heads a sub-tree that may contain a term for which zTerm/nTerm is -** a prefix. -** -** If an OOM error occurs, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK. -*/ -static int fts3ScanInteriorNode( - const char *zTerm, /* Term to select leaves for */ - int nTerm, /* Size of term zTerm in bytes */ - const char *zNode, /* Buffer containing segment interior node */ - int nNode, /* Size of buffer at zNode */ - sqlite3_int64 *piFirst, /* OUT: Selected child node */ - sqlite3_int64 *piLast /* OUT: Selected child node */ -){ - int rc = SQLITE_OK; /* Return code */ - const char *zCsr = zNode; /* Cursor to iterate through node */ - const char *zEnd = &zCsr[nNode];/* End of interior node buffer */ - char *zBuffer = 0; /* Buffer to load terms into */ - int nAlloc = 0; /* Size of allocated buffer */ - int isFirstTerm = 1; /* True when processing first term on page */ - sqlite3_int64 iChild; /* Block id of child node to descend to */ - - /* Skip over the 'height' varint that occurs at the start of every - ** interior node. Then load the blockid of the left-child of the b-tree - ** node into variable iChild. - ** - ** Even if the data structure on disk is corrupted, this (reading two - ** varints from the buffer) does not risk an overread. If zNode is a - ** root node, then the buffer comes from a SELECT statement. SQLite does - ** not make this guarantee explicitly, but in practice there are always - ** either more than 20 bytes of allocated space following the nNode bytes of - ** contents, or two zero bytes. Or, if the node is read from the %_segments - ** table, then there are always 20 bytes of zeroed padding following the - ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details). - */ - zCsr += sqlite3Fts3GetVarint(zCsr, &iChild); - zCsr += sqlite3Fts3GetVarint(zCsr, &iChild); - if( zCsr>zEnd ){ - return FTS_CORRUPT_VTAB; - } - - while( zCsrzEnd ){ - rc = FTS_CORRUPT_VTAB; - goto finish_scan; - } - if( nPrefix+nSuffix>nAlloc ){ - char *zNew; - nAlloc = (nPrefix+nSuffix) * 2; - zNew = (char *)sqlite3_realloc(zBuffer, nAlloc); - if( !zNew ){ - rc = SQLITE_NOMEM; - goto finish_scan; - } - zBuffer = zNew; - } - assert( zBuffer ); - memcpy(&zBuffer[nPrefix], zCsr, nSuffix); - nBuffer = nPrefix + nSuffix; - zCsr += nSuffix; - - /* Compare the term we are searching for with the term just loaded from - ** the interior node. If the specified term is greater than or equal - ** to the term from the interior node, then all terms on the sub-tree - ** headed by node iChild are smaller than zTerm. No need to search - ** iChild. - ** - ** If the interior node term is larger than the specified term, then - ** the tree headed by iChild may contain the specified term. - */ - cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer)); - if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){ - *piFirst = iChild; - piFirst = 0; - } - - if( piLast && cmp<0 ){ - *piLast = iChild; - piLast = 0; - } - - iChild++; - }; - - if( piFirst ) *piFirst = iChild; - if( piLast ) *piLast = iChild; - - finish_scan: - sqlite3_free(zBuffer); - return rc; -} - - -/* -** The buffer pointed to by argument zNode (size nNode bytes) contains an -** interior node of a b-tree segment. The zTerm buffer (size nTerm bytes) -** contains a term. This function searches the sub-tree headed by the zNode -** node for the range of leaf nodes that may contain the specified term -** or terms for which the specified term is a prefix. -** -** If piLeaf is not NULL, then *piLeaf is set to the blockid of the -** left-most leaf node in the tree that may contain the specified term. -** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the -** right-most leaf node that may contain a term for which the specified -** term is a prefix. -** -** It is possible that the range of returned leaf nodes does not contain -** the specified term or any terms for which it is a prefix. However, if the -** segment does contain any such terms, they are stored within the identified -** range. Because this function only inspects interior segment nodes (and -** never loads leaf nodes into memory), it is not possible to be sure. -** -** If an error occurs, an error code other than SQLITE_OK is returned. -*/ -static int fts3SelectLeaf( - Fts3Table *p, /* Virtual table handle */ - const char *zTerm, /* Term to select leaves for */ - int nTerm, /* Size of term zTerm in bytes */ - const char *zNode, /* Buffer containing segment interior node */ - int nNode, /* Size of buffer at zNode */ - sqlite3_int64 *piLeaf, /* Selected leaf node */ - sqlite3_int64 *piLeaf2 /* Selected leaf node */ -){ - int rc; /* Return code */ - int iHeight; /* Height of this node in tree */ - - assert( piLeaf || piLeaf2 ); - - sqlite3Fts3GetVarint32(zNode, &iHeight); - rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); - assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); - - if( rc==SQLITE_OK && iHeight>1 ){ - char *zBlob = 0; /* Blob read from %_segments table */ - int nBlob; /* Size of zBlob in bytes */ - - if( piLeaf && piLeaf2 && (*piLeaf!=*piLeaf2) ){ - rc = sqlite3Fts3ReadBlock(p, *piLeaf, &zBlob, &nBlob, 0); - if( rc==SQLITE_OK ){ - rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, 0); - } - sqlite3_free(zBlob); - piLeaf = 0; - zBlob = 0; - } - - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0); - } - if( rc==SQLITE_OK ){ - rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2); - } - sqlite3_free(zBlob); - } - - return rc; -} - -/* -** This function is used to create delta-encoded serialized lists of FTS3 -** varints. Each call to this function appends a single varint to a list. -*/ -static void fts3PutDeltaVarint( - char **pp, /* IN/OUT: Output pointer */ - sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ - sqlite3_int64 iVal /* Write this value to the list */ -){ - assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) ); - *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev); - *piPrev = iVal; -} - -/* -** When this function is called, *ppPoslist is assumed to point to the -** start of a position-list. After it returns, *ppPoslist points to the -** first byte after the position-list. -** -** A position list is list of positions (delta encoded) and columns for -** a single document record of a doclist. So, in other words, this -** routine advances *ppPoslist so that it points to the next docid in -** the doclist, or to the first byte past the end of the doclist. -** -** If pp is not NULL, then the contents of the position list are copied -** to *pp. *pp is set to point to the first byte past the last byte copied -** before this function returns. -*/ -static void fts3PoslistCopy(char **pp, char **ppPoslist){ - char *pEnd = *ppPoslist; - char c = 0; - - /* The end of a position list is marked by a zero encoded as an FTS3 - ** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by - ** a byte with the 0x80 bit set, then it is not a varint 0, but the tail - ** of some other, multi-byte, value. - ** - ** The following while-loop moves pEnd to point to the first byte that is not - ** immediately preceded by a byte with the 0x80 bit set. Then increments - ** pEnd once more so that it points to the byte immediately following the - ** last byte in the position-list. - */ - while( *pEnd | c ){ - c = *pEnd++ & 0x80; - testcase( c!=0 && (*pEnd)==0 ); - } - pEnd++; /* Advance past the POS_END terminator byte */ - - if( pp ){ - int n = (int)(pEnd - *ppPoslist); - char *p = *pp; - memcpy(p, *ppPoslist, n); - p += n; - *pp = p; - } - *ppPoslist = pEnd; -} - -/* -** When this function is called, *ppPoslist is assumed to point to the -** start of a column-list. After it returns, *ppPoslist points to the -** to the terminator (POS_COLUMN or POS_END) byte of the column-list. -** -** A column-list is list of delta-encoded positions for a single column -** within a single document within a doclist. -** -** The column-list is terminated either by a POS_COLUMN varint (1) or -** a POS_END varint (0). This routine leaves *ppPoslist pointing to -** the POS_COLUMN or POS_END that terminates the column-list. -** -** If pp is not NULL, then the contents of the column-list are copied -** to *pp. *pp is set to point to the first byte past the last byte copied -** before this function returns. The POS_COLUMN or POS_END terminator -** is not copied into *pp. -*/ -static void fts3ColumnlistCopy(char **pp, char **ppPoslist){ - char *pEnd = *ppPoslist; - char c = 0; - - /* A column-list is terminated by either a 0x01 or 0x00 byte that is - ** not part of a multi-byte varint. - */ - while( 0xFE & (*pEnd | c) ){ - c = *pEnd++ & 0x80; - testcase( c!=0 && ((*pEnd)&0xfe)==0 ); - } - if( pp ){ - int n = (int)(pEnd - *ppPoslist); - char *p = *pp; - memcpy(p, *ppPoslist, n); - p += n; - *pp = p; - } - *ppPoslist = pEnd; -} - -/* -** Value used to signify the end of an position-list. This is safe because -** it is not possible to have a document with 2^31 terms. -*/ -#define POSITION_LIST_END 0x7fffffff - -/* -** This function is used to help parse position-lists. When this function is -** called, *pp may point to the start of the next varint in the position-list -** being parsed, or it may point to 1 byte past the end of the position-list -** (in which case **pp will be a terminator bytes POS_END (0) or -** (1)). -** -** If *pp points past the end of the current position-list, set *pi to -** POSITION_LIST_END and return. Otherwise, read the next varint from *pp, -** increment the current value of *pi by the value read, and set *pp to -** point to the next value before returning. -** -** Before calling this routine *pi must be initialized to the value of -** the previous position, or zero if we are reading the first position -** in the position-list. Because positions are delta-encoded, the value -** of the previous position is needed in order to compute the value of -** the next position. -*/ -static void fts3ReadNextPos( - char **pp, /* IN/OUT: Pointer into position-list buffer */ - sqlite3_int64 *pi /* IN/OUT: Value read from position-list */ -){ - if( (**pp)&0xFE ){ - fts3GetDeltaVarint(pp, pi); - *pi -= 2; - }else{ - *pi = POSITION_LIST_END; - } -} - -/* -** If parameter iCol is not 0, write an POS_COLUMN (1) byte followed by -** the value of iCol encoded as a varint to *pp. This will start a new -** column list. -** -** Set *pp to point to the byte just after the last byte written before -** returning (do not modify it if iCol==0). Return the total number of bytes -** written (0 if iCol==0). -*/ -static int fts3PutColNumber(char **pp, int iCol){ - int n = 0; /* Number of bytes written */ - if( iCol ){ - char *p = *pp; /* Output pointer */ - n = 1 + sqlite3Fts3PutVarint(&p[1], iCol); - *p = 0x01; - *pp = &p[n]; - } - return n; -} - -/* -** Compute the union of two position lists. The output written -** into *pp contains all positions of both *pp1 and *pp2 in sorted -** order and with any duplicates removed. All pointers are -** updated appropriately. The caller is responsible for insuring -** that there is enough space in *pp to hold the complete output. -*/ -static void fts3PoslistMerge( - char **pp, /* Output buffer */ - char **pp1, /* Left input list */ - char **pp2 /* Right input list */ -){ - char *p = *pp; - char *p1 = *pp1; - char *p2 = *pp2; - - while( *p1 || *p2 ){ - int iCol1; /* The current column index in pp1 */ - int iCol2; /* The current column index in pp2 */ - - if( *p1==POS_COLUMN ) sqlite3Fts3GetVarint32(&p1[1], &iCol1); - else if( *p1==POS_END ) iCol1 = POSITION_LIST_END; - else iCol1 = 0; - - if( *p2==POS_COLUMN ) sqlite3Fts3GetVarint32(&p2[1], &iCol2); - else if( *p2==POS_END ) iCol2 = POSITION_LIST_END; - else iCol2 = 0; - - if( iCol1==iCol2 ){ - sqlite3_int64 i1 = 0; /* Last position from pp1 */ - sqlite3_int64 i2 = 0; /* Last position from pp2 */ - sqlite3_int64 iPrev = 0; - int n = fts3PutColNumber(&p, iCol1); - p1 += n; - p2 += n; - - /* At this point, both p1 and p2 point to the start of column-lists - ** for the same column (the column with index iCol1 and iCol2). - ** A column-list is a list of non-negative delta-encoded varints, each - ** incremented by 2 before being stored. Each list is terminated by a - ** POS_END (0) or POS_COLUMN (1). The following block merges the two lists - ** and writes the results to buffer p. p is left pointing to the byte - ** after the list written. No terminator (POS_END or POS_COLUMN) is - ** written to the output. - */ - fts3GetDeltaVarint(&p1, &i1); - fts3GetDeltaVarint(&p2, &i2); - do { - fts3PutDeltaVarint(&p, &iPrev, (i1pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e. -** when the *pp1 token appears before the *pp2 token, but not more than nToken -** slots before it. -** -** e.g. nToken==1 searches for adjacent positions. -*/ -static int fts3PoslistPhraseMerge( - char **pp, /* IN/OUT: Preallocated output buffer */ - int nToken, /* Maximum difference in token positions */ - int isSaveLeft, /* Save the left position */ - int isExact, /* If *pp1 is exactly nTokens before *pp2 */ - char **pp1, /* IN/OUT: Left input list */ - char **pp2 /* IN/OUT: Right input list */ -){ - char *p = *pp; - char *p1 = *pp1; - char *p2 = *pp2; - int iCol1 = 0; - int iCol2 = 0; - - /* Never set both isSaveLeft and isExact for the same invocation. */ - assert( isSaveLeft==0 || isExact==0 ); - - assert( p!=0 && *p1!=0 && *p2!=0 ); - if( *p1==POS_COLUMN ){ - p1++; - p1 += sqlite3Fts3GetVarint32(p1, &iCol1); - } - if( *p2==POS_COLUMN ){ - p2++; - p2 += sqlite3Fts3GetVarint32(p2, &iCol2); - } - - while( 1 ){ - if( iCol1==iCol2 ){ - char *pSave = p; - sqlite3_int64 iPrev = 0; - sqlite3_int64 iPos1 = 0; - sqlite3_int64 iPos2 = 0; - - if( iCol1 ){ - *p++ = POS_COLUMN; - p += sqlite3Fts3PutVarint(p, iCol1); - } - - assert( *p1!=POS_END && *p1!=POS_COLUMN ); - assert( *p2!=POS_END && *p2!=POS_COLUMN ); - fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; - fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; - - while( 1 ){ - if( iPos2==iPos1+nToken - || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken) - ){ - sqlite3_int64 iSave; - iSave = isSaveLeft ? iPos1 : iPos2; - fts3PutDeltaVarint(&p, &iPrev, iSave+2); iPrev -= 2; - pSave = 0; - assert( p ); - } - if( (!isSaveLeft && iPos2<=(iPos1+nToken)) || iPos2<=iPos1 ){ - if( (*p2&0xFE)==0 ) break; - fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2; - }else{ - if( (*p1&0xFE)==0 ) break; - fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2; - } - } - - if( pSave ){ - assert( pp && p ); - p = pSave; - } - - fts3ColumnlistCopy(0, &p1); - fts3ColumnlistCopy(0, &p2); - assert( (*p1&0xFE)==0 && (*p2&0xFE)==0 ); - if( 0==*p1 || 0==*p2 ) break; - - p1++; - p1 += sqlite3Fts3GetVarint32(p1, &iCol1); - p2++; - p2 += sqlite3Fts3GetVarint32(p2, &iCol2); - } - - /* Advance pointer p1 or p2 (whichever corresponds to the smaller of - ** iCol1 and iCol2) so that it points to either the 0x00 that marks the - ** end of the position list, or the 0x01 that precedes the next - ** column-number in the position list. - */ - else if( iCol1=pEnd ){ - *pp = 0; - }else{ - sqlite3_int64 iVal; - *pp += sqlite3Fts3GetVarint(*pp, &iVal); - if( bDescIdx ){ - *pVal -= iVal; - }else{ - *pVal += iVal; - } - } -} - -/* -** This function is used to write a single varint to a buffer. The varint -** is written to *pp. Before returning, *pp is set to point 1 byte past the -** end of the value written. -** -** If *pbFirst is zero when this function is called, the value written to -** the buffer is that of parameter iVal. -** -** If *pbFirst is non-zero when this function is called, then the value -** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal) -** (if bDescIdx is non-zero). -** -** Before returning, this function always sets *pbFirst to 1 and *piPrev -** to the value of parameter iVal. -*/ -static void fts3PutDeltaVarint3( - char **pp, /* IN/OUT: Output pointer */ - int bDescIdx, /* True for descending docids */ - sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */ - int *pbFirst, /* IN/OUT: True after first int written */ - sqlite3_int64 iVal /* Write this value to the list */ -){ - sqlite3_int64 iWrite; - if( bDescIdx==0 || *pbFirst==0 ){ - iWrite = iVal - *piPrev; - }else{ - iWrite = *piPrev - iVal; - } - assert( *pbFirst || *piPrev==0 ); - assert( *pbFirst==0 || iWrite>0 ); - *pp += sqlite3Fts3PutVarint(*pp, iWrite); - *piPrev = iVal; - *pbFirst = 1; -} - - -/* -** This macro is used by various functions that merge doclists. The two -** arguments are 64-bit docid values. If the value of the stack variable -** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2). -** Otherwise, (i2-i1). -** -** Using this makes it easier to write code that can merge doclists that are -** sorted in either ascending or descending order. -*/ -#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2)) - -/* -** This function does an "OR" merge of two doclists (output contains all -** positions contained in either argument doclist). If the docids in the -** input doclists are sorted in ascending order, parameter bDescDoclist -** should be false. If they are sorted in ascending order, it should be -** passed a non-zero value. -** -** If no error occurs, *paOut is set to point at an sqlite3_malloc'd buffer -** containing the output doclist and SQLITE_OK is returned. In this case -** *pnOut is set to the number of bytes in the output doclist. -** -** If an error occurs, an SQLite error code is returned. The output values -** are undefined in this case. -*/ -static int fts3DoclistOrMerge( - int bDescDoclist, /* True if arguments are desc */ - char *a1, int n1, /* First doclist */ - char *a2, int n2, /* Second doclist */ - char **paOut, int *pnOut /* OUT: Malloc'd doclist */ -){ - sqlite3_int64 i1 = 0; - sqlite3_int64 i2 = 0; - sqlite3_int64 iPrev = 0; - char *pEnd1 = &a1[n1]; - char *pEnd2 = &a2[n2]; - char *p1 = a1; - char *p2 = a2; - char *p; - char *aOut; - int bFirstOut = 0; - - *paOut = 0; - *pnOut = 0; - - /* Allocate space for the output. Both the input and output doclists - ** are delta encoded. If they are in ascending order (bDescDoclist==0), - ** then the first docid in each list is simply encoded as a varint. For - ** each subsequent docid, the varint stored is the difference between the - ** current and previous docid (a positive number - since the list is in - ** ascending order). - ** - ** The first docid written to the output is therefore encoded using the - ** same number of bytes as it is in whichever of the input lists it is - ** read from. And each subsequent docid read from the same input list - ** consumes either the same or less bytes as it did in the input (since - ** the difference between it and the previous value in the output must - ** be a positive value less than or equal to the delta value read from - ** the input list). The same argument applies to all but the first docid - ** read from the 'other' list. And to the contents of all position lists - ** that will be copied and merged from the input to the output. - ** - ** However, if the first docid copied to the output is a negative number, - ** then the encoding of the first docid from the 'other' input list may - ** be larger in the output than it was in the input (since the delta value - ** may be a larger positive integer than the actual docid). - ** - ** The space required to store the output is therefore the sum of the - ** sizes of the two inputs, plus enough space for exactly one of the input - ** docids to grow. - ** - ** A symetric argument may be made if the doclists are in descending - ** order. - */ - aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1); - if( !aOut ) return SQLITE_NOMEM; - - p = aOut; - fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); - while( p1 || p2 ){ - sqlite3_int64 iDiff = DOCID_CMP(i1, i2); - - if( p2 && p1 && iDiff==0 ){ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - fts3PoslistMerge(&p, &p1, &p2); - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - }else if( !p2 || (p1 && iDiff<0) ){ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - fts3PoslistCopy(&p, &p1); - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - }else{ - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2); - fts3PoslistCopy(&p, &p2); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - } - } - - *paOut = aOut; - *pnOut = (int)(p-aOut); - assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 ); - return SQLITE_OK; -} - -/* -** This function does a "phrase" merge of two doclists. In a phrase merge, -** the output contains a copy of each position from the right-hand input -** doclist for which there is a position in the left-hand input doclist -** exactly nDist tokens before it. -** -** If the docids in the input doclists are sorted in ascending order, -** parameter bDescDoclist should be false. If they are sorted in ascending -** order, it should be passed a non-zero value. -** -** The right-hand input doclist is overwritten by this function. -*/ -static void fts3DoclistPhraseMerge( - int bDescDoclist, /* True if arguments are desc */ - int nDist, /* Distance from left to right (1=adjacent) */ - char *aLeft, int nLeft, /* Left doclist */ - char *aRight, int *pnRight /* IN/OUT: Right/output doclist */ -){ - sqlite3_int64 i1 = 0; - sqlite3_int64 i2 = 0; - sqlite3_int64 iPrev = 0; - char *pEnd1 = &aLeft[nLeft]; - char *pEnd2 = &aRight[*pnRight]; - char *p1 = aLeft; - char *p2 = aRight; - char *p; - int bFirstOut = 0; - char *aOut = aRight; - - assert( nDist>0 ); - - p = aOut; - fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); - - while( p1 && p2 ){ - sqlite3_int64 iDiff = DOCID_CMP(i1, i2); - if( iDiff==0 ){ - char *pSave = p; - sqlite3_int64 iPrevSave = iPrev; - int bFirstOutSave = bFirstOut; - - fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1); - if( 0==fts3PoslistPhraseMerge(&p, nDist, 0, 1, &p1, &p2) ){ - p = pSave; - iPrev = iPrevSave; - bFirstOut = bFirstOutSave; - } - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - }else if( iDiff<0 ){ - fts3PoslistCopy(0, &p1); - fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1); - }else{ - fts3PoslistCopy(0, &p2); - fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); - } - } - - *pnRight = (int)(p - aOut); -} - -/* -** Argument pList points to a position list nList bytes in size. This -** function checks to see if the position list contains any entries for -** a token in position 0 (of any column). If so, it writes argument iDelta -** to the output buffer pOut, followed by a position list consisting only -** of the entries from pList at position 0, and terminated by an 0x00 byte. -** The value returned is the number of bytes written to pOut (if any). -*/ -SQLITE_PRIVATE int sqlite3Fts3FirstFilter( - sqlite3_int64 iDelta, /* Varint that may be written to pOut */ - char *pList, /* Position list (no 0x00 term) */ - int nList, /* Size of pList in bytes */ - char *pOut /* Write output here */ -){ - int nOut = 0; - int bWritten = 0; /* True once iDelta has been written */ - char *p = pList; - char *pEnd = &pList[nList]; - - if( *p!=0x01 ){ - if( *p==0x02 ){ - nOut += sqlite3Fts3PutVarint(&pOut[nOut], iDelta); - pOut[nOut++] = 0x02; - bWritten = 1; - } - fts3ColumnlistCopy(0, &p); - } - - while( paaOutput); i++){ - if( pTS->aaOutput[i] ){ - if( !aOut ){ - aOut = pTS->aaOutput[i]; - nOut = pTS->anOutput[i]; - pTS->aaOutput[i] = 0; - }else{ - int nNew; - char *aNew; - - int rc = fts3DoclistOrMerge(p->bDescIdx, - pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew - ); - if( rc!=SQLITE_OK ){ - sqlite3_free(aOut); - return rc; - } - - sqlite3_free(pTS->aaOutput[i]); - sqlite3_free(aOut); - pTS->aaOutput[i] = 0; - aOut = aNew; - nOut = nNew; - } - } - } - - pTS->aaOutput[0] = aOut; - pTS->anOutput[0] = nOut; - return SQLITE_OK; -} - -/* -** Merge the doclist aDoclist/nDoclist into the TermSelect object passed -** as the first argument. The merge is an "OR" merge (see function -** fts3DoclistOrMerge() for details). -** -** This function is called with the doclist for each term that matches -** a queried prefix. It merges all these doclists into one, the doclist -** for the specified prefix. Since there can be a very large number of -** doclists to merge, the merging is done pair-wise using the TermSelect -** object. -** -** This function returns SQLITE_OK if the merge is successful, or an -** SQLite error code (SQLITE_NOMEM) if an error occurs. -*/ -static int fts3TermSelectMerge( - Fts3Table *p, /* FTS table handle */ - TermSelect *pTS, /* TermSelect object to merge into */ - char *aDoclist, /* Pointer to doclist */ - int nDoclist /* Size of aDoclist in bytes */ -){ - if( pTS->aaOutput[0]==0 ){ - /* If this is the first term selected, copy the doclist to the output - ** buffer using memcpy(). */ - pTS->aaOutput[0] = sqlite3_malloc(nDoclist); - pTS->anOutput[0] = nDoclist; - if( pTS->aaOutput[0] ){ - memcpy(pTS->aaOutput[0], aDoclist, nDoclist); - }else{ - return SQLITE_NOMEM; - } - }else{ - char *aMerge = aDoclist; - int nMerge = nDoclist; - int iOut; - - for(iOut=0; iOutaaOutput); iOut++){ - if( pTS->aaOutput[iOut]==0 ){ - assert( iOut>0 ); - pTS->aaOutput[iOut] = aMerge; - pTS->anOutput[iOut] = nMerge; - break; - }else{ - char *aNew; - int nNew; - - int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge, - pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew - ); - if( rc!=SQLITE_OK ){ - if( aMerge!=aDoclist ) sqlite3_free(aMerge); - return rc; - } - - if( aMerge!=aDoclist ) sqlite3_free(aMerge); - sqlite3_free(pTS->aaOutput[iOut]); - pTS->aaOutput[iOut] = 0; - - aMerge = aNew; - nMerge = nNew; - if( (iOut+1)==SizeofArray(pTS->aaOutput) ){ - pTS->aaOutput[iOut] = aMerge; - pTS->anOutput[iOut] = nMerge; - } - } - } - } - return SQLITE_OK; -} - -/* -** Append SegReader object pNew to the end of the pCsr->apSegment[] array. -*/ -static int fts3SegReaderCursorAppend( - Fts3MultiSegReader *pCsr, - Fts3SegReader *pNew -){ - if( (pCsr->nSegment%16)==0 ){ - Fts3SegReader **apNew; - int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*); - apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte); - if( !apNew ){ - sqlite3Fts3SegReaderFree(pNew); - return SQLITE_NOMEM; - } - pCsr->apSegment = apNew; - } - pCsr->apSegment[pCsr->nSegment++] = pNew; - return SQLITE_OK; -} - -/* -** Add seg-reader objects to the Fts3MultiSegReader object passed as the -** 8th argument. -** -** This function returns SQLITE_OK if successful, or an SQLite error code -** otherwise. -*/ -static int fts3SegReaderCursor( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index to search (from 0 to p->nIndex-1) */ - int iLevel, /* Level of segments to scan */ - const char *zTerm, /* Term to query for */ - int nTerm, /* Size of zTerm in bytes */ - int isPrefix, /* True for a prefix search */ - int isScan, /* True to scan from zTerm to EOF */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - int rc = SQLITE_OK; /* Error code */ - sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */ - int rc2; /* Result of sqlite3_reset() */ - - /* If iLevel is less than 0 and this is not a scan, include a seg-reader - ** for the pending-terms. If this is a scan, then this call must be being - ** made by an fts4aux module, not an FTS table. In this case calling - ** Fts3SegReaderPending might segfault, as the data structures used by - ** fts4aux are not completely populated. So it's easiest to filter these - ** calls out here. */ - if( iLevel<0 && p->aIndex ){ - Fts3SegReader *pSeg = 0; - rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg); - if( rc==SQLITE_OK && pSeg ){ - rc = fts3SegReaderCursorAppend(pCsr, pSeg); - } - } - - if( iLevel!=FTS3_SEGCURSOR_PENDING ){ - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); - } - - while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ - Fts3SegReader *pSeg = 0; - - /* Read the values returned by the SELECT into local variables. */ - sqlite3_int64 iStartBlock = sqlite3_column_int64(pStmt, 1); - sqlite3_int64 iLeavesEndBlock = sqlite3_column_int64(pStmt, 2); - sqlite3_int64 iEndBlock = sqlite3_column_int64(pStmt, 3); - int nRoot = sqlite3_column_bytes(pStmt, 4); - char const *zRoot = sqlite3_column_blob(pStmt, 4); - - /* If zTerm is not NULL, and this segment is not stored entirely on its - ** root node, the range of leaves scanned can be reduced. Do this. */ - if( iStartBlock && zTerm ){ - sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0); - rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi); - if( rc!=SQLITE_OK ) goto finished; - if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock; - } - - rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, - (isPrefix==0 && isScan==0), - iStartBlock, iLeavesEndBlock, - iEndBlock, zRoot, nRoot, &pSeg - ); - if( rc!=SQLITE_OK ) goto finished; - rc = fts3SegReaderCursorAppend(pCsr, pSeg); - } - } - - finished: - rc2 = sqlite3_reset(pStmt); - if( rc==SQLITE_DONE ) rc = rc2; - - return rc; -} - -/* -** Set up a cursor object for iterating through a full-text index or a -** single level therein. -*/ -SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language-id to search */ - int iIndex, /* Index to search (from 0 to p->nIndex-1) */ - int iLevel, /* Level of segments to scan */ - const char *zTerm, /* Term to query for */ - int nTerm, /* Size of zTerm in bytes */ - int isPrefix, /* True for a prefix search */ - int isScan, /* True to scan from zTerm to EOF */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - assert( iIndex>=0 && iIndexnIndex ); - assert( iLevel==FTS3_SEGCURSOR_ALL - || iLevel==FTS3_SEGCURSOR_PENDING - || iLevel>=0 - ); - assert( iLevelbase.pVtab; - - if( isPrefix ){ - for(i=1; bFound==0 && inIndex; i++){ - if( p->aIndex[i].nPrefix==nTerm ){ - bFound = 1; - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr - ); - pSegcsr->bLookup = 1; - } - } - - for(i=1; bFound==0 && inIndex; i++){ - if( p->aIndex[i].nPrefix==nTerm+1 ){ - bFound = 1; - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr - ); - if( rc==SQLITE_OK ){ - rc = fts3SegReaderCursorAddZero( - p, pCsr->iLangid, zTerm, nTerm, pSegcsr - ); - } - } - } - } - - if( bFound==0 ){ - rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, - 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr - ); - pSegcsr->bLookup = !isPrefix; - } - } - - *ppSegcsr = pSegcsr; - return rc; -} - -/* -** Free an Fts3MultiSegReader allocated by fts3TermSegReaderCursor(). -*/ -static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){ - sqlite3Fts3SegReaderFinish(pSegcsr); - sqlite3_free(pSegcsr); -} - -/* -** This function retrieves the doclist for the specified term (or term -** prefix) from the database. -*/ -static int fts3TermSelect( - Fts3Table *p, /* Virtual table handle */ - Fts3PhraseToken *pTok, /* Token to query for */ - int iColumn, /* Column to query (or -ve for all columns) */ - int *pnOut, /* OUT: Size of buffer at *ppOut */ - char **ppOut /* OUT: Malloced result buffer */ -){ - int rc; /* Return code */ - Fts3MultiSegReader *pSegcsr; /* Seg-reader cursor for this term */ - TermSelect tsc; /* Object for pair-wise doclist merging */ - Fts3SegFilter filter; /* Segment term filter configuration */ - - pSegcsr = pTok->pSegcsr; - memset(&tsc, 0, sizeof(TermSelect)); - - filter.flags = FTS3_SEGMENT_IGNORE_EMPTY | FTS3_SEGMENT_REQUIRE_POS - | (pTok->isPrefix ? FTS3_SEGMENT_PREFIX : 0) - | (pTok->bFirst ? FTS3_SEGMENT_FIRST : 0) - | (iColumnnColumn ? FTS3_SEGMENT_COLUMN_FILTER : 0); - filter.iCol = iColumn; - filter.zTerm = pTok->z; - filter.nTerm = pTok->n; - - rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter); - while( SQLITE_OK==rc - && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr)) - ){ - rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist); - } - - if( rc==SQLITE_OK ){ - rc = fts3TermSelectFinishMerge(p, &tsc); - } - if( rc==SQLITE_OK ){ - *ppOut = tsc.aaOutput[0]; - *pnOut = tsc.anOutput[0]; - }else{ - int i; - for(i=0; ipSegcsr = 0; - return rc; -} - -/* -** This function counts the total number of docids in the doclist stored -** in buffer aList[], size nList bytes. -** -** If the isPoslist argument is true, then it is assumed that the doclist -** contains a position-list following each docid. Otherwise, it is assumed -** that the doclist is simply a list of docids stored as delta encoded -** varints. -*/ -static int fts3DoclistCountDocids(char *aList, int nList){ - int nDoc = 0; /* Return value */ - if( aList ){ - char *aEnd = &aList[nList]; /* Pointer to one byte after EOF */ - char *p = aList; /* Cursor */ - while( peSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){ - if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){ - pCsr->isEof = 1; - rc = sqlite3_reset(pCsr->pStmt); - }else{ - pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0); - rc = SQLITE_OK; - } - }else{ - rc = fts3EvalNext((Fts3Cursor *)pCursor); - } - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - return rc; -} - -/* -** This is the xFilter interface for the virtual table. See -** the virtual table xFilter method documentation for additional -** information. -** -** If idxNum==FTS3_FULLSCAN_SEARCH then do a full table scan against -** the %_content table. -** -** If idxNum==FTS3_DOCID_SEARCH then do a docid lookup for a single entry -** in the %_content table. -** -** If idxNum>=FTS3_FULLTEXT_SEARCH then use the full text index. The -** column on the left-hand side of the MATCH operator is column -** number idxNum-FTS3_FULLTEXT_SEARCH, 0 indexed. argv[0] is the right-hand -** side of the MATCH operator. -*/ -static int fts3FilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - int rc; - char *zSql; /* SQL statement used to access %_content */ - Fts3Table *p = (Fts3Table *)pCursor->pVtab; - Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; - - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(nVal); - - assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); - assert( nVal==0 || nVal==1 || nVal==2 ); - assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) ); - assert( p->pSegments==0 ); - - /* In case the cursor has been used before, clear it now. */ - sqlite3_finalize(pCsr->pStmt); - sqlite3_free(pCsr->aDoclist); - sqlite3Fts3ExprFree(pCsr->pExpr); - memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); - - if( idxStr ){ - pCsr->bDesc = (idxStr[0]=='D'); - }else{ - pCsr->bDesc = p->bDescIdx; - } - pCsr->eSearch = (i16)idxNum; - - if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){ - int iCol = idxNum-FTS3_FULLTEXT_SEARCH; - const char *zQuery = (const char *)sqlite3_value_text(apVal[0]); - - if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ - return SQLITE_NOMEM; - } - - pCsr->iLangid = 0; - if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]); - - assert( p->base.zErrMsg==0 ); - rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, - p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, - &p->base.zErrMsg - ); - if( rc!=SQLITE_OK ){ - return rc; - } - - rc = sqlite3Fts3ReadLock(p); - if( rc!=SQLITE_OK ) return rc; - - rc = fts3EvalStart(pCsr); - - sqlite3Fts3SegmentsClose(p); - if( rc!=SQLITE_OK ) return rc; - pCsr->pNextId = pCsr->aDoclist; - pCsr->iPrevId = 0; - } - - /* Compile a SELECT statement for this cursor. For a full-table-scan, the - ** statement loops through all rows of the %_content table. For a - ** full-text query or docid lookup, the statement retrieves a single - ** row by docid. - */ - if( idxNum==FTS3_FULLSCAN_SEARCH ){ - zSql = sqlite3_mprintf( - "SELECT %s ORDER BY rowid %s", - p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") - ); - if( zSql ){ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); - sqlite3_free(zSql); - }else{ - rc = SQLITE_NOMEM; - } - }else if( idxNum==FTS3_DOCID_SEARCH ){ - rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); - if( rc==SQLITE_OK ){ - rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); - } - } - if( rc!=SQLITE_OK ) return rc; - - return fts3NextMethod(pCursor); -} - -/* -** This is the xEof method of the virtual table. SQLite calls this -** routine to find out if it has reached the end of a result set. -*/ -static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){ - return ((Fts3Cursor *)pCursor)->isEof; -} - -/* -** This is the xRowid method. The SQLite core calls this routine to -** retrieve the rowid for the current row of the result set. fts3 -** exposes %_content.docid as the rowid for the virtual table. The -** rowid should be written to *pRowid. -*/ -static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ - Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; - *pRowid = pCsr->iPrevId; - return SQLITE_OK; -} - -/* -** This is the xColumn method, called by SQLite to request a value from -** the row that the supplied cursor currently points to. -** -** If: -** -** (iCol < p->nColumn) -> The value of the iCol'th user column. -** (iCol == p->nColumn) -> Magic column with the same name as the table. -** (iCol == p->nColumn+1) -> Docid column -** (iCol == p->nColumn+2) -> Langid column -*/ -static int fts3ColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - int rc = SQLITE_OK; /* Return Code */ - Fts3Cursor *pCsr = (Fts3Cursor *) pCursor; - Fts3Table *p = (Fts3Table *)pCursor->pVtab; - - /* The column value supplied by SQLite must be in range. */ - assert( iCol>=0 && iCol<=p->nColumn+2 ); - - if( iCol==p->nColumn+1 ){ - /* This call is a request for the "docid" column. Since "docid" is an - ** alias for "rowid", use the xRowid() method to obtain the value. - */ - sqlite3_result_int64(pCtx, pCsr->iPrevId); - }else if( iCol==p->nColumn ){ - /* The extra column whose name is the same as the table. - ** Return a blob which is a pointer to the cursor. */ - sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); - }else if( iCol==p->nColumn+2 && pCsr->pExpr ){ - sqlite3_result_int64(pCtx, pCsr->iLangid); - }else{ - /* The requested column is either a user column (one that contains - ** indexed data), or the language-id column. */ - rc = fts3CursorSeek(0, pCsr); - - if( rc==SQLITE_OK ){ - if( iCol==p->nColumn+2 ){ - int iLangid = 0; - if( p->zLanguageid ){ - iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1); - } - sqlite3_result_int(pCtx, iLangid); - }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){ - sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); - } - } - } - - assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - return rc; -} - -/* -** This function is the implementation of the xUpdate callback used by -** FTS3 virtual tables. It is invoked by SQLite each time a row is to be -** inserted, updated or deleted. -*/ -static int fts3UpdateMethod( - sqlite3_vtab *pVtab, /* Virtual table handle */ - int nArg, /* Size of argument array */ - sqlite3_value **apVal, /* Array of arguments */ - sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ -){ - return sqlite3Fts3UpdateMethod(pVtab, nArg, apVal, pRowid); -} - -/* -** Implementation of xSync() method. Flush the contents of the pending-terms -** hash-table to the database. -*/ -static int fts3SyncMethod(sqlite3_vtab *pVtab){ - - /* Following an incremental-merge operation, assuming that the input - ** segments are not completely consumed (the usual case), they are updated - ** in place to remove the entries that have already been merged. This - ** involves updating the leaf block that contains the smallest unmerged - ** entry and each block (if any) between the leaf and the root node. So - ** if the height of the input segment b-trees is N, and input segments - ** are merged eight at a time, updating the input segments at the end - ** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually - ** small - often between 0 and 2. So the overhead of the incremental - ** merge is somewhere between 8 and 24 blocks. To avoid this overhead - ** dwarfing the actual productive work accomplished, the incremental merge - ** is only attempted if it will write at least 64 leaf blocks. Hence - ** nMinMerge. - ** - ** Of course, updating the input segments also involves deleting a bunch - ** of blocks from the segments table. But this is not considered overhead - ** as it would also be required by a crisis-merge that used the same input - ** segments. - */ - const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ - - Fts3Table *p = (Fts3Table*)pVtab; - int rc = sqlite3Fts3PendingTermsFlush(p); - - if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){ - int mxLevel = 0; /* Maximum relative level value in db */ - int A; /* Incr-merge parameter A */ - - rc = sqlite3Fts3MaxLevel(p, &mxLevel); - assert( rc==SQLITE_OK || mxLevel==0 ); - A = p->nLeafAdd * mxLevel; - A += (A/2); - if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8); - } - sqlite3Fts3SegmentsClose(p); - return rc; -} - -/* -** Implementation of xBegin() method. This is a no-op. -*/ -static int fts3BeginMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table*)pVtab; - UNUSED_PARAMETER(pVtab); - assert( p->pSegments==0 ); - assert( p->nPendingData==0 ); - assert( p->inTransaction!=1 ); - TESTONLY( p->inTransaction = 1 ); - TESTONLY( p->mxSavepoint = -1; ); - p->nLeafAdd = 0; - return SQLITE_OK; -} - -/* -** Implementation of xCommit() method. This is a no-op. The contents of -** the pending-terms hash-table have already been flushed into the database -** by fts3SyncMethod(). -*/ -static int fts3CommitMethod(sqlite3_vtab *pVtab){ - TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); - UNUSED_PARAMETER(pVtab); - assert( p->nPendingData==0 ); - assert( p->inTransaction!=0 ); - assert( p->pSegments==0 ); - TESTONLY( p->inTransaction = 0 ); - TESTONLY( p->mxSavepoint = -1; ); - return SQLITE_OK; -} - -/* -** Implementation of xRollback(). Discard the contents of the pending-terms -** hash-table. Any changes made to the database are reverted by SQLite. -*/ -static int fts3RollbackMethod(sqlite3_vtab *pVtab){ - Fts3Table *p = (Fts3Table*)pVtab; - sqlite3Fts3PendingTermsClear(p); - assert( p->inTransaction!=0 ); - TESTONLY( p->inTransaction = 0 ); - TESTONLY( p->mxSavepoint = -1; ); - return SQLITE_OK; -} - -/* -** When called, *ppPoslist must point to the byte immediately following the -** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function -** moves *ppPoslist so that it instead points to the first byte of the -** same position list. -*/ -static void fts3ReversePoslist(char *pStart, char **ppPoslist){ - char *p = &(*ppPoslist)[-2]; - char c = 0; - - while( p>pStart && (c=*p--)==0 ); - while( p>pStart && (*p & 0x80) | c ){ - c = *p--; - } - if( p>pStart ){ p = &p[2]; } - while( *p++&0x80 ); - *ppPoslist = p; -} - -/* -** Helper function used by the implementation of the overloaded snippet(), -** offsets() and optimize() SQL functions. -** -** If the value passed as the third argument is a blob of size -** sizeof(Fts3Cursor*), then the blob contents are copied to the -** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error -** message is written to context pContext and SQLITE_ERROR returned. The -** string passed via zFunc is used as part of the error message. -*/ -static int fts3FunctionArg( - sqlite3_context *pContext, /* SQL function call context */ - const char *zFunc, /* Function name */ - sqlite3_value *pVal, /* argv[0] passed to function */ - Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ -){ - Fts3Cursor *pRet; - if( sqlite3_value_type(pVal)!=SQLITE_BLOB - || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) - ){ - char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); - sqlite3_result_error(pContext, zErr, -1); - sqlite3_free(zErr); - return SQLITE_ERROR; - } - memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *)); - *ppCsr = pRet; - return SQLITE_OK; -} - -/* -** Implementation of the snippet() function for FTS3 -*/ -static void fts3SnippetFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of apVal[] array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - const char *zStart = ""; - const char *zEnd = ""; - const char *zEllipsis = "..."; - int iCol = -1; - int nToken = 15; /* Default number of tokens in snippet */ - - /* There must be at least one argument passed to this function (otherwise - ** the non-overloaded version would have been called instead of this one). - */ - assert( nVal>=1 ); - - if( nVal>6 ){ - sqlite3_result_error(pContext, - "wrong number of arguments to function snippet()", -1); - return; - } - if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return; - - switch( nVal ){ - case 6: nToken = sqlite3_value_int(apVal[5]); - case 5: iCol = sqlite3_value_int(apVal[4]); - case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]); - case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]); - case 2: zStart = (const char*)sqlite3_value_text(apVal[1]); - } - if( !zEllipsis || !zEnd || !zStart ){ - sqlite3_result_error_nomem(pContext); - }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ - sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); - } -} - -/* -** Implementation of the offsets() function for FTS3 -*/ -static void fts3OffsetsFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - - UNUSED_PARAMETER(nVal); - - assert( nVal==1 ); - if( fts3FunctionArg(pContext, "offsets", apVal[0], &pCsr) ) return; - assert( pCsr ); - if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ - sqlite3Fts3Offsets(pContext, pCsr); - } -} - -/* -** Implementation of the special optimize() function for FTS3. This -** function merges all segments in the database to a single segment. -** Example usage is: -** -** SELECT optimize(t) FROM t LIMIT 1; -** -** where 't' is the name of an FTS3 table. -*/ -static void fts3OptimizeFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - int rc; /* Return code */ - Fts3Table *p; /* Virtual table handle */ - Fts3Cursor *pCursor; /* Cursor handle passed through apVal[0] */ - - UNUSED_PARAMETER(nVal); - - assert( nVal==1 ); - if( fts3FunctionArg(pContext, "optimize", apVal[0], &pCursor) ) return; - p = (Fts3Table *)pCursor->base.pVtab; - assert( p ); - - rc = sqlite3Fts3Optimize(p); - - switch( rc ){ - case SQLITE_OK: - sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC); - break; - case SQLITE_DONE: - sqlite3_result_text(pContext, "Index already optimal", -1, SQLITE_STATIC); - break; - default: - sqlite3_result_error_code(pContext, rc); - break; - } -} - -/* -** Implementation of the matchinfo() function for FTS3 -*/ -static void fts3MatchinfoFunc( - sqlite3_context *pContext, /* SQLite function call context */ - int nVal, /* Size of argument array */ - sqlite3_value **apVal /* Array of arguments */ -){ - Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */ - assert( nVal==1 || nVal==2 ); - if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){ - const char *zArg = 0; - if( nVal>1 ){ - zArg = (const char *)sqlite3_value_text(apVal[1]); - } - sqlite3Fts3Matchinfo(pContext, pCsr, zArg); - } -} - -/* -** This routine implements the xFindFunction method for the FTS3 -** virtual table. -*/ -static int fts3FindFunctionMethod( - sqlite3_vtab *pVtab, /* Virtual table handle */ - int nArg, /* Number of SQL function arguments */ - const char *zName, /* Name of SQL function */ - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ - void **ppArg /* Unused */ -){ - struct Overloaded { - const char *zName; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aOverload[] = { - { "snippet", fts3SnippetFunc }, - { "offsets", fts3OffsetsFunc }, - { "optimize", fts3OptimizeFunc }, - { "matchinfo", fts3MatchinfoFunc }, - }; - int i; /* Iterator variable */ - - UNUSED_PARAMETER(pVtab); - UNUSED_PARAMETER(nArg); - UNUSED_PARAMETER(ppArg); - - for(i=0; idb; /* Database connection */ - int rc; /* Return Code */ - - /* As it happens, the pending terms table is always empty here. This is - ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction - ** always opens a savepoint transaction. And the xSavepoint() method - ** flushes the pending terms table. But leave the (no-op) call to - ** PendingTermsFlush() in in case that changes. - */ - assert( p->nPendingData==0 ); - rc = sqlite3Fts3PendingTermsFlush(p); - - if( p->zContentTbl==0 ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';", - p->zDb, p->zName, zName - ); - } - - if( p->bHasDocsize ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_docsize' RENAME TO '%q_docsize';", - p->zDb, p->zName, zName - ); - } - if( p->bHasStat ){ - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_stat' RENAME TO '%q_stat';", - p->zDb, p->zName, zName - ); - } - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';", - p->zDb, p->zName, zName - ); - fts3DbExec(&rc, db, - "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';", - p->zDb, p->zName, zName - ); - return rc; -} - -/* -** The xSavepoint() method. -** -** Flush the contents of the pending-terms table to disk. -*/ -static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ - int rc = SQLITE_OK; - UNUSED_PARAMETER(iSavepoint); - assert( ((Fts3Table *)pVtab)->inTransaction ); - assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint ); - TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint ); - if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){ - rc = fts3SyncMethod(pVtab); - } - return rc; -} - -/* -** The xRelease() method. -** -** This is a no-op. -*/ -static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ - TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); - UNUSED_PARAMETER(iSavepoint); - UNUSED_PARAMETER(pVtab); - assert( p->inTransaction ); - assert( p->mxSavepoint >= iSavepoint ); - TESTONLY( p->mxSavepoint = iSavepoint-1 ); - return SQLITE_OK; -} - -/* -** The xRollbackTo() method. -** -** Discard the contents of the pending terms table. -*/ -static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ - Fts3Table *p = (Fts3Table*)pVtab; - UNUSED_PARAMETER(iSavepoint); - assert( p->inTransaction ); - assert( p->mxSavepoint >= iSavepoint ); - TESTONLY( p->mxSavepoint = iSavepoint ); - sqlite3Fts3PendingTermsClear(p); - return SQLITE_OK; -} - -static const sqlite3_module fts3Module = { - /* iVersion */ 2, - /* xCreate */ fts3CreateMethod, - /* xConnect */ fts3ConnectMethod, - /* xBestIndex */ fts3BestIndexMethod, - /* xDisconnect */ fts3DisconnectMethod, - /* xDestroy */ fts3DestroyMethod, - /* xOpen */ fts3OpenMethod, - /* xClose */ fts3CloseMethod, - /* xFilter */ fts3FilterMethod, - /* xNext */ fts3NextMethod, - /* xEof */ fts3EofMethod, - /* xColumn */ fts3ColumnMethod, - /* xRowid */ fts3RowidMethod, - /* xUpdate */ fts3UpdateMethod, - /* xBegin */ fts3BeginMethod, - /* xSync */ fts3SyncMethod, - /* xCommit */ fts3CommitMethod, - /* xRollback */ fts3RollbackMethod, - /* xFindFunction */ fts3FindFunctionMethod, - /* xRename */ fts3RenameMethod, - /* xSavepoint */ fts3SavepointMethod, - /* xRelease */ fts3ReleaseMethod, - /* xRollbackTo */ fts3RollbackToMethod, -}; - -/* -** This function is registered as the module destructor (called when an -** FTS3 enabled database connection is closed). It frees the memory -** allocated for the tokenizer hash table. -*/ -static void hashDestroy(void *p){ - Fts3Hash *pHash = (Fts3Hash *)p; - sqlite3Fts3HashClear(pHash); - sqlite3_free(pHash); -} - -/* -** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are -** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c -** respectively. The following three forward declarations are for functions -** declared in these files used to retrieve the respective implementations. -** -** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed -** to by the argument to point to the "simple" tokenizer implementation. -** And so on. -*/ -SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); -SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); -#ifdef SQLITE_ENABLE_FTS4_UNICODE61 -SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule); -#endif -#ifdef SQLITE_ENABLE_ICU -SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); -#endif - -/* -** Initialize the fts3 extension. If this extension is built as part -** of the sqlite library, then this function is called directly by -** SQLite. If fts3 is built as a dynamically loadable extension, this -** function is called by the sqlite3_extension_init() entry point. -*/ -SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ - int rc = SQLITE_OK; - Fts3Hash *pHash = 0; - const sqlite3_tokenizer_module *pSimple = 0; - const sqlite3_tokenizer_module *pPorter = 0; -#ifdef SQLITE_ENABLE_FTS4_UNICODE61 - const sqlite3_tokenizer_module *pUnicode = 0; -#endif - -#ifdef SQLITE_ENABLE_ICU - const sqlite3_tokenizer_module *pIcu = 0; - sqlite3Fts3IcuTokenizerModule(&pIcu); -#endif - -#ifdef SQLITE_ENABLE_FTS4_UNICODE61 - sqlite3Fts3UnicodeTokenizer(&pUnicode); -#endif - -#ifdef SQLITE_TEST - rc = sqlite3Fts3InitTerm(db); - if( rc!=SQLITE_OK ) return rc; -#endif - - rc = sqlite3Fts3InitAux(db); - if( rc!=SQLITE_OK ) return rc; - - sqlite3Fts3SimpleTokenizerModule(&pSimple); - sqlite3Fts3PorterTokenizerModule(&pPorter); - - /* Allocate and initialize the hash-table used to store tokenizers. */ - pHash = sqlite3_malloc(sizeof(Fts3Hash)); - if( !pHash ){ - rc = SQLITE_NOMEM; - }else{ - sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); - } - - /* Load the built-in tokenizers into the hash table */ - if( rc==SQLITE_OK ){ - if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple) - || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) - -#ifdef SQLITE_ENABLE_FTS4_UNICODE61 - || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) -#endif -#ifdef SQLITE_ENABLE_ICU - || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu)) -#endif - ){ - rc = SQLITE_NOMEM; - } - } - -#ifdef SQLITE_TEST - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ExprInitTestInterface(db); - } -#endif - - /* Create the virtual table wrapper around the hash-table and overload - ** the two scalar functions. If this is successful, register the - ** module with sqlite. - */ - if( SQLITE_OK==rc - && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2)) - && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) - ){ - rc = sqlite3_create_module_v2( - db, "fts3", &fts3Module, (void *)pHash, hashDestroy - ); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_module_v2( - db, "fts4", &fts3Module, (void *)pHash, 0 - ); - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3InitTok(db, (void *)pHash); - } - return rc; - } - - - /* An error has occurred. Delete the hash table and return the error code. */ - assert( rc!=SQLITE_OK ); - if( pHash ){ - sqlite3Fts3HashClear(pHash); - sqlite3_free(pHash); - } - return rc; -} - -/* -** Allocate an Fts3MultiSegReader for each token in the expression headed -** by pExpr. -** -** An Fts3SegReader object is a cursor that can seek or scan a range of -** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple -** Fts3SegReader objects internally to provide an interface to seek or scan -** within the union of all segments of a b-tree. Hence the name. -** -** If the allocated Fts3MultiSegReader just seeks to a single entry in a -** segment b-tree (if the term is not a prefix or it is a prefix for which -** there exists prefix b-tree of the right length) then it may be traversed -** and merged incrementally. Otherwise, it has to be merged into an in-memory -** doclist and then traversed. -*/ -static void fts3EvalAllocateReaders( - Fts3Cursor *pCsr, /* FTS cursor handle */ - Fts3Expr *pExpr, /* Allocate readers for this expression */ - int *pnToken, /* OUT: Total number of tokens in phrase. */ - int *pnOr, /* OUT: Total number of OR nodes in expr. */ - int *pRc /* IN/OUT: Error code */ -){ - if( pExpr && SQLITE_OK==*pRc ){ - if( pExpr->eType==FTSQUERY_PHRASE ){ - int i; - int nToken = pExpr->pPhrase->nToken; - *pnToken += nToken; - for(i=0; ipPhrase->aToken[i]; - int rc = fts3TermSegReaderCursor(pCsr, - pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr - ); - if( rc!=SQLITE_OK ){ - *pRc = rc; - return; - } - } - assert( pExpr->pPhrase->iDoclistToken==0 ); - pExpr->pPhrase->iDoclistToken = -1; - }else{ - *pnOr += (pExpr->eType==FTSQUERY_OR); - fts3EvalAllocateReaders(pCsr, pExpr->pLeft, pnToken, pnOr, pRc); - fts3EvalAllocateReaders(pCsr, pExpr->pRight, pnToken, pnOr, pRc); - } - } -} - -/* -** Arguments pList/nList contain the doclist for token iToken of phrase p. -** It is merged into the main doclist stored in p->doclist.aAll/nAll. -** -** This function assumes that pList points to a buffer allocated using -** sqlite3_malloc(). This function takes responsibility for eventually -** freeing the buffer. -*/ -static void fts3EvalPhraseMergeToken( - Fts3Table *pTab, /* FTS Table pointer */ - Fts3Phrase *p, /* Phrase to merge pList/nList into */ - int iToken, /* Token pList/nList corresponds to */ - char *pList, /* Pointer to doclist */ - int nList /* Number of bytes in pList */ -){ - assert( iToken!=p->iDoclistToken ); - - if( pList==0 ){ - sqlite3_free(p->doclist.aAll); - p->doclist.aAll = 0; - p->doclist.nAll = 0; - } - - else if( p->iDoclistToken<0 ){ - p->doclist.aAll = pList; - p->doclist.nAll = nList; - } - - else if( p->doclist.aAll==0 ){ - sqlite3_free(pList); - } - - else { - char *pLeft; - char *pRight; - int nLeft; - int nRight; - int nDiff; - - if( p->iDoclistTokendoclist.aAll; - nLeft = p->doclist.nAll; - pRight = pList; - nRight = nList; - nDiff = iToken - p->iDoclistToken; - }else{ - pRight = p->doclist.aAll; - nRight = p->doclist.nAll; - pLeft = pList; - nLeft = nList; - nDiff = p->iDoclistToken - iToken; - } - - fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight); - sqlite3_free(pLeft); - p->doclist.aAll = pRight; - p->doclist.nAll = nRight; - } - - if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; -} - -/* -** Load the doclist for phrase p into p->doclist.aAll/nAll. The loaded doclist -** does not take deferred tokens into account. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalPhraseLoad( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Phrase *p /* Phrase object */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int iToken; - int rc = SQLITE_OK; - - for(iToken=0; rc==SQLITE_OK && iTokennToken; iToken++){ - Fts3PhraseToken *pToken = &p->aToken[iToken]; - assert( pToken->pDeferred==0 || pToken->pSegcsr==0 ); - - if( pToken->pSegcsr ){ - int nThis = 0; - char *pThis = 0; - rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); - if( rc==SQLITE_OK ){ - fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); - } - } - assert( pToken->pSegcsr==0 ); - } - - return rc; -} - -/* -** This function is called on each phrase after the position lists for -** any deferred tokens have been loaded into memory. It updates the phrases -** current position list to include only those positions that are really -** instances of the phrase (after considering deferred tokens). If this -** means that the phrase does not appear in the current row, doclist.pList -** and doclist.nList are both zeroed. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ - int iToken; /* Used to iterate through phrase tokens */ - char *aPoslist = 0; /* Position list for deferred tokens */ - int nPoslist = 0; /* Number of bytes in aPoslist */ - int iPrev = -1; /* Token number of previous deferred token */ - - assert( pPhrase->doclist.bFreeList==0 ); - - for(iToken=0; iTokennToken; iToken++){ - Fts3PhraseToken *pToken = &pPhrase->aToken[iToken]; - Fts3DeferredToken *pDeferred = pToken->pDeferred; - - if( pDeferred ){ - char *pList; - int nList; - int rc = sqlite3Fts3DeferredTokenList(pDeferred, &pList, &nList); - if( rc!=SQLITE_OK ) return rc; - - if( pList==0 ){ - sqlite3_free(aPoslist); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - return SQLITE_OK; - - }else if( aPoslist==0 ){ - aPoslist = pList; - nPoslist = nList; - - }else{ - char *aOut = pList; - char *p1 = aPoslist; - char *p2 = aOut; - - assert( iPrev>=0 ); - fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2); - sqlite3_free(aPoslist); - aPoslist = pList; - nPoslist = (int)(aOut - aPoslist); - if( nPoslist==0 ){ - sqlite3_free(aPoslist); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - return SQLITE_OK; - } - } - iPrev = iToken; - } - } - - if( iPrev>=0 ){ - int nMaxUndeferred = pPhrase->iDoclistToken; - if( nMaxUndeferred<0 ){ - pPhrase->doclist.pList = aPoslist; - pPhrase->doclist.nList = nPoslist; - pPhrase->doclist.iDocid = pCsr->iPrevId; - pPhrase->doclist.bFreeList = 1; - }else{ - int nDistance; - char *p1; - char *p2; - char *aOut; - - if( nMaxUndeferred>iPrev ){ - p1 = aPoslist; - p2 = pPhrase->doclist.pList; - nDistance = nMaxUndeferred - iPrev; - }else{ - p1 = pPhrase->doclist.pList; - p2 = aPoslist; - nDistance = iPrev - nMaxUndeferred; - } - - aOut = (char *)sqlite3_malloc(nPoslist+8); - if( !aOut ){ - sqlite3_free(aPoslist); - return SQLITE_NOMEM; - } - - pPhrase->doclist.pList = aOut; - if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){ - pPhrase->doclist.bFreeList = 1; - pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList); - }else{ - sqlite3_free(aOut); - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - } - sqlite3_free(aPoslist); - } - } - - return SQLITE_OK; -} - -/* -** This function is called for each Fts3Phrase in a full-text query -** expression to initialize the mechanism for returning rows. Once this -** function has been called successfully on an Fts3Phrase, it may be -** used with fts3EvalPhraseNext() to iterate through the matching docids. -** -** If parameter bOptOk is true, then the phrase may (or may not) use the -** incremental loading strategy. Otherwise, the entire doclist is loaded into -** memory within this call. -** -** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code. -*/ -static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){ - int rc; /* Error code */ - Fts3PhraseToken *pFirst = &p->aToken[0]; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - - if( pCsr->bDesc==pTab->bDescIdx - && bOptOk==1 - && p->nToken==1 - && pFirst->pSegcsr - && pFirst->pSegcsr->bLookup - && pFirst->bFirst==0 - ){ - /* Use the incremental approach. */ - int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn); - rc = sqlite3Fts3MsrIncrStart( - pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n); - p->bIncr = 1; - - }else{ - /* Load the full doclist for the phrase into memory. */ - rc = fts3EvalPhraseLoad(pCsr, p); - p->bIncr = 0; - } - - assert( rc!=SQLITE_OK || p->nToken<1 || p->aToken[0].pSegcsr==0 || p->bIncr ); - return rc; -} - -/* -** This function is used to iterate backwards (from the end to start) -** through doclists. It is used by this module to iterate through phrase -** doclists in reverse and by the fts3_write.c module to iterate through -** pending-terms lists when writing to databases with "order=desc". -** -** The doclist may be sorted in ascending (parameter bDescIdx==0) or -** descending (parameter bDescIdx==1) order of docid. Regardless, this -** function iterates from the end of the doclist to the beginning. -*/ -SQLITE_PRIVATE void sqlite3Fts3DoclistPrev( - int bDescIdx, /* True if the doclist is desc */ - char *aDoclist, /* Pointer to entire doclist */ - int nDoclist, /* Length of aDoclist in bytes */ - char **ppIter, /* IN/OUT: Iterator pointer */ - sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */ - int *pnList, /* OUT: List length pointer */ - u8 *pbEof /* OUT: End-of-file flag */ -){ - char *p = *ppIter; - - assert( nDoclist>0 ); - assert( *pbEof==0 ); - assert( p || *piDocid==0 ); - assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) ); - - if( p==0 ){ - sqlite3_int64 iDocid = 0; - char *pNext = 0; - char *pDocid = aDoclist; - char *pEnd = &aDoclist[nDoclist]; - int iMul = 1; - - while( pDocid0 ); - assert( *pbEof==0 ); - assert( p || *piDocid==0 ); - assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); - - if( p==0 ){ - p = aDoclist; - p += sqlite3Fts3GetVarint(p, piDocid); - }else{ - fts3PoslistCopy(0, &p); - if( p>=&aDoclist[nDoclist] ){ - *pbEof = 1; - }else{ - sqlite3_int64 iVar; - p += sqlite3Fts3GetVarint(p, &iVar); - *piDocid += ((bDescIdx ? -1 : 1) * iVar); - } - } - - *ppIter = p; -} - -/* -** Attempt to move the phrase iterator to point to the next matching docid. -** If an error occurs, return an SQLite error code. Otherwise, return -** SQLITE_OK. -** -** If there is no "next" entry and no error occurs, then *pbEof is set to -** 1 before returning. Otherwise, if no error occurs and the iterator is -** successfully advanced, *pbEof is set to 0. -*/ -static int fts3EvalPhraseNext( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Phrase *p, /* Phrase object to advance to next docid */ - u8 *pbEof /* OUT: Set to 1 if EOF */ -){ - int rc = SQLITE_OK; - Fts3Doclist *pDL = &p->doclist; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - - if( p->bIncr ){ - assert( p->nToken==1 ); - assert( pDL->pNextDocid==0 ); - rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr, - &pDL->iDocid, &pDL->pList, &pDL->nList - ); - if( rc==SQLITE_OK && !pDL->pList ){ - *pbEof = 1; - } - }else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){ - sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll, - &pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof - ); - pDL->pList = pDL->pNextDocid; - }else{ - char *pIter; /* Used to iterate through aAll */ - char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */ - if( pDL->pNextDocid ){ - pIter = pDL->pNextDocid; - }else{ - pIter = pDL->aAll; - } - - if( pIter>=pEnd ){ - /* We have already reached the end of this doclist. EOF. */ - *pbEof = 1; - }else{ - sqlite3_int64 iDelta; - pIter += sqlite3Fts3GetVarint(pIter, &iDelta); - if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){ - pDL->iDocid += iDelta; - }else{ - pDL->iDocid -= iDelta; - } - pDL->pList = pIter; - fts3PoslistCopy(0, &pIter); - pDL->nList = (int)(pIter - pDL->pList); - - /* pIter now points just past the 0x00 that terminates the position- - ** list for document pDL->iDocid. However, if this position-list was - ** edited in place by fts3EvalNearTrim(), then pIter may not actually - ** point to the start of the next docid value. The following line deals - ** with this case by advancing pIter past the zero-padding added by - ** fts3EvalNearTrim(). */ - while( pIterpNextDocid = pIter; - assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter ); - *pbEof = 0; - } - } - - return rc; -} - -/* -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, fts3EvalPhraseStart() is called on all phrases within the -** expression. Also the Fts3Expr.bDeferred variable is set to true for any -** expressions for which all descendent tokens are deferred. -** -** If parameter bOptOk is zero, then it is guaranteed that the -** Fts3Phrase.doclist.aAll/nAll variables contain the entire doclist for -** each phrase in the expression (subject to deferred token processing). -** Or, if bOptOk is non-zero, then one or more tokens within the expression -** may be loaded incrementally, meaning doclist.aAll/nAll is not available. -** -** If an error occurs within this function, *pRc is set to an SQLite error -** code before returning. -*/ -static void fts3EvalStartReaders( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pExpr, /* Expression to initialize phrases in */ - int bOptOk, /* True to enable incremental loading */ - int *pRc /* IN/OUT: Error code */ -){ - if( pExpr && SQLITE_OK==*pRc ){ - if( pExpr->eType==FTSQUERY_PHRASE ){ - int i; - int nToken = pExpr->pPhrase->nToken; - for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; - } - pExpr->bDeferred = (i==nToken); - *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase); - }else{ - fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc); - fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc); - pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred); - } - } -} - -/* -** An array of the following structures is assembled as part of the process -** of selecting tokens to defer before the query starts executing (as part -** of the xFilter() method). There is one element in the array for each -** token in the FTS expression. -** -** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong -** to phrases that are connected only by AND and NEAR operators (not OR or -** NOT). When determining tokens to defer, each AND/NEAR cluster is considered -** separately. The root of a tokens AND/NEAR cluster is stored in -** Fts3TokenAndCost.pRoot. -*/ -typedef struct Fts3TokenAndCost Fts3TokenAndCost; -struct Fts3TokenAndCost { - Fts3Phrase *pPhrase; /* The phrase the token belongs to */ - int iToken; /* Position of token in phrase */ - Fts3PhraseToken *pToken; /* The token itself */ - Fts3Expr *pRoot; /* Root of NEAR/AND cluster */ - int nOvfl; /* Number of overflow pages to load doclist */ - int iCol; /* The column the token must match */ -}; - -/* -** This function is used to populate an allocated Fts3TokenAndCost array. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, if an error occurs during execution, *pRc is set to an -** SQLite error code. -*/ -static void fts3EvalTokenCosts( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pRoot, /* Root of current AND/NEAR cluster */ - Fts3Expr *pExpr, /* Expression to consider */ - Fts3TokenAndCost **ppTC, /* Write new entries to *(*ppTC)++ */ - Fts3Expr ***ppOr, /* Write new OR root to *(*ppOr)++ */ - int *pRc /* IN/OUT: Error code */ -){ - if( *pRc==SQLITE_OK ){ - if( pExpr->eType==FTSQUERY_PHRASE ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - int i; - for(i=0; *pRc==SQLITE_OK && inToken; i++){ - Fts3TokenAndCost *pTC = (*ppTC)++; - pTC->pPhrase = pPhrase; - pTC->iToken = i; - pTC->pRoot = pRoot; - pTC->pToken = &pPhrase->aToken[i]; - pTC->iCol = pPhrase->iColumn; - *pRc = sqlite3Fts3MsrOvfl(pCsr, pTC->pToken->pSegcsr, &pTC->nOvfl); - } - }else if( pExpr->eType!=FTSQUERY_NOT ){ - assert( pExpr->eType==FTSQUERY_OR - || pExpr->eType==FTSQUERY_AND - || pExpr->eType==FTSQUERY_NEAR - ); - assert( pExpr->pLeft && pExpr->pRight ); - if( pExpr->eType==FTSQUERY_OR ){ - pRoot = pExpr->pLeft; - **ppOr = pRoot; - (*ppOr)++; - } - fts3EvalTokenCosts(pCsr, pRoot, pExpr->pLeft, ppTC, ppOr, pRc); - if( pExpr->eType==FTSQUERY_OR ){ - pRoot = pExpr->pRight; - **ppOr = pRoot; - (*ppOr)++; - } - fts3EvalTokenCosts(pCsr, pRoot, pExpr->pRight, ppTC, ppOr, pRc); - } - } -} - -/* -** Determine the average document (row) size in pages. If successful, -** write this value to *pnPage and return SQLITE_OK. Otherwise, return -** an SQLite error code. -** -** The average document size in pages is calculated by first calculating -** determining the average size in bytes, B. If B is less than the amount -** of data that will fit on a single leaf page of an intkey table in -** this database, then the average docsize is 1. Otherwise, it is 1 plus -** the number of overflow pages consumed by a record B bytes in size. -*/ -static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){ - if( pCsr->nRowAvg==0 ){ - /* The average document size, which is required to calculate the cost - ** of each doclist, has not yet been determined. Read the required - ** data from the %_stat table to calculate it. - ** - ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3 - ** varints, where nCol is the number of columns in the FTS3 table. - ** The first varint is the number of documents currently stored in - ** the table. The following nCol varints contain the total amount of - ** data stored in all rows of each column of the table, from left - ** to right. - */ - int rc; - Fts3Table *p = (Fts3Table*)pCsr->base.pVtab; - sqlite3_stmt *pStmt; - sqlite3_int64 nDoc = 0; - sqlite3_int64 nByte = 0; - const char *pEnd; - const char *a; - - rc = sqlite3Fts3SelectDoctotal(p, &pStmt); - if( rc!=SQLITE_OK ) return rc; - a = sqlite3_column_blob(pStmt, 0); - assert( a ); - - pEnd = &a[sqlite3_column_bytes(pStmt, 0)]; - a += sqlite3Fts3GetVarint(a, &nDoc); - while( anDoc = nDoc; - pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz); - assert( pCsr->nRowAvg>0 ); - rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ) return rc; - } - - *pnPage = pCsr->nRowAvg; - return SQLITE_OK; -} - -/* -** This function is called to select the tokens (if any) that will be -** deferred. The array aTC[] has already been populated when this is -** called. -** -** This function is called once for each AND/NEAR cluster in the -** expression. Each invocation determines which tokens to defer within -** the cluster with root node pRoot. See comments above the definition -** of struct Fts3TokenAndCost for more details. -** -** If no error occurs, SQLITE_OK is returned and sqlite3Fts3DeferToken() -** called on each token to defer. Otherwise, an SQLite error code is -** returned. -*/ -static int fts3EvalSelectDeferred( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pRoot, /* Consider tokens with this root node */ - Fts3TokenAndCost *aTC, /* Array of expression tokens and costs */ - int nTC /* Number of entries in aTC[] */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int nDocSize = 0; /* Number of pages per doc loaded */ - int rc = SQLITE_OK; /* Return code */ - int ii; /* Iterator variable for various purposes */ - int nOvfl = 0; /* Total overflow pages used by doclists */ - int nToken = 0; /* Total number of tokens in cluster */ - - int nMinEst = 0; /* The minimum count for any phrase so far. */ - int nLoad4 = 1; /* (Phrases that will be loaded)^4. */ - - /* Tokens are never deferred for FTS tables created using the content=xxx - ** option. The reason being that it is not guaranteed that the content - ** table actually contains the same data as the index. To prevent this from - ** causing any problems, the deferred token optimization is completely - ** disabled for content=xxx tables. */ - if( pTab->zContentTbl ){ - return SQLITE_OK; - } - - /* Count the tokens in this AND/NEAR cluster. If none of the doclists - ** associated with the tokens spill onto overflow pages, or if there is - ** only 1 token, exit early. No tokens to defer in this case. */ - for(ii=0; ii0 ); - - - /* Iterate through all tokens in this AND/NEAR cluster, in ascending order - ** of the number of overflow pages that will be loaded by the pager layer - ** to retrieve the entire doclist for the token from the full-text index. - ** Load the doclists for tokens that are either: - ** - ** a. The cheapest token in the entire query (i.e. the one visited by the - ** first iteration of this loop), or - ** - ** b. Part of a multi-token phrase. - ** - ** After each token doclist is loaded, merge it with the others from the - ** same phrase and count the number of documents that the merged doclist - ** contains. Set variable "nMinEst" to the smallest number of documents in - ** any phrase doclist for which 1 or more token doclists have been loaded. - ** Let nOther be the number of other phrases for which it is certain that - ** one or more tokens will not be deferred. - ** - ** Then, for each token, defer it if loading the doclist would result in - ** loading N or more overflow pages into memory, where N is computed as: - ** - ** (nMinEst + 4^nOther - 1) / (4^nOther) - */ - for(ii=0; iinOvfl) - ){ - pTC = &aTC[iTC]; - } - } - assert( pTC ); - - if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){ - /* The number of overflow pages to load for this (and therefore all - ** subsequent) tokens is greater than the estimated number of pages - ** that will be loaded if all subsequent tokens are deferred. - */ - Fts3PhraseToken *pToken = pTC->pToken; - rc = sqlite3Fts3DeferToken(pCsr, pToken, pTC->iCol); - fts3SegReaderCursorFree(pToken->pSegcsr); - pToken->pSegcsr = 0; - }else{ - /* Set nLoad4 to the value of (4^nOther) for the next iteration of the - ** for-loop. Except, limit the value to 2^24 to prevent it from - ** overflowing the 32-bit integer it is stored in. */ - if( ii<12 ) nLoad4 = nLoad4*4; - - if( ii==0 || pTC->pPhrase->nToken>1 ){ - /* Either this is the cheapest token in the entire query, or it is - ** part of a multi-token phrase. Either way, the entire doclist will - ** (eventually) be loaded into memory. It may as well be now. */ - Fts3PhraseToken *pToken = pTC->pToken; - int nList = 0; - char *pList = 0; - rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); - assert( rc==SQLITE_OK || pList==0 ); - if( rc==SQLITE_OK ){ - int nCount; - fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList); - nCount = fts3DoclistCountDocids( - pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll - ); - if( ii==0 || nCountpToken = 0; - } - - return rc; -} - -/* -** This function is called from within the xFilter method. It initializes -** the full-text query currently stored in pCsr->pExpr. To iterate through -** the results of a query, the caller does: -** -** fts3EvalStart(pCsr); -** while( 1 ){ -** fts3EvalNext(pCsr); -** if( pCsr->bEof ) break; -** ... return row pCsr->iPrevId to the caller ... -** } -*/ -static int fts3EvalStart(Fts3Cursor *pCsr){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int nToken = 0; - int nOr = 0; - - /* Allocate a MultiSegReader for each token in the expression. */ - fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc); - - /* Determine which, if any, tokens in the expression should be deferred. */ -#ifndef SQLITE_DISABLE_FTS4_DEFERRED - if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){ - Fts3TokenAndCost *aTC; - Fts3Expr **apOr; - aTC = (Fts3TokenAndCost *)sqlite3_malloc( - sizeof(Fts3TokenAndCost) * nToken - + sizeof(Fts3Expr *) * nOr * 2 - ); - apOr = (Fts3Expr **)&aTC[nToken]; - - if( !aTC ){ - rc = SQLITE_NOMEM; - }else{ - int ii; - Fts3TokenAndCost *pTC = aTC; - Fts3Expr **ppOr = apOr; - - fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc); - nToken = (int)(pTC-aTC); - nOr = (int)(ppOr-apOr); - - if( rc==SQLITE_OK ){ - rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken); - for(ii=0; rc==SQLITE_OK && iipExpr, 1, &rc); - return rc; -} - -/* -** Invalidate the current position list for phrase pPhrase. -*/ -static void fts3EvalInvalidatePoslist(Fts3Phrase *pPhrase){ - if( pPhrase->doclist.bFreeList ){ - sqlite3_free(pPhrase->doclist.pList); - } - pPhrase->doclist.pList = 0; - pPhrase->doclist.nList = 0; - pPhrase->doclist.bFreeList = 0; -} - -/* -** This function is called to edit the position list associated with -** the phrase object passed as the fifth argument according to a NEAR -** condition. For example: -** -** abc NEAR/5 "def ghi" -** -** Parameter nNear is passed the NEAR distance of the expression (5 in -** the example above). When this function is called, *paPoslist points to -** the position list, and *pnToken is the number of phrase tokens in, the -** phrase on the other side of the NEAR operator to pPhrase. For example, -** if pPhrase refers to the "def ghi" phrase, then *paPoslist points to -** the position list associated with phrase "abc". -** -** All positions in the pPhrase position list that are not sufficiently -** close to a position in the *paPoslist position list are removed. If this -** leaves 0 positions, zero is returned. Otherwise, non-zero. -** -** Before returning, *paPoslist is set to point to the position lsit -** associated with pPhrase. And *pnToken is set to the number of tokens in -** pPhrase. -*/ -static int fts3EvalNearTrim( - int nNear, /* NEAR distance. As in "NEAR/nNear". */ - char *aTmp, /* Temporary space to use */ - char **paPoslist, /* IN/OUT: Position list */ - int *pnToken, /* IN/OUT: Tokens in phrase of *paPoslist */ - Fts3Phrase *pPhrase /* The phrase object to trim the doclist of */ -){ - int nParam1 = nNear + pPhrase->nToken; - int nParam2 = nNear + *pnToken; - int nNew; - char *p2; - char *pOut; - int res; - - assert( pPhrase->doclist.pList ); - - p2 = pOut = pPhrase->doclist.pList; - res = fts3PoslistNearMerge( - &pOut, aTmp, nParam1, nParam2, paPoslist, &p2 - ); - if( res ){ - nNew = (int)(pOut - pPhrase->doclist.pList) - 1; - assert( pPhrase->doclist.pList[nNew]=='\0' ); - assert( nNew<=pPhrase->doclist.nList && nNew>0 ); - memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew); - pPhrase->doclist.nList = nNew; - *paPoslist = pPhrase->doclist.pList; - *pnToken = pPhrase->nToken; - } - - return res; -} - -/* -** This function is a no-op if *pRc is other than SQLITE_OK when it is called. -** Otherwise, it advances the expression passed as the second argument to -** point to the next matching row in the database. Expressions iterate through -** matching rows in docid order. Ascending order if Fts3Cursor.bDesc is zero, -** or descending if it is non-zero. -** -** If an error occurs, *pRc is set to an SQLite error code. Otherwise, if -** successful, the following variables in pExpr are set: -** -** Fts3Expr.bEof (non-zero if EOF - there is no next row) -** Fts3Expr.iDocid (valid if bEof==0. The docid of the next row) -** -** If the expression is of type FTSQUERY_PHRASE, and the expression is not -** at EOF, then the following variables are populated with the position list -** for the phrase for the visited row: -** -** FTs3Expr.pPhrase->doclist.nList (length of pList in bytes) -** FTs3Expr.pPhrase->doclist.pList (pointer to position list) -** -** It says above that this function advances the expression to the next -** matching row. This is usually true, but there are the following exceptions: -** -** 1. Deferred tokens are not taken into account. If a phrase consists -** entirely of deferred tokens, it is assumed to match every row in -** the db. In this case the position-list is not populated at all. -** -** Or, if a phrase contains one or more deferred tokens and one or -** more non-deferred tokens, then the expression is advanced to the -** next possible match, considering only non-deferred tokens. In other -** words, if the phrase is "A B C", and "B" is deferred, the expression -** is advanced to the next row that contains an instance of "A * C", -** where "*" may match any single token. The position list in this case -** is populated as for "A * C" before returning. -** -** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is -** advanced to point to the next row that matches "x AND y". -** -** See fts3EvalTestDeferredAndNear() for details on testing if a row is -** really a match, taking into account deferred tokens and NEAR operators. -*/ -static void fts3EvalNextRow( - Fts3Cursor *pCsr, /* FTS Cursor handle */ - Fts3Expr *pExpr, /* Expr. to advance to next matching row */ - int *pRc /* IN/OUT: Error code */ -){ - if( *pRc==SQLITE_OK ){ - int bDescDoclist = pCsr->bDesc; /* Used by DOCID_CMP() macro */ - assert( pExpr->bEof==0 ); - pExpr->bStart = 1; - - switch( pExpr->eType ){ - case FTSQUERY_NEAR: - case FTSQUERY_AND: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - assert( !pLeft->bDeferred || !pRight->bDeferred ); - - if( pLeft->bDeferred ){ - /* LHS is entirely deferred. So we assume it matches every row. - ** Advance the RHS iterator to find the next row visited. */ - fts3EvalNextRow(pCsr, pRight, pRc); - pExpr->iDocid = pRight->iDocid; - pExpr->bEof = pRight->bEof; - }else if( pRight->bDeferred ){ - /* RHS is entirely deferred. So we assume it matches every row. - ** Advance the LHS iterator to find the next row visited. */ - fts3EvalNextRow(pCsr, pLeft, pRc); - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = pLeft->bEof; - }else{ - /* Neither the RHS or LHS are deferred. */ - fts3EvalNextRow(pCsr, pLeft, pRc); - fts3EvalNextRow(pCsr, pRight, pRc); - while( !pLeft->bEof && !pRight->bEof && *pRc==SQLITE_OK ){ - sqlite3_int64 iDiff = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - if( iDiff==0 ) break; - if( iDiff<0 ){ - fts3EvalNextRow(pCsr, pLeft, pRc); - }else{ - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = (pLeft->bEof || pRight->bEof); - } - break; - } - - case FTSQUERY_OR: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - - assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid ); - assert( pRight->bStart || pLeft->iDocid==pRight->iDocid ); - - if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){ - fts3EvalNextRow(pCsr, pLeft, pRc); - }else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){ - fts3EvalNextRow(pCsr, pRight, pRc); - }else{ - fts3EvalNextRow(pCsr, pLeft, pRc); - fts3EvalNextRow(pCsr, pRight, pRc); - } - - pExpr->bEof = (pLeft->bEof && pRight->bEof); - iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid); - if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){ - pExpr->iDocid = pLeft->iDocid; - }else{ - pExpr->iDocid = pRight->iDocid; - } - - break; - } - - case FTSQUERY_NOT: { - Fts3Expr *pLeft = pExpr->pLeft; - Fts3Expr *pRight = pExpr->pRight; - - if( pRight->bStart==0 ){ - fts3EvalNextRow(pCsr, pRight, pRc); - assert( *pRc!=SQLITE_OK || pRight->bStart ); - } - - fts3EvalNextRow(pCsr, pLeft, pRc); - if( pLeft->bEof==0 ){ - while( !*pRc - && !pRight->bEof - && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0 - ){ - fts3EvalNextRow(pCsr, pRight, pRc); - } - } - pExpr->iDocid = pLeft->iDocid; - pExpr->bEof = pLeft->bEof; - break; - } - - default: { - Fts3Phrase *pPhrase = pExpr->pPhrase; - fts3EvalInvalidatePoslist(pPhrase); - *pRc = fts3EvalPhraseNext(pCsr, pPhrase, &pExpr->bEof); - pExpr->iDocid = pPhrase->doclist.iDocid; - break; - } - } - } -} - -/* -** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR -** cluster, then this function returns 1 immediately. -** -** Otherwise, it checks if the current row really does match the NEAR -** expression, using the data currently stored in the position lists -** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression. -** -** If the current row is a match, the position list associated with each -** phrase in the NEAR expression is edited in place to contain only those -** phrase instances sufficiently close to their peers to satisfy all NEAR -** constraints. In this case it returns 1. If the NEAR expression does not -** match the current row, 0 is returned. The position lists may or may not -** be edited if 0 is returned. -*/ -static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){ - int res = 1; - - /* The following block runs if pExpr is the root of a NEAR query. - ** For example, the query: - ** - ** "w" NEAR "x" NEAR "y" NEAR "z" - ** - ** which is represented in tree form as: - ** - ** | - ** +--NEAR--+ <-- root of NEAR query - ** | | - ** +--NEAR--+ "z" - ** | | - ** +--NEAR--+ "y" - ** | | - ** "w" "x" - ** - ** The right-hand child of a NEAR node is always a phrase. The - ** left-hand child may be either a phrase or a NEAR node. There are - ** no exceptions to this - it's the way the parser in fts3_expr.c works. - */ - if( *pRc==SQLITE_OK - && pExpr->eType==FTSQUERY_NEAR - && pExpr->bEof==0 - && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) - ){ - Fts3Expr *p; - int nTmp = 0; /* Bytes of temp space */ - char *aTmp; /* Temp space for PoslistNearMerge() */ - - /* Allocate temporary working space. */ - for(p=pExpr; p->pLeft; p=p->pLeft){ - nTmp += p->pRight->pPhrase->doclist.nList; - } - nTmp += p->pPhrase->doclist.nList; - if( nTmp==0 ){ - res = 0; - }else{ - aTmp = sqlite3_malloc(nTmp*2); - if( !aTmp ){ - *pRc = SQLITE_NOMEM; - res = 0; - }else{ - char *aPoslist = p->pPhrase->doclist.pList; - int nToken = p->pPhrase->nToken; - - for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){ - Fts3Phrase *pPhrase = p->pRight->pPhrase; - int nNear = p->nNear; - res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); - } - - aPoslist = pExpr->pRight->pPhrase->doclist.pList; - nToken = pExpr->pRight->pPhrase->nToken; - for(p=pExpr->pLeft; p && res; p=p->pLeft){ - int nNear; - Fts3Phrase *pPhrase; - assert( p->pParent && p->pParent->pLeft==p ); - nNear = p->pParent->nNear; - pPhrase = ( - p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase - ); - res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); - } - } - - sqlite3_free(aTmp); - } - } - - return res; -} - -/* -** This function is a helper function for fts3EvalTestDeferredAndNear(). -** Assuming no error occurs or has occurred, It returns non-zero if the -** expression passed as the second argument matches the row that pCsr -** currently points to, or zero if it does not. -** -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** If an error occurs during execution of this function, *pRc is set to -** the appropriate SQLite error code. In this case the returned value is -** undefined. -*/ -static int fts3EvalTestExpr( - Fts3Cursor *pCsr, /* FTS cursor handle */ - Fts3Expr *pExpr, /* Expr to test. May or may not be root. */ - int *pRc /* IN/OUT: Error code */ -){ - int bHit = 1; /* Return value */ - if( *pRc==SQLITE_OK ){ - switch( pExpr->eType ){ - case FTSQUERY_NEAR: - case FTSQUERY_AND: - bHit = ( - fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc) - && fts3EvalTestExpr(pCsr, pExpr->pRight, pRc) - && fts3EvalNearTest(pExpr, pRc) - ); - - /* If the NEAR expression does not match any rows, zero the doclist for - ** all phrases involved in the NEAR. This is because the snippet(), - ** offsets() and matchinfo() functions are not supposed to recognize - ** any instances of phrases that are part of unmatched NEAR queries. - ** For example if this expression: - ** - ** ... MATCH 'a OR (b NEAR c)' - ** - ** is matched against a row containing: - ** - ** 'a b d e' - ** - ** then any snippet() should ony highlight the "a" term, not the "b" - ** (as "b" is part of a non-matching NEAR clause). - */ - if( bHit==0 - && pExpr->eType==FTSQUERY_NEAR - && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR) - ){ - Fts3Expr *p; - for(p=pExpr; p->pPhrase==0; p=p->pLeft){ - if( p->pRight->iDocid==pCsr->iPrevId ){ - fts3EvalInvalidatePoslist(p->pRight->pPhrase); - } - } - if( p->iDocid==pCsr->iPrevId ){ - fts3EvalInvalidatePoslist(p->pPhrase); - } - } - - break; - - case FTSQUERY_OR: { - int bHit1 = fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc); - int bHit2 = fts3EvalTestExpr(pCsr, pExpr->pRight, pRc); - bHit = bHit1 || bHit2; - break; - } - - case FTSQUERY_NOT: - bHit = ( - fts3EvalTestExpr(pCsr, pExpr->pLeft, pRc) - && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc) - ); - break; - - default: { -#ifndef SQLITE_DISABLE_FTS4_DEFERRED - if( pCsr->pDeferred - && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred) - ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 ); - if( pExpr->bDeferred ){ - fts3EvalInvalidatePoslist(pPhrase); - } - *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase); - bHit = (pPhrase->doclist.pList!=0); - pExpr->iDocid = pCsr->iPrevId; - }else -#endif - { - bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId); - } - break; - } - } - } - return bHit; -} - -/* -** This function is called as the second part of each xNext operation when -** iterating through the results of a full-text query. At this point the -** cursor points to a row that matches the query expression, with the -** following caveats: -** -** * Up until this point, "NEAR" operators in the expression have been -** treated as "AND". -** -** * Deferred tokens have not yet been considered. -** -** If *pRc is not SQLITE_OK when this function is called, it immediately -** returns 0. Otherwise, it tests whether or not after considering NEAR -** operators and deferred tokens the current row is still a match for the -** expression. It returns 1 if both of the following are true: -** -** 1. *pRc is SQLITE_OK when this function returns, and -** -** 2. After scanning the current FTS table row for the deferred tokens, -** it is determined that the row does *not* match the query. -** -** Or, if no error occurs and it seems the current row does match the FTS -** query, return 0. -*/ -static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){ - int rc = *pRc; - int bMiss = 0; - if( rc==SQLITE_OK ){ - - /* If there are one or more deferred tokens, load the current row into - ** memory and scan it to determine the position list for each deferred - ** token. Then, see if this row is really a match, considering deferred - ** tokens and NEAR operators (neither of which were taken into account - ** earlier, by fts3EvalNextRow()). - */ - if( pCsr->pDeferred ){ - rc = fts3CursorSeek(0, pCsr); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3CacheDeferredDoclists(pCsr); - } - } - bMiss = (0==fts3EvalTestExpr(pCsr, pCsr->pExpr, &rc)); - - /* Free the position-lists accumulated for each deferred token above. */ - sqlite3Fts3FreeDeferredDoclists(pCsr); - *pRc = rc; - } - return (rc==SQLITE_OK && bMiss); -} - -/* -** Advance to the next document that matches the FTS expression in -** Fts3Cursor.pExpr. -*/ -static int fts3EvalNext(Fts3Cursor *pCsr){ - int rc = SQLITE_OK; /* Return Code */ - Fts3Expr *pExpr = pCsr->pExpr; - assert( pCsr->isEof==0 ); - if( pExpr==0 ){ - pCsr->isEof = 1; - }else{ - do { - if( pCsr->isRequireSeek==0 ){ - sqlite3_reset(pCsr->pStmt); - } - assert( sqlite3_data_count(pCsr->pStmt)==0 ); - fts3EvalNextRow(pCsr, pExpr, &rc); - pCsr->isEof = pExpr->bEof; - pCsr->isRequireSeek = 1; - pCsr->isMatchinfoNeeded = 1; - pCsr->iPrevId = pExpr->iDocid; - }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) ); - } - return rc; -} - -/* -** Restart interation for expression pExpr so that the next call to -** fts3EvalNext() visits the first row. Do not allow incremental -** loading or merging of phrase doclists for this iteration. -** -** If *pRc is other than SQLITE_OK when this function is called, it is -** a no-op. If an error occurs within this function, *pRc is set to an -** SQLite error code before returning. -*/ -static void fts3EvalRestart( - Fts3Cursor *pCsr, - Fts3Expr *pExpr, - int *pRc -){ - if( pExpr && *pRc==SQLITE_OK ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - - if( pPhrase ){ - fts3EvalInvalidatePoslist(pPhrase); - if( pPhrase->bIncr ){ - assert( pPhrase->nToken==1 ); - assert( pPhrase->aToken[0].pSegcsr ); - sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr); - *pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase); - } - - pPhrase->doclist.pNextDocid = 0; - pPhrase->doclist.iDocid = 0; - } - - pExpr->iDocid = 0; - pExpr->bEof = 0; - pExpr->bStart = 0; - - fts3EvalRestart(pCsr, pExpr->pLeft, pRc); - fts3EvalRestart(pCsr, pExpr->pRight, pRc); - } -} - -/* -** After allocating the Fts3Expr.aMI[] array for each phrase in the -** expression rooted at pExpr, the cursor iterates through all rows matched -** by pExpr, calling this function for each row. This function increments -** the values in Fts3Expr.aMI[] according to the position-list currently -** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase -** expression nodes. -*/ -static void fts3EvalUpdateCounts(Fts3Expr *pExpr){ - if( pExpr ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - if( pPhrase && pPhrase->doclist.pList ){ - int iCol = 0; - char *p = pPhrase->doclist.pList; - - assert( *p ); - while( 1 ){ - u8 c = 0; - int iCnt = 0; - while( 0xFE & (*p | c) ){ - if( (c&0x80)==0 ) iCnt++; - c = *p++ & 0x80; - } - - /* aMI[iCol*3 + 1] = Number of occurrences - ** aMI[iCol*3 + 2] = Number of rows containing at least one instance - */ - pExpr->aMI[iCol*3 + 1] += iCnt; - pExpr->aMI[iCol*3 + 2] += (iCnt>0); - if( *p==0x00 ) break; - p++; - p += sqlite3Fts3GetVarint32(p, &iCol); - } - } - - fts3EvalUpdateCounts(pExpr->pLeft); - fts3EvalUpdateCounts(pExpr->pRight); - } -} - -/* -** Expression pExpr must be of type FTSQUERY_PHRASE. -** -** If it is not already allocated and populated, this function allocates and -** populates the Fts3Expr.aMI[] array for expression pExpr. If pExpr is part -** of a NEAR expression, then it also allocates and populates the same array -** for all other phrases that are part of the NEAR expression. -** -** SQLITE_OK is returned if the aMI[] array is successfully allocated and -** populated. Otherwise, if an error occurs, an SQLite error code is returned. -*/ -static int fts3EvalGatherStats( - Fts3Cursor *pCsr, /* Cursor object */ - Fts3Expr *pExpr /* FTSQUERY_PHRASE expression */ -){ - int rc = SQLITE_OK; /* Return code */ - - assert( pExpr->eType==FTSQUERY_PHRASE ); - if( pExpr->aMI==0 ){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - Fts3Expr *pRoot; /* Root of NEAR expression */ - Fts3Expr *p; /* Iterator used for several purposes */ - - sqlite3_int64 iPrevId = pCsr->iPrevId; - sqlite3_int64 iDocid; - u8 bEof; - - /* Find the root of the NEAR expression */ - pRoot = pExpr; - while( pRoot->pParent && pRoot->pParent->eType==FTSQUERY_NEAR ){ - pRoot = pRoot->pParent; - } - iDocid = pRoot->iDocid; - bEof = pRoot->bEof; - assert( pRoot->bStart ); - - /* Allocate space for the aMSI[] array of each FTSQUERY_PHRASE node */ - for(p=pRoot; p; p=p->pLeft){ - Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight); - assert( pE->aMI==0 ); - pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32)); - if( !pE->aMI ) return SQLITE_NOMEM; - memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32)); - } - - fts3EvalRestart(pCsr, pRoot, &rc); - - while( pCsr->isEof==0 && rc==SQLITE_OK ){ - - do { - /* Ensure the %_content statement is reset. */ - if( pCsr->isRequireSeek==0 ) sqlite3_reset(pCsr->pStmt); - assert( sqlite3_data_count(pCsr->pStmt)==0 ); - - /* Advance to the next document */ - fts3EvalNextRow(pCsr, pRoot, &rc); - pCsr->isEof = pRoot->bEof; - pCsr->isRequireSeek = 1; - pCsr->isMatchinfoNeeded = 1; - pCsr->iPrevId = pRoot->iDocid; - }while( pCsr->isEof==0 - && pRoot->eType==FTSQUERY_NEAR - && fts3EvalTestDeferredAndNear(pCsr, &rc) - ); - - if( rc==SQLITE_OK && pCsr->isEof==0 ){ - fts3EvalUpdateCounts(pRoot); - } - } - - pCsr->isEof = 0; - pCsr->iPrevId = iPrevId; - - if( bEof ){ - pRoot->bEof = bEof; - }else{ - /* Caution: pRoot may iterate through docids in ascending or descending - ** order. For this reason, even though it seems more defensive, the - ** do loop can not be written: - ** - ** do {...} while( pRoot->iDocidbEof==0 ); - }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); - fts3EvalTestDeferredAndNear(pCsr, &rc); - } - } - return rc; -} - -/* -** This function is used by the matchinfo() module to query a phrase -** expression node for the following information: -** -** 1. The total number of occurrences of the phrase in each column of -** the FTS table (considering all rows), and -** -** 2. For each column, the number of rows in the table for which the -** column contains at least one instance of the phrase. -** -** If no error occurs, SQLITE_OK is returned and the values for each column -** written into the array aiOut as follows: -** -** aiOut[iCol*3 + 1] = Number of occurrences -** aiOut[iCol*3 + 2] = Number of rows containing at least one instance -** -** Caveats: -** -** * If a phrase consists entirely of deferred tokens, then all output -** values are set to the number of documents in the table. In other -** words we assume that very common tokens occur exactly once in each -** column of each row of the table. -** -** * If a phrase contains some deferred tokens (and some non-deferred -** tokens), count the potential occurrence identified by considering -** the non-deferred tokens instead of actual phrase occurrences. -** -** * If the phrase is part of a NEAR expression, then only phrase instances -** that meet the NEAR constraint are included in the counts. -*/ -SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats( - Fts3Cursor *pCsr, /* FTS cursor handle */ - Fts3Expr *pExpr, /* Phrase expression */ - u32 *aiOut /* Array to write results into (see above) */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int iCol; - - if( pExpr->bDeferred && pExpr->pParent->eType!=FTSQUERY_NEAR ){ - assert( pCsr->nDoc>0 ); - for(iCol=0; iColnColumn; iCol++){ - aiOut[iCol*3 + 1] = (u32)pCsr->nDoc; - aiOut[iCol*3 + 2] = (u32)pCsr->nDoc; - } - }else{ - rc = fts3EvalGatherStats(pCsr, pExpr); - if( rc==SQLITE_OK ){ - assert( pExpr->aMI ); - for(iCol=0; iColnColumn; iCol++){ - aiOut[iCol*3 + 1] = pExpr->aMI[iCol*3 + 1]; - aiOut[iCol*3 + 2] = pExpr->aMI[iCol*3 + 2]; - } - } - } - - return rc; -} - -/* -** The expression pExpr passed as the second argument to this function -** must be of type FTSQUERY_PHRASE. -** -** The returned value is either NULL or a pointer to a buffer containing -** a position-list indicating the occurrences of the phrase in column iCol -** of the current row. -** -** More specifically, the returned buffer contains 1 varint for each -** occurrence of the phrase in the column, stored using the normal (delta+2) -** compression and is terminated by either an 0x01 or 0x00 byte. For example, -** if the requested column contains "a b X c d X X" and the position-list -** for 'X' is requested, the buffer returned may contain: -** -** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00 -** -** This function works regardless of whether or not the phrase is deferred, -** incremental, or neither. -*/ -SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( - Fts3Cursor *pCsr, /* FTS3 cursor object */ - Fts3Expr *pExpr, /* Phrase to return doclist for */ - int iCol, /* Column to return position list for */ - char **ppOut /* OUT: Pointer to position list */ -){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - char *pIter; - int iThis; - sqlite3_int64 iDocid; - - /* If this phrase is applies specifically to some column other than - ** column iCol, return a NULL pointer. */ - *ppOut = 0; - assert( iCol>=0 && iColnColumn ); - if( (pPhrase->iColumnnColumn && pPhrase->iColumn!=iCol) ){ - return SQLITE_OK; - } - - iDocid = pExpr->iDocid; - pIter = pPhrase->doclist.pList; - if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ - int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ - int bOr = 0; - u8 bEof = 0; - Fts3Expr *p; - - /* Check if this phrase descends from an OR expression node. If not, - ** return NULL. Otherwise, the entry that corresponds to docid - ** pCsr->iPrevId may lie earlier in the doclist buffer. */ - for(p=pExpr->pParent; p; p=p->pParent){ - if( p->eType==FTSQUERY_OR ) bOr = 1; - } - if( bOr==0 ) return SQLITE_OK; - - /* This is the descendent of an OR node. In this case we cannot use - ** an incremental phrase. Load the entire doclist for the phrase - ** into memory in this case. */ - if( pPhrase->bIncr ){ - int rc = SQLITE_OK; - int bEofSave = pExpr->bEof; - fts3EvalRestart(pCsr, pExpr, &rc); - while( rc==SQLITE_OK && !pExpr->bEof ){ - fts3EvalNextRow(pCsr, pExpr, &rc); - if( bEofSave==0 && pExpr->iDocid==iDocid ) break; - } - pIter = pPhrase->doclist.pList; - assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); - if( rc!=SQLITE_OK ) return rc; - } - - if( pExpr->bEof ){ - pIter = 0; - iDocid = 0; - } - bEof = (pPhrase->doclist.nAll==0); - assert( bDescDoclist==0 || bDescDoclist==1 ); - assert( pCsr->bDesc==0 || pCsr->bDesc==1 ); - - if( pCsr->bDesc==bDescDoclist ){ - int dummy; - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ - sqlite3Fts3DoclistPrev( - bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, - &pIter, &iDocid, &dummy, &bEof - ); - } - }else{ - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ - sqlite3Fts3DoclistNext( - bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, - &pIter, &iDocid, &bEof - ); - } - } - - if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0; - } - if( pIter==0 ) return SQLITE_OK; - - if( *pIter==0x01 ){ - pIter++; - pIter += sqlite3Fts3GetVarint32(pIter, &iThis); - }else{ - iThis = 0; - } - while( iThisdoclist, and -** * any Fts3MultiSegReader objects held by phrase tokens. -*/ -SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){ - if( pPhrase ){ - int i; - sqlite3_free(pPhrase->doclist.aAll); - fts3EvalInvalidatePoslist(pPhrase); - memset(&pPhrase->doclist, 0, sizeof(Fts3Doclist)); - for(i=0; inToken; i++){ - fts3SegReaderCursorFree(pPhrase->aToken[i].pSegcsr); - pPhrase->aToken[i].pSegcsr = 0; - } - } -} - - -/* -** Return SQLITE_CORRUPT_VTAB. -*/ -#ifdef SQLITE_DEBUG -SQLITE_PRIVATE int sqlite3Fts3Corrupt(){ - return SQLITE_CORRUPT_VTAB; -} -#endif - -#if !SQLITE_CORE -/* -** Initialize API pointer table, if required. -*/ -SQLITE_API int sqlite3_extension_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3Fts3Init(db); -} -#endif - -#endif - -/************** End of fts3.c ************************************************/ -/************** Begin file fts3_aux.c ****************************************/ -/* -** 2011 Jan 27 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ - -typedef struct Fts3auxTable Fts3auxTable; -typedef struct Fts3auxCursor Fts3auxCursor; - -struct Fts3auxTable { - sqlite3_vtab base; /* Base class used by SQLite core */ - Fts3Table *pFts3Tab; -}; - -struct Fts3auxCursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - Fts3MultiSegReader csr; /* Must be right after "base" */ - Fts3SegFilter filter; - char *zStop; - int nStop; /* Byte-length of string zStop */ - int isEof; /* True if cursor is at EOF */ - sqlite3_int64 iRowid; /* Current rowid */ - - int iCol; /* Current value of 'col' column */ - int nStat; /* Size of aStat[] array */ - struct Fts3auxColstats { - sqlite3_int64 nDoc; /* 'documents' values for current csr row */ - sqlite3_int64 nOcc; /* 'occurrences' values for current csr row */ - } *aStat; -}; - -/* -** Schema of the terms table. -*/ -#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)" - -/* -** This function does all the work for both the xConnect and xCreate methods. -** These tables have no persistent representation of their own, so xConnect -** and xCreate are identical operations. -*/ -static int fts3auxConnectMethod( - sqlite3 *db, /* Database connection */ - void *pUnused, /* Unused */ - int argc, /* Number of elements in argv array */ - const char * const *argv, /* xCreate/xConnect argument array */ - sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ - char **pzErr /* OUT: sqlite3_malloc'd error message */ -){ - char const *zDb; /* Name of database (e.g. "main") */ - char const *zFts3; /* Name of fts3 table */ - int nDb; /* Result of strlen(zDb) */ - int nFts3; /* Result of strlen(zFts3) */ - int nByte; /* Bytes of space to allocate here */ - int rc; /* value returned by declare_vtab() */ - Fts3auxTable *p; /* Virtual table object to return */ - - UNUSED_PARAMETER(pUnused); - - /* The user should invoke this in one of two forms: - ** - ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table); - ** CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table); - */ - if( argc!=4 && argc!=5 ) goto bad_args; - - zDb = argv[1]; - nDb = (int)strlen(zDb); - if( argc==5 ){ - if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){ - zDb = argv[3]; - nDb = (int)strlen(zDb); - zFts3 = argv[4]; - }else{ - goto bad_args; - } - }else{ - zFts3 = argv[3]; - } - nFts3 = (int)strlen(zFts3); - - rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA); - if( rc!=SQLITE_OK ) return rc; - - nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; - p = (Fts3auxTable *)sqlite3_malloc(nByte); - if( !p ) return SQLITE_NOMEM; - memset(p, 0, nByte); - - p->pFts3Tab = (Fts3Table *)&p[1]; - p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1]; - p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1]; - p->pFts3Tab->db = db; - p->pFts3Tab->nIndex = 1; - - memcpy((char *)p->pFts3Tab->zDb, zDb, nDb); - memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3); - sqlite3Fts3Dequote((char *)p->pFts3Tab->zName); - - *ppVtab = (sqlite3_vtab *)p; - return SQLITE_OK; - - bad_args: - *pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor"); - return SQLITE_ERROR; -} - -/* -** This function does the work for both the xDisconnect and xDestroy methods. -** These tables have no persistent representation of their own, so xDisconnect -** and xDestroy are identical operations. -*/ -static int fts3auxDisconnectMethod(sqlite3_vtab *pVtab){ - Fts3auxTable *p = (Fts3auxTable *)pVtab; - Fts3Table *pFts3 = p->pFts3Tab; - int i; - - /* Free any prepared statements held */ - for(i=0; iaStmt); i++){ - sqlite3_finalize(pFts3->aStmt[i]); - } - sqlite3_free(pFts3->zSegmentsTbl); - sqlite3_free(p); - return SQLITE_OK; -} - -#define FTS4AUX_EQ_CONSTRAINT 1 -#define FTS4AUX_GE_CONSTRAINT 2 -#define FTS4AUX_LE_CONSTRAINT 4 - -/* -** xBestIndex - Analyze a WHERE and ORDER BY clause. -*/ -static int fts3auxBestIndexMethod( - sqlite3_vtab *pVTab, - sqlite3_index_info *pInfo -){ - int i; - int iEq = -1; - int iGe = -1; - int iLe = -1; - - UNUSED_PARAMETER(pVTab); - - /* This vtab delivers always results in "ORDER BY term ASC" order. */ - if( pInfo->nOrderBy==1 - && pInfo->aOrderBy[0].iColumn==0 - && pInfo->aOrderBy[0].desc==0 - ){ - pInfo->orderByConsumed = 1; - } - - /* Search for equality and range constraints on the "term" column. */ - for(i=0; inConstraint; i++){ - if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){ - int op = pInfo->aConstraint[i].op; - if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i; - if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i; - if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i; - if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i; - if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i; - } - } - - if( iEq>=0 ){ - pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT; - pInfo->aConstraintUsage[iEq].argvIndex = 1; - pInfo->estimatedCost = 5; - }else{ - pInfo->idxNum = 0; - pInfo->estimatedCost = 20000; - if( iGe>=0 ){ - pInfo->idxNum += FTS4AUX_GE_CONSTRAINT; - pInfo->aConstraintUsage[iGe].argvIndex = 1; - pInfo->estimatedCost /= 2; - } - if( iLe>=0 ){ - pInfo->idxNum += FTS4AUX_LE_CONSTRAINT; - pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0); - pInfo->estimatedCost /= 2; - } - } - - return SQLITE_OK; -} - -/* -** xOpen - Open a cursor. -*/ -static int fts3auxOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - Fts3auxCursor *pCsr; /* Pointer to cursor object to return */ - - UNUSED_PARAMETER(pVTab); - - pCsr = (Fts3auxCursor *)sqlite3_malloc(sizeof(Fts3auxCursor)); - if( !pCsr ) return SQLITE_NOMEM; - memset(pCsr, 0, sizeof(Fts3auxCursor)); - - *ppCsr = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** xClose - Close a cursor. -*/ -static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - - sqlite3Fts3SegmentsClose(pFts3); - sqlite3Fts3SegReaderFinish(&pCsr->csr); - sqlite3_free((void *)pCsr->filter.zTerm); - sqlite3_free(pCsr->zStop); - sqlite3_free(pCsr->aStat); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){ - if( nSize>pCsr->nStat ){ - struct Fts3auxColstats *aNew; - aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat, - sizeof(struct Fts3auxColstats) * nSize - ); - if( aNew==0 ) return SQLITE_NOMEM; - memset(&aNew[pCsr->nStat], 0, - sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat) - ); - pCsr->aStat = aNew; - pCsr->nStat = nSize; - } - return SQLITE_OK; -} - -/* -** xNext - Advance the cursor to the next row, if any. -*/ -static int fts3auxNextMethod(sqlite3_vtab_cursor *pCursor){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - int rc; - - /* Increment our pretend rowid value. */ - pCsr->iRowid++; - - for(pCsr->iCol++; pCsr->iColnStat; pCsr->iCol++){ - if( pCsr->aStat[pCsr->iCol].nDoc>0 ) return SQLITE_OK; - } - - rc = sqlite3Fts3SegReaderStep(pFts3, &pCsr->csr); - if( rc==SQLITE_ROW ){ - int i = 0; - int nDoclist = pCsr->csr.nDoclist; - char *aDoclist = pCsr->csr.aDoclist; - int iCol; - - int eState = 0; - - if( pCsr->zStop ){ - int n = (pCsr->nStopcsr.nTerm) ? pCsr->nStop : pCsr->csr.nTerm; - int mc = memcmp(pCsr->zStop, pCsr->csr.zTerm, n); - if( mc<0 || (mc==0 && pCsr->csr.nTerm>pCsr->nStop) ){ - pCsr->isEof = 1; - return SQLITE_OK; - } - } - - if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM; - memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat); - iCol = 0; - - while( iaStat[0].nDoc++; - eState = 1; - iCol = 0; - break; - - /* State 1. In this state we are expecting either a 1, indicating - ** that the following integer will be a column number, or the - ** start of a position list for column 0. - ** - ** The only difference between state 1 and state 2 is that if the - ** integer encountered in state 1 is not 0 or 1, then we need to - ** increment the column 0 "nDoc" count for this term. - */ - case 1: - assert( iCol==0 ); - if( v>1 ){ - pCsr->aStat[1].nDoc++; - } - eState = 2; - /* fall through */ - - case 2: - if( v==0 ){ /* 0x00. Next integer will be a docid. */ - eState = 0; - }else if( v==1 ){ /* 0x01. Next integer will be a column number. */ - eState = 3; - }else{ /* 2 or greater. A position. */ - pCsr->aStat[iCol+1].nOcc++; - pCsr->aStat[0].nOcc++; - } - break; - - /* State 3. The integer just read is a column number. */ - default: assert( eState==3 ); - iCol = (int)v; - if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM; - pCsr->aStat[iCol+1].nDoc++; - eState = 2; - break; - } - } - - pCsr->iCol = 0; - rc = SQLITE_OK; - }else{ - pCsr->isEof = 1; - } - return rc; -} - -/* -** xFilter - Initialize a cursor to point at the start of its data. -*/ -static int fts3auxFilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab; - int rc; - int isScan; - - UNUSED_PARAMETER(nVal); - UNUSED_PARAMETER(idxStr); - - assert( idxStr==0 ); - assert( idxNum==FTS4AUX_EQ_CONSTRAINT || idxNum==0 - || idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT - || idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) - ); - isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT); - - /* In case this cursor is being reused, close and zero it. */ - testcase(pCsr->filter.zTerm); - sqlite3Fts3SegReaderFinish(&pCsr->csr); - sqlite3_free((void *)pCsr->filter.zTerm); - sqlite3_free(pCsr->aStat); - memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr); - - pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; - if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN; - - if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){ - const unsigned char *zStr = sqlite3_value_text(apVal[0]); - if( zStr ){ - pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr); - pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]); - if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM; - } - } - if( idxNum&FTS4AUX_LE_CONSTRAINT ){ - int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0; - pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx])); - pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]); - if( pCsr->zStop==0 ) return SQLITE_NOMEM; - } - - rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL, - pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr - ); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3SegReaderStart(pFts3, &pCsr->csr, &pCsr->filter); - } - - if( rc==SQLITE_OK ) rc = fts3auxNextMethod(pCursor); - return rc; -} - -/* -** xEof - Return true if the cursor is at EOF, or false otherwise. -*/ -static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - return pCsr->isEof; -} - -/* -** xColumn - Return a column value. -*/ -static int fts3auxColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - Fts3auxCursor *p = (Fts3auxCursor *)pCursor; - - assert( p->isEof==0 ); - if( iCol==0 ){ /* Column "term" */ - sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT); - }else if( iCol==1 ){ /* Column "col" */ - if( p->iCol ){ - sqlite3_result_int(pContext, p->iCol-1); - }else{ - sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC); - } - }else if( iCol==2 ){ /* Column "documents" */ - sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc); - }else{ /* Column "occurrences" */ - sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc); - } - - return SQLITE_OK; -} - -/* -** xRowid - Return the current rowid for the cursor. -*/ -static int fts3auxRowidMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite_int64 *pRowid /* OUT: Rowid value */ -){ - Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor; - *pRowid = pCsr->iRowid; - return SQLITE_OK; -} - -/* -** Register the fts3aux module with database connection db. Return SQLITE_OK -** if successful or an error code if sqlite3_create_module() fails. -*/ -SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){ - static const sqlite3_module fts3aux_module = { - 0, /* iVersion */ - fts3auxConnectMethod, /* xCreate */ - fts3auxConnectMethod, /* xConnect */ - fts3auxBestIndexMethod, /* xBestIndex */ - fts3auxDisconnectMethod, /* xDisconnect */ - fts3auxDisconnectMethod, /* xDestroy */ - fts3auxOpenMethod, /* xOpen */ - fts3auxCloseMethod, /* xClose */ - fts3auxFilterMethod, /* xFilter */ - fts3auxNextMethod, /* xNext */ - fts3auxEofMethod, /* xEof */ - fts3auxColumnMethod, /* xColumn */ - fts3auxRowidMethod, /* xRowid */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindFunction */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0 /* xRollbackTo */ - }; - int rc; /* Return code */ - - rc = sqlite3_create_module(db, "fts4aux", &fts3aux_module, 0); - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_aux.c ********************************************/ -/************** Begin file fts3_expr.c ***************************************/ -/* -** 2008 Nov 28 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This module contains code that implements a parser for fts3 query strings -** (the right-hand argument to the MATCH operator). Because the supported -** syntax is relatively simple, the whole tokenizer/parser system is -** hand-coded. -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* -** By default, this module parses the legacy syntax that has been -** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS -** is defined, then it uses the new syntax. The differences between -** the new and the old syntaxes are: -** -** a) The new syntax supports parenthesis. The old does not. -** -** b) The new syntax supports the AND and NOT operators. The old does not. -** -** c) The old syntax supports the "-" token qualifier. This is not -** supported by the new syntax (it is replaced by the NOT operator). -** -** d) When using the old syntax, the OR operator has a greater precedence -** than an implicit AND. When using the new, both implicity and explicit -** AND operators have a higher precedence than OR. -** -** If compiled with SQLITE_TEST defined, then this module exports the -** symbol "int sqlite3_fts3_enable_parentheses". Setting this variable -** to zero causes the module to use the old syntax. If it is set to -** non-zero the new syntax is activated. This is so both syntaxes can -** be tested using a single build of testfixture. -** -** The following describes the syntax supported by the fts3 MATCH -** operator in a similar format to that used by the lemon parser -** generator. This module does not use actually lemon, it uses a -** custom parser. -** -** query ::= andexpr (OR andexpr)*. -** -** andexpr ::= notexpr (AND? notexpr)*. -** -** notexpr ::= nearexpr (NOT nearexpr|-TOKEN)*. -** notexpr ::= LP query RP. -** -** nearexpr ::= phrase (NEAR distance_opt nearexpr)*. -** -** distance_opt ::= . -** distance_opt ::= / INTEGER. -** -** phrase ::= TOKEN. -** phrase ::= COLUMN:TOKEN. -** phrase ::= "TOKEN TOKEN TOKEN...". -*/ - -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_fts3_enable_parentheses = 0; -#else -# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS -# define sqlite3_fts3_enable_parentheses 1 -# else -# define sqlite3_fts3_enable_parentheses 0 -# endif -#endif - -/* -** Default span for NEAR operators. -*/ -#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10 - -/* #include */ -/* #include */ - -/* -** isNot: -** This variable is used by function getNextNode(). When getNextNode() is -** called, it sets ParseContext.isNot to true if the 'next node' is a -** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the -** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to -** zero. -*/ -typedef struct ParseContext ParseContext; -struct ParseContext { - sqlite3_tokenizer *pTokenizer; /* Tokenizer module */ - int iLangid; /* Language id used with tokenizer */ - const char **azCol; /* Array of column names for fts3 table */ - int bFts4; /* True to allow FTS4-only syntax */ - int nCol; /* Number of entries in azCol[] */ - int iDefaultCol; /* Default column to query */ - int isNot; /* True if getNextNode() sees a unary - */ - sqlite3_context *pCtx; /* Write error message here */ - int nNest; /* Number of nested brackets */ -}; - -/* -** This function is equivalent to the standard isspace() function. -** -** The standard isspace() can be awkward to use safely, because although it -** is defined to accept an argument of type int, its behavior when passed -** an integer that falls outside of the range of the unsigned char type -** is undefined (and sometimes, "undefined" means segfault). This wrapper -** is defined to accept an argument of type char, and always returns 0 for -** any values that fall outside of the range of the unsigned char type (i.e. -** negative values). -*/ -static int fts3isspace(char c){ - return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f'; -} - -/* -** Allocate nByte bytes of memory using sqlite3_malloc(). If successful, -** zero the memory before returning a pointer to it. If unsuccessful, -** return NULL. -*/ -static void *fts3MallocZero(int nByte){ - void *pRet = sqlite3_malloc(nByte); - if( pRet ) memset(pRet, 0, nByte); - return pRet; -} - -SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer( - sqlite3_tokenizer *pTokenizer, - int iLangid, - const char *z, - int n, - sqlite3_tokenizer_cursor **ppCsr -){ - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - sqlite3_tokenizer_cursor *pCsr = 0; - int rc; - - rc = pModule->xOpen(pTokenizer, z, n, &pCsr); - assert( rc==SQLITE_OK || pCsr==0 ); - if( rc==SQLITE_OK ){ - pCsr->pTokenizer = pTokenizer; - if( pModule->iVersion>=1 ){ - rc = pModule->xLanguageid(pCsr, iLangid); - if( rc!=SQLITE_OK ){ - pModule->xClose(pCsr); - pCsr = 0; - } - } - } - *ppCsr = pCsr; - return rc; -} - - -/* -** Extract the next token from buffer z (length n) using the tokenizer -** and other information (column names etc.) in pParse. Create an Fts3Expr -** structure of type FTSQUERY_PHRASE containing a phrase consisting of this -** single token and set *ppExpr to point to it. If the end of the buffer is -** reached before a token is found, set *ppExpr to zero. It is the -** responsibility of the caller to eventually deallocate the allocated -** Fts3Expr structure (if any) by passing it to sqlite3_free(). -** -** Return SQLITE_OK if successful, or SQLITE_NOMEM if a memory allocation -** fails. -*/ -static int getNextToken( - ParseContext *pParse, /* fts3 query parse context */ - int iCol, /* Value for Fts3Phrase.iColumn */ - const char *z, int n, /* Input string */ - Fts3Expr **ppExpr, /* OUT: expression */ - int *pnConsumed /* OUT: Number of bytes consumed */ -){ - sqlite3_tokenizer *pTokenizer = pParse->pTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - int rc; - sqlite3_tokenizer_cursor *pCursor; - Fts3Expr *pRet = 0; - int nConsumed = 0; - - rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); - if( rc==SQLITE_OK ){ - const char *zToken; - int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0; - int nByte; /* total space to allocate */ - - rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); - if( rc==SQLITE_OK ){ - nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; - pRet = (Fts3Expr *)fts3MallocZero(nByte); - if( !pRet ){ - rc = SQLITE_NOMEM; - }else{ - pRet->eType = FTSQUERY_PHRASE; - pRet->pPhrase = (Fts3Phrase *)&pRet[1]; - pRet->pPhrase->nToken = 1; - pRet->pPhrase->iColumn = iCol; - pRet->pPhrase->aToken[0].n = nToken; - pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1]; - memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken); - - if( iEndpPhrase->aToken[0].isPrefix = 1; - iEnd++; - } - - while( 1 ){ - if( !sqlite3_fts3_enable_parentheses - && iStart>0 && z[iStart-1]=='-' - ){ - pParse->isNot = 1; - iStart--; - }else if( pParse->bFts4 && iStart>0 && z[iStart-1]=='^' ){ - pRet->pPhrase->aToken[0].bFirst = 1; - iStart--; - }else{ - break; - } - } - - } - nConsumed = iEnd; - } - - pModule->xClose(pCursor); - } - - *pnConsumed = nConsumed; - *ppExpr = pRet; - return rc; -} - - -/* -** Enlarge a memory allocation. If an out-of-memory allocation occurs, -** then free the old allocation. -*/ -static void *fts3ReallocOrFree(void *pOrig, int nNew){ - void *pRet = sqlite3_realloc(pOrig, nNew); - if( !pRet ){ - sqlite3_free(pOrig); - } - return pRet; -} - -/* -** Buffer zInput, length nInput, contains the contents of a quoted string -** that appeared as part of an fts3 query expression. Neither quote character -** is included in the buffer. This function attempts to tokenize the entire -** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE -** containing the results. -** -** If successful, SQLITE_OK is returned and *ppExpr set to point at the -** allocated Fts3Expr structure. Otherwise, either SQLITE_NOMEM (out of memory -** error) or SQLITE_ERROR (tokenization error) is returned and *ppExpr set -** to 0. -*/ -static int getNextString( - ParseContext *pParse, /* fts3 query parse context */ - const char *zInput, int nInput, /* Input string */ - Fts3Expr **ppExpr /* OUT: expression */ -){ - sqlite3_tokenizer *pTokenizer = pParse->pTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - int rc; - Fts3Expr *p = 0; - sqlite3_tokenizer_cursor *pCursor = 0; - char *zTemp = 0; - int nTemp = 0; - - const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase); - int nToken = 0; - - /* The final Fts3Expr data structure, including the Fts3Phrase, - ** Fts3PhraseToken structures token buffers are all stored as a single - ** allocation so that the expression can be freed with a single call to - ** sqlite3_free(). Setting this up requires a two pass approach. - ** - ** The first pass, in the block below, uses a tokenizer cursor to iterate - ** through the tokens in the expression. This pass uses fts3ReallocOrFree() - ** to assemble data in two dynamic buffers: - ** - ** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase - ** structure, followed by the array of Fts3PhraseToken - ** structures. This pass only populates the Fts3PhraseToken array. - ** - ** Buffer zTemp: Contains copies of all tokens. - ** - ** The second pass, in the block that begins "if( rc==SQLITE_DONE )" below, - ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase - ** structures. - */ - rc = sqlite3Fts3OpenTokenizer( - pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); - if( rc==SQLITE_OK ){ - int ii; - for(ii=0; rc==SQLITE_OK; ii++){ - const char *zByte; - int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0; - rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); - if( rc==SQLITE_OK ){ - Fts3PhraseToken *pToken; - - p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken)); - if( !p ) goto no_mem; - - zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte); - if( !zTemp ) goto no_mem; - - assert( nToken==ii ); - pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii]; - memset(pToken, 0, sizeof(Fts3PhraseToken)); - - memcpy(&zTemp[nTemp], zByte, nByte); - nTemp += nByte; - - pToken->n = nByte; - pToken->isPrefix = (iEndbFirst = (iBegin>0 && zInput[iBegin-1]=='^'); - nToken = ii+1; - } - } - - pModule->xClose(pCursor); - pCursor = 0; - } - - if( rc==SQLITE_DONE ){ - int jj; - char *zBuf = 0; - - p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp); - if( !p ) goto no_mem; - memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p); - p->eType = FTSQUERY_PHRASE; - p->pPhrase = (Fts3Phrase *)&p[1]; - p->pPhrase->iColumn = pParse->iDefaultCol; - p->pPhrase->nToken = nToken; - - zBuf = (char *)&p->pPhrase->aToken[nToken]; - if( zTemp ){ - memcpy(zBuf, zTemp, nTemp); - sqlite3_free(zTemp); - }else{ - assert( nTemp==0 ); - } - - for(jj=0; jjpPhrase->nToken; jj++){ - p->pPhrase->aToken[jj].z = zBuf; - zBuf += p->pPhrase->aToken[jj].n; - } - rc = SQLITE_OK; - } - - *ppExpr = p; - return rc; -no_mem: - - if( pCursor ){ - pModule->xClose(pCursor); - } - sqlite3_free(zTemp); - sqlite3_free(p); - *ppExpr = 0; - return SQLITE_NOMEM; -} - -/* -** Function getNextNode(), which is called by fts3ExprParse(), may itself -** call fts3ExprParse(). So this forward declaration is required. -*/ -static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *); - -/* -** The output variable *ppExpr is populated with an allocated Fts3Expr -** structure, or set to 0 if the end of the input buffer is reached. -** -** Returns an SQLite error code. SQLITE_OK if everything works, SQLITE_NOMEM -** if a malloc failure occurs, or SQLITE_ERROR if a parse error is encountered. -** If SQLITE_ERROR is returned, pContext is populated with an error message. -*/ -static int getNextNode( - ParseContext *pParse, /* fts3 query parse context */ - const char *z, int n, /* Input string */ - Fts3Expr **ppExpr, /* OUT: expression */ - int *pnConsumed /* OUT: Number of bytes consumed */ -){ - static const struct Fts3Keyword { - char *z; /* Keyword text */ - unsigned char n; /* Length of the keyword */ - unsigned char parenOnly; /* Only valid in paren mode */ - unsigned char eType; /* Keyword code */ - } aKeyword[] = { - { "OR" , 2, 0, FTSQUERY_OR }, - { "AND", 3, 1, FTSQUERY_AND }, - { "NOT", 3, 1, FTSQUERY_NOT }, - { "NEAR", 4, 0, FTSQUERY_NEAR } - }; - int ii; - int iCol; - int iColLen; - int rc; - Fts3Expr *pRet = 0; - - const char *zInput = z; - int nInput = n; - - pParse->isNot = 0; - - /* Skip over any whitespace before checking for a keyword, an open or - ** close bracket, or a quoted string. - */ - while( nInput>0 && fts3isspace(*zInput) ){ - nInput--; - zInput++; - } - if( nInput==0 ){ - return SQLITE_DONE; - } - - /* See if we are dealing with a keyword. */ - for(ii=0; ii<(int)(sizeof(aKeyword)/sizeof(struct Fts3Keyword)); ii++){ - const struct Fts3Keyword *pKey = &aKeyword[ii]; - - if( (pKey->parenOnly & ~sqlite3_fts3_enable_parentheses)!=0 ){ - continue; - } - - if( nInput>=pKey->n && 0==memcmp(zInput, pKey->z, pKey->n) ){ - int nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM; - int nKey = pKey->n; - char cNext; - - /* If this is a "NEAR" keyword, check for an explicit nearness. */ - if( pKey->eType==FTSQUERY_NEAR ){ - assert( nKey==4 ); - if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){ - nNear = 0; - for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){ - nNear = nNear * 10 + (zInput[nKey] - '0'); - } - } - } - - /* At this point this is probably a keyword. But for that to be true, - ** the next byte must contain either whitespace, an open or close - ** parenthesis, a quote character, or EOF. - */ - cNext = zInput[nKey]; - if( fts3isspace(cNext) - || cNext=='"' || cNext=='(' || cNext==')' || cNext==0 - ){ - pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr)); - if( !pRet ){ - return SQLITE_NOMEM; - } - pRet->eType = pKey->eType; - pRet->nNear = nNear; - *ppExpr = pRet; - *pnConsumed = (int)((zInput - z) + nKey); - return SQLITE_OK; - } - - /* Turns out that wasn't a keyword after all. This happens if the - ** user has supplied a token such as "ORacle". Continue. - */ - } - } - - /* Check for an open bracket. */ - if( sqlite3_fts3_enable_parentheses ){ - if( *zInput=='(' ){ - int nConsumed; - pParse->nNest++; - rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed); - if( rc==SQLITE_OK && !*ppExpr ){ - rc = SQLITE_DONE; - } - *pnConsumed = (int)((zInput - z) + 1 + nConsumed); - return rc; - } - - /* Check for a close bracket. */ - if( *zInput==')' ){ - pParse->nNest--; - *pnConsumed = (int)((zInput - z) + 1); - return SQLITE_DONE; - } - } - - /* See if we are dealing with a quoted phrase. If this is the case, then - ** search for the closing quote and pass the whole string to getNextString() - ** for processing. This is easy to do, as fts3 has no syntax for escaping - ** a quote character embedded in a string. - */ - if( *zInput=='"' ){ - for(ii=1; iiiDefaultCol; - iColLen = 0; - for(ii=0; iinCol; ii++){ - const char *zStr = pParse->azCol[ii]; - int nStr = (int)strlen(zStr); - if( nInput>nStr && zInput[nStr]==':' - && sqlite3_strnicmp(zStr, zInput, nStr)==0 - ){ - iCol = ii; - iColLen = (int)((zInput - z) + nStr + 1); - break; - } - } - rc = getNextToken(pParse, iCol, &z[iColLen], n-iColLen, ppExpr, pnConsumed); - *pnConsumed += iColLen; - return rc; -} - -/* -** The argument is an Fts3Expr structure for a binary operator (any type -** except an FTSQUERY_PHRASE). Return an integer value representing the -** precedence of the operator. Lower values have a higher precedence (i.e. -** group more tightly). For example, in the C language, the == operator -** groups more tightly than ||, and would therefore have a higher precedence. -** -** When using the new fts3 query syntax (when SQLITE_ENABLE_FTS3_PARENTHESIS -** is defined), the order of the operators in precedence from highest to -** lowest is: -** -** NEAR -** NOT -** AND (including implicit ANDs) -** OR -** -** Note that when using the old query syntax, the OR operator has a higher -** precedence than the AND operator. -*/ -static int opPrecedence(Fts3Expr *p){ - assert( p->eType!=FTSQUERY_PHRASE ); - if( sqlite3_fts3_enable_parentheses ){ - return p->eType; - }else if( p->eType==FTSQUERY_NEAR ){ - return 1; - }else if( p->eType==FTSQUERY_OR ){ - return 2; - } - assert( p->eType==FTSQUERY_AND ); - return 3; -} - -/* -** Argument ppHead contains a pointer to the current head of a query -** expression tree being parsed. pPrev is the expression node most recently -** inserted into the tree. This function adds pNew, which is always a binary -** operator node, into the expression tree based on the relative precedence -** of pNew and the existing nodes of the tree. This may result in the head -** of the tree changing, in which case *ppHead is set to the new root node. -*/ -static void insertBinaryOperator( - Fts3Expr **ppHead, /* Pointer to the root node of a tree */ - Fts3Expr *pPrev, /* Node most recently inserted into the tree */ - Fts3Expr *pNew /* New binary node to insert into expression tree */ -){ - Fts3Expr *pSplit = pPrev; - while( pSplit->pParent && opPrecedence(pSplit->pParent)<=opPrecedence(pNew) ){ - pSplit = pSplit->pParent; - } - - if( pSplit->pParent ){ - assert( pSplit->pParent->pRight==pSplit ); - pSplit->pParent->pRight = pNew; - pNew->pParent = pSplit->pParent; - }else{ - *ppHead = pNew; - } - pNew->pLeft = pSplit; - pSplit->pParent = pNew; -} - -/* -** Parse the fts3 query expression found in buffer z, length n. This function -** returns either when the end of the buffer is reached or an unmatched -** closing bracket - ')' - is encountered. -** -** If successful, SQLITE_OK is returned, *ppExpr is set to point to the -** parsed form of the expression and *pnConsumed is set to the number of -** bytes read from buffer z. Otherwise, *ppExpr is set to 0 and SQLITE_NOMEM -** (out of memory error) or SQLITE_ERROR (parse error) is returned. -*/ -static int fts3ExprParse( - ParseContext *pParse, /* fts3 query parse context */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr, /* OUT: Parsed query structure */ - int *pnConsumed /* OUT: Number of bytes consumed */ -){ - Fts3Expr *pRet = 0; - Fts3Expr *pPrev = 0; - Fts3Expr *pNotBranch = 0; /* Only used in legacy parse mode */ - int nIn = n; - const char *zIn = z; - int rc = SQLITE_OK; - int isRequirePhrase = 1; - - while( rc==SQLITE_OK ){ - Fts3Expr *p = 0; - int nByte = 0; - rc = getNextNode(pParse, zIn, nIn, &p, &nByte); - if( rc==SQLITE_OK ){ - int isPhrase; - - if( !sqlite3_fts3_enable_parentheses - && p->eType==FTSQUERY_PHRASE && pParse->isNot - ){ - /* Create an implicit NOT operator. */ - Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr)); - if( !pNot ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_NOMEM; - goto exprparse_out; - } - pNot->eType = FTSQUERY_NOT; - pNot->pRight = p; - p->pParent = pNot; - if( pNotBranch ){ - pNot->pLeft = pNotBranch; - pNotBranch->pParent = pNot; - } - pNotBranch = pNot; - p = pPrev; - }else{ - int eType = p->eType; - isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft); - - /* The isRequirePhrase variable is set to true if a phrase or - ** an expression contained in parenthesis is required. If a - ** binary operator (AND, OR, NOT or NEAR) is encounted when - ** isRequirePhrase is set, this is a syntax error. - */ - if( !isPhrase && isRequirePhrase ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_ERROR; - goto exprparse_out; - } - - if( isPhrase && !isRequirePhrase ){ - /* Insert an implicit AND operator. */ - Fts3Expr *pAnd; - assert( pRet && pPrev ); - pAnd = fts3MallocZero(sizeof(Fts3Expr)); - if( !pAnd ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_NOMEM; - goto exprparse_out; - } - pAnd->eType = FTSQUERY_AND; - insertBinaryOperator(&pRet, pPrev, pAnd); - pPrev = pAnd; - } - - /* This test catches attempts to make either operand of a NEAR - ** operator something other than a phrase. For example, either of - ** the following: - ** - ** (bracketed expression) NEAR phrase - ** phrase NEAR (bracketed expression) - ** - ** Return an error in either case. - */ - if( pPrev && ( - (eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE) - || (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR) - )){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_ERROR; - goto exprparse_out; - } - - if( isPhrase ){ - if( pRet ){ - assert( pPrev && pPrev->pLeft && pPrev->pRight==0 ); - pPrev->pRight = p; - p->pParent = pPrev; - }else{ - pRet = p; - } - }else{ - insertBinaryOperator(&pRet, pPrev, p); - } - isRequirePhrase = !isPhrase; - } - assert( nByte>0 ); - } - assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) ); - nIn -= nByte; - zIn += nByte; - pPrev = p; - } - - if( rc==SQLITE_DONE && pRet && isRequirePhrase ){ - rc = SQLITE_ERROR; - } - - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - if( !sqlite3_fts3_enable_parentheses && pNotBranch ){ - if( !pRet ){ - rc = SQLITE_ERROR; - }else{ - Fts3Expr *pIter = pNotBranch; - while( pIter->pLeft ){ - pIter = pIter->pLeft; - } - pIter->pLeft = pRet; - pRet->pParent = pIter; - pRet = pNotBranch; - } - } - } - *pnConsumed = n - nIn; - -exprparse_out: - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRet); - sqlite3Fts3ExprFree(pNotBranch); - pRet = 0; - } - *ppExpr = pRet; - return rc; -} - -/* -** Return SQLITE_ERROR if the maximum depth of the expression tree passed -** as the only argument is more than nMaxDepth. -*/ -static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){ - int rc = SQLITE_OK; - if( p ){ - if( nMaxDepth<0 ){ - rc = SQLITE_TOOBIG; - }else{ - rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1); - if( rc==SQLITE_OK ){ - rc = fts3ExprCheckDepth(p->pRight, nMaxDepth-1); - } - } - } - return rc; -} - -/* -** This function attempts to transform the expression tree at (*pp) to -** an equivalent but more balanced form. The tree is modified in place. -** If successful, SQLITE_OK is returned and (*pp) set to point to the -** new root expression node. -** -** nMaxDepth is the maximum allowable depth of the balanced sub-tree. -** -** Otherwise, if an error occurs, an SQLite error code is returned and -** expression (*pp) freed. -*/ -static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){ - int rc = SQLITE_OK; /* Return code */ - Fts3Expr *pRoot = *pp; /* Initial root node */ - Fts3Expr *pFree = 0; /* List of free nodes. Linked by pParent. */ - int eType = pRoot->eType; /* Type of node in this tree */ - - if( nMaxDepth==0 ){ - rc = SQLITE_ERROR; - } - - if( rc==SQLITE_OK && (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){ - Fts3Expr **apLeaf; - apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth); - if( 0==apLeaf ){ - rc = SQLITE_NOMEM; - }else{ - memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth); - } - - if( rc==SQLITE_OK ){ - int i; - Fts3Expr *p; - - /* Set $p to point to the left-most leaf in the tree of eType nodes. */ - for(p=pRoot; p->eType==eType; p=p->pLeft){ - assert( p->pParent==0 || p->pParent->pLeft==p ); - assert( p->pLeft && p->pRight ); - } - - /* This loop runs once for each leaf in the tree of eType nodes. */ - while( 1 ){ - int iLvl; - Fts3Expr *pParent = p->pParent; /* Current parent of p */ - - assert( pParent==0 || pParent->pLeft==p ); - p->pParent = 0; - if( pParent ){ - pParent->pLeft = 0; - }else{ - pRoot = 0; - } - rc = fts3ExprBalance(&p, nMaxDepth-1); - if( rc!=SQLITE_OK ) break; - - for(iLvl=0; p && iLvlpLeft = apLeaf[iLvl]; - pFree->pRight = p; - pFree->pLeft->pParent = pFree; - pFree->pRight->pParent = pFree; - - p = pFree; - pFree = pFree->pParent; - p->pParent = 0; - apLeaf[iLvl] = 0; - } - } - if( p ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_TOOBIG; - break; - } - - /* If that was the last leaf node, break out of the loop */ - if( pParent==0 ) break; - - /* Set $p to point to the next leaf in the tree of eType nodes */ - for(p=pParent->pRight; p->eType==eType; p=p->pLeft); - - /* Remove pParent from the original tree. */ - assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent ); - pParent->pRight->pParent = pParent->pParent; - if( pParent->pParent ){ - pParent->pParent->pLeft = pParent->pRight; - }else{ - assert( pParent==pRoot ); - pRoot = pParent->pRight; - } - - /* Link pParent into the free node list. It will be used as an - ** internal node of the new tree. */ - pParent->pParent = pFree; - pFree = pParent; - } - - if( rc==SQLITE_OK ){ - p = 0; - for(i=0; ipParent = 0; - }else{ - assert( pFree!=0 ); - pFree->pRight = p; - pFree->pLeft = apLeaf[i]; - pFree->pLeft->pParent = pFree; - pFree->pRight->pParent = pFree; - - p = pFree; - pFree = pFree->pParent; - p->pParent = 0; - } - } - } - pRoot = p; - }else{ - /* An error occurred. Delete the contents of the apLeaf[] array - ** and pFree list. Everything else is cleaned up by the call to - ** sqlite3Fts3ExprFree(pRoot) below. */ - Fts3Expr *pDel; - for(i=0; ipParent; - sqlite3_free(pDel); - } - } - - assert( pFree==0 ); - sqlite3_free( apLeaf ); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(pRoot); - pRoot = 0; - } - *pp = pRoot; - return rc; -} - -/* -** This function is similar to sqlite3Fts3ExprParse(), with the following -** differences: -** -** 1. It does not do expression rebalancing. -** 2. It does not check that the expression does not exceed the -** maximum allowable depth. -** 3. Even if it fails, *ppExpr may still be set to point to an -** expression tree. It should be deleted using sqlite3Fts3ExprFree() -** in this case. -*/ -static int fts3ExprParseUnbalanced( - sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ - int iLangid, /* Language id for tokenizer */ - char **azCol, /* Array of column names for fts3 table */ - int bFts4, /* True to allow FTS4-only syntax */ - int nCol, /* Number of entries in azCol[] */ - int iDefaultCol, /* Default column to query */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr /* OUT: Parsed query structure */ -){ - int nParsed; - int rc; - ParseContext sParse; - - memset(&sParse, 0, sizeof(ParseContext)); - sParse.pTokenizer = pTokenizer; - sParse.iLangid = iLangid; - sParse.azCol = (const char **)azCol; - sParse.nCol = nCol; - sParse.iDefaultCol = iDefaultCol; - sParse.bFts4 = bFts4; - if( z==0 ){ - *ppExpr = 0; - return SQLITE_OK; - } - if( n<0 ){ - n = (int)strlen(z); - } - rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); - assert( rc==SQLITE_OK || *ppExpr==0 ); - - /* Check for mismatched parenthesis */ - if( rc==SQLITE_OK && sParse.nNest ){ - rc = SQLITE_ERROR; - } - - return rc; -} - -/* -** Parameters z and n contain a pointer to and length of a buffer containing -** an fts3 query expression, respectively. This function attempts to parse the -** query expression and create a tree of Fts3Expr structures representing the -** parsed expression. If successful, *ppExpr is set to point to the head -** of the parsed expression tree and SQLITE_OK is returned. If an error -** occurs, either SQLITE_NOMEM (out-of-memory error) or SQLITE_ERROR (parse -** error) is returned and *ppExpr is set to 0. -** -** If parameter n is a negative number, then z is assumed to point to a -** nul-terminated string and the length is determined using strlen(). -** -** The first parameter, pTokenizer, is passed the fts3 tokenizer module to -** use to normalize query tokens while parsing the expression. The azCol[] -** array, which is assumed to contain nCol entries, should contain the names -** of each column in the target fts3 table, in order from left to right. -** Column names must be nul-terminated strings. -** -** The iDefaultCol parameter should be passed the index of the table column -** that appears on the left-hand-side of the MATCH operator (the default -** column to match against for tokens for which a column name is not explicitly -** specified as part of the query string), or -1 if tokens may by default -** match any table column. -*/ -SQLITE_PRIVATE int sqlite3Fts3ExprParse( - sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ - int iLangid, /* Language id for tokenizer */ - char **azCol, /* Array of column names for fts3 table */ - int bFts4, /* True to allow FTS4-only syntax */ - int nCol, /* Number of entries in azCol[] */ - int iDefaultCol, /* Default column to query */ - const char *z, int n, /* Text of MATCH query */ - Fts3Expr **ppExpr, /* OUT: Parsed query structure */ - char **pzErr /* OUT: Error message (sqlite3_malloc) */ -){ - static const int MAX_EXPR_DEPTH = 12; - int rc = fts3ExprParseUnbalanced( - pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr - ); - - /* Rebalance the expression. And check that its depth does not exceed - ** MAX_EXPR_DEPTH. */ - if( rc==SQLITE_OK && *ppExpr ){ - rc = fts3ExprBalance(ppExpr, MAX_EXPR_DEPTH); - if( rc==SQLITE_OK ){ - rc = fts3ExprCheckDepth(*ppExpr, MAX_EXPR_DEPTH); - } - } - - if( rc!=SQLITE_OK ){ - sqlite3Fts3ExprFree(*ppExpr); - *ppExpr = 0; - if( rc==SQLITE_TOOBIG ){ - *pzErr = sqlite3_mprintf( - "FTS expression tree is too large (maximum depth %d)", MAX_EXPR_DEPTH - ); - rc = SQLITE_ERROR; - }else if( rc==SQLITE_ERROR ){ - *pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z); - } - } - - return rc; -} - -/* -** Free a single node of an expression tree. -*/ -static void fts3FreeExprNode(Fts3Expr *p){ - assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 ); - sqlite3Fts3EvalPhraseCleanup(p->pPhrase); - sqlite3_free(p->aMI); - sqlite3_free(p); -} - -/* -** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse(). -** -** This function would be simpler if it recursively called itself. But -** that would mean passing a sufficiently large expression to ExprParse() -** could cause a stack overflow. -*/ -SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *pDel){ - Fts3Expr *p; - assert( pDel==0 || pDel->pParent==0 ); - for(p=pDel; p && (p->pLeft||p->pRight); p=(p->pLeft ? p->pLeft : p->pRight)){ - assert( p->pParent==0 || p==p->pParent->pRight || p==p->pParent->pLeft ); - } - while( p ){ - Fts3Expr *pParent = p->pParent; - fts3FreeExprNode(p); - if( pParent && p==pParent->pLeft && pParent->pRight ){ - p = pParent->pRight; - while( p && (p->pLeft || p->pRight) ){ - assert( p==p->pParent->pRight || p==p->pParent->pLeft ); - p = (p->pLeft ? p->pLeft : p->pRight); - } - }else{ - p = pParent; - } - } -} - -/**************************************************************************** -***************************************************************************** -** Everything after this point is just test code. -*/ - -#ifdef SQLITE_TEST - -/* #include */ - -/* -** Function to query the hash-table of tokenizers (see README.tokenizers). -*/ -static int queryTestTokenizer( - sqlite3 *db, - const char *zName, - const sqlite3_tokenizer_module **pp -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?)"; - - *pp = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ - memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); - } - } - - return sqlite3_finalize(pStmt); -} - -/* -** Return a pointer to a buffer containing a text representation of the -** expression passed as the first argument. The buffer is obtained from -** sqlite3_malloc(). It is the responsibility of the caller to use -** sqlite3_free() to release the memory. If an OOM condition is encountered, -** NULL is returned. -** -** If the second argument is not NULL, then its contents are prepended to -** the returned expression text and then freed using sqlite3_free(). -*/ -static char *exprToString(Fts3Expr *pExpr, char *zBuf){ - if( pExpr==0 ){ - return sqlite3_mprintf(""); - } - switch( pExpr->eType ){ - case FTSQUERY_PHRASE: { - Fts3Phrase *pPhrase = pExpr->pPhrase; - int i; - zBuf = sqlite3_mprintf( - "%zPHRASE %d 0", zBuf, pPhrase->iColumn); - for(i=0; zBuf && inToken; i++){ - zBuf = sqlite3_mprintf("%z %.*s%s", zBuf, - pPhrase->aToken[i].n, pPhrase->aToken[i].z, - (pPhrase->aToken[i].isPrefix?"+":"") - ); - } - return zBuf; - } - - case FTSQUERY_NEAR: - zBuf = sqlite3_mprintf("%zNEAR/%d ", zBuf, pExpr->nNear); - break; - case FTSQUERY_NOT: - zBuf = sqlite3_mprintf("%zNOT ", zBuf); - break; - case FTSQUERY_AND: - zBuf = sqlite3_mprintf("%zAND ", zBuf); - break; - case FTSQUERY_OR: - zBuf = sqlite3_mprintf("%zOR ", zBuf); - break; - } - - if( zBuf ) zBuf = sqlite3_mprintf("%z{", zBuf); - if( zBuf ) zBuf = exprToString(pExpr->pLeft, zBuf); - if( zBuf ) zBuf = sqlite3_mprintf("%z} {", zBuf); - - if( zBuf ) zBuf = exprToString(pExpr->pRight, zBuf); - if( zBuf ) zBuf = sqlite3_mprintf("%z}", zBuf); - - return zBuf; -} - -/* -** This is the implementation of a scalar SQL function used to test the -** expression parser. It should be called as follows: -** -** fts3_exprtest(, , , ...); -** -** The first argument, , is the name of the fts3 tokenizer used -** to parse the query expression (see README.tokenizers). The second argument -** is the query expression to parse. Each subsequent argument is the name -** of a column of the fts3 table that the query expression may refer to. -** For example: -** -** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2'); -*/ -static void fts3ExprTest( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - sqlite3_tokenizer_module const *pModule = 0; - sqlite3_tokenizer *pTokenizer = 0; - int rc; - char **azCol = 0; - const char *zExpr; - int nExpr; - int nCol; - int ii; - Fts3Expr *pExpr; - char *zBuf = 0; - sqlite3 *db = sqlite3_context_db_handle(context); - - if( argc<3 ){ - sqlite3_result_error(context, - "Usage: fts3_exprtest(tokenizer, expr, col1, ...", -1 - ); - return; - } - - rc = queryTestTokenizer(db, - (const char *)sqlite3_value_text(argv[0]), &pModule); - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - }else if( !pModule ){ - sqlite3_result_error(context, "No such tokenizer module", -1); - goto exprtest_out; - } - - rc = pModule->xCreate(0, 0, &pTokenizer); - assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); - if( rc==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - } - pTokenizer->pModule = pModule; - - zExpr = (const char *)sqlite3_value_text(argv[1]); - nExpr = sqlite3_value_bytes(argv[1]); - nCol = argc-2; - azCol = (char **)sqlite3_malloc(nCol*sizeof(char *)); - if( !azCol ){ - sqlite3_result_error_nomem(context); - goto exprtest_out; - } - for(ii=0; iixDestroy(pTokenizer); - } - sqlite3_free(azCol); -} - -/* -** Register the query expression parser test function fts3_exprtest() -** with database connection db. -*/ -SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ - int rc = sqlite3_create_function( - db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0 - ); - if( rc==SQLITE_OK ){ - rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", - -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0 - ); - } - return rc; -} - -#endif -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_expr.c *******************************************/ -/************** Begin file fts3_hash.c ***************************************/ -/* -** 2001 September 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This is the implementation of generic hash-tables used in SQLite. -** We've modified it slightly to serve as a standalone hash table -** implementation for the full-text indexing module. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ - - -/* -** Malloc and Free functions -*/ -static void *fts3HashMalloc(int n){ - void *p = sqlite3_malloc(n); - if( p ){ - memset(p, 0, n); - } - return p; -} -static void fts3HashFree(void *p){ - sqlite3_free(p); -} - -/* Turn bulk memory into a hash table object by initializing the -** fields of the Hash structure. -** -** "pNew" is a pointer to the hash table that is to be initialized. -** keyClass is one of the constants -** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass -** determines what kind of key the hash table will use. "copyKey" is -** true if the hash table should make its own private copy of keys and -** false if it should just use the supplied pointer. -*/ -SQLITE_PRIVATE void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){ - assert( pNew!=0 ); - assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY ); - pNew->keyClass = keyClass; - pNew->copyKey = copyKey; - pNew->first = 0; - pNew->count = 0; - pNew->htsize = 0; - pNew->ht = 0; -} - -/* Remove all entries from a hash table. Reclaim all memory. -** Call this routine to delete a hash table or to reset a hash table -** to the empty state. -*/ -SQLITE_PRIVATE void sqlite3Fts3HashClear(Fts3Hash *pH){ - Fts3HashElem *elem; /* For looping over all elements of the table */ - - assert( pH!=0 ); - elem = pH->first; - pH->first = 0; - fts3HashFree(pH->ht); - pH->ht = 0; - pH->htsize = 0; - while( elem ){ - Fts3HashElem *next_elem = elem->next; - if( pH->copyKey && elem->pKey ){ - fts3HashFree(elem->pKey); - } - fts3HashFree(elem); - elem = next_elem; - } - pH->count = 0; -} - -/* -** Hash and comparison functions when the mode is FTS3_HASH_STRING -*/ -static int fts3StrHash(const void *pKey, int nKey){ - const char *z = (const char *)pKey; - int h = 0; - if( nKey<=0 ) nKey = (int) strlen(z); - while( nKey > 0 ){ - h = (h<<3) ^ h ^ *z++; - nKey--; - } - return h & 0x7fffffff; -} -static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return strncmp((const char*)pKey1,(const char*)pKey2,n1); -} - -/* -** Hash and comparison functions when the mode is FTS3_HASH_BINARY -*/ -static int fts3BinHash(const void *pKey, int nKey){ - int h = 0; - const char *z = (const char *)pKey; - while( nKey-- > 0 ){ - h = (h<<3) ^ h ^ *(z++); - } - return h & 0x7fffffff; -} -static int fts3BinCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return 1; - return memcmp(pKey1,pKey2,n1); -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** The C syntax in this function definition may be unfamilar to some -** programmers, so we provide the following additional explanation: -** -** The name of the function is "ftsHashFunction". The function takes a -** single parameter "keyClass". The return value of ftsHashFunction() -** is a pointer to another function. Specifically, the return value -** of ftsHashFunction() is a pointer to a function that takes two parameters -** with types "const void*" and "int" and returns an "int". -*/ -static int (*ftsHashFunction(int keyClass))(const void*,int){ - if( keyClass==FTS3_HASH_STRING ){ - return &fts3StrHash; - }else{ - assert( keyClass==FTS3_HASH_BINARY ); - return &fts3BinHash; - } -} - -/* -** Return a pointer to the appropriate hash function given the key class. -** -** For help in interpreted the obscure C code in the function definition, -** see the header comment on the previous function. -*/ -static int (*ftsCompareFunction(int keyClass))(const void*,int,const void*,int){ - if( keyClass==FTS3_HASH_STRING ){ - return &fts3StrCompare; - }else{ - assert( keyClass==FTS3_HASH_BINARY ); - return &fts3BinCompare; - } -} - -/* Link an element into the hash table -*/ -static void fts3HashInsertElement( - Fts3Hash *pH, /* The complete hash table */ - struct _fts3ht *pEntry, /* The entry into which pNew is inserted */ - Fts3HashElem *pNew /* The element to be inserted */ -){ - Fts3HashElem *pHead; /* First element already in pEntry */ - pHead = pEntry->chain; - if( pHead ){ - pNew->next = pHead; - pNew->prev = pHead->prev; - if( pHead->prev ){ pHead->prev->next = pNew; } - else { pH->first = pNew; } - pHead->prev = pNew; - }else{ - pNew->next = pH->first; - if( pH->first ){ pH->first->prev = pNew; } - pNew->prev = 0; - pH->first = pNew; - } - pEntry->count++; - pEntry->chain = pNew; -} - - -/* Resize the hash table so that it cantains "new_size" buckets. -** "new_size" must be a power of 2. The hash table might fail -** to resize if sqliteMalloc() fails. -** -** Return non-zero if a memory allocation error occurs. -*/ -static int fts3Rehash(Fts3Hash *pH, int new_size){ - struct _fts3ht *new_ht; /* The new hash table */ - Fts3HashElem *elem, *next_elem; /* For looping over existing elements */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( (new_size & (new_size-1))==0 ); - new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) ); - if( new_ht==0 ) return 1; - fts3HashFree(pH->ht); - pH->ht = new_ht; - pH->htsize = new_size; - xHash = ftsHashFunction(pH->keyClass); - for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); - next_elem = elem->next; - fts3HashInsertElement(pH, &new_ht[h], elem); - } - return 0; -} - -/* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key has -** already been computed and is passed as the 4th parameter. -*/ -static Fts3HashElem *fts3FindElementByHash( - const Fts3Hash *pH, /* The pH to be searched */ - const void *pKey, /* The key we are searching for */ - int nKey, - int h /* The hash for this key. */ -){ - Fts3HashElem *elem; /* Used to loop thru the element list */ - int count; /* Number of elements left to test */ - int (*xCompare)(const void*,int,const void*,int); /* comparison function */ - - if( pH->ht ){ - struct _fts3ht *pEntry = &pH->ht[h]; - elem = pEntry->chain; - count = pEntry->count; - xCompare = ftsCompareFunction(pH->keyClass); - while( count-- && elem ){ - if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ - return elem; - } - elem = elem->next; - } - } - return 0; -} - -/* Remove a single entry from the hash table given a pointer to that -** element and a hash on the element's key. -*/ -static void fts3RemoveElementByHash( - Fts3Hash *pH, /* The pH containing "elem" */ - Fts3HashElem* elem, /* The element to be removed from the pH */ - int h /* Hash value for the element */ -){ - struct _fts3ht *pEntry; - if( elem->prev ){ - elem->prev->next = elem->next; - }else{ - pH->first = elem->next; - } - if( elem->next ){ - elem->next->prev = elem->prev; - } - pEntry = &pH->ht[h]; - if( pEntry->chain==elem ){ - pEntry->chain = elem->next; - } - pEntry->count--; - if( pEntry->count<=0 ){ - pEntry->chain = 0; - } - if( pH->copyKey && elem->pKey ){ - fts3HashFree(elem->pKey); - } - fts3HashFree( elem ); - pH->count--; - if( pH->count<=0 ){ - assert( pH->first==0 ); - assert( pH->count==0 ); - fts3HashClear(pH); - } -} - -SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem( - const Fts3Hash *pH, - const void *pKey, - int nKey -){ - int h; /* A hash on key */ - int (*xHash)(const void*,int); /* The hash function */ - - if( pH==0 || pH->ht==0 ) return 0; - xHash = ftsHashFunction(pH->keyClass); - assert( xHash!=0 ); - h = (*xHash)(pKey,nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1)); -} - -/* -** Attempt to locate an element of the hash table pH with a key -** that matches pKey,nKey. Return the data for this element if it is -** found, or NULL if there is no match. -*/ -SQLITE_PRIVATE void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){ - Fts3HashElem *pElem; /* The element that matches key (if any) */ - - pElem = sqlite3Fts3HashFindElem(pH, pKey, nKey); - return pElem ? pElem->data : 0; -} - -/* Insert an element into the hash table pH. The key is pKey,nKey -** and the data is "data". -** -** If no element exists with a matching key, then a new -** element is created. A copy of the key is made if the copyKey -** flag is set. NULL is returned. -** -** If another element already exists with the same key, then the -** new data replaces the old data and the old data is returned. -** The key is not copied in this instance. If a malloc fails, then -** the new data is returned and the hash table is unchanged. -** -** If the "data" parameter to this function is NULL, then the -** element corresponding to "key" is removed from the hash table. -*/ -SQLITE_PRIVATE void *sqlite3Fts3HashInsert( - Fts3Hash *pH, /* The hash table to insert into */ - const void *pKey, /* The key */ - int nKey, /* Number of bytes in the key */ - void *data /* The data */ -){ - int hraw; /* Raw hash value of the key */ - int h; /* the hash of the key modulo hash table size */ - Fts3HashElem *elem; /* Used to loop thru the element list */ - Fts3HashElem *new_elem; /* New element added to the pH */ - int (*xHash)(const void*,int); /* The hash function */ - - assert( pH!=0 ); - xHash = ftsHashFunction(pH->keyClass); - assert( xHash!=0 ); - hraw = (*xHash)(pKey, nKey); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - elem = fts3FindElementByHash(pH,pKey,nKey,h); - if( elem ){ - void *old_data = elem->data; - if( data==0 ){ - fts3RemoveElementByHash(pH,elem,h); - }else{ - elem->data = data; - } - return old_data; - } - if( data==0 ) return 0; - if( (pH->htsize==0 && fts3Rehash(pH,8)) - || (pH->count>=pH->htsize && fts3Rehash(pH, pH->htsize*2)) - ){ - pH->count = 0; - return data; - } - assert( pH->htsize>0 ); - new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) ); - if( new_elem==0 ) return data; - if( pH->copyKey && pKey!=0 ){ - new_elem->pKey = fts3HashMalloc( nKey ); - if( new_elem->pKey==0 ){ - fts3HashFree(new_elem); - return data; - } - memcpy((void*)new_elem->pKey, pKey, nKey); - }else{ - new_elem->pKey = (void*)pKey; - } - new_elem->nKey = nKey; - pH->count++; - assert( pH->htsize>0 ); - assert( (pH->htsize & (pH->htsize-1))==0 ); - h = hraw & (pH->htsize-1); - fts3HashInsertElement(pH, &pH->ht[h], new_elem); - new_elem->data = data; - return 0; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_hash.c *******************************************/ -/************** Begin file fts3_porter.c *************************************/ -/* -** 2006 September 30 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Implementation of the full-text-search tokenizer that implements -** a Porter stemmer. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ -/* #include */ - - -/* -** Class derived from sqlite3_tokenizer -*/ -typedef struct porter_tokenizer { - sqlite3_tokenizer base; /* Base class */ -} porter_tokenizer; - -/* -** Class derived from sqlite3_tokenizer_cursor -*/ -typedef struct porter_tokenizer_cursor { - sqlite3_tokenizer_cursor base; - const char *zInput; /* input we are tokenizing */ - int nInput; /* size of the input */ - int iOffset; /* current position in zInput */ - int iToken; /* index of next token to be returned */ - char *zToken; /* storage for current token */ - int nAllocated; /* space allocated to zToken buffer */ -} porter_tokenizer_cursor; - - -/* -** Create a new tokenizer instance. -*/ -static int porterCreate( - int argc, const char * const *argv, - sqlite3_tokenizer **ppTokenizer -){ - porter_tokenizer *t; - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - - t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t)); - if( t==NULL ) return SQLITE_NOMEM; - memset(t, 0, sizeof(*t)); - *ppTokenizer = &t->base; - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int porterDestroy(sqlite3_tokenizer *pTokenizer){ - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is zInput[0..nInput-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int porterOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *zInput, int nInput, /* String to be tokenized */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - porter_tokenizer_cursor *c; - - UNUSED_PARAMETER(pTokenizer); - - c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); - if( c==NULL ) return SQLITE_NOMEM; - - c->zInput = zInput; - if( zInput==0 ){ - c->nInput = 0; - }else if( nInput<0 ){ - c->nInput = (int)strlen(zInput); - }else{ - c->nInput = nInput; - } - c->iOffset = 0; /* start tokenizing at the beginning */ - c->iToken = 0; - c->zToken = NULL; /* no space allocated, yet. */ - c->nAllocated = 0; - - *ppCursor = &c->base; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** porterOpen() above. -*/ -static int porterClose(sqlite3_tokenizer_cursor *pCursor){ - porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; - sqlite3_free(c->zToken); - sqlite3_free(c); - return SQLITE_OK; -} -/* -** Vowel or consonant -*/ -static const char cType[] = { - 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 2, 1 -}; - -/* -** isConsonant() and isVowel() determine if their first character in -** the string they point to is a consonant or a vowel, according -** to Porter ruls. -** -** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'. -** 'Y' is a consonant unless it follows another consonant, -** in which case it is a vowel. -** -** In these routine, the letters are in reverse order. So the 'y' rule -** is that 'y' is a consonant unless it is followed by another -** consonent. -*/ -static int isVowel(const char*); -static int isConsonant(const char *z){ - int j; - char x = *z; - if( x==0 ) return 0; - assert( x>='a' && x<='z' ); - j = cType[x-'a']; - if( j<2 ) return j; - return z[1]==0 || isVowel(z + 1); -} -static int isVowel(const char *z){ - int j; - char x = *z; - if( x==0 ) return 0; - assert( x>='a' && x<='z' ); - j = cType[x-'a']; - if( j<2 ) return 1-j; - return isConsonant(z + 1); -} - -/* -** Let any sequence of one or more vowels be represented by V and let -** C be sequence of one or more consonants. Then every word can be -** represented as: -** -** [C] (VC){m} [V] -** -** In prose: A word is an optional consonant followed by zero or -** vowel-consonant pairs followed by an optional vowel. "m" is the -** number of vowel consonant pairs. This routine computes the value -** of m for the first i bytes of a word. -** -** Return true if the m-value for z is 1 or more. In other words, -** return true if z contains at least one vowel that is followed -** by a consonant. -** -** In this routine z[] is in reverse order. So we are really looking -** for an instance of of a consonant followed by a vowel. -*/ -static int m_gt_0(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* Like mgt0 above except we are looking for a value of m which is -** exactly 1 -*/ -static int m_eq_1(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - if( *z==0 ) return 0; - while( isVowel(z) ){ z++; } - if( *z==0 ) return 1; - while( isConsonant(z) ){ z++; } - return *z==0; -} - -/* Like mgt0 above except we are looking for a value of m>1 instead -** or m>0 -*/ -static int m_gt_1(const char *z){ - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - if( *z==0 ) return 0; - while( isVowel(z) ){ z++; } - if( *z==0 ) return 0; - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* -** Return TRUE if there is a vowel anywhere within z[0..n-1] -*/ -static int hasVowel(const char *z){ - while( isConsonant(z) ){ z++; } - return *z!=0; -} - -/* -** Return TRUE if the word ends in a double consonant. -** -** The text is reversed here. So we are really looking at -** the first two characters of z[]. -*/ -static int doubleConsonant(const char *z){ - return isConsonant(z) && z[0]==z[1]; -} - -/* -** Return TRUE if the word ends with three letters which -** are consonant-vowel-consonent and where the final consonant -** is not 'w', 'x', or 'y'. -** -** The word is reversed here. So we are really checking the -** first three letters and the first one cannot be in [wxy]. -*/ -static int star_oh(const char *z){ - return - isConsonant(z) && - z[0]!='w' && z[0]!='x' && z[0]!='y' && - isVowel(z+1) && - isConsonant(z+2); -} - -/* -** If the word ends with zFrom and xCond() is true for the stem -** of the word that preceeds the zFrom ending, then change the -** ending to zTo. -** -** The input word *pz and zFrom are both in reverse order. zTo -** is in normal order. -** -** Return TRUE if zFrom matches. Return FALSE if zFrom does not -** match. Not that TRUE is returned even if xCond() fails and -** no substitution occurs. -*/ -static int stem( - char **pz, /* The word being stemmed (Reversed) */ - const char *zFrom, /* If the ending matches this... (Reversed) */ - const char *zTo, /* ... change the ending to this (not reversed) */ - int (*xCond)(const char*) /* Condition that must be true */ -){ - char *z = *pz; - while( *zFrom && *zFrom==*z ){ z++; zFrom++; } - if( *zFrom!=0 ) return 0; - if( xCond && !xCond(z) ) return 1; - while( *zTo ){ - *(--z) = *(zTo++); - } - *pz = z; - return 1; -} - -/* -** This is the fallback stemmer used when the porter stemmer is -** inappropriate. The input word is copied into the output with -** US-ASCII case folding. If the input word is too long (more -** than 20 bytes if it contains no digits or more than 6 bytes if -** it contains digits) then word is truncated to 20 or 6 bytes -** by taking 10 or 3 bytes from the beginning and end. -*/ -static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ - int i, mx, j; - int hasDigit = 0; - for(i=0; i='A' && c<='Z' ){ - zOut[i] = c - 'A' + 'a'; - }else{ - if( c>='0' && c<='9' ) hasDigit = 1; - zOut[i] = c; - } - } - mx = hasDigit ? 3 : 10; - if( nIn>mx*2 ){ - for(j=mx, i=nIn-mx; i=(int)sizeof(zReverse)-7 ){ - /* The word is too big or too small for the porter stemmer. - ** Fallback to the copy stemmer */ - copy_stemmer(zIn, nIn, zOut, pnOut); - return; - } - for(i=0, j=sizeof(zReverse)-6; i='A' && c<='Z' ){ - zReverse[j] = c + 'a' - 'A'; - }else if( c>='a' && c<='z' ){ - zReverse[j] = c; - }else{ - /* The use of a character not in [a-zA-Z] means that we fallback - ** to the copy stemmer */ - copy_stemmer(zIn, nIn, zOut, pnOut); - return; - } - } - memset(&zReverse[sizeof(zReverse)-5], 0, 5); - z = &zReverse[j+1]; - - - /* Step 1a */ - if( z[0]=='s' ){ - if( - !stem(&z, "sess", "ss", 0) && - !stem(&z, "sei", "i", 0) && - !stem(&z, "ss", "ss", 0) - ){ - z++; - } - } - - /* Step 1b */ - z2 = z; - if( stem(&z, "dee", "ee", m_gt_0) ){ - /* Do nothing. The work was all in the test */ - }else if( - (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel)) - && z!=z2 - ){ - if( stem(&z, "ta", "ate", 0) || - stem(&z, "lb", "ble", 0) || - stem(&z, "zi", "ize", 0) ){ - /* Do nothing. The work was all in the test */ - }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){ - z++; - }else if( m_eq_1(z) && star_oh(z) ){ - *(--z) = 'e'; - } - } - - /* Step 1c */ - if( z[0]=='y' && hasVowel(z+1) ){ - z[0] = 'i'; - } - - /* Step 2 */ - switch( z[1] ){ - case 'a': - stem(&z, "lanoita", "ate", m_gt_0) || - stem(&z, "lanoit", "tion", m_gt_0); - break; - case 'c': - stem(&z, "icne", "ence", m_gt_0) || - stem(&z, "icna", "ance", m_gt_0); - break; - case 'e': - stem(&z, "rezi", "ize", m_gt_0); - break; - case 'g': - stem(&z, "igol", "log", m_gt_0); - break; - case 'l': - stem(&z, "ilb", "ble", m_gt_0) || - stem(&z, "illa", "al", m_gt_0) || - stem(&z, "iltne", "ent", m_gt_0) || - stem(&z, "ile", "e", m_gt_0) || - stem(&z, "ilsuo", "ous", m_gt_0); - break; - case 'o': - stem(&z, "noitazi", "ize", m_gt_0) || - stem(&z, "noita", "ate", m_gt_0) || - stem(&z, "rota", "ate", m_gt_0); - break; - case 's': - stem(&z, "msila", "al", m_gt_0) || - stem(&z, "ssenevi", "ive", m_gt_0) || - stem(&z, "ssenluf", "ful", m_gt_0) || - stem(&z, "ssensuo", "ous", m_gt_0); - break; - case 't': - stem(&z, "itila", "al", m_gt_0) || - stem(&z, "itivi", "ive", m_gt_0) || - stem(&z, "itilib", "ble", m_gt_0); - break; - } - - /* Step 3 */ - switch( z[0] ){ - case 'e': - stem(&z, "etaci", "ic", m_gt_0) || - stem(&z, "evita", "", m_gt_0) || - stem(&z, "ezila", "al", m_gt_0); - break; - case 'i': - stem(&z, "itici", "ic", m_gt_0); - break; - case 'l': - stem(&z, "laci", "ic", m_gt_0) || - stem(&z, "luf", "", m_gt_0); - break; - case 's': - stem(&z, "ssen", "", m_gt_0); - break; - } - - /* Step 4 */ - switch( z[1] ){ - case 'a': - if( z[0]=='l' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'c': - if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){ - z += 4; - } - break; - case 'e': - if( z[0]=='r' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'i': - if( z[0]=='c' && m_gt_1(z+2) ){ - z += 2; - } - break; - case 'l': - if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){ - z += 4; - } - break; - case 'n': - if( z[0]=='t' ){ - if( z[2]=='a' ){ - if( m_gt_1(z+3) ){ - z += 3; - } - }else if( z[2]=='e' ){ - stem(&z, "tneme", "", m_gt_1) || - stem(&z, "tnem", "", m_gt_1) || - stem(&z, "tne", "", m_gt_1); - } - } - break; - case 'o': - if( z[0]=='u' ){ - if( m_gt_1(z+2) ){ - z += 2; - } - }else if( z[3]=='s' || z[3]=='t' ){ - stem(&z, "noi", "", m_gt_1); - } - break; - case 's': - if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){ - z += 3; - } - break; - case 't': - stem(&z, "eta", "", m_gt_1) || - stem(&z, "iti", "", m_gt_1); - break; - case 'u': - if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){ - z += 3; - } - break; - case 'v': - case 'z': - if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){ - z += 3; - } - break; - } - - /* Step 5a */ - if( z[0]=='e' ){ - if( m_gt_1(z+1) ){ - z++; - }else if( m_eq_1(z+1) && !star_oh(z+1) ){ - z++; - } - } - - /* Step 5b */ - if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){ - z++; - } - - /* z[] is now the stemmed word in reverse order. Flip it back - ** around into forward order and return. - */ - *pnOut = i = (int)strlen(z); - zOut[i] = 0; - while( *z ){ - zOut[--i] = *(z++); - } -} - -/* -** Characters that can be part of a token. We assume any character -** whose value is greater than 0x80 (any UTF character) can be -** part of a token. In other words, delimiters all must have -** values of 0x7f or lower. -*/ -static const char porterIdChar[] = { -/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ -}; -#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30])) - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to porterOpen(). -*/ -static int porterNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */ - const char **pzToken, /* OUT: *pzToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; - const char *z = c->zInput; - - while( c->iOffsetnInput ){ - int iStartOffset, ch; - - /* Scan past delimiter characters */ - while( c->iOffsetnInput && isDelim(z[c->iOffset]) ){ - c->iOffset++; - } - - /* Count non-delimiter characters. */ - iStartOffset = c->iOffset; - while( c->iOffsetnInput && !isDelim(z[c->iOffset]) ){ - c->iOffset++; - } - - if( c->iOffset>iStartOffset ){ - int n = c->iOffset-iStartOffset; - if( n>c->nAllocated ){ - char *pNew; - c->nAllocated = n+20; - pNew = sqlite3_realloc(c->zToken, c->nAllocated); - if( !pNew ) return SQLITE_NOMEM; - c->zToken = pNew; - } - porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); - *pzToken = c->zToken; - *piStartOffset = iStartOffset; - *piEndOffset = c->iOffset; - *piPosition = c->iToken++; - return SQLITE_OK; - } - } - return SQLITE_DONE; -} - -/* -** The set of routines that implement the porter-stemmer tokenizer -*/ -static const sqlite3_tokenizer_module porterTokenizerModule = { - 0, - porterCreate, - porterDestroy, - porterOpen, - porterClose, - porterNext, - 0 -}; - -/* -** Allocate a new porter tokenizer. Return a pointer to the new -** tokenizer in *ppModule -*/ -SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &porterTokenizerModule; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_porter.c *****************************************/ -/************** Begin file fts3_tokenizer.c **********************************/ -/* -** 2007 June 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This is part of an SQLite module implementing full-text search. -** This particular file implements the generic tokenizer interface. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ - -/* -** Implementation of the SQL scalar function for accessing the underlying -** hash table. This function may be called as follows: -** -** SELECT (); -** SELECT (, ); -** -** where is the name passed as the second argument -** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer'). -** -** If the argument is specified, it must be a blob value -** containing a pointer to be stored as the hash data corresponding -** to the string . If is not specified, then -** the string must already exist in the has table. Otherwise, -** an error is returned. -** -** Whether or not the argument is specified, the value returned -** is a blob containing the pointer stored as the hash data corresponding -** to string (after the hash-table is updated, if applicable). -*/ -static void scalarFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Fts3Hash *pHash; - void *pPtr = 0; - const unsigned char *zName; - int nName; - - assert( argc==1 || argc==2 ); - - pHash = (Fts3Hash *)sqlite3_user_data(context); - - zName = sqlite3_value_text(argv[0]); - nName = sqlite3_value_bytes(argv[0])+1; - - if( argc==2 ){ - void *pOld; - int n = sqlite3_value_bytes(argv[1]); - if( n!=sizeof(pPtr) ){ - sqlite3_result_error(context, "argument type mismatch", -1); - return; - } - pPtr = *(void **)sqlite3_value_blob(argv[1]); - pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); - if( pOld==pPtr ){ - sqlite3_result_error(context, "out of memory", -1); - return; - } - }else{ - pPtr = sqlite3Fts3HashFind(pHash, zName, nName); - if( !pPtr ){ - char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - } - - sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); -} - -SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char c){ - static const char isFtsIdChar[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ - }; - return (c&0x80 || isFtsIdChar[(int)(c)]); -} - -SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *zStr, int *pn){ - const char *z1; - const char *z2 = 0; - - /* Find the start of the next token. */ - z1 = zStr; - while( z2==0 ){ - char c = *z1; - switch( c ){ - case '\0': return 0; /* No more tokens here */ - case '\'': - case '"': - case '`': { - z2 = z1; - while( *++z2 && (*z2!=c || *++z2==c) ); - break; - } - case '[': - z2 = &z1[1]; - while( *z2 && z2[0]!=']' ) z2++; - if( *z2 ) z2++; - break; - - default: - if( sqlite3Fts3IsIdChar(*z1) ){ - z2 = &z1[1]; - while( sqlite3Fts3IsIdChar(*z2) ) z2++; - }else{ - z1++; - } - } - } - - *pn = (int)(z2-z1); - return z1; -} - -SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( - Fts3Hash *pHash, /* Tokenizer hash table */ - const char *zArg, /* Tokenizer name */ - sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */ - char **pzErr /* OUT: Set to malloced error message */ -){ - int rc; - char *z = (char *)zArg; - int n = 0; - char *zCopy; - char *zEnd; /* Pointer to nul-term of zCopy */ - sqlite3_tokenizer_module *m; - - zCopy = sqlite3_mprintf("%s", zArg); - if( !zCopy ) return SQLITE_NOMEM; - zEnd = &zCopy[strlen(zCopy)]; - - z = (char *)sqlite3Fts3NextToken(zCopy, &n); - z[n] = '\0'; - sqlite3Fts3Dequote(z); - - m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1); - if( !m ){ - *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); - rc = SQLITE_ERROR; - }else{ - char const **aArg = 0; - int iArg = 0; - z = &z[n+1]; - while( zxCreate(iArg, aArg, ppTok); - assert( rc!=SQLITE_OK || *ppTok ); - if( rc!=SQLITE_OK ){ - *pzErr = sqlite3_mprintf("unknown tokenizer"); - }else{ - (*ppTok)->pModule = m; - } - sqlite3_free((void *)aArg); - } - - sqlite3_free(zCopy); - return rc; -} - - -#ifdef SQLITE_TEST - -/* #include */ -/* #include */ - -/* -** Implementation of a special SQL scalar function for testing tokenizers -** designed to be used in concert with the Tcl testing framework. This -** function must be called with two or more arguments: -** -** SELECT (, ..., ); -** -** where is the name passed as the second argument -** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer') -** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test'). -** -** The return value is a string that may be interpreted as a Tcl -** list. For each token in the , three elements are -** added to the returned list. The first is the token position, the -** second is the token text (folded, stemmed, etc.) and the third is the -** substring of associated with the token. For example, -** using the built-in "simple" tokenizer: -** -** SELECT fts_tokenizer_test('simple', 'I don't see how'); -** -** will return the string: -** -** "{0 i I 1 dont don't 2 see see 3 how how}" -** -*/ -static void testFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - Fts3Hash *pHash; - sqlite3_tokenizer_module *p; - sqlite3_tokenizer *pTokenizer = 0; - sqlite3_tokenizer_cursor *pCsr = 0; - - const char *zErr = 0; - - const char *zName; - int nName; - const char *zInput; - int nInput; - - const char *azArg[64]; - - const char *zToken; - int nToken = 0; - int iStart = 0; - int iEnd = 0; - int iPos = 0; - int i; - - Tcl_Obj *pRet; - - if( argc<2 ){ - sqlite3_result_error(context, "insufficient arguments", -1); - return; - } - - nName = sqlite3_value_bytes(argv[0]); - zName = (const char *)sqlite3_value_text(argv[0]); - nInput = sqlite3_value_bytes(argv[argc-1]); - zInput = (const char *)sqlite3_value_text(argv[argc-1]); - - pHash = (Fts3Hash *)sqlite3_user_data(context); - p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); - - if( !p ){ - char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - - pRet = Tcl_NewObj(); - Tcl_IncrRefCount(pRet); - - for(i=1; ixCreate(argc-2, azArg, &pTokenizer) ){ - zErr = "error in xCreate()"; - goto finish; - } - pTokenizer->pModule = p; - if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){ - zErr = "error in xOpen()"; - goto finish; - } - - while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ - Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); - Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); - zToken = &zInput[iStart]; - nToken = iEnd-iStart; - Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); - } - - if( SQLITE_OK!=p->xClose(pCsr) ){ - zErr = "error in xClose()"; - goto finish; - } - if( SQLITE_OK!=p->xDestroy(pTokenizer) ){ - zErr = "error in xDestroy()"; - goto finish; - } - -finish: - if( zErr ){ - sqlite3_result_error(context, zErr, -1); - }else{ - sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); - } - Tcl_DecrRefCount(pRet); -} - -static -int registerTokenizer( - sqlite3 *db, - char *zName, - const sqlite3_tokenizer_module *p -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?, ?)"; - - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); - sqlite3_step(pStmt); - - return sqlite3_finalize(pStmt); -} - -static -int queryTokenizer( - sqlite3 *db, - char *zName, - const sqlite3_tokenizer_module **pp -){ - int rc; - sqlite3_stmt *pStmt; - const char zSql[] = "SELECT fts3_tokenizer(?)"; - - *pp = 0; - rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ - memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); - } - } - - return sqlite3_finalize(pStmt); -} - -SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); - -/* -** Implementation of the scalar function fts3_tokenizer_internal_test(). -** This function is used for testing only, it is not included in the -** build unless SQLITE_TEST is defined. -** -** The purpose of this is to test that the fts3_tokenizer() function -** can be used as designed by the C-code in the queryTokenizer and -** registerTokenizer() functions above. These two functions are repeated -** in the README.tokenizer file as an example, so it is important to -** test them. -** -** To run the tests, evaluate the fts3_tokenizer_internal_test() scalar -** function with no arguments. An assert() will fail if a problem is -** detected. i.e.: -** -** SELECT fts3_tokenizer_internal_test(); -** -*/ -static void intTestFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - int rc; - const sqlite3_tokenizer_module *p1; - const sqlite3_tokenizer_module *p2; - sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - - /* Test the query function */ - sqlite3Fts3SimpleTokenizerModule(&p1); - rc = queryTokenizer(db, "simple", &p2); - assert( rc==SQLITE_OK ); - assert( p1==p2 ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_ERROR ); - assert( p2==0 ); - assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); - - /* Test the storage function */ - rc = registerTokenizer(db, "nosuchtokenizer", p1); - assert( rc==SQLITE_OK ); - rc = queryTokenizer(db, "nosuchtokenizer", &p2); - assert( rc==SQLITE_OK ); - assert( p2==p1 ); - - sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); -} - -#endif - -/* -** Set up SQL objects in database db used to access the contents of -** the hash table pointed to by argument pHash. The hash table must -** been initialized to use string keys, and to take a private copy -** of the key when a value is inserted. i.e. by a call similar to: -** -** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); -** -** This function adds a scalar function (see header comment above -** scalarFunc() in this file for details) and, if ENABLE_TABLE is -** defined at compilation time, a temporary virtual table (see header -** comment above struct HashTableVtab) to the database schema. Both -** provide read/write access to the contents of *pHash. -** -** The third argument to this function, zName, is used as the name -** of both the scalar and, if created, the virtual table. -*/ -SQLITE_PRIVATE int sqlite3Fts3InitHashTable( - sqlite3 *db, - Fts3Hash *pHash, - const char *zName -){ - int rc = SQLITE_OK; - void *p = (void *)pHash; - const int any = SQLITE_ANY; - -#ifdef SQLITE_TEST - char *zTest = 0; - char *zTest2 = 0; - void *pdb = (void *)db; - zTest = sqlite3_mprintf("%s_test", zName); - zTest2 = sqlite3_mprintf("%s_internal_test", zName); - if( !zTest || !zTest2 ){ - rc = SQLITE_NOMEM; - } -#endif - - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0); - } - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0); - } -#ifdef SQLITE_TEST - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0); - } - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0); - } -#endif - -#ifdef SQLITE_TEST - sqlite3_free(zTest); - sqlite3_free(zTest2); -#endif - - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_tokenizer.c **************************************/ -/************** Begin file fts3_tokenizer1.c *********************************/ -/* -** 2006 Oct 10 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** Implementation of the "simple" full-text-search tokenizer. -*/ - -/* -** The code in this file is only compiled if: -** -** * The FTS3 module is being built as an extension -** (in which case SQLITE_CORE is not defined), or -** -** * The FTS3 module is being built into the core of -** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ -/* #include */ - - -typedef struct simple_tokenizer { - sqlite3_tokenizer base; - char delim[128]; /* flag ASCII delimiters */ -} simple_tokenizer; - -typedef struct simple_tokenizer_cursor { - sqlite3_tokenizer_cursor base; - const char *pInput; /* input we are tokenizing */ - int nBytes; /* size of the input */ - int iOffset; /* current position in pInput */ - int iToken; /* index of next token to be returned */ - char *pToken; /* storage for current token */ - int nTokenAllocated; /* space allocated to zToken buffer */ -} simple_tokenizer_cursor; - - -static int simpleDelim(simple_tokenizer *t, unsigned char c){ - return c<0x80 && t->delim[c]; -} -static int fts3_isalnum(int x){ - return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z'); -} - -/* -** Create a new tokenizer instance. -*/ -static int simpleCreate( - int argc, const char * const *argv, - sqlite3_tokenizer **ppTokenizer -){ - simple_tokenizer *t; - - t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t)); - if( t==NULL ) return SQLITE_NOMEM; - memset(t, 0, sizeof(*t)); - - /* TODO(shess) Delimiters need to remain the same from run to run, - ** else we need to reindex. One solution would be a meta-table to - ** track such information in the database, then we'd only want this - ** information on the initial create. - */ - if( argc>1 ){ - int i, n = (int)strlen(argv[1]); - for(i=0; i=0x80 ){ - sqlite3_free(t); - return SQLITE_ERROR; - } - t->delim[ch] = 1; - } - } else { - /* Mark non-alphanumeric ASCII characters as delimiters */ - int i; - for(i=1; i<0x80; i++){ - t->delim[i] = !fts3_isalnum(i) ? -1 : 0; - } - } - - *ppTokenizer = &t->base; - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int simpleDestroy(sqlite3_tokenizer *pTokenizer){ - sqlite3_free(pTokenizer); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int simpleOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *pInput, int nBytes, /* String to be tokenized */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - simple_tokenizer_cursor *c; - - UNUSED_PARAMETER(pTokenizer); - - c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); - if( c==NULL ) return SQLITE_NOMEM; - - c->pInput = pInput; - if( pInput==0 ){ - c->nBytes = 0; - }else if( nBytes<0 ){ - c->nBytes = (int)strlen(pInput); - }else{ - c->nBytes = nBytes; - } - c->iOffset = 0; /* start tokenizing at the beginning */ - c->iToken = 0; - c->pToken = NULL; /* no space allocated, yet. */ - c->nTokenAllocated = 0; - - *ppCursor = &c->base; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** simpleOpen() above. -*/ -static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ - simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; - sqlite3_free(c->pToken); - sqlite3_free(c); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to simpleOpen(). -*/ -static int simpleNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ - const char **ppToken, /* OUT: *ppToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; - simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer; - unsigned char *p = (unsigned char *)c->pInput; - - while( c->iOffsetnBytes ){ - int iStartOffset; - - /* Scan past delimiter characters */ - while( c->iOffsetnBytes && simpleDelim(t, p[c->iOffset]) ){ - c->iOffset++; - } - - /* Count non-delimiter characters. */ - iStartOffset = c->iOffset; - while( c->iOffsetnBytes && !simpleDelim(t, p[c->iOffset]) ){ - c->iOffset++; - } - - if( c->iOffset>iStartOffset ){ - int i, n = c->iOffset-iStartOffset; - if( n>c->nTokenAllocated ){ - char *pNew; - c->nTokenAllocated = n+20; - pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated); - if( !pNew ) return SQLITE_NOMEM; - c->pToken = pNew; - } - for(i=0; ipToken[i] = (char)((ch>='A' && ch<='Z') ? ch-'A'+'a' : ch); - } - *ppToken = c->pToken; - *pnBytes = n; - *piStartOffset = iStartOffset; - *piEndOffset = c->iOffset; - *piPosition = c->iToken++; - - return SQLITE_OK; - } - } - return SQLITE_DONE; -} - -/* -** The set of routines that implement the simple tokenizer -*/ -static const sqlite3_tokenizer_module simpleTokenizerModule = { - 0, - simpleCreate, - simpleDestroy, - simpleOpen, - simpleClose, - simpleNext, - 0, -}; - -/* -** Allocate a new simple tokenizer. Return a pointer to the new -** tokenizer in *ppModule -*/ -SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &simpleTokenizerModule; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_tokenizer1.c *************************************/ -/************** Begin file fts3_tokenize_vtab.c ******************************/ -/* -** 2013 Apr 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file contains code for the "fts3tokenize" virtual table module. -** An fts3tokenize virtual table is created as follows: -** -** CREATE VIRTUAL TABLE USING fts3tokenize( -** , , ... -** ); -** -** The table created has the following schema: -** -** CREATE TABLE (input, token, start, end, position) -** -** When queried, the query must include a WHERE clause of type: -** -** input = -** -** The virtual table module tokenizes this , using the FTS3 -** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE -** statement and returns one row for each token in the result. With -** fields set as follows: -** -** input: Always set to a copy of -** token: A token from the input. -** start: Byte offset of the token within the input . -** end: Byte offset of the byte immediately following the end of the -** token within the input string. -** pos: Token offset of token within input. -** -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ - -typedef struct Fts3tokTable Fts3tokTable; -typedef struct Fts3tokCursor Fts3tokCursor; - -/* -** Virtual table structure. -*/ -struct Fts3tokTable { - sqlite3_vtab base; /* Base class used by SQLite core */ - const sqlite3_tokenizer_module *pMod; - sqlite3_tokenizer *pTok; -}; - -/* -** Virtual table cursor structure. -*/ -struct Fts3tokCursor { - sqlite3_vtab_cursor base; /* Base class used by SQLite core */ - char *zInput; /* Input string */ - sqlite3_tokenizer_cursor *pCsr; /* Cursor to iterate through zInput */ - int iRowid; /* Current 'rowid' value */ - const char *zToken; /* Current 'token' value */ - int nToken; /* Size of zToken in bytes */ - int iStart; /* Current 'start' value */ - int iEnd; /* Current 'end' value */ - int iPos; /* Current 'pos' value */ -}; - -/* -** Query FTS for the tokenizer implementation named zName. -*/ -static int fts3tokQueryTokenizer( - Fts3Hash *pHash, - const char *zName, - const sqlite3_tokenizer_module **pp, - char **pzErr -){ - sqlite3_tokenizer_module *p; - int nName = (int)strlen(zName); - - p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); - if( !p ){ - *pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - return SQLITE_ERROR; - } - - *pp = p; - return SQLITE_OK; -} - -/* -** The second argument, argv[], is an array of pointers to nul-terminated -** strings. This function makes a copy of the array and strings into a -** single block of memory. It then dequotes any of the strings that appear -** to be quoted. -** -** If successful, output parameter *pazDequote is set to point at the -** array of dequoted strings and SQLITE_OK is returned. The caller is -** responsible for eventually calling sqlite3_free() to free the array -** in this case. Or, if an error occurs, an SQLite error code is returned. -** The final value of *pazDequote is undefined in this case. -*/ -static int fts3tokDequoteArray( - int argc, /* Number of elements in argv[] */ - const char * const *argv, /* Input array */ - char ***pazDequote /* Output array */ -){ - int rc = SQLITE_OK; /* Return code */ - if( argc==0 ){ - *pazDequote = 0; - }else{ - int i; - int nByte = 0; - char **azDequote; - - for(i=0; ixCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok); - } - - if( rc==SQLITE_OK ){ - pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable)); - if( pTab==0 ){ - rc = SQLITE_NOMEM; - } - } - - if( rc==SQLITE_OK ){ - memset(pTab, 0, sizeof(Fts3tokTable)); - pTab->pMod = pMod; - pTab->pTok = pTok; - *ppVtab = &pTab->base; - }else{ - if( pTok ){ - pMod->xDestroy(pTok); - } - } - - sqlite3_free(azDequote); - return rc; -} - -/* -** This function does the work for both the xDisconnect and xDestroy methods. -** These tables have no persistent representation of their own, so xDisconnect -** and xDestroy are identical operations. -*/ -static int fts3tokDisconnectMethod(sqlite3_vtab *pVtab){ - Fts3tokTable *pTab = (Fts3tokTable *)pVtab; - - pTab->pMod->xDestroy(pTab->pTok); - sqlite3_free(pTab); - return SQLITE_OK; -} - -/* -** xBestIndex - Analyze a WHERE and ORDER BY clause. -*/ -static int fts3tokBestIndexMethod( - sqlite3_vtab *pVTab, - sqlite3_index_info *pInfo -){ - int i; - UNUSED_PARAMETER(pVTab); - - for(i=0; inConstraint; i++){ - if( pInfo->aConstraint[i].usable - && pInfo->aConstraint[i].iColumn==0 - && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ - ){ - pInfo->idxNum = 1; - pInfo->aConstraintUsage[i].argvIndex = 1; - pInfo->aConstraintUsage[i].omit = 1; - pInfo->estimatedCost = 1; - return SQLITE_OK; - } - } - - pInfo->idxNum = 0; - assert( pInfo->estimatedCost>1000000.0 ); - - return SQLITE_OK; -} - -/* -** xOpen - Open a cursor. -*/ -static int fts3tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ - Fts3tokCursor *pCsr; - UNUSED_PARAMETER(pVTab); - - pCsr = (Fts3tokCursor *)sqlite3_malloc(sizeof(Fts3tokCursor)); - if( pCsr==0 ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(Fts3tokCursor)); - - *ppCsr = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** Reset the tokenizer cursor passed as the only argument. As if it had -** just been returned by fts3tokOpenMethod(). -*/ -static void fts3tokResetCursor(Fts3tokCursor *pCsr){ - if( pCsr->pCsr ){ - Fts3tokTable *pTab = (Fts3tokTable *)(pCsr->base.pVtab); - pTab->pMod->xClose(pCsr->pCsr); - pCsr->pCsr = 0; - } - sqlite3_free(pCsr->zInput); - pCsr->zInput = 0; - pCsr->zToken = 0; - pCsr->nToken = 0; - pCsr->iStart = 0; - pCsr->iEnd = 0; - pCsr->iPos = 0; - pCsr->iRowid = 0; -} - -/* -** xClose - Close a cursor. -*/ -static int fts3tokCloseMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - - fts3tokResetCursor(pCsr); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** xNext - Advance the cursor to the next row, if any. -*/ -static int fts3tokNextMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab); - int rc; /* Return code */ - - pCsr->iRowid++; - rc = pTab->pMod->xNext(pCsr->pCsr, - &pCsr->zToken, &pCsr->nToken, - &pCsr->iStart, &pCsr->iEnd, &pCsr->iPos - ); - - if( rc!=SQLITE_OK ){ - fts3tokResetCursor(pCsr); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - - return rc; -} - -/* -** xFilter - Initialize a cursor to point at the start of its data. -*/ -static int fts3tokFilterMethod( - sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ - int idxNum, /* Strategy index */ - const char *idxStr, /* Unused */ - int nVal, /* Number of elements in apVal */ - sqlite3_value **apVal /* Arguments for the indexing scheme */ -){ - int rc = SQLITE_ERROR; - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab); - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(nVal); - - fts3tokResetCursor(pCsr); - if( idxNum==1 ){ - const char *zByte = (const char *)sqlite3_value_text(apVal[0]); - int nByte = sqlite3_value_bytes(apVal[0]); - pCsr->zInput = sqlite3_malloc(nByte+1); - if( pCsr->zInput==0 ){ - rc = SQLITE_NOMEM; - }else{ - memcpy(pCsr->zInput, zByte, nByte); - pCsr->zInput[nByte] = 0; - rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr); - if( rc==SQLITE_OK ){ - pCsr->pCsr->pTokenizer = pTab->pTok; - } - } - } - - if( rc!=SQLITE_OK ) return rc; - return fts3tokNextMethod(pCursor); -} - -/* -** xEof - Return true if the cursor is at EOF, or false otherwise. -*/ -static int fts3tokEofMethod(sqlite3_vtab_cursor *pCursor){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - return (pCsr->zToken==0); -} - -/* -** xColumn - Return a column value. -*/ -static int fts3tokColumnMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ - int iCol /* Index of column to read value from */ -){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - - /* CREATE TABLE x(input, token, start, end, position) */ - switch( iCol ){ - case 0: - sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT); - break; - case 1: - sqlite3_result_text(pCtx, pCsr->zToken, pCsr->nToken, SQLITE_TRANSIENT); - break; - case 2: - sqlite3_result_int(pCtx, pCsr->iStart); - break; - case 3: - sqlite3_result_int(pCtx, pCsr->iEnd); - break; - default: - assert( iCol==4 ); - sqlite3_result_int(pCtx, pCsr->iPos); - break; - } - return SQLITE_OK; -} - -/* -** xRowid - Return the current rowid for the cursor. -*/ -static int fts3tokRowidMethod( - sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite_int64 *pRowid /* OUT: Rowid value */ -){ - Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor; - *pRowid = (sqlite3_int64)pCsr->iRowid; - return SQLITE_OK; -} - -/* -** Register the fts3tok module with database connection db. Return SQLITE_OK -** if successful or an error code if sqlite3_create_module() fails. -*/ -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ - static const sqlite3_module fts3tok_module = { - 0, /* iVersion */ - fts3tokConnectMethod, /* xCreate */ - fts3tokConnectMethod, /* xConnect */ - fts3tokBestIndexMethod, /* xBestIndex */ - fts3tokDisconnectMethod, /* xDisconnect */ - fts3tokDisconnectMethod, /* xDestroy */ - fts3tokOpenMethod, /* xOpen */ - fts3tokCloseMethod, /* xClose */ - fts3tokFilterMethod, /* xFilter */ - fts3tokNextMethod, /* xNext */ - fts3tokEofMethod, /* xEof */ - fts3tokColumnMethod, /* xColumn */ - fts3tokRowidMethod, /* xRowid */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindFunction */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0 /* xRollbackTo */ - }; - int rc; /* Return code */ - - rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash); - return rc; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_tokenize_vtab.c **********************************/ -/************** Begin file fts3_write.c **************************************/ -/* -** 2009 Oct 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** This file is part of the SQLite FTS3 extension module. Specifically, -** this file contains code to insert, update and delete rows from FTS3 -** tables. It also contains code to merge FTS3 b-tree segments. Some -** of the sub-routines used to merge segments are also used by the query -** code in fts3.c. -*/ - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ - - -#define FTS_MAX_APPENDABLE_HEIGHT 16 - -/* -** When full-text index nodes are loaded from disk, the buffer that they -** are loaded into has the following number of bytes of padding at the end -** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer -** of 920 bytes is allocated for it. -** -** This means that if we have a pointer into a buffer containing node data, -** it is always safe to read up to two varints from it without risking an -** overread, even if the node data is corrupted. -*/ -#define FTS3_NODE_PADDING (FTS3_VARINT_MAX*2) - -/* -** Under certain circumstances, b-tree nodes (doclists) can be loaded into -** memory incrementally instead of all at once. This can be a big performance -** win (reduced IO and CPU) if SQLite stops calling the virtual table xNext() -** method before retrieving all query results (as may happen, for example, -** if a query has a LIMIT clause). -** -** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD -** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes. -** The code is written so that the hard lower-limit for each of these values -** is 1. Clearly such small values would be inefficient, but can be useful -** for testing purposes. -** -** If this module is built with SQLITE_TEST defined, these constants may -** be overridden at runtime for testing purposes. File fts3_test.c contains -** a Tcl interface to read and write the values. -*/ -#ifdef SQLITE_TEST -int test_fts3_node_chunksize = (4*1024); -int test_fts3_node_chunk_threshold = (4*1024)*4; -# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize -# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold -#else -# define FTS3_NODE_CHUNKSIZE (4*1024) -# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4) -#endif - -/* -** The two values that may be meaningfully bound to the :1 parameter in -** statements SQL_REPLACE_STAT and SQL_SELECT_STAT. -*/ -#define FTS_STAT_DOCTOTAL 0 -#define FTS_STAT_INCRMERGEHINT 1 -#define FTS_STAT_AUTOINCRMERGE 2 - -/* -** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic -** and incremental merge operation that takes place. This is used for -** debugging FTS only, it should not usually be turned on in production -** systems. -*/ -#ifdef FTS3_LOG_MERGES -static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){ - sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel); -} -#else -#define fts3LogMerge(x, y) -#endif - - -typedef struct PendingList PendingList; -typedef struct SegmentNode SegmentNode; -typedef struct SegmentWriter SegmentWriter; - -/* -** An instance of the following data structure is used to build doclists -** incrementally. See function fts3PendingListAppend() for details. -*/ -struct PendingList { - int nData; - char *aData; - int nSpace; - sqlite3_int64 iLastDocid; - sqlite3_int64 iLastCol; - sqlite3_int64 iLastPos; -}; - - -/* -** Each cursor has a (possibly empty) linked list of the following objects. -*/ -struct Fts3DeferredToken { - Fts3PhraseToken *pToken; /* Pointer to corresponding expr token */ - int iCol; /* Column token must occur in */ - Fts3DeferredToken *pNext; /* Next in list of deferred tokens */ - PendingList *pList; /* Doclist is assembled here */ -}; - -/* -** An instance of this structure is used to iterate through the terms on -** a contiguous set of segment b-tree leaf nodes. Although the details of -** this structure are only manipulated by code in this file, opaque handles -** of type Fts3SegReader* are also used by code in fts3.c to iterate through -** terms when querying the full-text index. See functions: -** -** sqlite3Fts3SegReaderNew() -** sqlite3Fts3SegReaderFree() -** sqlite3Fts3SegReaderIterate() -** -** Methods used to manipulate Fts3SegReader structures: -** -** fts3SegReaderNext() -** fts3SegReaderFirstDocid() -** fts3SegReaderNextDocid() -*/ -struct Fts3SegReader { - int iIdx; /* Index within level, or 0x7FFFFFFF for PT */ - u8 bLookup; /* True for a lookup only */ - u8 rootOnly; /* True for a root-only reader */ - - sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */ - sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */ - sqlite3_int64 iEndBlock; /* Rowid of final block in segment (or 0) */ - sqlite3_int64 iCurrentBlock; /* Current leaf block (or 0) */ - - char *aNode; /* Pointer to node data (or NULL) */ - int nNode; /* Size of buffer at aNode (or 0) */ - int nPopulate; /* If >0, bytes of buffer aNode[] loaded */ - sqlite3_blob *pBlob; /* If not NULL, blob handle to read node */ - - Fts3HashElem **ppNextElem; - - /* Variables set by fts3SegReaderNext(). These may be read directly - ** by the caller. They are valid from the time SegmentReaderNew() returns - ** until SegmentReaderNext() returns something other than SQLITE_OK - ** (i.e. SQLITE_DONE). - */ - int nTerm; /* Number of bytes in current term */ - char *zTerm; /* Pointer to current term */ - int nTermAlloc; /* Allocated size of zTerm buffer */ - char *aDoclist; /* Pointer to doclist of current entry */ - int nDoclist; /* Size of doclist in current entry */ - - /* The following variables are used by fts3SegReaderNextDocid() to iterate - ** through the current doclist (aDoclist/nDoclist). - */ - char *pOffsetList; - int nOffsetList; /* For descending pending seg-readers only */ - sqlite3_int64 iDocid; -}; - -#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0) -#define fts3SegReaderIsRootOnly(p) ((p)->rootOnly!=0) - -/* -** An instance of this structure is used to create a segment b-tree in the -** database. The internal details of this type are only accessed by the -** following functions: -** -** fts3SegWriterAdd() -** fts3SegWriterFlush() -** fts3SegWriterFree() -*/ -struct SegmentWriter { - SegmentNode *pTree; /* Pointer to interior tree structure */ - sqlite3_int64 iFirst; /* First slot in %_segments written */ - sqlite3_int64 iFree; /* Next free slot in %_segments */ - char *zTerm; /* Pointer to previous term buffer */ - int nTerm; /* Number of bytes in zTerm */ - int nMalloc; /* Size of malloc'd buffer at zMalloc */ - char *zMalloc; /* Malloc'd space (possibly) used for zTerm */ - int nSize; /* Size of allocation at aData */ - int nData; /* Bytes of data in aData */ - char *aData; /* Pointer to block from malloc() */ -}; - -/* -** Type SegmentNode is used by the following three functions to create -** the interior part of the segment b+-tree structures (everything except -** the leaf nodes). These functions and type are only ever used by code -** within the fts3SegWriterXXX() family of functions described above. -** -** fts3NodeAddTerm() -** fts3NodeWrite() -** fts3NodeFree() -** -** When a b+tree is written to the database (either as a result of a merge -** or the pending-terms table being flushed), leaves are written into the -** database file as soon as they are completely populated. The interior of -** the tree is assembled in memory and written out only once all leaves have -** been populated and stored. This is Ok, as the b+-tree fanout is usually -** very large, meaning that the interior of the tree consumes relatively -** little memory. -*/ -struct SegmentNode { - SegmentNode *pParent; /* Parent node (or NULL for root node) */ - SegmentNode *pRight; /* Pointer to right-sibling */ - SegmentNode *pLeftmost; /* Pointer to left-most node of this depth */ - int nEntry; /* Number of terms written to node so far */ - char *zTerm; /* Pointer to previous term buffer */ - int nTerm; /* Number of bytes in zTerm */ - int nMalloc; /* Size of malloc'd buffer at zMalloc */ - char *zMalloc; /* Malloc'd space (possibly) used for zTerm */ - int nData; /* Bytes of valid data so far */ - char *aData; /* Node data */ -}; - -/* -** Valid values for the second argument to fts3SqlStmt(). -*/ -#define SQL_DELETE_CONTENT 0 -#define SQL_IS_EMPTY 1 -#define SQL_DELETE_ALL_CONTENT 2 -#define SQL_DELETE_ALL_SEGMENTS 3 -#define SQL_DELETE_ALL_SEGDIR 4 -#define SQL_DELETE_ALL_DOCSIZE 5 -#define SQL_DELETE_ALL_STAT 6 -#define SQL_SELECT_CONTENT_BY_ROWID 7 -#define SQL_NEXT_SEGMENT_INDEX 8 -#define SQL_INSERT_SEGMENTS 9 -#define SQL_NEXT_SEGMENTS_ID 10 -#define SQL_INSERT_SEGDIR 11 -#define SQL_SELECT_LEVEL 12 -#define SQL_SELECT_LEVEL_RANGE 13 -#define SQL_SELECT_LEVEL_COUNT 14 -#define SQL_SELECT_SEGDIR_MAX_LEVEL 15 -#define SQL_DELETE_SEGDIR_LEVEL 16 -#define SQL_DELETE_SEGMENTS_RANGE 17 -#define SQL_CONTENT_INSERT 18 -#define SQL_DELETE_DOCSIZE 19 -#define SQL_REPLACE_DOCSIZE 20 -#define SQL_SELECT_DOCSIZE 21 -#define SQL_SELECT_STAT 22 -#define SQL_REPLACE_STAT 23 - -#define SQL_SELECT_ALL_PREFIX_LEVEL 24 -#define SQL_DELETE_ALL_TERMS_SEGDIR 25 -#define SQL_DELETE_SEGDIR_RANGE 26 -#define SQL_SELECT_ALL_LANGID 27 -#define SQL_FIND_MERGE_LEVEL 28 -#define SQL_MAX_LEAF_NODE_ESTIMATE 29 -#define SQL_DELETE_SEGDIR_ENTRY 30 -#define SQL_SHIFT_SEGDIR_ENTRY 31 -#define SQL_SELECT_SEGDIR 32 -#define SQL_CHOMP_SEGDIR 33 -#define SQL_SEGMENT_IS_APPENDABLE 34 -#define SQL_SELECT_INDEXES 35 -#define SQL_SELECT_MXLEVEL 36 - -/* -** This function is used to obtain an SQLite prepared statement handle -** for the statement identified by the second argument. If successful, -** *pp is set to the requested statement handle and SQLITE_OK returned. -** Otherwise, an SQLite error code is returned and *pp is set to 0. -** -** If argument apVal is not NULL, then it must point to an array with -** at least as many entries as the requested statement has bound -** parameters. The values are bound to the statements parameters before -** returning. -*/ -static int fts3SqlStmt( - Fts3Table *p, /* Virtual table handle */ - int eStmt, /* One of the SQL_XXX constants above */ - sqlite3_stmt **pp, /* OUT: Statement handle */ - sqlite3_value **apVal /* Values to bind to statement */ -){ - const char *azSql[] = { -/* 0 */ "DELETE FROM %Q.'%q_content' WHERE rowid = ?", -/* 1 */ "SELECT NOT EXISTS(SELECT docid FROM %Q.'%q_content' WHERE rowid!=?)", -/* 2 */ "DELETE FROM %Q.'%q_content'", -/* 3 */ "DELETE FROM %Q.'%q_segments'", -/* 4 */ "DELETE FROM %Q.'%q_segdir'", -/* 5 */ "DELETE FROM %Q.'%q_docsize'", -/* 6 */ "DELETE FROM %Q.'%q_stat'", -/* 7 */ "SELECT %s WHERE rowid=?", -/* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1", -/* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", -/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)", -/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", - - /* Return segments in order from oldest to newest.*/ -/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC", -/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?" - "ORDER BY level DESC, idx ASC", - -/* 14 */ "SELECT count(*) FROM %Q.'%q_segdir' WHERE level = ?", -/* 15 */ "SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", - -/* 16 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ?", -/* 17 */ "DELETE FROM %Q.'%q_segments' WHERE blockid BETWEEN ? AND ?", -/* 18 */ "INSERT INTO %Q.'%q_content' VALUES(%s)", -/* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", -/* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", -/* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", -/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?", -/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)", -/* 24 */ "", -/* 25 */ "", - -/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", -/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", - -/* This statement is used to determine which level to read the input from -** when performing an incremental merge. It returns the absolute level number -** of the oldest level in the db that contains at least ? segments. Or, -** if no level in the FTS index contains more than ? segments, the statement -** returns zero rows. */ -/* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?" - " ORDER BY (level %% 1024) ASC LIMIT 1", - -/* Estimate the upper limit on the number of leaf nodes in a new segment -** created by merging the oldest :2 segments from absolute level :1. See -** function sqlite3Fts3Incrmerge() for details. */ -/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) " - " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?", - -/* SQL_DELETE_SEGDIR_ENTRY -** Delete the %_segdir entry on absolute level :1 with index :2. */ -/* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", - -/* SQL_SHIFT_SEGDIR_ENTRY -** Modify the idx value for the segment with idx=:3 on absolute level :2 -** to :1. */ -/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?", - -/* SQL_SELECT_SEGDIR -** Read a single entry from the %_segdir table. The entry from absolute -** level :1 with index value :2. */ -/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root " - "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", - -/* SQL_CHOMP_SEGDIR -** Update the start_block (:1) and root (:2) fields of the %_segdir -** entry located on absolute level :3 with index :4. */ -/* 33 */ "UPDATE %Q.'%q_segdir' SET start_block = ?, root = ?" - "WHERE level = ? AND idx = ?", - -/* SQL_SEGMENT_IS_APPENDABLE -** Return a single row if the segment with end_block=? is appendable. Or -** no rows otherwise. */ -/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL", - -/* SQL_SELECT_INDEXES -** Return the list of valid segment indexes for absolute level ? */ -/* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC", - -/* SQL_SELECT_MXLEVEL -** Return the largest relative level in the FTS index or indexes. */ -/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'" - }; - int rc = SQLITE_OK; - sqlite3_stmt *pStmt; - - assert( SizeofArray(azSql)==SizeofArray(p->aStmt) ); - assert( eStmt=0 ); - - pStmt = p->aStmt[eStmt]; - if( !pStmt ){ - char *zSql; - if( eStmt==SQL_CONTENT_INSERT ){ - zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist); - }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){ - zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist); - }else{ - zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName); - } - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL); - sqlite3_free(zSql); - assert( rc==SQLITE_OK || pStmt==0 ); - p->aStmt[eStmt] = pStmt; - } - } - if( apVal ){ - int i; - int nParam = sqlite3_bind_parameter_count(pStmt); - for(i=0; rc==SQLITE_OK && izContentTbl==0 ){ - rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_null(pStmt, 1); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - } - }else{ - rc = SQLITE_OK; - } - - return rc; -} - -/* -** FTS maintains a separate indexes for each language-id (a 32-bit integer). -** Within each language id, a separate index is maintained to store the -** document terms, and each configured prefix size (configured the FTS -** "prefix=" option). And each index consists of multiple levels ("relative -** levels"). -** -** All three of these values (the language id, the specific index and the -** level within the index) are encoded in 64-bit integer values stored -** in the %_segdir table on disk. This function is used to convert three -** separate component values into the single 64-bit integer value that -** can be used to query the %_segdir table. -** -** Specifically, each language-id/index combination is allocated 1024 -** 64-bit integer level values ("absolute levels"). The main terms index -** for language-id 0 is allocate values 0-1023. The first prefix index -** (if any) for language-id 0 is allocated values 1024-2047. And so on. -** Language 1 indexes are allocated immediately following language 0. -** -** So, for a system with nPrefix prefix indexes configured, the block of -** absolute levels that corresponds to language-id iLangid and index -** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024). -*/ -static sqlite3_int64 getAbsoluteLevel( - Fts3Table *p, /* FTS3 table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index in p->aIndex[] */ - int iLevel /* Level of segments */ -){ - sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */ - assert( iLangid>=0 ); - assert( p->nIndex>0 ); - assert( iIndex>=0 && iIndexnIndex ); - - iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL; - return iBase + iLevel; -} - -/* -** Set *ppStmt to a statement handle that may be used to iterate through -** all rows in the %_segdir table, from oldest to newest. If successful, -** return SQLITE_OK. If an error occurs while preparing the statement, -** return an SQLite error code. -** -** There is only ever one instance of this SQL statement compiled for -** each FTS3 table. -** -** The statement returns the following columns from the %_segdir table: -** -** 0: idx -** 1: start_block -** 2: leaves_end_block -** 3: end_block -** 4: root -*/ -SQLITE_PRIVATE int sqlite3Fts3AllSegdirs( - Fts3Table *p, /* FTS3 table */ - int iLangid, /* Language being queried */ - int iIndex, /* Index for p->aIndex[] */ - int iLevel, /* Level to select (relative level) */ - sqlite3_stmt **ppStmt /* OUT: Compiled statement */ -){ - int rc; - sqlite3_stmt *pStmt = 0; - - assert( iLevel==FTS3_SEGCURSOR_ALL || iLevel>=0 ); - assert( iLevel=0 && iIndexnIndex ); - - if( iLevel<0 ){ - /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */ - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pStmt, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - } - }else{ - /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */ - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel)); - } - } - *ppStmt = pStmt; - return rc; -} - - -/* -** Append a single varint to a PendingList buffer. SQLITE_OK is returned -** if successful, or an SQLite error code otherwise. -** -** This function also serves to allocate the PendingList structure itself. -** For example, to create a new PendingList structure containing two -** varints: -** -** PendingList *p = 0; -** fts3PendingListAppendVarint(&p, 1); -** fts3PendingListAppendVarint(&p, 2); -*/ -static int fts3PendingListAppendVarint( - PendingList **pp, /* IN/OUT: Pointer to PendingList struct */ - sqlite3_int64 i /* Value to append to data */ -){ - PendingList *p = *pp; - - /* Allocate or grow the PendingList as required. */ - if( !p ){ - p = sqlite3_malloc(sizeof(*p) + 100); - if( !p ){ - return SQLITE_NOMEM; - } - p->nSpace = 100; - p->aData = (char *)&p[1]; - p->nData = 0; - } - else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){ - int nNew = p->nSpace * 2; - p = sqlite3_realloc(p, sizeof(*p) + nNew); - if( !p ){ - sqlite3_free(*pp); - *pp = 0; - return SQLITE_NOMEM; - } - p->nSpace = nNew; - p->aData = (char *)&p[1]; - } - - /* Append the new serialized varint to the end of the list. */ - p->nData += sqlite3Fts3PutVarint(&p->aData[p->nData], i); - p->aData[p->nData] = '\0'; - *pp = p; - return SQLITE_OK; -} - -/* -** Add a docid/column/position entry to a PendingList structure. Non-zero -** is returned if the structure is sqlite3_realloced as part of adding -** the entry. Otherwise, zero. -** -** If an OOM error occurs, *pRc is set to SQLITE_NOMEM before returning. -** Zero is always returned in this case. Otherwise, if no OOM error occurs, -** it is set to SQLITE_OK. -*/ -static int fts3PendingListAppend( - PendingList **pp, /* IN/OUT: PendingList structure */ - sqlite3_int64 iDocid, /* Docid for entry to add */ - sqlite3_int64 iCol, /* Column for entry to add */ - sqlite3_int64 iPos, /* Position of term for entry to add */ - int *pRc /* OUT: Return code */ -){ - PendingList *p = *pp; - int rc = SQLITE_OK; - - assert( !p || p->iLastDocid<=iDocid ); - - if( !p || p->iLastDocid!=iDocid ){ - sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0); - if( p ){ - assert( p->nDatanSpace ); - assert( p->aData[p->nData]==0 ); - p->nData++; - } - if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iDelta)) ){ - goto pendinglistappend_out; - } - p->iLastCol = -1; - p->iLastPos = 0; - p->iLastDocid = iDocid; - } - if( iCol>0 && p->iLastCol!=iCol ){ - if( SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, 1)) - || SQLITE_OK!=(rc = fts3PendingListAppendVarint(&p, iCol)) - ){ - goto pendinglistappend_out; - } - p->iLastCol = iCol; - p->iLastPos = 0; - } - if( iCol>=0 ){ - assert( iPos>p->iLastPos || (iPos==0 && p->iLastPos==0) ); - rc = fts3PendingListAppendVarint(&p, 2+iPos-p->iLastPos); - if( rc==SQLITE_OK ){ - p->iLastPos = iPos; - } - } - - pendinglistappend_out: - *pRc = rc; - if( p!=*pp ){ - *pp = p; - return 1; - } - return 0; -} - -/* -** Free a PendingList object allocated by fts3PendingListAppend(). -*/ -static void fts3PendingListDelete(PendingList *pList){ - sqlite3_free(pList); -} - -/* -** Add an entry to one of the pending-terms hash tables. -*/ -static int fts3PendingTermsAddOne( - Fts3Table *p, - int iCol, - int iPos, - Fts3Hash *pHash, /* Pending terms hash table to add entry to */ - const char *zToken, - int nToken -){ - PendingList *pList; - int rc = SQLITE_OK; - - pList = (PendingList *)fts3HashFind(pHash, zToken, nToken); - if( pList ){ - p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem)); - } - if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){ - if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){ - /* Malloc failed while inserting the new entry. This can only - ** happen if there was no previous entry for this token. - */ - assert( 0==fts3HashFind(pHash, zToken, nToken) ); - sqlite3_free(pList); - rc = SQLITE_NOMEM; - } - } - if( rc==SQLITE_OK ){ - p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); - } - return rc; -} - -/* -** Tokenize the nul-terminated string zText and add all tokens to the -** pending-terms hash-table. The docid used is that currently stored in -** p->iPrevDocid, and the column is specified by argument iCol. -** -** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. -*/ -static int fts3PendingTermsAdd( - Fts3Table *p, /* Table into which text will be inserted */ - int iLangid, /* Language id to use */ - const char *zText, /* Text of document to be inserted */ - int iCol, /* Column into which text is being inserted */ - u32 *pnWord /* IN/OUT: Incr. by number tokens inserted */ -){ - int rc; - int iStart = 0; - int iEnd = 0; - int iPos = 0; - int nWord = 0; - - char const *zToken; - int nToken = 0; - - sqlite3_tokenizer *pTokenizer = p->pTokenizer; - sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; - sqlite3_tokenizer_cursor *pCsr; - int (*xNext)(sqlite3_tokenizer_cursor *pCursor, - const char**,int*,int*,int*,int*); - - assert( pTokenizer && pModule ); - - /* If the user has inserted a NULL value, this function may be called with - ** zText==0. In this case, add zero token entries to the hash table and - ** return early. */ - if( zText==0 ){ - *pnWord = 0; - return SQLITE_OK; - } - - rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr); - if( rc!=SQLITE_OK ){ - return rc; - } - - xNext = pModule->xNext; - while( SQLITE_OK==rc - && SQLITE_OK==(rc = xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos)) - ){ - int i; - if( iPos>=nWord ) nWord = iPos+1; - - /* Positions cannot be negative; we use -1 as a terminator internally. - ** Tokens must have a non-zero length. - */ - if( iPos<0 || !zToken || nToken<=0 ){ - rc = SQLITE_ERROR; - break; - } - - /* Add the term to the terms index */ - rc = fts3PendingTermsAddOne( - p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken - ); - - /* Add the term to each of the prefix indexes that it is not too - ** short for. */ - for(i=1; rc==SQLITE_OK && inIndex; i++){ - struct Fts3Index *pIndex = &p->aIndex[i]; - if( nTokennPrefix ) continue; - rc = fts3PendingTermsAddOne( - p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix - ); - } - } - - pModule->xClose(pCsr); - *pnWord += nWord; - return (rc==SQLITE_DONE ? SQLITE_OK : rc); -} - -/* -** Calling this function indicates that subsequent calls to -** fts3PendingTermsAdd() are to add term/position-list pairs for the -** contents of the document with docid iDocid. -*/ -static int fts3PendingTermsDocid( - Fts3Table *p, /* Full-text table handle */ - int iLangid, /* Language id of row being written */ - sqlite_int64 iDocid /* Docid of row being written */ -){ - assert( iLangid>=0 ); - - /* TODO(shess) Explore whether partially flushing the buffer on - ** forced-flush would provide better performance. I suspect that if - ** we ordered the doclists by size and flushed the largest until the - ** buffer was half empty, that would let the less frequent terms - ** generate longer doclists. - */ - if( iDocid<=p->iPrevDocid - || p->iPrevLangid!=iLangid - || p->nPendingData>p->nMaxPendingData - ){ - int rc = sqlite3Fts3PendingTermsFlush(p); - if( rc!=SQLITE_OK ) return rc; - } - p->iPrevDocid = iDocid; - p->iPrevLangid = iLangid; - return SQLITE_OK; -} - -/* -** Discard the contents of the pending-terms hash tables. -*/ -SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){ - int i; - for(i=0; inIndex; i++){ - Fts3HashElem *pElem; - Fts3Hash *pHash = &p->aIndex[i].hPending; - for(pElem=fts3HashFirst(pHash); pElem; pElem=fts3HashNext(pElem)){ - PendingList *pList = (PendingList *)fts3HashData(pElem); - fts3PendingListDelete(pList); - } - fts3HashClear(pHash); - } - p->nPendingData = 0; -} - -/* -** This function is called by the xUpdate() method as part of an INSERT -** operation. It adds entries for each term in the new record to the -** pendingTerms hash table. -** -** Argument apVal is the same as the similarly named argument passed to -** fts3InsertData(). Parameter iDocid is the docid of the new row. -*/ -static int fts3InsertTerms( - Fts3Table *p, - int iLangid, - sqlite3_value **apVal, - u32 *aSz -){ - int i; /* Iterator variable */ - for(i=2; inColumn+2; i++){ - const char *zText = (const char *)sqlite3_value_text(apVal[i]); - int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]); - if( rc!=SQLITE_OK ){ - return rc; - } - aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]); - } - return SQLITE_OK; -} - -/* -** This function is called by the xUpdate() method for an INSERT operation. -** The apVal parameter is passed a copy of the apVal argument passed by -** SQLite to the xUpdate() method. i.e: -** -** apVal[0] Not used for INSERT. -** apVal[1] rowid -** apVal[2] Left-most user-defined column -** ... -** apVal[p->nColumn+1] Right-most user-defined column -** apVal[p->nColumn+2] Hidden column with same name as table -** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid) -** apVal[p->nColumn+4] Hidden languageid column -*/ -static int fts3InsertData( - Fts3Table *p, /* Full-text table */ - sqlite3_value **apVal, /* Array of values to insert */ - sqlite3_int64 *piDocid /* OUT: Docid for row just inserted */ -){ - int rc; /* Return code */ - sqlite3_stmt *pContentInsert; /* INSERT INTO %_content VALUES(...) */ - - if( p->zContentTbl ){ - sqlite3_value *pRowid = apVal[p->nColumn+3]; - if( sqlite3_value_type(pRowid)==SQLITE_NULL ){ - pRowid = apVal[1]; - } - if( sqlite3_value_type(pRowid)!=SQLITE_INTEGER ){ - return SQLITE_CONSTRAINT; - } - *piDocid = sqlite3_value_int64(pRowid); - return SQLITE_OK; - } - - /* Locate the statement handle used to insert data into the %_content - ** table. The SQL for this statement is: - ** - ** INSERT INTO %_content VALUES(?, ?, ?, ...) - ** - ** The statement features N '?' variables, where N is the number of user - ** defined columns in the FTS3 table, plus one for the docid field. - */ - rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]); - if( rc==SQLITE_OK && p->zLanguageid ){ - rc = sqlite3_bind_int( - pContentInsert, p->nColumn+2, - sqlite3_value_int(apVal[p->nColumn+4]) - ); - } - if( rc!=SQLITE_OK ) return rc; - - /* There is a quirk here. The users INSERT statement may have specified - ** a value for the "rowid" field, for the "docid" field, or for both. - ** Which is a problem, since "rowid" and "docid" are aliases for the - ** same value. For example: - ** - ** INSERT INTO fts3tbl(rowid, docid) VALUES(1, 2); - ** - ** In FTS3, this is an error. It is an error to specify non-NULL values - ** for both docid and some other rowid alias. - */ - if( SQLITE_NULL!=sqlite3_value_type(apVal[3+p->nColumn]) ){ - if( SQLITE_NULL==sqlite3_value_type(apVal[0]) - && SQLITE_NULL!=sqlite3_value_type(apVal[1]) - ){ - /* A rowid/docid conflict. */ - return SQLITE_ERROR; - } - rc = sqlite3_bind_value(pContentInsert, 1, apVal[3+p->nColumn]); - if( rc!=SQLITE_OK ) return rc; - } - - /* Execute the statement to insert the record. Set *piDocid to the - ** new docid value. - */ - sqlite3_step(pContentInsert); - rc = sqlite3_reset(pContentInsert); - - *piDocid = sqlite3_last_insert_rowid(p->db); - return rc; -} - - - -/* -** Remove all data from the FTS3 table. Clear the hash table containing -** pending terms. -*/ -static int fts3DeleteAll(Fts3Table *p, int bContent){ - int rc = SQLITE_OK; /* Return code */ - - /* Discard the contents of the pending-terms hash table. */ - sqlite3Fts3PendingTermsClear(p); - - /* Delete everything from the shadow tables. Except, leave %_content as - ** is if bContent is false. */ - assert( p->zContentTbl==0 || bContent==0 ); - if( bContent ) fts3SqlExec(&rc, p, SQL_DELETE_ALL_CONTENT, 0); - fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGMENTS, 0); - fts3SqlExec(&rc, p, SQL_DELETE_ALL_SEGDIR, 0); - if( p->bHasDocsize ){ - fts3SqlExec(&rc, p, SQL_DELETE_ALL_DOCSIZE, 0); - } - if( p->bHasStat ){ - fts3SqlExec(&rc, p, SQL_DELETE_ALL_STAT, 0); - } - return rc; -} - -/* -** -*/ -static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){ - int iLangid = 0; - if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1); - return iLangid; -} - -/* -** The first element in the apVal[] array is assumed to contain the docid -** (an integer) of a row about to be deleted. Remove all terms from the -** full-text index. -*/ -static void fts3DeleteTerms( - int *pRC, /* Result code */ - Fts3Table *p, /* The FTS table to delete from */ - sqlite3_value *pRowid, /* The docid to be deleted */ - u32 *aSz, /* Sizes of deleted document written here */ - int *pbFound /* OUT: Set to true if row really does exist */ -){ - int rc; - sqlite3_stmt *pSelect; - - assert( *pbFound==0 ); - if( *pRC ) return; - rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pSelect) ){ - int i; - int iLangid = langidFromSelect(p, pSelect); - rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); - for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ - const char *zText = (const char *)sqlite3_column_text(pSelect, i); - rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]); - aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); - } - if( rc!=SQLITE_OK ){ - sqlite3_reset(pSelect); - *pRC = rc; - return; - } - *pbFound = 1; - } - rc = sqlite3_reset(pSelect); - }else{ - sqlite3_reset(pSelect); - } - *pRC = rc; -} - -/* -** Forward declaration to account for the circular dependency between -** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). -*/ -static int fts3SegmentMerge(Fts3Table *, int, int, int); - -/* -** This function allocates a new level iLevel index in the segdir table. -** Usually, indexes are allocated within a level sequentially starting -** with 0, so the allocated index is one greater than the value returned -** by: -** -** SELECT max(idx) FROM %_segdir WHERE level = :iLevel -** -** However, if there are already FTS3_MERGE_COUNT indexes at the requested -** level, they are merged into a single level (iLevel+1) segment and the -** allocated index is 0. -** -** If successful, *piIdx is set to the allocated index slot and SQLITE_OK -** returned. Otherwise, an SQLite error code is returned. -*/ -static int fts3AllocateSegdirIdx( - Fts3Table *p, - int iLangid, /* Language id */ - int iIndex, /* Index for p->aIndex */ - int iLevel, - int *piIdx -){ - int rc; /* Return Code */ - sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ - int iNext = 0; /* Result of query pNextIdx */ - - assert( iLangid>=0 ); - assert( p->nIndex>=1 ); - - /* Set variable iNext to the next available segdir index at level iLevel. */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64( - pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) - ); - if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ - iNext = sqlite3_column_int(pNextIdx, 0); - } - rc = sqlite3_reset(pNextIdx); - } - - if( rc==SQLITE_OK ){ - /* If iNext is FTS3_MERGE_COUNT, indicating that level iLevel is already - ** full, merge all segments in level iLevel into a single iLevel+1 - ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise, - ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. - */ - if( iNext>=FTS3_MERGE_COUNT ){ - fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel)); - rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel); - *piIdx = 0; - }else{ - *piIdx = iNext; - } - } - - return rc; -} - -/* -** The %_segments table is declared as follows: -** -** CREATE TABLE %_segments(blockid INTEGER PRIMARY KEY, block BLOB) -** -** This function reads data from a single row of the %_segments table. The -** specific row is identified by the iBlockid parameter. If paBlob is not -** NULL, then a buffer is allocated using sqlite3_malloc() and populated -** with the contents of the blob stored in the "block" column of the -** identified table row is. Whether or not paBlob is NULL, *pnBlob is set -** to the size of the blob in bytes before returning. -** -** If an error occurs, or the table does not contain the specified row, -** an SQLite error code is returned. Otherwise, SQLITE_OK is returned. If -** paBlob is non-NULL, then it is the responsibility of the caller to -** eventually free the returned buffer. -** -** This function may leave an open sqlite3_blob* handle in the -** Fts3Table.pSegments variable. This handle is reused by subsequent calls -** to this function. The handle may be closed by calling the -** sqlite3Fts3SegmentsClose() function. Reusing a blob handle is a handy -** performance improvement, but the blob handle should always be closed -** before control is returned to the user (to prevent a lock being held -** on the database file for longer than necessary). Thus, any virtual table -** method (xFilter etc.) that may directly or indirectly call this function -** must call sqlite3Fts3SegmentsClose() before returning. -*/ -SQLITE_PRIVATE int sqlite3Fts3ReadBlock( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iBlockid, /* Access the row with blockid=$iBlockid */ - char **paBlob, /* OUT: Blob data in malloc'd buffer */ - int *pnBlob, /* OUT: Size of blob data */ - int *pnLoad /* OUT: Bytes actually loaded */ -){ - int rc; /* Return code */ - - /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */ - assert( pnBlob ); - - if( p->pSegments ){ - rc = sqlite3_blob_reopen(p->pSegments, iBlockid); - }else{ - if( 0==p->zSegmentsTbl ){ - p->zSegmentsTbl = sqlite3_mprintf("%s_segments", p->zName); - if( 0==p->zSegmentsTbl ) return SQLITE_NOMEM; - } - rc = sqlite3_blob_open( - p->db, p->zDb, p->zSegmentsTbl, "block", iBlockid, 0, &p->pSegments - ); - } - - if( rc==SQLITE_OK ){ - int nByte = sqlite3_blob_bytes(p->pSegments); - *pnBlob = nByte; - if( paBlob ){ - char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING); - if( !aByte ){ - rc = SQLITE_NOMEM; - }else{ - if( pnLoad && nByte>(FTS3_NODE_CHUNK_THRESHOLD) ){ - nByte = FTS3_NODE_CHUNKSIZE; - *pnLoad = nByte; - } - rc = sqlite3_blob_read(p->pSegments, aByte, nByte, 0); - memset(&aByte[nByte], 0, FTS3_NODE_PADDING); - if( rc!=SQLITE_OK ){ - sqlite3_free(aByte); - aByte = 0; - } - } - *paBlob = aByte; - } - } - - return rc; -} - -/* -** Close the blob handle at p->pSegments, if it is open. See comments above -** the sqlite3Fts3ReadBlock() function for details. -*/ -SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *p){ - sqlite3_blob_close(p->pSegments); - p->pSegments = 0; -} - -static int fts3SegReaderIncrRead(Fts3SegReader *pReader){ - int nRead; /* Number of bytes to read */ - int rc; /* Return code */ - - nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE); - rc = sqlite3_blob_read( - pReader->pBlob, - &pReader->aNode[pReader->nPopulate], - nRead, - pReader->nPopulate - ); - - if( rc==SQLITE_OK ){ - pReader->nPopulate += nRead; - memset(&pReader->aNode[pReader->nPopulate], 0, FTS3_NODE_PADDING); - if( pReader->nPopulate==pReader->nNode ){ - sqlite3_blob_close(pReader->pBlob); - pReader->pBlob = 0; - pReader->nPopulate = 0; - } - } - return rc; -} - -static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){ - int rc = SQLITE_OK; - assert( !pReader->pBlob - || (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode]) - ); - while( pReader->pBlob && rc==SQLITE_OK - && (pFrom - pReader->aNode + nByte)>pReader->nPopulate - ){ - rc = fts3SegReaderIncrRead(pReader); - } - return rc; -} - -/* -** Set an Fts3SegReader cursor to point at EOF. -*/ -static void fts3SegReaderSetEof(Fts3SegReader *pSeg){ - if( !fts3SegReaderIsRootOnly(pSeg) ){ - sqlite3_free(pSeg->aNode); - sqlite3_blob_close(pSeg->pBlob); - pSeg->pBlob = 0; - } - pSeg->aNode = 0; -} - -/* -** Move the iterator passed as the first argument to the next term in the -** segment. If successful, SQLITE_OK is returned. If there is no next term, -** SQLITE_DONE. Otherwise, an SQLite error code. -*/ -static int fts3SegReaderNext( - Fts3Table *p, - Fts3SegReader *pReader, - int bIncr -){ - int rc; /* Return code of various sub-routines */ - char *pNext; /* Cursor variable */ - int nPrefix; /* Number of bytes in term prefix */ - int nSuffix; /* Number of bytes in term suffix */ - - if( !pReader->aDoclist ){ - pNext = pReader->aNode; - }else{ - pNext = &pReader->aDoclist[pReader->nDoclist]; - } - - if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){ - - if( fts3SegReaderIsPending(pReader) ){ - Fts3HashElem *pElem = *(pReader->ppNextElem); - if( pElem==0 ){ - pReader->aNode = 0; - }else{ - PendingList *pList = (PendingList *)fts3HashData(pElem); - pReader->zTerm = (char *)fts3HashKey(pElem); - pReader->nTerm = fts3HashKeysize(pElem); - pReader->nNode = pReader->nDoclist = pList->nData + 1; - pReader->aNode = pReader->aDoclist = pList->aData; - pReader->ppNextElem++; - assert( pReader->aNode ); - } - return SQLITE_OK; - } - - fts3SegReaderSetEof(pReader); - - /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf - ** blocks have already been traversed. */ - assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock ); - if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){ - return SQLITE_OK; - } - - rc = sqlite3Fts3ReadBlock( - p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, - (bIncr ? &pReader->nPopulate : 0) - ); - if( rc!=SQLITE_OK ) return rc; - assert( pReader->pBlob==0 ); - if( bIncr && pReader->nPopulatenNode ){ - pReader->pBlob = p->pSegments; - p->pSegments = 0; - } - pNext = pReader->aNode; - } - - assert( !fts3SegReaderIsPending(pReader) ); - - rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2); - if( rc!=SQLITE_OK ) return rc; - - /* Because of the FTS3_NODE_PADDING bytes of padding, the following is - ** safe (no risk of overread) even if the node data is corrupted. */ - pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix); - pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix); - if( nPrefix<0 || nSuffix<=0 - || &pNext[nSuffix]>&pReader->aNode[pReader->nNode] - ){ - return FTS_CORRUPT_VTAB; - } - - if( nPrefix+nSuffix>pReader->nTermAlloc ){ - int nNew = (nPrefix+nSuffix)*2; - char *zNew = sqlite3_realloc(pReader->zTerm, nNew); - if( !zNew ){ - return SQLITE_NOMEM; - } - pReader->zTerm = zNew; - pReader->nTermAlloc = nNew; - } - - rc = fts3SegReaderRequire(pReader, pNext, nSuffix+FTS3_VARINT_MAX); - if( rc!=SQLITE_OK ) return rc; - - memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix); - pReader->nTerm = nPrefix+nSuffix; - pNext += nSuffix; - pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist); - pReader->aDoclist = pNext; - pReader->pOffsetList = 0; - - /* Check that the doclist does not appear to extend past the end of the - ** b-tree node. And that the final byte of the doclist is 0x00. If either - ** of these statements is untrue, then the data structure is corrupt. - */ - if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode] - || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1]) - ){ - return FTS_CORRUPT_VTAB; - } - return SQLITE_OK; -} - -/* -** Set the SegReader to point to the first docid in the doclist associated -** with the current term. -*/ -static int fts3SegReaderFirstDocid(Fts3Table *pTab, Fts3SegReader *pReader){ - int rc = SQLITE_OK; - assert( pReader->aDoclist ); - assert( !pReader->pOffsetList ); - if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){ - u8 bEof = 0; - pReader->iDocid = 0; - pReader->nOffsetList = 0; - sqlite3Fts3DoclistPrev(0, - pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList, - &pReader->iDocid, &pReader->nOffsetList, &bEof - ); - }else{ - rc = fts3SegReaderRequire(pReader, pReader->aDoclist, FTS3_VARINT_MAX); - if( rc==SQLITE_OK ){ - int n = sqlite3Fts3GetVarint(pReader->aDoclist, &pReader->iDocid); - pReader->pOffsetList = &pReader->aDoclist[n]; - } - } - return rc; -} - -/* -** Advance the SegReader to point to the next docid in the doclist -** associated with the current term. -** -** If arguments ppOffsetList and pnOffsetList are not NULL, then -** *ppOffsetList is set to point to the first column-offset list -** in the doclist entry (i.e. immediately past the docid varint). -** *pnOffsetList is set to the length of the set of column-offset -** lists, not including the nul-terminator byte. For example: -*/ -static int fts3SegReaderNextDocid( - Fts3Table *pTab, - Fts3SegReader *pReader, /* Reader to advance to next docid */ - char **ppOffsetList, /* OUT: Pointer to current position-list */ - int *pnOffsetList /* OUT: Length of *ppOffsetList in bytes */ -){ - int rc = SQLITE_OK; - char *p = pReader->pOffsetList; - char c = 0; - - assert( p ); - - if( pTab->bDescIdx && fts3SegReaderIsPending(pReader) ){ - /* A pending-terms seg-reader for an FTS4 table that uses order=desc. - ** Pending-terms doclists are always built up in ascending order, so - ** we have to iterate through them backwards here. */ - u8 bEof = 0; - if( ppOffsetList ){ - *ppOffsetList = pReader->pOffsetList; - *pnOffsetList = pReader->nOffsetList - 1; - } - sqlite3Fts3DoclistPrev(0, - pReader->aDoclist, pReader->nDoclist, &p, &pReader->iDocid, - &pReader->nOffsetList, &bEof - ); - if( bEof ){ - pReader->pOffsetList = 0; - }else{ - pReader->pOffsetList = p; - } - }else{ - char *pEnd = &pReader->aDoclist[pReader->nDoclist]; - - /* Pointer p currently points at the first byte of an offset list. The - ** following block advances it to point one byte past the end of - ** the same offset list. */ - while( 1 ){ - - /* The following line of code (and the "p++" below the while() loop) is - ** normally all that is required to move pointer p to the desired - ** position. The exception is if this node is being loaded from disk - ** incrementally and pointer "p" now points to the first byte passed - ** the populated part of pReader->aNode[]. - */ - while( *p | c ) c = *p++ & 0x80; - assert( *p==0 ); - - if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break; - rc = fts3SegReaderIncrRead(pReader); - if( rc!=SQLITE_OK ) return rc; - } - p++; - - /* If required, populate the output variables with a pointer to and the - ** size of the previous offset-list. - */ - if( ppOffsetList ){ - *ppOffsetList = pReader->pOffsetList; - *pnOffsetList = (int)(p - pReader->pOffsetList - 1); - } - - /* List may have been edited in place by fts3EvalNearTrim() */ - while( p=pEnd ){ - pReader->pOffsetList = 0; - }else{ - rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX); - if( rc==SQLITE_OK ){ - sqlite3_int64 iDelta; - pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta); - if( pTab->bDescIdx ){ - pReader->iDocid -= iDelta; - }else{ - pReader->iDocid += iDelta; - } - } - } - } - - return SQLITE_OK; -} - - -SQLITE_PRIVATE int sqlite3Fts3MsrOvfl( - Fts3Cursor *pCsr, - Fts3MultiSegReader *pMsr, - int *pnOvfl -){ - Fts3Table *p = (Fts3Table*)pCsr->base.pVtab; - int nOvfl = 0; - int ii; - int rc = SQLITE_OK; - int pgsz = p->nPgsz; - - assert( p->bFts4 ); - assert( pgsz>0 ); - - for(ii=0; rc==SQLITE_OK && iinSegment; ii++){ - Fts3SegReader *pReader = pMsr->apSegment[ii]; - if( !fts3SegReaderIsPending(pReader) - && !fts3SegReaderIsRootOnly(pReader) - ){ - sqlite3_int64 jj; - for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){ - int nBlob; - rc = sqlite3Fts3ReadBlock(p, jj, 0, &nBlob, 0); - if( rc!=SQLITE_OK ) break; - if( (nBlob+35)>pgsz ){ - nOvfl += (nBlob + 34)/pgsz; - } - } - } - } - *pnOvfl = nOvfl; - return rc; -} - -/* -** Free all allocations associated with the iterator passed as the -** second argument. -*/ -SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ - if( pReader && !fts3SegReaderIsPending(pReader) ){ - sqlite3_free(pReader->zTerm); - if( !fts3SegReaderIsRootOnly(pReader) ){ - sqlite3_free(pReader->aNode); - sqlite3_blob_close(pReader->pBlob); - } - } - sqlite3_free(pReader); -} - -/* -** Allocate a new SegReader object. -*/ -SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( - int iAge, /* Segment "age". */ - int bLookup, /* True for a lookup only */ - sqlite3_int64 iStartLeaf, /* First leaf to traverse */ - sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ - sqlite3_int64 iEndBlock, /* Final block of segment */ - const char *zRoot, /* Buffer containing root node */ - int nRoot, /* Size of buffer containing root node */ - Fts3SegReader **ppReader /* OUT: Allocated Fts3SegReader */ -){ - Fts3SegReader *pReader; /* Newly allocated SegReader object */ - int nExtra = 0; /* Bytes to allocate segment root node */ - - assert( iStartLeaf<=iEndLeaf ); - if( iStartLeaf==0 ){ - nExtra = nRoot + FTS3_NODE_PADDING; - } - - pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra); - if( !pReader ){ - return SQLITE_NOMEM; - } - memset(pReader, 0, sizeof(Fts3SegReader)); - pReader->iIdx = iAge; - pReader->bLookup = bLookup!=0; - pReader->iStartBlock = iStartLeaf; - pReader->iLeafEndBlock = iEndLeaf; - pReader->iEndBlock = iEndBlock; - - if( nExtra ){ - /* The entire segment is stored in the root node. */ - pReader->aNode = (char *)&pReader[1]; - pReader->rootOnly = 1; - pReader->nNode = nRoot; - memcpy(pReader->aNode, zRoot, nRoot); - memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING); - }else{ - pReader->iCurrentBlock = iStartLeaf-1; - } - *ppReader = pReader; - return SQLITE_OK; -} - -/* -** This is a comparison function used as a qsort() callback when sorting -** an array of pending terms by term. This occurs as part of flushing -** the contents of the pending-terms hash table to the database. -*/ -static int fts3CompareElemByTerm(const void *lhs, const void *rhs){ - char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); - char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); - int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); - int n2 = fts3HashKeysize(*(Fts3HashElem **)rhs); - - int n = (n1aIndex */ - const char *zTerm, /* Term to search for */ - int nTerm, /* Size of buffer zTerm */ - int bPrefix, /* True for a prefix iterator */ - Fts3SegReader **ppReader /* OUT: SegReader for pending-terms */ -){ - Fts3SegReader *pReader = 0; /* Fts3SegReader object to return */ - Fts3HashElem *pE; /* Iterator variable */ - Fts3HashElem **aElem = 0; /* Array of term hash entries to scan */ - int nElem = 0; /* Size of array at aElem */ - int rc = SQLITE_OK; /* Return Code */ - Fts3Hash *pHash; - - pHash = &p->aIndex[iIndex].hPending; - if( bPrefix ){ - int nAlloc = 0; /* Size of allocated array at aElem */ - - for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){ - char *zKey = (char *)fts3HashKey(pE); - int nKey = fts3HashKeysize(pE); - if( nTerm==0 || (nKey>=nTerm && 0==memcmp(zKey, zTerm, nTerm)) ){ - if( nElem==nAlloc ){ - Fts3HashElem **aElem2; - nAlloc += 16; - aElem2 = (Fts3HashElem **)sqlite3_realloc( - aElem, nAlloc*sizeof(Fts3HashElem *) - ); - if( !aElem2 ){ - rc = SQLITE_NOMEM; - nElem = 0; - break; - } - aElem = aElem2; - } - - aElem[nElem++] = pE; - } - } - - /* If more than one term matches the prefix, sort the Fts3HashElem - ** objects in term order using qsort(). This uses the same comparison - ** callback as is used when flushing terms to disk. - */ - if( nElem>1 ){ - qsort(aElem, nElem, sizeof(Fts3HashElem *), fts3CompareElemByTerm); - } - - }else{ - /* The query is a simple term lookup that matches at most one term in - ** the index. All that is required is a straight hash-lookup. - ** - ** Because the stack address of pE may be accessed via the aElem pointer - ** below, the "Fts3HashElem *pE" must be declared so that it is valid - ** within this entire function, not just this "else{...}" block. - */ - pE = fts3HashFindElem(pHash, zTerm, nTerm); - if( pE ){ - aElem = &pE; - nElem = 1; - } - } - - if( nElem>0 ){ - int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); - pReader = (Fts3SegReader *)sqlite3_malloc(nByte); - if( !pReader ){ - rc = SQLITE_NOMEM; - }else{ - memset(pReader, 0, nByte); - pReader->iIdx = 0x7FFFFFFF; - pReader->ppNextElem = (Fts3HashElem **)&pReader[1]; - memcpy(pReader->ppNextElem, aElem, nElem*sizeof(Fts3HashElem *)); - } - } - - if( bPrefix ){ - sqlite3_free(aElem); - } - *ppReader = pReader; - return rc; -} - -/* -** Compare the entries pointed to by two Fts3SegReader structures. -** Comparison is as follows: -** -** 1) EOF is greater than not EOF. -** -** 2) The current terms (if any) are compared using memcmp(). If one -** term is a prefix of another, the longer term is considered the -** larger. -** -** 3) By segment age. An older segment is considered larger. -*/ -static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc; - if( pLhs->aNode && pRhs->aNode ){ - int rc2 = pLhs->nTerm - pRhs->nTerm; - if( rc2<0 ){ - rc = memcmp(pLhs->zTerm, pRhs->zTerm, pLhs->nTerm); - }else{ - rc = memcmp(pLhs->zTerm, pRhs->zTerm, pRhs->nTerm); - } - if( rc==0 ){ - rc = rc2; - } - }else{ - rc = (pLhs->aNode==0) - (pRhs->aNode==0); - } - if( rc==0 ){ - rc = pRhs->iIdx - pLhs->iIdx; - } - assert( rc!=0 ); - return rc; -} - -/* -** A different comparison function for SegReader structures. In this -** version, it is assumed that each SegReader points to an entry in -** a doclist for identical terms. Comparison is made as follows: -** -** 1) EOF (end of doclist in this case) is greater than not EOF. -** -** 2) By current docid. -** -** 3) By segment age. An older segment is considered larger. -*/ -static int fts3SegReaderDoclistCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0); - if( rc==0 ){ - if( pLhs->iDocid==pRhs->iDocid ){ - rc = pRhs->iIdx - pLhs->iIdx; - }else{ - rc = (pLhs->iDocid > pRhs->iDocid) ? 1 : -1; - } - } - assert( pLhs->aNode && pRhs->aNode ); - return rc; -} -static int fts3SegReaderDoclistCmpRev(Fts3SegReader *pLhs, Fts3SegReader *pRhs){ - int rc = (pLhs->pOffsetList==0)-(pRhs->pOffsetList==0); - if( rc==0 ){ - if( pLhs->iDocid==pRhs->iDocid ){ - rc = pRhs->iIdx - pLhs->iIdx; - }else{ - rc = (pLhs->iDocid < pRhs->iDocid) ? 1 : -1; - } - } - assert( pLhs->aNode && pRhs->aNode ); - return rc; -} - -/* -** Compare the term that the Fts3SegReader object passed as the first argument -** points to with the term specified by arguments zTerm and nTerm. -** -** If the pSeg iterator is already at EOF, return 0. Otherwise, return -** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are -** equal, or +ve if the pSeg term is greater than zTerm/nTerm. -*/ -static int fts3SegReaderTermCmp( - Fts3SegReader *pSeg, /* Segment reader object */ - const char *zTerm, /* Term to compare to */ - int nTerm /* Size of term zTerm in bytes */ -){ - int res = 0; - if( pSeg->aNode ){ - if( pSeg->nTerm>nTerm ){ - res = memcmp(pSeg->zTerm, zTerm, nTerm); - }else{ - res = memcmp(pSeg->zTerm, zTerm, pSeg->nTerm); - } - if( res==0 ){ - res = pSeg->nTerm-nTerm; - } - } - return res; -} - -/* -** Argument apSegment is an array of nSegment elements. It is known that -** the final (nSegment-nSuspect) members are already in sorted order -** (according to the comparison function provided). This function shuffles -** the array around until all entries are in sorted order. -*/ -static void fts3SegReaderSort( - Fts3SegReader **apSegment, /* Array to sort entries of */ - int nSegment, /* Size of apSegment array */ - int nSuspect, /* Unsorted entry count */ - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) /* Comparison function */ -){ - int i; /* Iterator variable */ - - assert( nSuspect<=nSegment ); - - if( nSuspect==nSegment ) nSuspect--; - for(i=nSuspect-1; i>=0; i--){ - int j; - for(j=i; j<(nSegment-1); j++){ - Fts3SegReader *pTmp; - if( xCmp(apSegment[j], apSegment[j+1])<0 ) break; - pTmp = apSegment[j+1]; - apSegment[j+1] = apSegment[j]; - apSegment[j] = pTmp; - } - } - -#ifndef NDEBUG - /* Check that the list really is sorted now. */ - for(i=0; i<(nSuspect-1); i++){ - assert( xCmp(apSegment[i], apSegment[i+1])<0 ); - } -#endif -} - -/* -** Insert a record into the %_segments table. -*/ -static int fts3WriteSegment( - Fts3Table *p, /* Virtual table handle */ - sqlite3_int64 iBlock, /* Block id for new block */ - char *z, /* Pointer to buffer containing block data */ - int n /* Size of buffer z in bytes */ -){ - sqlite3_stmt *pStmt; - int rc = fts3SqlStmt(p, SQL_INSERT_SEGMENTS, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, iBlock); - sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - } - return rc; -} - -/* -** Find the largest relative level number in the table. If successful, set -** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs, -** set *pnMax to zero and return an SQLite error code. -*/ -SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){ - int rc; - int mxLevel = 0; - sqlite3_stmt *pStmt = 0; - - rc = fts3SqlStmt(p, SQL_SELECT_MXLEVEL, &pStmt, 0); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - mxLevel = sqlite3_column_int(pStmt, 0); - } - rc = sqlite3_reset(pStmt); - } - *pnMax = mxLevel; - return rc; -} - -/* -** Insert a record into the %_segdir table. -*/ -static int fts3WriteSegdir( - Fts3Table *p, /* Virtual table handle */ - sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */ - int iIdx, /* Value for "idx" field */ - sqlite3_int64 iStartBlock, /* Value for "start_block" field */ - sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */ - sqlite3_int64 iEndBlock, /* Value for "end_block" field */ - char *zRoot, /* Blob value for "root" field */ - int nRoot /* Number of bytes in buffer zRoot */ -){ - sqlite3_stmt *pStmt; - int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pStmt, 1, iLevel); - sqlite3_bind_int(pStmt, 2, iIdx); - sqlite3_bind_int64(pStmt, 3, iStartBlock); - sqlite3_bind_int64(pStmt, 4, iLeafEndBlock); - sqlite3_bind_int64(pStmt, 5, iEndBlock); - sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - } - return rc; -} - -/* -** Return the size of the common prefix (if any) shared by zPrev and -** zNext, in bytes. For example, -** -** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3 -** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2 -** fts3PrefixCompress("abX", 3, "Xbcdef", 6) // returns 0 -*/ -static int fts3PrefixCompress( - const char *zPrev, /* Buffer containing previous term */ - int nPrev, /* Size of buffer zPrev in bytes */ - const char *zNext, /* Buffer containing next term */ - int nNext /* Size of buffer zNext in bytes */ -){ - int n; - UNUSED_PARAMETER(nNext); - for(n=0; nnData; /* Current size of node in bytes */ - int nReq = nData; /* Required space after adding zTerm */ - int nPrefix; /* Number of bytes of prefix compression */ - int nSuffix; /* Suffix length */ - - nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm); - nSuffix = nTerm-nPrefix; - - nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix; - if( nReq<=p->nNodeSize || !pTree->zTerm ){ - - if( nReq>p->nNodeSize ){ - /* An unusual case: this is the first term to be added to the node - ** and the static node buffer (p->nNodeSize bytes) is not large - ** enough. Use a separately malloced buffer instead This wastes - ** p->nNodeSize bytes, but since this scenario only comes about when - ** the database contain two terms that share a prefix of almost 2KB, - ** this is not expected to be a serious problem. - */ - assert( pTree->aData==(char *)&pTree[1] ); - pTree->aData = (char *)sqlite3_malloc(nReq); - if( !pTree->aData ){ - return SQLITE_NOMEM; - } - } - - if( pTree->zTerm ){ - /* There is no prefix-length field for first term in a node */ - nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nPrefix); - } - - nData += sqlite3Fts3PutVarint(&pTree->aData[nData], nSuffix); - memcpy(&pTree->aData[nData], &zTerm[nPrefix], nSuffix); - pTree->nData = nData + nSuffix; - pTree->nEntry++; - - if( isCopyTerm ){ - if( pTree->nMalloczMalloc, nTerm*2); - if( !zNew ){ - return SQLITE_NOMEM; - } - pTree->nMalloc = nTerm*2; - pTree->zMalloc = zNew; - } - pTree->zTerm = pTree->zMalloc; - memcpy(pTree->zTerm, zTerm, nTerm); - pTree->nTerm = nTerm; - }else{ - pTree->zTerm = (char *)zTerm; - pTree->nTerm = nTerm; - } - return SQLITE_OK; - } - } - - /* If control flows to here, it was not possible to append zTerm to the - ** current node. Create a new node (a right-sibling of the current node). - ** If this is the first node in the tree, the term is added to it. - ** - ** Otherwise, the term is not added to the new node, it is left empty for - ** now. Instead, the term is inserted into the parent of pTree. If pTree - ** has no parent, one is created here. - */ - pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize); - if( !pNew ){ - return SQLITE_NOMEM; - } - memset(pNew, 0, sizeof(SegmentNode)); - pNew->nData = 1 + FTS3_VARINT_MAX; - pNew->aData = (char *)&pNew[1]; - - if( pTree ){ - SegmentNode *pParent = pTree->pParent; - rc = fts3NodeAddTerm(p, &pParent, isCopyTerm, zTerm, nTerm); - if( pTree->pParent==0 ){ - pTree->pParent = pParent; - } - pTree->pRight = pNew; - pNew->pLeftmost = pTree->pLeftmost; - pNew->pParent = pParent; - pNew->zMalloc = pTree->zMalloc; - pNew->nMalloc = pTree->nMalloc; - pTree->zMalloc = 0; - }else{ - pNew->pLeftmost = pNew; - rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm); - } - - *ppTree = pNew; - return rc; -} - -/* -** Helper function for fts3NodeWrite(). -*/ -static int fts3TreeFinishNode( - SegmentNode *pTree, - int iHeight, - sqlite3_int64 iLeftChild -){ - int nStart; - assert( iHeight>=1 && iHeight<128 ); - nStart = FTS3_VARINT_MAX - sqlite3Fts3VarintLen(iLeftChild); - pTree->aData[nStart] = (char)iHeight; - sqlite3Fts3PutVarint(&pTree->aData[nStart+1], iLeftChild); - return nStart; -} - -/* -** Write the buffer for the segment node pTree and all of its peers to the -** database. Then call this function recursively to write the parent of -** pTree and its peers to the database. -** -** Except, if pTree is a root node, do not write it to the database. Instead, -** set output variables *paRoot and *pnRoot to contain the root node. -** -** If successful, SQLITE_OK is returned and output variable *piLast is -** set to the largest blockid written to the database (or zero if no -** blocks were written to the db). Otherwise, an SQLite error code is -** returned. -*/ -static int fts3NodeWrite( - Fts3Table *p, /* Virtual table handle */ - SegmentNode *pTree, /* SegmentNode handle */ - int iHeight, /* Height of this node in tree */ - sqlite3_int64 iLeaf, /* Block id of first leaf node */ - sqlite3_int64 iFree, /* Block id of next free slot in %_segments */ - sqlite3_int64 *piLast, /* OUT: Block id of last entry written */ - char **paRoot, /* OUT: Data for root node */ - int *pnRoot /* OUT: Size of root node in bytes */ -){ - int rc = SQLITE_OK; - - if( !pTree->pParent ){ - /* Root node of the tree. */ - int nStart = fts3TreeFinishNode(pTree, iHeight, iLeaf); - *piLast = iFree-1; - *pnRoot = pTree->nData - nStart; - *paRoot = &pTree->aData[nStart]; - }else{ - SegmentNode *pIter; - sqlite3_int64 iNextFree = iFree; - sqlite3_int64 iNextLeaf = iLeaf; - for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){ - int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf); - int nWrite = pIter->nData - nStart; - - rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite); - iNextFree++; - iNextLeaf += (pIter->nEntry+1); - } - if( rc==SQLITE_OK ){ - assert( iNextLeaf==iFree ); - rc = fts3NodeWrite( - p, pTree->pParent, iHeight+1, iFree, iNextFree, piLast, paRoot, pnRoot - ); - } - } - - return rc; -} - -/* -** Free all memory allocations associated with the tree pTree. -*/ -static void fts3NodeFree(SegmentNode *pTree){ - if( pTree ){ - SegmentNode *p = pTree->pLeftmost; - fts3NodeFree(p->pParent); - while( p ){ - SegmentNode *pRight = p->pRight; - if( p->aData!=(char *)&p[1] ){ - sqlite3_free(p->aData); - } - assert( pRight==0 || p->zMalloc==0 ); - sqlite3_free(p->zMalloc); - sqlite3_free(p); - p = pRight; - } - } -} - -/* -** Add a term to the segment being constructed by the SegmentWriter object -** *ppWriter. When adding the first term to a segment, *ppWriter should -** be passed NULL. This function will allocate a new SegmentWriter object -** and return it via the input/output variable *ppWriter in this case. -** -** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. -*/ -static int fts3SegWriterAdd( - Fts3Table *p, /* Virtual table handle */ - SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */ - int isCopyTerm, /* True if buffer zTerm must be copied */ - const char *zTerm, /* Pointer to buffer containing term */ - int nTerm, /* Size of term in bytes */ - const char *aDoclist, /* Pointer to buffer containing doclist */ - int nDoclist /* Size of doclist in bytes */ -){ - int nPrefix; /* Size of term prefix in bytes */ - int nSuffix; /* Size of term suffix in bytes */ - int nReq; /* Number of bytes required on leaf page */ - int nData; - SegmentWriter *pWriter = *ppWriter; - - if( !pWriter ){ - int rc; - sqlite3_stmt *pStmt; - - /* Allocate the SegmentWriter structure */ - pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter)); - if( !pWriter ) return SQLITE_NOMEM; - memset(pWriter, 0, sizeof(SegmentWriter)); - *ppWriter = pWriter; - - /* Allocate a buffer in which to accumulate data */ - pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize); - if( !pWriter->aData ) return SQLITE_NOMEM; - pWriter->nSize = p->nNodeSize; - - /* Find the next free blockid in the %_segments table */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - pWriter->iFree = sqlite3_column_int64(pStmt, 0); - pWriter->iFirst = pWriter->iFree; - } - rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ) return rc; - } - nData = pWriter->nData; - - nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm); - nSuffix = nTerm-nPrefix; - - /* Figure out how many bytes are required by this new entry */ - nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */ - sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */ - nSuffix + /* Term suffix */ - sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ - nDoclist; /* Doclist data */ - - if( nData>0 && nData+nReq>p->nNodeSize ){ - int rc; - - /* The current leaf node is full. Write it out to the database. */ - rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); - if( rc!=SQLITE_OK ) return rc; - p->nLeafAdd++; - - /* Add the current term to the interior node tree. The term added to - ** the interior tree must: - ** - ** a) be greater than the largest term on the leaf node just written - ** to the database (still available in pWriter->zTerm), and - ** - ** b) be less than or equal to the term about to be added to the new - ** leaf node (zTerm/nTerm). - ** - ** In other words, it must be the prefix of zTerm 1 byte longer than - ** the common prefix (if any) of zTerm and pWriter->zTerm. - */ - assert( nPrefixpTree, isCopyTerm, zTerm, nPrefix+1); - if( rc!=SQLITE_OK ) return rc; - - nData = 0; - pWriter->nTerm = 0; - - nPrefix = 0; - nSuffix = nTerm; - nReq = 1 + /* varint containing prefix size */ - sqlite3Fts3VarintLen(nTerm) + /* varint containing suffix size */ - nTerm + /* Term suffix */ - sqlite3Fts3VarintLen(nDoclist) + /* Size of doclist */ - nDoclist; /* Doclist data */ - } - - /* If the buffer currently allocated is too small for this entry, realloc - ** the buffer to make it large enough. - */ - if( nReq>pWriter->nSize ){ - char *aNew = sqlite3_realloc(pWriter->aData, nReq); - if( !aNew ) return SQLITE_NOMEM; - pWriter->aData = aNew; - pWriter->nSize = nReq; - } - assert( nData+nReq<=pWriter->nSize ); - - /* Append the prefix-compressed term and doclist to the buffer. */ - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix); - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix); - memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix); - nData += nSuffix; - nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist); - memcpy(&pWriter->aData[nData], aDoclist, nDoclist); - pWriter->nData = nData + nDoclist; - - /* Save the current term so that it can be used to prefix-compress the next. - ** If the isCopyTerm parameter is true, then the buffer pointed to by - ** zTerm is transient, so take a copy of the term data. Otherwise, just - ** store a copy of the pointer. - */ - if( isCopyTerm ){ - if( nTerm>pWriter->nMalloc ){ - char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2); - if( !zNew ){ - return SQLITE_NOMEM; - } - pWriter->nMalloc = nTerm*2; - pWriter->zMalloc = zNew; - pWriter->zTerm = zNew; - } - assert( pWriter->zTerm==pWriter->zMalloc ); - memcpy(pWriter->zTerm, zTerm, nTerm); - }else{ - pWriter->zTerm = (char *)zTerm; - } - pWriter->nTerm = nTerm; - - return SQLITE_OK; -} - -/* -** Flush all data associated with the SegmentWriter object pWriter to the -** database. This function must be called after all terms have been added -** to the segment using fts3SegWriterAdd(). If successful, SQLITE_OK is -** returned. Otherwise, an SQLite error code. -*/ -static int fts3SegWriterFlush( - Fts3Table *p, /* Virtual table handle */ - SegmentWriter *pWriter, /* SegmentWriter to flush to the db */ - sqlite3_int64 iLevel, /* Value for 'level' column of %_segdir */ - int iIdx /* Value for 'idx' column of %_segdir */ -){ - int rc; /* Return code */ - if( pWriter->pTree ){ - sqlite3_int64 iLast = 0; /* Largest block id written to database */ - sqlite3_int64 iLastLeaf; /* Largest leaf block id written to db */ - char *zRoot = NULL; /* Pointer to buffer containing root node */ - int nRoot = 0; /* Size of buffer zRoot */ - - iLastLeaf = pWriter->iFree; - rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, pWriter->nData); - if( rc==SQLITE_OK ){ - rc = fts3NodeWrite(p, pWriter->pTree, 1, - pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot); - } - if( rc==SQLITE_OK ){ - rc = fts3WriteSegdir( - p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot); - } - }else{ - /* The entire tree fits on the root node. Write it to the segdir table. */ - rc = fts3WriteSegdir( - p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData); - } - p->nLeafAdd++; - return rc; -} - -/* -** Release all memory held by the SegmentWriter object passed as the -** first argument. -*/ -static void fts3SegWriterFree(SegmentWriter *pWriter){ - if( pWriter ){ - sqlite3_free(pWriter->aData); - sqlite3_free(pWriter->zMalloc); - fts3NodeFree(pWriter->pTree); - sqlite3_free(pWriter); - } -} - -/* -** The first value in the apVal[] array is assumed to contain an integer. -** This function tests if there exist any documents with docid values that -** are different from that integer. i.e. if deleting the document with docid -** pRowid would mean the FTS3 table were empty. -** -** If successful, *pisEmpty is set to true if the table is empty except for -** document pRowid, or false otherwise, and SQLITE_OK is returned. If an -** error occurs, an SQLite error code is returned. -*/ -static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){ - sqlite3_stmt *pStmt; - int rc; - if( p->zContentTbl ){ - /* If using the content=xxx option, assume the table is never empty */ - *pisEmpty = 0; - rc = SQLITE_OK; - }else{ - rc = fts3SqlStmt(p, SQL_IS_EMPTY, &pStmt, &pRowid); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pisEmpty = sqlite3_column_int(pStmt, 0); - } - rc = sqlite3_reset(pStmt); - } - } - return rc; -} - -/* -** Set *pnMax to the largest segment level in the database for the index -** iIndex. -** -** Segment levels are stored in the 'level' column of the %_segdir table. -** -** Return SQLITE_OK if successful, or an SQLite error code if not. -*/ -static int fts3SegmentMaxLevel( - Fts3Table *p, - int iLangid, - int iIndex, - sqlite3_int64 *pnMax -){ - sqlite3_stmt *pStmt; - int rc; - assert( iIndex>=0 && iIndexnIndex ); - - /* Set pStmt to the compiled version of: - ** - ** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? - ** - ** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR). - */ - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); - if( rc!=SQLITE_OK ) return rc; - sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pStmt, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pnMax = sqlite3_column_int64(pStmt, 0); - } - return sqlite3_reset(pStmt); -} - -/* -** Delete all entries in the %_segments table associated with the segment -** opened with seg-reader pSeg. This function does not affect the contents -** of the %_segdir table. -*/ -static int fts3DeleteSegment( - Fts3Table *p, /* FTS table handle */ - Fts3SegReader *pSeg /* Segment to delete */ -){ - int rc = SQLITE_OK; /* Return code */ - if( pSeg->iStartBlock ){ - sqlite3_stmt *pDelete; /* SQL statement to delete rows */ - rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, pSeg->iStartBlock); - sqlite3_bind_int64(pDelete, 2, pSeg->iEndBlock); - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - } - return rc; -} - -/* -** This function is used after merging multiple segments into a single large -** segment to delete the old, now redundant, segment b-trees. Specifically, -** it: -** -** 1) Deletes all %_segments entries for the segments associated with -** each of the SegReader objects in the array passed as the third -** argument, and -** -** 2) deletes all %_segdir entries with level iLevel, or all %_segdir -** entries regardless of level if (iLevel<0). -** -** SQLITE_OK is returned if successful, otherwise an SQLite error code. -*/ -static int fts3DeleteSegdir( - Fts3Table *p, /* Virtual table handle */ - int iLangid, /* Language id */ - int iIndex, /* Index for p->aIndex */ - int iLevel, /* Level of %_segdir entries to delete */ - Fts3SegReader **apSegment, /* Array of SegReader objects */ - int nReader /* Size of array apSegment */ -){ - int rc = SQLITE_OK; /* Return Code */ - int i; /* Iterator variable */ - sqlite3_stmt *pDelete = 0; /* SQL statement to delete rows */ - - for(i=0; rc==SQLITE_OK && i=0 || iLevel==FTS3_SEGCURSOR_ALL ); - if( iLevel==FTS3_SEGCURSOR_ALL ){ - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); - sqlite3_bind_int64(pDelete, 2, - getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) - ); - } - }else{ - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64( - pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) - ); - } - } - - if( rc==SQLITE_OK ){ - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - - return rc; -} - -/* -** When this function is called, buffer *ppList (size *pnList bytes) contains -** a position list that may (or may not) feature multiple columns. This -** function adjusts the pointer *ppList and the length *pnList so that they -** identify the subset of the position list that corresponds to column iCol. -** -** If there are no entries in the input position list for column iCol, then -** *pnList is set to zero before returning. -** -** If parameter bZero is non-zero, then any part of the input list following -** the end of the output list is zeroed before returning. -*/ -static void fts3ColumnFilter( - int iCol, /* Column to filter on */ - int bZero, /* Zero out anything following *ppList */ - char **ppList, /* IN/OUT: Pointer to position list */ - int *pnList /* IN/OUT: Size of buffer *ppList in bytes */ -){ - char *pList = *ppList; - int nList = *pnList; - char *pEnd = &pList[nList]; - int iCurrent = 0; - char *p = pList; - - assert( iCol>=0 ); - while( 1 ){ - char c = 0; - while( ppMsr->nBuffer ){ - char *pNew; - pMsr->nBuffer = nList*2; - pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer); - if( !pNew ) return SQLITE_NOMEM; - pMsr->aBuffer = pNew; - } - - memcpy(pMsr->aBuffer, pList, nList); - return SQLITE_OK; -} - -SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ - sqlite3_int64 *piDocid, /* OUT: Docid value */ - char **paPoslist, /* OUT: Pointer to position list */ - int *pnPoslist /* OUT: Size of position list in bytes */ -){ - int nMerge = pMsr->nAdvance; - Fts3SegReader **apSegment = pMsr->apSegment; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - if( nMerge==0 ){ - *paPoslist = 0; - return SQLITE_OK; - } - - while( 1 ){ - Fts3SegReader *pSeg; - pSeg = pMsr->apSegment[0]; - - if( pSeg->pOffsetList==0 ){ - *paPoslist = 0; - break; - }else{ - int rc; - char *pList; - int nList; - int j; - sqlite3_int64 iDocid = apSegment[0]->iDocid; - - rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList); - j = 1; - while( rc==SQLITE_OK - && jpOffsetList - && apSegment[j]->iDocid==iDocid - ){ - rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0); - j++; - } - if( rc!=SQLITE_OK ) return rc; - fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp); - - if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pMsr, pList, nList+1); - if( rc!=SQLITE_OK ) return rc; - assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 ); - pList = pMsr->aBuffer; - } - - if( pMsr->iColFilter>=0 ){ - fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList); - } - - if( nList>0 ){ - *paPoslist = pList; - *piDocid = iDocid; - *pnPoslist = nList; - break; - } - } - } - - return SQLITE_OK; -} - -static int fts3SegReaderStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - const char *zTerm, /* Term searched for (or NULL) */ - int nTerm /* Length of zTerm in bytes */ -){ - int i; - int nSeg = pCsr->nSegment; - - /* If the Fts3SegFilter defines a specific term (or term prefix) to search - ** for, then advance each segment iterator until it points to a term of - ** equal or greater value than the specified term. This prevents many - ** unnecessary merge/sort operations for the case where single segment - ** b-tree leaf nodes contain more than one term. - */ - for(i=0; pCsr->bRestart==0 && inSegment; i++){ - int res = 0; - Fts3SegReader *pSeg = pCsr->apSegment[i]; - do { - int rc = fts3SegReaderNext(p, pSeg, 0); - if( rc!=SQLITE_OK ) return rc; - }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 ); - - if( pSeg->bLookup && res!=0 ){ - fts3SegReaderSetEof(pSeg); - } - } - fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp); - - return SQLITE_OK; -} - -SQLITE_PRIVATE int sqlite3Fts3SegReaderStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - Fts3SegFilter *pFilter /* Restrictions on range of iteration */ -){ - pCsr->pFilter = pFilter; - return fts3SegReaderStart(p, pCsr, pFilter->zTerm, pFilter->nTerm); -} - -SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr, /* Cursor object */ - int iCol, /* Column to match on. */ - const char *zTerm, /* Term to iterate through a doclist for */ - int nTerm /* Number of bytes in zTerm */ -){ - int i; - int rc; - int nSegment = pCsr->nSegment; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - assert( pCsr->pFilter==0 ); - assert( zTerm && nTerm>0 ); - - /* Advance each segment iterator until it points to the term zTerm/nTerm. */ - rc = fts3SegReaderStart(p, pCsr, zTerm, nTerm); - if( rc!=SQLITE_OK ) return rc; - - /* Determine how many of the segments actually point to zTerm/nTerm. */ - for(i=0; iapSegment[i]; - if( !pSeg->aNode || fts3SegReaderTermCmp(pSeg, zTerm, nTerm) ){ - break; - } - } - pCsr->nAdvance = i; - - /* Advance each of the segments to point to the first docid. */ - for(i=0; inAdvance; i++){ - rc = fts3SegReaderFirstDocid(p, pCsr->apSegment[i]); - if( rc!=SQLITE_OK ) return rc; - } - fts3SegReaderSort(pCsr->apSegment, i, i, xCmp); - - assert( iCol<0 || iColnColumn ); - pCsr->iColFilter = iCol; - - return SQLITE_OK; -} - -/* -** This function is called on a MultiSegReader that has been started using -** sqlite3Fts3MsrIncrStart(). One or more calls to MsrIncrNext() may also -** have been made. Calling this function puts the MultiSegReader in such -** a state that if the next two calls are: -** -** sqlite3Fts3SegReaderStart() -** sqlite3Fts3SegReaderStep() -** -** then the entire doclist for the term is available in -** MultiSegReader.aDoclist/nDoclist. -*/ -SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){ - int i; /* Used to iterate through segment-readers */ - - assert( pCsr->zTerm==0 ); - assert( pCsr->nTerm==0 ); - assert( pCsr->aDoclist==0 ); - assert( pCsr->nDoclist==0 ); - - pCsr->nAdvance = 0; - pCsr->bRestart = 1; - for(i=0; inSegment; i++){ - pCsr->apSegment[i]->pOffsetList = 0; - pCsr->apSegment[i]->nOffsetList = 0; - pCsr->apSegment[i]->iDocid = 0; - } - - return SQLITE_OK; -} - - -SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( - Fts3Table *p, /* Virtual table handle */ - Fts3MultiSegReader *pCsr /* Cursor object */ -){ - int rc = SQLITE_OK; - - int isIgnoreEmpty = (pCsr->pFilter->flags & FTS3_SEGMENT_IGNORE_EMPTY); - int isRequirePos = (pCsr->pFilter->flags & FTS3_SEGMENT_REQUIRE_POS); - int isColFilter = (pCsr->pFilter->flags & FTS3_SEGMENT_COLUMN_FILTER); - int isPrefix = (pCsr->pFilter->flags & FTS3_SEGMENT_PREFIX); - int isScan = (pCsr->pFilter->flags & FTS3_SEGMENT_SCAN); - int isFirst = (pCsr->pFilter->flags & FTS3_SEGMENT_FIRST); - - Fts3SegReader **apSegment = pCsr->apSegment; - int nSegment = pCsr->nSegment; - Fts3SegFilter *pFilter = pCsr->pFilter; - int (*xCmp)(Fts3SegReader *, Fts3SegReader *) = ( - p->bDescIdx ? fts3SegReaderDoclistCmpRev : fts3SegReaderDoclistCmp - ); - - if( pCsr->nSegment==0 ) return SQLITE_OK; - - do { - int nMerge; - int i; - - /* Advance the first pCsr->nAdvance entries in the apSegment[] array - ** forward. Then sort the list in order of current term again. - */ - for(i=0; inAdvance; i++){ - Fts3SegReader *pSeg = apSegment[i]; - if( pSeg->bLookup ){ - fts3SegReaderSetEof(pSeg); - }else{ - rc = fts3SegReaderNext(p, pSeg, 0); - } - if( rc!=SQLITE_OK ) return rc; - } - fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp); - pCsr->nAdvance = 0; - - /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */ - assert( rc==SQLITE_OK ); - if( apSegment[0]->aNode==0 ) break; - - pCsr->nTerm = apSegment[0]->nTerm; - pCsr->zTerm = apSegment[0]->zTerm; - - /* If this is a prefix-search, and if the term that apSegment[0] points - ** to does not share a suffix with pFilter->zTerm/nTerm, then all - ** required callbacks have been made. In this case exit early. - ** - ** Similarly, if this is a search for an exact match, and the first term - ** of segment apSegment[0] is not a match, exit early. - */ - if( pFilter->zTerm && !isScan ){ - if( pCsr->nTermnTerm - || (!isPrefix && pCsr->nTerm>pFilter->nTerm) - || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm) - ){ - break; - } - } - - nMerge = 1; - while( nMergeaNode - && apSegment[nMerge]->nTerm==pCsr->nTerm - && 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm) - ){ - nMerge++; - } - - assert( isIgnoreEmpty || (isRequirePos && !isColFilter) ); - if( nMerge==1 - && !isIgnoreEmpty - && !isFirst - && (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0) - ){ - pCsr->nDoclist = apSegment[0]->nDoclist; - if( fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist); - pCsr->aDoclist = pCsr->aBuffer; - }else{ - pCsr->aDoclist = apSegment[0]->aDoclist; - } - if( rc==SQLITE_OK ) rc = SQLITE_ROW; - }else{ - int nDoclist = 0; /* Size of doclist */ - sqlite3_int64 iPrev = 0; /* Previous docid stored in doclist */ - - /* The current term of the first nMerge entries in the array - ** of Fts3SegReader objects is the same. The doclists must be merged - ** and a single term returned with the merged doclist. - */ - for(i=0; ipOffsetList ){ - int j; /* Number of segments that share a docid */ - char *pList; - int nList; - int nByte; - sqlite3_int64 iDocid = apSegment[0]->iDocid; - fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList); - j = 1; - while( jpOffsetList - && apSegment[j]->iDocid==iDocid - ){ - fts3SegReaderNextDocid(p, apSegment[j], 0, 0); - j++; - } - - if( isColFilter ){ - fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList); - } - - if( !isIgnoreEmpty || nList>0 ){ - - /* Calculate the 'docid' delta value to write into the merged - ** doclist. */ - sqlite3_int64 iDelta; - if( p->bDescIdx && nDoclist>0 ){ - iDelta = iPrev - iDocid; - }else{ - iDelta = iDocid - iPrev; - } - assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) ); - assert( nDoclist>0 || iDelta==iDocid ); - - nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0); - if( nDoclist+nByte>pCsr->nBuffer ){ - char *aNew; - pCsr->nBuffer = (nDoclist+nByte)*2; - aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer); - if( !aNew ){ - return SQLITE_NOMEM; - } - pCsr->aBuffer = aNew; - } - - if( isFirst ){ - char *a = &pCsr->aBuffer[nDoclist]; - int nWrite; - - nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a); - if( nWrite ){ - iPrev = iDocid; - nDoclist += nWrite; - } - }else{ - nDoclist += sqlite3Fts3PutVarint(&pCsr->aBuffer[nDoclist], iDelta); - iPrev = iDocid; - if( isRequirePos ){ - memcpy(&pCsr->aBuffer[nDoclist], pList, nList); - nDoclist += nList; - pCsr->aBuffer[nDoclist++] = '\0'; - } - } - } - - fts3SegReaderSort(apSegment, nMerge, j, xCmp); - } - if( nDoclist>0 ){ - pCsr->aDoclist = pCsr->aBuffer; - pCsr->nDoclist = nDoclist; - rc = SQLITE_ROW; - } - } - pCsr->nAdvance = nMerge; - }while( rc==SQLITE_OK ); - - return rc; -} - - -SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish( - Fts3MultiSegReader *pCsr /* Cursor object */ -){ - if( pCsr ){ - int i; - for(i=0; inSegment; i++){ - sqlite3Fts3SegReaderFree(pCsr->apSegment[i]); - } - sqlite3_free(pCsr->apSegment); - sqlite3_free(pCsr->aBuffer); - - pCsr->nSegment = 0; - pCsr->apSegment = 0; - pCsr->aBuffer = 0; - } -} - -/* -** Merge all level iLevel segments in the database into a single -** iLevel+1 segment. Or, if iLevel<0, merge all segments into a -** single segment with a level equal to the numerically largest level -** currently present in the database. -** -** If this function is called with iLevel<0, but there is only one -** segment in the database, SQLITE_DONE is returned immediately. -** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, -** an SQLite error code is returned. -*/ -static int fts3SegmentMerge( - Fts3Table *p, - int iLangid, /* Language id to merge */ - int iIndex, /* Index in p->aIndex[] to merge */ - int iLevel /* Level to merge */ -){ - int rc; /* Return code */ - int iIdx = 0; /* Index of new segment */ - sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */ - SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ - Fts3SegFilter filter; /* Segment term filter condition */ - Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ - int bIgnoreEmpty = 0; /* True to ignore empty segments */ - - assert( iLevel==FTS3_SEGCURSOR_ALL - || iLevel==FTS3_SEGCURSOR_PENDING - || iLevel>=0 - ); - assert( iLevel=0 && iIndexnIndex ); - - rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr); - if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; - - if( iLevel==FTS3_SEGCURSOR_ALL ){ - /* This call is to merge all segments in the database to a single - ** segment. The level of the new segment is equal to the numerically - ** greatest segment level currently present in the database for this - ** index. The idx of the new segment is always 0. */ - if( csr.nSegment==1 ){ - rc = SQLITE_DONE; - goto finished; - } - rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel); - bIgnoreEmpty = 1; - - }else if( iLevel==FTS3_SEGCURSOR_PENDING ){ - iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0); - rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx); - }else{ - /* This call is to merge all segments at level iLevel. find the next - ** available segment index at level iLevel+1. The call to - ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to - ** a single iLevel+2 segment if necessary. */ - rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); - iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1); - } - if( rc!=SQLITE_OK ) goto finished; - assert( csr.nSegment>0 ); - assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); - assert( iNewLevelnIndex; i++){ - rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - sqlite3Fts3PendingTermsClear(p); - - /* Determine the auto-incr-merge setting if unknown. If enabled, - ** estimate the number of leaf blocks of content to be written - */ - if( rc==SQLITE_OK && p->bHasStat - && p->bAutoincrmerge==0xff && p->nLeafAdd>0 - ){ - sqlite3_stmt *pStmt = 0; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); - rc = sqlite3_step(pStmt); - p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0)); - rc = sqlite3_reset(pStmt); - } - } - return rc; -} - -/* -** Encode N integers as varints into a blob. -*/ -static void fts3EncodeIntArray( - int N, /* The number of integers to encode */ - u32 *a, /* The integer values */ - char *zBuf, /* Write the BLOB here */ - int *pNBuf /* Write number of bytes if zBuf[] used here */ -){ - int i, j; - for(i=j=0; iiPrevDocid. The sizes are encoded as -** a blob of varints. -*/ -static void fts3InsertDocsize( - int *pRC, /* Result code */ - Fts3Table *p, /* Table into which to insert */ - u32 *aSz /* Sizes of each column, in tokens */ -){ - char *pBlob; /* The BLOB encoding of the document size */ - int nBlob; /* Number of bytes in the BLOB */ - sqlite3_stmt *pStmt; /* Statement used to insert the encoding */ - int rc; /* Result code from subfunctions */ - - if( *pRC ) return; - pBlob = sqlite3_malloc( 10*p->nColumn ); - if( pBlob==0 ){ - *pRC = SQLITE_NOMEM; - return; - } - fts3EncodeIntArray(p->nColumn, aSz, pBlob, &nBlob); - rc = fts3SqlStmt(p, SQL_REPLACE_DOCSIZE, &pStmt, 0); - if( rc ){ - sqlite3_free(pBlob); - *pRC = rc; - return; - } - sqlite3_bind_int64(pStmt, 1, p->iPrevDocid); - sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, sqlite3_free); - sqlite3_step(pStmt); - *pRC = sqlite3_reset(pStmt); -} - -/* -** Record 0 of the %_stat table contains a blob consisting of N varints, -** where N is the number of user defined columns in the fts3 table plus -** two. If nCol is the number of user defined columns, then values of the -** varints are set as follows: -** -** Varint 0: Total number of rows in the table. -** -** Varint 1..nCol: For each column, the total number of tokens stored in -** the column for all rows of the table. -** -** Varint 1+nCol: The total size, in bytes, of all text values in all -** columns of all rows of the table. -** -*/ -static void fts3UpdateDocTotals( - int *pRC, /* The result code */ - Fts3Table *p, /* Table being updated */ - u32 *aSzIns, /* Size increases */ - u32 *aSzDel, /* Size decreases */ - int nChng /* Change in the number of documents */ -){ - char *pBlob; /* Storage for BLOB written into %_stat */ - int nBlob; /* Size of BLOB written into %_stat */ - u32 *a; /* Array of integers that becomes the BLOB */ - sqlite3_stmt *pStmt; /* Statement for reading and writing */ - int i; /* Loop counter */ - int rc; /* Result code from subfunctions */ - - const int nStat = p->nColumn+2; - - if( *pRC ) return; - a = sqlite3_malloc( (sizeof(u32)+10)*nStat ); - if( a==0 ){ - *pRC = SQLITE_NOMEM; - return; - } - pBlob = (char*)&a[nStat]; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); - if( rc ){ - sqlite3_free(a); - *pRC = rc; - return; - } - sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - fts3DecodeIntArray(nStat, a, - sqlite3_column_blob(pStmt, 0), - sqlite3_column_bytes(pStmt, 0)); - }else{ - memset(a, 0, sizeof(u32)*(nStat) ); - } - rc = sqlite3_reset(pStmt); - if( rc!=SQLITE_OK ){ - sqlite3_free(a); - *pRC = rc; - return; - } - if( nChng<0 && a[0]<(u32)(-nChng) ){ - a[0] = 0; - }else{ - a[0] += nChng; - } - for(i=0; inColumn+1; i++){ - u32 x = a[i+1]; - if( x+aSzIns[i] < aSzDel[i] ){ - x = 0; - }else{ - x = x + aSzIns[i] - aSzDel[i]; - } - a[i+1] = x; - } - fts3EncodeIntArray(nStat, a, pBlob, &nBlob); - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); - if( rc ){ - sqlite3_free(a); - *pRC = rc; - return; - } - sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); - sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC); - sqlite3_step(pStmt); - *pRC = sqlite3_reset(pStmt); - sqlite3_free(a); -} - -/* -** Merge the entire database so that there is one segment for each -** iIndex/iLangid combination. -*/ -static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ - int bSeenDone = 0; - int rc; - sqlite3_stmt *pAllLangid = 0; - - rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int(pAllLangid, 1, p->nIndex); - while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ - int i; - int iLangid = sqlite3_column_int(pAllLangid, 0); - for(i=0; rc==SQLITE_OK && inIndex; i++){ - rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL); - if( rc==SQLITE_DONE ){ - bSeenDone = 1; - rc = SQLITE_OK; - } - } - } - rc2 = sqlite3_reset(pAllLangid); - if( rc==SQLITE_OK ) rc = rc2; - } - - sqlite3Fts3SegmentsClose(p); - sqlite3Fts3PendingTermsClear(p); - - return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc; -} - -/* -** This function is called when the user executes the following statement: -** -** INSERT INTO () VALUES('rebuild'); -** -** The entire FTS index is discarded and rebuilt. If the table is one -** created using the content=xxx option, then the new index is based on -** the current contents of the xxx table. Otherwise, it is rebuilt based -** on the contents of the %_content table. -*/ -static int fts3DoRebuild(Fts3Table *p){ - int rc; /* Return Code */ - - rc = fts3DeleteAll(p, 0); - if( rc==SQLITE_OK ){ - u32 *aSz = 0; - u32 *aSzIns = 0; - u32 *aSzDel = 0; - sqlite3_stmt *pStmt = 0; - int nEntry = 0; - - /* Compose and prepare an SQL statement to loop through the content table */ - char *zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - - if( rc==SQLITE_OK ){ - int nByte = sizeof(u32) * (p->nColumn+1)*3; - aSz = (u32 *)sqlite3_malloc(nByte); - if( aSz==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(aSz, 0, nByte); - aSzIns = &aSz[p->nColumn+1]; - aSzDel = &aSzIns[p->nColumn+1]; - } - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - int iCol; - int iLangid = langidFromSelect(p, pStmt); - rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); - memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); - for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ - const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); - rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); - aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); - } - if( p->bHasDocsize ){ - fts3InsertDocsize(&rc, p, aSz); - } - if( rc!=SQLITE_OK ){ - sqlite3_finalize(pStmt); - pStmt = 0; - }else{ - nEntry++; - for(iCol=0; iCol<=p->nColumn; iCol++){ - aSzIns[iCol] += aSz[iCol]; - } - } - } - if( p->bFts4 ){ - fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry); - } - sqlite3_free(aSz); - - if( pStmt ){ - int rc2 = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - - return rc; -} - - -/* -** This function opens a cursor used to read the input data for an -** incremental merge operation. Specifically, it opens a cursor to scan -** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute -** level iAbsLevel. -*/ -static int fts3IncrmergeCsr( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level to open */ - int nSeg, /* Number of segments to merge */ - Fts3MultiSegReader *pCsr /* Cursor object to populate */ -){ - int rc; /* Return Code */ - sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */ - int nByte; /* Bytes allocated at pCsr->apSegment[] */ - - /* Allocate space for the Fts3MultiSegReader.aCsr[] array */ - memset(pCsr, 0, sizeof(*pCsr)); - nByte = sizeof(Fts3SegReader *) * nSeg; - pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte); - - if( pCsr->apSegment==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pCsr->apSegment, 0, nByte); - rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); - } - if( rc==SQLITE_OK ){ - int i; - int rc2; - sqlite3_bind_int64(pStmt, 1, iAbsLevel); - assert( pCsr->nSegment==0 ); - for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && iapSegment[i] - ); - pCsr->nSegment++; - } - rc2 = sqlite3_reset(pStmt); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -typedef struct IncrmergeWriter IncrmergeWriter; -typedef struct NodeWriter NodeWriter; -typedef struct Blob Blob; -typedef struct NodeReader NodeReader; - -/* -** An instance of the following structure is used as a dynamic buffer -** to build up nodes or other blobs of data in. -** -** The function blobGrowBuffer() is used to extend the allocation. -*/ -struct Blob { - char *a; /* Pointer to allocation */ - int n; /* Number of valid bytes of data in a[] */ - int nAlloc; /* Allocated size of a[] (nAlloc>=n) */ -}; - -/* -** This structure is used to build up buffers containing segment b-tree -** nodes (blocks). -*/ -struct NodeWriter { - sqlite3_int64 iBlock; /* Current block id */ - Blob key; /* Last key written to the current block */ - Blob block; /* Current block image */ -}; - -/* -** An object of this type contains the state required to create or append -** to an appendable b-tree segment. -*/ -struct IncrmergeWriter { - int nLeafEst; /* Space allocated for leaf blocks */ - int nWork; /* Number of leaf pages flushed */ - sqlite3_int64 iAbsLevel; /* Absolute level of input segments */ - int iIdx; /* Index of *output* segment in iAbsLevel+1 */ - sqlite3_int64 iStart; /* Block number of first allocated block */ - sqlite3_int64 iEnd; /* Block number of last allocated block */ - NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT]; -}; - -/* -** An object of the following type is used to read data from a single -** FTS segment node. See the following functions: -** -** nodeReaderInit() -** nodeReaderNext() -** nodeReaderRelease() -*/ -struct NodeReader { - const char *aNode; - int nNode; - int iOff; /* Current offset within aNode[] */ - - /* Output variables. Containing the current node entry. */ - sqlite3_int64 iChild; /* Pointer to child node */ - Blob term; /* Current term */ - const char *aDoclist; /* Pointer to doclist */ - int nDoclist; /* Size of doclist in bytes */ -}; - -/* -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, if the allocation at pBlob->a is not already at least nMin -** bytes in size, extend (realloc) it to be so. -** -** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a -** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc -** to reflect the new size of the pBlob->a[] buffer. -*/ -static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){ - if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){ - int nAlloc = nMin; - char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc); - if( a ){ - pBlob->nAlloc = nAlloc; - pBlob->a = a; - }else{ - *pRc = SQLITE_NOMEM; - } - } -} - -/* -** Attempt to advance the node-reader object passed as the first argument to -** the next entry on the node. -** -** Return an error code if an error occurs (SQLITE_NOMEM is possible). -** Otherwise return SQLITE_OK. If there is no next entry on the node -** (e.g. because the current entry is the last) set NodeReader->aNode to -** NULL to indicate EOF. Otherwise, populate the NodeReader structure output -** variables for the new entry. -*/ -static int nodeReaderNext(NodeReader *p){ - int bFirst = (p->term.n==0); /* True for first term on the node */ - int nPrefix = 0; /* Bytes to copy from previous term */ - int nSuffix = 0; /* Bytes to append to the prefix */ - int rc = SQLITE_OK; /* Return code */ - - assert( p->aNode ); - if( p->iChild && bFirst==0 ) p->iChild++; - if( p->iOff>=p->nNode ){ - /* EOF */ - p->aNode = 0; - }else{ - if( bFirst==0 ){ - p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nPrefix); - } - p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); - - blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); - if( rc==SQLITE_OK ){ - memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix); - p->term.n = nPrefix+nSuffix; - p->iOff += nSuffix; - if( p->iChild==0 ){ - p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist); - p->aDoclist = &p->aNode[p->iOff]; - p->iOff += p->nDoclist; - } - } - } - - assert( p->iOff<=p->nNode ); - - return rc; -} - -/* -** Release all dynamic resources held by node-reader object *p. -*/ -static void nodeReaderRelease(NodeReader *p){ - sqlite3_free(p->term.a); -} - -/* -** Initialize a node-reader object to read the node in buffer aNode/nNode. -** -** If successful, SQLITE_OK is returned and the NodeReader object set to -** point to the first entry on the node (if any). Otherwise, an SQLite -** error code is returned. -*/ -static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){ - memset(p, 0, sizeof(NodeReader)); - p->aNode = aNode; - p->nNode = nNode; - - /* Figure out if this is a leaf or an internal node. */ - if( p->aNode[0] ){ - /* An internal node. */ - p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild); - }else{ - p->iOff = 1; - } - - return nodeReaderNext(p); -} - -/* -** This function is called while writing an FTS segment each time a leaf o -** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed -** to be greater than the largest key on the node just written, but smaller -** than or equal to the first key that will be written to the next leaf -** node. -** -** The block id of the leaf node just written to disk may be found in -** (pWriter->aNodeWriter[0].iBlock) when this function is called. -*/ -static int fts3IncrmergePush( - Fts3Table *p, /* Fts3 table handle */ - IncrmergeWriter *pWriter, /* Writer object */ - const char *zTerm, /* Term to write to internal node */ - int nTerm /* Bytes at zTerm */ -){ - sqlite3_int64 iPtr = pWriter->aNodeWriter[0].iBlock; - int iLayer; - - assert( nTerm>0 ); - for(iLayer=1; ALWAYS(iLayeraNodeWriter[iLayer]; - int rc = SQLITE_OK; - int nPrefix; - int nSuffix; - int nSpace; - - /* Figure out how much space the key will consume if it is written to - ** the current node of layer iLayer. Due to the prefix compression, - ** the space required changes depending on which node the key is to - ** be added to. */ - nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm); - nSuffix = nTerm - nPrefix; - nSpace = sqlite3Fts3VarintLen(nPrefix); - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - - if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){ - /* If the current node of layer iLayer contains zero keys, or if adding - ** the key to it will not cause it to grow to larger than nNodeSize - ** bytes in size, write the key here. */ - - Blob *pBlk = &pNode->block; - if( pBlk->n==0 ){ - blobGrowBuffer(pBlk, p->nNodeSize, &rc); - if( rc==SQLITE_OK ){ - pBlk->a[0] = (char)iLayer; - pBlk->n = 1 + sqlite3Fts3PutVarint(&pBlk->a[1], iPtr); - } - } - blobGrowBuffer(pBlk, pBlk->n + nSpace, &rc); - blobGrowBuffer(&pNode->key, nTerm, &rc); - - if( rc==SQLITE_OK ){ - if( pNode->key.n ){ - pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix); - } - pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix); - memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix); - pBlk->n += nSuffix; - - memcpy(pNode->key.a, zTerm, nTerm); - pNode->key.n = nTerm; - } - }else{ - /* Otherwise, flush the current node of layer iLayer to disk. - ** Then allocate a new, empty sibling node. The key will be written - ** into the parent of this node. */ - rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n); - - assert( pNode->block.nAlloc>=p->nNodeSize ); - pNode->block.a[0] = (char)iLayer; - pNode->block.n = 1 + sqlite3Fts3PutVarint(&pNode->block.a[1], iPtr+1); - - iNextPtr = pNode->iBlock; - pNode->iBlock++; - pNode->key.n = 0; - } - - if( rc!=SQLITE_OK || iNextPtr==0 ) return rc; - iPtr = iNextPtr; - } - - assert( 0 ); - return 0; -} - -/* -** Append a term and (optionally) doclist to the FTS segment node currently -** stored in blob *pNode. The node need not contain any terms, but the -** header must be written before this function is called. -** -** A node header is a single 0x00 byte for a leaf node, or a height varint -** followed by the left-hand-child varint for an internal node. -** -** The term to be appended is passed via arguments zTerm/nTerm. For a -** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal -** node, both aDoclist and nDoclist must be passed 0. -** -** If the size of the value in blob pPrev is zero, then this is the first -** term written to the node. Otherwise, pPrev contains a copy of the -** previous term. Before this function returns, it is updated to contain a -** copy of zTerm/nTerm. -** -** It is assumed that the buffer associated with pNode is already large -** enough to accommodate the new entry. The buffer associated with pPrev -** is extended by this function if requrired. -** -** If an error (i.e. OOM condition) occurs, an SQLite error code is -** returned. Otherwise, SQLITE_OK. -*/ -static int fts3AppendToNode( - Blob *pNode, /* Current node image to append to */ - Blob *pPrev, /* Buffer containing previous term written */ - const char *zTerm, /* New term to write */ - int nTerm, /* Size of zTerm in bytes */ - const char *aDoclist, /* Doclist (or NULL) to write */ - int nDoclist /* Size of aDoclist in bytes */ -){ - int rc = SQLITE_OK; /* Return code */ - int bFirst = (pPrev->n==0); /* True if this is the first term written */ - int nPrefix; /* Size of term prefix in bytes */ - int nSuffix; /* Size of term suffix in bytes */ - - /* Node must have already been started. There must be a doclist for a - ** leaf node, and there must not be a doclist for an internal node. */ - assert( pNode->n>0 ); - assert( (pNode->a[0]=='\0')==(aDoclist!=0) ); - - blobGrowBuffer(pPrev, nTerm, &rc); - if( rc!=SQLITE_OK ) return rc; - - nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm); - nSuffix = nTerm - nPrefix; - memcpy(pPrev->a, zTerm, nTerm); - pPrev->n = nTerm; - - if( bFirst==0 ){ - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix); - } - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix); - memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix); - pNode->n += nSuffix; - - if( aDoclist ){ - pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist); - memcpy(&pNode->a[pNode->n], aDoclist, nDoclist); - pNode->n += nDoclist; - } - - assert( pNode->n<=pNode->nAlloc ); - - return SQLITE_OK; -} - -/* -** Append the current term and doclist pointed to by cursor pCsr to the -** appendable b-tree segment opened for writing by pWriter. -** -** Return SQLITE_OK if successful, or an SQLite error code otherwise. -*/ -static int fts3IncrmergeAppend( - Fts3Table *p, /* Fts3 table handle */ - IncrmergeWriter *pWriter, /* Writer object */ - Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */ -){ - const char *zTerm = pCsr->zTerm; - int nTerm = pCsr->nTerm; - const char *aDoclist = pCsr->aDoclist; - int nDoclist = pCsr->nDoclist; - int rc = SQLITE_OK; /* Return code */ - int nSpace; /* Total space in bytes required on leaf */ - int nPrefix; /* Size of prefix shared with previous term */ - int nSuffix; /* Size of suffix (nTerm - nPrefix) */ - NodeWriter *pLeaf; /* Object used to write leaf nodes */ - - pLeaf = &pWriter->aNodeWriter[0]; - nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm); - nSuffix = nTerm - nPrefix; - - nSpace = sqlite3Fts3VarintLen(nPrefix); - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; - - /* If the current block is not empty, and if adding this term/doclist - ** to the current block would make it larger than Fts3Table.nNodeSize - ** bytes, write this block out to the database. */ - if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){ - rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n); - pWriter->nWork++; - - /* Add the current term to the parent node. The term added to the - ** parent must: - ** - ** a) be greater than the largest term on the leaf node just written - ** to the database (still available in pLeaf->key), and - ** - ** b) be less than or equal to the term about to be added to the new - ** leaf node (zTerm/nTerm). - ** - ** In other words, it must be the prefix of zTerm 1 byte longer than - ** the common prefix (if any) of zTerm and pWriter->zTerm. - */ - if( rc==SQLITE_OK ){ - rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1); - } - - /* Advance to the next output block */ - pLeaf->iBlock++; - pLeaf->key.n = 0; - pLeaf->block.n = 0; - - nSuffix = nTerm; - nSpace = 1; - nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; - nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; - } - - blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc); - - if( rc==SQLITE_OK ){ - if( pLeaf->block.n==0 ){ - pLeaf->block.n = 1; - pLeaf->block.a[0] = '\0'; - } - rc = fts3AppendToNode( - &pLeaf->block, &pLeaf->key, zTerm, nTerm, aDoclist, nDoclist - ); - } - - return rc; -} - -/* -** This function is called to release all dynamic resources held by the -** merge-writer object pWriter, and if no error has occurred, to flush -** all outstanding node buffers held by pWriter to disk. -** -** If *pRc is not SQLITE_OK when this function is called, then no attempt -** is made to write any data to disk. Instead, this function serves only -** to release outstanding resources. -** -** Otherwise, if *pRc is initially SQLITE_OK and an error occurs while -** flushing buffers to disk, *pRc is set to an SQLite error code before -** returning. -*/ -static void fts3IncrmergeRelease( - Fts3Table *p, /* FTS3 table handle */ - IncrmergeWriter *pWriter, /* Merge-writer object */ - int *pRc /* IN/OUT: Error code */ -){ - int i; /* Used to iterate through non-root layers */ - int iRoot; /* Index of root in pWriter->aNodeWriter */ - NodeWriter *pRoot; /* NodeWriter for root node */ - int rc = *pRc; /* Error code */ - - /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment - ** root node. If the segment fits entirely on a single leaf node, iRoot - ** will be set to 0. If the root node is the parent of the leaves, iRoot - ** will be 1. And so on. */ - for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){ - NodeWriter *pNode = &pWriter->aNodeWriter[iRoot]; - if( pNode->block.n>0 ) break; - assert( *pRc || pNode->block.nAlloc==0 ); - assert( *pRc || pNode->key.nAlloc==0 ); - sqlite3_free(pNode->block.a); - sqlite3_free(pNode->key.a); - } - - /* Empty output segment. This is a no-op. */ - if( iRoot<0 ) return; - - /* The entire output segment fits on a single node. Normally, this means - ** the node would be stored as a blob in the "root" column of the %_segdir - ** table. However, this is not permitted in this case. The problem is that - ** space has already been reserved in the %_segments table, and so the - ** start_block and end_block fields of the %_segdir table must be populated. - ** And, by design or by accident, released versions of FTS cannot handle - ** segments that fit entirely on the root node with start_block!=0. - ** - ** Instead, create a synthetic root node that contains nothing but a - ** pointer to the single content node. So that the segment consists of a - ** single leaf and a single interior (root) node. - ** - ** Todo: Better might be to defer allocating space in the %_segments - ** table until we are sure it is needed. - */ - if( iRoot==0 ){ - Blob *pBlock = &pWriter->aNodeWriter[1].block; - blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc); - if( rc==SQLITE_OK ){ - pBlock->a[0] = 0x01; - pBlock->n = 1 + sqlite3Fts3PutVarint( - &pBlock->a[1], pWriter->aNodeWriter[0].iBlock - ); - } - iRoot = 1; - } - pRoot = &pWriter->aNodeWriter[iRoot]; - - /* Flush all currently outstanding nodes to disk. */ - for(i=0; iaNodeWriter[i]; - if( pNode->block.n>0 && rc==SQLITE_OK ){ - rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n); - } - sqlite3_free(pNode->block.a); - sqlite3_free(pNode->key.a); - } - - /* Write the %_segdir record. */ - if( rc==SQLITE_OK ){ - rc = fts3WriteSegdir(p, - pWriter->iAbsLevel+1, /* level */ - pWriter->iIdx, /* idx */ - pWriter->iStart, /* start_block */ - pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */ - pWriter->iEnd, /* end_block */ - pRoot->block.a, pRoot->block.n /* root */ - ); - } - sqlite3_free(pRoot->block.a); - sqlite3_free(pRoot->key.a); - - *pRc = rc; -} - -/* -** Compare the term in buffer zLhs (size in bytes nLhs) with that in -** zRhs (size in bytes nRhs) using memcmp. If one term is a prefix of -** the other, it is considered to be smaller than the other. -** -** Return -ve if zLhs is smaller than zRhs, 0 if it is equal, or +ve -** if it is greater. -*/ -static int fts3TermCmp( - const char *zLhs, int nLhs, /* LHS of comparison */ - const char *zRhs, int nRhs /* RHS of comparison */ -){ - int nCmp = MIN(nLhs, nRhs); - int res; - - res = memcmp(zLhs, zRhs, nCmp); - if( res==0 ) res = nLhs - nRhs; - - return res; -} - - -/* -** Query to see if the entry in the %_segments table with blockid iEnd is -** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before -** returning. Otherwise, set *pbRes to 0. -** -** Or, if an error occurs while querying the database, return an SQLite -** error code. The final value of *pbRes is undefined in this case. -** -** This is used to test if a segment is an "appendable" segment. If it -** is, then a NULL entry has been inserted into the %_segments table -** with blockid %_segdir.end_block. -*/ -static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){ - int bRes = 0; /* Result to set *pbRes to */ - sqlite3_stmt *pCheck = 0; /* Statement to query database with */ - int rc; /* Return code */ - - rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pCheck, 1, iEnd); - if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1; - rc = sqlite3_reset(pCheck); - } - - *pbRes = bRes; - return rc; -} - -/* -** This function is called when initializing an incremental-merge operation. -** It checks if the existing segment with index value iIdx at absolute level -** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the -** merge-writer object *pWriter is initialized to write to it. -** -** An existing segment can be appended to by an incremental merge if: -** -** * It was initially created as an appendable segment (with all required -** space pre-allocated), and -** -** * The first key read from the input (arguments zKey and nKey) is -** greater than the largest key currently stored in the potential -** output segment. -*/ -static int fts3IncrmergeLoad( - Fts3Table *p, /* Fts3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ - int iIdx, /* Index of candidate output segment */ - const char *zKey, /* First key to write */ - int nKey, /* Number of bytes in nKey */ - IncrmergeWriter *pWriter /* Populate this object */ -){ - int rc; /* Return code */ - sqlite3_stmt *pSelect = 0; /* SELECT to read %_segdir entry */ - - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pSelect, 0); - if( rc==SQLITE_OK ){ - sqlite3_int64 iStart = 0; /* Value of %_segdir.start_block */ - sqlite3_int64 iLeafEnd = 0; /* Value of %_segdir.leaves_end_block */ - sqlite3_int64 iEnd = 0; /* Value of %_segdir.end_block */ - const char *aRoot = 0; /* Pointer to %_segdir.root buffer */ - int nRoot = 0; /* Size of aRoot[] in bytes */ - int rc2; /* Return code from sqlite3_reset() */ - int bAppendable = 0; /* Set to true if segment is appendable */ - - /* Read the %_segdir entry for index iIdx absolute level (iAbsLevel+1) */ - sqlite3_bind_int64(pSelect, 1, iAbsLevel+1); - sqlite3_bind_int(pSelect, 2, iIdx); - if( sqlite3_step(pSelect)==SQLITE_ROW ){ - iStart = sqlite3_column_int64(pSelect, 1); - iLeafEnd = sqlite3_column_int64(pSelect, 2); - iEnd = sqlite3_column_int64(pSelect, 3); - nRoot = sqlite3_column_bytes(pSelect, 4); - aRoot = sqlite3_column_blob(pSelect, 4); - }else{ - return sqlite3_reset(pSelect); - } - - /* Check for the zero-length marker in the %_segments table */ - rc = fts3IsAppendable(p, iEnd, &bAppendable); - - /* Check that zKey/nKey is larger than the largest key the candidate */ - if( rc==SQLITE_OK && bAppendable ){ - char *aLeaf = 0; - int nLeaf = 0; - - rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0); - if( rc==SQLITE_OK ){ - NodeReader reader; - for(rc = nodeReaderInit(&reader, aLeaf, nLeaf); - rc==SQLITE_OK && reader.aNode; - rc = nodeReaderNext(&reader) - ){ - assert( reader.aNode ); - } - if( fts3TermCmp(zKey, nKey, reader.term.a, reader.term.n)<=0 ){ - bAppendable = 0; - } - nodeReaderRelease(&reader); - } - sqlite3_free(aLeaf); - } - - if( rc==SQLITE_OK && bAppendable ){ - /* It is possible to append to this segment. Set up the IncrmergeWriter - ** object to do so. */ - int i; - int nHeight = (int)aRoot[0]; - NodeWriter *pNode; - - pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT; - pWriter->iStart = iStart; - pWriter->iEnd = iEnd; - pWriter->iAbsLevel = iAbsLevel; - pWriter->iIdx = iIdx; - - for(i=nHeight+1; iaNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; - } - - pNode = &pWriter->aNodeWriter[nHeight]; - pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight; - blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc); - if( rc==SQLITE_OK ){ - memcpy(pNode->block.a, aRoot, nRoot); - pNode->block.n = nRoot; - } - - for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){ - NodeReader reader; - pNode = &pWriter->aNodeWriter[i]; - - rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); - while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); - blobGrowBuffer(&pNode->key, reader.term.n, &rc); - if( rc==SQLITE_OK ){ - memcpy(pNode->key.a, reader.term.a, reader.term.n); - pNode->key.n = reader.term.n; - if( i>0 ){ - char *aBlock = 0; - int nBlock = 0; - pNode = &pWriter->aNodeWriter[i-1]; - pNode->iBlock = reader.iChild; - rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0); - blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc); - if( rc==SQLITE_OK ){ - memcpy(pNode->block.a, aBlock, nBlock); - pNode->block.n = nBlock; - } - sqlite3_free(aBlock); - } - } - nodeReaderRelease(&reader); - } - } - - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -/* -** Determine the largest segment index value that exists within absolute -** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus -** one before returning SQLITE_OK. Or, if there are no segments at all -** within level iAbsLevel, set *piIdx to zero. -** -** If an error occurs, return an SQLite error code. The final value of -** *piIdx is undefined in this case. -*/ -static int fts3IncrmergeOutputIdx( - Fts3Table *p, /* FTS Table handle */ - sqlite3_int64 iAbsLevel, /* Absolute index of input segments */ - int *piIdx /* OUT: Next free index at iAbsLevel+1 */ -){ - int rc; - sqlite3_stmt *pOutputIdx = 0; /* SQL used to find output index */ - - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pOutputIdx, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pOutputIdx, 1, iAbsLevel+1); - sqlite3_step(pOutputIdx); - *piIdx = sqlite3_column_int(pOutputIdx, 0); - rc = sqlite3_reset(pOutputIdx); - } - - return rc; -} - -/* -** Allocate an appendable output segment on absolute level iAbsLevel+1 -** with idx value iIdx. -** -** In the %_segdir table, a segment is defined by the values in three -** columns: -** -** start_block -** leaves_end_block -** end_block -** -** When an appendable segment is allocated, it is estimated that the -** maximum number of leaf blocks that may be required is the sum of the -** number of leaf blocks consumed by the input segments, plus the number -** of input segments, multiplied by two. This value is stored in stack -** variable nLeafEst. -** -** A total of 16*nLeafEst blocks are allocated when an appendable segment -** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous -** array of leaf nodes starts at the first block allocated. The array -** of interior nodes that are parents of the leaf nodes start at block -** (start_block + (1 + end_block - start_block) / 16). And so on. -** -** In the actual code below, the value "16" is replaced with the -** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT. -*/ -static int fts3IncrmergeWriter( - Fts3Table *p, /* Fts3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ - int iIdx, /* Index of new output segment */ - Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */ - IncrmergeWriter *pWriter /* Populate this object */ -){ - int rc; /* Return Code */ - int i; /* Iterator variable */ - int nLeafEst = 0; /* Blocks allocated for leaf nodes */ - sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */ - sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */ - - /* Calculate nLeafEst. */ - rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pLeafEst, 1, iAbsLevel); - sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment); - if( SQLITE_ROW==sqlite3_step(pLeafEst) ){ - nLeafEst = sqlite3_column_int(pLeafEst, 0); - } - rc = sqlite3_reset(pLeafEst); - } - if( rc!=SQLITE_OK ) return rc; - - /* Calculate the first block to use in the output segment */ - rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0); - if( rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pFirstBlock) ){ - pWriter->iStart = sqlite3_column_int64(pFirstBlock, 0); - pWriter->iEnd = pWriter->iStart - 1; - pWriter->iEnd += nLeafEst * FTS_MAX_APPENDABLE_HEIGHT; - } - rc = sqlite3_reset(pFirstBlock); - } - if( rc!=SQLITE_OK ) return rc; - - /* Insert the marker in the %_segments table to make sure nobody tries - ** to steal the space just allocated. This is also used to identify - ** appendable segments. */ - rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0); - if( rc!=SQLITE_OK ) return rc; - - pWriter->iAbsLevel = iAbsLevel; - pWriter->nLeafEst = nLeafEst; - pWriter->iIdx = iIdx; - - /* Set up the array of NodeWriter objects */ - for(i=0; iaNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; - } - return SQLITE_OK; -} - -/* -** Remove an entry from the %_segdir table. This involves running the -** following two statements: -** -** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx -** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx -** -** The DELETE statement removes the specific %_segdir level. The UPDATE -** statement ensures that the remaining segments have contiguously allocated -** idx values. -*/ -static int fts3RemoveSegdirEntry( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level to delete from */ - int iIdx /* Index of %_segdir entry to delete */ -){ - int rc; /* Return code */ - sqlite3_stmt *pDelete = 0; /* DELETE statement */ - - rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDelete, 1, iAbsLevel); - sqlite3_bind_int(pDelete, 2, iIdx); - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } - - return rc; -} - -/* -** One or more segments have just been removed from absolute level iAbsLevel. -** Update the 'idx' values of the remaining segments in the level so that -** the idx values are a contiguous sequence starting from 0. -*/ -static int fts3RepackSegdirLevel( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel /* Absolute level to repack */ -){ - int rc; /* Return code */ - int *aIdx = 0; /* Array of remaining idx values */ - int nIdx = 0; /* Valid entries in aIdx[] */ - int nAlloc = 0; /* Allocated size of aIdx[] */ - int i; /* Iterator variable */ - sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */ - sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */ - - rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int64(pSelect, 1, iAbsLevel); - while( SQLITE_ROW==sqlite3_step(pSelect) ){ - if( nIdx>=nAlloc ){ - int *aNew; - nAlloc += 16; - aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int)); - if( !aNew ){ - rc = SQLITE_NOMEM; - break; - } - aIdx = aNew; - } - aIdx[nIdx++] = sqlite3_column_int(pSelect, 0); - } - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0); - } - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pUpdate, 2, iAbsLevel); - } - - assert( p->bIgnoreSavepoint==0 ); - p->bIgnoreSavepoint = 1; - for(i=0; rc==SQLITE_OK && ibIgnoreSavepoint = 0; - - sqlite3_free(aIdx); - return rc; -} - -static void fts3StartNode(Blob *pNode, int iHeight, sqlite3_int64 iChild){ - pNode->a[0] = (char)iHeight; - if( iChild ){ - assert( pNode->nAlloc>=1+sqlite3Fts3VarintLen(iChild) ); - pNode->n = 1 + sqlite3Fts3PutVarint(&pNode->a[1], iChild); - }else{ - assert( pNode->nAlloc>=1 ); - pNode->n = 1; - } -} - -/* -** The first two arguments are a pointer to and the size of a segment b-tree -** node. The node may be a leaf or an internal node. -** -** This function creates a new node image in blob object *pNew by copying -** all terms that are greater than or equal to zTerm/nTerm (for leaf nodes) -** or greater than zTerm/nTerm (for internal nodes) from aNode/nNode. -*/ -static int fts3TruncateNode( - const char *aNode, /* Current node image */ - int nNode, /* Size of aNode in bytes */ - Blob *pNew, /* OUT: Write new node image here */ - const char *zTerm, /* Omit all terms smaller than this */ - int nTerm, /* Size of zTerm in bytes */ - sqlite3_int64 *piBlock /* OUT: Block number in next layer down */ -){ - NodeReader reader; /* Reader object */ - Blob prev = {0, 0, 0}; /* Previous term written to new node */ - int rc = SQLITE_OK; /* Return code */ - int bLeaf = aNode[0]=='\0'; /* True for a leaf node */ - - /* Allocate required output space */ - blobGrowBuffer(pNew, nNode, &rc); - if( rc!=SQLITE_OK ) return rc; - pNew->n = 0; - - /* Populate new node buffer */ - for(rc = nodeReaderInit(&reader, aNode, nNode); - rc==SQLITE_OK && reader.aNode; - rc = nodeReaderNext(&reader) - ){ - if( pNew->n==0 ){ - int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm); - if( res<0 || (bLeaf==0 && res==0) ) continue; - fts3StartNode(pNew, (int)aNode[0], reader.iChild); - *piBlock = reader.iChild; - } - rc = fts3AppendToNode( - pNew, &prev, reader.term.a, reader.term.n, - reader.aDoclist, reader.nDoclist - ); - if( rc!=SQLITE_OK ) break; - } - if( pNew->n==0 ){ - fts3StartNode(pNew, (int)aNode[0], reader.iChild); - *piBlock = reader.iChild; - } - assert( pNew->n<=pNew->nAlloc ); - - nodeReaderRelease(&reader); - sqlite3_free(prev.a); - return rc; -} - -/* -** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute -** level iAbsLevel. This may involve deleting entries from the %_segments -** table, and modifying existing entries in both the %_segments and %_segdir -** tables. -** -** SQLITE_OK is returned if the segment is updated successfully. Or an -** SQLite error code otherwise. -*/ -static int fts3TruncateSegment( - Fts3Table *p, /* FTS3 table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level of segment to modify */ - int iIdx, /* Index within level of segment to modify */ - const char *zTerm, /* Remove terms smaller than this */ - int nTerm /* Number of bytes in buffer zTerm */ -){ - int rc = SQLITE_OK; /* Return code */ - Blob root = {0,0,0}; /* New root page image */ - Blob block = {0,0,0}; /* Buffer used for any other block */ - sqlite3_int64 iBlock = 0; /* Block id */ - sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */ - sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */ - sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */ - - rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0); - if( rc==SQLITE_OK ){ - int rc2; /* sqlite3_reset() return code */ - sqlite3_bind_int64(pFetch, 1, iAbsLevel); - sqlite3_bind_int(pFetch, 2, iIdx); - if( SQLITE_ROW==sqlite3_step(pFetch) ){ - const char *aRoot = sqlite3_column_blob(pFetch, 4); - int nRoot = sqlite3_column_bytes(pFetch, 4); - iOldStart = sqlite3_column_int64(pFetch, 1); - rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock); - } - rc2 = sqlite3_reset(pFetch); - if( rc==SQLITE_OK ) rc = rc2; - } - - while( rc==SQLITE_OK && iBlock ){ - char *aBlock = 0; - int nBlock = 0; - iNewStart = iBlock; - - rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0); - if( rc==SQLITE_OK ){ - rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock); - } - if( rc==SQLITE_OK ){ - rc = fts3WriteSegment(p, iNewStart, block.a, block.n); - } - sqlite3_free(aBlock); - } - - /* Variable iNewStart now contains the first valid leaf node. */ - if( rc==SQLITE_OK && iNewStart ){ - sqlite3_stmt *pDel = 0; - rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pDel, 1, iOldStart); - sqlite3_bind_int64(pDel, 2, iNewStart-1); - sqlite3_step(pDel); - rc = sqlite3_reset(pDel); - } - } - - if( rc==SQLITE_OK ){ - sqlite3_stmt *pChomp = 0; - rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pChomp, 1, iNewStart); - sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC); - sqlite3_bind_int64(pChomp, 3, iAbsLevel); - sqlite3_bind_int(pChomp, 4, iIdx); - sqlite3_step(pChomp); - rc = sqlite3_reset(pChomp); - } - } - - sqlite3_free(root.a); - sqlite3_free(block.a); - return rc; -} - -/* -** This function is called after an incrmental-merge operation has run to -** merge (or partially merge) two or more segments from absolute level -** iAbsLevel. -** -** Each input segment is either removed from the db completely (if all of -** its data was copied to the output segment by the incrmerge operation) -** or modified in place so that it no longer contains those entries that -** have been duplicated in the output segment. -*/ -static int fts3IncrmergeChomp( - Fts3Table *p, /* FTS table handle */ - sqlite3_int64 iAbsLevel, /* Absolute level containing segments */ - Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */ - int *pnRem /* Number of segments not deleted */ -){ - int i; - int nRem = 0; - int rc = SQLITE_OK; - - for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){ - Fts3SegReader *pSeg = 0; - int j; - - /* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding - ** somewhere in the pCsr->apSegment[] array. */ - for(j=0; ALWAYS(jnSegment); j++){ - pSeg = pCsr->apSegment[j]; - if( pSeg->iIdx==i ) break; - } - assert( jnSegment && pSeg->iIdx==i ); - - if( pSeg->aNode==0 ){ - /* Seg-reader is at EOF. Remove the entire input segment. */ - rc = fts3DeleteSegment(p, pSeg); - if( rc==SQLITE_OK ){ - rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx); - } - *pnRem = 0; - }else{ - /* The incremental merge did not copy all the data from this - ** segment to the upper level. The segment is modified in place - ** so that it contains no keys smaller than zTerm/nTerm. */ - const char *zTerm = pSeg->zTerm; - int nTerm = pSeg->nTerm; - rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm); - nRem++; - } - } - - if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){ - rc = fts3RepackSegdirLevel(p, iAbsLevel); - } - - *pnRem = nRem; - return rc; -} - -/* -** Store an incr-merge hint in the database. -*/ -static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){ - sqlite3_stmt *pReplace = 0; - int rc; /* Return code */ - - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0); - if( rc==SQLITE_OK ){ - sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT); - sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC); - sqlite3_step(pReplace); - rc = sqlite3_reset(pReplace); - } - - return rc; -} - -/* -** Load an incr-merge hint from the database. The incr-merge hint, if one -** exists, is stored in the rowid==1 row of the %_stat table. -** -** If successful, populate blob *pHint with the value read from the %_stat -** table and return SQLITE_OK. Otherwise, if an error occurs, return an -** SQLite error code. -*/ -static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){ - sqlite3_stmt *pSelect = 0; - int rc; - - pHint->n = 0; - rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pSelect, 0); - if( rc==SQLITE_OK ){ - int rc2; - sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT); - if( SQLITE_ROW==sqlite3_step(pSelect) ){ - const char *aHint = sqlite3_column_blob(pSelect, 0); - int nHint = sqlite3_column_bytes(pSelect, 0); - if( aHint ){ - blobGrowBuffer(pHint, nHint, &rc); - if( rc==SQLITE_OK ){ - memcpy(pHint->a, aHint, nHint); - pHint->n = nHint; - } - } - } - rc2 = sqlite3_reset(pSelect); - if( rc==SQLITE_OK ) rc = rc2; - } - - return rc; -} - -/* -** If *pRc is not SQLITE_OK when this function is called, it is a no-op. -** Otherwise, append an entry to the hint stored in blob *pHint. Each entry -** consists of two varints, the absolute level number of the input segments -** and the number of input segments. -** -** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs, -** set *pRc to an SQLite error code before returning. -*/ -static void fts3IncrmergeHintPush( - Blob *pHint, /* Hint blob to append to */ - i64 iAbsLevel, /* First varint to store in hint */ - int nInput, /* Second varint to store in hint */ - int *pRc /* IN/OUT: Error code */ -){ - blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc); - if( *pRc==SQLITE_OK ){ - pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel); - pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput); - } -} - -/* -** Read the last entry (most recently pushed) from the hint blob *pHint -** and then remove the entry. Write the two values read to *piAbsLevel and -** *pnInput before returning. -** -** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does -** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB. -*/ -static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ - const int nHint = pHint->n; - int i; - - i = pHint->n-2; - while( i>0 && (pHint->a[i-1] & 0x80) ) i--; - while( i>0 && (pHint->a[i-1] & 0x80) ) i--; - - pHint->n = i; - i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); - i += sqlite3Fts3GetVarint32(&pHint->a[i], pnInput); - if( i!=nHint ) return SQLITE_CORRUPT_VTAB; - - return SQLITE_OK; -} - - -/* -** Attempt an incremental merge that writes nMerge leaf blocks. -** -** Incremental merges happen nMin segments at a time. The two -** segments to be merged are the nMin oldest segments (the ones with -** the smallest indexes) in the highest level that contains at least -** nMin segments. Multiple merges might occur in an attempt to write the -** quota of nMerge leaf blocks. -*/ -SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ - int rc; /* Return code */ - int nRem = nMerge; /* Number of leaf pages yet to be written */ - Fts3MultiSegReader *pCsr; /* Cursor used to read input data */ - Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */ - IncrmergeWriter *pWriter; /* Writer object */ - int nSeg = 0; /* Number of input segments */ - sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */ - Blob hint = {0, 0, 0}; /* Hint read from %_stat table */ - int bDirtyHint = 0; /* True if blob 'hint' has been modified */ - - /* Allocate space for the cursor, filter and writer objects */ - const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter); - pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc); - if( !pWriter ) return SQLITE_NOMEM; - pFilter = (Fts3SegFilter *)&pWriter[1]; - pCsr = (Fts3MultiSegReader *)&pFilter[1]; - - rc = fts3IncrmergeHintLoad(p, &hint); - while( rc==SQLITE_OK && nRem>0 ){ - const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex; - sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */ - int bUseHint = 0; /* True if attempting to append */ - - /* Search the %_segdir table for the absolute level with the smallest - ** relative level number that contains at least nMin segments, if any. - ** If one is found, set iAbsLevel to the absolute level number and - ** nSeg to nMin. If no level with at least nMin segments can be found, - ** set nSeg to -1. - */ - rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0); - sqlite3_bind_int(pFindLevel, 1, nMin); - if( sqlite3_step(pFindLevel)==SQLITE_ROW ){ - iAbsLevel = sqlite3_column_int64(pFindLevel, 0); - nSeg = nMin; - }else{ - nSeg = -1; - } - rc = sqlite3_reset(pFindLevel); - - /* If the hint read from the %_stat table is not empty, check if the - ** last entry in it specifies a relative level smaller than or equal - ** to the level identified by the block above (if any). If so, this - ** iteration of the loop will work on merging at the hinted level. - */ - if( rc==SQLITE_OK && hint.n ){ - int nHint = hint.n; - sqlite3_int64 iHintAbsLevel = 0; /* Hint level */ - int nHintSeg = 0; /* Hint number of segments */ - - rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg); - if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){ - iAbsLevel = iHintAbsLevel; - nSeg = nHintSeg; - bUseHint = 1; - bDirtyHint = 1; - }else{ - /* This undoes the effect of the HintPop() above - so that no entry - ** is removed from the hint blob. */ - hint.n = nHint; - } - } - - /* If nSeg is less that zero, then there is no level with at least - ** nMin segments and no hint in the %_stat table. No work to do. - ** Exit early in this case. */ - if( nSeg<0 ) break; - - /* Open a cursor to iterate through the contents of the oldest nSeg - ** indexes of absolute level iAbsLevel. If this cursor is opened using - ** the 'hint' parameters, it is possible that there are less than nSeg - ** segments available in level iAbsLevel. In this case, no work is - ** done on iAbsLevel - fall through to the next iteration of the loop - ** to start work on some other level. */ - memset(pWriter, 0, nAlloc); - pFilter->flags = FTS3_SEGMENT_REQUIRE_POS; - if( rc==SQLITE_OK ){ - rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr); - } - if( SQLITE_OK==rc && pCsr->nSegment==nSeg - && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter)) - && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr)) - ){ - int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */ - rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx); - if( rc==SQLITE_OK ){ - if( bUseHint && iIdx>0 ){ - const char *zKey = pCsr->zTerm; - int nKey = pCsr->nTerm; - rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter); - }else{ - rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter); - } - } - - if( rc==SQLITE_OK && pWriter->nLeafEst ){ - fts3LogMerge(nSeg, iAbsLevel); - do { - rc = fts3IncrmergeAppend(p, pWriter, pCsr); - if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr); - if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK; - }while( rc==SQLITE_ROW ); - - /* Update or delete the input segments */ - if( rc==SQLITE_OK ){ - nRem -= (1 + pWriter->nWork); - rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg); - if( nSeg!=0 ){ - bDirtyHint = 1; - fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc); - } - } - } - - fts3IncrmergeRelease(p, pWriter, &rc); - } - - sqlite3Fts3SegReaderFinish(pCsr); - } - - /* Write the hint values into the %_stat table for the next incr-merger */ - if( bDirtyHint && rc==SQLITE_OK ){ - rc = fts3IncrmergeHintStore(p, &hint); - } - - sqlite3_free(pWriter); - sqlite3_free(hint.a); - return rc; -} - -/* -** Convert the text beginning at *pz into an integer and return -** its value. Advance *pz to point to the first character past -** the integer. -*/ -static int fts3Getint(const char **pz){ - const char *z = *pz; - int i = 0; - while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0'; - *pz = z; - return i; -} - -/* -** Process statements of the form: -** -** INSERT INTO table(table) VALUES('merge=A,B'); -** -** A and B are integers that decode to be the number of leaf pages -** written for the merge, and the minimum number of segments on a level -** before it will be selected for a merge, respectively. -*/ -static int fts3DoIncrmerge( - Fts3Table *p, /* FTS3 table handle */ - const char *zParam /* Nul-terminated string containing "A,B" */ -){ - int rc; - int nMin = (FTS3_MERGE_COUNT / 2); - int nMerge = 0; - const char *z = zParam; - - /* Read the first integer value */ - nMerge = fts3Getint(&z); - - /* If the first integer value is followed by a ',', read the second - ** integer value. */ - if( z[0]==',' && z[1]!='\0' ){ - z++; - nMin = fts3Getint(&z); - } - - if( z[0]!='\0' || nMin<2 ){ - rc = SQLITE_ERROR; - }else{ - rc = SQLITE_OK; - if( !p->bHasStat ){ - assert( p->bFts4==0 ); - sqlite3Fts3CreateStatTable(&rc, p); - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3Incrmerge(p, nMerge, nMin); - } - sqlite3Fts3SegmentsClose(p); - } - return rc; -} - -/* -** Process statements of the form: -** -** INSERT INTO table(table) VALUES('automerge=X'); -** -** where X is an integer. X==0 means to turn automerge off. X!=0 means -** turn it on. The setting is persistent. -*/ -static int fts3DoAutoincrmerge( - Fts3Table *p, /* FTS3 table handle */ - const char *zParam /* Nul-terminated string containing boolean */ -){ - int rc = SQLITE_OK; - sqlite3_stmt *pStmt = 0; - p->bAutoincrmerge = fts3Getint(&zParam)!=0; - if( !p->bHasStat ){ - assert( p->bFts4==0 ); - sqlite3Fts3CreateStatTable(&rc, p); - if( rc ) return rc; - } - rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); - if( rc ) return rc;; - sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); - sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge); - sqlite3_step(pStmt); - rc = sqlite3_reset(pStmt); - return rc; -} - -/* -** Return a 64-bit checksum for the FTS index entry specified by the -** arguments to this function. -*/ -static u64 fts3ChecksumEntry( - const char *zTerm, /* Pointer to buffer containing term */ - int nTerm, /* Size of zTerm in bytes */ - int iLangid, /* Language id for current row */ - int iIndex, /* Index (0..Fts3Table.nIndex-1) */ - i64 iDocid, /* Docid for current row. */ - int iCol, /* Column number */ - int iPos /* Position */ -){ - int i; - u64 ret = (u64)iDocid; - - ret += (ret<<3) + iLangid; - ret += (ret<<3) + iIndex; - ret += (ret<<3) + iCol; - ret += (ret<<3) + iPos; - for(i=0; inIndex-1) */ - int *pRc /* OUT: Return code */ -){ - Fts3SegFilter filter; - Fts3MultiSegReader csr; - int rc; - u64 cksum = 0; - - assert( *pRc==SQLITE_OK ); - - memset(&filter, 0, sizeof(filter)); - memset(&csr, 0, sizeof(csr)); - filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; - filter.flags |= FTS3_SEGMENT_SCAN; - - rc = sqlite3Fts3SegReaderCursor( - p, iLangid, iIndex, FTS3_SEGCURSOR_ALL, 0, 0, 0, 1,&csr - ); - if( rc==SQLITE_OK ){ - rc = sqlite3Fts3SegReaderStart(p, &csr, &filter); - } - - if( rc==SQLITE_OK ){ - while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){ - char *pCsr = csr.aDoclist; - char *pEnd = &pCsr[csr.nDoclist]; - - i64 iDocid = 0; - i64 iCol = 0; - i64 iPos = 0; - - pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid); - while( pCsrnIndex); - while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ - int iLangid = sqlite3_column_int(pAllLangid, 0); - int i; - for(i=0; inIndex; i++){ - cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc); - } - } - rc2 = sqlite3_reset(pAllLangid); - if( rc==SQLITE_OK ) rc = rc2; - } - - /* This block calculates the checksum according to the %_content table */ - rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); - if( rc==SQLITE_OK ){ - sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; - sqlite3_stmt *pStmt = 0; - char *zSql; - - zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); - if( !zSql ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); - sqlite3_free(zSql); - } - - while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ - i64 iDocid = sqlite3_column_int64(pStmt, 0); - int iLang = langidFromSelect(p, pStmt); - int iCol; - - for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ - const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); - int nText = sqlite3_column_bytes(pStmt, iCol+1); - sqlite3_tokenizer_cursor *pT = 0; - - rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT); - while( rc==SQLITE_OK ){ - char const *zToken; /* Buffer containing token */ - int nToken = 0; /* Number of bytes in token */ - int iDum1 = 0, iDum2 = 0; /* Dummy variables */ - int iPos = 0; /* Position of token in zText */ - - rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos); - if( rc==SQLITE_OK ){ - int i; - cksum2 = cksum2 ^ fts3ChecksumEntry( - zToken, nToken, iLang, 0, iDocid, iCol, iPos - ); - for(i=1; inIndex; i++){ - if( p->aIndex[i].nPrefix<=nToken ){ - cksum2 = cksum2 ^ fts3ChecksumEntry( - zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos - ); - } - } - } - } - if( pT ) pModule->xClose(pT); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - } - - sqlite3_finalize(pStmt); - } - - *pbOk = (cksum1==cksum2); - return rc; -} - -/* -** Run the integrity-check. If no error occurs and the current contents of -** the FTS index are correct, return SQLITE_OK. Or, if the contents of the -** FTS index are incorrect, return SQLITE_CORRUPT_VTAB. -** -** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite -** error code. -** -** The integrity-check works as follows. For each token and indexed token -** prefix in the document set, a 64-bit checksum is calculated (by code -** in fts3ChecksumEntry()) based on the following: -** -** + The index number (0 for the main index, 1 for the first prefix -** index etc.), -** + The token (or token prefix) text itself, -** + The language-id of the row it appears in, -** + The docid of the row it appears in, -** + The column it appears in, and -** + The tokens position within that column. -** -** The checksums for all entries in the index are XORed together to create -** a single checksum for the entire index. -** -** The integrity-check code calculates the same checksum in two ways: -** -** 1. By scanning the contents of the FTS index, and -** 2. By scanning and tokenizing the content table. -** -** If the two checksums are identical, the integrity-check is deemed to have -** passed. -*/ -static int fts3DoIntegrityCheck( - Fts3Table *p /* FTS3 table handle */ -){ - int rc; - int bOk = 0; - rc = fts3IntegrityCheck(p, &bOk); - if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB; - return rc; -} - -/* -** Handle a 'special' INSERT of the form: -** -** "INSERT INTO tbl(tbl) VALUES()" -** -** Argument pVal contains the result of . Currently the only -** meaningful value to insert is the text 'optimize'. -*/ -static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ - int rc; /* Return Code */ - const char *zVal = (const char *)sqlite3_value_text(pVal); - int nVal = sqlite3_value_bytes(pVal); - - if( !zVal ){ - return SQLITE_NOMEM; - }else if( nVal==8 && 0==sqlite3_strnicmp(zVal, "optimize", 8) ){ - rc = fts3DoOptimize(p, 0); - }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){ - rc = fts3DoRebuild(p); - }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){ - rc = fts3DoIntegrityCheck(p); - }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){ - rc = fts3DoIncrmerge(p, &zVal[6]); - }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){ - rc = fts3DoAutoincrmerge(p, &zVal[10]); -#ifdef SQLITE_TEST - }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ - p->nNodeSize = atoi(&zVal[9]); - rc = SQLITE_OK; - }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ - p->nMaxPendingData = atoi(&zVal[11]); - rc = SQLITE_OK; -#endif - }else{ - rc = SQLITE_ERROR; - } - - return rc; -} - -#ifndef SQLITE_DISABLE_FTS4_DEFERRED -/* -** Delete all cached deferred doclists. Deferred doclists are cached -** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function. -*/ -SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){ - Fts3DeferredToken *pDef; - for(pDef=pCsr->pDeferred; pDef; pDef=pDef->pNext){ - fts3PendingListDelete(pDef->pList); - pDef->pList = 0; - } -} - -/* -** Free all entries in the pCsr->pDeffered list. Entries are added to -** this list using sqlite3Fts3DeferToken(). -*/ -SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){ - Fts3DeferredToken *pDef; - Fts3DeferredToken *pNext; - for(pDef=pCsr->pDeferred; pDef; pDef=pNext){ - pNext = pDef->pNext; - fts3PendingListDelete(pDef->pList); - sqlite3_free(pDef); - } - pCsr->pDeferred = 0; -} - -/* -** Generate deferred-doclists for all tokens in the pCsr->pDeferred list -** based on the row that pCsr currently points to. -** -** A deferred-doclist is like any other doclist with position information -** included, except that it only contains entries for a single row of the -** table, not for all rows. -*/ -SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){ - int rc = SQLITE_OK; /* Return code */ - if( pCsr->pDeferred ){ - int i; /* Used to iterate through table columns */ - sqlite3_int64 iDocid; /* Docid of the row pCsr points to */ - Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */ - - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - sqlite3_tokenizer *pT = p->pTokenizer; - sqlite3_tokenizer_module const *pModule = pT->pModule; - - assert( pCsr->isRequireSeek==0 ); - iDocid = sqlite3_column_int64(pCsr->pStmt, 0); - - for(i=0; inColumn && rc==SQLITE_OK; i++){ - const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); - sqlite3_tokenizer_cursor *pTC = 0; - - rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); - while( rc==SQLITE_OK ){ - char const *zToken; /* Buffer containing token */ - int nToken = 0; /* Number of bytes in token */ - int iDum1 = 0, iDum2 = 0; /* Dummy variables */ - int iPos = 0; /* Position of token in zText */ - - rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); - for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ - Fts3PhraseToken *pPT = pDef->pToken; - if( (pDef->iCol>=p->nColumn || pDef->iCol==i) - && (pPT->bFirst==0 || iPos==0) - && (pPT->n==nToken || (pPT->isPrefix && pPT->nz, pPT->n)) - ){ - fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc); - } - } - } - if( pTC ) pModule->xClose(pTC); - if( rc==SQLITE_DONE ) rc = SQLITE_OK; - } - - for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ - if( pDef->pList ){ - rc = fts3PendingListAppendVarint(&pDef->pList, 0); - } - } - } - - return rc; -} - -SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList( - Fts3DeferredToken *p, - char **ppData, - int *pnData -){ - char *pRet; - int nSkip; - sqlite3_int64 dummy; - - *ppData = 0; - *pnData = 0; - - if( p->pList==0 ){ - return SQLITE_OK; - } - - pRet = (char *)sqlite3_malloc(p->pList->nData); - if( !pRet ) return SQLITE_NOMEM; - - nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy); - *pnData = p->pList->nData - nSkip; - *ppData = pRet; - - memcpy(pRet, &p->pList->aData[nSkip], *pnData); - return SQLITE_OK; -} - -/* -** Add an entry for token pToken to the pCsr->pDeferred list. -*/ -SQLITE_PRIVATE int sqlite3Fts3DeferToken( - Fts3Cursor *pCsr, /* Fts3 table cursor */ - Fts3PhraseToken *pToken, /* Token to defer */ - int iCol /* Column that token must appear in (or -1) */ -){ - Fts3DeferredToken *pDeferred; - pDeferred = sqlite3_malloc(sizeof(*pDeferred)); - if( !pDeferred ){ - return SQLITE_NOMEM; - } - memset(pDeferred, 0, sizeof(*pDeferred)); - pDeferred->pToken = pToken; - pDeferred->pNext = pCsr->pDeferred; - pDeferred->iCol = iCol; - pCsr->pDeferred = pDeferred; - - assert( pToken->pDeferred==0 ); - pToken->pDeferred = pDeferred; - - return SQLITE_OK; -} -#endif - -/* -** SQLite value pRowid contains the rowid of a row that may or may not be -** present in the FTS3 table. If it is, delete it and adjust the contents -** of subsiduary data structures accordingly. -*/ -static int fts3DeleteByRowid( - Fts3Table *p, - sqlite3_value *pRowid, - int *pnChng, /* IN/OUT: Decrement if row is deleted */ - u32 *aSzDel -){ - int rc = SQLITE_OK; /* Return code */ - int bFound = 0; /* True if *pRowid really is in the table */ - - fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound); - if( bFound && rc==SQLITE_OK ){ - int isEmpty = 0; /* Deleting *pRowid leaves the table empty */ - rc = fts3IsEmpty(p, pRowid, &isEmpty); - if( rc==SQLITE_OK ){ - if( isEmpty ){ - /* Deleting this row means the whole table is empty. In this case - ** delete the contents of all three tables and throw away any - ** data in the pendingTerms hash table. */ - rc = fts3DeleteAll(p, 1); - *pnChng = 0; - memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2); - }else{ - *pnChng = *pnChng - 1; - if( p->zContentTbl==0 ){ - fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); - } - if( p->bHasDocsize ){ - fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid); - } - } - } - } - - return rc; -} - -/* -** This function does the work for the xUpdate method of FTS3 virtual -** tables. The schema of the virtual table being: -** -** CREATE TABLE
( -** , -**
HIDDEN, -** docid HIDDEN, -** HIDDEN -** ); -** -** -*/ -SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( - sqlite3_vtab *pVtab, /* FTS3 vtab object */ - int nArg, /* Size of argument array */ - sqlite3_value **apVal, /* Array of arguments */ - sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ -){ - Fts3Table *p = (Fts3Table *)pVtab; - int rc = SQLITE_OK; /* Return Code */ - int isRemove = 0; /* True for an UPDATE or DELETE */ - u32 *aSzIns = 0; /* Sizes of inserted documents */ - u32 *aSzDel = 0; /* Sizes of deleted documents */ - int nChng = 0; /* Net change in number of documents */ - int bInsertDone = 0; - - assert( p->pSegments==0 ); - assert( - nArg==1 /* DELETE operations */ - || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ - ); - - /* Check for a "special" INSERT operation. One of the form: - ** - ** INSERT INTO xyz(xyz) VALUES('command'); - */ - if( nArg>1 - && sqlite3_value_type(apVal[0])==SQLITE_NULL - && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL - ){ - rc = fts3SpecialInsert(p, apVal[p->nColumn+2]); - goto update_out; - } - - if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ - rc = SQLITE_CONSTRAINT; - goto update_out; - } - - /* Allocate space to hold the change in document sizes */ - aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 ); - if( aSzDel==0 ){ - rc = SQLITE_NOMEM; - goto update_out; - } - aSzIns = &aSzDel[p->nColumn+1]; - memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2); - - /* If this is an INSERT operation, or an UPDATE that modifies the rowid - ** value, then this operation requires constraint handling. - ** - ** If the on-conflict mode is REPLACE, this means that the existing row - ** should be deleted from the database before inserting the new row. Or, - ** if the on-conflict mode is other than REPLACE, then this method must - ** detect the conflict and return SQLITE_CONSTRAINT before beginning to - ** modify the database file. - */ - if( nArg>1 && p->zContentTbl==0 ){ - /* Find the value object that holds the new rowid value. */ - sqlite3_value *pNewRowid = apVal[3+p->nColumn]; - if( sqlite3_value_type(pNewRowid)==SQLITE_NULL ){ - pNewRowid = apVal[1]; - } - - if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && ( - sqlite3_value_type(apVal[0])==SQLITE_NULL - || sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid) - )){ - /* The new rowid is not NULL (in this case the rowid will be - ** automatically assigned and there is no chance of a conflict), and - ** the statement is either an INSERT or an UPDATE that modifies the - ** rowid column. So if the conflict mode is REPLACE, then delete any - ** existing row with rowid=pNewRowid. - ** - ** Or, if the conflict mode is not REPLACE, insert the new record into - ** the %_content table. If we hit the duplicate rowid constraint (or any - ** other error) while doing so, return immediately. - ** - ** This branch may also run if pNewRowid contains a value that cannot - ** be losslessly converted to an integer. In this case, the eventual - ** call to fts3InsertData() (either just below or further on in this - ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is - ** invoked, it will delete zero rows (since no row will have - ** docid=$pNewRowid if $pNewRowid is not an integer value). - */ - if( sqlite3_vtab_on_conflict(p->db)==SQLITE_REPLACE ){ - rc = fts3DeleteByRowid(p, pNewRowid, &nChng, aSzDel); - }else{ - rc = fts3InsertData(p, apVal, pRowid); - bInsertDone = 1; - } - } - } - if( rc!=SQLITE_OK ){ - goto update_out; - } - - /* If this is a DELETE or UPDATE operation, remove the old record. */ - if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ - assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER ); - rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel); - isRemove = 1; - } - - /* If this is an INSERT or UPDATE operation, insert the new record. */ - if( nArg>1 && rc==SQLITE_OK ){ - int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); - if( bInsertDone==0 ){ - rc = fts3InsertData(p, apVal, pRowid); - if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ - rc = FTS_CORRUPT_VTAB; - } - } - if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ - rc = fts3PendingTermsDocid(p, iLangid, *pRowid); - } - if( rc==SQLITE_OK ){ - assert( p->iPrevDocid==*pRowid ); - rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); - } - if( p->bHasDocsize ){ - fts3InsertDocsize(&rc, p, aSzIns); - } - nChng++; - } - - if( p->bFts4 ){ - fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); - } - - update_out: - sqlite3_free(aSzDel); - sqlite3Fts3SegmentsClose(p); - return rc; -} - -/* -** Flush any data in the pending-terms hash table to disk. If successful, -** merge all segments in the database (including the new segment, if -** there was any data to flush) into a single segment. -*/ -SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ - int rc; - rc = sqlite3_exec(p->db, "SAVEPOINT fts3", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = fts3DoOptimize(p, 1); - if( rc==SQLITE_OK || rc==SQLITE_DONE ){ - int rc2 = sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); - if( rc2!=SQLITE_OK ) rc = rc2; - }else{ - sqlite3_exec(p->db, "ROLLBACK TO fts3", 0, 0, 0); - sqlite3_exec(p->db, "RELEASE fts3", 0, 0, 0); - } - } - sqlite3Fts3SegmentsClose(p); - return rc; -} - -#endif - -/************** End of fts3_write.c ******************************************/ -/************** Begin file fts3_snippet.c ************************************/ -/* -** 2009 Oct 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -*/ - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ - -/* -** Characters that may appear in the second argument to matchinfo(). -*/ -#define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */ -#define FTS3_MATCHINFO_NCOL 'c' /* 1 value */ -#define FTS3_MATCHINFO_NDOC 'n' /* 1 value */ -#define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */ -#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */ -#define FTS3_MATCHINFO_LCS 's' /* nCol values */ -#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ - -/* -** The default value for the second argument to matchinfo(). -*/ -#define FTS3_MATCHINFO_DEFAULT "pcx" - - -/* -** Used as an fts3ExprIterate() context when loading phrase doclists to -** Fts3Expr.aDoclist[]/nDoclist. -*/ -typedef struct LoadDoclistCtx LoadDoclistCtx; -struct LoadDoclistCtx { - Fts3Cursor *pCsr; /* FTS3 Cursor */ - int nPhrase; /* Number of phrases seen so far */ - int nToken; /* Number of tokens seen so far */ -}; - -/* -** The following types are used as part of the implementation of the -** fts3BestSnippet() routine. -*/ -typedef struct SnippetIter SnippetIter; -typedef struct SnippetPhrase SnippetPhrase; -typedef struct SnippetFragment SnippetFragment; - -struct SnippetIter { - Fts3Cursor *pCsr; /* Cursor snippet is being generated from */ - int iCol; /* Extract snippet from this column */ - int nSnippet; /* Requested snippet length (in tokens) */ - int nPhrase; /* Number of phrases in query */ - SnippetPhrase *aPhrase; /* Array of size nPhrase */ - int iCurrent; /* First token of current snippet */ -}; - -struct SnippetPhrase { - int nToken; /* Number of tokens in phrase */ - char *pList; /* Pointer to start of phrase position list */ - int iHead; /* Next value in position list */ - char *pHead; /* Position list data following iHead */ - int iTail; /* Next value in trailing position list */ - char *pTail; /* Position list data following iTail */ -}; - -struct SnippetFragment { - int iCol; /* Column snippet is extracted from */ - int iPos; /* Index of first token in snippet */ - u64 covered; /* Mask of query phrases covered */ - u64 hlmask; /* Mask of snippet terms to highlight */ -}; - -/* -** This type is used as an fts3ExprIterate() context object while -** accumulating the data returned by the matchinfo() function. -*/ -typedef struct MatchInfo MatchInfo; -struct MatchInfo { - Fts3Cursor *pCursor; /* FTS3 Cursor */ - int nCol; /* Number of columns in table */ - int nPhrase; /* Number of matchable phrases in query */ - sqlite3_int64 nDoc; /* Number of docs in database */ - u32 *aMatchinfo; /* Pre-allocated buffer */ -}; - - - -/* -** The snippet() and offsets() functions both return text values. An instance -** of the following structure is used to accumulate those values while the -** functions are running. See fts3StringAppend() for details. -*/ -typedef struct StrBuffer StrBuffer; -struct StrBuffer { - char *z; /* Pointer to buffer containing string */ - int n; /* Length of z in bytes (excl. nul-term) */ - int nAlloc; /* Allocated size of buffer z in bytes */ -}; - - -/* -** This function is used to help iterate through a position-list. A position -** list is a list of unique integers, sorted from smallest to largest. Each -** element of the list is represented by an FTS3 varint that takes the value -** of the difference between the current element and the previous one plus -** two. For example, to store the position-list: -** -** 4 9 113 -** -** the three varints: -** -** 6 7 106 -** -** are encoded. -** -** When this function is called, *pp points to the start of an element of -** the list. *piPos contains the value of the previous entry in the list. -** After it returns, *piPos contains the value of the next element of the -** list and *pp is advanced to the following varint. -*/ -static void fts3GetDeltaPosition(char **pp, int *piPos){ - int iVal; - *pp += sqlite3Fts3GetVarint32(*pp, &iVal); - *piPos += (iVal-2); -} - -/* -** Helper function for fts3ExprIterate() (see below). -*/ -static int fts3ExprIterate2( - Fts3Expr *pExpr, /* Expression to iterate phrases of */ - int *piPhrase, /* Pointer to phrase counter */ - int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ - void *pCtx /* Second argument to pass to callback */ -){ - int rc; /* Return code */ - int eType = pExpr->eType; /* Type of expression node pExpr */ - - if( eType!=FTSQUERY_PHRASE ){ - assert( pExpr->pLeft && pExpr->pRight ); - rc = fts3ExprIterate2(pExpr->pLeft, piPhrase, x, pCtx); - if( rc==SQLITE_OK && eType!=FTSQUERY_NOT ){ - rc = fts3ExprIterate2(pExpr->pRight, piPhrase, x, pCtx); - } - }else{ - rc = x(pExpr, *piPhrase, pCtx); - (*piPhrase)++; - } - return rc; -} - -/* -** Iterate through all phrase nodes in an FTS3 query, except those that -** are part of a sub-tree that is the right-hand-side of a NOT operator. -** For each phrase node found, the supplied callback function is invoked. -** -** If the callback function returns anything other than SQLITE_OK, -** the iteration is abandoned and the error code returned immediately. -** Otherwise, SQLITE_OK is returned after a callback has been made for -** all eligible phrase nodes. -*/ -static int fts3ExprIterate( - Fts3Expr *pExpr, /* Expression to iterate phrases of */ - int (*x)(Fts3Expr*,int,void*), /* Callback function to invoke for phrases */ - void *pCtx /* Second argument to pass to callback */ -){ - int iPhrase = 0; /* Variable used as the phrase counter */ - return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); -} - -/* -** This is an fts3ExprIterate() callback used while loading the doclists -** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also -** fts3ExprLoadDoclists(). -*/ -static int fts3ExprLoadDoclistsCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ - int rc = SQLITE_OK; - Fts3Phrase *pPhrase = pExpr->pPhrase; - LoadDoclistCtx *p = (LoadDoclistCtx *)ctx; - - UNUSED_PARAMETER(iPhrase); - - p->nPhrase++; - p->nToken += pPhrase->nToken; - - return rc; -} - -/* -** Load the doclists for each phrase in the query associated with FTS3 cursor -** pCsr. -** -** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable -** phrases in the expression (all phrases except those directly or -** indirectly descended from the right-hand-side of a NOT operator). If -** pnToken is not NULL, then it is set to the number of tokens in all -** matchable phrases of the expression. -*/ -static int fts3ExprLoadDoclists( - Fts3Cursor *pCsr, /* Fts3 cursor for current query */ - int *pnPhrase, /* OUT: Number of phrases in query */ - int *pnToken /* OUT: Number of tokens in query */ -){ - int rc; /* Return Code */ - LoadDoclistCtx sCtx = {0,0,0}; /* Context for fts3ExprIterate() */ - sCtx.pCsr = pCsr; - rc = fts3ExprIterate(pCsr->pExpr, fts3ExprLoadDoclistsCb, (void *)&sCtx); - if( pnPhrase ) *pnPhrase = sCtx.nPhrase; - if( pnToken ) *pnToken = sCtx.nToken; - return rc; -} - -static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ - (*(int *)ctx)++; - UNUSED_PARAMETER(pExpr); - UNUSED_PARAMETER(iPhrase); - return SQLITE_OK; -} -static int fts3ExprPhraseCount(Fts3Expr *pExpr){ - int nPhrase = 0; - (void)fts3ExprIterate(pExpr, fts3ExprPhraseCountCb, (void *)&nPhrase); - return nPhrase; -} - -/* -** Advance the position list iterator specified by the first two -** arguments so that it points to the first element with a value greater -** than or equal to parameter iNext. -*/ -static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){ - char *pIter = *ppIter; - if( pIter ){ - int iIter = *piIter; - - while( iIteriCurrent<0 ){ - /* The SnippetIter object has just been initialized. The first snippet - ** candidate always starts at offset 0 (even if this candidate has a - ** score of 0.0). - */ - pIter->iCurrent = 0; - - /* Advance the 'head' iterator of each phrase to the first offset that - ** is greater than or equal to (iNext+nSnippet). - */ - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, pIter->nSnippet); - } - }else{ - int iStart; - int iEnd = 0x7FFFFFFF; - - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - if( pPhrase->pHead && pPhrase->iHeadiHead; - } - } - if( iEnd==0x7FFFFFFF ){ - return 1; - } - - pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1; - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - fts3SnippetAdvance(&pPhrase->pHead, &pPhrase->iHead, iEnd+1); - fts3SnippetAdvance(&pPhrase->pTail, &pPhrase->iTail, iStart); - } - } - - return 0; -} - -/* -** Retrieve information about the current candidate snippet of snippet -** iterator pIter. -*/ -static void fts3SnippetDetails( - SnippetIter *pIter, /* Snippet iterator */ - u64 mCovered, /* Bitmask of phrases already covered */ - int *piToken, /* OUT: First token of proposed snippet */ - int *piScore, /* OUT: "Score" for this snippet */ - u64 *pmCover, /* OUT: Bitmask of phrases covered */ - u64 *pmHighlight /* OUT: Bitmask of terms to highlight */ -){ - int iStart = pIter->iCurrent; /* First token of snippet */ - int iScore = 0; /* Score of this snippet */ - int i; /* Loop counter */ - u64 mCover = 0; /* Mask of phrases covered by this snippet */ - u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */ - - for(i=0; inPhrase; i++){ - SnippetPhrase *pPhrase = &pIter->aPhrase[i]; - if( pPhrase->pTail ){ - char *pCsr = pPhrase->pTail; - int iCsr = pPhrase->iTail; - - while( iCsr<(iStart+pIter->nSnippet) ){ - int j; - u64 mPhrase = (u64)1 << i; - u64 mPos = (u64)1 << (iCsr - iStart); - assert( iCsr>=iStart ); - if( (mCover|mCovered)&mPhrase ){ - iScore++; - }else{ - iScore += 1000; - } - mCover |= mPhrase; - - for(j=0; jnToken; j++){ - mHighlight |= (mPos>>j); - } - - if( 0==(*pCsr & 0x0FE) ) break; - fts3GetDeltaPosition(&pCsr, &iCsr); - } - } - } - - /* Set the output variables before returning. */ - *piToken = iStart; - *piScore = iScore; - *pmCover = mCover; - *pmHighlight = mHighlight; -} - -/* -** This function is an fts3ExprIterate() callback used by fts3BestSnippet(). -** Each invocation populates an element of the SnippetIter.aPhrase[] array. -*/ -static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ - SnippetIter *p = (SnippetIter *)ctx; - SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; - char *pCsr; - int rc; - - pPhrase->nToken = pExpr->pPhrase->nToken; - rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr); - assert( rc==SQLITE_OK || pCsr==0 ); - if( pCsr ){ - int iFirst = 0; - pPhrase->pList = pCsr; - fts3GetDeltaPosition(&pCsr, &iFirst); - assert( iFirst>=0 ); - pPhrase->pHead = pCsr; - pPhrase->pTail = pCsr; - pPhrase->iHead = iFirst; - pPhrase->iTail = iFirst; - }else{ - assert( rc!=SQLITE_OK || ( - pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 - )); - } - - return rc; -} - -/* -** Select the fragment of text consisting of nFragment contiguous tokens -** from column iCol that represent the "best" snippet. The best snippet -** is the snippet with the highest score, where scores are calculated -** by adding: -** -** (a) +1 point for each occurrence of a matchable phrase in the snippet. -** -** (b) +1000 points for the first occurrence of each matchable phrase in -** the snippet for which the corresponding mCovered bit is not set. -** -** The selected snippet parameters are stored in structure *pFragment before -** returning. The score of the selected snippet is stored in *piScore -** before returning. -*/ -static int fts3BestSnippet( - int nSnippet, /* Desired snippet length */ - Fts3Cursor *pCsr, /* Cursor to create snippet for */ - int iCol, /* Index of column to create snippet from */ - u64 mCovered, /* Mask of phrases already covered */ - u64 *pmSeen, /* IN/OUT: Mask of phrases seen */ - SnippetFragment *pFragment, /* OUT: Best snippet found */ - int *piScore /* OUT: Score of snippet pFragment */ -){ - int rc; /* Return Code */ - int nList; /* Number of phrases in expression */ - SnippetIter sIter; /* Iterates through snippet candidates */ - int nByte; /* Number of bytes of space to allocate */ - int iBestScore = -1; /* Best snippet score found so far */ - int i; /* Loop counter */ - - memset(&sIter, 0, sizeof(sIter)); - - /* Iterate through the phrases in the expression to count them. The same - ** callback makes sure the doclists are loaded for each phrase. - */ - rc = fts3ExprLoadDoclists(pCsr, &nList, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Now that it is known how many phrases there are, allocate and zero - ** the required space using malloc(). - */ - nByte = sizeof(SnippetPhrase) * nList; - sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte); - if( !sIter.aPhrase ){ - return SQLITE_NOMEM; - } - memset(sIter.aPhrase, 0, nByte); - - /* Initialize the contents of the SnippetIter object. Then iterate through - ** the set of phrases in the expression to populate the aPhrase[] array. - */ - sIter.pCsr = pCsr; - sIter.iCol = iCol; - sIter.nSnippet = nSnippet; - sIter.nPhrase = nList; - sIter.iCurrent = -1; - (void)fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); - - /* Set the *pmSeen output variable. */ - for(i=0; iiCol = iCol; - while( !fts3SnippetNextCandidate(&sIter) ){ - int iPos; - int iScore; - u64 mCover; - u64 mHighlight; - fts3SnippetDetails(&sIter, mCovered, &iPos, &iScore, &mCover, &mHighlight); - assert( iScore>=0 ); - if( iScore>iBestScore ){ - pFragment->iPos = iPos; - pFragment->hlmask = mHighlight; - pFragment->covered = mCover; - iBestScore = iScore; - } - } - - sqlite3_free(sIter.aPhrase); - *piScore = iBestScore; - return SQLITE_OK; -} - - -/* -** Append a string to the string-buffer passed as the first argument. -** -** If nAppend is negative, then the length of the string zAppend is -** determined using strlen(). -*/ -static int fts3StringAppend( - StrBuffer *pStr, /* Buffer to append to */ - const char *zAppend, /* Pointer to data to append to buffer */ - int nAppend /* Size of zAppend in bytes (or -1) */ -){ - if( nAppend<0 ){ - nAppend = (int)strlen(zAppend); - } - - /* If there is insufficient space allocated at StrBuffer.z, use realloc() - ** to grow the buffer until so that it is big enough to accomadate the - ** appended data. - */ - if( pStr->n+nAppend+1>=pStr->nAlloc ){ - int nAlloc = pStr->nAlloc+nAppend+100; - char *zNew = sqlite3_realloc(pStr->z, nAlloc); - if( !zNew ){ - return SQLITE_NOMEM; - } - pStr->z = zNew; - pStr->nAlloc = nAlloc; - } - - /* Append the data to the string buffer. */ - memcpy(&pStr->z[pStr->n], zAppend, nAppend); - pStr->n += nAppend; - pStr->z[pStr->n] = '\0'; - - return SQLITE_OK; -} - -/* -** The fts3BestSnippet() function often selects snippets that end with a -** query term. That is, the final term of the snippet is always a term -** that requires highlighting. For example, if 'X' is a highlighted term -** and '.' is a non-highlighted term, BestSnippet() may select: -** -** ........X.....X -** -** This function "shifts" the beginning of the snippet forward in the -** document so that there are approximately the same number of -** non-highlighted terms to the right of the final highlighted term as there -** are to the left of the first highlighted term. For example, to this: -** -** ....X.....X.... -** -** This is done as part of extracting the snippet text, not when selecting -** the snippet. Snippet selection is done based on doclists only, so there -** is no way for fts3BestSnippet() to know whether or not the document -** actually contains terms that follow the final highlighted term. -*/ -static int fts3SnippetShift( - Fts3Table *pTab, /* FTS3 table snippet comes from */ - int iLangid, /* Language id to use in tokenizing */ - int nSnippet, /* Number of tokens desired for snippet */ - const char *zDoc, /* Document text to extract snippet from */ - int nDoc, /* Size of buffer zDoc in bytes */ - int *piPos, /* IN/OUT: First token of snippet */ - u64 *pHlmask /* IN/OUT: Mask of tokens to highlight */ -){ - u64 hlmask = *pHlmask; /* Local copy of initial highlight-mask */ - - if( hlmask ){ - int nLeft; /* Tokens to the left of first highlight */ - int nRight; /* Tokens to the right of last highlight */ - int nDesired; /* Ideal number of tokens to shift forward */ - - for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++); - for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++); - nDesired = (nLeft-nRight)/2; - - /* Ideally, the start of the snippet should be pushed forward in the - ** document nDesired tokens. This block checks if there are actually - ** nDesired tokens to the right of the snippet. If so, *piPos and - ** *pHlMask are updated to shift the snippet nDesired tokens to the - ** right. Otherwise, the snippet is shifted by the number of tokens - ** available. - */ - if( nDesired>0 ){ - int nShift; /* Number of tokens to shift snippet by */ - int iCurrent = 0; /* Token counter */ - int rc; /* Return Code */ - sqlite3_tokenizer_module *pMod; - sqlite3_tokenizer_cursor *pC; - pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; - - /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) - ** or more tokens in zDoc/nDoc. - */ - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); - if( rc!=SQLITE_OK ){ - return rc; - } - while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ - const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0; - rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); - } - pMod->xClose(pC); - if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; } - - nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet; - assert( nShift<=nDesired ); - if( nShift>0 ){ - *piPos += nShift; - *pHlmask = hlmask >> nShift; - } - } - } - return SQLITE_OK; -} - -/* -** Extract the snippet text for fragment pFragment from cursor pCsr and -** append it to string buffer pOut. -*/ -static int fts3SnippetText( - Fts3Cursor *pCsr, /* FTS3 Cursor */ - SnippetFragment *pFragment, /* Snippet to extract */ - int iFragment, /* Fragment number */ - int isLast, /* True for final fragment in snippet */ - int nSnippet, /* Number of tokens in extracted snippet */ - const char *zOpen, /* String inserted before highlighted term */ - const char *zClose, /* String inserted after highlighted term */ - const char *zEllipsis, /* String inserted between snippets */ - StrBuffer *pOut /* Write output here */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc; /* Return code */ - const char *zDoc; /* Document text to extract snippet from */ - int nDoc; /* Size of zDoc in bytes */ - int iCurrent = 0; /* Current token number of document */ - int iEnd = 0; /* Byte offset of end of current token */ - int isShiftDone = 0; /* True after snippet is shifted */ - int iPos = pFragment->iPos; /* First token of snippet */ - u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ - int iCol = pFragment->iCol+1; /* Query column to extract text from */ - sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ - sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ - - zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); - if( zDoc==0 ){ - if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ - return SQLITE_NOMEM; - } - return SQLITE_OK; - } - nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); - - /* Open a token cursor on the document. */ - pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); - if( rc!=SQLITE_OK ){ - return rc; - } - - while( rc==SQLITE_OK ){ - const char *ZDUMMY; /* Dummy argument used with tokenizer */ - int DUMMY1 = -1; /* Dummy argument used with tokenizer */ - int iBegin = 0; /* Offset in zDoc of start of token */ - int iFin = 0; /* Offset in zDoc of end of token */ - int isHighlight = 0; /* True for highlighted terms */ - - /* Variable DUMMY1 is initialized to a negative value above. Elsewhere - ** in the FTS code the variable that the third argument to xNext points to - ** is initialized to zero before the first (*but not necessarily - ** subsequent*) call to xNext(). This is done for a particular application - ** that needs to know whether or not the tokenizer is being used for - ** snippet generation or for some other purpose. - ** - ** Extreme care is required when writing code to depend on this - ** initialization. It is not a documented part of the tokenizer interface. - ** If a tokenizer is used directly by any code outside of FTS, this - ** convention might not be respected. */ - rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_DONE ){ - /* Special case - the last token of the snippet is also the last token - ** of the column. Append any punctuation that occurred between the end - ** of the previous token and the end of the document to the output. - ** Then break out of the loop. */ - rc = fts3StringAppend(pOut, &zDoc[iEnd], -1); - } - break; - } - if( iCurrentiLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask - ); - isShiftDone = 1; - - /* Now that the shift has been done, check if the initial "..." are - ** required. They are required if (a) this is not the first fragment, - ** or (b) this fragment does not begin at position 0 of its column. - */ - if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); - } - if( rc!=SQLITE_OK || iCurrent=(iPos+nSnippet) ){ - if( isLast ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); - } - break; - } - - /* Set isHighlight to true if this term should be highlighted. */ - isHighlight = (hlmask & ((u64)1 << (iCurrent-iPos)))!=0; - - if( iCurrent>iPos ) rc = fts3StringAppend(pOut, &zDoc[iEnd], iBegin-iEnd); - if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zOpen, -1); - if( rc==SQLITE_OK ) rc = fts3StringAppend(pOut, &zDoc[iBegin], iFin-iBegin); - if( rc==SQLITE_OK && isHighlight ) rc = fts3StringAppend(pOut, zClose, -1); - - iEnd = iFin; - } - - pMod->xClose(pC); - return rc; -} - - -/* -** This function is used to count the entries in a column-list (a -** delta-encoded list of term offsets within a single column of a single -** row). When this function is called, *ppCollist should point to the -** beginning of the first varint in the column-list (the varint that -** contains the position of the first matching term in the column data). -** Before returning, *ppCollist is set to point to the first byte after -** the last varint in the column-list (either the 0x00 signifying the end -** of the position-list, or the 0x01 that precedes the column number of -** the next column in the position-list). -** -** The number of elements in the column-list is returned. -*/ -static int fts3ColumnlistCount(char **ppCollist){ - char *pEnd = *ppCollist; - char c = 0; - int nEntry = 0; - - /* A column-list is terminated by either a 0x01 or 0x00. */ - while( 0xFE & (*pEnd | c) ){ - c = *pEnd++ & 0x80; - if( !c ) nEntry++; - } - - *ppCollist = pEnd; - return nEntry; -} - -/* -** fts3ExprIterate() callback used to collect the "global" matchinfo stats -** for a single query. -** -** fts3ExprIterate() callback to load the 'global' elements of a -** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements -** of the matchinfo array that are constant for all rows returned by the -** current query. -** -** Argument pCtx is actually a pointer to a struct of type MatchInfo. This -** function populates Matchinfo.aMatchinfo[] as follows: -** -** for(iCol=0; iColpCursor, pExpr, &p->aMatchinfo[3*iPhrase*p->nCol] - ); -} - -/* -** fts3ExprIterate() callback used to collect the "local" part of the -** FTS3_MATCHINFO_HITS array. The local stats are those elements of the -** array that are different for each row returned by the query. -*/ -static int fts3ExprLocalHitsCb( - Fts3Expr *pExpr, /* Phrase expression node */ - int iPhrase, /* Phrase number */ - void *pCtx /* Pointer to MatchInfo structure */ -){ - int rc = SQLITE_OK; - MatchInfo *p = (MatchInfo *)pCtx; - int iStart = iPhrase * p->nCol * 3; - int i; - - for(i=0; inCol && rc==SQLITE_OK; i++){ - char *pCsr; - rc = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i, &pCsr); - if( pCsr ){ - p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr); - }else{ - p->aMatchinfo[iStart+i*3] = 0; - } - } - - return rc; -} - -static int fts3MatchinfoCheck( - Fts3Table *pTab, - char cArg, - char **pzErr -){ - if( (cArg==FTS3_MATCHINFO_NPHRASE) - || (cArg==FTS3_MATCHINFO_NCOL) - || (cArg==FTS3_MATCHINFO_NDOC && pTab->bFts4) - || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bFts4) - || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) - || (cArg==FTS3_MATCHINFO_LCS) - || (cArg==FTS3_MATCHINFO_HITS) - ){ - return SQLITE_OK; - } - *pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg); - return SQLITE_ERROR; -} - -static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ - int nVal; /* Number of integers output by cArg */ - - switch( cArg ){ - case FTS3_MATCHINFO_NDOC: - case FTS3_MATCHINFO_NPHRASE: - case FTS3_MATCHINFO_NCOL: - nVal = 1; - break; - - case FTS3_MATCHINFO_AVGLENGTH: - case FTS3_MATCHINFO_LENGTH: - case FTS3_MATCHINFO_LCS: - nVal = pInfo->nCol; - break; - - default: - assert( cArg==FTS3_MATCHINFO_HITS ); - nVal = pInfo->nCol * pInfo->nPhrase * 3; - break; - } - - return nVal; -} - -static int fts3MatchinfoSelectDoctotal( - Fts3Table *pTab, - sqlite3_stmt **ppStmt, - sqlite3_int64 *pnDoc, - const char **paLen -){ - sqlite3_stmt *pStmt; - const char *a; - sqlite3_int64 nDoc; - - if( !*ppStmt ){ - int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt); - if( rc!=SQLITE_OK ) return rc; - } - pStmt = *ppStmt; - assert( sqlite3_data_count(pStmt)==1 ); - - a = sqlite3_column_blob(pStmt, 0); - a += sqlite3Fts3GetVarint(a, &nDoc); - if( nDoc==0 ) return FTS_CORRUPT_VTAB; - *pnDoc = (u32)nDoc; - - if( paLen ) *paLen = a; - return SQLITE_OK; -} - -/* -** An instance of the following structure is used to store state while -** iterating through a multi-column position-list corresponding to the -** hits for a single phrase on a single row in order to calculate the -** values for a matchinfo() FTS3_MATCHINFO_LCS request. -*/ -typedef struct LcsIterator LcsIterator; -struct LcsIterator { - Fts3Expr *pExpr; /* Pointer to phrase expression */ - int iPosOffset; /* Tokens count up to end of this phrase */ - char *pRead; /* Cursor used to iterate through aDoclist */ - int iPos; /* Current position */ -}; - -/* -** If LcsIterator.iCol is set to the following value, the iterator has -** finished iterating through all offsets for all columns. -*/ -#define LCS_ITERATOR_FINISHED 0x7FFFFFFF; - -static int fts3MatchinfoLcsCb( - Fts3Expr *pExpr, /* Phrase expression node */ - int iPhrase, /* Phrase number (numbered from zero) */ - void *pCtx /* Pointer to MatchInfo structure */ -){ - LcsIterator *aIter = (LcsIterator *)pCtx; - aIter[iPhrase].pExpr = pExpr; - return SQLITE_OK; -} - -/* -** Advance the iterator passed as an argument to the next position. Return -** 1 if the iterator is at EOF or if it now points to the start of the -** position list for the next column. -*/ -static int fts3LcsIteratorAdvance(LcsIterator *pIter){ - char *pRead = pIter->pRead; - sqlite3_int64 iRead; - int rc = 0; - - pRead += sqlite3Fts3GetVarint(pRead, &iRead); - if( iRead==0 || iRead==1 ){ - pRead = 0; - rc = 1; - }else{ - pIter->iPos += (int)(iRead-2); - } - - pIter->pRead = pRead; - return rc; -} - -/* -** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag. -** -** If the call is successful, the longest-common-substring lengths for each -** column are written into the first nCol elements of the pInfo->aMatchinfo[] -** array before returning. SQLITE_OK is returned in this case. -** -** Otherwise, if an error occurs, an SQLite error code is returned and the -** data written to the first nCol elements of pInfo->aMatchinfo[] is -** undefined. -*/ -static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){ - LcsIterator *aIter; - int i; - int iCol; - int nToken = 0; - - /* Allocate and populate the array of LcsIterator objects. The array - ** contains one element for each matchable phrase in the query. - **/ - aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase); - if( !aIter ) return SQLITE_NOMEM; - memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase); - (void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter); - - for(i=0; inPhrase; i++){ - LcsIterator *pIter = &aIter[i]; - nToken -= pIter->pExpr->pPhrase->nToken; - pIter->iPosOffset = nToken; - } - - for(iCol=0; iColnCol; iCol++){ - int nLcs = 0; /* LCS value for this column */ - int nLive = 0; /* Number of iterators in aIter not at EOF */ - - for(i=0; inPhrase; i++){ - int rc; - LcsIterator *pIt = &aIter[i]; - rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead); - if( rc!=SQLITE_OK ) return rc; - if( pIt->pRead ){ - pIt->iPos = pIt->iPosOffset; - fts3LcsIteratorAdvance(&aIter[i]); - nLive++; - } - } - - while( nLive>0 ){ - LcsIterator *pAdv = 0; /* The iterator to advance by one position */ - int nThisLcs = 0; /* LCS for the current iterator positions */ - - for(i=0; inPhrase; i++){ - LcsIterator *pIter = &aIter[i]; - if( pIter->pRead==0 ){ - /* This iterator is already at EOF for this column. */ - nThisLcs = 0; - }else{ - if( pAdv==0 || pIter->iPosiPos ){ - pAdv = pIter; - } - if( nThisLcs==0 || pIter->iPos==pIter[-1].iPos ){ - nThisLcs++; - }else{ - nThisLcs = 1; - } - if( nThisLcs>nLcs ) nLcs = nThisLcs; - } - } - if( fts3LcsIteratorAdvance(pAdv) ) nLive--; - } - - pInfo->aMatchinfo[iCol] = nLcs; - } - - sqlite3_free(aIter); - return SQLITE_OK; -} - -/* -** Populate the buffer pInfo->aMatchinfo[] with an array of integers to -** be returned by the matchinfo() function. Argument zArg contains the -** format string passed as the second argument to matchinfo (or the -** default value "pcx" if no second argument was specified). The format -** string has already been validated and the pInfo->aMatchinfo[] array -** is guaranteed to be large enough for the output. -** -** If bGlobal is true, then populate all fields of the matchinfo() output. -** If it is false, then assume that those fields that do not change between -** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS) -** have already been populated. -** -** Return SQLITE_OK if successful, or an SQLite error code if an error -** occurs. If a value other than SQLITE_OK is returned, the state the -** pInfo->aMatchinfo[] buffer is left in is undefined. -*/ -static int fts3MatchinfoValues( - Fts3Cursor *pCsr, /* FTS3 cursor object */ - int bGlobal, /* True to grab the global stats */ - MatchInfo *pInfo, /* Matchinfo context object */ - const char *zArg /* Matchinfo format string */ -){ - int rc = SQLITE_OK; - int i; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - sqlite3_stmt *pSelect = 0; - - for(i=0; rc==SQLITE_OK && zArg[i]; i++){ - - switch( zArg[i] ){ - case FTS3_MATCHINFO_NPHRASE: - if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase; - break; - - case FTS3_MATCHINFO_NCOL: - if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol; - break; - - case FTS3_MATCHINFO_NDOC: - if( bGlobal ){ - sqlite3_int64 nDoc = 0; - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0); - pInfo->aMatchinfo[0] = (u32)nDoc; - } - break; - - case FTS3_MATCHINFO_AVGLENGTH: - if( bGlobal ){ - sqlite3_int64 nDoc; /* Number of rows in table */ - const char *a; /* Aggregate column length array */ - - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a); - if( rc==SQLITE_OK ){ - int iCol; - for(iCol=0; iColnCol; iCol++){ - u32 iVal; - sqlite3_int64 nToken; - a += sqlite3Fts3GetVarint(a, &nToken); - iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc); - pInfo->aMatchinfo[iCol] = iVal; - } - } - } - break; - - case FTS3_MATCHINFO_LENGTH: { - sqlite3_stmt *pSelectDocsize = 0; - rc = sqlite3Fts3SelectDocsize(pTab, pCsr->iPrevId, &pSelectDocsize); - if( rc==SQLITE_OK ){ - int iCol; - const char *a = sqlite3_column_blob(pSelectDocsize, 0); - for(iCol=0; iColnCol; iCol++){ - sqlite3_int64 nToken; - a += sqlite3Fts3GetVarint(a, &nToken); - pInfo->aMatchinfo[iCol] = (u32)nToken; - } - } - sqlite3_reset(pSelectDocsize); - break; - } - - case FTS3_MATCHINFO_LCS: - rc = fts3ExprLoadDoclists(pCsr, 0, 0); - if( rc==SQLITE_OK ){ - rc = fts3MatchinfoLcs(pCsr, pInfo); - } - break; - - default: { - Fts3Expr *pExpr; - assert( zArg[i]==FTS3_MATCHINFO_HITS ); - pExpr = pCsr->pExpr; - rc = fts3ExprLoadDoclists(pCsr, 0, 0); - if( rc!=SQLITE_OK ) break; - if( bGlobal ){ - if( pCsr->pDeferred ){ - rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0); - if( rc!=SQLITE_OK ) break; - } - rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); - if( rc!=SQLITE_OK ) break; - } - (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); - break; - } - } - - pInfo->aMatchinfo += fts3MatchinfoSize(pInfo, zArg[i]); - } - - sqlite3_reset(pSelect); - return rc; -} - - -/* -** Populate pCsr->aMatchinfo[] with data for the current row. The -** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). -*/ -static int fts3GetMatchinfo( - Fts3Cursor *pCsr, /* FTS3 Cursor object */ - const char *zArg /* Second argument to matchinfo() function */ -){ - MatchInfo sInfo; - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int bGlobal = 0; /* Collect 'global' stats as well as local */ - - memset(&sInfo, 0, sizeof(MatchInfo)); - sInfo.pCursor = pCsr; - sInfo.nCol = pTab->nColumn; - - /* If there is cached matchinfo() data, but the format string for the - ** cache does not match the format string for this request, discard - ** the cached data. */ - if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){ - assert( pCsr->aMatchinfo ); - sqlite3_free(pCsr->aMatchinfo); - pCsr->zMatchinfo = 0; - pCsr->aMatchinfo = 0; - } - - /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the - ** matchinfo function has been called for this query. In this case - ** allocate the array used to accumulate the matchinfo data and - ** initialize those elements that are constant for every row. - */ - if( pCsr->aMatchinfo==0 ){ - int nMatchinfo = 0; /* Number of u32 elements in match-info */ - int nArg; /* Bytes in zArg */ - int i; /* Used to iterate through zArg */ - - /* Determine the number of phrases in the query */ - pCsr->nPhrase = fts3ExprPhraseCount(pCsr->pExpr); - sInfo.nPhrase = pCsr->nPhrase; - - /* Determine the number of integers in the buffer returned by this call. */ - for(i=0; zArg[i]; i++){ - nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]); - } - - /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */ - nArg = (int)strlen(zArg); - pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1); - if( !pCsr->aMatchinfo ) return SQLITE_NOMEM; - - pCsr->zMatchinfo = (char *)&pCsr->aMatchinfo[nMatchinfo]; - pCsr->nMatchinfo = nMatchinfo; - memcpy(pCsr->zMatchinfo, zArg, nArg+1); - memset(pCsr->aMatchinfo, 0, sizeof(u32)*nMatchinfo); - pCsr->isMatchinfoNeeded = 1; - bGlobal = 1; - } - - sInfo.aMatchinfo = pCsr->aMatchinfo; - sInfo.nPhrase = pCsr->nPhrase; - if( pCsr->isMatchinfoNeeded ){ - rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); - pCsr->isMatchinfoNeeded = 0; - } - - return rc; -} - -/* -** Implementation of snippet() function. -*/ -SQLITE_PRIVATE void sqlite3Fts3Snippet( - sqlite3_context *pCtx, /* SQLite function call context */ - Fts3Cursor *pCsr, /* Cursor object */ - const char *zStart, /* Snippet start text - "" */ - const char *zEnd, /* Snippet end text - "" */ - const char *zEllipsis, /* Snippet ellipsis text - "..." */ - int iCol, /* Extract snippet from this column */ - int nToken /* Approximate number of tokens in snippet */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc = SQLITE_OK; - int i; - StrBuffer res = {0, 0, 0}; - - /* The returned text includes up to four fragments of text extracted from - ** the data in the current row. The first iteration of the for(...) loop - ** below attempts to locate a single fragment of text nToken tokens in - ** size that contains at least one instance of all phrases in the query - ** expression that appear in the current row. If such a fragment of text - ** cannot be found, the second iteration of the loop attempts to locate - ** a pair of fragments, and so on. - */ - int nSnippet = 0; /* Number of fragments in this snippet */ - SnippetFragment aSnippet[4]; /* Maximum of 4 fragments per snippet */ - int nFToken = -1; /* Number of tokens in each fragment */ - - if( !pCsr->pExpr ){ - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); - return; - } - - for(nSnippet=1; 1; nSnippet++){ - - int iSnip; /* Loop counter 0..nSnippet-1 */ - u64 mCovered = 0; /* Bitmask of phrases covered by snippet */ - u64 mSeen = 0; /* Bitmask of phrases seen by BestSnippet() */ - - if( nToken>=0 ){ - nFToken = (nToken+nSnippet-1) / nSnippet; - }else{ - nFToken = -1 * nToken; - } - - for(iSnip=0; iSnipnColumn; iRead++){ - SnippetFragment sF = {0, 0, 0, 0}; - int iS; - if( iCol>=0 && iRead!=iCol ) continue; - - /* Find the best snippet of nFToken tokens in column iRead. */ - rc = fts3BestSnippet(nFToken, pCsr, iRead, mCovered, &mSeen, &sF, &iS); - if( rc!=SQLITE_OK ){ - goto snippet_out; - } - if( iS>iBestScore ){ - *pFragment = sF; - iBestScore = iS; - } - } - - mCovered |= pFragment->covered; - } - - /* If all query phrases seen by fts3BestSnippet() are present in at least - ** one of the nSnippet snippet fragments, break out of the loop. - */ - assert( (mCovered&mSeen)==mCovered ); - if( mSeen==mCovered || nSnippet==SizeofArray(aSnippet) ) break; - } - - assert( nFToken>0 ); - - for(i=0; ipCsr, pExpr, p->iCol, &pList); - nTerm = pExpr->pPhrase->nToken; - if( pList ){ - fts3GetDeltaPosition(&pList, &iPos); - assert( iPos>=0 ); - } - - for(iTerm=0; iTermaTerm[p->iTerm++]; - pT->iOff = nTerm-iTerm-1; - pT->pList = pList; - pT->iPos = iPos; - } - - return rc; -} - -/* -** Implementation of offsets() function. -*/ -SQLITE_PRIVATE void sqlite3Fts3Offsets( - sqlite3_context *pCtx, /* SQLite function call context */ - Fts3Cursor *pCsr /* Cursor object */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; - int rc; /* Return Code */ - int nToken; /* Number of tokens in query */ - int iCol; /* Column currently being processed */ - StrBuffer res = {0, 0, 0}; /* Result string */ - TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ - - if( !pCsr->pExpr ){ - sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC); - return; - } - - memset(&sCtx, 0, sizeof(sCtx)); - assert( pCsr->isRequireSeek==0 ); - - /* Count the number of terms in the query */ - rc = fts3ExprLoadDoclists(pCsr, 0, &nToken); - if( rc!=SQLITE_OK ) goto offsets_out; - - /* Allocate the array of TermOffset iterators. */ - sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken); - if( 0==sCtx.aTerm ){ - rc = SQLITE_NOMEM; - goto offsets_out; - } - sCtx.iDocid = pCsr->iPrevId; - sCtx.pCsr = pCsr; - - /* Loop through the table columns, appending offset information to - ** string-buffer res for each column. - */ - for(iCol=0; iColnColumn; iCol++){ - sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ - const char *ZDUMMY; /* Dummy argument used with xNext() */ - int NDUMMY = 0; /* Dummy argument used with xNext() */ - int iStart = 0; - int iEnd = 0; - int iCurrent = 0; - const char *zDoc; - int nDoc; - - /* Initialize the contents of sCtx.aTerm[] for column iCol. There is - ** no way that this operation can fail, so the return code from - ** fts3ExprIterate() can be discarded. - */ - sCtx.iCol = iCol; - sCtx.iTerm = 0; - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx); - - /* Retreive the text stored in column iCol. If an SQL NULL is stored - ** in column iCol, jump immediately to the next iteration of the loop. - ** If an OOM occurs while retrieving the data (this can happen if SQLite - ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM - ** to the caller. - */ - zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1); - nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1); - if( zDoc==0 ){ - if( sqlite3_column_type(pCsr->pStmt, iCol+1)==SQLITE_NULL ){ - continue; - } - rc = SQLITE_NOMEM; - goto offsets_out; - } - - /* Initialize a tokenizer iterator to iterate through column iCol. */ - rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, - zDoc, nDoc, &pC - ); - if( rc!=SQLITE_OK ) goto offsets_out; - - rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); - while( rc==SQLITE_OK ){ - int i; /* Used to loop through terms */ - int iMinPos = 0x7FFFFFFF; /* Position of next token */ - TermOffset *pTerm = 0; /* TermOffset associated with next token */ - - for(i=0; ipList && (pT->iPos-pT->iOff)iPos-pT->iOff; - pTerm = pT; - } - } - - if( !pTerm ){ - /* All offsets for this column have been gathered. */ - rc = SQLITE_DONE; - }else{ - assert( iCurrent<=iMinPos ); - if( 0==(0xFE&*pTerm->pList) ){ - pTerm->pList = 0; - }else{ - fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos); - } - while( rc==SQLITE_OK && iCurrentxNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); - } - if( rc==SQLITE_OK ){ - char aBuffer[64]; - sqlite3_snprintf(sizeof(aBuffer), aBuffer, - "%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart - ); - rc = fts3StringAppend(&res, aBuffer, -1); - }else if( rc==SQLITE_DONE && pTab->zContentTbl==0 ){ - rc = FTS_CORRUPT_VTAB; - } - } - } - if( rc==SQLITE_DONE ){ - rc = SQLITE_OK; - } - - pMod->xClose(pC); - if( rc!=SQLITE_OK ) goto offsets_out; - } - - offsets_out: - sqlite3_free(sCtx.aTerm); - assert( rc!=SQLITE_DONE ); - sqlite3Fts3SegmentsClose(pTab); - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pCtx, rc); - sqlite3_free(res.z); - }else{ - sqlite3_result_text(pCtx, res.z, res.n-1, sqlite3_free); - } - return; -} - -/* -** Implementation of matchinfo() function. -*/ -SQLITE_PRIVATE void sqlite3Fts3Matchinfo( - sqlite3_context *pContext, /* Function call context */ - Fts3Cursor *pCsr, /* FTS3 table cursor */ - const char *zArg /* Second arg to matchinfo() function */ -){ - Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc; - int i; - const char *zFormat; - - if( zArg ){ - for(i=0; zArg[i]; i++){ - char *zErr = 0; - if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ - sqlite3_result_error(pContext, zErr, -1); - sqlite3_free(zErr); - return; - } - } - zFormat = zArg; - }else{ - zFormat = FTS3_MATCHINFO_DEFAULT; - } - - if( !pCsr->pExpr ){ - sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); - return; - } - - /* Retrieve matchinfo() data. */ - rc = fts3GetMatchinfo(pCsr, zFormat); - sqlite3Fts3SegmentsClose(pTab); - - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pContext, rc); - }else{ - int n = pCsr->nMatchinfo * sizeof(u32); - sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); - } -} - -#endif - -/************** End of fts3_snippet.c ****************************************/ -/************** Begin file fts3_unicode.c ************************************/ -/* -** 2012 May 24 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -** -** Implementation of the "unicode" full-text-search tokenizer. -*/ - -#ifdef SQLITE_ENABLE_FTS4_UNICODE61 - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) - -/* #include */ -/* #include */ -/* #include */ -/* #include */ - - -/* -** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied -** from the sqlite3 source file utf.c. If this file is compiled as part -** of the amalgamation, they are not required. -*/ -#ifndef SQLITE_AMALGAMATION - -static const unsigned char sqlite3Utf8Trans1[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, -}; - -#define READ_UTF8(zIn, zTerm, c) \ - c = *(zIn++); \ - if( c>=0xc0 ){ \ - c = sqlite3Utf8Trans1[c-0xc0]; \ - while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \ - c = (c<<6) + (0x3f & *(zIn++)); \ - } \ - if( c<0x80 \ - || (c&0xFFFFF800)==0xD800 \ - || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ - } - -#define WRITE_UTF8(zOut, c) { \ - if( c<0x00080 ){ \ - *zOut++ = (u8)(c&0xFF); \ - } \ - else if( c<0x00800 ){ \ - *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - } \ - else if( c<0x10000 ){ \ - *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \ - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - }else{ \ - *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \ - *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \ - *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ - *zOut++ = 0x80 + (u8)(c & 0x3F); \ - } \ -} - -#endif /* ifndef SQLITE_AMALGAMATION */ - -typedef struct unicode_tokenizer unicode_tokenizer; -typedef struct unicode_cursor unicode_cursor; - -struct unicode_tokenizer { - sqlite3_tokenizer base; - int bRemoveDiacritic; - int nException; - int *aiException; -}; - -struct unicode_cursor { - sqlite3_tokenizer_cursor base; - const unsigned char *aInput; /* Input text being tokenized */ - int nInput; /* Size of aInput[] in bytes */ - int iOff; /* Current offset within aInput[] */ - int iToken; /* Index of next token to be returned */ - char *zToken; /* storage for current token */ - int nAlloc; /* space allocated at zToken */ -}; - - -/* -** Destroy a tokenizer allocated by unicodeCreate(). -*/ -static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){ - if( pTokenizer ){ - unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer; - sqlite3_free(p->aiException); - sqlite3_free(p); - } - return SQLITE_OK; -} - -/* -** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE -** statement has specified that the tokenizer for this table shall consider -** all characters in string zIn/nIn to be separators (if bAlnum==0) or -** token characters (if bAlnum==1). -** -** For each codepoint in the zIn/nIn string, this function checks if the -** sqlite3FtsUnicodeIsalnum() function already returns the desired result. -** If so, no action is taken. Otherwise, the codepoint is added to the -** unicode_tokenizer.aiException[] array. For the purposes of tokenization, -** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all -** codepoints in the aiException[] array. -** -** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic() -** identifies as a diacritic) occurs in the zIn/nIn string it is ignored. -** It is not possible to change the behavior of the tokenizer with respect -** to these codepoints. -*/ -static int unicodeAddExceptions( - unicode_tokenizer *p, /* Tokenizer to add exceptions to */ - int bAlnum, /* Replace Isalnum() return value with this */ - const char *zIn, /* Array of characters to make exceptions */ - int nIn /* Length of z in bytes */ -){ - const unsigned char *z = (const unsigned char *)zIn; - const unsigned char *zTerm = &z[nIn]; - int iCode; - int nEntry = 0; - - assert( bAlnum==0 || bAlnum==1 ); - - while( zaiException, (p->nException+nEntry)*sizeof(int)); - if( aNew==0 ) return SQLITE_NOMEM; - nNew = p->nException; - - z = (const unsigned char *)zIn; - while( zi; j--) aNew[j] = aNew[j-1]; - aNew[i] = iCode; - nNew++; - } - } - p->aiException = aNew; - p->nException = nNew; - } - - return SQLITE_OK; -} - -/* -** Return true if the p->aiException[] array contains the value iCode. -*/ -static int unicodeIsException(unicode_tokenizer *p, int iCode){ - if( p->nException>0 ){ - int *a = p->aiException; - int iLo = 0; - int iHi = p->nException-1; - - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( iCode==a[iTest] ){ - return 1; - }else if( iCode>a[iTest] ){ - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - } - - return 0; -} - -/* -** Return true if, for the purposes of tokenization, codepoint iCode is -** considered a token character (not a separator). -*/ -static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){ - assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 ); - return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode); -} - -/* -** Create a new tokenizer instance. -*/ -static int unicodeCreate( - int nArg, /* Size of array argv[] */ - const char * const *azArg, /* Tokenizer creation arguments */ - sqlite3_tokenizer **pp /* OUT: New tokenizer handle */ -){ - unicode_tokenizer *pNew; /* New tokenizer object */ - int i; - int rc = SQLITE_OK; - - pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer)); - if( pNew==NULL ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(unicode_tokenizer)); - pNew->bRemoveDiacritic = 1; - - for(i=0; rc==SQLITE_OK && ibRemoveDiacritic = 1; - } - else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){ - pNew->bRemoveDiacritic = 0; - } - else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){ - rc = unicodeAddExceptions(pNew, 1, &z[11], n-11); - } - else if( n>=11 && memcmp("separators=", z, 11)==0 ){ - rc = unicodeAddExceptions(pNew, 0, &z[11], n-11); - } - else{ - /* Unrecognized argument */ - rc = SQLITE_ERROR; - } - } - - if( rc!=SQLITE_OK ){ - unicodeDestroy((sqlite3_tokenizer *)pNew); - pNew = 0; - } - *pp = (sqlite3_tokenizer *)pNew; - return rc; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int unicodeOpen( - sqlite3_tokenizer *p, /* The tokenizer */ - const char *aInput, /* Input string */ - int nInput, /* Size of string aInput in bytes */ - sqlite3_tokenizer_cursor **pp /* OUT: New cursor object */ -){ - unicode_cursor *pCsr; - - pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor)); - if( pCsr==0 ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(unicode_cursor)); - - pCsr->aInput = (const unsigned char *)aInput; - if( aInput==0 ){ - pCsr->nInput = 0; - }else if( nInput<0 ){ - pCsr->nInput = (int)strlen(aInput); - }else{ - pCsr->nInput = nInput; - } - - *pp = &pCsr->base; - UNUSED_PARAMETER(p); - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to -** simpleOpen() above. -*/ -static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){ - unicode_cursor *pCsr = (unicode_cursor *) pCursor; - sqlite3_free(pCsr->zToken); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. The cursor must -** have been opened by a prior call to simpleOpen(). -*/ -static int unicodeNext( - sqlite3_tokenizer_cursor *pC, /* Cursor returned by simpleOpen */ - const char **paToken, /* OUT: Token text */ - int *pnToken, /* OUT: Number of bytes at *paToken */ - int *piStart, /* OUT: Starting offset of token */ - int *piEnd, /* OUT: Ending offset of token */ - int *piPos /* OUT: Position integer of token */ -){ - unicode_cursor *pCsr = (unicode_cursor *)pC; - unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer); - int iCode; - char *zOut; - const unsigned char *z = &pCsr->aInput[pCsr->iOff]; - const unsigned char *zStart = z; - const unsigned char *zEnd; - const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput]; - - /* Scan past any delimiter characters before the start of the next token. - ** Return SQLITE_DONE early if this takes us all the way to the end of - ** the input. */ - while( z=zTerm ) return SQLITE_DONE; - - zOut = pCsr->zToken; - do { - int iOut; - - /* Grow the output buffer if required. */ - if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){ - char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64); - if( !zNew ) return SQLITE_NOMEM; - zOut = &zNew[zOut - pCsr->zToken]; - pCsr->zToken = zNew; - pCsr->nAlloc += 64; - } - - /* Write the folded case of the last character read to the output */ - zEnd = z; - iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic); - if( iOut ){ - WRITE_UTF8(zOut, iOut); - } - - /* If the cursor is not at EOF, read the next character */ - if( z>=zTerm ) break; - READ_UTF8(z, zTerm, iCode); - }while( unicodeIsAlnum(p, iCode) - || sqlite3FtsUnicodeIsdiacritic(iCode) - ); - - /* Set the output variables and return. */ - pCsr->iOff = (z - pCsr->aInput); - *paToken = pCsr->zToken; - *pnToken = zOut - pCsr->zToken; - *piStart = (zStart - pCsr->aInput); - *piEnd = (zEnd - pCsr->aInput); - *piPos = pCsr->iToken++; - return SQLITE_OK; -} - -/* -** Set *ppModule to a pointer to the sqlite3_tokenizer_module -** structure for the unicode tokenizer. -*/ -SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){ - static const sqlite3_tokenizer_module module = { - 0, - unicodeCreate, - unicodeDestroy, - unicodeOpen, - unicodeClose, - unicodeNext, - 0, - }; - *ppModule = &module; -} - -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ -#endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */ - -/************** End of fts3_unicode.c ****************************************/ -/************** Begin file fts3_unicode2.c ***********************************/ -/* -** 2012 May 25 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -****************************************************************************** -*/ - -/* -** DO NOT EDIT THIS MACHINE GENERATED FILE. -*/ - -#if defined(SQLITE_ENABLE_FTS4_UNICODE61) -#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) - -/* #include */ - -/* -** Return true if the argument corresponds to a unicode codepoint -** classified as either a letter or a number. Otherwise false. -** -** The results are undefined if the value passed to this function -** is less than zero. -*/ -SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){ - /* Each unsigned integer in the following array corresponds to a contiguous - ** range of unicode codepoints that are not either letters or numbers (i.e. - ** codepoints for which this function should return 0). - ** - ** The most significant 22 bits in each 32-bit value contain the first - ** codepoint in the range. The least significant 10 bits are used to store - ** the size of the range (always at least 1). In other words, the value - ** ((C<<22) + N) represents a range of N codepoints starting with codepoint - ** C. It is not possible to represent a range larger than 1023 codepoints - ** using this format. - */ - const static unsigned int aEntry[] = { - 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, - 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, - 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, - 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, - 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, - 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, - 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, - 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, - 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, - 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, - 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, - 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, - 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, - 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, - 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, - 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, - 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, - 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, - 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, - 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, - 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, - 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, - 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, - 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, - 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, - 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, - 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, - 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, - 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, - 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, - 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, - 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, - 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, - 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, - 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, - 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, - 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, - 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, - 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, - 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, - 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, - 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, - 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, - 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, - 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, - 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, - 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, - 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, - 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, - 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, - 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, - 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, - 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, - 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, - 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, - 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, - 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, - 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, - 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, - 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, - 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, - 0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, - 0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, - 0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, - 0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, - 0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, - 0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, - 0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, - 0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, - 0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, - 0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, - 0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, - 0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, - 0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, - 0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, - 0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, - 0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, - 0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, - 0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, - 0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, - 0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, - 0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001, - 0x43FFF401, - }; - static const unsigned int aAscii[4] = { - 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, - }; - - if( c<128 ){ - return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); - }else if( c<(1<<22) ){ - unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; - int iRes; - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; - int iLo = 0; - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( key >= aEntry[iTest] ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - assert( aEntry[0]=aEntry[iRes] ); - return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); - } - return 1; -} - - -/* -** If the argument is a codepoint corresponding to a lowercase letter -** in the ASCII range with a diacritic added, return the codepoint -** of the ASCII letter only. For example, if passed 235 - "LATIN -** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER -** E"). The resuls of passing a codepoint that corresponds to an -** uppercase letter are undefined. -*/ -static int remove_diacritic(int c){ - unsigned short aDia[] = { - 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, - 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, - 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, - 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, - 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928, - 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234, - 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504, - 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529, - 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, - 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122, - 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536, - 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730, - 62924, 63050, 63082, 63274, 63390, - }; - char aChar[] = { - '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c', - 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', - 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', - 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', - 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', - 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', - 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', - 'e', 'i', 'o', 'u', 'y', - }; - - unsigned int key = (((unsigned int)c)<<3) | 0x00000007; - int iRes = 0; - int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; - int iLo = 0; - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - if( key >= aDia[iTest] ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - assert( key>=aDia[iRes] ); - return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]); -}; - - -/* -** Return true if the argument interpreted as a unicode codepoint -** is a diacritical modifier character. -*/ -SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int c){ - unsigned int mask0 = 0x08029FDF; - unsigned int mask1 = 0x000361F8; - if( c<768 || c>817 ) return 0; - return (c < 768+32) ? - (mask0 & (1 << (c-768))) : - (mask1 & (1 << (c-768-32))); -} - - -/* -** Interpret the argument as a unicode codepoint. If the codepoint -** is an upper case character that has a lower case equivalent, -** return the codepoint corresponding to the lower case version. -** Otherwise, return a copy of the argument. -** -** The results are undefined if the value passed to this function -** is less than zero. -*/ -SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){ - /* Each entry in the following array defines a rule for folding a range - ** of codepoints to lower case. The rule applies to a range of nRange - ** codepoints starting at codepoint iCode. - ** - ** If the least significant bit in flags is clear, then the rule applies - ** to all nRange codepoints (i.e. all nRange codepoints are upper case and - ** need to be folded). Or, if it is set, then the rule only applies to - ** every second codepoint in the range, starting with codepoint C. - ** - ** The 7 most significant bits in flags are an index into the aiOff[] - ** array. If a specific codepoint C does require folding, then its lower - ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF). - ** - ** The contents of this array are generated by parsing the CaseFolding.txt - ** file distributed as part of the "Unicode Character Database". See - ** http://www.unicode.org for details. - */ - static const struct TableEntry { - unsigned short iCode; - unsigned char flags; - unsigned char nRange; - } aEntry[] = { - {65, 14, 26}, {181, 64, 1}, {192, 14, 23}, - {216, 14, 7}, {256, 1, 48}, {306, 1, 6}, - {313, 1, 16}, {330, 1, 46}, {376, 116, 1}, - {377, 1, 6}, {383, 104, 1}, {385, 50, 1}, - {386, 1, 4}, {390, 44, 1}, {391, 0, 1}, - {393, 42, 2}, {395, 0, 1}, {398, 32, 1}, - {399, 38, 1}, {400, 40, 1}, {401, 0, 1}, - {403, 42, 1}, {404, 46, 1}, {406, 52, 1}, - {407, 48, 1}, {408, 0, 1}, {412, 52, 1}, - {413, 54, 1}, {415, 56, 1}, {416, 1, 6}, - {422, 60, 1}, {423, 0, 1}, {425, 60, 1}, - {428, 0, 1}, {430, 60, 1}, {431, 0, 1}, - {433, 58, 2}, {435, 1, 4}, {439, 62, 1}, - {440, 0, 1}, {444, 0, 1}, {452, 2, 1}, - {453, 0, 1}, {455, 2, 1}, {456, 0, 1}, - {458, 2, 1}, {459, 1, 18}, {478, 1, 18}, - {497, 2, 1}, {498, 1, 4}, {502, 122, 1}, - {503, 134, 1}, {504, 1, 40}, {544, 110, 1}, - {546, 1, 18}, {570, 70, 1}, {571, 0, 1}, - {573, 108, 1}, {574, 68, 1}, {577, 0, 1}, - {579, 106, 1}, {580, 28, 1}, {581, 30, 1}, - {582, 1, 10}, {837, 36, 1}, {880, 1, 4}, - {886, 0, 1}, {902, 18, 1}, {904, 16, 3}, - {908, 26, 1}, {910, 24, 2}, {913, 14, 17}, - {931, 14, 9}, {962, 0, 1}, {975, 4, 1}, - {976, 140, 1}, {977, 142, 1}, {981, 146, 1}, - {982, 144, 1}, {984, 1, 24}, {1008, 136, 1}, - {1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1}, - {1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1}, - {1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32}, - {1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1}, - {1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38}, - {4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1}, - {7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1}, - {7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6}, - {7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6}, - {8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8}, - {8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2}, - {8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1}, - {8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2}, - {8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2}, - {8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2}, - {8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1}, - {8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16}, - {8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47}, - {11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1}, - {11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1}, - {11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1}, - {11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2}, - {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1}, - {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14}, - {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1}, - {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1}, - {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1}, - {65313, 14, 26}, - }; - static const unsigned short aiOff[] = { - 1, 2, 8, 15, 16, 26, 28, 32, - 37, 38, 40, 48, 63, 64, 69, 71, - 79, 80, 116, 202, 203, 205, 206, 207, - 209, 210, 211, 213, 214, 217, 218, 219, - 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, - 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, - 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, - 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, - 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, - 65514, 65521, 65527, 65528, 65529, - }; - - int ret = c; - - assert( c>=0 ); - assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); - - if( c<128 ){ - if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); - }else if( c<65536 ){ - int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; - int iLo = 0; - int iRes = -1; - - while( iHi>=iLo ){ - int iTest = (iHi + iLo) / 2; - int cmp = (c - aEntry[iTest].iCode); - if( cmp>=0 ){ - iRes = iTest; - iLo = iTest+1; - }else{ - iHi = iTest-1; - } - } - assert( iRes<0 || c>=aEntry[iRes].iCode ); - - if( iRes>=0 ){ - const struct TableEntry *p = &aEntry[iRes]; - if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ - ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; - assert( ret>0 ); - } - } - - if( bRemoveDiacritic ) ret = remove_diacritic(ret); - } - - else if( c>=66560 && c<66600 ){ - ret = c + 40; - } - - return ret; -} -#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */ -#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */ - -/************** End of fts3_unicode2.c ***************************************/ -/************** Begin file rtree.c *******************************************/ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file contains code for implementations of the r-tree and r*-tree -** algorithms packaged as an SQLite virtual table module. -*/ - -/* -** Database Format of R-Tree Tables -** -------------------------------- -** -** The data structure for a single virtual r-tree table is stored in three -** native SQLite tables declared as follows. In each case, the '%' character -** in the table name is replaced with the user-supplied name of the r-tree -** table. -** -** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB) -** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) -** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER) -** -** The data for each node of the r-tree structure is stored in the %_node -** table. For each node that is not the root node of the r-tree, there is -** an entry in the %_parent table associating the node with its parent. -** And for each row of data in the table, there is an entry in the %_rowid -** table that maps from the entries rowid to the id of the node that it -** is stored on. -** -** The root node of an r-tree always exists, even if the r-tree table is -** empty. The nodeno of the root node is always 1. All other nodes in the -** table must be the same size as the root node. The content of each node -** is formatted as follows: -** -** 1. If the node is the root node (node 1), then the first 2 bytes -** of the node contain the tree depth as a big-endian integer. -** For non-root nodes, the first 2 bytes are left unused. -** -** 2. The next 2 bytes contain the number of entries currently -** stored in the node. -** -** 3. The remainder of the node contains the node entries. Each entry -** consists of a single 8-byte integer followed by an even number -** of 4-byte coordinates. For leaf nodes the integer is the rowid -** of a record. For internal nodes it is the node number of a -** child page. -*/ - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) - -/* -** This file contains an implementation of a couple of different variants -** of the r-tree algorithm. See the README file for further details. The -** same data-structure is used for all, but the algorithms for insert and -** delete operations vary. The variants used are selected at compile time -** by defining the following symbols: -*/ - -/* Either, both or none of the following may be set to activate -** r*tree variant algorithms. -*/ -#define VARIANT_RSTARTREE_CHOOSESUBTREE 0 -#define VARIANT_RSTARTREE_REINSERT 1 - -/* -** Exactly one of the following must be set to 1. -*/ -#define VARIANT_GUTTMAN_QUADRATIC_SPLIT 0 -#define VARIANT_GUTTMAN_LINEAR_SPLIT 0 -#define VARIANT_RSTARTREE_SPLIT 1 - -#define VARIANT_GUTTMAN_SPLIT \ - (VARIANT_GUTTMAN_LINEAR_SPLIT||VARIANT_GUTTMAN_QUADRATIC_SPLIT) - -#if VARIANT_GUTTMAN_QUADRATIC_SPLIT - #define PickNext QuadraticPickNext - #define PickSeeds QuadraticPickSeeds - #define AssignCells splitNodeGuttman -#endif -#if VARIANT_GUTTMAN_LINEAR_SPLIT - #define PickNext LinearPickNext - #define PickSeeds LinearPickSeeds - #define AssignCells splitNodeGuttman -#endif -#if VARIANT_RSTARTREE_SPLIT - #define AssignCells splitNodeStartree -#endif - -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - -#ifndef SQLITE_CORE - SQLITE_EXTENSION_INIT1 -#else -#endif - -/* #include */ -/* #include */ - -#ifndef SQLITE_AMALGAMATION -#include "sqlite3rtree.h" -typedef sqlite3_int64 i64; -typedef unsigned char u8; -typedef unsigned int u32; -#endif - -/* The following macro is used to suppress compiler warnings. -*/ -#ifndef UNUSED_PARAMETER -# define UNUSED_PARAMETER(x) (void)(x) -#endif - -typedef struct Rtree Rtree; -typedef struct RtreeCursor RtreeCursor; -typedef struct RtreeNode RtreeNode; -typedef struct RtreeCell RtreeCell; -typedef struct RtreeConstraint RtreeConstraint; -typedef struct RtreeMatchArg RtreeMatchArg; -typedef struct RtreeGeomCallback RtreeGeomCallback; -typedef union RtreeCoord RtreeCoord; - -/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ -#define RTREE_MAX_DIMENSIONS 5 - -/* Size of hash table Rtree.aHash. This hash table is not expected to -** ever contain very many entries, so a fixed number of buckets is -** used. -*/ -#define HASHSIZE 128 - -/* -** An rtree virtual-table object. -*/ -struct Rtree { - sqlite3_vtab base; - sqlite3 *db; /* Host database connection */ - int iNodeSize; /* Size in bytes of each node in the node table */ - int nDim; /* Number of dimensions */ - int nBytesPerCell; /* Bytes consumed per cell */ - int iDepth; /* Current depth of the r-tree structure */ - char *zDb; /* Name of database containing r-tree table */ - char *zName; /* Name of r-tree table */ - RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ - int nBusy; /* Current number of users of this structure */ - - /* List of nodes removed during a CondenseTree operation. List is - ** linked together via the pointer normally used for hash chains - - ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree - ** headed by the node (leaf nodes have RtreeNode.iNode==0). - */ - RtreeNode *pDeleted; - int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */ - - /* Statements to read/write/delete a record from xxx_node */ - sqlite3_stmt *pReadNode; - sqlite3_stmt *pWriteNode; - sqlite3_stmt *pDeleteNode; - - /* Statements to read/write/delete a record from xxx_rowid */ - sqlite3_stmt *pReadRowid; - sqlite3_stmt *pWriteRowid; - sqlite3_stmt *pDeleteRowid; - - /* Statements to read/write/delete a record from xxx_parent */ - sqlite3_stmt *pReadParent; - sqlite3_stmt *pWriteParent; - sqlite3_stmt *pDeleteParent; - - int eCoordType; -}; - -/* Possible values for eCoordType: */ -#define RTREE_COORD_REAL32 0 -#define RTREE_COORD_INT32 1 - -/* -** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will -** only deal with integer coordinates. No floating point operations -** will be done. -*/ -#ifdef SQLITE_RTREE_INT_ONLY - typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ - typedef int RtreeValue; /* Low accuracy coordinate */ -#else - typedef double RtreeDValue; /* High accuracy coordinate */ - typedef float RtreeValue; /* Low accuracy coordinate */ -#endif - -/* -** The minimum number of cells allowed for a node is a third of the -** maximum. In Gutman's notation: -** -** m = M/3 -** -** If an R*-tree "Reinsert" operation is required, the same number of -** cells are removed from the overfull node and reinserted into the tree. -*/ -#define RTREE_MINCELLS(p) ((((p)->iNodeSize-4)/(p)->nBytesPerCell)/3) -#define RTREE_REINSERT(p) RTREE_MINCELLS(p) -#define RTREE_MAXCELLS 51 - -/* -** The smallest possible node-size is (512-64)==448 bytes. And the largest -** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates). -** Therefore all non-root nodes must contain at least 3 entries. Since -** 2^40 is greater than 2^64, an r-tree structure always has a depth of -** 40 or less. -*/ -#define RTREE_MAX_DEPTH 40 - -/* -** An rtree cursor object. -*/ -struct RtreeCursor { - sqlite3_vtab_cursor base; - RtreeNode *pNode; /* Node cursor is currently pointing at */ - int iCell; /* Index of current cell in pNode */ - int iStrategy; /* Copy of idxNum search parameter */ - int nConstraint; /* Number of entries in aConstraint */ - RtreeConstraint *aConstraint; /* Search constraints. */ -}; - -union RtreeCoord { - RtreeValue f; - int i; -}; - -/* -** The argument is an RtreeCoord. Return the value stored within the RtreeCoord -** formatted as a RtreeDValue (double or int64). This macro assumes that local -** variable pRtree points to the Rtree structure associated with the -** RtreeCoord. -*/ -#ifdef SQLITE_RTREE_INT_ONLY -# define DCOORD(coord) ((RtreeDValue)coord.i) -#else -# define DCOORD(coord) ( \ - (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ - ((double)coord.f) : \ - ((double)coord.i) \ - ) -#endif - -/* -** A search constraint. -*/ -struct RtreeConstraint { - int iCoord; /* Index of constrained coordinate */ - int op; /* Constraining operation */ - RtreeDValue rValue; /* Constraint value. */ - int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); - sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ -}; - -/* Possible values for RtreeConstraint.op */ -#define RTREE_EQ 0x41 -#define RTREE_LE 0x42 -#define RTREE_LT 0x43 -#define RTREE_GE 0x44 -#define RTREE_GT 0x45 -#define RTREE_MATCH 0x46 - -/* -** An rtree structure node. -*/ -struct RtreeNode { - RtreeNode *pParent; /* Parent node */ - i64 iNode; - int nRef; - int isDirty; - u8 *zData; - RtreeNode *pNext; /* Next node in this hash chain */ -}; -#define NCELL(pNode) readInt16(&(pNode)->zData[2]) - -/* -** Structure to store a deserialized rtree record. -*/ -struct RtreeCell { - i64 iRowid; - RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; -}; - - -/* -** Value for the first field of every RtreeMatchArg object. The MATCH -** operator tests that the first field of a blob operand matches this -** value to avoid operating on invalid blobs (which could cause a segfault). -*/ -#define RTREE_GEOMETRY_MAGIC 0x891245AB - -/* -** An instance of this structure must be supplied as a blob argument to -** the right-hand-side of an SQL MATCH operator used to constrain an -** r-tree query. -*/ -struct RtreeMatchArg { - u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ - int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); - void *pContext; - int nParam; - RtreeDValue aParam[1]; -}; - -/* -** When a geometry callback is created (see sqlite3_rtree_geometry_callback), -** a single instance of the following structure is allocated. It is used -** as the context for the user-function created by by s_r_g_c(). The object -** is eventually deleted by the destructor mechanism provided by -** sqlite3_create_function_v2() (which is called by s_r_g_c() to create -** the geometry callback function). -*/ -struct RtreeGeomCallback { - int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); - void *pContext; -}; - -#ifndef MAX -# define MAX(x,y) ((x) < (y) ? (y) : (x)) -#endif -#ifndef MIN -# define MIN(x,y) ((x) > (y) ? (y) : (x)) -#endif - -/* -** Functions to deserialize a 16 bit integer, 32 bit real number and -** 64 bit integer. The deserialized value is returned. -*/ -static int readInt16(u8 *p){ - return (p[0]<<8) + p[1]; -} -static void readCoord(u8 *p, RtreeCoord *pCoord){ - u32 i = ( - (((u32)p[0]) << 24) + - (((u32)p[1]) << 16) + - (((u32)p[2]) << 8) + - (((u32)p[3]) << 0) - ); - *(u32 *)pCoord = i; -} -static i64 readInt64(u8 *p){ - return ( - (((i64)p[0]) << 56) + - (((i64)p[1]) << 48) + - (((i64)p[2]) << 40) + - (((i64)p[3]) << 32) + - (((i64)p[4]) << 24) + - (((i64)p[5]) << 16) + - (((i64)p[6]) << 8) + - (((i64)p[7]) << 0) - ); -} - -/* -** Functions to serialize a 16 bit integer, 32 bit real number and -** 64 bit integer. The value returned is the number of bytes written -** to the argument buffer (always 2, 4 and 8 respectively). -*/ -static int writeInt16(u8 *p, int i){ - p[0] = (i>> 8)&0xFF; - p[1] = (i>> 0)&0xFF; - return 2; -} -static int writeCoord(u8 *p, RtreeCoord *pCoord){ - u32 i; - assert( sizeof(RtreeCoord)==4 ); - assert( sizeof(u32)==4 ); - i = *(u32 *)pCoord; - p[0] = (i>>24)&0xFF; - p[1] = (i>>16)&0xFF; - p[2] = (i>> 8)&0xFF; - p[3] = (i>> 0)&0xFF; - return 4; -} -static int writeInt64(u8 *p, i64 i){ - p[0] = (i>>56)&0xFF; - p[1] = (i>>48)&0xFF; - p[2] = (i>>40)&0xFF; - p[3] = (i>>32)&0xFF; - p[4] = (i>>24)&0xFF; - p[5] = (i>>16)&0xFF; - p[6] = (i>> 8)&0xFF; - p[7] = (i>> 0)&0xFF; - return 8; -} - -/* -** Increment the reference count of node p. -*/ -static void nodeReference(RtreeNode *p){ - if( p ){ - p->nRef++; - } -} - -/* -** Clear the content of node p (set all bytes to 0x00). -*/ -static void nodeZero(Rtree *pRtree, RtreeNode *p){ - memset(&p->zData[2], 0, pRtree->iNodeSize-2); - p->isDirty = 1; -} - -/* -** Given a node number iNode, return the corresponding key to use -** in the Rtree.aHash table. -*/ -static int nodeHash(i64 iNode){ - return ( - (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^ - (iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0) - ) % HASHSIZE; -} - -/* -** Search the node hash table for node iNode. If found, return a pointer -** to it. Otherwise, return 0. -*/ -static RtreeNode *nodeHashLookup(Rtree *pRtree, i64 iNode){ - RtreeNode *p; - for(p=pRtree->aHash[nodeHash(iNode)]; p && p->iNode!=iNode; p=p->pNext); - return p; -} - -/* -** Add node pNode to the node hash table. -*/ -static void nodeHashInsert(Rtree *pRtree, RtreeNode *pNode){ - int iHash; - assert( pNode->pNext==0 ); - iHash = nodeHash(pNode->iNode); - pNode->pNext = pRtree->aHash[iHash]; - pRtree->aHash[iHash] = pNode; -} - -/* -** Remove node pNode from the node hash table. -*/ -static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){ - RtreeNode **pp; - if( pNode->iNode!=0 ){ - pp = &pRtree->aHash[nodeHash(pNode->iNode)]; - for( ; (*pp)!=pNode; pp = &(*pp)->pNext){ assert(*pp); } - *pp = pNode->pNext; - pNode->pNext = 0; - } -} - -/* -** Allocate and return new r-tree node. Initially, (RtreeNode.iNode==0), -** indicating that node has not yet been assigned a node number. It is -** assigned a node number when nodeWrite() is called to write the -** node contents out to the database. -*/ -static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ - RtreeNode *pNode; - pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize); - if( pNode ){ - memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); - pNode->zData = (u8 *)&pNode[1]; - pNode->nRef = 1; - pNode->pParent = pParent; - pNode->isDirty = 1; - nodeReference(pParent); - } - return pNode; -} - -/* -** Obtain a reference to an r-tree node. -*/ -static int -nodeAcquire( - Rtree *pRtree, /* R-tree structure */ - i64 iNode, /* Node number to load */ - RtreeNode *pParent, /* Either the parent node or NULL */ - RtreeNode **ppNode /* OUT: Acquired node */ -){ - int rc; - int rc2 = SQLITE_OK; - RtreeNode *pNode; - - /* Check if the requested node is already in the hash table. If so, - ** increase its reference count and return it. - */ - if( (pNode = nodeHashLookup(pRtree, iNode)) ){ - assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); - if( pParent && !pNode->pParent ){ - nodeReference(pParent); - pNode->pParent = pParent; - } - pNode->nRef++; - *ppNode = pNode; - return SQLITE_OK; - } - - sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); - rc = sqlite3_step(pRtree->pReadNode); - if( rc==SQLITE_ROW ){ - const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); - if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){ - pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize); - if( !pNode ){ - rc2 = SQLITE_NOMEM; - }else{ - pNode->pParent = pParent; - pNode->zData = (u8 *)&pNode[1]; - pNode->nRef = 1; - pNode->iNode = iNode; - pNode->isDirty = 0; - pNode->pNext = 0; - memcpy(pNode->zData, zBlob, pRtree->iNodeSize); - nodeReference(pParent); - } - } - } - rc = sqlite3_reset(pRtree->pReadNode); - if( rc==SQLITE_OK ) rc = rc2; - - /* If the root node was just loaded, set pRtree->iDepth to the height - ** of the r-tree structure. A height of zero means all data is stored on - ** the root node. A height of one means the children of the root node - ** are the leaves, and so on. If the depth as specified on the root node - ** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt. - */ - if( pNode && iNode==1 ){ - pRtree->iDepth = readInt16(pNode->zData); - if( pRtree->iDepth>RTREE_MAX_DEPTH ){ - rc = SQLITE_CORRUPT_VTAB; - } - } - - /* If no error has occurred so far, check if the "number of entries" - ** field on the node is too large. If so, set the return code to - ** SQLITE_CORRUPT_VTAB. - */ - if( pNode && rc==SQLITE_OK ){ - if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){ - rc = SQLITE_CORRUPT_VTAB; - } - } - - if( rc==SQLITE_OK ){ - if( pNode!=0 ){ - nodeHashInsert(pRtree, pNode); - }else{ - rc = SQLITE_CORRUPT_VTAB; - } - *ppNode = pNode; - }else{ - sqlite3_free(pNode); - *ppNode = 0; - } - - return rc; -} - -/* -** Overwrite cell iCell of node pNode with the contents of pCell. -*/ -static void nodeOverwriteCell( - Rtree *pRtree, - RtreeNode *pNode, - RtreeCell *pCell, - int iCell -){ - int ii; - u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; - p += writeInt64(p, pCell->iRowid); - for(ii=0; ii<(pRtree->nDim*2); ii++){ - p += writeCoord(p, &pCell->aCoord[ii]); - } - pNode->isDirty = 1; -} - -/* -** Remove cell the cell with index iCell from node pNode. -*/ -static void nodeDeleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell){ - u8 *pDst = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; - u8 *pSrc = &pDst[pRtree->nBytesPerCell]; - int nByte = (NCELL(pNode) - iCell - 1) * pRtree->nBytesPerCell; - memmove(pDst, pSrc, nByte); - writeInt16(&pNode->zData[2], NCELL(pNode)-1); - pNode->isDirty = 1; -} - -/* -** Insert the contents of cell pCell into node pNode. If the insert -** is successful, return SQLITE_OK. -** -** If there is not enough free space in pNode, return SQLITE_FULL. -*/ -static int -nodeInsertCell( - Rtree *pRtree, - RtreeNode *pNode, - RtreeCell *pCell -){ - int nCell; /* Current number of cells in pNode */ - int nMaxCell; /* Maximum number of cells for pNode */ - - nMaxCell = (pRtree->iNodeSize-4)/pRtree->nBytesPerCell; - nCell = NCELL(pNode); - - assert( nCell<=nMaxCell ); - if( nCellzData[2], nCell+1); - pNode->isDirty = 1; - } - - return (nCell==nMaxCell); -} - -/* -** If the node is dirty, write it out to the database. -*/ -static int -nodeWrite(Rtree *pRtree, RtreeNode *pNode){ - int rc = SQLITE_OK; - if( pNode->isDirty ){ - sqlite3_stmt *p = pRtree->pWriteNode; - if( pNode->iNode ){ - sqlite3_bind_int64(p, 1, pNode->iNode); - }else{ - sqlite3_bind_null(p, 1); - } - sqlite3_bind_blob(p, 2, pNode->zData, pRtree->iNodeSize, SQLITE_STATIC); - sqlite3_step(p); - pNode->isDirty = 0; - rc = sqlite3_reset(p); - if( pNode->iNode==0 && rc==SQLITE_OK ){ - pNode->iNode = sqlite3_last_insert_rowid(pRtree->db); - nodeHashInsert(pRtree, pNode); - } - } - return rc; -} - -/* -** Release a reference to a node. If the node is dirty and the reference -** count drops to zero, the node data is written to the database. -*/ -static int -nodeRelease(Rtree *pRtree, RtreeNode *pNode){ - int rc = SQLITE_OK; - if( pNode ){ - assert( pNode->nRef>0 ); - pNode->nRef--; - if( pNode->nRef==0 ){ - if( pNode->iNode==1 ){ - pRtree->iDepth = -1; - } - if( pNode->pParent ){ - rc = nodeRelease(pRtree, pNode->pParent); - } - if( rc==SQLITE_OK ){ - rc = nodeWrite(pRtree, pNode); - } - nodeHashDelete(pRtree, pNode); - sqlite3_free(pNode); - } - } - return rc; -} - -/* -** Return the 64-bit integer value associated with cell iCell of -** node pNode. If pNode is a leaf node, this is a rowid. If it is -** an internal node, then the 64-bit integer is a child page number. -*/ -static i64 nodeGetRowid( - Rtree *pRtree, - RtreeNode *pNode, - int iCell -){ - assert( iCellzData[4 + pRtree->nBytesPerCell*iCell]); -} - -/* -** Return coordinate iCoord from cell iCell in node pNode. -*/ -static void nodeGetCoord( - Rtree *pRtree, - RtreeNode *pNode, - int iCell, - int iCoord, - RtreeCoord *pCoord /* Space to write result to */ -){ - readCoord(&pNode->zData[12 + pRtree->nBytesPerCell*iCell + 4*iCoord], pCoord); -} - -/* -** Deserialize cell iCell of node pNode. Populate the structure pointed -** to by pCell with the results. -*/ -static void nodeGetCell( - Rtree *pRtree, - RtreeNode *pNode, - int iCell, - RtreeCell *pCell -){ - int ii; - pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); - for(ii=0; iinDim*2; ii++){ - nodeGetCoord(pRtree, pNode, iCell, ii, &pCell->aCoord[ii]); - } -} - - -/* Forward declaration for the function that does the work of -** the virtual table module xCreate() and xConnect() methods. -*/ -static int rtreeInit( - sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int -); - -/* -** Rtree virtual table module xCreate method. -*/ -static int rtreeCreate( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1); -} - -/* -** Rtree virtual table module xConnect method. -*/ -static int rtreeConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0); -} - -/* -** Increment the r-tree reference count. -*/ -static void rtreeReference(Rtree *pRtree){ - pRtree->nBusy++; -} - -/* -** Decrement the r-tree reference count. When the reference count reaches -** zero the structure is deleted. -*/ -static void rtreeRelease(Rtree *pRtree){ - pRtree->nBusy--; - if( pRtree->nBusy==0 ){ - sqlite3_finalize(pRtree->pReadNode); - sqlite3_finalize(pRtree->pWriteNode); - sqlite3_finalize(pRtree->pDeleteNode); - sqlite3_finalize(pRtree->pReadRowid); - sqlite3_finalize(pRtree->pWriteRowid); - sqlite3_finalize(pRtree->pDeleteRowid); - sqlite3_finalize(pRtree->pReadParent); - sqlite3_finalize(pRtree->pWriteParent); - sqlite3_finalize(pRtree->pDeleteParent); - sqlite3_free(pRtree); - } -} - -/* -** Rtree virtual table module xDisconnect method. -*/ -static int rtreeDisconnect(sqlite3_vtab *pVtab){ - rtreeRelease((Rtree *)pVtab); - return SQLITE_OK; -} - -/* -** Rtree virtual table module xDestroy method. -*/ -static int rtreeDestroy(sqlite3_vtab *pVtab){ - Rtree *pRtree = (Rtree *)pVtab; - int rc; - char *zCreate = sqlite3_mprintf( - "DROP TABLE '%q'.'%q_node';" - "DROP TABLE '%q'.'%q_rowid';" - "DROP TABLE '%q'.'%q_parent';", - pRtree->zDb, pRtree->zName, - pRtree->zDb, pRtree->zName, - pRtree->zDb, pRtree->zName - ); - if( !zCreate ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0); - sqlite3_free(zCreate); - } - if( rc==SQLITE_OK ){ - rtreeRelease(pRtree); - } - - return rc; -} - -/* -** Rtree virtual table module xOpen method. -*/ -static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ - int rc = SQLITE_NOMEM; - RtreeCursor *pCsr; - - pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor)); - if( pCsr ){ - memset(pCsr, 0, sizeof(RtreeCursor)); - pCsr->base.pVtab = pVTab; - rc = SQLITE_OK; - } - *ppCursor = (sqlite3_vtab_cursor *)pCsr; - - return rc; -} - - -/* -** Free the RtreeCursor.aConstraint[] array and its contents. -*/ -static void freeCursorConstraints(RtreeCursor *pCsr){ - if( pCsr->aConstraint ){ - int i; /* Used to iterate through constraint array */ - for(i=0; inConstraint; i++){ - sqlite3_rtree_geometry *pGeom = pCsr->aConstraint[i].pGeom; - if( pGeom ){ - if( pGeom->xDelUser ) pGeom->xDelUser(pGeom->pUser); - sqlite3_free(pGeom); - } - } - sqlite3_free(pCsr->aConstraint); - pCsr->aConstraint = 0; - } -} - -/* -** Rtree virtual table module xClose method. -*/ -static int rtreeClose(sqlite3_vtab_cursor *cur){ - Rtree *pRtree = (Rtree *)(cur->pVtab); - int rc; - RtreeCursor *pCsr = (RtreeCursor *)cur; - freeCursorConstraints(pCsr); - rc = nodeRelease(pRtree, pCsr->pNode); - sqlite3_free(pCsr); - return rc; -} - -/* -** Rtree virtual table module xEof method. -** -** Return non-zero if the cursor does not currently point to a valid -** record (i.e if the scan has finished), or zero otherwise. -*/ -static int rtreeEof(sqlite3_vtab_cursor *cur){ - RtreeCursor *pCsr = (RtreeCursor *)cur; - return (pCsr->pNode==0); -} - -/* -** The r-tree constraint passed as the second argument to this function is -** guaranteed to be a MATCH constraint. -*/ -static int testRtreeGeom( - Rtree *pRtree, /* R-Tree object */ - RtreeConstraint *pConstraint, /* MATCH constraint to test */ - RtreeCell *pCell, /* Cell to test */ - int *pbRes /* OUT: Test result */ -){ - int i; - RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2]; - int nCoord = pRtree->nDim*2; - - assert( pConstraint->op==RTREE_MATCH ); - assert( pConstraint->pGeom ); - - for(i=0; iaCoord[i]); - } - return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes); -} - -/* -** Cursor pCursor currently points to a cell in a non-leaf page. -** Set *pbEof to true if the sub-tree headed by the cell is filtered -** (excluded) by the constraints in the pCursor->aConstraint[] -** array, or false otherwise. -** -** Return SQLITE_OK if successful or an SQLite error code if an error -** occurs within a geometry callback. -*/ -static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ - RtreeCell cell; - int ii; - int bRes = 0; - int rc = SQLITE_OK; - - nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); - for(ii=0; bRes==0 && iinConstraint; ii++){ - RtreeConstraint *p = &pCursor->aConstraint[ii]; - RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); - RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); - - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH - ); - - switch( p->op ){ - case RTREE_LE: case RTREE_LT: - bRes = p->rValuerValue>cell_max; - break; - - case RTREE_EQ: - bRes = (p->rValue>cell_max || p->rValueop==RTREE_MATCH ); - rc = testRtreeGeom(pRtree, p, &cell, &bRes); - bRes = !bRes; - break; - } - } - } - - *pbEof = bRes; - return rc; -} - -/* -** Test if the cell that cursor pCursor currently points to -** would be filtered (excluded) by the constraints in the -** pCursor->aConstraint[] array. If so, set *pbEof to true before -** returning. If the cell is not filtered (excluded) by the constraints, -** set pbEof to zero. -** -** Return SQLITE_OK if successful or an SQLite error code if an error -** occurs within a geometry callback. -** -** This function assumes that the cell is part of a leaf node. -*/ -static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ - RtreeCell cell; - int ii; - *pbEof = 0; - - nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); - for(ii=0; iinConstraint; ii++){ - RtreeConstraint *p = &pCursor->aConstraint[ii]; - RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]); - int res; - assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE - || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH - ); - switch( p->op ){ - case RTREE_LE: res = (coord<=p->rValue); break; - case RTREE_LT: res = (coordrValue); break; - case RTREE_GE: res = (coord>=p->rValue); break; - case RTREE_GT: res = (coord>p->rValue); break; - case RTREE_EQ: res = (coord==p->rValue); break; - default: { - int rc; - assert( p->op==RTREE_MATCH ); - rc = testRtreeGeom(pRtree, p, &cell, &res); - if( rc!=SQLITE_OK ){ - return rc; - } - break; - } - } - - if( !res ){ - *pbEof = 1; - return SQLITE_OK; - } - } - - return SQLITE_OK; -} - -/* -** Cursor pCursor currently points at a node that heads a sub-tree of -** height iHeight (if iHeight==0, then the node is a leaf). Descend -** to point to the left-most cell of the sub-tree that matches the -** configured constraints. -*/ -static int descendToCell( - Rtree *pRtree, - RtreeCursor *pCursor, - int iHeight, - int *pEof /* OUT: Set to true if cannot descend */ -){ - int isEof; - int rc; - int ii; - RtreeNode *pChild; - sqlite3_int64 iRowid; - - RtreeNode *pSavedNode = pCursor->pNode; - int iSavedCell = pCursor->iCell; - - assert( iHeight>=0 ); - - if( iHeight==0 ){ - rc = testRtreeEntry(pRtree, pCursor, &isEof); - }else{ - rc = testRtreeCell(pRtree, pCursor, &isEof); - } - if( rc!=SQLITE_OK || isEof || iHeight==0 ){ - goto descend_to_cell_out; - } - - iRowid = nodeGetRowid(pRtree, pCursor->pNode, pCursor->iCell); - rc = nodeAcquire(pRtree, iRowid, pCursor->pNode, &pChild); - if( rc!=SQLITE_OK ){ - goto descend_to_cell_out; - } - - nodeRelease(pRtree, pCursor->pNode); - pCursor->pNode = pChild; - isEof = 1; - for(ii=0; isEof && iiiCell = ii; - rc = descendToCell(pRtree, pCursor, iHeight-1, &isEof); - if( rc!=SQLITE_OK ){ - goto descend_to_cell_out; - } - } - - if( isEof ){ - assert( pCursor->pNode==pChild ); - nodeReference(pSavedNode); - nodeRelease(pRtree, pChild); - pCursor->pNode = pSavedNode; - pCursor->iCell = iSavedCell; - } - -descend_to_cell_out: - *pEof = isEof; - return rc; -} - -/* -** One of the cells in node pNode is guaranteed to have a 64-bit -** integer value equal to iRowid. Return the index of this cell. -*/ -static int nodeRowidIndex( - Rtree *pRtree, - RtreeNode *pNode, - i64 iRowid, - int *piIndex -){ - int ii; - int nCell = NCELL(pNode); - for(ii=0; iipParent; - if( pParent ){ - return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex); - } - *piIndex = -1; - return SQLITE_OK; -} - -/* -** Rtree virtual table module xNext method. -*/ -static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){ - Rtree *pRtree = (Rtree *)(pVtabCursor->pVtab); - RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - int rc = SQLITE_OK; - - /* RtreeCursor.pNode must not be NULL. If is is NULL, then this cursor is - ** already at EOF. It is against the rules to call the xNext() method of - ** a cursor that has already reached EOF. - */ - assert( pCsr->pNode ); - - if( pCsr->iStrategy==1 ){ - /* This "scan" is a direct lookup by rowid. There is no next entry. */ - nodeRelease(pRtree, pCsr->pNode); - pCsr->pNode = 0; - }else{ - /* Move to the next entry that matches the configured constraints. */ - int iHeight = 0; - while( pCsr->pNode ){ - RtreeNode *pNode = pCsr->pNode; - int nCell = NCELL(pNode); - for(pCsr->iCell++; pCsr->iCelliCell++){ - int isEof; - rc = descendToCell(pRtree, pCsr, iHeight, &isEof); - if( rc!=SQLITE_OK || !isEof ){ - return rc; - } - } - pCsr->pNode = pNode->pParent; - rc = nodeParentIndex(pRtree, pNode, &pCsr->iCell); - if( rc!=SQLITE_OK ){ - return rc; - } - nodeReference(pCsr->pNode); - nodeRelease(pRtree, pNode); - iHeight++; - } - } - - return rc; -} - -/* -** Rtree virtual table module xRowid method. -*/ -static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ - Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - - assert(pCsr->pNode); - *pRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); - - return SQLITE_OK; -} - -/* -** Rtree virtual table module xColumn method. -*/ -static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - Rtree *pRtree = (Rtree *)cur->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)cur; - - if( i==0 ){ - i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); - sqlite3_result_int64(ctx, iRowid); - }else{ - RtreeCoord c; - nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); -#ifndef SQLITE_RTREE_INT_ONLY - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - sqlite3_result_double(ctx, c.f); - }else -#endif - { - assert( pRtree->eCoordType==RTREE_COORD_INT32 ); - sqlite3_result_int(ctx, c.i); - } - } - - return SQLITE_OK; -} - -/* -** Use nodeAcquire() to obtain the leaf node containing the record with -** rowid iRowid. If successful, set *ppLeaf to point to the node and -** return SQLITE_OK. If there is no such record in the table, set -** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf -** to zero and return an SQLite error code. -*/ -static int findLeafNode(Rtree *pRtree, i64 iRowid, RtreeNode **ppLeaf){ - int rc; - *ppLeaf = 0; - sqlite3_bind_int64(pRtree->pReadRowid, 1, iRowid); - if( sqlite3_step(pRtree->pReadRowid)==SQLITE_ROW ){ - i64 iNode = sqlite3_column_int64(pRtree->pReadRowid, 0); - rc = nodeAcquire(pRtree, iNode, 0, ppLeaf); - sqlite3_reset(pRtree->pReadRowid); - }else{ - rc = sqlite3_reset(pRtree->pReadRowid); - } - return rc; -} - -/* -** This function is called to configure the RtreeConstraint object passed -** as the second argument for a MATCH constraint. The value passed as the -** first argument to this function is the right-hand operand to the MATCH -** operator. -*/ -static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ - RtreeMatchArg *p; - sqlite3_rtree_geometry *pGeom; - int nBlob; - - /* Check that value is actually a blob. */ - if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; - - /* Check that the blob is roughly the right size. */ - nBlob = sqlite3_value_bytes(pValue); - if( nBlob<(int)sizeof(RtreeMatchArg) - || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 - ){ - return SQLITE_ERROR; - } - - pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc( - sizeof(sqlite3_rtree_geometry) + nBlob - ); - if( !pGeom ) return SQLITE_NOMEM; - memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); - p = (RtreeMatchArg *)&pGeom[1]; - - memcpy(p, sqlite3_value_blob(pValue), nBlob); - if( p->magic!=RTREE_GEOMETRY_MAGIC - || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue)) - ){ - sqlite3_free(pGeom); - return SQLITE_ERROR; - } - - pGeom->pContext = p->pContext; - pGeom->nParam = p->nParam; - pGeom->aParam = p->aParam; - - pCons->xGeom = p->xGeom; - pCons->pGeom = pGeom; - return SQLITE_OK; -} - -/* -** Rtree virtual table module xFilter method. -*/ -static int rtreeFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; - RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; - - RtreeNode *pRoot = 0; - int ii; - int rc = SQLITE_OK; - - rtreeReference(pRtree); - - freeCursorConstraints(pCsr); - pCsr->iStrategy = idxNum; - - if( idxNum==1 ){ - /* Special case - lookup by rowid. */ - RtreeNode *pLeaf; /* Leaf on which the required cell resides */ - i64 iRowid = sqlite3_value_int64(argv[0]); - rc = findLeafNode(pRtree, iRowid, &pLeaf); - pCsr->pNode = pLeaf; - if( pLeaf ){ - assert( rc==SQLITE_OK ); - rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell); - } - }else{ - /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array - ** with the configured constraints. - */ - if( argc>0 ){ - pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc); - pCsr->nConstraint = argc; - if( !pCsr->aConstraint ){ - rc = SQLITE_NOMEM; - }else{ - memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*argc); - assert( (idxStr==0 && argc==0) - || (idxStr && (int)strlen(idxStr)==argc*2) ); - for(ii=0; iiaConstraint[ii]; - p->op = idxStr[ii*2]; - p->iCoord = idxStr[ii*2+1]-'a'; - if( p->op==RTREE_MATCH ){ - /* A MATCH operator. The right-hand-side must be a blob that - ** can be cast into an RtreeMatchArg object. One created using - ** an sqlite3_rtree_geometry_callback() SQL user function. - */ - rc = deserializeGeometry(argv[ii], p); - if( rc!=SQLITE_OK ){ - break; - } - }else{ -#ifdef SQLITE_RTREE_INT_ONLY - p->rValue = sqlite3_value_int64(argv[ii]); -#else - p->rValue = sqlite3_value_double(argv[ii]); -#endif - } - } - } - } - - if( rc==SQLITE_OK ){ - pCsr->pNode = 0; - rc = nodeAcquire(pRtree, 1, 0, &pRoot); - } - if( rc==SQLITE_OK ){ - int isEof = 1; - int nCell = NCELL(pRoot); - pCsr->pNode = pRoot; - for(pCsr->iCell=0; rc==SQLITE_OK && pCsr->iCelliCell++){ - assert( pCsr->pNode==pRoot ); - rc = descendToCell(pRtree, pCsr, pRtree->iDepth, &isEof); - if( !isEof ){ - break; - } - } - if( rc==SQLITE_OK && isEof ){ - assert( pCsr->pNode==pRoot ); - nodeRelease(pRtree, pRoot); - pCsr->pNode = 0; - } - assert( rc!=SQLITE_OK || !pCsr->pNode || pCsr->iCellpNode) ); - } - } - - rtreeRelease(pRtree); - return rc; -} - -/* -** Rtree virtual table module xBestIndex method. There are three -** table scan strategies to choose from (in order from most to -** least desirable): -** -** idxNum idxStr Strategy -** ------------------------------------------------ -** 1 Unused Direct lookup by rowid. -** 2 See below R-tree query or full-table scan. -** ------------------------------------------------ -** -** If strategy 1 is used, then idxStr is not meaningful. If strategy -** 2 is used, idxStr is formatted to contain 2 bytes for each -** constraint used. The first two bytes of idxStr correspond to -** the constraint in sqlite3_index_info.aConstraintUsage[] with -** (argvIndex==1) etc. -** -** The first of each pair of bytes in idxStr identifies the constraint -** operator as follows: -** -** Operator Byte Value -** ---------------------- -** = 0x41 ('A') -** <= 0x42 ('B') -** < 0x43 ('C') -** >= 0x44 ('D') -** > 0x45 ('E') -** MATCH 0x46 ('F') -** ---------------------- -** -** The second of each pair of bytes identifies the coordinate column -** to which the constraint applies. The leftmost coordinate column -** is 'a', the second from the left 'b' etc. -*/ -static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - int rc = SQLITE_OK; - int ii; - - int iIdx = 0; - char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; - memset(zIdxStr, 0, sizeof(zIdxStr)); - UNUSED_PARAMETER(tab); - - assert( pIdxInfo->idxStr==0 ); - for(ii=0; iinConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ - struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; - - if( p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ - /* We have an equality constraint on the rowid. Use strategy 1. */ - int jj; - for(jj=0; jjaConstraintUsage[jj].argvIndex = 0; - pIdxInfo->aConstraintUsage[jj].omit = 0; - } - pIdxInfo->idxNum = 1; - pIdxInfo->aConstraintUsage[ii].argvIndex = 1; - pIdxInfo->aConstraintUsage[jj].omit = 1; - - /* This strategy involves a two rowid lookups on an B-Tree structures - ** and then a linear search of an R-Tree node. This should be - ** considered almost as quick as a direct rowid lookup (for which - ** sqlite uses an internal cost of 0.0). - */ - pIdxInfo->estimatedCost = 10.0; - return SQLITE_OK; - } - - if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ - u8 op; - switch( p->op ){ - case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; - case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break; - case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break; - case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break; - case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break; - default: - assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH ); - op = RTREE_MATCH; - break; - } - zIdxStr[iIdx++] = op; - zIdxStr[iIdx++] = p->iColumn - 1 + 'a'; - pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); - pIdxInfo->aConstraintUsage[ii].omit = 1; - } - } - - pIdxInfo->idxNum = 2; - pIdxInfo->needToFreeIdxStr = 1; - if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){ - return SQLITE_NOMEM; - } - assert( iIdx>=0 ); - pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1)); - return rc; -} - -/* -** Return the N-dimensional volumn of the cell stored in *p. -*/ -static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){ - RtreeDValue area = (RtreeDValue)1; - int ii; - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); - } - return area; -} - -/* -** Return the margin length of cell p. The margin length is the sum -** of the objects size in each dimension. -*/ -static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){ - RtreeDValue margin = (RtreeDValue)0; - int ii; - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); - } - return margin; -} - -/* -** Store the union of cells p1 and p2 in p1. -*/ -static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ - int ii; - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f); - p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f); - } - }else{ - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i); - p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i); - } - } -} - -/* -** Return true if the area covered by p2 is a subset of the area covered -** by p1. False otherwise. -*/ -static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ - int ii; - int isInt = (pRtree->eCoordType==RTREE_COORD_INT32); - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - RtreeCoord *a1 = &p1->aCoord[ii]; - RtreeCoord *a2 = &p2->aCoord[ii]; - if( (!isInt && (a2[0].fa1[1].f)) - || ( isInt && (a2[0].ia1[1].i)) - ){ - return 0; - } - } - return 1; -} - -/* -** Return the amount cell p would grow by if it were unioned with pCell. -*/ -static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ - RtreeDValue area; - RtreeCell cell; - memcpy(&cell, p, sizeof(RtreeCell)); - area = cellArea(pRtree, &cell); - cellUnion(pRtree, &cell, pCell); - return (cellArea(pRtree, &cell)-area); -} - -#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT -static RtreeDValue cellOverlap( - Rtree *pRtree, - RtreeCell *p, - RtreeCell *aCell, - int nCell, - int iExclude -){ - int ii; - RtreeDValue overlap = 0.0; - for(ii=0; iinDim*2); jj+=2){ - RtreeDValue x1, x2; - - x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); - x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); - - if( x2iDepth-iHeight); ii++){ - int iCell; - sqlite3_int64 iBest = 0; - - RtreeDValue fMinGrowth = 0.0; - RtreeDValue fMinArea = 0.0; -#if VARIANT_RSTARTREE_CHOOSESUBTREE - RtreeDValue fMinOverlap = 0.0; - RtreeDValue overlap; -#endif - - int nCell = NCELL(pNode); - RtreeCell cell; - RtreeNode *pChild; - - RtreeCell *aCell = 0; - -#if VARIANT_RSTARTREE_CHOOSESUBTREE - if( ii==(pRtree->iDepth-1) ){ - int jj; - aCell = sqlite3_malloc(sizeof(RtreeCell)*nCell); - if( !aCell ){ - rc = SQLITE_NOMEM; - nodeRelease(pRtree, pNode); - pNode = 0; - continue; - } - for(jj=0; jjiDepth-1) ){ - overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell); - }else{ - overlap = 0.0; - } - if( (iCell==0) - || (overlappParent ){ - RtreeNode *pParent = p->pParent; - RtreeCell cell; - int iCell; - - if( nodeParentIndex(pRtree, p, &iCell) ){ - return SQLITE_CORRUPT_VTAB; - } - - nodeGetCell(pRtree, pParent, iCell, &cell); - if( !cellContains(pRtree, &cell, pCell) ){ - cellUnion(pRtree, &cell, pCell); - nodeOverwriteCell(pRtree, pParent, &cell, iCell); - } - - p = pParent; - } - return SQLITE_OK; -} - -/* -** Write mapping (iRowid->iNode) to the _rowid table. -*/ -static int rowidWrite(Rtree *pRtree, sqlite3_int64 iRowid, sqlite3_int64 iNode){ - sqlite3_bind_int64(pRtree->pWriteRowid, 1, iRowid); - sqlite3_bind_int64(pRtree->pWriteRowid, 2, iNode); - sqlite3_step(pRtree->pWriteRowid); - return sqlite3_reset(pRtree->pWriteRowid); -} - -/* -** Write mapping (iNode->iPar) to the _parent table. -*/ -static int parentWrite(Rtree *pRtree, sqlite3_int64 iNode, sqlite3_int64 iPar){ - sqlite3_bind_int64(pRtree->pWriteParent, 1, iNode); - sqlite3_bind_int64(pRtree->pWriteParent, 2, iPar); - sqlite3_step(pRtree->pWriteParent); - return sqlite3_reset(pRtree->pWriteParent); -} - -static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int); - -#if VARIANT_GUTTMAN_LINEAR_SPLIT -/* -** Implementation of the linear variant of the PickNext() function from -** Guttman[84]. -*/ -static RtreeCell *LinearPickNext( - Rtree *pRtree, - RtreeCell *aCell, - int nCell, - RtreeCell *pLeftBox, - RtreeCell *pRightBox, - int *aiUsed -){ - int ii; - for(ii=0; aiUsed[ii]; ii++); - aiUsed[ii] = 1; - return &aCell[ii]; -} - -/* -** Implementation of the linear variant of the PickSeeds() function from -** Guttman[84]. -*/ -static void LinearPickSeeds( - Rtree *pRtree, - RtreeCell *aCell, - int nCell, - int *piLeftSeed, - int *piRightSeed -){ - int i; - int iLeftSeed = 0; - int iRightSeed = 1; - RtreeDValue maxNormalInnerWidth = (RtreeDValue)0; - - /* Pick two "seed" cells from the array of cells. The algorithm used - ** here is the LinearPickSeeds algorithm from Gutman[1984]. The - ** indices of the two seed cells in the array are stored in local - ** variables iLeftSeek and iRightSeed. - */ - for(i=0; inDim; i++){ - RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]); - RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]); - RtreeDValue x3 = x1; - RtreeDValue x4 = x2; - int jj; - - int iCellLeft = 0; - int iCellRight = 0; - - for(jj=1; jjx4 ) x4 = right; - if( left>x3 ){ - x3 = left; - iCellRight = jj; - } - if( rightmaxNormalInnerWidth ){ - iLeftSeed = iCellLeft; - iRightSeed = iCellRight; - } - } - } - - *piLeftSeed = iLeftSeed; - *piRightSeed = iRightSeed; -} -#endif /* VARIANT_GUTTMAN_LINEAR_SPLIT */ - -#if VARIANT_GUTTMAN_QUADRATIC_SPLIT -/* -** Implementation of the quadratic variant of the PickNext() function from -** Guttman[84]. -*/ -static RtreeCell *QuadraticPickNext( - Rtree *pRtree, - RtreeCell *aCell, - int nCell, - RtreeCell *pLeftBox, - RtreeCell *pRightBox, - int *aiUsed -){ - #define FABS(a) ((a)<0.0?-1.0*(a):(a)) - - int iSelect = -1; - RtreeDValue fDiff; - int ii; - for(ii=0; iifDiff ){ - fDiff = diff; - iSelect = ii; - } - } - } - aiUsed[iSelect] = 1; - return &aCell[iSelect]; -} - -/* -** Implementation of the quadratic variant of the PickSeeds() function from -** Guttman[84]. -*/ -static void QuadraticPickSeeds( - Rtree *pRtree, - RtreeCell *aCell, - int nCell, - int *piLeftSeed, - int *piRightSeed -){ - int ii; - int jj; - - int iLeftSeed = 0; - int iRightSeed = 1; - RtreeDValue fWaste = 0.0; - - for(ii=0; iifWaste ){ - iLeftSeed = ii; - iRightSeed = jj; - fWaste = waste; - } - } - } - - *piLeftSeed = iLeftSeed; - *piRightSeed = iRightSeed; -} -#endif /* VARIANT_GUTTMAN_QUADRATIC_SPLIT */ - -/* -** Arguments aIdx, aDistance and aSpare all point to arrays of size -** nIdx. The aIdx array contains the set of integers from 0 to -** (nIdx-1) in no particular order. This function sorts the values -** in aIdx according to the indexed values in aDistance. For -** example, assuming the inputs: -** -** aIdx = { 0, 1, 2, 3 } -** aDistance = { 5.0, 2.0, 7.0, 6.0 } -** -** this function sets the aIdx array to contain: -** -** aIdx = { 0, 1, 2, 3 } -** -** The aSpare array is used as temporary working space by the -** sorting algorithm. -*/ -static void SortByDistance( - int *aIdx, - int nIdx, - RtreeDValue *aDistance, - int *aSpare -){ - if( nIdx>1 ){ - int iLeft = 0; - int iRight = 0; - - int nLeft = nIdx/2; - int nRight = nIdx-nLeft; - int *aLeft = aIdx; - int *aRight = &aIdx[nLeft]; - - SortByDistance(aLeft, nLeft, aDistance, aSpare); - SortByDistance(aRight, nRight, aDistance, aSpare); - - memcpy(aSpare, aLeft, sizeof(int)*nLeft); - aLeft = aSpare; - - while( iLeft1 ){ - - int iLeft = 0; - int iRight = 0; - - int nLeft = nIdx/2; - int nRight = nIdx-nLeft; - int *aLeft = aIdx; - int *aRight = &aIdx[nLeft]; - - SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare); - SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare); - - memcpy(aSpare, aLeft, sizeof(int)*nLeft); - aLeft = aSpare; - while( iLeftnDim+1)*(sizeof(int*)+nCell*sizeof(int)); - - aaSorted = (int **)sqlite3_malloc(nByte); - if( !aaSorted ){ - return SQLITE_NOMEM; - } - - aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell]; - memset(aaSorted, 0, nByte); - for(ii=0; iinDim; ii++){ - int jj; - aaSorted[ii] = &((int *)&aaSorted[pRtree->nDim])[ii*nCell]; - for(jj=0; jjnDim; ii++){ - RtreeDValue margin = 0.0; - RtreeDValue fBestOverlap = 0.0; - RtreeDValue fBestArea = 0.0; - int iBestLeft = 0; - int nLeft; - - for( - nLeft=RTREE_MINCELLS(pRtree); - nLeft<=(nCell-RTREE_MINCELLS(pRtree)); - nLeft++ - ){ - RtreeCell left; - RtreeCell right; - int kk; - RtreeDValue overlap; - RtreeDValue area; - - memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell)); - memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell)); - for(kk=1; kk<(nCell-1); kk++){ - if( kk0; i--){ - RtreeCell *pNext; - pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); - RtreeDValue diff = - cellGrowth(pRtree, pBboxLeft, pNext) - - cellGrowth(pRtree, pBboxRight, pNext) - ; - if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i) - || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i)) - ){ - nodeInsertCell(pRtree, pRight, pNext); - cellUnion(pRtree, pBboxRight, pNext); - }else{ - nodeInsertCell(pRtree, pLeft, pNext); - cellUnion(pRtree, pBboxLeft, pNext); - } - } - - sqlite3_free(aiUsed); - return SQLITE_OK; -} -#endif - -static int updateMapping( - Rtree *pRtree, - i64 iRowid, - RtreeNode *pNode, - int iHeight -){ - int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64); - xSetMapping = ((iHeight==0)?rowidWrite:parentWrite); - if( iHeight>0 ){ - RtreeNode *pChild = nodeHashLookup(pRtree, iRowid); - if( pChild ){ - nodeRelease(pRtree, pChild->pParent); - nodeReference(pNode); - pChild->pParent = pNode; - } - } - return xSetMapping(pRtree, iRowid, pNode->iNode); -} - -static int SplitNode( - Rtree *pRtree, - RtreeNode *pNode, - RtreeCell *pCell, - int iHeight -){ - int i; - int newCellIsRight = 0; - - int rc = SQLITE_OK; - int nCell = NCELL(pNode); - RtreeCell *aCell; - int *aiUsed; - - RtreeNode *pLeft = 0; - RtreeNode *pRight = 0; - - RtreeCell leftbbox; - RtreeCell rightbbox; - - /* Allocate an array and populate it with a copy of pCell and - ** all cells from node pLeft. Then zero the original node. - */ - aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1)); - if( !aCell ){ - rc = SQLITE_NOMEM; - goto splitnode_out; - } - aiUsed = (int *)&aCell[nCell+1]; - memset(aiUsed, 0, sizeof(int)*(nCell+1)); - for(i=0; iiNode==1 ){ - pRight = nodeNew(pRtree, pNode); - pLeft = nodeNew(pRtree, pNode); - pRtree->iDepth++; - pNode->isDirty = 1; - writeInt16(pNode->zData, pRtree->iDepth); - }else{ - pLeft = pNode; - pRight = nodeNew(pRtree, pLeft->pParent); - nodeReference(pLeft); - } - - if( !pLeft || !pRight ){ - rc = SQLITE_NOMEM; - goto splitnode_out; - } - - memset(pLeft->zData, 0, pRtree->iNodeSize); - memset(pRight->zData, 0, pRtree->iNodeSize); - - rc = AssignCells(pRtree, aCell, nCell, pLeft, pRight, &leftbbox, &rightbbox); - if( rc!=SQLITE_OK ){ - goto splitnode_out; - } - - /* Ensure both child nodes have node numbers assigned to them by calling - ** nodeWrite(). Node pRight always needs a node number, as it was created - ** by nodeNew() above. But node pLeft sometimes already has a node number. - ** In this case avoid the all to nodeWrite(). - */ - if( SQLITE_OK!=(rc = nodeWrite(pRtree, pRight)) - || (0==pLeft->iNode && SQLITE_OK!=(rc = nodeWrite(pRtree, pLeft))) - ){ - goto splitnode_out; - } - - rightbbox.iRowid = pRight->iNode; - leftbbox.iRowid = pLeft->iNode; - - if( pNode->iNode==1 ){ - rc = rtreeInsertCell(pRtree, pLeft->pParent, &leftbbox, iHeight+1); - if( rc!=SQLITE_OK ){ - goto splitnode_out; - } - }else{ - RtreeNode *pParent = pLeft->pParent; - int iCell; - rc = nodeParentIndex(pRtree, pLeft, &iCell); - if( rc==SQLITE_OK ){ - nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell); - rc = AdjustTree(pRtree, pParent, &leftbbox); - } - if( rc!=SQLITE_OK ){ - goto splitnode_out; - } - } - if( (rc = rtreeInsertCell(pRtree, pRight->pParent, &rightbbox, iHeight+1)) ){ - goto splitnode_out; - } - - for(i=0; iiRowid ){ - newCellIsRight = 1; - } - if( rc!=SQLITE_OK ){ - goto splitnode_out; - } - } - if( pNode->iNode==1 ){ - for(i=0; iiRowid, pLeft, iHeight); - } - - if( rc==SQLITE_OK ){ - rc = nodeRelease(pRtree, pRight); - pRight = 0; - } - if( rc==SQLITE_OK ){ - rc = nodeRelease(pRtree, pLeft); - pLeft = 0; - } - -splitnode_out: - nodeRelease(pRtree, pRight); - nodeRelease(pRtree, pLeft); - sqlite3_free(aCell); - return rc; -} - -/* -** If node pLeaf is not the root of the r-tree and its pParent pointer is -** still NULL, load all ancestor nodes of pLeaf into memory and populate -** the pLeaf->pParent chain all the way up to the root node. -** -** This operation is required when a row is deleted (or updated - an update -** is implemented as a delete followed by an insert). SQLite provides the -** rowid of the row to delete, which can be used to find the leaf on which -** the entry resides (argument pLeaf). Once the leaf is located, this -** function is called to determine its ancestry. -*/ -static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){ - int rc = SQLITE_OK; - RtreeNode *pChild = pLeaf; - while( rc==SQLITE_OK && pChild->iNode!=1 && pChild->pParent==0 ){ - int rc2 = SQLITE_OK; /* sqlite3_reset() return code */ - sqlite3_bind_int64(pRtree->pReadParent, 1, pChild->iNode); - rc = sqlite3_step(pRtree->pReadParent); - if( rc==SQLITE_ROW ){ - RtreeNode *pTest; /* Used to test for reference loops */ - i64 iNode; /* Node number of parent node */ - - /* Before setting pChild->pParent, test that we are not creating a - ** loop of references (as we would if, say, pChild==pParent). We don't - ** want to do this as it leads to a memory leak when trying to delete - ** the referenced counted node structures. - */ - iNode = sqlite3_column_int64(pRtree->pReadParent, 0); - for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent); - if( !pTest ){ - rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent); - } - } - rc = sqlite3_reset(pRtree->pReadParent); - if( rc==SQLITE_OK ) rc = rc2; - if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB; - pChild = pChild->pParent; - } - return rc; -} - -static int deleteCell(Rtree *, RtreeNode *, int, int); - -static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){ - int rc; - int rc2; - RtreeNode *pParent = 0; - int iCell; - - assert( pNode->nRef==1 ); - - /* Remove the entry in the parent cell. */ - rc = nodeParentIndex(pRtree, pNode, &iCell); - if( rc==SQLITE_OK ){ - pParent = pNode->pParent; - pNode->pParent = 0; - rc = deleteCell(pRtree, pParent, iCell, iHeight+1); - } - rc2 = nodeRelease(pRtree, pParent); - if( rc==SQLITE_OK ){ - rc = rc2; - } - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Remove the xxx_node entry. */ - sqlite3_bind_int64(pRtree->pDeleteNode, 1, pNode->iNode); - sqlite3_step(pRtree->pDeleteNode); - if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteNode)) ){ - return rc; - } - - /* Remove the xxx_parent entry. */ - sqlite3_bind_int64(pRtree->pDeleteParent, 1, pNode->iNode); - sqlite3_step(pRtree->pDeleteParent); - if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){ - return rc; - } - - /* Remove the node from the in-memory hash table and link it into - ** the Rtree.pDeleted list. Its contents will be re-inserted later on. - */ - nodeHashDelete(pRtree, pNode); - pNode->iNode = iHeight; - pNode->pNext = pRtree->pDeleted; - pNode->nRef++; - pRtree->pDeleted = pNode; - - return SQLITE_OK; -} - -static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){ - RtreeNode *pParent = pNode->pParent; - int rc = SQLITE_OK; - if( pParent ){ - int ii; - int nCell = NCELL(pNode); - RtreeCell box; /* Bounding box for pNode */ - nodeGetCell(pRtree, pNode, 0, &box); - for(ii=1; iiiNode; - rc = nodeParentIndex(pRtree, pNode, &ii); - if( rc==SQLITE_OK ){ - nodeOverwriteCell(pRtree, pParent, &box, ii); - rc = fixBoundingBox(pRtree, pParent); - } - } - return rc; -} - -/* -** Delete the cell at index iCell of node pNode. After removing the -** cell, adjust the r-tree data structure if required. -*/ -static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){ - RtreeNode *pParent; - int rc; - - if( SQLITE_OK!=(rc = fixLeafParent(pRtree, pNode)) ){ - return rc; - } - - /* Remove the cell from the node. This call just moves bytes around - ** the in-memory node image, so it cannot fail. - */ - nodeDeleteCell(pRtree, pNode, iCell); - - /* If the node is not the tree root and now has less than the minimum - ** number of cells, remove it from the tree. Otherwise, update the - ** cell in the parent node so that it tightly contains the updated - ** node. - */ - pParent = pNode->pParent; - assert( pParent || pNode->iNode==1 ); - if( pParent ){ - if( NCELL(pNode)nDim; iDim++){ - aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]); - aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]); - } - } - for(iDim=0; iDimnDim; iDim++){ - aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); - } - - for(ii=0; iinDim; iDim++){ - RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - - DCOORD(aCell[ii].aCoord[iDim*2])); - aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); - } - } - - SortByDistance(aOrder, nCell, aDistance, aSpare); - nodeZero(pRtree, pNode); - - for(ii=0; rc==SQLITE_OK && ii<(nCell-(RTREE_MINCELLS(pRtree)+1)); ii++){ - RtreeCell *p = &aCell[aOrder[ii]]; - nodeInsertCell(pRtree, pNode, p); - if( p->iRowid==pCell->iRowid ){ - if( iHeight==0 ){ - rc = rowidWrite(pRtree, p->iRowid, pNode->iNode); - }else{ - rc = parentWrite(pRtree, p->iRowid, pNode->iNode); - } - } - } - if( rc==SQLITE_OK ){ - rc = fixBoundingBox(pRtree, pNode); - } - for(; rc==SQLITE_OK && iiiNode currently contains - ** the height of the sub-tree headed by the cell. - */ - RtreeNode *pInsert; - RtreeCell *p = &aCell[aOrder[ii]]; - rc = ChooseLeaf(pRtree, p, iHeight, &pInsert); - if( rc==SQLITE_OK ){ - int rc2; - rc = rtreeInsertCell(pRtree, pInsert, p, iHeight); - rc2 = nodeRelease(pRtree, pInsert); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - - sqlite3_free(aCell); - return rc; -} - -/* -** Insert cell pCell into node pNode. Node pNode is the head of a -** subtree iHeight high (leaf nodes have iHeight==0). -*/ -static int rtreeInsertCell( - Rtree *pRtree, - RtreeNode *pNode, - RtreeCell *pCell, - int iHeight -){ - int rc = SQLITE_OK; - if( iHeight>0 ){ - RtreeNode *pChild = nodeHashLookup(pRtree, pCell->iRowid); - if( pChild ){ - nodeRelease(pRtree, pChild->pParent); - nodeReference(pNode); - pChild->pParent = pNode; - } - } - if( nodeInsertCell(pRtree, pNode, pCell) ){ -#if VARIANT_RSTARTREE_REINSERT - if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1){ - rc = SplitNode(pRtree, pNode, pCell, iHeight); - }else{ - pRtree->iReinsertHeight = iHeight; - rc = Reinsert(pRtree, pNode, pCell, iHeight); - } -#else - rc = SplitNode(pRtree, pNode, pCell, iHeight); -#endif - }else{ - rc = AdjustTree(pRtree, pNode, pCell); - if( rc==SQLITE_OK ){ - if( iHeight==0 ){ - rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode); - }else{ - rc = parentWrite(pRtree, pCell->iRowid, pNode->iNode); - } - } - } - return rc; -} - -static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){ - int ii; - int rc = SQLITE_OK; - int nCell = NCELL(pNode); - - for(ii=0; rc==SQLITE_OK && iiiNode currently contains - ** the height of the sub-tree headed by the cell. - */ - rc = ChooseLeaf(pRtree, &cell, (int)pNode->iNode, &pInsert); - if( rc==SQLITE_OK ){ - int rc2; - rc = rtreeInsertCell(pRtree, pInsert, &cell, (int)pNode->iNode); - rc2 = nodeRelease(pRtree, pInsert); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - return rc; -} - -/* -** Select a currently unused rowid for a new r-tree record. -*/ -static int newRowid(Rtree *pRtree, i64 *piRowid){ - int rc; - sqlite3_bind_null(pRtree->pWriteRowid, 1); - sqlite3_bind_null(pRtree->pWriteRowid, 2); - sqlite3_step(pRtree->pWriteRowid); - rc = sqlite3_reset(pRtree->pWriteRowid); - *piRowid = sqlite3_last_insert_rowid(pRtree->db); - return rc; -} - -/* -** Remove the entry with rowid=iDelete from the r-tree structure. -*/ -static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ - int rc; /* Return code */ - RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */ - int iCell; /* Index of iDelete cell in pLeaf */ - RtreeNode *pRoot; /* Root node of rtree structure */ - - - /* Obtain a reference to the root node to initialize Rtree.iDepth */ - rc = nodeAcquire(pRtree, 1, 0, &pRoot); - - /* Obtain a reference to the leaf node that contains the entry - ** about to be deleted. - */ - if( rc==SQLITE_OK ){ - rc = findLeafNode(pRtree, iDelete, &pLeaf); - } - - /* Delete the cell in question from the leaf node. */ - if( rc==SQLITE_OK ){ - int rc2; - rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell); - if( rc==SQLITE_OK ){ - rc = deleteCell(pRtree, pLeaf, iCell, 0); - } - rc2 = nodeRelease(pRtree, pLeaf); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - - /* Delete the corresponding entry in the _rowid table. */ - if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pRtree->pDeleteRowid, 1, iDelete); - sqlite3_step(pRtree->pDeleteRowid); - rc = sqlite3_reset(pRtree->pDeleteRowid); - } - - /* Check if the root node now has exactly one child. If so, remove - ** it, schedule the contents of the child for reinsertion and - ** reduce the tree height by one. - ** - ** This is equivalent to copying the contents of the child into - ** the root node (the operation that Gutman's paper says to perform - ** in this scenario). - */ - if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ - int rc2; - RtreeNode *pChild; - i64 iChild = nodeGetRowid(pRtree, pRoot, 0); - rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); - if( rc==SQLITE_OK ){ - rc = removeNode(pRtree, pChild, pRtree->iDepth-1); - } - rc2 = nodeRelease(pRtree, pChild); - if( rc==SQLITE_OK ) rc = rc2; - if( rc==SQLITE_OK ){ - pRtree->iDepth--; - writeInt16(pRoot->zData, pRtree->iDepth); - pRoot->isDirty = 1; - } - } - - /* Re-insert the contents of any underfull nodes removed from the tree. */ - for(pLeaf=pRtree->pDeleted; pLeaf; pLeaf=pRtree->pDeleted){ - if( rc==SQLITE_OK ){ - rc = reinsertNodeContent(pRtree, pLeaf); - } - pRtree->pDeleted = pLeaf->pNext; - sqlite3_free(pLeaf); - } - - /* Release the reference to the root node. */ - if( rc==SQLITE_OK ){ - rc = nodeRelease(pRtree, pRoot); - }else{ - nodeRelease(pRtree, pRoot); - } - - return rc; -} - -/* -** Rounding constants for float->double conversion. -*/ -#define RNDTOWARDS (1.0 - 1.0/8388608.0) /* Round towards zero */ -#define RNDAWAY (1.0 + 1.0/8388608.0) /* Round away from zero */ - -#if !defined(SQLITE_RTREE_INT_ONLY) -/* -** Convert an sqlite3_value into an RtreeValue (presumably a float) -** while taking care to round toward negative or positive, respectively. -*/ -static RtreeValue rtreeValueDown(sqlite3_value *v){ - double d = sqlite3_value_double(v); - float f = (float)d; - if( f>d ){ - f = (float)(d*(d<0 ? RNDAWAY : RNDTOWARDS)); - } - return f; -} -static RtreeValue rtreeValueUp(sqlite3_value *v){ - double d = sqlite3_value_double(v); - float f = (float)d; - if( f1 */ - int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ - - rtreeReference(pRtree); - assert(nData>=1); - - /* Constraint handling. A write operation on an r-tree table may return - ** SQLITE_CONSTRAINT for two reasons: - ** - ** 1. A duplicate rowid value, or - ** 2. The supplied data violates the "x2>=x1" constraint. - ** - ** In the first case, if the conflict-handling mode is REPLACE, then - ** the conflicting row can be removed before proceeding. In the second - ** case, SQLITE_CONSTRAINT must be returned regardless of the - ** conflict-handling mode specified by the user. - */ - if( nData>1 ){ - int ii; - - /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ - assert( nData==(pRtree->nDim*2 + 3) ); -#ifndef SQLITE_RTREE_INT_ONLY - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]); - cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]); - if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ - rc = SQLITE_CONSTRAINT; - goto constraint; - } - } - }else -#endif - { - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); - cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); - if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ - rc = SQLITE_CONSTRAINT; - goto constraint; - } - } - } - - /* If a rowid value was supplied, check if it is already present in - ** the table. If so, the constraint has failed. */ - if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){ - cell.iRowid = sqlite3_value_int64(azData[2]); - if( sqlite3_value_type(azData[0])==SQLITE_NULL - || sqlite3_value_int64(azData[0])!=cell.iRowid - ){ - int steprc; - sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); - steprc = sqlite3_step(pRtree->pReadRowid); - rc = sqlite3_reset(pRtree->pReadRowid); - if( SQLITE_ROW==steprc ){ - if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ - rc = rtreeDeleteRowid(pRtree, cell.iRowid); - }else{ - rc = SQLITE_CONSTRAINT; - goto constraint; - } - } - } - bHaveRowid = 1; - } - } - - /* If azData[0] is not an SQL NULL value, it is the rowid of a - ** record to delete from the r-tree table. The following block does - ** just that. - */ - if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){ - rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0])); - } - - /* If the azData[] array contains more than one element, elements - ** (azData[2]..azData[argc-1]) contain a new record to insert into - ** the r-tree structure. - */ - if( rc==SQLITE_OK && nData>1 ){ - /* Insert the new record into the r-tree */ - RtreeNode *pLeaf = 0; - - /* Figure out the rowid of the new row. */ - if( bHaveRowid==0 ){ - rc = newRowid(pRtree, &cell.iRowid); - } - *pRowid = cell.iRowid; - - if( rc==SQLITE_OK ){ - rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); - } - if( rc==SQLITE_OK ){ - int rc2; - pRtree->iReinsertHeight = -1; - rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); - rc2 = nodeRelease(pRtree, pLeaf); - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - -constraint: - rtreeRelease(pRtree); - return rc; -} - -/* -** The xRename method for rtree module virtual tables. -*/ -static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){ - Rtree *pRtree = (Rtree *)pVtab; - int rc = SQLITE_NOMEM; - char *zSql = sqlite3_mprintf( - "ALTER TABLE %Q.'%q_node' RENAME TO \"%w_node\";" - "ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";" - "ALTER TABLE %Q.'%q_rowid' RENAME TO \"%w_rowid\";" - , pRtree->zDb, pRtree->zName, zNewName - , pRtree->zDb, pRtree->zName, zNewName - , pRtree->zDb, pRtree->zName, zNewName - ); - if( zSql ){ - rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0); - sqlite3_free(zSql); - } - return rc; -} - -static sqlite3_module rtreeModule = { - 0, /* iVersion */ - rtreeCreate, /* xCreate - create a table */ - rtreeConnect, /* xConnect - connect to an existing table */ - rtreeBestIndex, /* xBestIndex - Determine search strategy */ - rtreeDisconnect, /* xDisconnect - Disconnect from a table */ - rtreeDestroy, /* xDestroy - Drop a table */ - rtreeOpen, /* xOpen - open a cursor */ - rtreeClose, /* xClose - close a cursor */ - rtreeFilter, /* xFilter - configure scan constraints */ - rtreeNext, /* xNext - advance a cursor */ - rtreeEof, /* xEof */ - rtreeColumn, /* xColumn - read data */ - rtreeRowid, /* xRowid - read data */ - rtreeUpdate, /* xUpdate - write data */ - 0, /* xBegin - begin transaction */ - 0, /* xSync - sync transaction */ - 0, /* xCommit - commit transaction */ - 0, /* xRollback - rollback transaction */ - 0, /* xFindFunction - function overloading */ - rtreeRename, /* xRename - rename the table */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0 /* xRollbackTo */ -}; - -static int rtreeSqlInit( - Rtree *pRtree, - sqlite3 *db, - const char *zDb, - const char *zPrefix, - int isCreate -){ - int rc = SQLITE_OK; - - #define N_STATEMENT 9 - static const char *azSql[N_STATEMENT] = { - /* Read and write the xxx_node table */ - "SELECT data FROM '%q'.'%q_node' WHERE nodeno = :1", - "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)", - "DELETE FROM '%q'.'%q_node' WHERE nodeno = :1", - - /* Read and write the xxx_rowid table */ - "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1", - "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)", - "DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1", - - /* Read and write the xxx_parent table */ - "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1", - "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)", - "DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1" - }; - sqlite3_stmt **appStmt[N_STATEMENT]; - int i; - - pRtree->db = db; - - if( isCreate ){ - char *zCreate = sqlite3_mprintf( -"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);" -"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);" -"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY, parentnode INTEGER);" -"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))", - zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize - ); - if( !zCreate ){ - return SQLITE_NOMEM; - } - rc = sqlite3_exec(db, zCreate, 0, 0, 0); - sqlite3_free(zCreate); - if( rc!=SQLITE_OK ){ - return rc; - } - } - - appStmt[0] = &pRtree->pReadNode; - appStmt[1] = &pRtree->pWriteNode; - appStmt[2] = &pRtree->pDeleteNode; - appStmt[3] = &pRtree->pReadRowid; - appStmt[4] = &pRtree->pWriteRowid; - appStmt[5] = &pRtree->pDeleteRowid; - appStmt[6] = &pRtree->pReadParent; - appStmt[7] = &pRtree->pWriteParent; - appStmt[8] = &pRtree->pDeleteParent; - - for(i=0; iiNodeSize is populated and SQLITE_OK returned. -** Otherwise, an SQLite error code is returned. -** -** If this function is being called as part of an xConnect(), then the rtree -** table already exists. In this case the node-size is determined by inspecting -** the root node of the tree. -** -** Otherwise, for an xCreate(), use 64 bytes less than the database page-size. -** This ensures that each node is stored on a single database page. If the -** database page-size is so large that more than RTREE_MAXCELLS entries -** would fit in a single node, use a smaller node-size. -*/ -static int getNodeSize( - sqlite3 *db, /* Database handle */ - Rtree *pRtree, /* Rtree handle */ - int isCreate, /* True for xCreate, false for xConnect */ - char **pzErr /* OUT: Error message, if any */ -){ - int rc; - char *zSql; - if( isCreate ){ - int iPageSize = 0; - zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); - rc = getIntFromStmt(db, zSql, &iPageSize); - if( rc==SQLITE_OK ){ - pRtree->iNodeSize = iPageSize-64; - if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)iNodeSize ){ - pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; - } - }else{ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - }else{ - zSql = sqlite3_mprintf( - "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", - pRtree->zDb, pRtree->zName - ); - rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); - if( rc!=SQLITE_OK ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - } - - sqlite3_free(zSql); - return rc; -} - -/* -** This function is the implementation of both the xConnect and xCreate -** methods of the r-tree virtual table. -** -** argv[0] -> module name -** argv[1] -> database name -** argv[2] -> table name -** argv[...] -> column names... -*/ -static int rtreeInit( - sqlite3 *db, /* Database connection */ - void *pAux, /* One of the RTREE_COORD_* constants */ - int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ - sqlite3_vtab **ppVtab, /* OUT: New virtual table */ - char **pzErr, /* OUT: Error message, if any */ - int isCreate /* True for xCreate, false for xConnect */ -){ - int rc = SQLITE_OK; - Rtree *pRtree; - int nDb; /* Length of string argv[1] */ - int nName; /* Length of string argv[2] */ - int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32); - - const char *aErrMsg[] = { - 0, /* 0 */ - "Wrong number of columns for an rtree table", /* 1 */ - "Too few columns for an rtree table", /* 2 */ - "Too many columns for an rtree table" /* 3 */ - }; - - int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; - if( aErrMsg[iErr] ){ - *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); - return SQLITE_ERROR; - } - - sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); - - /* Allocate the sqlite3_vtab structure */ - nDb = (int)strlen(argv[1]); - nName = (int)strlen(argv[2]); - pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); - if( !pRtree ){ - return SQLITE_NOMEM; - } - memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); - pRtree->nBusy = 1; - pRtree->base.pModule = &rtreeModule; - pRtree->zDb = (char *)&pRtree[1]; - pRtree->zName = &pRtree->zDb[nDb+1]; - pRtree->nDim = (argc-4)/2; - pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; - pRtree->eCoordType = eCoordType; - memcpy(pRtree->zDb, argv[1], nDb); - memcpy(pRtree->zName, argv[2], nName); - - /* Figure out the node size to use. */ - rc = getNodeSize(db, pRtree, isCreate, pzErr); - - /* Create/Connect to the underlying relational database schema. If - ** that is successful, call sqlite3_declare_vtab() to configure - ** the r-tree table schema. - */ - if( rc==SQLITE_OK ){ - if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - }else{ - char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); - char *zTmp; - int ii; - for(ii=4; zSql && ii*2 coordinates. -*/ -static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ - char *zText = 0; - RtreeNode node; - Rtree tree; - int ii; - - UNUSED_PARAMETER(nArg); - memset(&node, 0, sizeof(RtreeNode)); - memset(&tree, 0, sizeof(Rtree)); - tree.nDim = sqlite3_value_int(apArg[0]); - tree.nBytesPerCell = 8 + 8 * tree.nDim; - node.zData = (u8 *)sqlite3_value_blob(apArg[1]); - - for(ii=0; iimagic = RTREE_GEOMETRY_MAGIC; - pBlob->xGeom = pGeomCtx->xGeom; - pBlob->pContext = pGeomCtx->pContext; - pBlob->nParam = nArg; - for(i=0; iaParam[i] = sqlite3_value_int64(aArg[i]); -#else - pBlob->aParam[i] = sqlite3_value_double(aArg[i]); -#endif - } - sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); - } -} - -/* -** Register a new geometry function for use with the r-tree MATCH operator. -*/ -SQLITE_API int sqlite3_rtree_geometry_callback( - sqlite3 *db, - const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *), - void *pContext -){ - RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ - - /* Allocate and populate the context object. */ - pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); - if( !pGeomCtx ) return SQLITE_NOMEM; - pGeomCtx->xGeom = xGeom; - pGeomCtx->pContext = pContext; - - /* Create the new user-function. Register a destructor function to delete - ** the context object when it is no longer required. */ - return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, - (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free - ); -} - -#if !SQLITE_CORE -SQLITE_API int sqlite3_extension_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3RtreeInit(db); -} -#endif - -#endif - -/************** End of rtree.c ***********************************************/ -/************** Begin file icu.c *********************************************/ -/* -** 2007 May 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $ -** -** This file implements an integration between the ICU library -** ("International Components for Unicode", an open-source library -** for handling unicode data) and SQLite. The integration uses -** ICU to provide the following to SQLite: -** -** * An implementation of the SQL regexp() function (and hence REGEXP -** operator) using the ICU uregex_XX() APIs. -** -** * Implementations of the SQL scalar upper() and lower() functions -** for case mapping. -** -** * Integration of ICU and SQLite collation seqences. -** -** * An implementation of the LIKE operator that uses ICU to -** provide case-independent matching. -*/ - -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) - -/* Include ICU headers */ -#include -#include -#include -#include - -/* #include */ - -#ifndef SQLITE_CORE - SQLITE_EXTENSION_INIT1 -#else -#endif - -/* -** Maximum length (in bytes) of the pattern in a LIKE or GLOB -** operator. -*/ -#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH -# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 -#endif - -/* -** Version of sqlite3_free() that is always a function, never a macro. -*/ -static void xFree(void *p){ - sqlite3_free(p); -} - -/* -** Compare two UTF-8 strings for equality where the first string is -** a "LIKE" expression. Return true (1) if they are the same and -** false (0) if they are different. -*/ -static int icuLikeCompare( - const uint8_t *zPattern, /* LIKE pattern */ - const uint8_t *zString, /* The UTF-8 string to compare against */ - const UChar32 uEsc /* The escape character */ -){ - static const int MATCH_ONE = (UChar32)'_'; - static const int MATCH_ALL = (UChar32)'%'; - - int iPattern = 0; /* Current byte index in zPattern */ - int iString = 0; /* Current byte index in zString */ - - int prevEscape = 0; /* True if the previous character was uEsc */ - - while( zPattern[iPattern]!=0 ){ - - /* Read (and consume) the next character from the input pattern. */ - UChar32 uPattern; - U8_NEXT_UNSAFE(zPattern, iPattern, uPattern); - assert(uPattern!=0); - - /* There are now 4 possibilities: - ** - ** 1. uPattern is an unescaped match-all character "%", - ** 2. uPattern is an unescaped match-one character "_", - ** 3. uPattern is an unescaped escape character, or - ** 4. uPattern is to be handled as an ordinary character - */ - if( !prevEscape && uPattern==MATCH_ALL ){ - /* Case 1. */ - uint8_t c; - - /* Skip any MATCH_ALL or MATCH_ONE characters that follow a - ** MATCH_ALL. For each MATCH_ONE, skip one character in the - ** test string. - */ - while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){ - if( c==MATCH_ONE ){ - if( zString[iString]==0 ) return 0; - U8_FWD_1_UNSAFE(zString, iString); - } - iPattern++; - } - - if( zPattern[iPattern]==0 ) return 1; - - while( zString[iString] ){ - if( icuLikeCompare(&zPattern[iPattern], &zString[iString], uEsc) ){ - return 1; - } - U8_FWD_1_UNSAFE(zString, iString); - } - return 0; - - }else if( !prevEscape && uPattern==MATCH_ONE ){ - /* Case 2. */ - if( zString[iString]==0 ) return 0; - U8_FWD_1_UNSAFE(zString, iString); - - }else if( !prevEscape && uPattern==uEsc){ - /* Case 3. */ - prevEscape = 1; - - }else{ - /* Case 4. */ - UChar32 uString; - U8_NEXT_UNSAFE(zString, iString, uString); - uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT); - uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT); - if( uString!=uPattern ){ - return 0; - } - prevEscape = 0; - } - } - - return zString[iString]==0; -} - -/* -** Implementation of the like() SQL function. This function implements -** the build-in LIKE operator. The first argument to the function is the -** pattern and the second argument is the string. So, the SQL statements: -** -** A LIKE B -** -** is implemented as like(B, A). If there is an escape character E, -** -** A LIKE B ESCAPE E -** -** is mapped to like(B, A, E). -*/ -static void icuLikeFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - const unsigned char *zA = sqlite3_value_text(argv[0]); - const unsigned char *zB = sqlite3_value_text(argv[1]); - UChar32 uEsc = 0; - - /* Limit the length of the LIKE or GLOB pattern to avoid problems - ** of deep recursion and N*N behavior in patternCompare(). - */ - if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){ - sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); - return; - } - - - if( argc==3 ){ - /* The escape character string must consist of a single UTF-8 character. - ** Otherwise, return an error. - */ - int nE= sqlite3_value_bytes(argv[2]); - const unsigned char *zE = sqlite3_value_text(argv[2]); - int i = 0; - if( zE==0 ) return; - U8_NEXT(zE, i, nE, uEsc); - if( i!=nE){ - sqlite3_result_error(context, - "ESCAPE expression must be a single character", -1); - return; - } - } - - if( zA && zB ){ - sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc)); - } -} - -/* -** This function is called when an ICU function called from within -** the implementation of an SQL scalar function returns an error. -** -** The scalar function context passed as the first argument is -** loaded with an error message based on the following two args. -*/ -static void icuFunctionError( - sqlite3_context *pCtx, /* SQLite scalar function context */ - const char *zName, /* Name of ICU function that failed */ - UErrorCode e /* Error code returned by ICU function */ -){ - char zBuf[128]; - sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); - zBuf[127] = '\0'; - sqlite3_result_error(pCtx, zBuf, -1); -} - -/* -** Function to delete compiled regexp objects. Registered as -** a destructor function with sqlite3_set_auxdata(). -*/ -static void icuRegexpDelete(void *p){ - URegularExpression *pExpr = (URegularExpression *)p; - uregex_close(pExpr); -} - -/* -** Implementation of SQLite REGEXP operator. This scalar function takes -** two arguments. The first is a regular expression pattern to compile -** the second is a string to match against that pattern. If either -** argument is an SQL NULL, then NULL Is returned. Otherwise, the result -** is 1 if the string matches the pattern, or 0 otherwise. -** -** SQLite maps the regexp() function to the regexp() operator such -** that the following two are equivalent: -** -** zString REGEXP zPattern -** regexp(zPattern, zString) -** -** Uses the following ICU regexp APIs: -** -** uregex_open() -** uregex_matches() -** uregex_close() -*/ -static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){ - UErrorCode status = U_ZERO_ERROR; - URegularExpression *pExpr; - UBool res; - const UChar *zString = sqlite3_value_text16(apArg[1]); - - (void)nArg; /* Unused parameter */ - - /* If the left hand side of the regexp operator is NULL, - ** then the result is also NULL. - */ - if( !zString ){ - return; - } - - pExpr = sqlite3_get_auxdata(p, 0); - if( !pExpr ){ - const UChar *zPattern = sqlite3_value_text16(apArg[0]); - if( !zPattern ){ - return; - } - pExpr = uregex_open(zPattern, -1, 0, 0, &status); - - if( U_SUCCESS(status) ){ - sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete); - }else{ - assert(!pExpr); - icuFunctionError(p, "uregex_open", status); - return; - } - } - - /* Configure the text that the regular expression operates on. */ - uregex_setText(pExpr, zString, -1, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "uregex_setText", status); - return; - } - - /* Attempt the match */ - res = uregex_matches(pExpr, 0, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "uregex_matches", status); - return; - } - - /* Set the text that the regular expression operates on to a NULL - ** pointer. This is not really necessary, but it is tidier than - ** leaving the regular expression object configured with an invalid - ** pointer after this function returns. - */ - uregex_setText(pExpr, 0, 0, &status); - - /* Return 1 or 0. */ - sqlite3_result_int(p, res ? 1 : 0); -} - -/* -** Implementations of scalar functions for case mapping - upper() and -** lower(). Function upper() converts its input to upper-case (ABC). -** Function lower() converts to lower-case (abc). -** -** ICU provides two types of case mapping, "general" case mapping and -** "language specific". Refer to ICU documentation for the differences -** between the two. -** -** To utilise "general" case mapping, the upper() or lower() scalar -** functions are invoked with one argument: -** -** upper('ABC') -> 'abc' -** lower('abc') -> 'ABC' -** -** To access ICU "language specific" case mapping, upper() or lower() -** should be invoked with two arguments. The second argument is the name -** of the locale to use. Passing an empty string ("") or SQL NULL value -** as the second argument is the same as invoking the 1 argument version -** of upper() or lower(). -** -** lower('I', 'en_us') -> 'i' -** lower('I', 'tr_tr') -> 'ı' (small dotless i) -** -** http://www.icu-project.org/userguide/posix.html#case_mappings -*/ -static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ - const UChar *zInput; - UChar *zOutput; - int nInput; - int nOutput; - - UErrorCode status = U_ZERO_ERROR; - const char *zLocale = 0; - - assert(nArg==1 || nArg==2); - if( nArg==2 ){ - zLocale = (const char *)sqlite3_value_text(apArg[1]); - } - - zInput = sqlite3_value_text16(apArg[0]); - if( !zInput ){ - return; - } - nInput = sqlite3_value_bytes16(apArg[0]); - - nOutput = nInput * 2 + 2; - zOutput = sqlite3_malloc(nOutput); - if( !zOutput ){ - return; - } - - if( sqlite3_user_data(p) ){ - u_strToUpper(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status); - }else{ - u_strToLower(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status); - } - - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "u_strToLower()/u_strToUpper", status); - return; - } - - sqlite3_result_text16(p, zOutput, -1, xFree); -} - -/* -** Collation sequence destructor function. The pCtx argument points to -** a UCollator structure previously allocated using ucol_open(). -*/ -static void icuCollationDel(void *pCtx){ - UCollator *p = (UCollator *)pCtx; - ucol_close(p); -} - -/* -** Collation sequence comparison function. The pCtx argument points to -** a UCollator structure previously allocated using ucol_open(). -*/ -static int icuCollationColl( - void *pCtx, - int nLeft, - const void *zLeft, - int nRight, - const void *zRight -){ - UCollationResult res; - UCollator *p = (UCollator *)pCtx; - res = ucol_strcoll(p, (UChar *)zLeft, nLeft/2, (UChar *)zRight, nRight/2); - switch( res ){ - case UCOL_LESS: return -1; - case UCOL_GREATER: return +1; - case UCOL_EQUAL: return 0; - } - assert(!"Unexpected return value from ucol_strcoll()"); - return 0; -} - -/* -** Implementation of the scalar function icu_load_collation(). -** -** This scalar function is used to add ICU collation based collation -** types to an SQLite database connection. It is intended to be called -** as follows: -** -** SELECT icu_load_collation(, ); -** -** Where is a string containing an ICU locale identifier (i.e. -** "en_AU", "tr_TR" etc.) and is the name of the -** collation sequence to create. -*/ -static void icuLoadCollation( - sqlite3_context *p, - int nArg, - sqlite3_value **apArg -){ - sqlite3 *db = (sqlite3 *)sqlite3_user_data(p); - UErrorCode status = U_ZERO_ERROR; - const char *zLocale; /* Locale identifier - (eg. "jp_JP") */ - const char *zName; /* SQL Collation sequence name (eg. "japanese") */ - UCollator *pUCollator; /* ICU library collation object */ - int rc; /* Return code from sqlite3_create_collation_x() */ - - assert(nArg==2); - zLocale = (const char *)sqlite3_value_text(apArg[0]); - zName = (const char *)sqlite3_value_text(apArg[1]); - - if( !zLocale || !zName ){ - return; - } - - pUCollator = ucol_open(zLocale, &status); - if( !U_SUCCESS(status) ){ - icuFunctionError(p, "ucol_open", status); - return; - } - assert(p); - - rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator, - icuCollationColl, icuCollationDel - ); - if( rc!=SQLITE_OK ){ - ucol_close(pUCollator); - sqlite3_result_error(p, "Error registering collation function", -1); - } -} - -/* -** Register the ICU extension functions with database db. -*/ -SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){ - struct IcuScalar { - const char *zName; /* Function name */ - int nArg; /* Number of arguments */ - int enc; /* Optimal text encoding */ - void *pContext; /* sqlite3_user_data() context */ - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } scalars[] = { - {"regexp", 2, SQLITE_ANY, 0, icuRegexpFunc}, - - {"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16}, - {"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16}, - {"upper", 1, SQLITE_UTF16, (void*)1, icuCaseFunc16}, - {"upper", 2, SQLITE_UTF16, (void*)1, icuCaseFunc16}, - - {"lower", 1, SQLITE_UTF8, 0, icuCaseFunc16}, - {"lower", 2, SQLITE_UTF8, 0, icuCaseFunc16}, - {"upper", 1, SQLITE_UTF8, (void*)1, icuCaseFunc16}, - {"upper", 2, SQLITE_UTF8, (void*)1, icuCaseFunc16}, - - {"like", 2, SQLITE_UTF8, 0, icuLikeFunc}, - {"like", 3, SQLITE_UTF8, 0, icuLikeFunc}, - - {"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation}, - }; - - int rc = SQLITE_OK; - int i; - - for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){ - struct IcuScalar *p = &scalars[i]; - rc = sqlite3_create_function( - db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0 - ); - } - - return rc; -} - -#if !SQLITE_CORE -SQLITE_API int sqlite3_extension_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi -){ - SQLITE_EXTENSION_INIT2(pApi) - return sqlite3IcuInit(db); -} -#endif - -#endif - -/************** End of icu.c *************************************************/ -/************** Begin file fts3_icu.c ****************************************/ -/* -** 2007 June 22 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This file implements a tokenizer for fts3 based on the ICU library. -*/ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) -#ifdef SQLITE_ENABLE_ICU - -/* #include */ -/* #include */ - -#include -/* #include */ -/* #include */ -#include - -typedef struct IcuTokenizer IcuTokenizer; -typedef struct IcuCursor IcuCursor; - -struct IcuTokenizer { - sqlite3_tokenizer base; - char *zLocale; -}; - -struct IcuCursor { - sqlite3_tokenizer_cursor base; - - UBreakIterator *pIter; /* ICU break-iterator object */ - int nChar; /* Number of UChar elements in pInput */ - UChar *aChar; /* Copy of input using utf-16 encoding */ - int *aOffset; /* Offsets of each character in utf-8 input */ - - int nBuffer; - char *zBuffer; - - int iToken; -}; - -/* -** Create a new tokenizer instance. -*/ -static int icuCreate( - int argc, /* Number of entries in argv[] */ - const char * const *argv, /* Tokenizer creation arguments */ - sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ -){ - IcuTokenizer *p; - int n = 0; - - if( argc>0 ){ - n = strlen(argv[0])+1; - } - p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n); - if( !p ){ - return SQLITE_NOMEM; - } - memset(p, 0, sizeof(IcuTokenizer)); - - if( n ){ - p->zLocale = (char *)&p[1]; - memcpy(p->zLocale, argv[0], n); - } - - *ppTokenizer = (sqlite3_tokenizer *)p; - - return SQLITE_OK; -} - -/* -** Destroy a tokenizer -*/ -static int icuDestroy(sqlite3_tokenizer *pTokenizer){ - IcuTokenizer *p = (IcuTokenizer *)pTokenizer; - sqlite3_free(p); - return SQLITE_OK; -} - -/* -** Prepare to begin tokenizing a particular string. The input -** string to be tokenized is pInput[0..nBytes-1]. A cursor -** used to incrementally tokenize this string is returned in -** *ppCursor. -*/ -static int icuOpen( - sqlite3_tokenizer *pTokenizer, /* The tokenizer */ - const char *zInput, /* Input string */ - int nInput, /* Length of zInput in bytes */ - sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ -){ - IcuTokenizer *p = (IcuTokenizer *)pTokenizer; - IcuCursor *pCsr; - - const int32_t opt = U_FOLD_CASE_DEFAULT; - UErrorCode status = U_ZERO_ERROR; - int nChar; - - UChar32 c; - int iInput = 0; - int iOut = 0; - - *ppCursor = 0; - - if( zInput==0 ){ - nInput = 0; - zInput = ""; - }else if( nInput<0 ){ - nInput = strlen(zInput); - } - nChar = nInput+1; - pCsr = (IcuCursor *)sqlite3_malloc( - sizeof(IcuCursor) + /* IcuCursor */ - ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */ - (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ - ); - if( !pCsr ){ - return SQLITE_NOMEM; - } - memset(pCsr, 0, sizeof(IcuCursor)); - pCsr->aChar = (UChar *)&pCsr[1]; - pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3]; - - pCsr->aOffset[iOut] = iInput; - U8_NEXT(zInput, iInput, nInput, c); - while( c>0 ){ - int isError = 0; - c = u_foldCase(c, opt); - U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); - if( isError ){ - sqlite3_free(pCsr); - return SQLITE_ERROR; - } - pCsr->aOffset[iOut] = iInput; - - if( iInputpIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status); - if( !U_SUCCESS(status) ){ - sqlite3_free(pCsr); - return SQLITE_ERROR; - } - pCsr->nChar = iOut; - - ubrk_first(pCsr->pIter); - *ppCursor = (sqlite3_tokenizer_cursor *)pCsr; - return SQLITE_OK; -} - -/* -** Close a tokenization cursor previously opened by a call to icuOpen(). -*/ -static int icuClose(sqlite3_tokenizer_cursor *pCursor){ - IcuCursor *pCsr = (IcuCursor *)pCursor; - ubrk_close(pCsr->pIter); - sqlite3_free(pCsr->zBuffer); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* -** Extract the next token from a tokenization cursor. -*/ -static int icuNext( - sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ - const char **ppToken, /* OUT: *ppToken is the token text */ - int *pnBytes, /* OUT: Number of bytes in token */ - int *piStartOffset, /* OUT: Starting offset of token */ - int *piEndOffset, /* OUT: Ending offset of token */ - int *piPosition /* OUT: Position integer of token */ -){ - IcuCursor *pCsr = (IcuCursor *)pCursor; - - int iStart = 0; - int iEnd = 0; - int nByte = 0; - - while( iStart==iEnd ){ - UChar32 c; - - iStart = ubrk_current(pCsr->pIter); - iEnd = ubrk_next(pCsr->pIter); - if( iEnd==UBRK_DONE ){ - return SQLITE_DONE; - } - - while( iStartaChar, iWhite, pCsr->nChar, c); - if( u_isspace(c) ){ - iStart = iWhite; - }else{ - break; - } - } - assert(iStart<=iEnd); - } - - do { - UErrorCode status = U_ZERO_ERROR; - if( nByte ){ - char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte); - if( !zNew ){ - return SQLITE_NOMEM; - } - pCsr->zBuffer = zNew; - pCsr->nBuffer = nByte; - } - - u_strToUTF8( - pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */ - &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */ - &status /* Output success/failure */ - ); - } while( nByte>pCsr->nBuffer ); - - *ppToken = pCsr->zBuffer; - *pnBytes = nByte; - *piStartOffset = pCsr->aOffset[iStart]; - *piEndOffset = pCsr->aOffset[iEnd]; - *piPosition = pCsr->iToken++; - - return SQLITE_OK; -} - -/* -** The set of routines that implement the simple tokenizer -*/ -static const sqlite3_tokenizer_module icuTokenizerModule = { - 0, /* iVersion */ - icuCreate, /* xCreate */ - icuDestroy, /* xCreate */ - icuOpen, /* xOpen */ - icuClose, /* xClose */ - icuNext, /* xNext */ -}; - -/* -** Set *ppModule to point at the implementation of the ICU tokenizer. -*/ -SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule( - sqlite3_tokenizer_module const**ppModule -){ - *ppModule = &icuTokenizerModule; -} - -#endif /* defined(SQLITE_ENABLE_ICU) */ -#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ - -/************** End of fts3_icu.c ********************************************/ diff --git a/src/3rdparty/sqlite3.h b/src/3rdparty/sqlite3.h deleted file mode 100644 index e398838287..0000000000 --- a/src/3rdparty/sqlite3.h +++ /dev/null @@ -1,7245 +0,0 @@ -/* -** 2001 September 15 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** This header file defines the interface that the SQLite library -** presents to client programs. If a C-function, structure, datatype, -** or constant definition does not appear in this file, then it is -** not a published API of SQLite, is subject to change without -** notice, and should not be referenced by programs that use SQLite. -** -** Some of the definitions that are in this file are marked as -** "experimental". Experimental interfaces are normally new -** features recently added to SQLite. We do not anticipate changes -** to experimental interfaces but reserve the right to make minor changes -** if experience from use "in the wild" suggest such changes are prudent. -** -** The official C-language API documentation for SQLite is derived -** from comments in this file. This file is the authoritative source -** on how SQLite interfaces are suppose to operate. -** -** The name of this file under configuration management is "sqlite.h.in". -** The makefile makes some minor changes to this file (such as inserting -** the version number) and changes its name to "sqlite3.h" as -** part of the build process. -*/ -#ifndef _SQLITE3_H_ -#define _SQLITE3_H_ -#include /* Needed for the definition of va_list */ - -/* -** Make sure we can call this stuff from C++. -*/ -#ifdef __cplusplus -extern "C" { -#endif - - -/* -** Add the ability to override 'extern' -*/ -#ifndef SQLITE_EXTERN -# define SQLITE_EXTERN extern -#endif - -#ifndef SQLITE_API -# define SQLITE_API -#endif - - -/* -** These no-op macros are used in front of interfaces to mark those -** interfaces as either deprecated or experimental. New applications -** should not use deprecated interfaces - they are support for backwards -** compatibility only. Application writers should be aware that -** experimental interfaces are subject to change in point releases. -** -** These macros used to resolve to various kinds of compiler magic that -** would generate warning messages when they were used. But that -** compiler magic ended up generating such a flurry of bug reports -** that we have taken it all out and gone back to using simple -** noop macros. -*/ -#define SQLITE_DEPRECATED -#define SQLITE_EXPERIMENTAL - -/* -** Ensure these symbols were not defined by some previous header file. -*/ -#ifdef SQLITE_VERSION -# undef SQLITE_VERSION -#endif -#ifdef SQLITE_VERSION_NUMBER -# undef SQLITE_VERSION_NUMBER -#endif - -/* -** CAPI3REF: Compile-Time Library Version Numbers -** -** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header -** evaluates to a string literal that is the SQLite version in the -** format "X.Y.Z" where X is the major version number (always 3 for -** SQLite3) and Y is the minor version number and Z is the release number.)^ -** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer -** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same -** numbers used in [SQLITE_VERSION].)^ -** The SQLITE_VERSION_NUMBER for any given release of SQLite will also -** be larger than the release from which it is derived. Either Y will -** be held constant and Z will be incremented or else Y will be incremented -** and Z will be reset to zero. -** -** Since version 3.6.18, SQLite source code has been stored in the -** Fossil configuration management -** system. ^The SQLITE_SOURCE_ID macro evaluates to -** a string which identifies a particular check-in of SQLite -** within its configuration management system. ^The SQLITE_SOURCE_ID -** string contains the date and time of the check-in (UTC) and an SHA1 -** hash of the entire source tree. -** -** See also: [sqlite3_libversion()], -** [sqlite3_libversion_number()], [sqlite3_sourceid()], -** [sqlite_version()] and [sqlite_source_id()]. -*/ -#define SQLITE_VERSION "3.7.17" -#define SQLITE_VERSION_NUMBER 3007017 -#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668" - -/* -** CAPI3REF: Run-Time Library Version Numbers -** KEYWORDS: sqlite3_version, sqlite3_sourceid -** -** These interfaces provide the same information as the [SQLITE_VERSION], -** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros -** but are associated with the library instead of the header file. ^(Cautious -** programmers might include assert() statements in their application to -** verify that values returned by these interfaces match the macros in -** the header, and thus insure that the application is -** compiled with matching library and header files. -** -**
-** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
-** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
-** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
-** 
)^ -** -** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] -** macro. ^The sqlite3_libversion() function returns a pointer to the -** to the sqlite3_version[] string constant. The sqlite3_libversion() -** function is provided for use in DLLs since DLL users usually do not have -** direct access to string constants within the DLL. ^The -** sqlite3_libversion_number() function returns an integer equal to -** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns -** a pointer to a string constant whose value is the same as the -** [SQLITE_SOURCE_ID] C preprocessor macro. -** -** See also: [sqlite_version()] and [sqlite_source_id()]. -*/ -SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; -SQLITE_API const char *sqlite3_libversion(void); -SQLITE_API const char *sqlite3_sourceid(void); -SQLITE_API int sqlite3_libversion_number(void); - -/* -** CAPI3REF: Run-Time Library Compilation Options Diagnostics -** -** ^The sqlite3_compileoption_used() function returns 0 or 1 -** indicating whether the specified option was defined at -** compile time. ^The SQLITE_ prefix may be omitted from the -** option name passed to sqlite3_compileoption_used(). -** -** ^The sqlite3_compileoption_get() function allows iterating -** over the list of options that were defined at compile time by -** returning the N-th compile time option string. ^If N is out of range, -** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ -** prefix is omitted from any strings returned by -** sqlite3_compileoption_get(). -** -** ^Support for the diagnostic functions sqlite3_compileoption_used() -** and sqlite3_compileoption_get() may be omitted by specifying the -** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. -** -** See also: SQL functions [sqlite_compileoption_used()] and -** [sqlite_compileoption_get()] and the [compile_options pragma]. -*/ -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS -SQLITE_API int sqlite3_compileoption_used(const char *zOptName); -SQLITE_API const char *sqlite3_compileoption_get(int N); -#endif - -/* -** CAPI3REF: Test To See If The Library Is Threadsafe -** -** ^The sqlite3_threadsafe() function returns zero if and only if -** SQLite was compiled with mutexing code omitted due to the -** [SQLITE_THREADSAFE] compile-time option being set to 0. -** -** SQLite can be compiled with or without mutexes. When -** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes -** are enabled and SQLite is threadsafe. When the -** [SQLITE_THREADSAFE] macro is 0, -** the mutexes are omitted. Without the mutexes, it is not safe -** to use SQLite concurrently from more than one thread. -** -** Enabling mutexes incurs a measurable performance penalty. -** So if speed is of utmost importance, it makes sense to disable -** the mutexes. But for maximum safety, mutexes should be enabled. -** ^The default behavior is for mutexes to be enabled. -** -** This interface can be used by an application to make sure that the -** version of SQLite that it is linking against was compiled with -** the desired setting of the [SQLITE_THREADSAFE] macro. -** -** This interface only reports on the compile-time mutex setting -** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with -** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but -** can be fully or partially disabled using a call to [sqlite3_config()] -** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], -** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the -** sqlite3_threadsafe() function shows only the compile-time setting of -** thread safety, not any run-time changes to that setting made by -** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() -** is unchanged by calls to sqlite3_config().)^ -** -** See the [threading mode] documentation for additional information. -*/ -SQLITE_API int sqlite3_threadsafe(void); - -/* -** CAPI3REF: Database Connection Handle -** KEYWORDS: {database connection} {database connections} -** -** Each open SQLite database is represented by a pointer to an instance of -** the opaque structure named "sqlite3". It is useful to think of an sqlite3 -** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] -** and [sqlite3_close_v2()] are its destructors. There are many other -** interfaces (such as -** [sqlite3_prepare_v2()], [sqlite3_create_function()], and -** [sqlite3_busy_timeout()] to name but three) that are methods on an -** sqlite3 object. -*/ -typedef struct sqlite3 sqlite3; - -/* -** CAPI3REF: 64-Bit Integer Types -** KEYWORDS: sqlite_int64 sqlite_uint64 -** -** Because there is no cross-platform way to specify 64-bit integer types -** SQLite includes typedefs for 64-bit signed and unsigned integers. -** -** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. -** The sqlite_int64 and sqlite_uint64 types are supported for backwards -** compatibility only. -** -** ^The sqlite3_int64 and sqlite_int64 types can store integer values -** between -9223372036854775808 and +9223372036854775807 inclusive. ^The -** sqlite3_uint64 and sqlite_uint64 types can store integer values -** between 0 and +18446744073709551615 inclusive. -*/ -#ifdef SQLITE_INT64_TYPE - typedef SQLITE_INT64_TYPE sqlite_int64; - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 sqlite_int64; - typedef unsigned __int64 sqlite_uint64; -#else - typedef long long int sqlite_int64; - typedef unsigned long long int sqlite_uint64; -#endif -typedef sqlite_int64 sqlite3_int64; -typedef sqlite_uint64 sqlite3_uint64; - -/* -** If compiling for a processor that lacks floating point support, -** substitute integer for floating-point. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# define double sqlite3_int64 -#endif - -/* -** CAPI3REF: Closing A Database Connection -** -** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors -** for the [sqlite3] object. -** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if -** the [sqlite3] object is successfully destroyed and all associated -** resources are deallocated. -** -** ^If the database connection is associated with unfinalized prepared -** statements or unfinished sqlite3_backup objects then sqlite3_close() -** will leave the database connection open and return [SQLITE_BUSY]. -** ^If sqlite3_close_v2() is called with unfinalized prepared statements -** and unfinished sqlite3_backups, then the database connection becomes -** an unusable "zombie" which will automatically be deallocated when the -** last prepared statement is finalized or the last sqlite3_backup is -** finished. The sqlite3_close_v2() interface is intended for use with -** host languages that are garbage collected, and where the order in which -** destructors are called is arbitrary. -** -** Applications should [sqlite3_finalize | finalize] all [prepared statements], -** [sqlite3_blob_close | close] all [BLOB handles], and -** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated -** with the [sqlite3] object prior to attempting to close the object. ^If -** sqlite3_close_v2() is called on a [database connection] that still has -** outstanding [prepared statements], [BLOB handles], and/or -** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation -** of resources is deferred until all [prepared statements], [BLOB handles], -** and [sqlite3_backup] objects are also destroyed. -** -** ^If an [sqlite3] object is destroyed while a transaction is open, -** the transaction is automatically rolled back. -** -** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] -** must be either a NULL -** pointer or an [sqlite3] object pointer obtained -** from [sqlite3_open()], [sqlite3_open16()], or -** [sqlite3_open_v2()], and not previously closed. -** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer -** argument is a harmless no-op. -*/ -SQLITE_API int sqlite3_close(sqlite3*); -SQLITE_API int sqlite3_close_v2(sqlite3*); - -/* -** The type for a callback function. -** This is legacy and deprecated. It is included for historical -** compatibility and is not documented. -*/ -typedef int (*sqlite3_callback)(void*,int,char**, char**); - -/* -** CAPI3REF: One-Step Query Execution Interface -** -** The sqlite3_exec() interface is a convenience wrapper around -** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], -** that allows an application to run multiple statements of SQL -** without having to use a lot of C code. -** -** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, -** semicolon-separate SQL statements passed into its 2nd argument, -** in the context of the [database connection] passed in as its 1st -** argument. ^If the callback function of the 3rd argument to -** sqlite3_exec() is not NULL, then it is invoked for each result row -** coming out of the evaluated SQL statements. ^The 4th argument to -** sqlite3_exec() is relayed through to the 1st argument of each -** callback invocation. ^If the callback pointer to sqlite3_exec() -** is NULL, then no callback is ever invoked and result rows are -** ignored. -** -** ^If an error occurs while evaluating the SQL statements passed into -** sqlite3_exec(), then execution of the current statement stops and -** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() -** is not NULL then any error message is written into memory obtained -** from [sqlite3_malloc()] and passed back through the 5th parameter. -** To avoid memory leaks, the application should invoke [sqlite3_free()] -** on error message strings returned through the 5th parameter of -** of sqlite3_exec() after the error message string is no longer needed. -** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors -** occur, then sqlite3_exec() sets the pointer in its 5th parameter to -** NULL before returning. -** -** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() -** routine returns SQLITE_ABORT without invoking the callback again and -** without running any subsequent SQL statements. -** -** ^The 2nd argument to the sqlite3_exec() callback function is the -** number of columns in the result. ^The 3rd argument to the sqlite3_exec() -** callback is an array of pointers to strings obtained as if from -** [sqlite3_column_text()], one for each column. ^If an element of a -** result row is NULL then the corresponding string pointer for the -** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the -** sqlite3_exec() callback is an array of pointers to strings where each -** entry represents the name of corresponding result column as obtained -** from [sqlite3_column_name()]. -** -** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer -** to an empty string, or a pointer that contains only whitespace and/or -** SQL comments, then no SQL statements are evaluated and the database -** is not changed. -** -** Restrictions: -** -**
    -**
  • The application must insure that the 1st parameter to sqlite3_exec() -** is a valid and open [database connection]. -**
  • The application must not close [database connection] specified by -** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. -**
  • The application must not modify the SQL statement text passed into -** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. -**
-*/ -SQLITE_API int sqlite3_exec( - sqlite3*, /* An open database */ - const char *sql, /* SQL to be evaluated */ - int (*callback)(void*,int,char**,char**), /* Callback function */ - void *, /* 1st argument to callback */ - char **errmsg /* Error msg written here */ -); - -/* -** CAPI3REF: Result Codes -** KEYWORDS: SQLITE_OK {error code} {error codes} -** KEYWORDS: {result code} {result codes} -** -** Many SQLite functions return an integer result code from the set shown -** here in order to indicate success or failure. -** -** New error codes may be added in future versions of SQLite. -** -** See also: [SQLITE_IOERR_READ | extended result codes], -** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes]. -*/ -#define SQLITE_OK 0 /* Successful result */ -/* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ -#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ -/* end-of-error-codes */ - -/* -** CAPI3REF: Extended Result Codes -** KEYWORDS: {extended error code} {extended error codes} -** KEYWORDS: {extended result code} {extended result codes} -** -** In its default configuration, SQLite API routines return one of 26 integer -** [SQLITE_OK | result codes]. However, experience has shown that many of -** these result codes are too coarse-grained. They do not provide as -** much information about problems as programmers might like. In an effort to -** address this, newer versions of SQLite (version 3.3.8 and later) include -** support for additional result codes that provide more detailed information -** about errors. The extended result codes are enabled or disabled -** on a per database connection basis using the -** [sqlite3_extended_result_codes()] API. -** -** Some of the available extended result codes are listed here. -** One may expect the number of extended result codes will be expand -** over time. Software that uses extended result codes should expect -** to see new result codes in future releases of SQLite. -** -** The SQLITE_OK result code will never be extended. It will always -** be exactly zero. -*/ -#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) -#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) -#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) -#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) -#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) -#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) -#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) -#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) -#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) -#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) -#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) -#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) -#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) -#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) -#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) -#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) -#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) -#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) -#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) -#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) -#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) -#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) -#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) -#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) -#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) -#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) -#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) -#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) -#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) -#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) -#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) -#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) -#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) -#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) -#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) -#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) -#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) -#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) -#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) -#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) -#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) -#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) -#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) -#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) -#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) - -/* -** CAPI3REF: Flags For File Open Operations -** -** These bit values are intended for use in the -** 3rd parameter to the [sqlite3_open_v2()] interface and -** in the 4th parameter to the [sqlite3_vfs.xOpen] method. -*/ -#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ -#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ -#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ -#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ -#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ -#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ - -/* Reserved: 0x00F00000 */ - -/* -** CAPI3REF: Device Characteristics -** -** The xDeviceCharacteristics method of the [sqlite3_io_methods] -** object returns an integer which is a vector of these -** bit values expressing I/O characteristics of the mass storage -** device that holds the file that the [sqlite3_io_methods] -** refers to. -** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that -** after reboot following a crash or power loss, the only bytes in a -** file that were written at the application level might have changed -** and that adjacent bytes, even bytes within the same sector are -** guaranteed to be unchanged. -*/ -#define SQLITE_IOCAP_ATOMIC 0x00000001 -#define SQLITE_IOCAP_ATOMIC512 0x00000002 -#define SQLITE_IOCAP_ATOMIC1K 0x00000004 -#define SQLITE_IOCAP_ATOMIC2K 0x00000008 -#define SQLITE_IOCAP_ATOMIC4K 0x00000010 -#define SQLITE_IOCAP_ATOMIC8K 0x00000020 -#define SQLITE_IOCAP_ATOMIC16K 0x00000040 -#define SQLITE_IOCAP_ATOMIC32K 0x00000080 -#define SQLITE_IOCAP_ATOMIC64K 0x00000100 -#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 -#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 -#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 -#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 - -/* -** CAPI3REF: File Locking Levels -** -** SQLite uses one of these integer values as the second -** argument to calls it makes to the xLock() and xUnlock() methods -** of an [sqlite3_io_methods] object. -*/ -#define SQLITE_LOCK_NONE 0 -#define SQLITE_LOCK_SHARED 1 -#define SQLITE_LOCK_RESERVED 2 -#define SQLITE_LOCK_PENDING 3 -#define SQLITE_LOCK_EXCLUSIVE 4 - -/* -** CAPI3REF: Synchronization Type Flags -** -** When SQLite invokes the xSync() method of an -** [sqlite3_io_methods] object it uses a combination of -** these integer values as the second argument. -** -** When the SQLITE_SYNC_DATAONLY flag is used, it means that the -** sync operation only needs to flush data to mass storage. Inode -** information need not be flushed. If the lower four bits of the flag -** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. -** If the lower four bits equal SQLITE_SYNC_FULL, that means -** to use Mac OS X style fullsync instead of fsync(). -** -** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags -** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL -** settings. The [synchronous pragma] determines when calls to the -** xSync VFS method occur and applies uniformly across all platforms. -** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how -** energetic or rigorous or forceful the sync operations are and -** only make a difference on Mac OSX for the default SQLite code. -** (Third-party VFS implementations might also make the distinction -** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the -** operating systems natively supported by SQLite, only Mac OSX -** cares about the difference.) -*/ -#define SQLITE_SYNC_NORMAL 0x00002 -#define SQLITE_SYNC_FULL 0x00003 -#define SQLITE_SYNC_DATAONLY 0x00010 - -/* -** CAPI3REF: OS Interface Open File Handle -** -** An [sqlite3_file] object represents an open file in the -** [sqlite3_vfs | OS interface layer]. Individual OS interface -** implementations will -** want to subclass this object by appending additional fields -** for their own use. The pMethods entry is a pointer to an -** [sqlite3_io_methods] object that defines methods for performing -** I/O operations on the open file. -*/ -typedef struct sqlite3_file sqlite3_file; -struct sqlite3_file { - const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ -}; - -/* -** CAPI3REF: OS Interface File Virtual Methods Object -** -** Every file opened by the [sqlite3_vfs.xOpen] method populates an -** [sqlite3_file] object (or, more commonly, a subclass of the -** [sqlite3_file] object) with a pointer to an instance of this object. -** This object defines the methods used to perform various operations -** against the open file represented by the [sqlite3_file] object. -** -** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element -** to a non-NULL pointer, then the sqlite3_io_methods.xClose method -** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The -** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] -** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element -** to NULL. -** -** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or -** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). -** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] -** flag may be ORed in to indicate that only the data of the file -** and not its inode needs to be synced. -** -** The integer values to xLock() and xUnlock() are one of -**
    -**
  • [SQLITE_LOCK_NONE], -**
  • [SQLITE_LOCK_SHARED], -**
  • [SQLITE_LOCK_RESERVED], -**
  • [SQLITE_LOCK_PENDING], or -**
  • [SQLITE_LOCK_EXCLUSIVE]. -**
-** xLock() increases the lock. xUnlock() decreases the lock. -** The xCheckReservedLock() method checks whether any database connection, -** either in this process or in some other process, is holding a RESERVED, -** PENDING, or EXCLUSIVE lock on the file. It returns true -** if such a lock exists and false otherwise. -** -** The xFileControl() method is a generic interface that allows custom -** VFS implementations to directly control an open file using the -** [sqlite3_file_control()] interface. The second "op" argument is an -** integer opcode. The third argument is a generic pointer intended to -** point to a structure that may contain arguments or space in which to -** write return values. Potential uses for xFileControl() might be -** functions to enable blocking locks with timeouts, to change the -** locking strategy (for example to use dot-file locks), to inquire -** about the status of a lock, or to break stale locks. The SQLite -** core reserves all opcodes less than 100 for its own use. -** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. -** Applications that define a custom xFileControl method should use opcodes -** greater than 100 to avoid conflicts. VFS implementations should -** return [SQLITE_NOTFOUND] for file control opcodes that they do not -** recognize. -** -** The xSectorSize() method returns the sector size of the -** device that underlies the file. The sector size is the -** minimum write that can be performed without disturbing -** other bytes in the file. The xDeviceCharacteristics() -** method returns a bit vector describing behaviors of the -** underlying device: -** -**
    -**
  • [SQLITE_IOCAP_ATOMIC] -**
  • [SQLITE_IOCAP_ATOMIC512] -**
  • [SQLITE_IOCAP_ATOMIC1K] -**
  • [SQLITE_IOCAP_ATOMIC2K] -**
  • [SQLITE_IOCAP_ATOMIC4K] -**
  • [SQLITE_IOCAP_ATOMIC8K] -**
  • [SQLITE_IOCAP_ATOMIC16K] -**
  • [SQLITE_IOCAP_ATOMIC32K] -**
  • [SQLITE_IOCAP_ATOMIC64K] -**
  • [SQLITE_IOCAP_SAFE_APPEND] -**
  • [SQLITE_IOCAP_SEQUENTIAL] -**
-** -** The SQLITE_IOCAP_ATOMIC property means that all writes of -** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values -** mean that writes of blocks that are nnn bytes in size and -** are aligned to an address which is an integer multiple of -** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means -** that when data is appended to a file, the data is appended -** first then the size of the file is extended, never the other -** way around. The SQLITE_IOCAP_SEQUENTIAL property means that -** information is written to disk in the same order as calls -** to xWrite(). -** -** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill -** in the unread portions of the buffer with zeros. A VFS that -** fails to zero-fill short reads might seem to work. However, -** failure to zero-fill short reads will eventually lead to -** database corruption. -*/ -typedef struct sqlite3_io_methods sqlite3_io_methods; -struct sqlite3_io_methods { - int iVersion; - int (*xClose)(sqlite3_file*); - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); - int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); - int (*xSync)(sqlite3_file*, int flags); - int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); - int (*xLock)(sqlite3_file*, int); - int (*xUnlock)(sqlite3_file*, int); - int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); - int (*xFileControl)(sqlite3_file*, int op, void *pArg); - int (*xSectorSize)(sqlite3_file*); - int (*xDeviceCharacteristics)(sqlite3_file*); - /* Methods above are valid for version 1 */ - int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); - int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); - void (*xShmBarrier)(sqlite3_file*); - int (*xShmUnmap)(sqlite3_file*, int deleteFlag); - /* Methods above are valid for version 2 */ - int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); - int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); - /* Methods above are valid for version 3 */ - /* Additional methods may be added in future releases */ -}; - -/* -** CAPI3REF: Standard File Control Opcodes -** -** These integer constants are opcodes for the xFileControl method -** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] -** interface. -** -** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This -** opcode causes the xFileControl method to write the current state of -** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], -** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) -** into an integer that the pArg argument points to. This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -**
    -**
  • [[SQLITE_FCNTL_SIZE_HINT]] -** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS -** layer a hint of how large the database file will grow to be during the -** current transaction. This hint is not guaranteed to be accurate but it -** is often close. The underlying VFS might choose to preallocate database -** file space based on this hint in order to help writes to the database -** file run faster. -** -**
  • [[SQLITE_FCNTL_CHUNK_SIZE]] -** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS -** extends and truncates the database file in chunks of a size specified -** by the user. The fourth argument to [sqlite3_file_control()] should -** point to an integer (type int) containing the new chunk-size to use -** for the nominated database. Allocating database file space in large -** chunks (say 1MB at a time), may reduce file-system fragmentation and -** improve performance on some systems. -** -**
  • [[SQLITE_FCNTL_FILE_POINTER]] -** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer -** to the [sqlite3_file] object associated with a particular database -** connection. See the [sqlite3_file_control()] documentation for -** additional information. -** -**
  • [[SQLITE_FCNTL_SYNC_OMITTED]] -** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by -** SQLite and sent to all VFSes in place of a call to the xSync method -** when the database connection has [PRAGMA synchronous] set to OFF.)^ -** Some specialized VFSes need this signal in order to operate correctly -** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most -** VFSes do not need this signal and should silently ignore this opcode. -** Applications should not call [sqlite3_file_control()] with this -** opcode as doing so may disrupt the operation of the specialized VFSes -** that do require it. -** -**
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] -** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic -** retry counts and intervals for certain disk I/O operations for the -** windows [VFS] in order to provide robustness in the presence of -** anti-virus programs. By default, the windows VFS will retry file read, -** file write, and file delete operations up to 10 times, with a delay -** of 25 milliseconds before the first retry and with the delay increasing -** by an additional 25 milliseconds with each subsequent retry. This -** opcode allows these two values (10 retries and 25 milliseconds of delay) -** to be adjusted. The values are changed for all database connections -** within the same process. The argument is a pointer to an array of two -** integers where the first integer i the new retry count and the second -** integer is the delay. If either integer is negative, then the setting -** is not changed but instead the prior value of that setting is written -** into the array entry, allowing the current retry settings to be -** interrogated. The zDbName parameter is ignored. -** -**
  • [[SQLITE_FCNTL_PERSIST_WAL]] -** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the -** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary -** write ahead log and shared memory files used for transaction control -** are automatically deleted when the latest connection to the database -** closes. Setting persistent WAL mode causes those files to persist after -** close. Persisting the files is useful when other processes that do not -** have write permission on the directory containing the database file want -** to read the database file, as the WAL and shared memory files must exist -** in order for the database to be readable. The fourth parameter to -** [sqlite3_file_control()] for this opcode should be a pointer to an integer. -** That integer is 0 to disable persistent WAL mode or 1 to enable persistent -** WAL mode. If the integer is -1, then it is overwritten with the current -** WAL persistence setting. -** -**
  • [[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] -** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the -** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting -** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the -** xDeviceCharacteristics methods. The fourth parameter to -** [sqlite3_file_control()] for this opcode should be a pointer to an integer. -** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage -** mode. If the integer is -1, then it is overwritten with the current -** zero-damage mode setting. -** -**
  • [[SQLITE_FCNTL_OVERWRITE]] -** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening -** a write transaction to indicate that, unless it is rolled back for some -** reason, the entire database file will be overwritten by the current -** transaction. This is used by VACUUM operations. -** -**
  • [[SQLITE_FCNTL_VFSNAME]] -** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of -** all [VFSes] in the VFS stack. The names are of all VFS shims and the -** final bottom-level VFS are written into memory obtained from -** [sqlite3_malloc()] and the result is stored in the char* variable -** that the fourth parameter of [sqlite3_file_control()] points to. -** The caller is responsible for freeing the memory when done. As with -** all file-control actions, there is no guarantee that this will actually -** do anything. Callers should initialize the char* variable to a NULL -** pointer in case this file-control is not implemented. This file-control -** is intended for diagnostic use only. -** -**
  • [[SQLITE_FCNTL_PRAGMA]] -** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] -** file control is sent to the open [sqlite3_file] object corresponding -** to the database file to which the pragma statement refers. ^The argument -** to the [SQLITE_FCNTL_PRAGMA] file control is an array of -** pointers to strings (char**) in which the second element of the array -** is the name of the pragma and the third element is the argument to the -** pragma or NULL if the pragma has no argument. ^The handler for an -** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element -** of the char** argument point to a string obtained from [sqlite3_mprintf()] -** or the equivalent and that string will become the result of the pragma or -** the error message if the pragma fails. ^If the -** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal -** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] -** file control returns [SQLITE_OK], then the parser assumes that the -** VFS has handled the PRAGMA itself and the parser generates a no-op -** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns -** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means -** that the VFS encountered an error while handling the [PRAGMA] and the -** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] -** file control occurs at the beginning of pragma statement analysis and so -** it is able to override built-in [PRAGMA] statements. -** -**
  • [[SQLITE_FCNTL_BUSYHANDLER]] -** ^The [SQLITE_FCNTL_BUSYHANDLER] -** file-control may be invoked by SQLite on the database file handle -** shortly after it is opened in order to provide a custom VFS with access -** to the connections busy-handler callback. The argument is of type (void **) -** - an array of two (void *) values. The first (void *) actually points -** to a function of type (int (*)(void *)). In order to invoke the connections -** busy-handler, this function should be invoked with the second (void *) in -** the array as the only argument. If it returns non-zero, then the operation -** should be retried. If it returns zero, the custom VFS should abandon the -** current operation. -** -**
  • [[SQLITE_FCNTL_TEMPFILENAME]] -** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control -** to have SQLite generate a -** temporary filename using the same algorithm that is followed to generate -** temporary filenames for TEMP tables and other internal uses. The -** argument should be a char** which will be filled with the filename -** written into memory obtained from [sqlite3_malloc()]. The caller should -** invoke [sqlite3_free()] on the result to avoid a memory leak. -** -**
  • [[SQLITE_FCNTL_MMAP_SIZE]] -** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the -** maximum number of bytes that will be used for memory-mapped I/O. -** The argument is a pointer to a value of type sqlite3_int64 that -** is an advisory maximum number of bytes in the file to memory map. The -** pointer is overwritten with the old value. The limit is not changed if -** the value originally pointed to is negative, and so the current limit -** can be queried by passing in a pointer to a negative number. This -** file-control is used internally to implement [PRAGMA mmap_size]. -** -**
-*/ -#define SQLITE_FCNTL_LOCKSTATE 1 -#define SQLITE_GET_LOCKPROXYFILE 2 -#define SQLITE_SET_LOCKPROXYFILE 3 -#define SQLITE_LAST_ERRNO 4 -#define SQLITE_FCNTL_SIZE_HINT 5 -#define SQLITE_FCNTL_CHUNK_SIZE 6 -#define SQLITE_FCNTL_FILE_POINTER 7 -#define SQLITE_FCNTL_SYNC_OMITTED 8 -#define SQLITE_FCNTL_WIN32_AV_RETRY 9 -#define SQLITE_FCNTL_PERSIST_WAL 10 -#define SQLITE_FCNTL_OVERWRITE 11 -#define SQLITE_FCNTL_VFSNAME 12 -#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 -#define SQLITE_FCNTL_PRAGMA 14 -#define SQLITE_FCNTL_BUSYHANDLER 15 -#define SQLITE_FCNTL_TEMPFILENAME 16 -#define SQLITE_FCNTL_MMAP_SIZE 18 - -/* -** CAPI3REF: Mutex Handle -** -** The mutex module within SQLite defines [sqlite3_mutex] to be an -** abstract type for a mutex object. The SQLite core never looks -** at the internal representation of an [sqlite3_mutex]. It only -** deals with pointers to the [sqlite3_mutex] object. -** -** Mutexes are created using [sqlite3_mutex_alloc()]. -*/ -typedef struct sqlite3_mutex sqlite3_mutex; - -/* -** CAPI3REF: OS Interface Object -** -** An instance of the sqlite3_vfs object defines the interface between -** the SQLite core and the underlying operating system. The "vfs" -** in the name of the object stands for "virtual file system". See -** the [VFS | VFS documentation] for further information. -** -** The value of the iVersion field is initially 1 but may be larger in -** future versions of SQLite. Additional fields may be appended to this -** object when the iVersion value is increased. Note that the structure -** of the sqlite3_vfs object changes in the transaction between -** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not -** modified. -** -** The szOsFile field is the size of the subclassed [sqlite3_file] -** structure used by this VFS. mxPathname is the maximum length of -** a pathname in this VFS. -** -** Registered sqlite3_vfs objects are kept on a linked list formed by -** the pNext pointer. The [sqlite3_vfs_register()] -** and [sqlite3_vfs_unregister()] interfaces manage this list -** in a thread-safe way. The [sqlite3_vfs_find()] interface -** searches the list. Neither the application code nor the VFS -** implementation should use the pNext pointer. -** -** The pNext field is the only field in the sqlite3_vfs -** structure that SQLite will ever modify. SQLite will only access -** or modify this field while holding a particular static mutex. -** The application should never modify anything within the sqlite3_vfs -** object once the object has been registered. -** -** The zName field holds the name of the VFS module. The name must -** be unique across all VFS modules. -** -** [[sqlite3_vfs.xOpen]] -** ^SQLite guarantees that the zFilename parameter to xOpen -** is either a NULL pointer or string obtained -** from xFullPathname() with an optional suffix added. -** ^If a suffix is added to the zFilename parameter, it will -** consist of a single "-" character followed by no more than -** 11 alphanumeric and/or "-" characters. -** ^SQLite further guarantees that -** the string will be valid and unchanged until xClose() is -** called. Because of the previous sentence, -** the [sqlite3_file] can safely store a pointer to the -** filename if it needs to remember the filename for some reason. -** If the zFilename parameter to xOpen is a NULL pointer then xOpen -** must invent its own temporary name for the file. ^Whenever the -** xFilename parameter is NULL it will also be the case that the -** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. -** -** The flags argument to xOpen() includes all bits set in -** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] -** or [sqlite3_open16()] is used, then flags includes at least -** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. -** If xOpen() opens a file read-only then it sets *pOutFlags to -** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. -** -** ^(SQLite will also add one of the following flags to the xOpen() -** call, depending on the object being opened: -** -**
    -**
  • [SQLITE_OPEN_MAIN_DB] -**
  • [SQLITE_OPEN_MAIN_JOURNAL] -**
  • [SQLITE_OPEN_TEMP_DB] -**
  • [SQLITE_OPEN_TEMP_JOURNAL] -**
  • [SQLITE_OPEN_TRANSIENT_DB] -**
  • [SQLITE_OPEN_SUBJOURNAL] -**
  • [SQLITE_OPEN_MASTER_JOURNAL] -**
  • [SQLITE_OPEN_WAL] -**
)^ -** -** The file I/O implementation can use the object type flags to -** change the way it deals with files. For example, an application -** that does not care about crash recovery or rollback might make -** the open of a journal file a no-op. Writes to this journal would -** also be no-ops, and any attempt to read the journal would return -** SQLITE_IOERR. Or the implementation might recognize that a database -** file will be doing page-aligned sector reads and writes in a random -** order and set up its I/O subsystem accordingly. -** -** SQLite might also add one of the following flags to the xOpen method: -** -**
    -**
  • [SQLITE_OPEN_DELETEONCLOSE] -**
  • [SQLITE_OPEN_EXCLUSIVE] -**
-** -** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be -** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] -** will be set for TEMP databases and their journals, transient -** databases, and subjournals. -** -** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction -** with the [SQLITE_OPEN_CREATE] flag, which are both directly -** analogous to the O_EXCL and O_CREAT flags of the POSIX open() -** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the -** SQLITE_OPEN_CREATE, is used to indicate that file should always -** be created, and that it is an error if it already exists. -** It is not used to indicate the file should be opened -** for exclusive access. -** -** ^At least szOsFile bytes of memory are allocated by SQLite -** to hold the [sqlite3_file] structure passed as the third -** argument to xOpen. The xOpen method does not have to -** allocate the structure; it should just fill it in. Note that -** the xOpen method must set the sqlite3_file.pMethods to either -** a valid [sqlite3_io_methods] object or to NULL. xOpen must do -** this even if the open fails. SQLite expects that the sqlite3_file.pMethods -** element will be valid after xOpen returns regardless of the success -** or failure of the xOpen call. -** -** [[sqlite3_vfs.xAccess]] -** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] -** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to -** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] -** to test whether a file is at least readable. The file can be a -** directory. -** -** ^SQLite will always allocate at least mxPathname+1 bytes for the -** output buffer xFullPathname. The exact size of the output buffer -** is also passed as a parameter to both methods. If the output buffer -** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is -** handled as a fatal error by SQLite, vfs implementations should endeavor -** to prevent this by setting mxPathname to a sufficiently large value. -** -** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() -** interfaces are not strictly a part of the filesystem, but they are -** included in the VFS structure for completeness. -** The xRandomness() function attempts to return nBytes bytes -** of good-quality randomness into zOut. The return value is -** the actual number of bytes of randomness obtained. -** The xSleep() method causes the calling thread to sleep for at -** least the number of microseconds given. ^The xCurrentTime() -** method returns a Julian Day Number for the current date and time as -** a floating point value. -** ^The xCurrentTimeInt64() method returns, as an integer, the Julian -** Day Number multiplied by 86400000 (the number of milliseconds in -** a 24-hour day). -** ^SQLite will use the xCurrentTimeInt64() method to get the current -** date and time if that method is available (if iVersion is 2 or -** greater and the function pointer is not NULL) and will fall back -** to xCurrentTime() if xCurrentTimeInt64() is unavailable. -** -** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces -** are not used by the SQLite core. These optional interfaces are provided -** by some VFSes to facilitate testing of the VFS code. By overriding -** system calls with functions under its control, a test program can -** simulate faults and error conditions that would otherwise be difficult -** or impossible to induce. The set of system calls that can be overridden -** varies from one VFS to another, and from one version of the same VFS to the -** next. Applications that use these interfaces must be prepared for any -** or all of these interfaces to be NULL or for their behavior to change -** from one release to the next. Applications must not attempt to access -** any of these methods if the iVersion of the VFS is less than 3. -*/ -typedef struct sqlite3_vfs sqlite3_vfs; -typedef void (*sqlite3_syscall_ptr)(void); -struct sqlite3_vfs { - int iVersion; /* Structure version number (currently 3) */ - int szOsFile; /* Size of subclassed sqlite3_file */ - int mxPathname; /* Maximum file pathname length */ - sqlite3_vfs *pNext; /* Next registered VFS */ - const char *zName; /* Name of this virtual file system */ - void *pAppData; /* Pointer to application-specific data */ - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - int (*xGetLastError)(sqlite3_vfs*, int, char *); - /* - ** The methods above are in version 1 of the sqlite_vfs object - ** definition. Those that follow are added in version 2 or later - */ - int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); - /* - ** The methods above are in versions 1 and 2 of the sqlite_vfs object. - ** Those below are for version 3 and greater. - */ - int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); - sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); - const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); - /* - ** The methods above are in versions 1 through 3 of the sqlite_vfs object. - ** New fields may be appended in figure versions. The iVersion - ** value will increment whenever this happens. - */ -}; - -/* -** CAPI3REF: Flags for the xAccess VFS method -** -** These integer constants can be used as the third parameter to -** the xAccess method of an [sqlite3_vfs] object. They determine -** what kind of permissions the xAccess method is looking for. -** With SQLITE_ACCESS_EXISTS, the xAccess method -** simply checks whether the file exists. -** With SQLITE_ACCESS_READWRITE, the xAccess method -** checks whether the named directory is both readable and writable -** (in other words, if files can be added, removed, and renamed within -** the directory). -** The SQLITE_ACCESS_READWRITE constant is currently used only by the -** [temp_store_directory pragma], though this could change in a future -** release of SQLite. -** With SQLITE_ACCESS_READ, the xAccess method -** checks whether the file is readable. The SQLITE_ACCESS_READ constant is -** currently unused, though it might be used in a future release of -** SQLite. -*/ -#define SQLITE_ACCESS_EXISTS 0 -#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ -#define SQLITE_ACCESS_READ 2 /* Unused */ - -/* -** CAPI3REF: Flags for the xShmLock VFS method -** -** These integer constants define the various locking operations -** allowed by the xShmLock method of [sqlite3_io_methods]. The -** following are the only legal combinations of flags to the -** xShmLock method: -** -**
    -**
  • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED -**
  • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE -**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED -**
  • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE -**
-** -** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as -** was given no the corresponding lock. -** -** The xShmLock method can transition between unlocked and SHARED or -** between unlocked and EXCLUSIVE. It cannot transition between SHARED -** and EXCLUSIVE. -*/ -#define SQLITE_SHM_UNLOCK 1 -#define SQLITE_SHM_LOCK 2 -#define SQLITE_SHM_SHARED 4 -#define SQLITE_SHM_EXCLUSIVE 8 - -/* -** CAPI3REF: Maximum xShmLock index -** -** The xShmLock method on [sqlite3_io_methods] may use values -** between 0 and this upper bound as its "offset" argument. -** The SQLite core will never attempt to acquire or release a -** lock outside of this range -*/ -#define SQLITE_SHM_NLOCK 8 - - -/* -** CAPI3REF: Initialize The SQLite Library -** -** ^The sqlite3_initialize() routine initializes the -** SQLite library. ^The sqlite3_shutdown() routine -** deallocates any resources that were allocated by sqlite3_initialize(). -** These routines are designed to aid in process initialization and -** shutdown on embedded systems. Workstation applications using -** SQLite normally do not need to invoke either of these routines. -** -** A call to sqlite3_initialize() is an "effective" call if it is -** the first time sqlite3_initialize() is invoked during the lifetime of -** the process, or if it is the first time sqlite3_initialize() is invoked -** following a call to sqlite3_shutdown(). ^(Only an effective call -** of sqlite3_initialize() does any initialization. All other calls -** are harmless no-ops.)^ -** -** A call to sqlite3_shutdown() is an "effective" call if it is the first -** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only -** an effective call to sqlite3_shutdown() does any deinitialization. -** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^ -** -** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown() -** is not. The sqlite3_shutdown() interface must only be called from a -** single thread. All open [database connections] must be closed and all -** other SQLite resources must be deallocated prior to invoking -** sqlite3_shutdown(). -** -** Among other things, ^sqlite3_initialize() will invoke -** sqlite3_os_init(). Similarly, ^sqlite3_shutdown() -** will invoke sqlite3_os_end(). -** -** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success. -** ^If for some reason, sqlite3_initialize() is unable to initialize -** the library (perhaps it is unable to allocate a needed resource such -** as a mutex) it returns an [error code] other than [SQLITE_OK]. -** -** ^The sqlite3_initialize() routine is called internally by many other -** SQLite interfaces so that an application usually does not need to -** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] -** calls sqlite3_initialize() so the SQLite library will be automatically -** initialized when [sqlite3_open()] is called if it has not be initialized -** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] -** compile-time option, then the automatic calls to sqlite3_initialize() -** are omitted and the application must call sqlite3_initialize() directly -** prior to using any other SQLite interface. For maximum portability, -** it is recommended that applications always invoke sqlite3_initialize() -** directly prior to using any other SQLite interface. Future releases -** of SQLite may require this. In other words, the behavior exhibited -** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the -** default behavior in some future release of SQLite. -** -** The sqlite3_os_init() routine does operating-system specific -** initialization of the SQLite library. The sqlite3_os_end() -** routine undoes the effect of sqlite3_os_init(). Typical tasks -** performed by these routines include allocation or deallocation -** of static resources, initialization of global variables, -** setting up a default [sqlite3_vfs] module, or setting up -** a default configuration using [sqlite3_config()]. -** -** The application should never invoke either sqlite3_os_init() -** or sqlite3_os_end() directly. The application should only invoke -** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() -** interface is called automatically by sqlite3_initialize() and -** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate -** implementations for sqlite3_os_init() and sqlite3_os_end() -** are built into SQLite when it is compiled for Unix, Windows, or OS/2. -** When [custom builds | built for other platforms] -** (using the [SQLITE_OS_OTHER=1] compile-time -** option) the application must supply a suitable implementation for -** sqlite3_os_init() and sqlite3_os_end(). An application-supplied -** implementation of sqlite3_os_init() or sqlite3_os_end() -** must return [SQLITE_OK] on success and some other [error code] upon -** failure. -*/ -SQLITE_API int sqlite3_initialize(void); -SQLITE_API int sqlite3_shutdown(void); -SQLITE_API int sqlite3_os_init(void); -SQLITE_API int sqlite3_os_end(void); - -/* -** CAPI3REF: Configuring The SQLite Library -** -** The sqlite3_config() interface is used to make global configuration -** changes to SQLite in order to tune SQLite to the specific needs of -** the application. The default configuration is recommended for most -** applications and so this routine is usually not necessary. It is -** provided to support rare applications with unusual needs. -** -** The sqlite3_config() interface is not threadsafe. The application -** must insure that no other SQLite interfaces are invoked by other -** threads while sqlite3_config() is running. Furthermore, sqlite3_config() -** may only be invoked prior to library initialization using -** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. -** ^If sqlite3_config() is called after [sqlite3_initialize()] and before -** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. -** Note, however, that ^sqlite3_config() can be called as part of the -** implementation of an application-defined [sqlite3_os_init()]. -** -** The first argument to sqlite3_config() is an integer -** [configuration option] that determines -** what property of SQLite is to be configured. Subsequent arguments -** vary depending on the [configuration option] -** in the first argument. -** -** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. -** ^If the option is unknown or SQLite is unable to set the option -** then this routine returns a non-zero [error code]. -*/ -SQLITE_API int sqlite3_config(int, ...); - -/* -** CAPI3REF: Configure database connections -** -** The sqlite3_db_config() interface is used to make configuration -** changes to a [database connection]. The interface is similar to -** [sqlite3_config()] except that the changes apply to a single -** [database connection] (specified in the first argument). -** -** The second argument to sqlite3_db_config(D,V,...) is the -** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code -** that indicates what aspect of the [database connection] is being configured. -** Subsequent arguments vary depending on the configuration verb. -** -** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if -** the call is considered successful. -*/ -SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); - -/* -** CAPI3REF: Memory Allocation Routines -** -** An instance of this object defines the interface between SQLite -** and low-level memory allocation routines. -** -** This object is used in only one place in the SQLite interface. -** A pointer to an instance of this object is the argument to -** [sqlite3_config()] when the configuration option is -** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. -** By creating an instance of this object -** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) -** during configuration, an application can specify an alternative -** memory allocation subsystem for SQLite to use for all of its -** dynamic memory needs. -** -** Note that SQLite comes with several [built-in memory allocators] -** that are perfectly adequate for the overwhelming majority of applications -** and that this object is only useful to a tiny minority of applications -** with specialized memory allocation requirements. This object is -** also used during testing of SQLite in order to specify an alternative -** memory allocator that simulates memory out-of-memory conditions in -** order to verify that SQLite recovers gracefully from such -** conditions. -** -** The xMalloc, xRealloc, and xFree methods must work like the -** malloc(), realloc() and free() functions from the standard C library. -** ^SQLite guarantees that the second argument to -** xRealloc is always a value returned by a prior call to xRoundup. -** -** xSize should return the allocated size of a memory allocation -** previously obtained from xMalloc or xRealloc. The allocated size -** is always at least as big as the requested size but may be larger. -** -** The xRoundup method returns what would be the allocated size of -** a memory allocation given a particular requested size. Most memory -** allocators round up memory allocations at least to the next multiple -** of 8. Some allocators round up to a larger multiple or to a power of 2. -** Every memory allocation request coming in through [sqlite3_malloc()] -** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, -** that causes the corresponding memory allocation to fail. -** -** The xInit method initializes the memory allocator. (For example, -** it might allocate any require mutexes or initialize internal data -** structures. The xShutdown method is invoked (indirectly) by -** [sqlite3_shutdown()] and should deallocate any resources acquired -** by xInit. The pAppData pointer is used as the only parameter to -** xInit and xShutdown. -** -** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes -** the xInit method, so the xInit method need not be threadsafe. The -** xShutdown method is only called from [sqlite3_shutdown()] so it does -** not need to be threadsafe either. For all other methods, SQLite -** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the -** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which -** it is by default) and so the methods are automatically serialized. -** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other -** methods must be threadsafe or else make their own arrangements for -** serialization. -** -** SQLite will never invoke xInit() more than once without an intervening -** call to xShutdown(). -*/ -typedef struct sqlite3_mem_methods sqlite3_mem_methods; -struct sqlite3_mem_methods { - void *(*xMalloc)(int); /* Memory allocation function */ - void (*xFree)(void*); /* Free a prior allocation */ - void *(*xRealloc)(void*,int); /* Resize an allocation */ - int (*xSize)(void*); /* Return the size of an allocation */ - int (*xRoundup)(int); /* Round up request size to allocation size */ - int (*xInit)(void*); /* Initialize the memory allocator */ - void (*xShutdown)(void*); /* Deinitialize the memory allocator */ - void *pAppData; /* Argument to xInit() and xShutdown() */ -}; - -/* -** CAPI3REF: Configuration Options -** KEYWORDS: {configuration option} -** -** These constants are the available integer configuration options that -** can be passed as the first argument to the [sqlite3_config()] interface. -** -** New configuration options may be added in future releases of SQLite. -** Existing configuration options might be discontinued. Applications -** should check the return code from [sqlite3_config()] to make sure that -** the call worked. The [sqlite3_config()] interface will return a -** non-zero [error code] if a discontinued or unsupported configuration option -** is invoked. -** -**
-** [[SQLITE_CONFIG_SINGLETHREAD]]
SQLITE_CONFIG_SINGLETHREAD
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Single-thread. In other words, it disables -** all mutexing and puts SQLite into a mode where it can only be used -** by a single thread. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to change the [threading mode] from its default -** value of Single-thread and so [sqlite3_config()] will return -** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD -** configuration option.
-** -** [[SQLITE_CONFIG_MULTITHREAD]]
SQLITE_CONFIG_MULTITHREAD
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Multi-thread. In other words, it disables -** mutexing on [database connection] and [prepared statement] objects. -** The application is responsible for serializing access to -** [database connections] and [prepared statements]. But other mutexes -** are enabled so that SQLite will be safe to use in a multi-threaded -** environment as long as no two threads attempt to use the same -** [database connection] at the same time. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to set the Multi-thread [threading mode] and -** [sqlite3_config()] will return [SQLITE_ERROR] if called with the -** SQLITE_CONFIG_MULTITHREAD configuration option.
-** -** [[SQLITE_CONFIG_SERIALIZED]]
SQLITE_CONFIG_SERIALIZED
-**
There are no arguments to this option. ^This option sets the -** [threading mode] to Serialized. In other words, this option enables -** all mutexes including the recursive -** mutexes on [database connection] and [prepared statement] objects. -** In this mode (which is the default when SQLite is compiled with -** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access -** to [database connections] and [prepared statements] so that the -** application is free to use the same [database connection] or the -** same [prepared statement] in different threads at the same time. -** ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** it is not possible to set the Serialized [threading mode] and -** [sqlite3_config()] will return [SQLITE_ERROR] if called with the -** SQLITE_CONFIG_SERIALIZED configuration option.
-** -** [[SQLITE_CONFIG_MALLOC]]
SQLITE_CONFIG_MALLOC
-**
^(This option takes a single argument which is a pointer to an -** instance of the [sqlite3_mem_methods] structure. The argument specifies -** alternative low-level memory allocation routines to be used in place of -** the memory allocation routines built into SQLite.)^ ^SQLite makes -** its own private copy of the content of the [sqlite3_mem_methods] structure -** before the [sqlite3_config()] call returns.
-** -** [[SQLITE_CONFIG_GETMALLOC]]
SQLITE_CONFIG_GETMALLOC
-**
^(This option takes a single argument which is a pointer to an -** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods] -** structure is filled with the currently defined memory allocation routines.)^ -** This option can be used to overload the default memory allocation -** routines with a wrapper that simulations memory allocation failure or -** tracks memory usage, for example.
-** -** [[SQLITE_CONFIG_MEMSTATUS]]
SQLITE_CONFIG_MEMSTATUS
-**
^This option takes single argument of type int, interpreted as a -** boolean, which enables or disables the collection of memory allocation -** statistics. ^(When memory allocation statistics are disabled, the -** following SQLite interfaces become non-operational: -**
    -**
  • [sqlite3_memory_used()] -**
  • [sqlite3_memory_highwater()] -**
  • [sqlite3_soft_heap_limit64()] -**
  • [sqlite3_status()] -**
)^ -** ^Memory allocation statistics are enabled by default unless SQLite is -** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory -** allocation statistics are disabled by default. -**
-** -** [[SQLITE_CONFIG_SCRATCH]]
SQLITE_CONFIG_SCRATCH
-**
^This option specifies a static memory buffer that SQLite can use for -** scratch memory. There are three arguments: A pointer an 8-byte -** aligned memory buffer from which the scratch allocations will be -** drawn, the size of each scratch allocation (sz), -** and the maximum number of scratch allocations (N). The sz -** argument must be a multiple of 16. -** The first argument must be a pointer to an 8-byte aligned buffer -** of at least sz*N bytes of memory. -** ^SQLite will use no more than two scratch buffers per thread. So -** N should be set to twice the expected maximum number of threads. -** ^SQLite will never require a scratch buffer that is more than 6 -** times the database page size. ^If SQLite needs needs additional -** scratch memory beyond what is provided by this configuration option, then -** [sqlite3_malloc()] will be used to obtain the memory needed.
-** -** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
-**
^This option specifies a static memory buffer that SQLite can use for -** the database page cache with the default page cache implementation. -** This configuration should not be used if an application-define page -** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option. -** There are three arguments to this option: A pointer to 8-byte aligned -** memory, the size of each page buffer (sz), and the number of pages (N). -** The sz argument should be the size of the largest database page -** (a power of two between 512 and 32768) plus a little extra for each -** page header. ^The page header size is 20 to 40 bytes depending on -** the host architecture. ^It is harmless, apart from the wasted memory, -** to make sz a little too large. The first -** argument should point to an allocation of at least sz*N bytes of memory. -** ^SQLite will use the memory provided by the first argument to satisfy its -** memory needs for the first N pages that it adds to cache. ^If additional -** page cache memory is needed beyond what is provided by this option, then -** SQLite goes to [sqlite3_malloc()] for the additional storage space. -** The pointer in the first argument must -** be aligned to an 8-byte boundary or subsequent behavior of SQLite -** will be undefined.
-** -** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
-**
^This option specifies a static memory buffer that SQLite will use -** for all of its dynamic memory allocation needs beyond those provided -** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. -** There are three arguments: An 8-byte aligned pointer to the memory, -** the number of bytes in the memory buffer, and the minimum allocation size. -** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts -** to using its default memory allocator (the system malloc() implementation), -** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the -** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or -** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory -** allocator is engaged to handle all of SQLites memory allocation needs. -** The first pointer (the memory pointer) must be aligned to an 8-byte -** boundary or subsequent behavior of SQLite will be undefined. -** The minimum allocation size is capped at 2**12. Reasonable values -** for the minimum allocation size are 2**5 through 2**8.
-** -** [[SQLITE_CONFIG_MUTEX]]
SQLITE_CONFIG_MUTEX
-**
^(This option takes a single argument which is a pointer to an -** instance of the [sqlite3_mutex_methods] structure. The argument specifies -** alternative low-level mutex routines to be used in place -** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the -** content of the [sqlite3_mutex_methods] structure before the call to -** [sqlite3_config()] returns. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** the entire mutexing subsystem is omitted from the build and hence calls to -** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will -** return [SQLITE_ERROR].
-** -** [[SQLITE_CONFIG_GETMUTEX]]
SQLITE_CONFIG_GETMUTEX
-**
^(This option takes a single argument which is a pointer to an -** instance of the [sqlite3_mutex_methods] structure. The -** [sqlite3_mutex_methods] -** structure is filled with the currently defined mutex routines.)^ -** This option can be used to overload the default mutex allocation -** routines with a wrapper used to track mutex usage for performance -** profiling or testing, for example. ^If SQLite is compiled with -** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then -** the entire mutexing subsystem is omitted from the build and hence calls to -** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will -** return [SQLITE_ERROR].
-** -** [[SQLITE_CONFIG_LOOKASIDE]]
SQLITE_CONFIG_LOOKASIDE
-**
^(This option takes two arguments that determine the default -** memory allocation for the lookaside memory allocator on each -** [database connection]. The first argument is the -** size of each lookaside buffer slot and the second is the number of -** slots allocated to each database connection.)^ ^(This option sets the -** default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] -** verb to [sqlite3_db_config()] can be used to change the lookaside -** configuration on individual connections.)^
-** -** [[SQLITE_CONFIG_PCACHE2]]
SQLITE_CONFIG_PCACHE2
-**
^(This option takes a single argument which is a pointer to -** an [sqlite3_pcache_methods2] object. This object specifies the interface -** to a custom page cache implementation.)^ ^SQLite makes a copy of the -** object and uses it for page cache memory allocations.
-** -** [[SQLITE_CONFIG_GETPCACHE2]]
SQLITE_CONFIG_GETPCACHE2
-**
^(This option takes a single argument which is a pointer to an -** [sqlite3_pcache_methods2] object. SQLite copies of the current -** page cache implementation into that object.)^
-** -** [[SQLITE_CONFIG_LOG]]
SQLITE_CONFIG_LOG
-**
The SQLITE_CONFIG_LOG option is used to configure the SQLite -** global [error log]. -** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a -** function with a call signature of void(*)(void*,int,const char*), -** and a pointer to void. ^If the function pointer is not NULL, it is -** invoked by [sqlite3_log()] to process each logging event. ^If the -** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. -** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is -** passed through as the first parameter to the application-defined logger -** function whenever that function is invoked. ^The second parameter to -** the logger function is a copy of the first parameter to the corresponding -** [sqlite3_log()] call and is intended to be a [result code] or an -** [extended result code]. ^The third parameter passed to the logger is -** log message after formatting via [sqlite3_snprintf()]. -** The SQLite logging interface is not reentrant; the logger function -** supplied by the application must not invoke any SQLite interface. -** In a multi-threaded application, the application-defined logger -** function must be threadsafe.
-** -** [[SQLITE_CONFIG_URI]]
SQLITE_CONFIG_URI -**
This option takes a single argument of type int. If non-zero, then -** URI handling is globally enabled. If the parameter is zero, then URI handling -** is globally disabled. If URI handling is globally enabled, all filenames -** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or -** specified as part of [ATTACH] commands are interpreted as URIs, regardless -** of whether or not the [SQLITE_OPEN_URI] flag is set when the database -** connection is opened. If it is globally disabled, filenames are -** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the -** database connection is opened. By default, URI handling is globally -** disabled. The default value may be changed by compiling with the -** [SQLITE_USE_URI] symbol defined. -** -** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]
SQLITE_CONFIG_COVERING_INDEX_SCAN -**
This option takes a single integer argument which is interpreted as -** a boolean in order to enable or disable the use of covering indices for -** full table scans in the query optimizer. The default setting is determined -** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" -** if that compile-time option is omitted. -** The ability to disable the use of covering indices for full table scans -** is because some incorrectly coded legacy applications might malfunction -** malfunction when the optimization is enabled. Providing the ability to -** disable the optimization allows the older, buggy application code to work -** without change even with newer versions of SQLite. -** -** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] -**
SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE -**
These options are obsolete and should not be used by new code. -** They are retained for backwards compatibility but are now no-ops. -**
-** -** [[SQLITE_CONFIG_SQLLOG]] -**
SQLITE_CONFIG_SQLLOG -**
This option is only available if sqlite is compiled with the -** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should -** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). -** The second should be of type (void*). The callback is invoked by the library -** in three separate circumstances, identified by the value passed as the -** fourth parameter. If the fourth parameter is 0, then the database connection -** passed as the second argument has just been opened. The third argument -** points to a buffer containing the name of the main database file. If the -** fourth parameter is 1, then the SQL statement that the third parameter -** points to has just been executed. Or, if the fourth parameter is 2, then -** the connection being passed as the second parameter is being closed. The -** third parameter is passed NULL In this case. An example of using this -** configuration option can be seen in the "test_sqllog.c" source file in -** the canonical SQLite source tree.
-** -** [[SQLITE_CONFIG_MMAP_SIZE]] -**
SQLITE_CONFIG_MMAP_SIZE -**
SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values -** that are the default mmap size limit (the default setting for -** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. -** The default setting can be overridden by each database connection using -** either the [PRAGMA mmap_size] command, or by using the -** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size -** cannot be changed at run-time. Nor may the maximum allowed mmap size -** exceed the compile-time maximum mmap size set by the -** [SQLITE_MAX_MMAP_SIZE] compile-time option. -** If either argument to this option is negative, then that argument is -** changed to its compile-time default. -**
-*/ -#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ -#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ -#define SQLITE_CONFIG_SERIALIZED 3 /* nil */ -#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ -#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ -#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ -#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ -#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ -#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ -#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ -#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ -/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ -#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ -#define SQLITE_CONFIG_PCACHE 14 /* no-op */ -#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ -#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ -#define SQLITE_CONFIG_URI 17 /* int */ -#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ -#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ -#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ -#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ -#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ - -/* -** CAPI3REF: Database Connection Configuration Options -** -** These constants are the available integer configuration options that -** can be passed as the second argument to the [sqlite3_db_config()] interface. -** -** New configuration options may be added in future releases of SQLite. -** Existing configuration options might be discontinued. Applications -** should check the return code from [sqlite3_db_config()] to make sure that -** the call worked. ^The [sqlite3_db_config()] interface will return a -** non-zero [error code] if a discontinued or unsupported configuration option -** is invoked. -** -**
-**
SQLITE_DBCONFIG_LOOKASIDE
-**
^This option takes three additional arguments that determine the -** [lookaside memory allocator] configuration for the [database connection]. -** ^The first argument (the third parameter to [sqlite3_db_config()] is a -** pointer to a memory buffer to use for lookaside memory. -** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb -** may be NULL in which case SQLite will allocate the -** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the -** size of each lookaside buffer slot. ^The third argument is the number of -** slots. The size of the buffer in the first argument must be greater than -** or equal to the product of the second and third arguments. The buffer -** must be aligned to an 8-byte boundary. ^If the second argument to -** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally -** rounded down to the next smaller multiple of 8. ^(The lookaside memory -** configuration for a database connection can only be changed when that -** connection is not currently using lookaside memory, or in other words -** when the "current value" returned by -** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. -** Any attempt to change the lookaside memory configuration when lookaside -** memory is in use leaves the configuration unchanged and returns -** [SQLITE_BUSY].)^
-** -**
SQLITE_DBCONFIG_ENABLE_FKEY
-**
^This option is used to enable or disable the enforcement of -** [foreign key constraints]. There should be two additional arguments. -** The first argument is an integer which is 0 to disable FK enforcement, -** positive to enable FK enforcement or negative to leave FK enforcement -** unchanged. The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether FK enforcement is off or on -** following this call. The second parameter may be a NULL pointer, in -** which case the FK enforcement setting is not reported back.
-** -**
SQLITE_DBCONFIG_ENABLE_TRIGGER
-**
^This option is used to enable or disable [CREATE TRIGGER | triggers]. -** There should be two additional arguments. -** The first argument is an integer which is 0 to disable triggers, -** positive to enable triggers or negative to leave the setting unchanged. -** The second parameter is a pointer to an integer into which -** is written 0 or 1 to indicate whether triggers are disabled or enabled -** following this call. The second parameter may be a NULL pointer, in -** which case the trigger setting is not reported back.
-** -**
-*/ -#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ -#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ -#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ - - -/* -** CAPI3REF: Enable Or Disable Extended Result Codes -** -** ^The sqlite3_extended_result_codes() routine enables or disables the -** [extended result codes] feature of SQLite. ^The extended result -** codes are disabled by default for historical compatibility. -*/ -SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); - -/* -** CAPI3REF: Last Insert Rowid -** -** ^Each entry in an SQLite table has a unique 64-bit signed -** integer key called the [ROWID | "rowid"]. ^The rowid is always available -** as an undeclared column named ROWID, OID, or _ROWID_ as long as those -** names are not also used by explicitly declared columns. ^If -** the table has a column of type [INTEGER PRIMARY KEY] then that column -** is another alias for the rowid. -** -** ^This routine returns the [rowid] of the most recent -** successful [INSERT] into the database from the [database connection] -** in the first argument. ^As of SQLite version 3.7.7, this routines -** records the last insert rowid of both ordinary tables and [virtual tables]. -** ^If no successful [INSERT]s -** have ever occurred on that database connection, zero is returned. -** -** ^(If an [INSERT] occurs within a trigger or within a [virtual table] -** method, then this routine will return the [rowid] of the inserted -** row as long as the trigger or virtual table method is running. -** But once the trigger or virtual table method ends, the value returned -** by this routine reverts to what it was before the trigger or virtual -** table method began.)^ -** -** ^An [INSERT] that fails due to a constraint violation is not a -** successful [INSERT] and does not change the value returned by this -** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, -** and INSERT OR ABORT make no changes to the return value of this -** routine when their insertion fails. ^(When INSERT OR REPLACE -** encounters a constraint violation, it does not fail. The -** INSERT continues to completion after deleting rows that caused -** the constraint problem so INSERT OR REPLACE will always change -** the return value of this interface.)^ -** -** ^For the purposes of this routine, an [INSERT] is considered to -** be successful even if it is subsequently rolled back. -** -** This function is accessible to SQL statements via the -** [last_insert_rowid() SQL function]. -** -** If a separate thread performs a new [INSERT] on the same -** database connection while the [sqlite3_last_insert_rowid()] -** function is running and thus changes the last insert [rowid], -** then the value returned by [sqlite3_last_insert_rowid()] is -** unpredictable and might not equal either the old or the new -** last insert [rowid]. -*/ -SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); - -/* -** CAPI3REF: Count The Number Of Rows Modified -** -** ^This function returns the number of database rows that were changed -** or inserted or deleted by the most recently completed SQL statement -** on the [database connection] specified by the first parameter. -** ^(Only changes that are directly specified by the [INSERT], [UPDATE], -** or [DELETE] statement are counted. Auxiliary changes caused by -** triggers or [foreign key actions] are not counted.)^ Use the -** [sqlite3_total_changes()] function to find the total number of changes -** including changes caused by triggers and foreign key actions. -** -** ^Changes to a view that are simulated by an [INSTEAD OF trigger] -** are not counted. Only real table changes are counted. -** -** ^(A "row change" is a change to a single row of a single table -** caused by an INSERT, DELETE, or UPDATE statement. Rows that -** are changed as side effects of [REPLACE] constraint resolution, -** rollback, ABORT processing, [DROP TABLE], or by any other -** mechanisms do not count as direct row changes.)^ -** -** A "trigger context" is a scope of execution that begins and -** ends with the script of a [CREATE TRIGGER | trigger]. -** Most SQL statements are -** evaluated outside of any trigger. This is the "top level" -** trigger context. If a trigger fires from the top level, a -** new trigger context is entered for the duration of that one -** trigger. Subtriggers create subcontexts for their duration. -** -** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does -** not create a new trigger context. -** -** ^This function returns the number of direct row changes in the -** most recent INSERT, UPDATE, or DELETE statement within the same -** trigger context. -** -** ^Thus, when called from the top level, this function returns the -** number of changes in the most recent INSERT, UPDATE, or DELETE -** that also occurred at the top level. ^(Within the body of a trigger, -** the sqlite3_changes() interface can be called to find the number of -** changes in the most recently completed INSERT, UPDATE, or DELETE -** statement within the body of the same trigger. -** However, the number returned does not include changes -** caused by subtriggers since those have their own context.)^ -** -** See also the [sqlite3_total_changes()] interface, the -** [count_changes pragma], and the [changes() SQL function]. -** -** If a separate thread makes changes on the same database connection -** while [sqlite3_changes()] is running then the value returned -** is unpredictable and not meaningful. -*/ -SQLITE_API int sqlite3_changes(sqlite3*); - -/* -** CAPI3REF: Total Number Of Rows Modified -** -** ^This function returns the number of row changes caused by [INSERT], -** [UPDATE] or [DELETE] statements since the [database connection] was opened. -** ^(The count returned by sqlite3_total_changes() includes all changes -** from all [CREATE TRIGGER | trigger] contexts and changes made by -** [foreign key actions]. However, -** the count does not include changes used to implement [REPLACE] constraints, -** do rollbacks or ABORT processing, or [DROP TABLE] processing. The -** count does not include rows of views that fire an [INSTEAD OF trigger], -** though if the INSTEAD OF trigger makes changes of its own, those changes -** are counted.)^ -** ^The sqlite3_total_changes() function counts the changes as soon as -** the statement that makes them is completed (when the statement handle -** is passed to [sqlite3_reset()] or [sqlite3_finalize()]). -** -** See also the [sqlite3_changes()] interface, the -** [count_changes pragma], and the [total_changes() SQL function]. -** -** If a separate thread makes changes on the same database connection -** while [sqlite3_total_changes()] is running then the value -** returned is unpredictable and not meaningful. -*/ -SQLITE_API int sqlite3_total_changes(sqlite3*); - -/* -** CAPI3REF: Interrupt A Long-Running Query -** -** ^This function causes any pending database operation to abort and -** return at its earliest opportunity. This routine is typically -** called in response to a user action such as pressing "Cancel" -** or Ctrl-C where the user wants a long query operation to halt -** immediately. -** -** ^It is safe to call this routine from a thread different from the -** thread that is currently running the database operation. But it -** is not safe to call this routine with a [database connection] that -** is closed or might close before sqlite3_interrupt() returns. -** -** ^If an SQL operation is very nearly finished at the time when -** sqlite3_interrupt() is called, then it might not have an opportunity -** to be interrupted and might continue to completion. -** -** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. -** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE -** that is inside an explicit transaction, then the entire transaction -** will be rolled back automatically. -** -** ^The sqlite3_interrupt(D) call is in effect until all currently running -** SQL statements on [database connection] D complete. ^Any new SQL statements -** that are started after the sqlite3_interrupt() call and before the -** running statements reaches zero are interrupted as if they had been -** running prior to the sqlite3_interrupt() call. ^New SQL statements -** that are started after the running statement count reaches zero are -** not effected by the sqlite3_interrupt(). -** ^A call to sqlite3_interrupt(D) that occurs when there are no running -** SQL statements is a no-op and has no effect on SQL statements -** that are started after the sqlite3_interrupt() call returns. -** -** If the database connection closes while [sqlite3_interrupt()] -** is running then bad things will likely happen. -*/ -SQLITE_API void sqlite3_interrupt(sqlite3*); - -/* -** CAPI3REF: Determine If An SQL Statement Is Complete -** -** These routines are useful during command-line input to determine if the -** currently entered text seems to form a complete SQL statement or -** if additional input is needed before sending the text into -** SQLite for parsing. ^These routines return 1 if the input string -** appears to be a complete SQL statement. ^A statement is judged to be -** complete if it ends with a semicolon token and is not a prefix of a -** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within -** string literals or quoted identifier names or comments are not -** independent tokens (they are part of the token in which they are -** embedded) and thus do not count as a statement terminator. ^Whitespace -** and comments that follow the final semicolon are ignored. -** -** ^These routines return 0 if the statement is incomplete. ^If a -** memory allocation fails, then SQLITE_NOMEM is returned. -** -** ^These routines do not parse the SQL statements thus -** will not detect syntactically incorrect SQL. -** -** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior -** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked -** automatically by sqlite3_complete16(). If that initialization fails, -** then the return value from sqlite3_complete16() will be non-zero -** regardless of whether or not the input SQL is complete.)^ -** -** The input to [sqlite3_complete()] must be a zero-terminated -** UTF-8 string. -** -** The input to [sqlite3_complete16()] must be a zero-terminated -** UTF-16 string in native byte order. -*/ -SQLITE_API int sqlite3_complete(const char *sql); -SQLITE_API int sqlite3_complete16(const void *sql); - -/* -** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors -** -** ^This routine sets a callback function that might be invoked whenever -** an attempt is made to open a database table that another thread -** or process has locked. -** -** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] -** is returned immediately upon encountering the lock. ^If the busy callback -** is not NULL, then the callback might be invoked with two arguments. -** -** ^The first argument to the busy handler is a copy of the void* pointer which -** is the third argument to sqlite3_busy_handler(). ^The second argument to -** the busy handler callback is the number of times that the busy handler has -** been invoked for this locking event. ^If the -** busy callback returns 0, then no additional attempts are made to -** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. -** ^If the callback returns non-zero, then another attempt -** is made to open the database for reading and the cycle repeats. -** -** The presence of a busy handler does not guarantee that it will be invoked -** when there is lock contention. ^If SQLite determines that invoking the busy -** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] -** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler. -** Consider a scenario where one process is holding a read lock that -** it is trying to promote to a reserved lock and -** a second process is holding a reserved lock that it is trying -** to promote to an exclusive lock. The first process cannot proceed -** because it is blocked by the second and the second process cannot -** proceed because it is blocked by the first. If both processes -** invoke the busy handlers, neither will make any progress. Therefore, -** SQLite returns [SQLITE_BUSY] for the first process, hoping that this -** will induce the first process to release its read lock and allow -** the second process to proceed. -** -** ^The default busy callback is NULL. -** -** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] -** when SQLite is in the middle of a large transaction where all the -** changes will not fit into the in-memory cache. SQLite will -** already hold a RESERVED lock on the database file, but it needs -** to promote this lock to EXCLUSIVE so that it can spill cache -** pages into the database file without harm to concurrent -** readers. ^If it is unable to promote the lock, then the in-memory -** cache will be left in an inconsistent state and so the error -** code is promoted from the relatively benign [SQLITE_BUSY] to -** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion -** forces an automatic rollback of the changes. See the -** -** CorruptionFollowingBusyError wiki page for a discussion of why -** this is important. -** -** ^(There can only be a single busy handler defined for each -** [database connection]. Setting a new busy handler clears any -** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] -** will also set or clear the busy handler. -** -** The busy callback should not take any actions which modify the -** database connection that invoked the busy handler. Any such actions -** result in undefined behavior. -** -** A busy handler must not close the database connection -** or [prepared statement] that invoked the busy handler. -*/ -SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); - -/* -** CAPI3REF: Set A Busy Timeout -** -** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps -** for a specified amount of time when a table is locked. ^The handler -** will sleep multiple times until at least "ms" milliseconds of sleeping -** have accumulated. ^After at least "ms" milliseconds of sleeping, -** the handler returns 0 which causes [sqlite3_step()] to return -** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. -** -** ^Calling this routine with an argument less than or equal to zero -** turns off all busy handlers. -** -** ^(There can only be a single busy handler for a particular -** [database connection] any any given moment. If another busy handler -** was defined (using [sqlite3_busy_handler()]) prior to calling -** this routine, that other busy handler is cleared.)^ -*/ -SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); - -/* -** CAPI3REF: Convenience Routines For Running Queries -** -** This is a legacy interface that is preserved for backwards compatibility. -** Use of this interface is not recommended. -** -** Definition: A result table is memory data structure created by the -** [sqlite3_get_table()] interface. A result table records the -** complete query results from one or more queries. -** -** The table conceptually has a number of rows and columns. But -** these numbers are not part of the result table itself. These -** numbers are obtained separately. Let N be the number of rows -** and M be the number of columns. -** -** A result table is an array of pointers to zero-terminated UTF-8 strings. -** There are (N+1)*M elements in the array. The first M pointers point -** to zero-terminated strings that contain the names of the columns. -** The remaining entries all point to query results. NULL values result -** in NULL pointers. All other values are in their UTF-8 zero-terminated -** string representation as returned by [sqlite3_column_text()]. -** -** A result table might consist of one or more memory allocations. -** It is not safe to pass a result table directly to [sqlite3_free()]. -** A result table should be deallocated using [sqlite3_free_table()]. -** -** ^(As an example of the result table format, suppose a query result -** is as follows: -** -**
-**        Name        | Age
-**        -----------------------
-**        Alice       | 43
-**        Bob         | 28
-**        Cindy       | 21
-** 
-** -** There are two column (M==2) and three rows (N==3). Thus the -** result table has 8 entries. Suppose the result table is stored -** in an array names azResult. Then azResult holds this content: -** -**
-**        azResult[0] = "Name";
-**        azResult[1] = "Age";
-**        azResult[2] = "Alice";
-**        azResult[3] = "43";
-**        azResult[4] = "Bob";
-**        azResult[5] = "28";
-**        azResult[6] = "Cindy";
-**        azResult[7] = "21";
-** 
)^ -** -** ^The sqlite3_get_table() function evaluates one or more -** semicolon-separated SQL statements in the zero-terminated UTF-8 -** string of its 2nd parameter and returns a result table to the -** pointer given in its 3rd parameter. -** -** After the application has finished with the result from sqlite3_get_table(), -** it must pass the result table pointer to sqlite3_free_table() in order to -** release the memory that was malloced. Because of the way the -** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling -** function must not try to call [sqlite3_free()] directly. Only -** [sqlite3_free_table()] is able to release the memory properly and safely. -** -** The sqlite3_get_table() interface is implemented as a wrapper around -** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access -** to any internal data structures of SQLite. It uses only the public -** interface defined here. As a consequence, errors that occur in the -** wrapper layer outside of the internal [sqlite3_exec()] call are not -** reflected in subsequent calls to [sqlite3_errcode()] or -** [sqlite3_errmsg()]. -*/ -SQLITE_API int sqlite3_get_table( - sqlite3 *db, /* An open database */ - const char *zSql, /* SQL to be evaluated */ - char ***pazResult, /* Results of the query */ - int *pnRow, /* Number of result rows written here */ - int *pnColumn, /* Number of result columns written here */ - char **pzErrmsg /* Error msg written here */ -); -SQLITE_API void sqlite3_free_table(char **result); - -/* -** CAPI3REF: Formatted String Printing Functions -** -** These routines are work-alikes of the "printf()" family of functions -** from the standard C library. -** -** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. -** The strings returned by these two routines should be -** released by [sqlite3_free()]. ^Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough -** memory to hold the resulting string. -** -** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from -** the standard C library. The result is written into the -** buffer supplied as the second parameter whose size is given by -** the first parameter. Note that the order of the -** first two parameters is reversed from snprintf().)^ This is an -** historical accident that cannot be fixed without breaking -** backwards compatibility. ^(Note also that sqlite3_snprintf() -** returns a pointer to its buffer instead of the number of -** characters actually written into the buffer.)^ We admit that -** the number of characters written would be a more useful return -** value but we cannot change the implementation of sqlite3_snprintf() -** now without breaking compatibility. -** -** ^As long as the buffer size is greater than zero, sqlite3_snprintf() -** guarantees that the buffer is always zero-terminated. ^The first -** parameter "n" is the total size of the buffer, including space for -** the zero terminator. So the longest string that can be completely -** written will be n-1 characters. -** -** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). -** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. -** -** ^(The %q option works like %s in that it substitutes a nul-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal.)^ By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, assume the string variable zText contains text as follows: -** -**
-**  char *zText = "It's a happy day!";
-** 
-** -** One can use this text in an SQL statement as follows: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
-**  INSERT INTO table1 VALUES('It''s a happy day!')
-** 
-** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
-**  INSERT INTO table1 VALUES('It's a happy day!');
-** 
-** -** This second example is an SQL syntax error. As a general rule you should -** always use %q instead of %s when inserting text into a string literal. -** -** ^(The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Additionally, if the parameter in the -** argument list is a NULL pointer, %Q substitutes the text "NULL" (without -** single quotes).)^ So, for example, one could say: -** -**
-**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
-**  sqlite3_exec(db, zSQL, 0, 0, 0);
-**  sqlite3_free(zSQL);
-** 
-** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** ^(The "%z" formatting option works like "%s" but with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string.)^ -*/ -SQLITE_API char *sqlite3_mprintf(const char*,...); -SQLITE_API char *sqlite3_vmprintf(const char*, va_list); -SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); -SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); - -/* -** CAPI3REF: Memory Allocation Subsystem -** -** The SQLite core uses these three routines for all of its own -** internal memory allocation needs. "Core" in the previous sentence -** does not include operating-system specific VFS implementation. The -** Windows VFS uses native malloc() and free() for some operations. -** -** ^The sqlite3_malloc() routine returns a pointer to a block -** of memory at least N bytes in length, where N is the parameter. -** ^If sqlite3_malloc() is unable to obtain sufficient free -** memory, it returns a NULL pointer. ^If the parameter N to -** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns -** a NULL pointer. -** -** ^Calling sqlite3_free() with a pointer previously returned -** by sqlite3_malloc() or sqlite3_realloc() releases that memory so -** that it might be reused. ^The sqlite3_free() routine is -** a no-op if is called with a NULL pointer. Passing a NULL pointer -** to sqlite3_free() is harmless. After being freed, memory -** should neither be read nor written. Even reading previously freed -** memory might result in a segmentation fault or other severe error. -** Memory corruption, a segmentation fault, or other severe error -** might result if sqlite3_free() is called with a non-NULL pointer that -** was not obtained from sqlite3_malloc() or sqlite3_realloc(). -** -** ^(The sqlite3_realloc() interface attempts to resize a -** prior memory allocation to be at least N bytes, where N is the -** second parameter. The memory allocation to be resized is the first -** parameter.)^ ^ If the first parameter to sqlite3_realloc() -** is a NULL pointer then its behavior is identical to calling -** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). -** ^If the second parameter to sqlite3_realloc() is zero or -** negative then the behavior is exactly the same as calling -** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). -** ^sqlite3_realloc() returns a pointer to a memory allocation -** of at least N bytes in size or NULL if sufficient memory is unavailable. -** ^If M is the size of the prior allocation, then min(N,M) bytes -** of the prior allocation are copied into the beginning of buffer returned -** by sqlite3_realloc() and the prior allocation is freed. -** ^If sqlite3_realloc() returns NULL, then the prior allocation -** is not freed. -** -** ^The memory returned by sqlite3_malloc() and sqlite3_realloc() -** is always aligned to at least an 8 byte boundary, or to a -** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time -** option is used. -** -** In SQLite version 3.5.0 and 3.5.1, it was possible to define -** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in -** implementation of these routines to be omitted. That capability -** is no longer provided. Only built-in memory allocators can be used. -** -** Prior to SQLite version 3.7.10, the Windows OS interface layer called -** the system malloc() and free() directly when converting -** filenames between the UTF-8 encoding used by SQLite -** and whatever filename encoding is used by the particular Windows -** installation. Memory allocation errors were detected, but -** they were reported back as [SQLITE_CANTOPEN] or -** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. -** -** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] -** must be either NULL or else pointers obtained from a prior -** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have -** not yet been released. -** -** The application must not read or write any part of -** a block of memory after it has been released using -** [sqlite3_free()] or [sqlite3_realloc()]. -*/ -SQLITE_API void *sqlite3_malloc(int); -SQLITE_API void *sqlite3_realloc(void*, int); -SQLITE_API void sqlite3_free(void*); - -/* -** CAPI3REF: Memory Allocator Statistics -** -** SQLite provides these two interfaces for reporting on the status -** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] -** routines, which form the built-in memory allocation subsystem. -** -** ^The [sqlite3_memory_used()] routine returns the number of bytes -** of memory currently outstanding (malloced but not freed). -** ^The [sqlite3_memory_highwater()] routine returns the maximum -** value of [sqlite3_memory_used()] since the high-water mark -** was last reset. ^The values returned by [sqlite3_memory_used()] and -** [sqlite3_memory_highwater()] include any overhead -** added by SQLite in its implementation of [sqlite3_malloc()], -** but not overhead added by the any underlying system library -** routines that [sqlite3_malloc()] may call. -** -** ^The memory high-water mark is reset to the current value of -** [sqlite3_memory_used()] if and only if the parameter to -** [sqlite3_memory_highwater()] is true. ^The value returned -** by [sqlite3_memory_highwater(1)] is the high-water mark -** prior to the reset. -*/ -SQLITE_API sqlite3_int64 sqlite3_memory_used(void); -SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); - -/* -** CAPI3REF: Pseudo-Random Number Generator -** -** SQLite contains a high-quality pseudo-random number generator (PRNG) used to -** select random [ROWID | ROWIDs] when inserting new records into a table that -** already uses the largest possible [ROWID]. The PRNG is also used for -** the build-in random() and randomblob() SQL functions. This interface allows -** applications to access the same PRNG for other purposes. -** -** ^A call to this routine stores N bytes of randomness into buffer P. -** -** ^The first time this routine is invoked (either internally or by -** the application) the PRNG is seeded using randomness obtained -** from the xRandomness method of the default [sqlite3_vfs] object. -** ^On all subsequent invocations, the pseudo-randomness is generated -** internally and without recourse to the [sqlite3_vfs] xRandomness -** method. -*/ -SQLITE_API void sqlite3_randomness(int N, void *P); - -/* -** CAPI3REF: Compile-Time Authorization Callbacks -** -** ^This routine registers an authorizer callback with a particular -** [database connection], supplied in the first argument. -** ^The authorizer callback is invoked as SQL statements are being compiled -** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various -** points during the compilation process, as logic is being created -** to perform various actions, the authorizer callback is invoked to -** see if those actions are allowed. ^The authorizer callback should -** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the -** specific action but allow the SQL statement to continue to be -** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be -** rejected with an error. ^If the authorizer callback returns -** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] -** then the [sqlite3_prepare_v2()] or equivalent call that triggered -** the authorizer will fail with an error message. -** -** When the callback returns [SQLITE_OK], that means the operation -** requested is ok. ^When the callback returns [SQLITE_DENY], the -** [sqlite3_prepare_v2()] or equivalent call that triggered the -** authorizer will fail with an error message explaining that -** access is denied. -** -** ^The first parameter to the authorizer callback is a copy of the third -** parameter to the sqlite3_set_authorizer() interface. ^The second parameter -** to the callback is an integer [SQLITE_COPY | action code] that specifies -** the particular action to be authorized. ^The third through sixth parameters -** to the callback are zero-terminated strings that contain additional -** details about the action to be authorized. -** -** ^If the action code is [SQLITE_READ] -** and the callback returns [SQLITE_IGNORE] then the -** [prepared statement] statement is constructed to substitute -** a NULL value in place of the table column that would have -** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] -** return can be used to deny an untrusted user access to individual -** columns of a table. -** ^If the action code is [SQLITE_DELETE] and the callback returns -** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the -** [truncate optimization] is disabled and all rows are deleted individually. -** -** An authorizer is used when [sqlite3_prepare | preparing] -** SQL statements from an untrusted source, to ensure that the SQL statements -** do not try to access data they are not allowed to see, or that they do not -** try to execute malicious statements that damage the database. For -** example, an application may allow a user to enter arbitrary -** SQL queries for evaluation by a database. But the application does -** not want the user to be able to make arbitrary changes to the -** database. An authorizer could then be put in place while the -** user-entered SQL is being [sqlite3_prepare | prepared] that -** disallows everything except [SELECT] statements. -** -** Applications that need to process SQL from untrusted sources -** might also consider lowering resource limits using [sqlite3_limit()] -** and limiting database size using the [max_page_count] [PRAGMA] -** in addition to using an authorizer. -** -** ^(Only a single authorizer can be in place on a database connection -** at a time. Each call to sqlite3_set_authorizer overrides the -** previous call.)^ ^Disable the authorizer by installing a NULL callback. -** The authorizer is disabled by default. -** -** The authorizer callback must not do anything that will modify -** the database connection that invoked the authorizer callback. -** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their -** database connections for the meaning of "modify" in this paragraph. -** -** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the -** statement might be re-prepared during [sqlite3_step()] due to a -** schema change. Hence, the application should ensure that the -** correct authorizer callback remains in place during the [sqlite3_step()]. -** -** ^Note that the authorizer callback is invoked only during -** [sqlite3_prepare()] or its variants. Authorization is not -** performed during statement evaluation in [sqlite3_step()], unless -** as stated in the previous paragraph, sqlite3_step() invokes -** sqlite3_prepare_v2() to reprepare a statement after a schema change. -*/ -SQLITE_API int sqlite3_set_authorizer( - sqlite3*, - int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), - void *pUserData -); - -/* -** CAPI3REF: Authorizer Return Codes -** -** The [sqlite3_set_authorizer | authorizer callback function] must -** return either [SQLITE_OK] or one of these two constants in order -** to signal SQLite whether or not the action is permitted. See the -** [sqlite3_set_authorizer | authorizer documentation] for additional -** information. -** -** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code] -** from the [sqlite3_vtab_on_conflict()] interface. -*/ -#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ -#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ - -/* -** CAPI3REF: Authorizer Action Codes -** -** The [sqlite3_set_authorizer()] interface registers a callback function -** that is invoked to authorize certain SQL statement actions. The -** second parameter to the callback is an integer code that specifies -** what action is being authorized. These are the integer action codes that -** the authorizer callback may be passed. -** -** These action code values signify what kind of operation is to be -** authorized. The 3rd and 4th parameters to the authorization -** callback function will be parameters or NULL depending on which of these -** codes is used as the second parameter. ^(The 5th parameter to the -** authorizer callback is the name of the database ("main", "temp", -** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback -** is the name of the inner-most trigger or view that is responsible for -** the access attempt or NULL if this access attempt is directly from -** top-level SQL code. -*/ -/******************************************* 3rd ************ 4th ***********/ -#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ -#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ -#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ -#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ -#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ -#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ -#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ -#define SQLITE_DELETE 9 /* Table Name NULL */ -#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ -#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ -#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ -#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ -#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ -#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ -#define SQLITE_DROP_VIEW 17 /* View Name NULL */ -#define SQLITE_INSERT 18 /* Table Name NULL */ -#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ -#define SQLITE_READ 20 /* Table Name Column Name */ -#define SQLITE_SELECT 21 /* NULL NULL */ -#define SQLITE_TRANSACTION 22 /* Operation NULL */ -#define SQLITE_UPDATE 23 /* Table Name Column Name */ -#define SQLITE_ATTACH 24 /* Filename NULL */ -#define SQLITE_DETACH 25 /* Database Name NULL */ -#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ -#define SQLITE_REINDEX 27 /* Index Name NULL */ -#define SQLITE_ANALYZE 28 /* Table Name NULL */ -#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ -#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ -#define SQLITE_FUNCTION 31 /* NULL Function Name */ -#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ -#define SQLITE_COPY 0 /* No longer used */ - -/* -** CAPI3REF: Tracing And Profiling Functions -** -** These routines register callback functions that can be used for -** tracing and profiling the execution of SQL statements. -** -** ^The callback function registered by sqlite3_trace() is invoked at -** various times when an SQL statement is being run by [sqlite3_step()]. -** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the -** SQL statement text as the statement first begins executing. -** ^(Additional sqlite3_trace() callbacks might occur -** as each triggered subprogram is entered. The callbacks for triggers -** contain a UTF-8 SQL comment that identifies the trigger.)^ -** -** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit -** the length of [bound parameter] expansion in the output of sqlite3_trace(). -** -** ^The callback function registered by sqlite3_profile() is invoked -** as each SQL statement finishes. ^The profile callback contains -** the original statement text and an estimate of wall-clock time -** of how long that statement took to run. ^The profile callback -** time is in units of nanoseconds, however the current implementation -** is only capable of millisecond resolution so the six least significant -** digits in the time are meaningless. Future versions of SQLite -** might provide greater resolution on the profiler callback. The -** sqlite3_profile() function is considered experimental and is -** subject to change in future versions of SQLite. -*/ -SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); -SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, - void(*xProfile)(void*,const char*,sqlite3_uint64), void*); - -/* -** CAPI3REF: Query Progress Callbacks -** -** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback -** function X to be invoked periodically during long running calls to -** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for -** database connection D. An example use for this -** interface is to keep a GUI updated during a large query. -** -** ^The parameter P is passed through as the only parameter to the -** callback function X. ^The parameter N is the number of -** [virtual machine instructions] that are evaluated between successive -** invocations of the callback X. -** -** ^Only a single progress handler may be defined at one time per -** [database connection]; setting a new progress handler cancels the -** old one. ^Setting parameter X to NULL disables the progress handler. -** ^The progress handler is also disabled by setting N to a value less -** than 1. -** -** ^If the progress callback returns non-zero, the operation is -** interrupted. This feature can be used to implement a -** "Cancel" button on a GUI progress dialog box. -** -** The progress handler callback must not do anything that will modify -** the database connection that invoked the progress handler. -** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their -** database connections for the meaning of "modify" in this paragraph. -** -*/ -SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); - -/* -** CAPI3REF: Opening A New Database Connection -** -** ^These routines open an SQLite database file as specified by the -** filename argument. ^The filename argument is interpreted as UTF-8 for -** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte -** order for sqlite3_open16(). ^(A [database connection] handle is usually -** returned in *ppDb, even if an error occurs. The only exception is that -** if SQLite is unable to allocate memory to hold the [sqlite3] object, -** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] -** object.)^ ^(If the database is opened (and/or created) successfully, then -** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The -** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain -** an English language description of the error following a failure of any -** of the sqlite3_open() routines. -** -** ^The default encoding for the database will be UTF-8 if -** sqlite3_open() or sqlite3_open_v2() is called and -** UTF-16 in the native byte order if sqlite3_open16() is used. -** -** Whether or not an error occurs when it is opened, resources -** associated with the [database connection] handle should be released by -** passing it to [sqlite3_close()] when it is no longer required. -** -** The sqlite3_open_v2() interface works like sqlite3_open() -** except that it accepts two additional parameters for additional control -** over the new database connection. ^(The flags parameter to -** sqlite3_open_v2() can take one of -** the following three values, optionally combined with the -** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], -** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ -** -**
-** ^(
[SQLITE_OPEN_READONLY]
-**
The database is opened in read-only mode. If the database does not -** already exist, an error is returned.
)^ -** -** ^(
[SQLITE_OPEN_READWRITE]
-**
The database is opened for reading and writing if possible, or reading -** only if the file is write protected by the operating system. In either -** case the database must already exist, otherwise an error is returned.
)^ -** -** ^(
[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
-**
The database is opened for reading and writing, and is created if -** it does not already exist. This is the behavior that is always used for -** sqlite3_open() and sqlite3_open16().
)^ -**
-** -** If the 3rd parameter to sqlite3_open_v2() is not one of the -** combinations shown above optionally combined with other -** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] -** then the behavior is undefined. -** -** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection -** opens in the multi-thread [threading mode] as long as the single-thread -** mode has not been set at compile-time or start-time. ^If the -** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens -** in the serialized [threading mode] unless single-thread was -** previously selected at compile-time or start-time. -** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be -** eligible to use [shared cache mode], regardless of whether or not shared -** cache is enabled using [sqlite3_enable_shared_cache()]. ^The -** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not -** participate in [shared cache mode] even if it is enabled. -** -** ^The fourth parameter to sqlite3_open_v2() is the name of the -** [sqlite3_vfs] object that defines the operating system interface that -** the new database connection should use. ^If the fourth parameter is -** a NULL pointer then the default [sqlite3_vfs] object is used. -** -** ^If the filename is ":memory:", then a private, temporary in-memory database -** is created for the connection. ^This in-memory database will vanish when -** the database connection is closed. Future versions of SQLite might -** make use of additional special filenames that begin with the ":" character. -** It is recommended that when a database filename actually does begin with -** a ":" character you should prefix the filename with a pathname such as -** "./" to avoid ambiguity. -** -** ^If the filename is an empty string, then a private, temporary -** on-disk database will be created. ^This private database will be -** automatically deleted as soon as the database connection is closed. -** -** [[URI filenames in sqlite3_open()]]

URI Filenames

-** -** ^If [URI filename] interpretation is enabled, and the filename argument -** begins with "file:", then the filename is interpreted as a URI. ^URI -** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is -** set in the fourth argument to sqlite3_open_v2(), or if it has -** been enabled globally using the [SQLITE_CONFIG_URI] option with the -** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. -** As of SQLite version 3.7.7, URI filename interpretation is turned off -** by default, but future releases of SQLite might enable URI filename -** interpretation by default. See "[URI filenames]" for additional -** information. -** -** URI filenames are parsed according to RFC 3986. ^If the URI contains an -** authority, then it must be either an empty string or the string -** "localhost". ^If the authority is not an empty string or "localhost", an -** error is returned to the caller. ^The fragment component of a URI, if -** present, is ignored. -** -** ^SQLite uses the path component of the URI as the name of the disk file -** which contains the database. ^If the path begins with a '/' character, -** then it is interpreted as an absolute path. ^If the path does not begin -** with a '/' (meaning that the authority section is omitted from the URI) -** then the path is interpreted as a relative path. -** ^On windows, the first component of an absolute path -** is a drive specification (e.g. "C:"). -** -** [[core URI query parameters]] -** The query component of a URI may contain parameters that are interpreted -** either by SQLite itself, or by a [VFS | custom VFS implementation]. -** SQLite interprets the following three query parameters: -** -**
    -**
  • vfs: ^The "vfs" parameter may be used to specify the name of -** a VFS object that provides the operating system interface that should -** be used to access the database file on disk. ^If this option is set to -** an empty string the default VFS object is used. ^Specifying an unknown -** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is -** present, then the VFS specified by the option takes precedence over -** the value passed as the fourth parameter to sqlite3_open_v2(). -** -**
  • mode: ^(The mode parameter may be set to either "ro", "rw", -** "rwc", or "memory". Attempting to set it to any other value is -** an error)^. -** ^If "ro" is specified, then the database is opened for read-only -** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the -** third argument to sqlite3_open_v2(). ^If the mode option is set to -** "rw", then the database is opened for read-write (but not create) -** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had -** been set. ^Value "rwc" is equivalent to setting both -** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is -** set to "memory" then a pure [in-memory database] that never reads -** or writes from disk is used. ^It is an error to specify a value for -** the mode parameter that is less restrictive than that specified by -** the flags passed in the third parameter to sqlite3_open_v2(). -** -**
  • cache: ^The cache parameter may be set to either "shared" or -** "private". ^Setting it to "shared" is equivalent to setting the -** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to -** sqlite3_open_v2(). ^Setting the cache parameter to "private" is -** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. -** ^If sqlite3_open_v2() is used and the "cache" parameter is present in -** a URI filename, its value overrides any behavior requested by setting -** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. -**
-** -** ^Specifying an unknown parameter in the query component of a URI is not an -** error. Future versions of SQLite might understand additional query -** parameters. See "[query parameters with special meaning to SQLite]" for -** additional information. -** -** [[URI filename examples]]

URI filename examples

-** -**
-**
URI filenames Results -**
file:data.db -** Open the file "data.db" in the current directory. -**
file:/home/fred/data.db
-** file:///home/fred/data.db
-** file://localhost/home/fred/data.db
-** Open the database file "/home/fred/data.db". -**
file://darkstar/home/fred/data.db -** An error. "darkstar" is not a recognized authority. -**
-** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db -** Windows only: Open the file "data.db" on fred's desktop on drive -** C:. Note that the %20 escaping in this example is not strictly -** necessary - space characters can be used literally -** in URI filenames. -**
file:data.db?mode=ro&cache=private -** Open file "data.db" in the current directory for read-only access. -** Regardless of whether or not shared-cache mode is enabled by -** default, use a private cache. -**
file:/home/fred/data.db?vfs=unix-nolock -** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". -**
file:data.db?mode=readonly -** An error. "readonly" is not a valid option for the "mode" parameter. -**
-** -** ^URI hexadecimal escape sequences (%HH) are supported within the path and -** query components of a URI. A hexadecimal escape sequence consists of a -** percent sign - "%" - followed by exactly two hexadecimal digits -** specifying an octet value. ^Before the path or query components of a -** URI filename are interpreted, they are encoded using UTF-8 and all -** hexadecimal escape sequences replaced by a single byte containing the -** corresponding octet. If this process generates an invalid UTF-8 encoding, -** the results are undefined. -** -** Note to Windows users: The encoding used for the filename argument -** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever -** codepage is currently defined. Filenames containing international -** characters must be converted to UTF-8 prior to passing them into -** sqlite3_open() or sqlite3_open_v2(). -** -** Note to Windows Runtime users: The temporary directory must be set -** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various -** features that require the use of temporary files may fail. -** -** See also: [sqlite3_temp_directory] -*/ -SQLITE_API int sqlite3_open( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -SQLITE_API int sqlite3_open16( - const void *filename, /* Database filename (UTF-16) */ - sqlite3 **ppDb /* OUT: SQLite db handle */ -); -SQLITE_API int sqlite3_open_v2( - const char *filename, /* Database filename (UTF-8) */ - sqlite3 **ppDb, /* OUT: SQLite db handle */ - int flags, /* Flags */ - const char *zVfs /* Name of VFS module to use */ -); - -/* -** CAPI3REF: Obtain Values For URI Parameters -** -** These are utility routines, useful to VFS implementations, that check -** to see if a database file was a URI that contained a specific query -** parameter, and if so obtains the value of that query parameter. -** -** If F is the database filename pointer passed into the xOpen() method of -** a VFS implementation when the flags parameter to xOpen() has one or -** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and -** P is the name of the query parameter, then -** sqlite3_uri_parameter(F,P) returns the value of the P -** parameter if it exists or a NULL pointer if P does not appear as a -** query parameter on F. If P is a query parameter of F -** has no explicit value, then sqlite3_uri_parameter(F,P) returns -** a pointer to an empty string. -** -** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean -** parameter and returns true (1) or false (0) according to the value -** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the -** value of query parameter P is one of "yes", "true", or "on" in any -** case or if the value begins with a non-zero number. The -** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of -** query parameter P is one of "no", "false", or "off" in any case or -** if the value begins with a numeric zero. If P is not a query -** parameter on F or if the value of P is does not match any of the -** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). -** -** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a -** 64-bit signed integer and returns that integer, or D if P does not -** exist. If the value of P is something other than an integer, then -** zero is returned. -** -** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and -** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and -** is not a database file pathname pointer that SQLite passed into the xOpen -** VFS method, then the behavior of this routine is undefined and probably -** undesirable. -*/ -SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); -SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); -SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); - - -/* -** CAPI3REF: Error Codes And Messages -** -** ^The sqlite3_errcode() interface returns the numeric [result code] or -** [extended result code] for the most recent failed sqlite3_* API call -** associated with a [database connection]. If a prior API call failed -** but the most recent API call succeeded, the return value from -** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() -** interface is the same except that it always returns the -** [extended result code] even when extended result codes are -** disabled. -** -** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language -** text that describes the error, as either UTF-8 or UTF-16 respectively. -** ^(Memory to hold the error message string is managed internally. -** The application does not need to worry about freeing the result. -** However, the error string might be overwritten or deallocated by -** subsequent calls to other SQLite interface functions.)^ -** -** ^The sqlite3_errstr() interface returns the English-language text -** that describes the [result code], as UTF-8. -** ^(Memory to hold the error message string is managed internally -** and must not be freed by the application)^. -** -** When the serialized [threading mode] is in use, it might be the -** case that a second error occurs on a separate thread in between -** the time of the first error and the call to these interfaces. -** When that happens, the second error will be reported since these -** interfaces always report the most recent result. To avoid -** this, each thread can obtain exclusive use of the [database connection] D -** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning -** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after -** all calls to the interfaces listed here are completed. -** -** If an interface fails with SQLITE_MISUSE, that means the interface -** was invoked incorrectly by the application. In that case, the -** error code and message may or may not be set. -*/ -SQLITE_API int sqlite3_errcode(sqlite3 *db); -SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); -SQLITE_API const char *sqlite3_errmsg(sqlite3*); -SQLITE_API const void *sqlite3_errmsg16(sqlite3*); -SQLITE_API const char *sqlite3_errstr(int); - -/* -** CAPI3REF: SQL Statement Object -** KEYWORDS: {prepared statement} {prepared statements} -** -** An instance of this object represents a single SQL statement. -** This object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". -** -** The life of a statement object goes something like this: -** -**

    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to [host parameters] using the sqlite3_bind_*() -** interfaces. -**
  3. Run the SQL by calling [sqlite3_step()] one or more times. -**
  4. Reset the statement using [sqlite3_reset()] then go back -** to step 2. Do this zero or more times. -**
  5. Destroy the object using [sqlite3_finalize()]. -**
-** -** Refer to documentation on individual methods above for additional -** information. -*/ -typedef struct sqlite3_stmt sqlite3_stmt; - -/* -** CAPI3REF: Run-time Limits -** -** ^(This interface allows the size of various constructs to be limited -** on a connection by connection basis. The first parameter is the -** [database connection] whose limit is to be set or queried. The -** second parameter is one of the [limit categories] that define a -** class of constructs to be size limited. The third parameter is the -** new limit for that construct.)^ -** -** ^If the new limit is a negative number, the limit is unchanged. -** ^(For each limit category SQLITE_LIMIT_NAME there is a -** [limits | hard upper bound] -** set at compile-time by a C preprocessor macro called -** [limits | SQLITE_MAX_NAME]. -** (The "_LIMIT_" in the name is changed to "_MAX_".))^ -** ^Attempts to increase a limit above its hard upper bound are -** silently truncated to the hard upper bound. -** -** ^Regardless of whether or not the limit was changed, the -** [sqlite3_limit()] interface returns the prior value of the limit. -** ^Hence, to find the current value of a limit without changing it, -** simply invoke this interface with the third parameter set to -1. -** -** Run-time limits are intended for use in applications that manage -** both their own internal database and also databases that are controlled -** by untrusted external sources. An example application might be a -** web browser that has its own databases for storing history and -** separate databases controlled by JavaScript applications downloaded -** off the Internet. The internal databases can be given the -** large, default limits. Databases managed by external sources can -** be given much smaller limits designed to prevent a denial of service -** attack. Developers might also want to use the [sqlite3_set_authorizer()] -** interface to further control untrusted SQL. The size of the database -** created by an untrusted script can be contained using the -** [max_page_count] [PRAGMA]. -** -** New run-time limit categories may be added in future releases. -*/ -SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); - -/* -** CAPI3REF: Run-Time Limit Categories -** KEYWORDS: {limit category} {*limit categories} -** -** These constants define various performance limits -** that can be lowered at run-time using [sqlite3_limit()]. -** The synopsis of the meanings of the various limits is shown below. -** Additional information is available at [limits | Limits in SQLite]. -** -**
-** [[SQLITE_LIMIT_LENGTH]] ^(
SQLITE_LIMIT_LENGTH
-**
The maximum size of any string or BLOB or table row, in bytes.
)^ -** -** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
SQLITE_LIMIT_SQL_LENGTH
-**
The maximum length of an SQL statement, in bytes.
)^ -** -** [[SQLITE_LIMIT_COLUMN]] ^(
SQLITE_LIMIT_COLUMN
-**
The maximum number of columns in a table definition or in the -** result set of a [SELECT] or the maximum number of columns in an index -** or in an ORDER BY or GROUP BY clause.
)^ -** -** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
-**
The maximum depth of the parse tree on any expression.
)^ -** -** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
SQLITE_LIMIT_COMPOUND_SELECT
-**
The maximum number of terms in a compound SELECT statement.
)^ -** -** [[SQLITE_LIMIT_VDBE_OP]] ^(
SQLITE_LIMIT_VDBE_OP
-**
The maximum number of instructions in a virtual machine program -** used to implement an SQL statement. This limit is not currently -** enforced, though that might be added in some future release of -** SQLite.
)^ -** -** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
SQLITE_LIMIT_FUNCTION_ARG
-**
The maximum number of arguments on a function.
)^ -** -** [[SQLITE_LIMIT_ATTACHED]] ^(
SQLITE_LIMIT_ATTACHED
-**
The maximum number of [ATTACH | attached databases].)^
-** -** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] -** ^(
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
-**
The maximum length of the pattern argument to the [LIKE] or -** [GLOB] operators.
)^ -** -** [[SQLITE_LIMIT_VARIABLE_NUMBER]] -** ^(
SQLITE_LIMIT_VARIABLE_NUMBER
-**
The maximum index number of any [parameter] in an SQL statement.)^ -** -** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
SQLITE_LIMIT_TRIGGER_DEPTH
-**
The maximum depth of recursion for triggers.
)^ -**
-*/ -#define SQLITE_LIMIT_LENGTH 0 -#define SQLITE_LIMIT_SQL_LENGTH 1 -#define SQLITE_LIMIT_COLUMN 2 -#define SQLITE_LIMIT_EXPR_DEPTH 3 -#define SQLITE_LIMIT_COMPOUND_SELECT 4 -#define SQLITE_LIMIT_VDBE_OP 5 -#define SQLITE_LIMIT_FUNCTION_ARG 6 -#define SQLITE_LIMIT_ATTACHED 7 -#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 -#define SQLITE_LIMIT_VARIABLE_NUMBER 9 -#define SQLITE_LIMIT_TRIGGER_DEPTH 10 - -/* -** CAPI3REF: Compiling An SQL Statement -** KEYWORDS: {SQL statement compiler} -** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. -** -** The first argument, "db", is a [database connection] obtained from a -** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or -** [sqlite3_open16()]. The database connection must not have been closed. -** -** The second argument, "zSql", is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. -** -** ^If the nByte argument is less than zero, then zSql is read up to the -** first zero terminator. ^If nByte is non-negative, then it is the maximum -** number of bytes read from zSql. ^When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** the nByte-th byte, whichever comes first. If the caller knows -** that the supplied string is nul-terminated, then there is a small -** performance advantage to be gained by passing an nByte parameter that -** is equal to the number of bytes in the input string including -** the nul-terminator bytes as this saves SQLite from having to -** make a copy of the input string. -** -** ^If pzTail is not NULL then *pzTail is made to point to the first byte -** past the end of the first SQL statement in zSql. These routines only -** compile the first statement in zSql, so *pzTail is left pointing to -** what remains uncompiled. -** -** ^*ppStmt is left pointing to a compiled [prepared statement] that can be -** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set -** to NULL. ^If the input text contains no SQL (if the input is an empty -** string or a comment) then *ppStmt is set to NULL. -** The calling procedure is responsible for deleting the compiled -** SQL statement using [sqlite3_finalize()] after it has finished with it. -** ppStmt may not be NULL. -** -** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; -** otherwise an [error code] is returned. -** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** ^In the "v2" interfaces, the prepared statement -** that is returned (the [sqlite3_stmt] object) contains a copy of the -** original SQL text. This causes the [sqlite3_step()] interface to -** behave differently in three ways: -** -**
    -**
  1. -** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it -** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY] -** retries will occur before sqlite3_step() gives up and returns an error. -**
  2. -** -**
  3. -** ^When an error occurs, [sqlite3_step()] will return one of the detailed -** [error codes] or [extended error codes]. ^The legacy behavior was that -** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code -** and the application would have to make a second call to [sqlite3_reset()] -** in order to find the underlying cause of the problem. With the "v2" prepare -** interfaces, the underlying reason for the error is returned immediately. -**
  4. -** -**
  5. -** ^If the specific value bound to [parameter | host parameter] in the -** WHERE clause might influence the choice of query plan for a statement, -** then the statement will be automatically recompiled, as if there had been -** a schema change, on the first [sqlite3_step()] call following any change -** to the [sqlite3_bind_text | bindings] of that [parameter]. -** ^The specific value of WHERE-clause [parameter] might influence the -** choice of query plan if the parameter is the left-hand side of a [LIKE] -** or [GLOB] operator or if the parameter is compared to an indexed column -** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. -** the -**
  6. -**
-*/ -SQLITE_API int sqlite3_prepare( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -SQLITE_API int sqlite3_prepare_v2( - sqlite3 *db, /* Database handle */ - const char *zSql, /* SQL statement, UTF-8 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail /* OUT: Pointer to unused portion of zSql */ -); -SQLITE_API int sqlite3_prepare16( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); -SQLITE_API int sqlite3_prepare16_v2( - sqlite3 *db, /* Database handle */ - const void *zSql, /* SQL statement, UTF-16 encoded */ - int nByte, /* Maximum length of zSql in bytes. */ - sqlite3_stmt **ppStmt, /* OUT: Statement handle */ - const void **pzTail /* OUT: Pointer to unused portion of zSql */ -); - -/* -** CAPI3REF: Retrieving Statement SQL -** -** ^This interface can be used to retrieve a saved copy of the original -** SQL text used to create a [prepared statement] if that statement was -** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. -*/ -SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Determine If An SQL Statement Writes The Database -** -** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if -** and only if the [prepared statement] X makes no direct changes to -** the content of the database file. -** -** Note that [application-defined SQL functions] or -** [virtual tables] might change the database indirectly as a side effect. -** ^(For example, if an application defines a function "eval()" that -** calls [sqlite3_exec()], then the following SQL statement would -** change the database file through side-effects: -** -**
-**    SELECT eval('DELETE FROM t1') FROM t2;
-** 
-** -** But because the [SELECT] statement does not change the database file -** directly, sqlite3_stmt_readonly() would still return true.)^ -** -** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK], -** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, -** since the statements themselves do not actually modify the database but -** rather they control the timing of when other statements modify the -** database. ^The [ATTACH] and [DETACH] statements also cause -** sqlite3_stmt_readonly() to return true since, while those statements -** change the configuration of a database connection, they do not make -** changes to the content of the database files on disk. -*/ -SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Determine If A Prepared Statement Has Been Reset -** -** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the -** [prepared statement] S has been stepped at least once using -** [sqlite3_step(S)] but has not run to completion and/or has not -** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S) -** interface returns false if S is a NULL pointer. If S is not a -** NULL pointer and is not a pointer to a valid [prepared statement] -** object, then the behavior is undefined and probably undesirable. -** -** This interface can be used in combination [sqlite3_next_stmt()] -** to locate all prepared statements associated with a database -** connection that are in need of being reset. This can be used, -** for example, in diagnostic routines to search for prepared -** statements that are holding a transaction open. -*/ -SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); - -/* -** CAPI3REF: Dynamically Typed Value Object -** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} -** -** SQLite uses the sqlite3_value object to represent all values -** that can be stored in a database table. SQLite uses dynamic typing -** for the values it stores. ^Values stored in sqlite3_value objects -** can be integers, floating point values, strings, BLOBs, or NULL. -** -** An sqlite3_value object may be either "protected" or "unprotected". -** Some interfaces require a protected sqlite3_value. Other interfaces -** will accept either a protected or an unprotected sqlite3_value. -** Every interface that accepts sqlite3_value arguments specifies -** whether or not it requires a protected sqlite3_value. -** -** The terms "protected" and "unprotected" refer to whether or not -** a mutex is held. An internal mutex is held for a protected -** sqlite3_value object but no mutex is held for an unprotected -** sqlite3_value object. If SQLite is compiled to be single-threaded -** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) -** or if SQLite is run in one of reduced mutex modes -** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] -** then there is no distinction between protected and unprotected -** sqlite3_value objects and they can be used interchangeably. However, -** for maximum code portability it is recommended that applications -** still make the distinction between protected and unprotected -** sqlite3_value objects even when not strictly required. -** -** ^The sqlite3_value objects that are passed as parameters into the -** implementation of [application-defined SQL functions] are protected. -** ^The sqlite3_value object returned by -** [sqlite3_column_value()] is unprotected. -** Unprotected sqlite3_value objects may only be used with -** [sqlite3_result_value()] and [sqlite3_bind_value()]. -** The [sqlite3_value_blob | sqlite3_value_type()] family of -** interfaces require protected sqlite3_value objects. -*/ -typedef struct Mem sqlite3_value; - -/* -** CAPI3REF: SQL Function Context Object -** -** The context in which an SQL function executes is stored in an -** sqlite3_context object. ^A pointer to an sqlite3_context object -** is always first parameter to [application-defined SQL functions]. -** The application-defined SQL function implementation will pass this -** pointer through into calls to [sqlite3_result_int | sqlite3_result()], -** [sqlite3_aggregate_context()], [sqlite3_user_data()], -** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], -** and/or [sqlite3_set_auxdata()]. -*/ -typedef struct sqlite3_context sqlite3_context; - -/* -** CAPI3REF: Binding Values To Prepared Statements -** KEYWORDS: {host parameter} {host parameters} {host parameter name} -** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} -** -** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, -** literals may be replaced by a [parameter] that matches one of following -** templates: -** -**
    -**
  • ? -**
  • ?NNN -**
  • :VVV -**
  • @VVV -**
  • $VVV -**
-** -** In the templates above, NNN represents an integer literal, -** and VVV represents an alphanumeric identifier.)^ ^The values of these -** parameters (also called "host parameter names" or "SQL parameters") -** can be set using the sqlite3_bind_*() routines defined here. -** -** ^The first argument to the sqlite3_bind_*() routines is always -** a pointer to the [sqlite3_stmt] object returned from -** [sqlite3_prepare_v2()] or its variants. -** -** ^The second argument is the index of the SQL parameter to be set. -** ^The leftmost SQL parameter has an index of 1. ^When the same named -** SQL parameter is used more than once, second and subsequent -** occurrences have the same index as the first occurrence. -** ^The index for named parameters can be looked up using the -** [sqlite3_bind_parameter_index()] API if desired. ^The index -** for "?NNN" parameters is the value of NNN. -** ^The NNN value must be between 1 and the [sqlite3_limit()] -** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). -** -** ^The third argument is the value to bind to the parameter. -** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16() -** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter -** is ignored and the end result is the same as sqlite3_bind_null(). -** -** ^(In those routines that have a fourth argument, its value is the -** number of bytes in the parameter. To be clear: the value is the -** number of bytes in the value, not the number of characters.)^ -** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() -** is negative, then the length of the string is -** the number of bytes up to the first zero terminator. -** If the fourth parameter to sqlite3_bind_blob() is negative, then -** the behavior is undefined. -** If a non-negative fourth parameter is provided to sqlite3_bind_text() -** or sqlite3_bind_text16() then that parameter must be the byte offset -** where the NUL terminator would occur assuming the string were NUL -** terminated. If any NUL characters occur at byte offsets less than -** the value of the fourth parameter then the resulting string value will -** contain embedded NULs. The result of expressions involving strings -** with embedded NULs is undefined. -** -** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and -** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or -** string after SQLite has finished with it. ^The destructor is called -** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(), -** sqlite3_bind_text(), or sqlite3_bind_text16() fails. -** ^If the fifth argument is -** the special value [SQLITE_STATIC], then SQLite assumes that the -** information is in static, unmanaged space and does not need to be freed. -** ^If the fifth argument has the value [SQLITE_TRANSIENT], then -** SQLite makes its own private copy of the data immediately, before -** the sqlite3_bind_*() routine returns. -** -** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that -** is filled with zeroes. ^A zeroblob uses a fixed amount of memory -** (just an integer to hold its size) while it is being processed. -** Zeroblobs are intended to serve as placeholders for BLOBs whose -** content is later written using -** [sqlite3_blob_open | incremental BLOB I/O] routines. -** ^A negative value for the zeroblob results in a zero-length BLOB. -** -** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer -** for the [prepared statement] or with a prepared statement for which -** [sqlite3_step()] has been called more recently than [sqlite3_reset()], -** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() -** routine is passed a [prepared statement] that has been finalized, the -** result is undefined and probably harmful. -** -** ^Bindings are not cleared by the [sqlite3_reset()] routine. -** ^Unbound parameters are interpreted as NULL. -** -** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an -** [error code] if anything goes wrong. -** ^[SQLITE_RANGE] is returned if the parameter -** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. -** -** See also: [sqlite3_bind_parameter_count()], -** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. -*/ -SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); -SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); -SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); -SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); -SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); -SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); -SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); -SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); -SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); - -/* -** CAPI3REF: Number Of SQL Parameters -** -** ^This routine can be used to find the number of [SQL parameters] -** in a [prepared statement]. SQL parameters are tokens of the -** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as -** placeholders for values that are [sqlite3_bind_blob | bound] -** to the parameters at a later time. -** -** ^(This routine actually returns the index of the largest (rightmost) -** parameter. For all forms except ?NNN, this will correspond to the -** number of unique parameters. If parameters of the ?NNN form are used, -** there may be gaps in the list.)^ -** -** See also: [sqlite3_bind_blob|sqlite3_bind()], -** [sqlite3_bind_parameter_name()], and -** [sqlite3_bind_parameter_index()]. -*/ -SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); - -/* -** CAPI3REF: Name Of A Host Parameter -** -** ^The sqlite3_bind_parameter_name(P,N) interface returns -** the name of the N-th [SQL parameter] in the [prepared statement] P. -** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" -** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" -** respectively. -** In other words, the initial ":" or "$" or "@" or "?" -** is included as part of the name.)^ -** ^Parameters of the form "?" without a following integer have no name -** and are referred to as "nameless" or "anonymous parameters". -** -** ^The first host parameter has an index of 1, not 0. -** -** ^If the value N is out of range or if the N-th parameter is -** nameless, then NULL is returned. ^The returned string is -** always in UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. -** -** See also: [sqlite3_bind_blob|sqlite3_bind()], -** [sqlite3_bind_parameter_count()], and -** [sqlite3_bind_parameter_index()]. -*/ -SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); - -/* -** CAPI3REF: Index Of A Parameter With A Given Name -** -** ^Return the index of an SQL parameter given its name. ^The -** index value returned is suitable for use as the second -** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero -** is returned if no matching parameter is found. ^The parameter -** name must be given in UTF-8 even if the original statement -** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. -** -** See also: [sqlite3_bind_blob|sqlite3_bind()], -** [sqlite3_bind_parameter_count()], and -** [sqlite3_bind_parameter_index()]. -*/ -SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); - -/* -** CAPI3REF: Reset All Bindings On A Prepared Statement -** -** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset -** the [sqlite3_bind_blob | bindings] on a [prepared statement]. -** ^Use this routine to reset all host parameters to NULL. -*/ -SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); - -/* -** CAPI3REF: Number Of Columns In A Result Set -** -** ^Return the number of columns in the result set returned by the -** [prepared statement]. ^This routine returns 0 if pStmt is an SQL -** statement that does not return data (for example an [UPDATE]). -** -** See also: [sqlite3_data_count()] -*/ -SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Column Names In A Result Set -** -** ^These routines return the name assigned to a particular column -** in the result set of a [SELECT] statement. ^The sqlite3_column_name() -** interface returns a pointer to a zero-terminated UTF-8 string -** and sqlite3_column_name16() returns a pointer to a zero-terminated -** UTF-16 string. ^The first parameter is the [prepared statement] -** that implements the [SELECT] statement. ^The second parameter is the -** column number. ^The leftmost column is number 0. -** -** ^The returned string pointer is valid until either the [prepared statement] -** is destroyed by [sqlite3_finalize()] or until the statement is automatically -** reprepared by the first call to [sqlite3_step()] for a particular run -** or until the next call to -** sqlite3_column_name() or sqlite3_column_name16() on the same column. -** -** ^If sqlite3_malloc() fails during the processing of either routine -** (for example during a conversion from UTF-8 to UTF-16) then a -** NULL pointer is returned. -** -** ^The name of a result column is the value of the "AS" clause for -** that column, if there is an AS clause. If there is no AS clause -** then the name of the column is unspecified and may change from -** one release of SQLite to the next. -*/ -SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); -SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); - -/* -** CAPI3REF: Source Of Data In A Query Result -** -** ^These routines provide a means to determine the database, table, and -** table column that is the origin of a particular result column in -** [SELECT] statement. -** ^The name of the database or table or column can be returned as -** either a UTF-8 or UTF-16 string. ^The _database_ routines return -** the database name, the _table_ routines return the table name, and -** the origin_ routines return the column name. -** ^The returned string is valid until the [prepared statement] is destroyed -** using [sqlite3_finalize()] or until the statement is automatically -** reprepared by the first call to [sqlite3_step()] for a particular run -** or until the same information is requested -** again in a different encoding. -** -** ^The names returned are the original un-aliased names of the -** database, table, and column. -** -** ^The first argument to these interfaces is a [prepared statement]. -** ^These functions return information about the Nth result column returned by -** the statement, where N is the second function argument. -** ^The left-most column is column 0 for these routines. -** -** ^If the Nth column returned by the statement is an expression or -** subquery and is not a column value, then all of these functions return -** NULL. ^These routine might also return NULL if a memory allocation error -** occurs. ^Otherwise, they return the name of the attached database, table, -** or column that query result column was extracted from. -** -** ^As with all other SQLite APIs, those whose names end with "16" return -** UTF-16 encoded strings and the other functions return UTF-8. -** -** ^These APIs are only available if the library was compiled with the -** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. -** -** If two or more threads call one or more of these routines against the same -** prepared statement and column at the same time then the results are -** undefined. -** -** If two or more threads call one or more -** [sqlite3_column_database_name | column metadata interfaces] -** for the same [prepared statement] and result column -** at the same time then the results are undefined. -*/ -SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); -SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); -SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Declared Datatype Of A Query Result -** -** ^(The first parameter is a [prepared statement]. -** If this statement is a [SELECT] statement and the Nth column of the -** returned result set of that [SELECT] is a table column (not an -** expression or subquery) then the declared type of the table -** column is returned.)^ ^If the Nth column of the result set is an -** expression or subquery, then a NULL pointer is returned. -** ^The returned string is always UTF-8 encoded. -** -** ^(For example, given the database schema: -** -** CREATE TABLE t1(c1 VARIANT); -** -** and the following statement to be compiled: -** -** SELECT c1 + 1, c1 FROM t1; -** -** this routine would return the string "VARIANT" for the second result -** column (i==1), and a NULL pointer for the first result column (i==0).)^ -** -** ^SQLite uses dynamic run-time typing. ^So just because a column -** is declared to contain a particular type does not mean that the -** data stored in that column is of the declared type. SQLite is -** strongly typed, but the typing is dynamic not static. ^Type -** is associated with individual values, not with the containers -** used to hold those values. -*/ -SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); -SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); - -/* -** CAPI3REF: Evaluate An SQL Statement -** -** After a [prepared statement] has been prepared using either -** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy -** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function -** must be called one or more times to evaluate the statement. -** -** The details of the behavior of the sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy -** interface will continue to be supported. -** -** ^In the legacy interface, the return value will be either [SQLITE_BUSY], -** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. -** ^With the "v2" interface, any of the other [result codes] or -** [extended result codes] might be returned as well. -** -** ^[SQLITE_BUSY] means that the database engine was unable to acquire the -** database locks it needs to do its job. ^If the statement is a [COMMIT] -** or occurs outside of an explicit transaction, then you can retry the -** statement. If the statement is not a [COMMIT] and occurs within an -** explicit transaction then you should rollback the transaction before -** continuing. -** -** ^[SQLITE_DONE] means that the statement has finished executing -** successfully. sqlite3_step() should not be called again on this virtual -** machine without first calling [sqlite3_reset()] to reset the virtual -** machine back to its initial state. -** -** ^If the SQL statement being executed returns any data, then [SQLITE_ROW] -** is returned each time a new row of data is ready for processing by the -** caller. The values may be accessed using the [column access functions]. -** sqlite3_step() is called again to retrieve the next row of data. -** -** ^[SQLITE_ERROR] means that a run-time error (such as a constraint -** violation) has occurred. sqlite3_step() should not be called again on -** the VM. More information may be found by calling [sqlite3_errmsg()]. -** ^With the legacy interface, a more specific error code (for example, -** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) -** can be obtained by calling [sqlite3_reset()] on the -** [prepared statement]. ^In the "v2" interface, -** the more specific error code is returned directly by sqlite3_step(). -** -** [SQLITE_MISUSE] means that the this routine was called inappropriately. -** Perhaps it was called on a [prepared statement] that has -** already been [sqlite3_finalize | finalized] or on one that had -** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could -** be the case that the same database connection is being used by two or -** more threads at the same moment in time. -** -** For all versions of SQLite up to and including 3.6.23.1, a call to -** [sqlite3_reset()] was required after sqlite3_step() returned anything -** other than [SQLITE_ROW] before any subsequent invocation of -** sqlite3_step(). Failure to reset the prepared statement using -** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from -** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began -** calling [sqlite3_reset()] automatically in this circumstance rather -** than returning [SQLITE_MISUSE]. This is not considered a compatibility -** break because any application that ever receives an SQLITE_MISUSE error -** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option -** can be used to restore the legacy behavior. -** -** Goofy Interface Alert: In the legacy interface, the sqlite3_step() -** API always returns a generic error code, [SQLITE_ERROR], following any -** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call -** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the -** specific [error codes] that better describes the error. -** We admit that this is a goofy design. The problem has been fixed -** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead -** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, -** then the more specific [error codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. -*/ -SQLITE_API int sqlite3_step(sqlite3_stmt*); - -/* -** CAPI3REF: Number of columns in a result set -** -** ^The sqlite3_data_count(P) interface returns the number of columns in the -** current row of the result set of [prepared statement] P. -** ^If prepared statement P does not have results ready to return -** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of -** interfaces) then sqlite3_data_count(P) returns 0. -** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. -** ^The sqlite3_data_count(P) routine returns 0 if the previous call to -** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) -** will return non-zero if previous call to [sqlite3_step](P) returned -** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] -** where it always returns zero since each step of that multi-step -** pragma returns 0 columns of data. -** -** See also: [sqlite3_column_count()] -*/ -SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Fundamental Datatypes -** KEYWORDS: SQLITE_TEXT -** -** ^(Every value in SQLite has one of five fundamental datatypes: -** -**
    -**
  • 64-bit signed integer -**
  • 64-bit IEEE floating point number -**
  • string -**
  • BLOB -**
  • NULL -**
)^ -** -** These constants are codes for each of those types. -** -** Note that the SQLITE_TEXT constant was also used in SQLite version 2 -** for a completely different meaning. Software that links against both -** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not -** SQLITE_TEXT. -*/ -#define SQLITE_INTEGER 1 -#define SQLITE_FLOAT 2 -#define SQLITE_BLOB 4 -#define SQLITE_NULL 5 -#ifdef SQLITE_TEXT -# undef SQLITE_TEXT -#else -# define SQLITE_TEXT 3 -#endif -#define SQLITE3_TEXT 3 - -/* -** CAPI3REF: Result Values From A Query -** KEYWORDS: {column access functions} -** -** These routines form the "result set" interface. -** -** ^These routines return information about a single column of the current -** result row of a query. ^In every case the first argument is a pointer -** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] -** that was returned from [sqlite3_prepare_v2()] or one of its variants) -** and the second argument is the index of the column for which information -** should be returned. ^The leftmost column of the result set has the index 0. -** ^The number of columns in the result can be determined using -** [sqlite3_column_count()]. -** -** If the SQL statement does not currently point to a valid row, or if the -** column index is out of range, the result is undefined. -** These routines may only be called when the most recent call to -** [sqlite3_step()] has returned [SQLITE_ROW] and neither -** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently. -** If any of these routines are called after [sqlite3_reset()] or -** [sqlite3_finalize()] or after [sqlite3_step()] has returned -** something other than [SQLITE_ROW], the results are undefined. -** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] -** are called from a different thread while any of these routines -** are pending, then the results are undefined. -** -** ^The sqlite3_column_type() routine returns the -** [SQLITE_INTEGER | datatype code] for the initial data type -** of the result column. ^The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future -** versions of SQLite may change the behavior of sqlite3_column_type() -** following a type conversion. -** -** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() -** routine returns the number of bytes in that BLOB or string. -** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts -** the string to UTF-8 and then returns the number of bytes. -** ^If the result is a numeric value then sqlite3_column_bytes() uses -** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns -** the number of bytes in that string. -** ^If the result is NULL, then sqlite3_column_bytes() returns zero. -** -** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() -** routine returns the number of bytes in that BLOB or string. -** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts -** the string to UTF-16 and then returns the number of bytes. -** ^If the result is a numeric value then sqlite3_column_bytes16() uses -** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns -** the number of bytes in that string. -** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. -** -** ^The values returned by [sqlite3_column_bytes()] and -** [sqlite3_column_bytes16()] do not include the zero terminators at the end -** of the string. ^For clarity: the values returned by -** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of -** bytes in the string, not the number of characters. -** -** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), -** even empty strings, are always zero-terminated. ^The return -** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. -** -** ^The object returned by [sqlite3_column_value()] is an -** [unprotected sqlite3_value] object. An unprotected sqlite3_value object -** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. -** If the [unprotected sqlite3_value] object returned by -** [sqlite3_column_value()] is used in any other way, including calls -** to routines like [sqlite3_value_int()], [sqlite3_value_text()], -** or [sqlite3_value_bytes()], then the behavior is undefined. -** -** These routines attempt to convert the value where appropriate. ^For -** example, if the internal representation is FLOAT and a text result -** is requested, [sqlite3_snprintf()] is used internally to perform the -** conversion automatically. ^(The following table details the conversions -** that are applied: -** -**
-** -**
Internal
Type
Requested
Type
Conversion -** -**
NULL INTEGER Result is 0 -**
NULL FLOAT Result is 0.0 -**
NULL TEXT Result is NULL pointer -**
NULL BLOB Result is NULL pointer -**
INTEGER FLOAT Convert from integer to float -**
INTEGER TEXT ASCII rendering of the integer -**
INTEGER BLOB Same as INTEGER->TEXT -**
FLOAT INTEGER Convert from float to integer -**
FLOAT TEXT ASCII rendering of the float -**
FLOAT BLOB Same as FLOAT->TEXT -**
TEXT INTEGER Use atoi() -**
TEXT FLOAT Use atof() -**
TEXT BLOB No change -**
BLOB INTEGER Convert to TEXT then use atoi() -**
BLOB FLOAT Convert to TEXT then use atof() -**
BLOB TEXT Add a zero terminator if needed -**
-**
)^ -** -** The table above makes reference to standard C library functions atoi() -** and atof(). SQLite does not really use these functions. It has its -** own equivalent internal routines. The atoi() and atof() names are -** used in the table for brevity and because they are familiar to most -** C programmers. -** -** Note that when type conversions occur, pointers returned by prior -** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or -** sqlite3_column_text16() may be invalidated. -** Type conversions and pointer invalidations might occur -** in the following cases: -** -**
    -**
  • The initial content is a BLOB and sqlite3_column_text() or -** sqlite3_column_text16() is called. A zero-terminator might -** need to be added to the string.
  • -**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or -** sqlite3_column_text16() is called. The content must be converted -** to UTF-16.
  • -**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or -** sqlite3_column_text() is called. The content must be converted -** to UTF-8.
  • -**
-** -** ^Conversions between UTF-16be and UTF-16le are always done in place and do -** not invalidate a prior pointer, though of course the content of the buffer -** that the prior pointer references will have been modified. Other kinds -** of conversion are done in place when it is possible, but sometimes they -** are not possible and in those cases prior pointers are invalidated. -** -** The safest and easiest to remember policy is to invoke these routines -** in one of the following ways: -** -**
    -**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • -**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • -**
-** -** In other words, you should call sqlite3_column_text(), -** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result -** into the desired format, then invoke sqlite3_column_bytes() or -** sqlite3_column_bytes16() to find the size of the result. Do not mix calls -** to sqlite3_column_text() or sqlite3_column_blob() with calls to -** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() -** with calls to sqlite3_column_bytes(). -** -** ^The pointers returned are valid until a type conversion occurs as -** described above, or until [sqlite3_step()] or [sqlite3_reset()] or -** [sqlite3_finalize()] is called. ^The memory space used to hold strings -** and BLOBs is freed automatically. Do not pass the pointers returned -** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into -** [sqlite3_free()]. -** -** ^(If a memory allocation error occurs during the evaluation of any -** of these routines, a default value is returned. The default value -** is either the integer 0, the floating point number 0.0, or a NULL -** pointer. Subsequent calls to [sqlite3_errcode()] will return -** [SQLITE_NOMEM].)^ -*/ -SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); -SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); -SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); -SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); -SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); - -/* -** CAPI3REF: Destroy A Prepared Statement Object -** -** ^The sqlite3_finalize() function is called to delete a [prepared statement]. -** ^If the most recent evaluation of the statement encountered no errors -** or if the statement is never been evaluated, then sqlite3_finalize() returns -** SQLITE_OK. ^If the most recent evaluation of statement S failed, then -** sqlite3_finalize(S) returns the appropriate [error code] or -** [extended error code]. -** -** ^The sqlite3_finalize(S) routine can be called at any point during -** the life cycle of [prepared statement] S: -** before statement S is ever evaluated, after -** one or more calls to [sqlite3_reset()], or after any call -** to [sqlite3_step()] regardless of whether or not the statement has -** completed execution. -** -** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. -** -** The application must finalize every [prepared statement] in order to avoid -** resource leaks. It is a grievous error for the application to try to use -** a prepared statement after it has been finalized. Any use of a prepared -** statement after it has been finalized can result in undefined and -** undesirable behavior such as segfaults and heap corruption. -*/ -SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Reset A Prepared Statement Object -** -** The sqlite3_reset() function is called to reset a [prepared statement] -** object back to its initial state, ready to be re-executed. -** ^Any SQL statement variables that had values bound to them using -** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. -** Use [sqlite3_clear_bindings()] to reset the bindings. -** -** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S -** back to the beginning of its program. -** -** ^If the most recent call to [sqlite3_step(S)] for the -** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], -** or if [sqlite3_step(S)] has never before been called on S, -** then [sqlite3_reset(S)] returns [SQLITE_OK]. -** -** ^If the most recent call to [sqlite3_step(S)] for the -** [prepared statement] S indicated an error, then -** [sqlite3_reset(S)] returns an appropriate [error code]. -** -** ^The [sqlite3_reset(S)] interface does not change the values -** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. -*/ -SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Create Or Redefine SQL Functions -** KEYWORDS: {function creation routines} -** KEYWORDS: {application-defined SQL function} -** KEYWORDS: {application-defined SQL functions} -** -** ^These functions (collectively known as "function creation routines") -** are used to add SQL functions or aggregates or to redefine the behavior -** of existing SQL functions or aggregates. The only differences between -** these routines are the text encoding expected for -** the second parameter (the name of the function being created) -** and the presence or absence of a destructor callback for -** the application data pointer. -** -** ^The first parameter is the [database connection] to which the SQL -** function is to be added. ^If an application uses more than one database -** connection then application-defined SQL functions must be added -** to each database connection separately. -** -** ^The second parameter is the name of the SQL function to be created or -** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 -** representation, exclusive of the zero-terminator. ^Note that the name -** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. -** ^Any attempt to create a function with a longer name -** will result in [SQLITE_MISUSE] being returned. -** -** ^The third parameter (nArg) -** is the number of arguments that the SQL function or -** aggregate takes. ^If this parameter is -1, then the SQL function or -** aggregate may take any number of arguments between 0 and the limit -** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third -** parameter is less than -1 or greater than 127 then the behavior is -** undefined. -** -** ^The fourth parameter, eTextRep, specifies what -** [SQLITE_UTF8 | text encoding] this SQL function prefers for -** its parameters. Every SQL function implementation must be able to work -** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. ^An application may -** invoke sqlite3_create_function() or sqlite3_create_function16() multiple -** times with the same function but with different values of eTextRep. -** ^When multiple implementations of the same function are available, SQLite -** will pick the one that involves the least amount of data conversion. -** If there is only a single implementation which does not care what text -** encoding is used, then the fourth argument should be [SQLITE_ANY]. -** -** ^(The fifth parameter is an arbitrary pointer. The implementation of the -** function can gain access to this pointer using [sqlite3_user_data()].)^ -** -** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are -** pointers to C-language functions that implement the SQL function or -** aggregate. ^A scalar SQL function requires an implementation of the xFunc -** callback only; NULL pointers must be passed as the xStep and xFinal -** parameters. ^An aggregate SQL function requires an implementation of xStep -** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing -** SQL function or aggregate, pass NULL pointers for all three function -** callbacks. -** -** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, -** then it is destructor for the application data pointer. -** The destructor is invoked when the function is deleted, either by being -** overloaded or when the database connection closes.)^ -** ^The destructor is also invoked if the call to -** sqlite3_create_function_v2() fails. -** ^When the destructor callback of the tenth parameter is invoked, it -** is passed a single argument which is a copy of the application data -** pointer which was the fifth parameter to sqlite3_create_function_v2(). -** -** ^It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing preferred text encodings. ^SQLite will use -** the implementation that most closely matches the way in which the -** SQL function is used. ^A function implementation with a non-negative -** nArg parameter is a better match than a function implementation with -** a negative nArg. ^A function where the preferred text encoding -** matches the database encoding is a better -** match than a function where the encoding is different. -** ^A function where the encoding difference is between UTF16le and UTF16be -** is a closer match than a function where the encoding difference is -** between UTF8 and UTF16. -** -** ^Built-in functions may be overloaded by new application-defined functions. -** -** ^An application-defined function is permitted to call other -** SQLite interfaces. However, such calls must not -** close the database connection nor finalize or reset the prepared -** statement in which the function is running. -*/ -SQLITE_API int sqlite3_create_function( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -SQLITE_API int sqlite3_create_function16( - sqlite3 *db, - const void *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*) -); -SQLITE_API int sqlite3_create_function_v2( - sqlite3 *db, - const char *zFunctionName, - int nArg, - int eTextRep, - void *pApp, - void (*xFunc)(sqlite3_context*,int,sqlite3_value**), - void (*xStep)(sqlite3_context*,int,sqlite3_value**), - void (*xFinal)(sqlite3_context*), - void(*xDestroy)(void*) -); - -/* -** CAPI3REF: Text Encodings -** -** These constant define integer codes that represent the various -** text encodings supported by SQLite. -*/ -#define SQLITE_UTF8 1 -#define SQLITE_UTF16LE 2 -#define SQLITE_UTF16BE 3 -#define SQLITE_UTF16 4 /* Use native byte order */ -#define SQLITE_ANY 5 /* sqlite3_create_function only */ -#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ - -/* -** CAPI3REF: Deprecated Functions -** DEPRECATED -** -** These functions are [deprecated]. In order to maintain -** backwards compatibility with older code, these functions continue -** to be supported. However, new applications should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you what they do. -*/ -#ifndef SQLITE_OMIT_DEPRECATED -SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); -SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); -SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); -SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), - void*,sqlite3_int64); -#endif - -/* -** CAPI3REF: Obtaining SQL Function Parameter Values -** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 3rd parameter to these callbacks is an array of pointers to -** [protected sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. -** -** These routines work only with [protected sqlite3_value] objects. -** Any attempt to use these routines on an [unprotected sqlite3_value] -** object results in undefined behavior. -** -** ^These routines work just like the corresponding [column access functions] -** except that these routines take a single [protected sqlite3_value] object -** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. -** -** ^The sqlite3_value_text16() interface extracts a UTF-16 string -** in the native byte-order of the host machine. ^The -** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces -** extract UTF-16 strings as big-endian and little-endian respectively. -** -** ^(The sqlite3_value_numeric_type() interface attempts to apply -** numeric affinity to the value. This means that an attempt is -** made to convert the value to an integer or floating point. If -** such a conversion is possible without loss of information (in other -** words, if the value is a string that looks like a number) -** then the conversion is performed. Otherwise no conversion occurs. -** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ -** -** Please pay particular attention to the fact that the pointer returned -** from [sqlite3_value_blob()], [sqlite3_value_text()], or -** [sqlite3_value_text16()] can be invalidated by a subsequent call to -** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], -** or [sqlite3_value_text16()]. -** -** These routines must be called from the same thread as -** the SQL function that supplied the [sqlite3_value*] parameters. -*/ -SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); -SQLITE_API double sqlite3_value_double(sqlite3_value*); -SQLITE_API int sqlite3_value_int(sqlite3_value*); -SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); -SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); -SQLITE_API int sqlite3_value_type(sqlite3_value*); -SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); - -/* -** CAPI3REF: Obtain Aggregate Function Context -** -** Implementations of aggregate SQL functions use this -** routine to allocate memory for storing their state. -** -** ^The first time the sqlite3_aggregate_context(C,N) routine is called -** for a particular aggregate function, SQLite -** allocates N of memory, zeroes out that memory, and returns a pointer -** to the new memory. ^On second and subsequent calls to -** sqlite3_aggregate_context() for the same aggregate function instance, -** the same buffer is returned. Sqlite3_aggregate_context() is normally -** called once for each invocation of the xStep callback and then one -** last time when the xFinal callback is invoked. ^(When no rows match -** an aggregate query, the xStep() callback of the aggregate function -** implementation is never called and xFinal() is called exactly once. -** In those cases, sqlite3_aggregate_context() might be called for the -** first time from within xFinal().)^ -** -** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer -** when first called if N is less than or equal to zero or if a memory -** allocate error occurs. -** -** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is -** determined by the N parameter on first successful call. Changing the -** value of N in subsequent call to sqlite3_aggregate_context() within -** the same aggregate function instance will not resize the memory -** allocation.)^ Within the xFinal callback, it is customary to set -** N=0 in calls to sqlite3_aggregate_context(C,N) so that no -** pointless memory allocations occur. -** -** ^SQLite automatically frees the memory allocated by -** sqlite3_aggregate_context() when the aggregate query concludes. -** -** The first parameter must be a copy of the -** [sqlite3_context | SQL function context] that is the first parameter -** to the xStep or xFinal callback routine that implements the aggregate -** function. -** -** This routine must be called from the same thread in which -** the aggregate SQL function is running. -*/ -SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); - -/* -** CAPI3REF: User Data For Functions -** -** ^The sqlite3_user_data() interface returns a copy of -** the pointer that was the pUserData parameter (the 5th parameter) -** of the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. -** -** This routine must be called from the same thread in which -** the application-defined function is running. -*/ -SQLITE_API void *sqlite3_user_data(sqlite3_context*); - -/* -** CAPI3REF: Database Connection For Functions -** -** ^The sqlite3_context_db_handle() interface returns a copy of -** the pointer to the [database connection] (the 1st parameter) -** of the [sqlite3_create_function()] -** and [sqlite3_create_function16()] routines that originally -** registered the application defined function. -*/ -SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); - -/* -** CAPI3REF: Function Auxiliary Data -** -** The following two functions may be used by scalar SQL functions to -** associate metadata with argument values. If the same value is passed to -** multiple invocations of the same SQL function during query execution, under -** some circumstances the associated metadata may be preserved. This may -** be used, for example, to add a regular-expression matching scalar -** function. The compiled version of the regular expression is stored as -** metadata associated with the SQL value passed as the regular expression -** pattern. The compiled regular expression can be reused on multiple -** invocations of the same function so that the original pattern string -** does not need to be recompiled on each invocation. -** -** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata -** associated by the sqlite3_set_auxdata() function with the Nth argument -** value to the application-defined function. ^If no metadata has been ever -** been set for the Nth argument of the function, or if the corresponding -** function parameter has changed since the meta-data was set, -** then sqlite3_get_auxdata() returns a NULL pointer. -** -** ^The sqlite3_set_auxdata() interface saves the metadata -** pointed to by its 3rd parameter as the metadata for the N-th -** argument of the application-defined function. Subsequent -** calls to sqlite3_get_auxdata() might return this data, if it has -** not been destroyed. -** ^If it is not NULL, SQLite will invoke the destructor -** function given by the 4th parameter to sqlite3_set_auxdata() on -** the metadata when the corresponding function parameter changes -** or when the SQL statement completes, whichever comes first. -** -** SQLite is free to call the destructor and drop metadata on any -** parameter of any function at any time. ^The only guarantee is that -** the destructor will be called before the metadata is dropped. -** -** ^(In practice, metadata is preserved between function calls for -** expressions that are constant at compile time. This includes literal -** values and [parameters].)^ -** -** These routines must be called from the same thread in which -** the SQL function is running. -*/ -SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); -SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); - - -/* -** CAPI3REF: Constants Defining Special Destructor Behavior -** -** These are special values for the destructor that is passed in as the -** final argument to routines like [sqlite3_result_blob()]. ^If the destructor -** argument is SQLITE_STATIC, it means that the content pointer is constant -** and will never change. It does not need to be destroyed. ^The -** SQLITE_TRANSIENT value means that the content will likely change in -** the near future and that SQLite should make its own private copy of -** the content before returning. -** -** The typedef is necessary to work around problems in certain -** C++ compilers. -*/ -typedef void (*sqlite3_destructor_type)(void*); -#define SQLITE_STATIC ((sqlite3_destructor_type)0) -#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) - -/* -** CAPI3REF: Setting The Result Of An SQL Function -** -** These routines are used by the xFunc or xFinal callbacks that -** implement SQL functions and aggregates. See -** [sqlite3_create_function()] and [sqlite3_create_function16()] -** for additional information. -** -** These functions work very much like the [parameter binding] family of -** functions used to bind values to host parameters in prepared statements. -** Refer to the [SQL parameter] documentation for additional information. -** -** ^The sqlite3_result_blob() interface sets the result from -** an application-defined function to be the BLOB whose content is pointed -** to by the second parameter and which is N bytes long where N is the -** third parameter. -** -** ^The sqlite3_result_zeroblob() interfaces set the result of -** the application-defined function to be a BLOB containing all zero -** bytes and N bytes in size, where N is the value of the 2nd parameter. -** -** ^The sqlite3_result_double() interface sets the result from -** an application-defined function to be a floating point value specified -** by its 2nd argument. -** -** ^The sqlite3_result_error() and sqlite3_result_error16() functions -** cause the implemented SQL function to throw an exception. -** ^SQLite uses the string pointed to by the -** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() -** as the text of an error message. ^SQLite interprets the error -** message string from sqlite3_result_error() as UTF-8. ^SQLite -** interprets the string from sqlite3_result_error16() as UTF-16 in native -** byte order. ^If the third parameter to sqlite3_result_error() -** or sqlite3_result_error16() is negative then SQLite takes as the error -** message all text up through the first zero character. -** ^If the third parameter to sqlite3_result_error() or -** sqlite3_result_error16() is non-negative then SQLite takes that many -** bytes (not characters) from the 2nd parameter as the error message. -** ^The sqlite3_result_error() and sqlite3_result_error16() -** routines make a private copy of the error message text before -** they return. Hence, the calling function can deallocate or -** modify the text after they return without harm. -** ^The sqlite3_result_error_code() function changes the error code -** returned by SQLite as a result of an error in a function. ^By default, -** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() -** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. -** -** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an -** error indicating that a string or BLOB is too long to represent. -** -** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an -** error indicating that a memory allocation failed. -** -** ^The sqlite3_result_int() interface sets the return value -** of the application-defined function to be the 32-bit signed integer -** value given in the 2nd argument. -** ^The sqlite3_result_int64() interface sets the return value -** of the application-defined function to be the 64-bit signed integer -** value given in the 2nd argument. -** -** ^The sqlite3_result_null() interface sets the return value -** of the application-defined function to be NULL. -** -** ^The sqlite3_result_text(), sqlite3_result_text16(), -** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces -** set the return value of the application-defined function to be -** a text string which is represented as UTF-8, UTF-16 native byte order, -** UTF-16 little endian, or UTF-16 big endian, respectively. -** ^SQLite takes the text result from the application from -** the 2nd parameter of the sqlite3_result_text* interfaces. -** ^If the 3rd parameter to the sqlite3_result_text* interfaces -** is negative, then SQLite takes result text from the 2nd parameter -** through the first zero character. -** ^If the 3rd parameter to the sqlite3_result_text* interfaces -** is non-negative, then as many bytes (not characters) of the text -** pointed to by the 2nd parameter are taken as the application-defined -** function result. If the 3rd parameter is non-negative, then it -** must be the byte offset into the string where the NUL terminator would -** appear if the string where NUL terminated. If any NUL characters occur -** in the string at a byte offset that is less than the value of the 3rd -** parameter, then the resulting string will contain embedded NULs and the -** result of expressions operating on strings with embedded NULs is undefined. -** ^If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that -** function as the destructor on the text or BLOB result when it has -** finished using that result. -** ^If the 4th parameter to the sqlite3_result_text* interfaces or to -** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite -** assumes that the text or BLOB result is in constant space and does not -** copy the content of the parameter nor call a destructor on the content -** when it has finished using that result. -** ^If the 4th parameter to the sqlite3_result_text* interfaces -** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from -** from [sqlite3_malloc()] before it returns. -** -** ^The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the -** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The -** sqlite3_result_value() interface makes a copy of the [sqlite3_value] -** so that the [sqlite3_value] specified in the parameter may change or -** be deallocated after sqlite3_result_value() returns without harm. -** ^A [protected sqlite3_value] object may always be used where an -** [unprotected sqlite3_value] object is required, so either -** kind of [sqlite3_value] object can be used with this interface. -** -** If these routines are called from within the different thread -** than the one containing the application-defined function that received -** the [sqlite3_context] pointer, the results are undefined. -*/ -SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_double(sqlite3_context*, double); -SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); -SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); -SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); -SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); -SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); -SQLITE_API void sqlite3_result_int(sqlite3_context*, int); -SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); -SQLITE_API void sqlite3_result_null(sqlite3_context*); -SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); -SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); - -/* -** CAPI3REF: Define New Collating Sequences -** -** ^These functions add, remove, or modify a [collation] associated -** with the [database connection] specified as the first argument. -** -** ^The name of the collation is a UTF-8 string -** for sqlite3_create_collation() and sqlite3_create_collation_v2() -** and a UTF-16 string in native byte order for sqlite3_create_collation16(). -** ^Collation names that compare equal according to [sqlite3_strnicmp()] are -** considered to be the same name. -** -** ^(The third argument (eTextRep) must be one of the constants: -**
    -**
  • [SQLITE_UTF8], -**
  • [SQLITE_UTF16LE], -**
  • [SQLITE_UTF16BE], -**
  • [SQLITE_UTF16], or -**
  • [SQLITE_UTF16_ALIGNED]. -**
)^ -** ^The eTextRep argument determines the encoding of strings passed -** to the collating function callback, xCallback. -** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep -** force strings to be UTF16 with native byte order. -** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin -** on an even byte address. -** -** ^The fourth argument, pArg, is an application data pointer that is passed -** through as the first argument to the collating function callback. -** -** ^The fifth argument, xCallback, is a pointer to the collating function. -** ^Multiple collating functions can be registered using the same name but -** with different eTextRep parameters and SQLite will use whichever -** function requires the least amount of data transformation. -** ^If the xCallback argument is NULL then the collating function is -** deleted. ^When all collating functions having the same name are deleted, -** that collation is no longer usable. -** -** ^The collating function callback is invoked with a copy of the pArg -** application data pointer and with two strings in the encoding specified -** by the eTextRep argument. The collating function must return an -** integer that is negative, zero, or positive -** if the first string is less than, equal to, or greater than the second, -** respectively. A collating function must always return the same answer -** given the same inputs. If two or more collating functions are registered -** to the same collation name (using different eTextRep values) then all -** must give an equivalent answer when invoked with equivalent strings. -** The collating function must obey the following properties for all -** strings A, B, and C: -** -**
    -**
  1. If A==B then B==A. -**
  2. If A==B and B==C then A==C. -**
  3. If A<B THEN B>A. -**
  4. If A<B and B<C then A<C. -**
-** -** If a collating function fails any of the above constraints and that -** collating function is registered and used, then the behavior of SQLite -** is undefined. -** -** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() -** with the addition that the xDestroy callback is invoked on pArg when -** the collating function is deleted. -** ^Collating functions are deleted when they are overridden by later -** calls to the collation creation functions or when the -** [database connection] is closed using [sqlite3_close()]. -** -** ^The xDestroy callback is not called if the -** sqlite3_create_collation_v2() function fails. Applications that invoke -** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should -** check the return code and dispose of the application data pointer -** themselves rather than expecting SQLite to deal with it for them. -** This is different from every other SQLite interface. The inconsistency -** is unfortunate but cannot be changed without breaking backwards -** compatibility. -** -** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. -*/ -SQLITE_API int sqlite3_create_collation( - sqlite3*, - const char *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*) -); -SQLITE_API int sqlite3_create_collation_v2( - sqlite3*, - const char *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*), - void(*xDestroy)(void*) -); -SQLITE_API int sqlite3_create_collation16( - sqlite3*, - const void *zName, - int eTextRep, - void *pArg, - int(*xCompare)(void*,int,const void*,int,const void*) -); - -/* -** CAPI3REF: Collation Needed Callbacks -** -** ^To avoid having to register all collation sequences before a database -** can be used, a single callback function may be registered with the -** [database connection] to be invoked whenever an undefined collation -** sequence is required. -** -** ^If the function is registered using the sqlite3_collation_needed() API, -** then it is passed the names of undefined collation sequences as strings -** encoded in UTF-8. ^If sqlite3_collation_needed16() is used, -** the names are passed as UTF-16 in machine native byte order. -** ^A call to either function replaces the existing collation-needed callback. -** -** ^(When the callback is invoked, the first argument passed is a copy -** of the second argument to sqlite3_collation_needed() or -** sqlite3_collation_needed16(). The second argument is the database -** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE], indicating the most desirable form of the collation -** sequence function required. The fourth parameter is the name of the -** required collation sequence.)^ -** -** The callback function should register the desired collation using -** [sqlite3_create_collation()], [sqlite3_create_collation16()], or -** [sqlite3_create_collation_v2()]. -*/ -SQLITE_API int sqlite3_collation_needed( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const char*) -); -SQLITE_API int sqlite3_collation_needed16( - sqlite3*, - void*, - void(*)(void*,sqlite3*,int eTextRep,const void*) -); - -#ifdef SQLITE_HAS_CODEC -/* -** Specify the key for an encrypted database. This routine should be -** called right after sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -SQLITE_API int sqlite3_key( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The key */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -SQLITE_API int sqlite3_rekey( - sqlite3 *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** Specify the activation key for a SEE database. Unless -** activated, none of the SEE routines will work. -*/ -SQLITE_API void sqlite3_activate_see( - const char *zPassPhrase /* Activation phrase */ -); -#endif - -#ifdef SQLITE_ENABLE_CEROD -/* -** Specify the activation key for a CEROD database. Unless -** activated, none of the CEROD routines will work. -*/ -SQLITE_API void sqlite3_activate_cerod( - const char *zPassPhrase /* Activation phrase */ -); -#endif - -/* -** CAPI3REF: Suspend Execution For A Short Time -** -** The sqlite3_sleep() function causes the current thread to suspend execution -** for at least a number of milliseconds specified in its parameter. -** -** If the operating system does not support sleep requests with -** millisecond time resolution, then the time will be rounded up to -** the nearest second. The number of milliseconds of sleep actually -** requested from the operating system is returned. -** -** ^SQLite implements this interface by calling the xSleep() -** method of the default [sqlite3_vfs] object. If the xSleep() method -** of the default VFS is not implemented correctly, or not implemented at -** all, then the behavior of sqlite3_sleep() may deviate from the description -** in the previous paragraphs. -*/ -SQLITE_API int sqlite3_sleep(int); - -/* -** CAPI3REF: Name Of The Folder Holding Temporary Files -** -** ^(If this global variable is made to point to a string which is -** the name of a folder (a.k.a. directory), then all temporary files -** created by SQLite when using a built-in [sqlite3_vfs | VFS] -** will be placed in that directory.)^ ^If this variable -** is a NULL pointer, then SQLite performs a search for an appropriate -** temporary file directory. -** -** It is not safe to read or modify this variable in more than one -** thread at a time. It is not safe to read or modify this variable -** if a [database connection] is being used at the same time in a separate -** thread. -** It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been called and that this variable remain unchanged -** thereafter. -** -** ^The [temp_store_directory pragma] may modify this variable and cause -** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, -** the [temp_store_directory pragma] always assumes that any string -** that this variable points to is held in memory obtained from -** [sqlite3_malloc] and the pragma may attempt to free that memory -** using [sqlite3_free]. -** Hence, if this variable is modified directly, either it should be -** made NULL or made to point to memory obtained from [sqlite3_malloc] -** or else the use of the [temp_store_directory pragma] should be avoided. -** -** Note to Windows Runtime users: The temporary directory must be set -** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various -** features that require the use of temporary files may fail. Here is an -** example of how to do this using C++ with the Windows Runtime: -** -**
-** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
-**       TemporaryFolder->Path->Data();
-** char zPathBuf[MAX_PATH + 1];
-** memset(zPathBuf, 0, sizeof(zPathBuf));
-** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
-**       NULL, NULL);
-** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
-** 
-*/ -SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory; - -/* -** CAPI3REF: Name Of The Folder Holding Database Files -** -** ^(If this global variable is made to point to a string which is -** the name of a folder (a.k.a. directory), then all database files -** specified with a relative pathname and created or accessed by -** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed -** to be relative to that directory.)^ ^If this variable is a NULL -** pointer, then SQLite assumes that all database files specified -** with a relative pathname are relative to the current directory -** for the process. Only the windows VFS makes use of this global -** variable; it is ignored by the unix VFS. -** -** Changing the value of this variable while a database connection is -** open can result in a corrupt database. -** -** It is not safe to read or modify this variable in more than one -** thread at a time. It is not safe to read or modify this variable -** if a [database connection] is being used at the same time in a separate -** thread. -** It is intended that this variable be set once -** as part of process initialization and before any SQLite interface -** routines have been called and that this variable remain unchanged -** thereafter. -** -** ^The [data_store_directory pragma] may modify this variable and cause -** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, -** the [data_store_directory pragma] always assumes that any string -** that this variable points to is held in memory obtained from -** [sqlite3_malloc] and the pragma may attempt to free that memory -** using [sqlite3_free]. -** Hence, if this variable is modified directly, either it should be -** made NULL or made to point to memory obtained from [sqlite3_malloc] -** or else the use of the [data_store_directory pragma] should be avoided. -*/ -SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; - -/* -** CAPI3REF: Test For Auto-Commit Mode -** KEYWORDS: {autocommit mode} -** -** ^The sqlite3_get_autocommit() interface returns non-zero or -** zero if the given database connection is or is not in autocommit mode, -** respectively. ^Autocommit mode is on by default. -** ^Autocommit mode is disabled by a [BEGIN] statement. -** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. -** -** If certain kinds of errors occur on a statement within a multi-statement -** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], -** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the -** transaction might be rolled back automatically. The only way to -** find out whether SQLite automatically rolled back the transaction after -** an error is to use this function. -** -** If another thread changes the autocommit status of the database -** connection while this routine is running, then the return value -** is undefined. -*/ -SQLITE_API int sqlite3_get_autocommit(sqlite3*); - -/* -** CAPI3REF: Find The Database Handle Of A Prepared Statement -** -** ^The sqlite3_db_handle interface returns the [database connection] handle -** to which a [prepared statement] belongs. ^The [database connection] -** returned by sqlite3_db_handle is the same [database connection] -** that was the first argument -** to the [sqlite3_prepare_v2()] call (or its variants) that was used to -** create the statement in the first place. -*/ -SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); - -/* -** CAPI3REF: Return The Filename For A Database Connection -** -** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename -** associated with database N of connection D. ^The main database file -** has the name "main". If there is no attached database N on the database -** connection D, or if database N is a temporary or in-memory database, then -** a NULL pointer is returned. -** -** ^The filename returned by this function is the output of the -** xFullPathname method of the [VFS]. ^In other words, the filename -** will be an absolute pathname, even if the filename used -** to open the database originally was a URI or relative pathname. -*/ -SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); - -/* -** CAPI3REF: Determine if a database is read-only -** -** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N -** of connection D is read-only, 0 if it is read/write, or -1 if N is not -** the name of a database on connection D. -*/ -SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); - -/* -** CAPI3REF: Find the next prepared statement -** -** ^This interface returns a pointer to the next [prepared statement] after -** pStmt associated with the [database connection] pDb. ^If pStmt is NULL -** then this interface returns a pointer to the first prepared statement -** associated with the database connection pDb. ^If no prepared statement -** satisfies the conditions of this routine, it returns NULL. -** -** The [database connection] pointer D in a call to -** [sqlite3_next_stmt(D,S)] must refer to an open database -** connection and in particular must not be a NULL pointer. -*/ -SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); - -/* -** CAPI3REF: Commit And Rollback Notification Callbacks -** -** ^The sqlite3_commit_hook() interface registers a callback -** function to be invoked whenever a transaction is [COMMIT | committed]. -** ^Any callback set by a previous call to sqlite3_commit_hook() -** for the same database connection is overridden. -** ^The sqlite3_rollback_hook() interface registers a callback -** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. -** ^Any callback set by a previous call to sqlite3_rollback_hook() -** for the same database connection is overridden. -** ^The pArg argument is passed through to the callback. -** ^If the callback on a commit hook function returns non-zero, -** then the commit is converted into a rollback. -** -** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions -** return the P argument from the previous call of the same function -** on the same [database connection] D, or NULL for -** the first call for each function on D. -** -** The commit and rollback hook callbacks are not reentrant. -** The callback implementation must not do anything that will modify -** the database connection that invoked the callback. Any actions -** to modify the database connection must be deferred until after the -** completion of the [sqlite3_step()] call that triggered the commit -** or rollback hook in the first place. -** Note that running any other SQL statements, including SELECT statements, -** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify -** the database connections for the meaning of "modify" in this paragraph. -** -** ^Registering a NULL function disables the callback. -** -** ^When the commit hook callback routine returns zero, the [COMMIT] -** operation is allowed to continue normally. ^If the commit hook -** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. -** ^The rollback hook is invoked on a rollback that results from a commit -** hook returning non-zero, just as it would be with any other rollback. -** -** ^For the purposes of this API, a transaction is said to have been -** rolled back if an explicit "ROLLBACK" statement is executed, or -** an error or constraint causes an implicit rollback to occur. -** ^The rollback callback is not invoked if a transaction is -** automatically rolled back because the database connection is closed. -** -** See also the [sqlite3_update_hook()] interface. -*/ -SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); -SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); - -/* -** CAPI3REF: Data Change Notification Callbacks -** -** ^The sqlite3_update_hook() interface registers a callback function -** with the [database connection] identified by the first argument -** to be invoked whenever a row is updated, inserted or deleted. -** ^Any callback set by a previous call to this function -** for the same database connection is overridden. -** -** ^The second argument is a pointer to the function to invoke when a -** row is updated, inserted or deleted. -** ^The first argument to the callback is a copy of the third argument -** to sqlite3_update_hook(). -** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], -** or [SQLITE_UPDATE], depending on the operation that caused the callback -** to be invoked. -** ^The third and fourth arguments to the callback contain pointers to the -** database and table name containing the affected row. -** ^The final callback parameter is the [rowid] of the row. -** ^In the case of an update, this is the [rowid] after the update takes place. -** -** ^(The update hook is not invoked when internal system tables are -** modified (i.e. sqlite_master and sqlite_sequence).)^ -** -** ^In the current implementation, the update hook -** is not invoked when duplication rows are deleted because of an -** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook -** invoked when rows are deleted using the [truncate optimization]. -** The exceptions defined in this paragraph might change in a future -** release of SQLite. -** -** The update hook implementation must not do anything that will modify -** the database connection that invoked the update hook. Any actions -** to modify the database connection must be deferred until after the -** completion of the [sqlite3_step()] call that triggered the update hook. -** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their -** database connections for the meaning of "modify" in this paragraph. -** -** ^The sqlite3_update_hook(D,C,P) function -** returns the P argument from the previous call -** on the same [database connection] D, or NULL for -** the first call on D. -** -** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] -** interfaces. -*/ -SQLITE_API void *sqlite3_update_hook( - sqlite3*, - void(*)(void *,int ,char const *,char const *,sqlite3_int64), - void* -); - -/* -** CAPI3REF: Enable Or Disable Shared Pager Cache -** -** ^(This routine enables or disables the sharing of the database cache -** and schema data structures between [database connection | connections] -** to the same database. Sharing is enabled if the argument is true -** and disabled if the argument is false.)^ -** -** ^Cache sharing is enabled and disabled for an entire process. -** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, -** sharing was enabled or disabled for each thread separately. -** -** ^(The cache sharing mode set by this interface effects all subsequent -** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. -** Existing database connections continue use the sharing mode -** that was in effect at the time they were opened.)^ -** -** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled -** successfully. An [error code] is returned otherwise.)^ -** -** ^Shared cache is disabled by default. But this might change in -** future releases of SQLite. Applications that care about shared -** cache setting should set it explicitly. -** -** This interface is threadsafe on processors where writing a -** 32-bit integer is atomic. -** -** See Also: [SQLite Shared-Cache Mode] -*/ -SQLITE_API int sqlite3_enable_shared_cache(int); - -/* -** CAPI3REF: Attempt To Free Heap Memory -** -** ^The sqlite3_release_memory() interface attempts to free N bytes -** of heap memory by deallocating non-essential memory allocations -** held by the database library. Memory used to cache database -** pages to improve performance is an example of non-essential memory. -** ^sqlite3_release_memory() returns the number of bytes actually freed, -** which might be more or less than the amount requested. -** ^The sqlite3_release_memory() routine is a no-op returning zero -** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. -** -** See also: [sqlite3_db_release_memory()] -*/ -SQLITE_API int sqlite3_release_memory(int); - -/* -** CAPI3REF: Free Memory Used By A Database Connection -** -** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap -** memory as possible from database connection D. Unlike the -** [sqlite3_release_memory()] interface, this interface is effect even -** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is -** omitted. -** -** See also: [sqlite3_release_memory()] -*/ -SQLITE_API int sqlite3_db_release_memory(sqlite3*); - -/* -** CAPI3REF: Impose A Limit On Heap Size -** -** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the -** soft limit on the amount of heap memory that may be allocated by SQLite. -** ^SQLite strives to keep heap memory utilization below the soft heap -** limit by reducing the number of pages held in the page cache -** as heap memory usages approaches the limit. -** ^The soft heap limit is "soft" because even though SQLite strives to stay -** below the limit, it will exceed the limit rather than generate -** an [SQLITE_NOMEM] error. In other words, the soft heap limit -** is advisory only. -** -** ^The return value from sqlite3_soft_heap_limit64() is the size of -** the soft heap limit prior to the call, or negative in the case of an -** error. ^If the argument N is negative -** then no change is made to the soft heap limit. Hence, the current -** size of the soft heap limit can be determined by invoking -** sqlite3_soft_heap_limit64() with a negative argument. -** -** ^If the argument N is zero then the soft heap limit is disabled. -** -** ^(The soft heap limit is not enforced in the current implementation -** if one or more of following conditions are true: -** -**
    -**
  • The soft heap limit is set to zero. -**
  • Memory accounting is disabled using a combination of the -** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and -** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. -**
  • An alternative page cache implementation is specified using -** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). -**
  • The page cache allocates from its own memory pool supplied -** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than -** from the heap. -**
)^ -** -** Beginning with SQLite version 3.7.3, the soft heap limit is enforced -** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] -** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], -** the soft heap limit is enforced on every memory allocation. Without -** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced -** when memory is allocated by the page cache. Testing suggests that because -** the page cache is the predominate memory user in SQLite, most -** applications will achieve adequate soft heap limit enforcement without -** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. -** -** The circumstances under which SQLite will enforce the soft heap limit may -** changes in future releases of SQLite. -*/ -SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); - -/* -** CAPI3REF: Deprecated Soft Heap Limit Interface -** DEPRECATED -** -** This is a deprecated version of the [sqlite3_soft_heap_limit64()] -** interface. This routine is provided for historical compatibility -** only. All new applications should use the -** [sqlite3_soft_heap_limit64()] interface rather than this one. -*/ -SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); - - -/* -** CAPI3REF: Extract Metadata About A Column Of A Table -** -** ^This routine returns metadata about a specific column of a specific -** database table accessible using the [database connection] handle -** passed as the first function argument. -** -** ^The column is identified by the second, third and fourth parameters to -** this function. ^The second parameter is either the name of the database -** (i.e. "main", "temp", or an attached database) containing the specified -** table or NULL. ^If it is NULL, then all attached databases are searched -** for the table using the same algorithm used by the database engine to -** resolve unqualified table references. -** -** ^The third and fourth parameters to this function are the table and column -** name of the desired column, respectively. Neither of these parameters -** may be NULL. -** -** ^Metadata is returned by writing to the memory locations passed as the 5th -** and subsequent parameters to this function. ^Any of these arguments may be -** NULL, in which case the corresponding element of metadata is omitted. -** -** ^(
-** -**
Parameter Output
Type
Description -** -**
5th const char* Data type -**
6th const char* Name of default collation sequence -**
7th int True if column has a NOT NULL constraint -**
8th int True if column is part of the PRIMARY KEY -**
9th int True if column is [AUTOINCREMENT] -**
-**
)^ -** -** ^The memory pointed to by the character pointers returned for the -** declaration type and collation sequence is valid only until the next -** call to any SQLite API function. -** -** ^If the specified table is actually a view, an [error code] is returned. -** -** ^If the specified column is "rowid", "oid" or "_rowid_" and an -** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output -** parameters are set for the explicitly declared column. ^(If there is no -** explicitly declared [INTEGER PRIMARY KEY] column, then the output -** parameters are set as follows: -** -**
-**     data type: "INTEGER"
-**     collation sequence: "BINARY"
-**     not null: 0
-**     primary key: 1
-**     auto increment: 0
-** 
)^ -** -** ^(This function may load one or more schemas from database files. If an -** error occurs during this process, or if the requested table or column -** cannot be found, an [error code] is returned and an error message left -** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ -** -** ^This API is only available if the library was compiled with the -** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. -*/ -SQLITE_API int sqlite3_table_column_metadata( - sqlite3 *db, /* Connection handle */ - const char *zDbName, /* Database name or NULL */ - const char *zTableName, /* Table name */ - const char *zColumnName, /* Column name */ - char const **pzDataType, /* OUTPUT: Declared data type */ - char const **pzCollSeq, /* OUTPUT: Collation sequence name */ - int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ - int *pPrimaryKey, /* OUTPUT: True if column part of PK */ - int *pAutoinc /* OUTPUT: True if column is auto-increment */ -); - -/* -** CAPI3REF: Load An Extension -** -** ^This interface loads an SQLite extension library from the named file. -** -** ^The sqlite3_load_extension() interface attempts to load an -** [SQLite extension] library contained in the file zFile. If -** the file cannot be loaded directly, attempts are made to load -** with various operating-system specific extensions added. -** So for example, if "samplelib" cannot be loaded, then names like -** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might -** be tried also. -** -** ^The entry point is zProc. -** ^(zProc may be 0, in which case SQLite will try to come up with an -** entry point name on its own. It first tries "sqlite3_extension_init". -** If that does not work, it constructs a name "sqlite3_X_init" where the -** X is consists of the lower-case equivalent of all ASCII alphabetic -** characters in the filename from the last "/" to the first following -** "." and omitting any initial "lib".)^ -** ^The sqlite3_load_extension() interface returns -** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. -** ^If an error occurs and pzErrMsg is not 0, then the -** [sqlite3_load_extension()] interface shall attempt to -** fill *pzErrMsg with error message text stored in memory -** obtained from [sqlite3_malloc()]. The calling function -** should free this memory by calling [sqlite3_free()]. -** -** ^Extension loading must be enabled using -** [sqlite3_enable_load_extension()] prior to calling this API, -** otherwise an error will be returned. -** -** See also the [load_extension() SQL function]. -*/ -SQLITE_API int sqlite3_load_extension( - sqlite3 *db, /* Load the extension into this database connection */ - const char *zFile, /* Name of the shared library containing extension */ - const char *zProc, /* Entry point. Derived from zFile if 0 */ - char **pzErrMsg /* Put error message here if not 0 */ -); - -/* -** CAPI3REF: Enable Or Disable Extension Loading -** -** ^So as not to open security holes in older applications that are -** unprepared to deal with [extension loading], and as a means of disabling -** [extension loading] while evaluating user-entered SQL, the following API -** is provided to turn the [sqlite3_load_extension()] mechanism on and off. -** -** ^Extension loading is off by default. -** ^Call the sqlite3_enable_load_extension() routine with onoff==1 -** to turn extension loading on and call it with onoff==0 to turn -** it back off again. -*/ -SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); - -/* -** CAPI3REF: Automatically Load Statically Linked Extensions -** -** ^This interface causes the xEntryPoint() function to be invoked for -** each new [database connection] that is created. The idea here is that -** xEntryPoint() is the entry point for a statically linked [SQLite extension] -** that is to be automatically loaded into all new database connections. -** -** ^(Even though the function prototype shows that xEntryPoint() takes -** no arguments and returns void, SQLite invokes xEntryPoint() with three -** arguments and expects and integer result as if the signature of the -** entry point where as follows: -** -**
-**    int xEntryPoint(
-**      sqlite3 *db,
-**      const char **pzErrMsg,
-**      const struct sqlite3_api_routines *pThunk
-**    );
-** 
)^ -** -** If the xEntryPoint routine encounters an error, it should make *pzErrMsg -** point to an appropriate error message (obtained from [sqlite3_mprintf()]) -** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg -** is NULL before calling the xEntryPoint(). ^SQLite will invoke -** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any -** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], -** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. -** -** ^Calling sqlite3_auto_extension(X) with an entry point X that is already -** on the list of automatic extensions is a harmless no-op. ^No entry point -** will be called more than once for each database connection that is opened. -** -** See also: [sqlite3_reset_auto_extension()]. -*/ -SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); - -/* -** CAPI3REF: Reset Automatic Extension Loading -** -** ^This interface disables all automatic extensions previously -** registered using [sqlite3_auto_extension()]. -*/ -SQLITE_API void sqlite3_reset_auto_extension(void); - -/* -** The interface to the virtual-table mechanism is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** Structures used by the virtual table interface -*/ -typedef struct sqlite3_vtab sqlite3_vtab; -typedef struct sqlite3_index_info sqlite3_index_info; -typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; -typedef struct sqlite3_module sqlite3_module; - -/* -** CAPI3REF: Virtual Table Object -** KEYWORDS: sqlite3_module {virtual table module} -** -** This structure, sometimes called a "virtual table module", -** defines the implementation of a [virtual tables]. -** This structure consists mostly of methods for the module. -** -** ^A virtual table module is created by filling in a persistent -** instance of this structure and passing a pointer to that instance -** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. -** ^The registration remains valid until it is replaced by a different -** module or until the [database connection] closes. The content -** of this structure must not change while it is registered with -** any database connection. -*/ -struct sqlite3_module { - int iVersion; - int (*xCreate)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xConnect)(sqlite3*, void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVTab, char**); - int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); - int (*xDisconnect)(sqlite3_vtab *pVTab); - int (*xDestroy)(sqlite3_vtab *pVTab); - int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); - int (*xClose)(sqlite3_vtab_cursor*); - int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, - int argc, sqlite3_value **argv); - int (*xNext)(sqlite3_vtab_cursor*); - int (*xEof)(sqlite3_vtab_cursor*); - int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); - int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); - int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); - int (*xBegin)(sqlite3_vtab *pVTab); - int (*xSync)(sqlite3_vtab *pVTab); - int (*xCommit)(sqlite3_vtab *pVTab); - int (*xRollback)(sqlite3_vtab *pVTab); - int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg); - int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); - /* The methods above are in version 1 of the sqlite_module object. Those - ** below are for version 2 and greater. */ - int (*xSavepoint)(sqlite3_vtab *pVTab, int); - int (*xRelease)(sqlite3_vtab *pVTab, int); - int (*xRollbackTo)(sqlite3_vtab *pVTab, int); -}; - -/* -** CAPI3REF: Virtual Table Indexing Information -** KEYWORDS: sqlite3_index_info -** -** The sqlite3_index_info structure and its substructures is used as part -** of the [virtual table] interface to -** pass information into and receive the reply from the [xBestIndex] -** method of a [virtual table module]. The fields under **Inputs** are the -** inputs to xBestIndex and are read-only. xBestIndex inserts its -** results into the **Outputs** fields. -** -** ^(The aConstraint[] array records WHERE clause constraints of the form: -** -**
column OP expr
-** -** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is -** stored in aConstraint[].op using one of the -** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ -** ^(The index of the column is stored in -** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the -** expr on the right-hand side can be evaluated (and thus the constraint -** is usable) and false if it cannot.)^ -** -** ^The optimizer automatically inverts terms of the form "expr OP column" -** and makes other simplifications to the WHERE clause in an attempt to -** get as many WHERE clause terms into the form shown above as possible. -** ^The aConstraint[] array only reports WHERE clause terms that are -** relevant to the particular virtual table being queried. -** -** ^Information about the ORDER BY clause is stored in aOrderBy[]. -** ^Each term of aOrderBy records a column of the ORDER BY clause. -** -** The [xBestIndex] method must fill aConstraintUsage[] with information -** about what parameters to pass to xFilter. ^If argvIndex>0 then -** the right-hand side of the corresponding aConstraint[] is evaluated -** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit -** is true, then the constraint is assumed to be fully handled by the -** virtual table and is not checked again by SQLite.)^ -** -** ^The idxNum and idxPtr values are recorded and passed into the -** [xFilter] method. -** ^[sqlite3_free()] is used to free idxPtr if and only if -** needToFreeIdxPtr is true. -** -** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in -** the correct order to satisfy the ORDER BY clause so that no separate -** sorting step is required. -** -** ^The estimatedCost value is an estimate of the cost of doing the -** particular lookup. A full scan of a table with N entries should have -** a cost of N. A binary search of a table of N entries should have a -** cost of approximately log(N). -*/ -struct sqlite3_index_info { - /* Inputs */ - int nConstraint; /* Number of entries in aConstraint */ - struct sqlite3_index_constraint { - int iColumn; /* Column on left-hand side of constraint */ - unsigned char op; /* Constraint operator */ - unsigned char usable; /* True if this constraint is usable */ - int iTermOffset; /* Used internally - xBestIndex should ignore */ - } *aConstraint; /* Table of WHERE clause constraints */ - int nOrderBy; /* Number of terms in the ORDER BY clause */ - struct sqlite3_index_orderby { - int iColumn; /* Column number */ - unsigned char desc; /* True for DESC. False for ASC. */ - } *aOrderBy; /* The ORDER BY clause */ - /* Outputs */ - struct sqlite3_index_constraint_usage { - int argvIndex; /* if >0, constraint is part of argv to xFilter */ - unsigned char omit; /* Do not code a test for this constraint */ - } *aConstraintUsage; - int idxNum; /* Number used to identify the index */ - char *idxStr; /* String, possibly obtained from sqlite3_malloc */ - int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ - int orderByConsumed; /* True if output is already ordered */ - double estimatedCost; /* Estimated cost of using this index */ -}; - -/* -** CAPI3REF: Virtual Table Constraint Operator Codes -** -** These macros defined the allowed values for the -** [sqlite3_index_info].aConstraint[].op field. Each value represents -** an operator that is part of a constraint term in the wHERE clause of -** a query that uses a [virtual table]. -*/ -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 - -/* -** CAPI3REF: Register A Virtual Table Implementation -** -** ^These routines are used to register a new [virtual table module] name. -** ^Module names must be registered before -** creating a new [virtual table] using the module and before using a -** preexisting [virtual table] for the module. -** -** ^The module name is registered on the [database connection] specified -** by the first parameter. ^The name of the module is given by the -** second parameter. ^The third parameter is a pointer to -** the implementation of the [virtual table module]. ^The fourth -** parameter is an arbitrary client data pointer that is passed through -** into the [xCreate] and [xConnect] methods of the virtual table module -** when a new virtual table is be being created or reinitialized. -** -** ^The sqlite3_create_module_v2() interface has a fifth parameter which -** is a pointer to a destructor for the pClientData. ^SQLite will -** invoke the destructor function (if it is not NULL) when SQLite -** no longer needs the pClientData pointer. ^The destructor will also -** be invoked if the call to sqlite3_create_module_v2() fails. -** ^The sqlite3_create_module() -** interface is equivalent to sqlite3_create_module_v2() with a NULL -** destructor. -*/ -SQLITE_API int sqlite3_create_module( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *p, /* Methods for the module */ - void *pClientData /* Client data for xCreate/xConnect */ -); -SQLITE_API int sqlite3_create_module_v2( - sqlite3 *db, /* SQLite connection to register module with */ - const char *zName, /* Name of the module */ - const sqlite3_module *p, /* Methods for the module */ - void *pClientData, /* Client data for xCreate/xConnect */ - void(*xDestroy)(void*) /* Module destructor function */ -); - -/* -** CAPI3REF: Virtual Table Instance Object -** KEYWORDS: sqlite3_vtab -** -** Every [virtual table module] implementation uses a subclass -** of this object to describe a particular instance -** of the [virtual table]. Each subclass will -** be tailored to the specific needs of the module implementation. -** The purpose of this superclass is to define certain fields that are -** common to all module implementations. -** -** ^Virtual tables methods can set an error message by assigning a -** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should -** take care that any prior string is freed by a call to [sqlite3_free()] -** prior to assigning a new string to zErrMsg. ^After the error message -** is delivered up to the client application, the string will be automatically -** freed by sqlite3_free() and the zErrMsg field will be zeroed. -*/ -struct sqlite3_vtab { - const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* NO LONGER USED */ - char *zErrMsg; /* Error message from sqlite3_mprintf() */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** CAPI3REF: Virtual Table Cursor Object -** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} -** -** Every [virtual table module] implementation uses a subclass of the -** following structure to describe cursors that point into the -** [virtual table] and are used -** to loop through the virtual table. Cursors are created using the -** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed -** by the [sqlite3_module.xClose | xClose] method. Cursors are used -** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods -** of the module. Each module implementation will define -** the content of a cursor structure to suit its own needs. -** -** This superclass exists in order to define fields of the cursor that -** are common to all implementations. -*/ -struct sqlite3_vtab_cursor { - sqlite3_vtab *pVtab; /* Virtual table of this cursor */ - /* Virtual table implementations will typically add additional fields */ -}; - -/* -** CAPI3REF: Declare The Schema Of A Virtual Table -** -** ^The [xCreate] and [xConnect] methods of a -** [virtual table module] call this interface -** to declare the format (the names and datatypes of the columns) of -** the virtual tables they implement. -*/ -SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); - -/* -** CAPI3REF: Overload A Function For A Virtual Table -** -** ^(Virtual tables can provide alternative implementations of functions -** using the [xFindFunction] method of the [virtual table module]. -** But global versions of those functions -** must exist in order to be overloaded.)^ -** -** ^(This API makes sure a global version of a function with a particular -** name and number of parameters exists. If no such function exists -** before this API is called, a new function is created.)^ ^The implementation -** of the new function always causes an exception to be thrown. So -** the new function is not good for anything by itself. Its only -** purpose is to be a placeholder function that can be overloaded -** by a [virtual table]. -*/ -SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); - -/* -** The interface to the virtual-table mechanism defined above (back up -** to a comment remarkably similar to this one) is currently considered -** to be experimental. The interface might change in incompatible ways. -** If this is a problem for you, do not use the interface at this time. -** -** When the virtual-table mechanism stabilizes, we will declare the -** interface fixed, support it indefinitely, and remove this comment. -*/ - -/* -** CAPI3REF: A Handle To An Open BLOB -** KEYWORDS: {BLOB handle} {BLOB handles} -** -** An instance of this object represents an open BLOB on which -** [sqlite3_blob_open | incremental BLOB I/O] can be performed. -** ^Objects of this type are created by [sqlite3_blob_open()] -** and destroyed by [sqlite3_blob_close()]. -** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces -** can be used to read or write small subsections of the BLOB. -** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes. -*/ -typedef struct sqlite3_blob sqlite3_blob; - -/* -** CAPI3REF: Open A BLOB For Incremental I/O -** -** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located -** in row iRow, column zColumn, table zTable in database zDb; -** in other words, the same BLOB that would be selected by: -** -**
-**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
-** 
)^ -** -** ^If the flags parameter is non-zero, then the BLOB is opened for read -** and write access. ^If it is zero, the BLOB is opened for read access. -** ^It is not possible to open a column that is part of an index or primary -** key for writing. ^If [foreign key constraints] are enabled, it is -** not possible to open a column that is part of a [child key] for writing. -** -** ^Note that the database name is not the filename that contains -** the database but rather the symbolic name of the database that -** appears after the AS keyword when the database is connected using [ATTACH]. -** ^For the main database file, the database name is "main". -** ^For TEMP tables, the database name is "temp". -** -** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written -** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set -** to be a null pointer.)^ -** ^This function sets the [database connection] error code and message -** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related -** functions. ^Note that the *ppBlob variable is always initialized in a -** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob -** regardless of the success or failure of this routine. -** -** ^(If the row that a BLOB handle points to is modified by an -** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects -** then the BLOB handle is marked as "expired". -** This is true if any column of the row is changed, even a column -** other than the one the BLOB handle is open on.)^ -** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for -** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. -** ^(Changes written into a BLOB prior to the BLOB expiring are not -** rolled back by the expiration of the BLOB. Such changes will eventually -** commit if the transaction continues to completion.)^ -** -** ^Use the [sqlite3_blob_bytes()] interface to determine the size of -** the opened blob. ^The size of a blob may not be changed by this -** interface. Use the [UPDATE] SQL command to change the size of a -** blob. -** -** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces -** and the built-in [zeroblob] SQL function can be used, if desired, -** to create an empty, zero-filled blob in which to read or write using -** this interface. -** -** To avoid a resource leak, every open [BLOB handle] should eventually -** be released by a call to [sqlite3_blob_close()]. -*/ -SQLITE_API int sqlite3_blob_open( - sqlite3*, - const char *zDb, - const char *zTable, - const char *zColumn, - sqlite3_int64 iRow, - int flags, - sqlite3_blob **ppBlob -); - -/* -** CAPI3REF: Move a BLOB Handle to a New Row -** -** ^This function is used to move an existing blob handle so that it points -** to a different row of the same database table. ^The new row is identified -** by the rowid value passed as the second argument. Only the row can be -** changed. ^The database, table and column on which the blob handle is open -** remain the same. Moving an existing blob handle to a new row can be -** faster than closing the existing handle and opening a new one. -** -** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - -** it must exist and there must be either a blob or text value stored in -** the nominated column.)^ ^If the new row is not present in the table, or if -** it does not contain a blob or text value, or if another error occurs, an -** SQLite error code is returned and the blob handle is considered aborted. -** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or -** [sqlite3_blob_reopen()] on an aborted blob handle immediately return -** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle -** always returns zero. -** -** ^This function sets the database handle error code and message. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); - -/* -** CAPI3REF: Close A BLOB Handle -** -** ^Closes an open [BLOB handle]. -** -** ^Closing a BLOB shall cause the current transaction to commit -** if there are no other BLOBs, no pending prepared statements, and the -** database connection is in [autocommit mode]. -** ^If any writes were made to the BLOB, they might be held in cache -** until the close operation if they will fit. -** -** ^(Closing the BLOB often forces the changes -** out to disk and so if any I/O errors occur, they will likely occur -** at the time when the BLOB is closed. Any errors that occur during -** closing are reported as a non-zero return value.)^ -** -** ^(The BLOB is closed unconditionally. Even if this routine returns -** an error code, the BLOB is still closed.)^ -** -** ^Calling this routine with a null pointer (such as would be returned -** by a failed call to [sqlite3_blob_open()]) is a harmless no-op. -*/ -SQLITE_API int sqlite3_blob_close(sqlite3_blob *); - -/* -** CAPI3REF: Return The Size Of An Open BLOB -** -** ^Returns the size in bytes of the BLOB accessible via the -** successfully opened [BLOB handle] in its only argument. ^The -** incremental blob I/O routines can only read or overwriting existing -** blob content; they cannot change the size of a blob. -** -** This routine only works on a [BLOB handle] which has been created -** by a prior successful call to [sqlite3_blob_open()] and which has not -** been closed by [sqlite3_blob_close()]. Passing any other pointer in -** to this routine results in undefined and probably undesirable behavior. -*/ -SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); - -/* -** CAPI3REF: Read Data From A BLOB Incrementally -** -** ^(This function is used to read data from an open [BLOB handle] into a -** caller-supplied buffer. N bytes of data are copied into buffer Z -** from the open BLOB, starting at offset iOffset.)^ -** -** ^If offset iOffset is less than N bytes from the end of the BLOB, -** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is -** less than zero, [SQLITE_ERROR] is returned and no data is read. -** ^The size of the blob (and hence the maximum value of N+iOffset) -** can be determined using the [sqlite3_blob_bytes()] interface. -** -** ^An attempt to read from an expired [BLOB handle] fails with an -** error code of [SQLITE_ABORT]. -** -** ^(On success, sqlite3_blob_read() returns SQLITE_OK. -** Otherwise, an [error code] or an [extended error code] is returned.)^ -** -** This routine only works on a [BLOB handle] which has been created -** by a prior successful call to [sqlite3_blob_open()] and which has not -** been closed by [sqlite3_blob_close()]. Passing any other pointer in -** to this routine results in undefined and probably undesirable behavior. -** -** See also: [sqlite3_blob_write()]. -*/ -SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); - -/* -** CAPI3REF: Write Data Into A BLOB Incrementally -** -** ^This function is used to write data into an open [BLOB handle] from a -** caller-supplied buffer. ^N bytes of data are copied from the buffer Z -** into the open BLOB, starting at offset iOffset. -** -** ^If the [BLOB handle] passed as the first argument was not opened for -** writing (the flags parameter to [sqlite3_blob_open()] was zero), -** this function returns [SQLITE_READONLY]. -** -** ^This function may only modify the contents of the BLOB; it is -** not possible to increase the size of a BLOB using this API. -** ^If offset iOffset is less than N bytes from the end of the BLOB, -** [SQLITE_ERROR] is returned and no data is written. ^If N is -** less than zero [SQLITE_ERROR] is returned and no data is written. -** The size of the BLOB (and hence the maximum value of N+iOffset) -** can be determined using the [sqlite3_blob_bytes()] interface. -** -** ^An attempt to write to an expired [BLOB handle] fails with an -** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred -** before the [BLOB handle] expired are not rolled back by the -** expiration of the handle, though of course those changes might -** have been overwritten by the statement that expired the BLOB handle -** or by other independent statements. -** -** ^(On success, sqlite3_blob_write() returns SQLITE_OK. -** Otherwise, an [error code] or an [extended error code] is returned.)^ -** -** This routine only works on a [BLOB handle] which has been created -** by a prior successful call to [sqlite3_blob_open()] and which has not -** been closed by [sqlite3_blob_close()]. Passing any other pointer in -** to this routine results in undefined and probably undesirable behavior. -** -** See also: [sqlite3_blob_read()]. -*/ -SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); - -/* -** CAPI3REF: Virtual File System Objects -** -** A virtual filesystem (VFS) is an [sqlite3_vfs] object -** that SQLite uses to interact -** with the underlying operating system. Most SQLite builds come with a -** single default VFS that is appropriate for the host computer. -** New VFSes can be registered and existing VFSes can be unregistered. -** The following interfaces are provided. -** -** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. -** ^Names are case sensitive. -** ^Names are zero-terminated UTF-8 strings. -** ^If there is no match, a NULL pointer is returned. -** ^If zVfsName is NULL then the default VFS is returned. -** -** ^New VFSes are registered with sqlite3_vfs_register(). -** ^Each new VFS becomes the default VFS if the makeDflt flag is set. -** ^The same VFS can be registered multiple times without injury. -** ^To make an existing VFS into the default VFS, register it again -** with the makeDflt flag set. If two different VFSes with the -** same name are registered, the behavior is undefined. If a -** VFS is registered with a name that is NULL or an empty string, -** then the behavior is undefined. -** -** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. -** ^(If the default VFS is unregistered, another VFS is chosen as -** the default. The choice for the new VFS is arbitrary.)^ -*/ -SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); -SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); -SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); - -/* -** CAPI3REF: Mutexes -** -** The SQLite core uses these routines for thread -** synchronization. Though they are intended for internal -** use by SQLite, code that links against SQLite is -** permitted to use any of these routines. -** -** The SQLite source code contains multiple implementations -** of these mutex routines. An appropriate implementation -** is selected automatically at compile-time. ^(The following -** implementations are available in the SQLite core: -** -**
    -**
  • SQLITE_MUTEX_PTHREADS -**
  • SQLITE_MUTEX_W32 -**
  • SQLITE_MUTEX_NOOP -**
)^ -** -** ^The SQLITE_MUTEX_NOOP implementation is a set of routines -** that does no real locking and is appropriate for use in -** a single-threaded application. ^The SQLITE_MUTEX_PTHREADS and -** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix -** and Windows. -** -** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor -** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex -** implementation is included with the library. In this case the -** application must supply a custom mutex implementation using the -** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function -** before calling sqlite3_initialize() or any other public sqlite3_ -** function that calls sqlite3_initialize().)^ -** -** ^The sqlite3_mutex_alloc() routine allocates a new -** mutex and returns a pointer to it. ^If it returns NULL -** that means that a mutex could not be allocated. ^SQLite -** will unwind its stack and return an error. ^(The argument -** to sqlite3_mutex_alloc() is one of these integer constants: -** -**
    -**
  • SQLITE_MUTEX_FAST -**
  • SQLITE_MUTEX_RECURSIVE -**
  • SQLITE_MUTEX_STATIC_MASTER -**
  • SQLITE_MUTEX_STATIC_MEM -**
  • SQLITE_MUTEX_STATIC_MEM2 -**
  • SQLITE_MUTEX_STATIC_PRNG -**
  • SQLITE_MUTEX_STATIC_LRU -**
  • SQLITE_MUTEX_STATIC_LRU2 -**
)^ -** -** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) -** cause sqlite3_mutex_alloc() to create -** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE -** is used but not necessarily so when SQLITE_MUTEX_FAST is used. -** The mutex implementation does not need to make a distinction -** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does -** not want to. ^SQLite will only request a recursive mutex in -** cases where it really needs one. ^If a faster non-recursive mutex -** implementation is available on the host platform, the mutex subsystem -** might return such a mutex in response to SQLITE_MUTEX_FAST. -** -** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other -** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return -** a pointer to a static preexisting mutex. ^Six static mutexes are -** used by the current version of SQLite. Future versions of SQLite -** may add additional static mutexes. Static mutexes are for internal -** use by SQLite only. Applications that use SQLite mutexes should -** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or -** SQLITE_MUTEX_RECURSIVE. -** -** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST -** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() -** returns a different mutex on every call. ^But for the static -** mutex types, the same mutex is returned on every call that has -** the same type number. -** -** ^The sqlite3_mutex_free() routine deallocates a previously -** allocated dynamic mutex. ^SQLite is careful to deallocate every -** dynamic mutex that it allocates. The dynamic mutexes must not be in -** use when they are deallocated. Attempting to deallocate a static -** mutex results in undefined behavior. ^SQLite never deallocates -** a static mutex. -** -** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt -** to enter a mutex. ^If another thread is already within the mutex, -** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return -** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] -** upon successful entry. ^(Mutexes created using -** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. -** In such cases the, -** mutex must be exited an equal number of times before another thread -** can enter.)^ ^(If the same thread tries to enter any other -** kind of mutex more than once, the behavior is undefined. -** SQLite will never exhibit -** such behavior in its own use of mutexes.)^ -** -** ^(Some systems (for example, Windows 95) do not support the operation -** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() -** will always return SQLITE_BUSY. The SQLite core only ever uses -** sqlite3_mutex_try() as an optimization so this is acceptable behavior.)^ -** -** ^The sqlite3_mutex_leave() routine exits a mutex that was -** previously entered by the same thread. ^(The behavior -** is undefined if the mutex is not currently entered by the -** calling thread or is not currently allocated. SQLite will -** never do either.)^ -** -** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or -** sqlite3_mutex_leave() is a NULL pointer, then all three routines -** behave as no-ops. -** -** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. -*/ -SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); -SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); -SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); -SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); -SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); - -/* -** CAPI3REF: Mutex Methods Object -** -** An instance of this structure defines the low-level routines -** used to allocate and use mutexes. -** -** Usually, the default mutex implementations provided by SQLite are -** sufficient, however the user has the option of substituting a custom -** implementation for specialized deployments or systems for which SQLite -** does not provide a suitable implementation. In this case, the user -** creates and populates an instance of this structure to pass -** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. -** Additionally, an instance of this structure can be used as an -** output variable when querying the system for the current mutex -** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. -** -** ^The xMutexInit method defined by this structure is invoked as -** part of system initialization by the sqlite3_initialize() function. -** ^The xMutexInit routine is called by SQLite exactly once for each -** effective call to [sqlite3_initialize()]. -** -** ^The xMutexEnd method defined by this structure is invoked as -** part of system shutdown by the sqlite3_shutdown() function. The -** implementation of this method is expected to release all outstanding -** resources obtained by the mutex methods implementation, especially -** those obtained by the xMutexInit method. ^The xMutexEnd() -** interface is invoked exactly once for each call to [sqlite3_shutdown()]. -** -** ^(The remaining seven methods defined by this structure (xMutexAlloc, -** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and -** xMutexNotheld) implement the following interfaces (respectively): -** -**
    -**
  • [sqlite3_mutex_alloc()]
  • -**
  • [sqlite3_mutex_free()]
  • -**
  • [sqlite3_mutex_enter()]
  • -**
  • [sqlite3_mutex_try()]
  • -**
  • [sqlite3_mutex_leave()]
  • -**
  • [sqlite3_mutex_held()]
  • -**
  • [sqlite3_mutex_notheld()]
  • -**
)^ -** -** The only difference is that the public sqlite3_XXX functions enumerated -** above silently ignore any invocations that pass a NULL pointer instead -** of a valid mutex handle. The implementations of the methods defined -** by this structure are not required to handle this case, the results -** of passing a NULL pointer instead of a valid mutex handle are undefined -** (i.e. it is acceptable to provide an implementation that segfaults if -** it is passed a NULL pointer). -** -** The xMutexInit() method must be threadsafe. ^It must be harmless to -** invoke xMutexInit() multiple times within the same process and without -** intervening calls to xMutexEnd(). Second and subsequent calls to -** xMutexInit() must be no-ops. -** -** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] -** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory -** allocation for a static mutex. ^However xMutexAlloc() may use SQLite -** memory allocation for a fast or recursive mutex. -** -** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is -** called, but only if the prior call to xMutexInit returned SQLITE_OK. -** If xMutexInit fails in any way, it is expected to clean up after itself -** prior to returning. -*/ -typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; -struct sqlite3_mutex_methods { - int (*xMutexInit)(void); - int (*xMutexEnd)(void); - sqlite3_mutex *(*xMutexAlloc)(int); - void (*xMutexFree)(sqlite3_mutex *); - void (*xMutexEnter)(sqlite3_mutex *); - int (*xMutexTry)(sqlite3_mutex *); - void (*xMutexLeave)(sqlite3_mutex *); - int (*xMutexHeld)(sqlite3_mutex *); - int (*xMutexNotheld)(sqlite3_mutex *); -}; - -/* -** CAPI3REF: Mutex Verification Routines -** -** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines -** are intended for use inside assert() statements. ^The SQLite core -** never uses these routines except inside an assert() and applications -** are advised to follow the lead of the core. ^The SQLite core only -** provides implementations for these routines when it is compiled -** with the SQLITE_DEBUG flag. ^External mutex implementations -** are only required to provide these routines if SQLITE_DEBUG is -** defined and if NDEBUG is not defined. -** -** ^These routines should return true if the mutex in their argument -** is held or not held, respectively, by the calling thread. -** -** ^The implementation is not required to provide versions of these -** routines that actually work. If the implementation does not provide working -** versions of these routines, it should at least provide stubs that always -** return true so that one does not get spurious assertion failures. -** -** ^If the argument to sqlite3_mutex_held() is a NULL pointer then -** the routine should return 1. This seems counter-intuitive since -** clearly the mutex cannot be held if it does not exist. But -** the reason the mutex does not exist is because the build is not -** using mutexes. And we do not want the assert() containing the -** call to sqlite3_mutex_held() to fail, so a non-zero return is -** the appropriate thing to do. ^The sqlite3_mutex_notheld() -** interface should also return 1 when given a NULL pointer. -*/ -#ifndef NDEBUG -SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); -SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); -#endif - -/* -** CAPI3REF: Mutex Types -** -** The [sqlite3_mutex_alloc()] interface takes a single argument -** which is one of these integer constants. -** -** The set of static mutexes may change from one SQLite release to the -** next. Applications that override the built-in mutex logic must be -** prepared to accommodate additional static mutexes. -*/ -#define SQLITE_MUTEX_FAST 0 -#define SQLITE_MUTEX_RECURSIVE 1 -#define SQLITE_MUTEX_STATIC_MASTER 2 -#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ -#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ -#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ -#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ -#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ -#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ -#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ - -/* -** CAPI3REF: Retrieve the mutex for a database connection -** -** ^This interface returns a pointer the [sqlite3_mutex] object that -** serializes access to the [database connection] given in the argument -** when the [threading mode] is Serialized. -** ^If the [threading mode] is Single-thread or Multi-thread then this -** routine returns a NULL pointer. -*/ -SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); - -/* -** CAPI3REF: Low-Level Control Of Database Files -** -** ^The [sqlite3_file_control()] interface makes a direct call to the -** xFileControl method for the [sqlite3_io_methods] object associated -** with a particular database identified by the second argument. ^The -** name of the database is "main" for the main database or "temp" for the -** TEMP database, or the name that appears after the AS keyword for -** databases that are added using the [ATTACH] SQL command. -** ^A NULL pointer can be used in place of "main" to refer to the -** main database file. -** ^The third and fourth parameters to this routine -** are passed directly through to the second and third parameters of -** the xFileControl method. ^The return value of the xFileControl -** method becomes the return value of this routine. -** -** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes -** a pointer to the underlying [sqlite3_file] object to be written into -** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER -** case is a short-circuit path which does not actually invoke the -** underlying sqlite3_io_methods.xFileControl method. -** -** ^If the second parameter (zDbName) does not match the name of any -** open database file, then SQLITE_ERROR is returned. ^This error -** code is not remembered and will not be recalled by [sqlite3_errcode()] -** or [sqlite3_errmsg()]. The underlying xFileControl method might -** also return SQLITE_ERROR. There is no way to distinguish between -** an incorrect zDbName and an SQLITE_ERROR return from the underlying -** xFileControl method. -** -** See also: [SQLITE_FCNTL_LOCKSTATE] -*/ -SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); - -/* -** CAPI3REF: Testing Interface -** -** ^The sqlite3_test_control() interface is used to read out internal -** state of SQLite and to inject faults into SQLite for testing -** purposes. ^The first parameter is an operation code that determines -** the number, meaning, and operation of all subsequent parameters. -** -** This interface is not for use by applications. It exists solely -** for verifying the correct operation of the SQLite library. Depending -** on how the SQLite library is compiled, this interface might not exist. -** -** The details of the operation codes, their meanings, the parameters -** they take, and what they do are all subject to change without notice. -** Unlike most of the SQLite API, this function is not guaranteed to -** operate consistently from one release to the next. -*/ -SQLITE_API int sqlite3_test_control(int op, ...); - -/* -** CAPI3REF: Testing Interface Operation Codes -** -** These constants are the valid operation code parameters used -** as the first argument to [sqlite3_test_control()]. -** -** These parameters and their meanings are subject to change -** without notice. These values are for testing purposes only. -** Applications should not use any of these parameters or the -** [sqlite3_test_control()] interface. -*/ -#define SQLITE_TESTCTRL_FIRST 5 -#define SQLITE_TESTCTRL_PRNG_SAVE 5 -#define SQLITE_TESTCTRL_PRNG_RESTORE 6 -#define SQLITE_TESTCTRL_PRNG_RESET 7 -#define SQLITE_TESTCTRL_BITVEC_TEST 8 -#define SQLITE_TESTCTRL_FAULT_INSTALL 9 -#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 -#define SQLITE_TESTCTRL_PENDING_BYTE 11 -#define SQLITE_TESTCTRL_ASSERT 12 -#define SQLITE_TESTCTRL_ALWAYS 13 -#define SQLITE_TESTCTRL_RESERVE 14 -#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 -#define SQLITE_TESTCTRL_ISKEYWORD 16 -#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 -#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 -#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 -#define SQLITE_TESTCTRL_LAST 19 - -/* -** CAPI3REF: SQLite Runtime Status -** -** ^This interface is used to retrieve runtime status information -** about the performance of SQLite, and optionally to reset various -** highwater marks. ^The first argument is an integer code for -** the specific parameter to measure. ^(Recognized integer codes -** are of the form [status parameters | SQLITE_STATUS_...].)^ -** ^The current value of the parameter is returned into *pCurrent. -** ^The highest recorded value is returned in *pHighwater. ^If the -** resetFlag is true, then the highest record value is reset after -** *pHighwater is written. ^(Some parameters do not record the highest -** value. For those parameters -** nothing is written into *pHighwater and the resetFlag is ignored.)^ -** ^(Other parameters record only the highwater mark and not the current -** value. For these latter parameters nothing is written into *pCurrent.)^ -** -** ^The sqlite3_status() routine returns SQLITE_OK on success and a -** non-zero [error code] on failure. -** -** This routine is threadsafe but is not atomic. This routine can be -** called while other threads are running the same or different SQLite -** interfaces. However the values returned in *pCurrent and -** *pHighwater reflect the status of SQLite at different points in time -** and it is possible that another thread might change the parameter -** in between the times when *pCurrent and *pHighwater are written. -** -** See also: [sqlite3_db_status()] -*/ -SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); - - -/* -** CAPI3REF: Status Parameters -** KEYWORDS: {status parameters} -** -** These integer constants designate various run-time status parameters -** that can be returned by [sqlite3_status()]. -** -**
-** [[SQLITE_STATUS_MEMORY_USED]] ^(
SQLITE_STATUS_MEMORY_USED
-**
This parameter is the current amount of memory checked out -** using [sqlite3_malloc()], either directly or indirectly. The -** figure includes calls made to [sqlite3_malloc()] by the application -** and internal memory usage by the SQLite library. Scratch memory -** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache -** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in -** this parameter. The amount returned is the sum of the allocation -** sizes as reported by the xSize method in [sqlite3_mem_methods].
)^ -** -** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
SQLITE_STATUS_MALLOC_SIZE
-**
This parameter records the largest memory allocation request -** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their -** internal equivalents). Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. -** The value written into the *pCurrent parameter is undefined.
)^ -** -** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
SQLITE_STATUS_MALLOC_COUNT
-**
This parameter records the number of separate memory allocations -** currently checked out.
)^ -** -** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
SQLITE_STATUS_PAGECACHE_USED
-**
This parameter returns the number of pages used out of the -** [pagecache memory allocator] that was configured using -** [SQLITE_CONFIG_PAGECACHE]. The -** value returned is in pages, not in bytes.
)^ -** -** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] -** ^(
SQLITE_STATUS_PAGECACHE_OVERFLOW
-**
This parameter returns the number of bytes of page cache -** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] -** buffer and where forced to overflow to [sqlite3_malloc()]. The -** returned value includes allocations that overflowed because they -** where too large (they were larger than the "sz" parameter to -** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because -** no space was left in the page cache.
)^ -** -** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
SQLITE_STATUS_PAGECACHE_SIZE
-**
This parameter records the largest memory allocation request -** handed to [pagecache memory allocator]. Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. -** The value written into the *pCurrent parameter is undefined.
)^ -** -** [[SQLITE_STATUS_SCRATCH_USED]] ^(
SQLITE_STATUS_SCRATCH_USED
-**
This parameter returns the number of allocations used out of the -** [scratch memory allocator] configured using -** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not -** in bytes. Since a single thread may only have one scratch allocation -** outstanding at time, this parameter also reports the number of threads -** using scratch memory at the same time.
)^ -** -** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
SQLITE_STATUS_SCRATCH_OVERFLOW
-**
This parameter returns the number of bytes of scratch memory -** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] -** buffer and where forced to overflow to [sqlite3_malloc()]. The values -** returned include overflows because the requested allocation was too -** larger (that is, because the requested allocation was larger than the -** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer -** slots were available. -**
)^ -** -** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(
SQLITE_STATUS_SCRATCH_SIZE
-**
This parameter records the largest memory allocation request -** handed to [scratch memory allocator]. Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. -** The value written into the *pCurrent parameter is undefined.
)^ -** -** [[SQLITE_STATUS_PARSER_STACK]] ^(
SQLITE_STATUS_PARSER_STACK
-**
This parameter records the deepest parser stack. It is only -** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
)^ -**
-** -** New status parameters may be added from time to time. -*/ -#define SQLITE_STATUS_MEMORY_USED 0 -#define SQLITE_STATUS_PAGECACHE_USED 1 -#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 -#define SQLITE_STATUS_SCRATCH_USED 3 -#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 -#define SQLITE_STATUS_MALLOC_SIZE 5 -#define SQLITE_STATUS_PARSER_STACK 6 -#define SQLITE_STATUS_PAGECACHE_SIZE 7 -#define SQLITE_STATUS_SCRATCH_SIZE 8 -#define SQLITE_STATUS_MALLOC_COUNT 9 - -/* -** CAPI3REF: Database Connection Status -** -** ^This interface is used to retrieve runtime status information -** about a single [database connection]. ^The first argument is the -** database connection object to be interrogated. ^The second argument -** is an integer constant, taken from the set of -** [SQLITE_DBSTATUS options], that -** determines the parameter to interrogate. The set of -** [SQLITE_DBSTATUS options] is likely -** to grow in future releases of SQLite. -** -** ^The current value of the requested parameter is written into *pCur -** and the highest instantaneous value is written into *pHiwtr. ^If -** the resetFlg is true, then the highest instantaneous value is -** reset back down to the current value. -** -** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a -** non-zero [error code] on failure. -** -** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. -*/ -SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); - -/* -** CAPI3REF: Status Parameters for database connections -** KEYWORDS: {SQLITE_DBSTATUS options} -** -** These constants are the available integer "verbs" that can be passed as -** the second argument to the [sqlite3_db_status()] interface. -** -** New verbs may be added in future releases of SQLite. Existing verbs -** might be discontinued. Applications should check the return code from -** [sqlite3_db_status()] to make sure that the call worked. -** The [sqlite3_db_status()] interface will return a non-zero error code -** if a discontinued or unsupported verb is invoked. -** -**
-** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
SQLITE_DBSTATUS_LOOKASIDE_USED
-**
This parameter returns the number of lookaside memory slots currently -** checked out.
)^ -** -** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
SQLITE_DBSTATUS_LOOKASIDE_HIT
-**
This parameter returns the number malloc attempts that were -** satisfied using lookaside memory. Only the high-water value is meaningful; -** the current value is always zero.)^ -** -** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] -** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
-**
This parameter returns the number malloc attempts that might have -** been satisfied using lookaside memory but failed due to the amount of -** memory requested being larger than the lookaside slot size. -** Only the high-water value is meaningful; -** the current value is always zero.)^ -** -** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] -** ^(
SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
-**
This parameter returns the number malloc attempts that might have -** been satisfied using lookaside memory but failed due to all lookaside -** memory already being in use. -** Only the high-water value is meaningful; -** the current value is always zero.)^ -** -** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
SQLITE_DBSTATUS_CACHE_USED
-**
This parameter returns the approximate number of of bytes of heap -** memory used by all pager caches associated with the database connection.)^ -** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. -** -** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
SQLITE_DBSTATUS_SCHEMA_USED
-**
This parameter returns the approximate number of of bytes of heap -** memory used to store the schema for all databases associated -** with the connection - main, temp, and any [ATTACH]-ed databases.)^ -** ^The full amount of memory used by the schemas is reported, even if the -** schema memory is shared with other database connections due to -** [shared cache mode] being enabled. -** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. -** -** [[SQLITE_DBSTATUS_STMT_USED]] ^(
SQLITE_DBSTATUS_STMT_USED
-**
This parameter returns the approximate number of of bytes of heap -** and lookaside memory used by all prepared statements associated with -** the database connection.)^ -** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. -**
-** -** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
SQLITE_DBSTATUS_CACHE_HIT
-**
This parameter returns the number of pager cache hits that have -** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT -** is always 0. -**
-** -** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
SQLITE_DBSTATUS_CACHE_MISS
-**
This parameter returns the number of pager cache misses that have -** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS -** is always 0. -**
-** -** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
SQLITE_DBSTATUS_CACHE_WRITE
-**
This parameter returns the number of dirty cache entries that have -** been written to disk. Specifically, the number of pages written to the -** wal file in wal mode databases, or the number of pages written to the -** database file in rollback mode databases. Any pages written as part of -** transaction rollback or database recovery operations are not included. -** If an IO or other error occurs while writing a page to disk, the effect -** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The -** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. -**
-**
-*/ -#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 -#define SQLITE_DBSTATUS_CACHE_USED 1 -#define SQLITE_DBSTATUS_SCHEMA_USED 2 -#define SQLITE_DBSTATUS_STMT_USED 3 -#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 -#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 -#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 -#define SQLITE_DBSTATUS_CACHE_HIT 7 -#define SQLITE_DBSTATUS_CACHE_MISS 8 -#define SQLITE_DBSTATUS_CACHE_WRITE 9 -#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ - - -/* -** CAPI3REF: Prepared Statement Status -** -** ^(Each prepared statement maintains various -** [SQLITE_STMTSTATUS counters] that measure the number -** of times it has performed specific operations.)^ These counters can -** be used to monitor the performance characteristics of the prepared -** statements. For example, if the number of table steps greatly exceeds -** the number of table searches or result rows, that would tend to indicate -** that the prepared statement is using a full table scan rather than -** an index. -** -** ^(This interface is used to retrieve and reset counter values from -** a [prepared statement]. The first argument is the prepared statement -** object to be interrogated. The second argument -** is an integer code for a specific [SQLITE_STMTSTATUS counter] -** to be interrogated.)^ -** ^The current value of the requested counter is returned. -** ^If the resetFlg is true, then the counter is reset to zero after this -** interface call returns. -** -** See also: [sqlite3_status()] and [sqlite3_db_status()]. -*/ -SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); - -/* -** CAPI3REF: Status Parameters for prepared statements -** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters} -** -** These preprocessor macros define integer codes that name counter -** values associated with the [sqlite3_stmt_status()] interface. -** The meanings of the various counters are as follows: -** -**
-** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
SQLITE_STMTSTATUS_FULLSCAN_STEP
-**
^This is the number of times that SQLite has stepped forward in -** a table as part of a full table scan. Large numbers for this counter -** may indicate opportunities for performance improvement through -** careful use of indices.
-** -** [[SQLITE_STMTSTATUS_SORT]]
SQLITE_STMTSTATUS_SORT
-**
^This is the number of sort operations that have occurred. -** A non-zero value in this counter may indicate an opportunity to -** improvement performance through careful use of indices.
-** -** [[SQLITE_STMTSTATUS_AUTOINDEX]]
SQLITE_STMTSTATUS_AUTOINDEX
-**
^This is the number of rows inserted into transient indices that -** were created automatically in order to help joins run faster. -** A non-zero value in this counter may indicate an opportunity to -** improvement performance by adding permanent indices that do not -** need to be reinitialized each time the statement is run.
-**
-*/ -#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 -#define SQLITE_STMTSTATUS_SORT 2 -#define SQLITE_STMTSTATUS_AUTOINDEX 3 - -/* -** CAPI3REF: Custom Page Cache Object -** -** The sqlite3_pcache type is opaque. It is implemented by -** the pluggable module. The SQLite core has no knowledge of -** its size or internal structure and never deals with the -** sqlite3_pcache object except by holding and passing pointers -** to the object. -** -** See [sqlite3_pcache_methods2] for additional information. -*/ -typedef struct sqlite3_pcache sqlite3_pcache; - -/* -** CAPI3REF: Custom Page Cache Object -** -** The sqlite3_pcache_page object represents a single page in the -** page cache. The page cache will allocate instances of this -** object. Various methods of the page cache use pointers to instances -** of this object as parameters or as their return value. -** -** See [sqlite3_pcache_methods2] for additional information. -*/ -typedef struct sqlite3_pcache_page sqlite3_pcache_page; -struct sqlite3_pcache_page { - void *pBuf; /* The content of the page */ - void *pExtra; /* Extra information associated with the page */ -}; - -/* -** CAPI3REF: Application Defined Page Cache. -** KEYWORDS: {page cache} -** -** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can -** register an alternative page cache implementation by passing in an -** instance of the sqlite3_pcache_methods2 structure.)^ -** In many applications, most of the heap memory allocated by -** SQLite is used for the page cache. -** By implementing a -** custom page cache using this API, an application can better control -** the amount of memory consumed by SQLite, the way in which -** that memory is allocated and released, and the policies used to -** determine exactly which parts of a database file are cached and for -** how long. -** -** The alternative page cache mechanism is an -** extreme measure that is only needed by the most demanding applications. -** The built-in page cache is recommended for most uses. -** -** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an -** internal buffer by SQLite within the call to [sqlite3_config]. Hence -** the application may discard the parameter after the call to -** [sqlite3_config()] returns.)^ -** -** [[the xInit() page cache method]] -** ^(The xInit() method is called once for each effective -** call to [sqlite3_initialize()])^ -** (usually only once during the lifetime of the process). ^(The xInit() -** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ -** The intent of the xInit() method is to set up global data structures -** required by the custom page cache implementation. -** ^(If the xInit() method is NULL, then the -** built-in default page cache is used instead of the application defined -** page cache.)^ -** -** [[the xShutdown() page cache method]] -** ^The xShutdown() method is called by [sqlite3_shutdown()]. -** It can be used to clean up -** any outstanding resources before process shutdown, if required. -** ^The xShutdown() method may be NULL. -** -** ^SQLite automatically serializes calls to the xInit method, -** so the xInit method need not be threadsafe. ^The -** xShutdown method is only called from [sqlite3_shutdown()] so it does -** not need to be threadsafe either. All other methods must be threadsafe -** in multithreaded applications. -** -** ^SQLite will never invoke xInit() more than once without an intervening -** call to xShutdown(). -** -** [[the xCreate() page cache methods]] -** ^SQLite invokes the xCreate() method to construct a new cache instance. -** SQLite will typically create one cache instance for each open database file, -** though this is not guaranteed. ^The -** first parameter, szPage, is the size in bytes of the pages that must -** be allocated by the cache. ^szPage will always a power of two. ^The -** second parameter szExtra is a number of bytes of extra storage -** associated with each page cache entry. ^The szExtra parameter will -** a number less than 250. SQLite will use the -** extra szExtra bytes on each page to store metadata about the underlying -** database page on disk. The value passed into szExtra depends -** on the SQLite version, the target platform, and how SQLite was compiled. -** ^The third argument to xCreate(), bPurgeable, is true if the cache being -** created will be used to cache database pages of a file stored on disk, or -** false if it is used for an in-memory database. The cache implementation -** does not have to do anything special based with the value of bPurgeable; -** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will -** never invoke xUnpin() except to deliberately delete a page. -** ^In other words, calls to xUnpin() on a cache with bPurgeable set to -** false will always have the "discard" flag set to true. -** ^Hence, a cache created with bPurgeable false will -** never contain any unpinned pages. -** -** [[the xCachesize() page cache method]] -** ^(The xCachesize() method may be called at any time by SQLite to set the -** suggested maximum cache-size (number of pages stored by) the cache -** instance passed as the first argument. This is the value configured using -** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable -** parameter, the implementation is not required to do anything with this -** value; it is advisory only. -** -** [[the xPagecount() page cache methods]] -** The xPagecount() method must return the number of pages currently -** stored in the cache, both pinned and unpinned. -** -** [[the xFetch() page cache methods]] -** The xFetch() method locates a page in the cache and returns a pointer to -** an sqlite3_pcache_page object associated with that page, or a NULL pointer. -** The pBuf element of the returned sqlite3_pcache_page object will be a -** pointer to a buffer of szPage bytes used to store the content of a -** single database page. The pExtra element of sqlite3_pcache_page will be -** a pointer to the szExtra bytes of extra storage that SQLite has requested -** for each entry in the page cache. -** -** The page to be fetched is determined by the key. ^The minimum key value -** is 1. After it has been retrieved using xFetch, the page is considered -** to be "pinned". -** -** If the requested page is already in the page cache, then the page cache -** implementation must return a pointer to the page buffer with its content -** intact. If the requested page is not already in the cache, then the -** cache implementation should use the value of the createFlag -** parameter to help it determined what action to take: -** -** -**
createFlag Behavior when page is not already in cache -**
0 Do not allocate a new page. Return NULL. -**
1 Allocate a new page if it easy and convenient to do so. -** Otherwise return NULL. -**
2 Make every effort to allocate a new page. Only return -** NULL if allocating a new page is effectively impossible. -**
-** -** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite -** will only use a createFlag of 2 after a prior call with a createFlag of 1 -** failed.)^ In between the to xFetch() calls, SQLite may -** attempt to unpin one or more cache pages by spilling the content of -** pinned pages to disk and synching the operating system disk cache. -** -** [[the xUnpin() page cache method]] -** ^xUnpin() is called by SQLite with a pointer to a currently pinned page -** as its second argument. If the third parameter, discard, is non-zero, -** then the page must be evicted from the cache. -** ^If the discard parameter is -** zero, then the page may be discarded or retained at the discretion of -** page cache implementation. ^The page cache implementation -** may choose to evict unpinned pages at any time. -** -** The cache must not perform any reference counting. A single -** call to xUnpin() unpins the page regardless of the number of prior calls -** to xFetch(). -** -** [[the xRekey() page cache methods]] -** The xRekey() method is used to change the key value associated with the -** page passed as the second argument. If the cache -** previously contains an entry associated with newKey, it must be -** discarded. ^Any prior cache entry associated with newKey is guaranteed not -** to be pinned. -** -** When SQLite calls the xTruncate() method, the cache must discard all -** existing cache entries with page numbers (keys) greater than or equal -** to the value of the iLimit parameter passed to xTruncate(). If any -** of these pages are pinned, they are implicitly unpinned, meaning that -** they can be safely discarded. -** -** [[the xDestroy() page cache method]] -** ^The xDestroy() method is used to delete a cache allocated by xCreate(). -** All resources associated with the specified cache should be freed. ^After -** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] -** handle invalid, and will not use it with any other sqlite3_pcache_methods2 -** functions. -** -** [[the xShrink() page cache method]] -** ^SQLite invokes the xShrink() method when it wants the page cache to -** free up as much of heap memory as possible. The page cache implementation -** is not obligated to free any memory, but well-behaved implementations should -** do their best. -*/ -typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; -struct sqlite3_pcache_methods2 { - int iVersion; - void *pArg; - int (*xInit)(void*); - void (*xShutdown)(void*); - sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); - void (*xCachesize)(sqlite3_pcache*, int nCachesize); - int (*xPagecount)(sqlite3_pcache*); - sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); - void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); - void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, - unsigned oldKey, unsigned newKey); - void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); - void (*xDestroy)(sqlite3_pcache*); - void (*xShrink)(sqlite3_pcache*); -}; - -/* -** This is the obsolete pcache_methods object that has now been replaced -** by sqlite3_pcache_methods2. This object is not used by SQLite. It is -** retained in the header file for backwards compatibility only. -*/ -typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; -struct sqlite3_pcache_methods { - void *pArg; - int (*xInit)(void*); - void (*xShutdown)(void*); - sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); - void (*xCachesize)(sqlite3_pcache*, int nCachesize); - int (*xPagecount)(sqlite3_pcache*); - void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); - void (*xUnpin)(sqlite3_pcache*, void*, int discard); - void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); - void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); - void (*xDestroy)(sqlite3_pcache*); -}; - - -/* -** CAPI3REF: Online Backup Object -** -** The sqlite3_backup object records state information about an ongoing -** online backup operation. ^The sqlite3_backup object is created by -** a call to [sqlite3_backup_init()] and is destroyed by a call to -** [sqlite3_backup_finish()]. -** -** See Also: [Using the SQLite Online Backup API] -*/ -typedef struct sqlite3_backup sqlite3_backup; - -/* -** CAPI3REF: Online Backup API. -** -** The backup API copies the content of one database into another. -** It is useful either for creating backups of databases or -** for copying in-memory databases to or from persistent files. -** -** See Also: [Using the SQLite Online Backup API] -** -** ^SQLite holds a write transaction open on the destination database file -** for the duration of the backup operation. -** ^The source database is read-locked only while it is being read; -** it is not locked continuously for the entire backup operation. -** ^Thus, the backup may be performed on a live source database without -** preventing other database connections from -** reading or writing to the source database while the backup is underway. -** -** ^(To perform a backup operation: -**
    -**
  1. sqlite3_backup_init() is called once to initialize the -** backup, -**
  2. sqlite3_backup_step() is called one or more times to transfer -** the data between the two databases, and finally -**
  3. sqlite3_backup_finish() is called to release all resources -** associated with the backup operation. -**
)^ -** There should be exactly one call to sqlite3_backup_finish() for each -** successful call to sqlite3_backup_init(). -** -** [[sqlite3_backup_init()]] sqlite3_backup_init() -** -** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the -** [database connection] associated with the destination database -** and the database name, respectively. -** ^The database name is "main" for the main database, "temp" for the -** temporary database, or the name specified after the AS keyword in -** an [ATTACH] statement for an attached database. -** ^The S and M arguments passed to -** sqlite3_backup_init(D,N,S,M) identify the [database connection] -** and database name of the source database, respectively. -** ^The source and destination [database connections] (parameters S and D) -** must be different or else sqlite3_backup_init(D,N,S,M) will fail with -** an error. -** -** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is -** returned and an error code and error message are stored in the -** destination [database connection] D. -** ^The error code and message for the failed call to sqlite3_backup_init() -** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or -** [sqlite3_errmsg16()] functions. -** ^A successful call to sqlite3_backup_init() returns a pointer to an -** [sqlite3_backup] object. -** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and -** sqlite3_backup_finish() functions to perform the specified backup -** operation. -** -** [[sqlite3_backup_step()]] sqlite3_backup_step() -** -** ^Function sqlite3_backup_step(B,N) will copy up to N pages between -** the source and destination databases specified by [sqlite3_backup] object B. -** ^If N is negative, all remaining source pages are copied. -** ^If sqlite3_backup_step(B,N) successfully copies N pages and there -** are still more pages to be copied, then the function returns [SQLITE_OK]. -** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages -** from source to destination, then it returns [SQLITE_DONE]. -** ^If an error occurs while running sqlite3_backup_step(B,N), -** then an [error code] is returned. ^As well as [SQLITE_OK] and -** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], -** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an -** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. -** -** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if -**
    -**
  1. the destination database was opened read-only, or -**
  2. the destination database is using write-ahead-log journaling -** and the destination and source page sizes differ, or -**
  3. the destination database is an in-memory database and the -** destination and source page sizes differ. -**
)^ -** -** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then -** the [sqlite3_busy_handler | busy-handler function] -** is invoked (if one is specified). ^If the -** busy-handler returns non-zero before the lock is available, then -** [SQLITE_BUSY] is returned to the caller. ^In this case the call to -** sqlite3_backup_step() can be retried later. ^If the source -** [database connection] -** is being used to write to the source database when sqlite3_backup_step() -** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this -** case the call to sqlite3_backup_step() can be retried later on. ^(If -** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or -** [SQLITE_READONLY] is returned, then -** there is no point in retrying the call to sqlite3_backup_step(). These -** errors are considered fatal.)^ The application must accept -** that the backup operation has failed and pass the backup operation handle -** to the sqlite3_backup_finish() to release associated resources. -** -** ^The first call to sqlite3_backup_step() obtains an exclusive lock -** on the destination file. ^The exclusive lock is not released until either -** sqlite3_backup_finish() is called or the backup operation is complete -** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to -** sqlite3_backup_step() obtains a [shared lock] on the source database that -** lasts for the duration of the sqlite3_backup_step() call. -** ^Because the source database is not locked between calls to -** sqlite3_backup_step(), the source database may be modified mid-way -** through the backup process. ^If the source database is modified by an -** external process or via a database connection other than the one being -** used by the backup operation, then the backup will be automatically -** restarted by the next call to sqlite3_backup_step(). ^If the source -** database is modified by the using the same database connection as is used -** by the backup operation, then the backup database is automatically -** updated at the same time. -** -** [[sqlite3_backup_finish()]] sqlite3_backup_finish() -** -** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the -** application wishes to abandon the backup operation, the application -** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). -** ^The sqlite3_backup_finish() interfaces releases all -** resources associated with the [sqlite3_backup] object. -** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any -** active write-transaction on the destination database is rolled back. -** The [sqlite3_backup] object is invalid -** and may not be used following a call to sqlite3_backup_finish(). -** -** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no -** sqlite3_backup_step() errors occurred, regardless or whether or not -** sqlite3_backup_step() completed. -** ^If an out-of-memory condition or IO error occurred during any prior -** sqlite3_backup_step() call on the same [sqlite3_backup] object, then -** sqlite3_backup_finish() returns the corresponding [error code]. -** -** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() -** is not a permanent error and does not affect the return value of -** sqlite3_backup_finish(). -** -** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] -** sqlite3_backup_remaining() and sqlite3_backup_pagecount() -** -** ^Each call to sqlite3_backup_step() sets two values inside -** the [sqlite3_backup] object: the number of pages still to be backed -** up and the total number of pages in the source database file. -** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces -** retrieve these two values, respectively. -** -** ^The values returned by these functions are only updated by -** sqlite3_backup_step(). ^If the source database is modified during a backup -** operation, then the values are not updated to account for any extra -** pages that need to be updated or the size of the source database file -** changing. -** -** Concurrent Usage of Database Handles -** -** ^The source [database connection] may be used by the application for other -** purposes while a backup operation is underway or being initialized. -** ^If SQLite is compiled and configured to support threadsafe database -** connections, then the source database connection may be used concurrently -** from within other threads. -** -** However, the application must guarantee that the destination -** [database connection] is not passed to any other API (by any thread) after -** sqlite3_backup_init() is called and before the corresponding call to -** sqlite3_backup_finish(). SQLite does not currently check to see -** if the application incorrectly accesses the destination [database connection] -** and so no error code is reported, but the operations may malfunction -** nevertheless. Use of the destination database connection while a -** backup is in progress might also also cause a mutex deadlock. -** -** If running in [shared cache mode], the application must -** guarantee that the shared cache used by the destination database -** is not accessed while the backup is running. In practice this means -** that the application must guarantee that the disk file being -** backed up to is not accessed by any connection within the process, -** not just the specific connection that was passed to sqlite3_backup_init(). -** -** The [sqlite3_backup] object itself is partially threadsafe. Multiple -** threads may safely make multiple concurrent calls to sqlite3_backup_step(). -** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() -** APIs are not strictly speaking threadsafe. If they are invoked at the -** same time as another thread is invoking sqlite3_backup_step() it is -** possible that they return invalid values. -*/ -SQLITE_API sqlite3_backup *sqlite3_backup_init( - sqlite3 *pDest, /* Destination database handle */ - const char *zDestName, /* Destination database name */ - sqlite3 *pSource, /* Source database handle */ - const char *zSourceName /* Source database name */ -); -SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); -SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); -SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); -SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); - -/* -** CAPI3REF: Unlock Notification -** -** ^When running in shared-cache mode, a database operation may fail with -** an [SQLITE_LOCKED] error if the required locks on the shared-cache or -** individual tables within the shared-cache cannot be obtained. See -** [SQLite Shared-Cache Mode] for a description of shared-cache locking. -** ^This API may be used to register a callback that SQLite will invoke -** when the connection currently holding the required lock relinquishes it. -** ^This API is only available if the library was compiled with the -** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. -** -** See Also: [Using the SQLite Unlock Notification Feature]. -** -** ^Shared-cache locks are released when a database connection concludes -** its current transaction, either by committing it or rolling it back. -** -** ^When a connection (known as the blocked connection) fails to obtain a -** shared-cache lock and SQLITE_LOCKED is returned to the caller, the -** identity of the database connection (the blocking connection) that -** has locked the required resource is stored internally. ^After an -** application receives an SQLITE_LOCKED error, it may call the -** sqlite3_unlock_notify() method with the blocked connection handle as -** the first argument to register for a callback that will be invoked -** when the blocking connections current transaction is concluded. ^The -** callback is invoked from within the [sqlite3_step] or [sqlite3_close] -** call that concludes the blocking connections transaction. -** -** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, -** there is a chance that the blocking connection will have already -** concluded its transaction by the time sqlite3_unlock_notify() is invoked. -** If this happens, then the specified callback is invoked immediately, -** from within the call to sqlite3_unlock_notify().)^ -** -** ^If the blocked connection is attempting to obtain a write-lock on a -** shared-cache table, and more than one other connection currently holds -** a read-lock on the same table, then SQLite arbitrarily selects one of -** the other connections to use as the blocking connection. -** -** ^(There may be at most one unlock-notify callback registered by a -** blocked connection. If sqlite3_unlock_notify() is called when the -** blocked connection already has a registered unlock-notify callback, -** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is -** called with a NULL pointer as its second argument, then any existing -** unlock-notify callback is canceled. ^The blocked connections -** unlock-notify callback may also be canceled by closing the blocked -** connection using [sqlite3_close()]. -** -** The unlock-notify callback is not reentrant. If an application invokes -** any sqlite3_xxx API functions from within an unlock-notify callback, a -** crash or deadlock may be the result. -** -** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always -** returns SQLITE_OK. -** -** Callback Invocation Details -** -** When an unlock-notify callback is registered, the application provides a -** single void* pointer that is passed to the callback when it is invoked. -** However, the signature of the callback function allows SQLite to pass -** it an array of void* context pointers. The first argument passed to -** an unlock-notify callback is a pointer to an array of void* pointers, -** and the second is the number of entries in the array. -** -** When a blocking connections transaction is concluded, there may be -** more than one blocked connection that has registered for an unlock-notify -** callback. ^If two or more such blocked connections have specified the -** same callback function, then instead of invoking the callback function -** multiple times, it is invoked once with the set of void* context pointers -** specified by the blocked connections bundled together into an array. -** This gives the application an opportunity to prioritize any actions -** related to the set of unblocked database connections. -** -** Deadlock Detection -** -** Assuming that after registering for an unlock-notify callback a -** database waits for the callback to be issued before taking any further -** action (a reasonable assumption), then using this API may cause the -** application to deadlock. For example, if connection X is waiting for -** connection Y's transaction to be concluded, and similarly connection -** Y is waiting on connection X's transaction, then neither connection -** will proceed and the system may remain deadlocked indefinitely. -** -** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock -** detection. ^If a given call to sqlite3_unlock_notify() would put the -** system in a deadlocked state, then SQLITE_LOCKED is returned and no -** unlock-notify callback is registered. The system is said to be in -** a deadlocked state if connection A has registered for an unlock-notify -** callback on the conclusion of connection B's transaction, and connection -** B has itself registered for an unlock-notify callback when connection -** A's transaction is concluded. ^Indirect deadlock is also detected, so -** the system is also considered to be deadlocked if connection B has -** registered for an unlock-notify callback on the conclusion of connection -** C's transaction, where connection C is waiting on connection A. ^Any -** number of levels of indirection are allowed. -** -** The "DROP TABLE" Exception -** -** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost -** always appropriate to call sqlite3_unlock_notify(). There is however, -** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, -** SQLite checks if there are any currently executing SELECT statements -** that belong to the same connection. If there are, SQLITE_LOCKED is -** returned. In this case there is no "blocking connection", so invoking -** sqlite3_unlock_notify() results in the unlock-notify callback being -** invoked immediately. If the application then re-attempts the "DROP TABLE" -** or "DROP INDEX" query, an infinite loop might be the result. -** -** One way around this problem is to check the extended error code returned -** by an sqlite3_step() call. ^(If there is a blocking connection, then the -** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in -** the special "DROP TABLE/INDEX" case, the extended error code is just -** SQLITE_LOCKED.)^ -*/ -SQLITE_API int sqlite3_unlock_notify( - sqlite3 *pBlocked, /* Waiting connection */ - void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ - void *pNotifyArg /* Argument to pass to xNotify */ -); - - -/* -** CAPI3REF: String Comparison -** -** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications -** and extensions to compare the contents of two buffers containing UTF-8 -** strings in a case-independent fashion, using the same definition of "case -** independence" that SQLite uses internally when comparing identifiers. -*/ -SQLITE_API int sqlite3_stricmp(const char *, const char *); -SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); - -/* -** CAPI3REF: String Globbing -* -** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches -** the glob pattern P, and it returns non-zero if string X does not match -** the glob pattern P. ^The definition of glob pattern matching used in -** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the -** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case -** sensitive. -** -** Note that this routine returns zero on a match and non-zero if the strings -** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. -*/ -SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); - -/* -** CAPI3REF: Error Logging Interface -** -** ^The [sqlite3_log()] interface writes a message into the [error log] -** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. -** ^If logging is enabled, the zFormat string and subsequent arguments are -** used with [sqlite3_snprintf()] to generate the final output string. -** -** The sqlite3_log() interface is intended for use by extensions such as -** virtual tables, collating functions, and SQL functions. While there is -** nothing to prevent an application from calling sqlite3_log(), doing so -** is considered bad form. -** -** The zFormat string must not be NULL. -** -** To avoid deadlocks and other threading problems, the sqlite3_log() routine -** will not use dynamically allocated memory. The log message is stored in -** a fixed-length buffer on the stack. If the log message is longer than -** a few hundred characters, it will be truncated to the length of the -** buffer. -*/ -SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); - -/* -** CAPI3REF: Write-Ahead Log Commit Hook -** -** ^The [sqlite3_wal_hook()] function is used to register a callback that -** will be invoked each time a database connection commits data to a -** [write-ahead log] (i.e. whenever a transaction is committed in -** [journal_mode | journal_mode=WAL mode]). -** -** ^The callback is invoked by SQLite after the commit has taken place and -** the associated write-lock on the database released, so the implementation -** may read, write or [checkpoint] the database as required. -** -** ^The first parameter passed to the callback function when it is invoked -** is a copy of the third parameter passed to sqlite3_wal_hook() when -** registering the callback. ^The second is a copy of the database handle. -** ^The third parameter is the name of the database that was written to - -** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter -** is the number of pages currently in the write-ahead log file, -** including those that were just committed. -** -** The callback function should normally return [SQLITE_OK]. ^If an error -** code is returned, that error will propagate back up through the -** SQLite code base to cause the statement that provoked the callback -** to report an error, though the commit will have still occurred. If the -** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value -** that does not correspond to any valid SQLite error code, the results -** are undefined. -** -** A single database handle may have at most a single write-ahead log callback -** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any -** previously registered write-ahead log callback. ^Note that the -** [sqlite3_wal_autocheckpoint()] interface and the -** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will -** those overwrite any prior [sqlite3_wal_hook()] settings. -*/ -SQLITE_API void *sqlite3_wal_hook( - sqlite3*, - int(*)(void *,sqlite3*,const char*,int), - void* -); - -/* -** CAPI3REF: Configure an auto-checkpoint -** -** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around -** [sqlite3_wal_hook()] that causes any database on [database connection] D -** to automatically [checkpoint] -** after committing a transaction if there are N or -** more frames in the [write-ahead log] file. ^Passing zero or -** a negative value as the nFrame parameter disables automatic -** checkpoints entirely. -** -** ^The callback registered by this function replaces any existing callback -** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback -** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism -** configured by this function. -** -** ^The [wal_autocheckpoint pragma] can be used to invoke this interface -** from SQL. -** -** ^Every new [database connection] defaults to having the auto-checkpoint -** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] -** pages. The use of this interface -** is only necessary if the default setting is found to be suboptimal -** for a particular application. -*/ -SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); - -/* -** CAPI3REF: Checkpoint a database -** -** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X -** on [database connection] D to be [checkpointed]. ^If X is NULL or an -** empty string, then a checkpoint is run on all databases of -** connection D. ^If the database connection D is not in -** [WAL | write-ahead log mode] then this interface is a harmless no-op. -** -** ^The [wal_checkpoint pragma] can be used to invoke this interface -** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the -** [wal_autocheckpoint pragma] can be used to cause this interface to be -** run whenever the WAL reaches a certain size threshold. -** -** See also: [sqlite3_wal_checkpoint_v2()] -*/ -SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); - -/* -** CAPI3REF: Checkpoint a database -** -** Run a checkpoint operation on WAL database zDb attached to database -** handle db. The specific operation is determined by the value of the -** eMode parameter: -** -**
-**
SQLITE_CHECKPOINT_PASSIVE
-** Checkpoint as many frames as possible without waiting for any database -** readers or writers to finish. Sync the db file if all frames in the log -** are checkpointed. This mode is the same as calling -** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked. -** -**
SQLITE_CHECKPOINT_FULL
-** This mode blocks (calls the busy-handler callback) until there is no -** database writer and all readers are reading from the most recent database -** snapshot. It then checkpoints all frames in the log file and syncs the -** database file. This call blocks database writers while it is running, -** but not database readers. -** -**
SQLITE_CHECKPOINT_RESTART
-** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after -** checkpointing the log file it blocks (calls the busy-handler callback) -** until all readers are reading from the database file only. This ensures -** that the next client to write to the database file restarts the log file -** from the beginning. This call blocks database writers while it is running, -** but not database readers. -**
-** -** If pnLog is not NULL, then *pnLog is set to the total number of frames in -** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to -** the total number of checkpointed frames (including any that were already -** checkpointed when this function is called). *pnLog and *pnCkpt may be -** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. -** If no values are available because of an error, they are both set to -1 -** before returning to communicate this to the caller. -** -** All calls obtain an exclusive "checkpoint" lock on the database file. If -** any other process is running a checkpoint operation at the same time, the -** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a -** busy-handler configured, it will not be invoked in this case. -** -** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive -** "writer" lock on the database file. If the writer lock cannot be obtained -** immediately, and a busy-handler is configured, it is invoked and the writer -** lock retried until either the busy-handler returns 0 or the lock is -** successfully obtained. The busy-handler is also invoked while waiting for -** database readers as described above. If the busy-handler returns 0 before -** the writer lock is obtained or while waiting for database readers, the -** checkpoint operation proceeds from that point in the same way as -** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible -** without blocking any further. SQLITE_BUSY is returned in this case. -** -** If parameter zDb is NULL or points to a zero length string, then the -** specified operation is attempted on all WAL databases. In this case the -** values written to output parameters *pnLog and *pnCkpt are undefined. If -** an SQLITE_BUSY error is encountered when processing one or more of the -** attached WAL databases, the operation is still attempted on any remaining -** attached databases and SQLITE_BUSY is returned to the caller. If any other -** error occurs while processing an attached database, processing is abandoned -** and the error code returned to the caller immediately. If no error -** (SQLITE_BUSY or otherwise) is encountered while processing the attached -** databases, SQLITE_OK is returned. -** -** If database zDb is the name of an attached database that is not in WAL -** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If -** zDb is not NULL (or a zero length string) and is not the name of any -** attached database, SQLITE_ERROR is returned to the caller. -*/ -SQLITE_API int sqlite3_wal_checkpoint_v2( - sqlite3 *db, /* Database handle */ - const char *zDb, /* Name of attached database (or NULL) */ - int eMode, /* SQLITE_CHECKPOINT_* value */ - int *pnLog, /* OUT: Size of WAL log in frames */ - int *pnCkpt /* OUT: Total number of frames checkpointed */ -); - -/* -** CAPI3REF: Checkpoint operation parameters -** -** These constants can be used as the 3rd parameter to -** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] -** documentation for additional information about the meaning and use of -** each of these values. -*/ -#define SQLITE_CHECKPOINT_PASSIVE 0 -#define SQLITE_CHECKPOINT_FULL 1 -#define SQLITE_CHECKPOINT_RESTART 2 - -/* -** CAPI3REF: Virtual Table Interface Configuration -** -** This function may be called by either the [xConnect] or [xCreate] method -** of a [virtual table] implementation to configure -** various facets of the virtual table interface. -** -** If this interface is invoked outside the context of an xConnect or -** xCreate virtual table method then the behavior is undefined. -** -** At present, there is only one option that may be configured using -** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options -** may be added in the future. -*/ -SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); - -/* -** CAPI3REF: Virtual Table Configuration Options -** -** These macros define the various options to the -** [sqlite3_vtab_config()] interface that [virtual table] implementations -** can use to customize and optimize their behavior. -** -**
-**
SQLITE_VTAB_CONSTRAINT_SUPPORT -**
Calls of the form -** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, -** where X is an integer. If X is zero, then the [virtual table] whose -** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not -** support constraints. In this configuration (which is the default) if -** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire -** statement is rolled back as if [ON CONFLICT | OR ABORT] had been -** specified as part of the users SQL statement, regardless of the actual -** ON CONFLICT mode specified. -** -** If X is non-zero, then the virtual table implementation guarantees -** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before -** any modifications to internal or persistent data structures have been made. -** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite -** is able to roll back a statement or database transaction, and abandon -** or continue processing the current SQL statement as appropriate. -** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns -** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode -** had been ABORT. -** -** Virtual table implementations that are required to handle OR REPLACE -** must do so within the [xUpdate] method. If a call to the -** [sqlite3_vtab_on_conflict()] function indicates that the current ON -** CONFLICT policy is REPLACE, the virtual table implementation should -** silently replace the appropriate rows within the xUpdate callback and -** return SQLITE_OK. Or, if this is not possible, it may return -** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT -** constraint handling. -**
-*/ -#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 - -/* -** CAPI3REF: Determine The Virtual Table Conflict Policy -** -** This function may only be called from within a call to the [xUpdate] method -** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The -** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], -** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode -** of the SQL statement that triggered the call to the [xUpdate] method of the -** [virtual table]. -*/ -SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); - -/* -** CAPI3REF: Conflict resolution modes -** -** These constants are returned by [sqlite3_vtab_on_conflict()] to -** inform a [virtual table] implementation what the [ON CONFLICT] mode -** is for the SQL statement being evaluated. -** -** Note that the [SQLITE_IGNORE] constant is also used as a potential -** return value from the [sqlite3_set_authorizer()] callback and that -** [SQLITE_ABORT] is also a [result code]. -*/ -#define SQLITE_ROLLBACK 1 -/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ -#define SQLITE_FAIL 3 -/* #define SQLITE_ABORT 4 // Also an error code */ -#define SQLITE_REPLACE 5 - - - -/* -** Undo the hack that converts floating point types to integer for -** builds on processors without floating point support. -*/ -#ifdef SQLITE_OMIT_FLOATING_POINT -# undef double -#endif - -#ifdef __cplusplus -} /* End of the 'extern "C"' block */ -#endif -#endif - -/* -** 2010 August 30 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -*/ - -#ifndef _SQLITE3RTREE_H_ -#define _SQLITE3RTREE_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; - -/* -** Register a geometry callback named zGeom that can be used as part of an -** R-Tree geometry query as follows: -** -** SELECT ... FROM WHERE MATCH $zGeom(... params ...) -*/ -SQLITE_API int sqlite3_rtree_geometry_callback( - sqlite3 *db, - const char *zGeom, -#ifdef SQLITE_RTREE_INT_ONLY - int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), -#else - int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), -#endif - void *pContext -); - - -/* -** A pointer to a structure of the following type is passed as the first -** argument to callbacks registered using rtree_geometry_callback(). -*/ -struct sqlite3_rtree_geometry { - void *pContext; /* Copy of pContext passed to s_r_g_c() */ - int nParam; /* Size of array aParam[] */ - double *aParam; /* Parameters passed to SQL geom function */ - void *pUser; /* Callback implementation user data */ - void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ -}; - - -#ifdef __cplusplus -} /* end of the 'extern "C"' block */ -#endif - -#endif /* ifndef _SQLITE3RTREE_H_ */ - From 19932175e98f1e2b502ea33f4998febfee48cac7 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Fri, 16 Aug 2013 18:41:25 -0700 Subject: [PATCH 233/881] add external 3rdparty submodule --- .gitmodules | 3 +++ src/3rdparty | 1 + 2 files changed, 4 insertions(+) create mode 160000 src/3rdparty diff --git a/.gitmodules b/.gitmodules index 2ede715f49..ccaf1bfdae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "magic"] path = magic url = git://git.bro.org/bromagic +[submodule "src/3rdparty"] + path = src/3rdparty + url = git://git.bro-ids.org/bro-3rdparty diff --git a/src/3rdparty b/src/3rdparty new file mode 160000 index 0000000000..12b5cb446c --- /dev/null +++ b/src/3rdparty @@ -0,0 +1 @@ +Subproject commit 12b5cb446c8128bb22e5cbd7baa7d53669539487 From dc370fdd8d1f6846a72903204e6fce5e9a45ce72 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 19 Aug 2013 14:18:18 -0500 Subject: [PATCH 234/881] Fix a deadlock w/ SQLite. sqlite3_shutdown() was called a bit too early, when SQLite-using threads may still have yet to fully shutdown. --- src/main.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cc b/src/main.cc index fef3d94063..9868f62be9 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1154,10 +1154,10 @@ int main(int argc, char** argv) curl_global_cleanup(); #endif - sqlite3_shutdown(); - terminate_bro(); + sqlite3_shutdown(); + // Close files after net_delete(), because net_delete() // might write to connection content files. BroFile::CloseCachedFiles(); From 746c3d5bb6248c11020d3d60e216ffc94d7864d8 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 19 Aug 2013 12:18:36 -0700 Subject: [PATCH 235/881] Changing submodule URLs from bro-ids.org to bro.org. --- .gitmodules | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitmodules b/.gitmodules index ccaf1bfdae..87826d2ef6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,24 +1,24 @@ [submodule "aux/bro-aux"] path = aux/bro-aux - url = git://git.bro-ids.org/bro-aux + url = git://git.bro.org/bro-aux [submodule "aux/binpac"] path = aux/binpac - url = git://git.bro-ids.org/binpac + url = git://git.bro.org/binpac [submodule "aux/broccoli"] path = aux/broccoli - url = git://git.bro-ids.org/broccoli + url = git://git.bro.org/broccoli [submodule "aux/broctl"] path = aux/broctl - url = git://git.bro-ids.org/broctl + url = git://git.bro.org/broctl [submodule "aux/btest"] path = aux/btest - url = git://git.bro-ids.org/btest + url = git://git.bro.org/btest [submodule "cmake"] path = cmake - url = git://git.bro-ids.org/cmake + url = git://git.bro.org/cmake [submodule "magic"] path = magic url = git://git.bro.org/bromagic [submodule "src/3rdparty"] path = src/3rdparty - url = git://git.bro-ids.org/bro-3rdparty + url = git://git.bro.org/bro-3rdparty From 671be75308ccd21ab91ef198d2682d79f3623091 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 19 Aug 2013 22:07:15 -0700 Subject: [PATCH 236/881] Updating submodule(s). [nomail] --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index 6f8f124db9..43913d5064 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 6f8f124db961da7eecff6b6f7eff761ab2f5fcb7 +Subproject commit 43913d50645f69b2b833773511f8de2fd6b3222c From 867e4b52d89834bf75abf16322a217cf2f2b5b1d Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 19 Aug 2013 22:08:30 -0700 Subject: [PATCH 237/881] More doc reorg, and a light pass over the first 3 sections. --- INSTALL | 313 +--------------- NEWS | 352 ++++++++++++++---- doc/frameworks/geoip.rst | 2 + doc/index.rst | 7 + doc/install/CHANGES-binpac.txt | 1 + doc/install/CHANGES-bro-aux.txt | 1 + doc/install/CHANGES-bro.txt | 1 + doc/install/CHANGES-broccoli-python.txt | 1 + doc/install/CHANGES-broccoli-ruby.txt | 1 + doc/install/CHANGES-broccoli.txt | 1 + doc/install/CHANGES-broctl.txt | 1 + doc/install/CHANGES-btest.txt | 1 + doc/install/CHANGES-capstats.txt | 1 + doc/install/CHANGES-pysubnettree.txt | 1 + doc/install/CHANGES-trace-summary.txt | 1 + doc/install/NEWS.rst | 1 + doc/install/changes.rst | 75 ++++ doc/install/guidelines.rst | 43 +++ doc/install/index.rst | 13 + doc/install/install.rst | 241 ++++++++++++ doc/install/release-notes.rst | 13 + doc/{intro => install}/reporting-problems.rst | 4 +- doc/install/upgrade.rst | 10 + doc/intro/architecture.png | Bin 0 -> 139697 bytes doc/intro/bro-eyes.png | Bin 0 -> 46415 bytes doc/intro/history.png | Bin 0 -> 163112 bytes doc/intro/index.rst | 248 +++++++++++- doc/intro/install.rst | 1 - doc/intro/overview.rst | 5 - doc/intro/upgrade.rst | 308 --------------- .../quickstart.rst => quickstart/index.rst} | 79 ++-- doc/scripting/index.rst | 2 + doc/scripts/packages.rst | 2 + doc/using/index.rst | 2 + 34 files changed, 995 insertions(+), 737 deletions(-) create mode 120000 doc/install/CHANGES-binpac.txt create mode 120000 doc/install/CHANGES-bro-aux.txt create mode 120000 doc/install/CHANGES-bro.txt create mode 120000 doc/install/CHANGES-broccoli-python.txt create mode 120000 doc/install/CHANGES-broccoli-ruby.txt create mode 120000 doc/install/CHANGES-broccoli.txt create mode 120000 doc/install/CHANGES-broctl.txt create mode 120000 doc/install/CHANGES-btest.txt create mode 120000 doc/install/CHANGES-capstats.txt create mode 120000 doc/install/CHANGES-pysubnettree.txt create mode 120000 doc/install/CHANGES-trace-summary.txt create mode 120000 doc/install/NEWS.rst create mode 100644 doc/install/changes.rst create mode 100644 doc/install/guidelines.rst create mode 100644 doc/install/index.rst create mode 100644 doc/install/install.rst create mode 100644 doc/install/release-notes.rst rename doc/{intro => install}/reporting-problems.rst (99%) create mode 100644 doc/install/upgrade.rst create mode 100644 doc/intro/architecture.png create mode 100644 doc/intro/bro-eyes.png create mode 100644 doc/intro/history.png delete mode 120000 doc/intro/install.rst delete mode 100644 doc/intro/overview.rst delete mode 100644 doc/intro/upgrade.rst rename doc/{intro/quickstart.rst => quickstart/index.rst} (87%) diff --git a/INSTALL b/INSTALL index 4604a26bf5..4915ba6aa6 100644 --- a/INSTALL +++ b/INSTALL @@ -1,314 +1,3 @@ -.. _CMake: http://www.cmake.org -.. _SWIG: http://www.swig.org -.. _Xcode: https://developer.apple.com/xcode/ -.. _MacPorts: http://www.macports.org -.. _Fink: http://www.finkproject.org -.. _Homebrew: http://mxcl.github.com/homebrew -.. _bro downloads page: http://bro.org/download/index.html -============== -Installing Bro -============== +See doc/install/install.rst for more installation instructions. -Bro can be downloaded in either pre-built binary package or -source code forms. - -Prerequisites -============= - -Bro requires the following libraries and tools to be installed -before you begin: - - * Libpcap http://www.tcpdump.org - - * OpenSSL libraries http://www.openssl.org - - * BIND8 library - - * Libmagic - - * Libz - - * Bash (for BroControl) - -To build Bro from source, the following additional dependencies are required: - - * CMake 2.6.3 or greater http://www.cmake.org - - * SWIG http://www.swig.org - - * Bison (GNU Parser Generator) - - * Flex (Fast Lexical Analyzer) - - * Libpcap headers http://www.tcpdump.org - - * OpenSSL headers http://www.openssl.org - - * libmagic headers - - * zlib headers - - * Perl - -Bro can make use of some optional libraries and tools if they are found at -build time: - - * LibGeoIP (for geo-locating IP addresses) - - * gperftools (tcmalloc is used to improve memory and CPU usage) - - * sendmail (for BroControl) - - * ipsumdump (for trace-summary) http://www.cs.ucla.edu/~kohler/ipsumdump - - * Ruby executable, library, and headers (for Broccoli Ruby bindings) - - -Installing From Pre-Built Binary Release Packages -================================================= - -See the `bro downloads page`_ for currently supported/targeted platforms. - -* RPM - - .. console:: - - sudo yum localinstall Bro-*.rpm - -* DEB - - .. console:: - - sudo gdebi Bro-*.deb - -* MacOS Disk Image with Installer - - Just open the ``Bro-*.dmg`` and then run the ``.pkg`` installer. - Everything installed by the package will go into ``/opt/bro``. - -The primary install prefix for binary packages is ``/opt/bro``. -Non-MacOS packages that include BroControl also put variable/runtime -data (e.g. Bro logs) in ``/var/opt/bro``. - - -Installing From Source -====================== - -Required Dependencies -~~~~~~~~~~~~~~~~~~~~~ - -The following dependencies are required to build Bro: - -* RPM/RedHat-based Linux: - - .. console:: - - sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel - -* DEB/Debian-based Linux: - - .. console:: - - sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev - -* FreeBSD - - Most required dependencies should come with a minimal FreeBSD install - except for the following. - - .. console:: - - sudo pkg_add -r bash cmake swig bison python - - Note that ``bash`` needs to be in ``PATH``, which by default it is - not. The FreeBSD package installs the binary into - ``/usr/local/bin``. - -* Mac OS X - - Compiling source code on Macs requires first downloading Xcode_, - then going through its "Preferences..." -> "Downloads" menus to - install the "Command Line Tools" component. - - Lion (10.7) and Mountain Lion (10.8) come with all required - dependencies except for CMake_, SWIG_, and ``libmagic``. - - Distributions of these dependencies can likely be obtained from your - preferred Mac OS X package management system (e.g. MacPorts_, Fink_, - or Homebrew_). - - Specifically for MacPorts, the ``swig``, ``swig-ruby``, ``swig-python`` - and ``file`` packages provide the required dependencies. - -Optional Dependencies -~~~~~~~~~~~~~~~~~~~~~ - -Bro can use libGeoIP for geo-locating IP addresses, and sendmail for -sending emails. - -* RedHat Enterprise Linux: - - .. console:: - - sudo yum install geoip-devel sendmail - -* CentOS Linux: - - .. console:: - - sudo yum install GeoIP-devel sendmail - -* DEB/Debian-based Linux: - - .. console:: - - sudo apt-get install libgeoip-dev sendmail - -* Ports-based FreeBSD - - .. console:: - - sudo pkg_add -r GeoIP - - sendmail is typically already available. - -* Mac OS X - - Vanilla OS X installations don't ship with libGeoIP, but - if installed from your preferred package management system (e.g. MacPorts, - Fink, or Homebrew), they should be automatically detected and Bro will - compile against them. - -Additional steps may be needed to :doc:`get the right GeoIP database `. - -Compiling Bro Source Code -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Bro releases are bundled into source packages for convenience and -available from the `bro downloads page`_. - -Alternatively, the latest Bro development version can be obtained through git -repositories hosted at `git.bro.org `_. See -our `git development documentation -`_ for comprehensive -information on Bro's use of git revision control, but the short story -for downloading the full source code experience for Bro via git is: - -.. console:: - - git clone --recursive git://git.bro.org/bro - -.. note:: If you choose to clone the ``bro`` repository non-recursively for - a "minimal Bro experience", be aware that compiling it depends on - BinPAC, which has its own ``binpac`` repository. Either install it - first or initialize/update the cloned ``bro`` repository's - ``aux/binpac`` submodule. - -The typical way to build and install from source is (for more options, -run ``./configure --help``): - -.. console:: - - ./configure - make - make install - -The default installation path is ``/usr/local/bro``, which would typically -require root privileges when doing the ``make install``. A different -installation path can be chosen by specifying the ``--prefix`` option. -Note that ``/usr`` and ``/opt/bro`` are the -standard prefixes for binary Bro packages to be installed, so those are -typically not good choices unless you are creating such a package. - -Depending on the Bro package you downloaded, there may be auxiliary -tools and libraries available in the ``aux/`` directory. Some of them -will be automatically built and installed along with Bro. There are -``--disable-*`` options that can be given to the configure script to -turn off unwanted auxiliary projects that would otherwise be installed -automatically. Finally, use ``make install-aux`` to install some of -the other programs that are in the ``aux/bro-aux`` directory. - -OpenBSD users, please see our FAQ at -http://www.bro.org/documentation/faq.html if you are having -problems installing Bro. - - -Upgrading From a Previous Version of Bro -======================================== - -If you're doing an upgrade install (rather than a fresh install), -there's two suggested approaches: either install Bro using the same -installation prefix directory as before, or pick a new prefix and copy -local customizations over. - -Re-Use Previous Install Prefix -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you choose to configure and install Bro with the same prefix -directory as before, local customization and configuration to files in -``$prefix/share/bro/site`` and ``$prefix/etc`` won't be overwritten -(``$prefix`` indicating the root of where Bro was installed). Also, logs -generated at run-time won't be touched by the upgrade. (But making -a backup of local changes before upgrading is still recommended.) - -After upgrading, remember to check ``$prefix/share/bro/site`` and -``$prefix/etc`` for ``.example`` files, which indicate the -distribution's version of the file differs from the local one, which may -include local changes. Review the differences, and make adjustments -as necessary (for differences that aren't the result of a local change, -use the new version's). - -Pick a New Install prefix -~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you want to install the newer version in a different prefix -directory than before, you can just copy local customization and -configuration files from ``$prefix/share/bro/site`` and ``$prefix/etc`` -to the new location (``$prefix`` indicating the root of where Bro was -originally installed). Make sure to review the files for difference -before copying and make adjustments as necessary (for differences that -aren't the result of a local change, use the new version's). Of -particular note, the copied version of ``$prefix/etc/broctl.cfg`` is -likely to need changes to the ``SpoolDir`` and ``LogDir`` settings. - - -Configure the Run-Time Environment -================================== - -Just remember that you may need to adjust your ``PATH`` environment variable -according to the platform/shell/package you're using. For example: - -Bourne-Shell Syntax: - -.. console:: - - export PATH=/usr/local/bro/bin:$PATH - -C-Shell Syntax: - -.. console:: - - setenv PATH /usr/local/bro/bin:$PATH - -Or substitute ``/opt/bro/bin`` instead if you installed from a binary package. - -Running Bro -=========== - -Bro is a complex program and it takes a bit of time to get familiar -with it. A good place for newcomers to start is the Quick Start Guide -at http://www.bro.org/documentation/quickstart.html. - -For developers that wish to run Bro directly from the ``build/`` -directory (i.e., without performing ``make install``), they will have -to first adjust ``BROPATH`` to look for scripts inside the build -directory. Sourcing either ``build/bro-path-dev.sh`` or -``build/bro-path-dev.csh`` as appropriate for the current shell -accomplishes this and also augments your ``PATH`` so you can use the -Bro binary directly:: - - ./configure - make - source build/bro-path-dev.sh - bro diff --git a/NEWS b/NEWS index e4ae28cd61..fcc0863b92 100644 --- a/NEWS +++ b/NEWS @@ -1,17 +1,14 @@ -Release Notes -============= - This document summarizes the most important changes in the current Bro release. For a complete list of changes, see the ``CHANGES`` file (note that submodules, such as BroControl and Broccoli, come with their own CHANGES.) -Bro 2.2 -------- +Bro 2.2 (Work In Progress) +========================== New Functionality -~~~~~~~~~~~~~~~~~ +----------------- - GPRS Tunnelling Protocol (GTPv1) decapsulation. @@ -147,8 +144,28 @@ New Functionality base/utils/active-http.bro for providing an interface for querying remote web servers. +- Summary statistics framework. [Extend] + +- A number of new applications build on top of the summary statistics + framework: + + * Scan detection: Detectors for port and address scans return. See + policy/misc/scan.bro. + + * Tracerouter detector: policy/misc/detect-traceroute + + * Web application detection/measurement: policy/misc/app-metrics.bro + + * FTP brute-forcing detector: policy/protocols/ftp/detect-bruteforcing.bro + + * HTTP-based SQL injection detector: policy/protocols/http/detect-sqli.bro + (existed before, but now ported to the new framework) + + * SSH brute-forcing detector feeding the intelligence framework: + policy/protocols/ssh/detect-bruteforcing.bro + Changed Functionality -~~~~~~~~~~~~~~~~~~~~~ +--------------------- - We removed the following, already deprecated, functionality: @@ -231,11 +248,12 @@ Changed Functionality - We removed the BitTorrent DPD signatures pending further updates to that analyzer. + Bro 2.1 -------- +======= New Functionality -~~~~~~~~~~~~~~~~~ +----------------- - Bro now comes with extensive IPv6 support. Past versions offered only basic IPv6 functionality that was rarely used in practice as it @@ -314,30 +332,9 @@ New Functionality outputs. We do not yet recommend them for production (but welcome feedback!) -- Summary statistics framework. [Extend] - -- A number of new applications build on top of the summary statistics - framework: - - * Scan detection: Detectors for port and address scans return. See - policy/misc/scan.bro. - - * Tracerouter detector: policy/misc/detect-traceroute - - * Web application detection/measurement: policy/misc/app-metrics.bro - - * FTP brute-forcing detector: policy/protocols/ftp/detect-bruteforcing.bro - - * HTTP-based SQL injection detector: policy/protocols/http/detect-sqli.bro - (existed before, but now ported to the new framework) - - * SSH brute-forcing detector feeding the intelligence framework: - policy/protocols/ssh/detect-bruteforcing.bro - - Changed Functionality -~~~~~~~~~~~~~~~~~~~~~ +--------------------- The following summarizes the most important differences in existing functionality. Note that this list is not complete, see CHANGES for @@ -371,7 +368,10 @@ the full set. soon. With that, "match" and "using" are no longer reserved keywords. - The syntax for IPv6 literals changed from "2607:f8b0:4009:802::1012" - to "[2607:f8b0:4009:802::1012]". + to "[2607:f8b0:4009:802::1012]". When an IP address variable or IP + address literal is enclosed in pipes (for example, + ``|[fe80::db15]|``) the result is now the size of the address in + bits (32 for IPv4 and 128 for IPv6). - Bro now spawns threads for doing its logging. From a user's perspective not much should change, except that the OS may now show @@ -411,60 +411,274 @@ the full set. - The ASCII writers "header_*" options have been renamed to "meta_*" (because there's now also a footer). +- Some built-in functions have been removed: "addr_to_count" (use + "addr_to_counts" instead), "bro_has_ipv6" (this is no longer + relevant because Bro now always supports IPv6), "active_connection" + (use "connection_exists" instead), and "connection_record" (use + "lookup_connection" instead). + +- The "NFS3::mode2string" built-in function has been renamed to + "file_mode". + +- Some built-in functions have been changed: "exit" (now takes the + exit code as a parameter), "to_port" (now takes a string as + parameter instead of a count and transport protocol, but + "count_to_port" is still available), "connect" (now takes an + additional string parameter specifying the zone of a non-global IPv6 + address), and "listen" (now takes three additional parameters to + enable listening on IPv6 addresses). + +- Some Bro script variables have been renamed: + "LogAscii::header_prefix" has been renamed to + "LogAscii::meta_prefix", "LogAscii::include_header" has been renamed + to "LogAscii::include_meta". + +- Some Bro script variables have been removed: "tunnel_port", + "parse_udp_tunnels", "use_connection_compressor", + "cc_handle_resets", "cc_handle_only_syns", and + "cc_instantiate_on_data". + +- A couple events have changed: the "icmp_redirect" event now includes + the target and destination addresses and any Neighbor Discovery + options in the message, and the last parameter of the + "dns_AAAA_reply" event has been removed because it was unused. + +- The format of the ASCII log files has changed very slightly. Two + new lines are automatically added, one to record the time when the + log was opened, and the other to record the time when the log was + closed. + +- In BroControl, the option (in broctl.cfg) "CFlowAddr" was renamed to + "CFlowAddress". + Bro 2.0 -------- +======= -As the version number jump suggests, Bro 2.0 is a major upgrade and -lots of things have changed. We have assembled a separate upgrade -guide with the most important changes compared to Bro 1.5 at -http://www.bro.org/documentation/upgrade.html. You can find -the offline version of that document in ``doc/upgrade.rst.``. +As the version number jump from 1.5 suggests, Bro 2.0 is a major +upgrade and lots of things have changed. Most importantly, we have +rewritten almost all of Bro's default scripts from scratch, using +quite different structure now and focusing more on operational +deployment. The result is a system that works much better "out of the +box", even without much initial site-specific configuration. The +down-side is that 1.x configurations will need to be adapted to work +with the new version. The two rules of thumb are: -Compared to the earlier 2.0 Beta version, the major changes in the -final release are: + (1) If you have written your own Bro scripts + that do not depend on any of the standard scripts formerly + found in ``policy/``, they will most likely just keep working + (although you might want to adapt them to use some of the new + features, like the new logging framework; see below). - * The default scripts now come with complete reference - documentation. See - http://www.bro.org/documentation/index.html. + (2) If you have custom code that depends on specifics of 1.x + default scripts (including most configuration tuning), that is + unlikely to work with 2.x. We recommend to start by using just + the new scripts first, and then port over any customizations + incrementally as necessary (they may be much easier to do now, + or even unnecessary). Send mail to the Bro user mailing list + if you need help. - * libz and libmagic are now required dependencies. +Below we summarize changes from 1.x to 2.x in more detail. This list +isn't complete, see the :download:`CHANGES ` file in the +distribution for the full story. - * Reduced snaplen default from 65535 to old default of 8192. The - large value was introducing performance problems on many - systems. +Script Organization +------------------- - * Replaced the --snaplen/-l command line option with a - scripting-layer option called "snaplen". The new option can also - be redefined on the command line, e.g. ``bro -i eth0 - snaplen=65535``. +In versions before 2.0, Bro scripts were all maintained in a flat +directory called ``policy/`` in the source tree. This directory is now +renamed to ``scripts/`` and contains major subdirectories ``base/``, +``policy/``, and ``site/``, each of which may also be subdivided +further. - * Reintroduced the BRO_LOG_SUFFIX environment variable that the - ASCII logger now respects to add a suffix to the log files it - creates. +The contents of the new ``scripts/`` directory, like the old/flat +``policy/`` still gets installed under the ``share/bro`` +subdirectory of the installation prefix path just like previous +versions. For example, if Bro was compiled like ``./configure +--prefix=/usr/local/bro && make && make install``, then the script +hierarchy can be found in ``/usr/local/bro/share/bro``. - * The ASCII logs now include further header information, and - fields set to an empty value are now logged as ``(empty)`` by - default (instead of ``-``, which is already used for fields that - are not set at all). +The main +subdirectories of that hierarchy are as follows: - * Some NOTICES were renamed, and the signatures of some SSL events - have changed. +- ``base/`` contains all scripts that are loaded by Bro by default + (unless the ``-b`` command line option is used to run Bro in a + minimal configuration). Note that is a major conceptual change: + rather than not loading anything by default, Bro now uses an + extensive set of default scripts out of the box. - * bro-cut got some new capabilities: + The scripts under this directory generally either accumulate/log + useful state/protocol information for monitored traffic, configure a + default/recommended mode of operation, or provide extra Bro + scripting-layer functionality that has no significant performance cost. - - If no field names are given on the command line, we now pass - through all fields. +- ``policy/`` contains all scripts that a user will need to explicitly + tell Bro to load. These are scripts that implement + functionality/analysis that not all users may want to use and may have + more significant performance costs. For a new installation, you + should go through these and see what appears useful to load. - - New options -u/-U for time output in UTC. +- ``site/`` remains a directory that can be used to store locally + developed scripts. It now comes with some preinstalled example + scripts that contain recommended default configurations going beyond + the ``base/`` setup. E.g. ``local.bro`` loads extra scripts from + ``policy/`` and does extra tuning. These files can be customized in + place without being overwritten by upgrades/reinstalls, unlike + scripts in other directories. - - New option -F to give output field separator. +With version 2.0, the default ``BROPATH`` is set to automatically +search for scripts in ``policy/``, ``site/`` and their parent +directory, but **not** ``base/``. Generally, everything under +``base/`` is loaded automatically, but for users of the ``-b`` option, +it's important to know that loading a script in that directory +requires the extra ``base/`` path qualification. For example, the +following two scripts: - * Broccoli supports more types internally, allowing to send - complex records. +* ``$PREFIX/share/bro/base/protocols/ssl/main.bro`` +* ``$PREFIX/share/bro/policy/protocols/ssl/validate-certs.bro`` - * Many smaller bug fixes, portability improvements, and general - polishing across all modules. +are referenced from another Bro script like: + +.. code:: bro + + @load base/protocols/ssl/main + @load protocols/ssl/validate-certs + +Notice how ``policy/`` can be omitted as a convenience in the second +case. ``@load`` can now also use relative path, e.g., ``@load +../main``. +Logging Framework +----------------- +- The logs generated by scripts that ship with Bro are entirely redone + to use a standardized, machine parsable format via the new logging + framework. Generally, the log content has been restructured towards + making it more directly useful to operations. Also, several + analyzers have been significantly extended and thus now log more + information. Take a look at ``ssl.log``. + + * A particular format change that may be useful to note is that the + ``conn.log`` ``service`` field is derived from DPD instead of + well-known ports (while that was already possible in 1.5, it was + not the default). + + * Also, ``conn.log`` now reports raw number of packets/bytes per + endpoint. + +- The new logging framework makes it possible to extend, customize, + and filter logs very easily. See the :doc:`logging framework ` + for more information on usage. + +- A common pattern found in the new scripts is to store logging stream + records for protocols inside the ``connection`` records so that + state can be collected until enough is seen to log a coherent unit + of information regarding the activity of that connection. This + state is now frequently seen/accessible in event handlers, for + example, like ``c$`` where ```` is replaced by + the name of the protocol. This field is added to the ``connection`` + record by ``redef``'ing it in a + ``base/protocols//main.bro`` script. + +- The logging code has been rewritten internally, with script-level + interface and output backend now clearly separated. While ASCII + logging is still the default, we will add further output types in + the future (binary format, direct database logging). + + +Notice Framework +---------------- + +The way users interact with "notices" has changed significantly in +order to make it easier to define a site policy and more extensible +for adding customized actions. See the :doc:`notice framework `. + + +New Default Settings +-------------------- + +- Dynamic Protocol Detection (DPD) is now enabled/loaded by default. + +- The default packet filter now examines all packets instead of + dynamically building a filter based on which protocol analysis scripts + are loaded. See ``PacketFilter::all_packets`` for how to revert to old + behavior. + +API Changes +----------- + +- The ``@prefixes`` directive works differently now. + Any added prefixes are now searched for and loaded *after* all input + files have been parsed. After all input files are parsed, Bro + searches ``BROPATH`` for prefixed, flattened versions of all of the + parsed input files. For example, if ``lcl`` is in ``@prefixes``, and + ``site.bro`` is loaded, then a file named ``lcl.site.bro`` that's in + ``BROPATH`` would end up being automatically loaded as well. Packages + work similarly, e.g. loading ``protocols/http`` means a file named + ``lcl.protocols.http.bro`` in ``BROPATH`` gets loaded automatically. + +- The ``make_addr`` BIF now returns a ``subnet`` versus an ``addr`` + + +Variable Naming +--------------- + +- ``Module`` is more widely used for namespacing. E.g. the new + ``site.bro`` exports the ``local_nets`` identifier (among other + things) into the ``Site`` module. + +- Identifiers may have been renamed to conform to new `scripting + conventions + `_ + + +Removed Functionality +--------------------- + +We have remove a bunch of functionality that was rarely used and/or +had not been maintained for a while already: + + - The ``net`` script data type. + - The ``alarm`` statement; use the notice framework instead. + - Trace rewriting. + - DFA state expiration in regexp engine. + - Active mapping. + - Native DAG support (may come back eventually) + - ClamAV support. + - The connection compressor is now disabled by default, and will + be removed in the future. + +BroControl Changes +------------------ + +BroControl looks pretty much similar to the version coming with Bro 1.x, +but has been cleaned up and streamlined significantly internally. + +BroControl has a new ``process`` command to process a trace on disk +offline using a similar configuration to what BroControl installs for +live analysis. + +BroControl now has an extensive plugin interface for adding new +commands and options. Note that this is still considered experimental. + +We have removed the ``analysis`` command, and BroControl currently +does not send daily alarm summaries anymore (this may be restored +later). + +Development Infrastructure +-------------------------- + +Bro development has moved from using SVN to Git for revision control. +Users that want to use the latest Bro development snapshot by checking it out +from the source repositories should see the `development process +`_. Note that all the various +sub-components now reside in their own repositories. However, the +top-level Bro repository includes them as git submodules so it's easy +to check them all out simultaneously. + +Bro now uses `CMake `_ for its build system so +that is a new required dependency when building from source. + +Bro now comes with a growing suite of regression tests in +``testing/``. diff --git a/doc/frameworks/geoip.rst b/doc/frameworks/geoip.rst index bd9ae0c08d..3c3883a607 100644 --- a/doc/frameworks/geoip.rst +++ b/doc/frameworks/geoip.rst @@ -1,4 +1,6 @@ +.. _geolocation: + =========== GeoLocation =========== diff --git a/doc/index.rst b/doc/index.rst index c423e98211..5afbb022a1 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,6 +9,8 @@ Bro Documentation :maxdepth: 2 intro/index.rst + quickstart/index.rst + install/index.rst using/index.rst scripting/index.rst frameworks/index.rst @@ -20,3 +22,8 @@ Bro Documentation section, but can't figure out how to include it into toctree) * :ref:`General Index ` * :ref:`search` + + install + upgrade + changes + reporting-problems diff --git a/doc/install/CHANGES-binpac.txt b/doc/install/CHANGES-binpac.txt new file mode 120000 index 0000000000..5cbc08dc22 --- /dev/null +++ b/doc/install/CHANGES-binpac.txt @@ -0,0 +1 @@ +../../aux/binpac/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-bro-aux.txt b/doc/install/CHANGES-bro-aux.txt new file mode 120000 index 0000000000..4fcaa82e52 --- /dev/null +++ b/doc/install/CHANGES-bro-aux.txt @@ -0,0 +1 @@ +../../aux/bro-aux/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-bro.txt b/doc/install/CHANGES-bro.txt new file mode 120000 index 0000000000..693f810dc8 --- /dev/null +++ b/doc/install/CHANGES-bro.txt @@ -0,0 +1 @@ +../../CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-broccoli-python.txt b/doc/install/CHANGES-broccoli-python.txt new file mode 120000 index 0000000000..fd01ad3cd4 --- /dev/null +++ b/doc/install/CHANGES-broccoli-python.txt @@ -0,0 +1 @@ +../../aux/broccoli/bindings/broccoli-python/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-broccoli-ruby.txt b/doc/install/CHANGES-broccoli-ruby.txt new file mode 120000 index 0000000000..e04b33936c --- /dev/null +++ b/doc/install/CHANGES-broccoli-ruby.txt @@ -0,0 +1 @@ +../../aux/broccoli/bindings/broccoli-ruby/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-broccoli.txt b/doc/install/CHANGES-broccoli.txt new file mode 120000 index 0000000000..22aeb7e410 --- /dev/null +++ b/doc/install/CHANGES-broccoli.txt @@ -0,0 +1 @@ +../../aux/broccoli/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-broctl.txt b/doc/install/CHANGES-broctl.txt new file mode 120000 index 0000000000..fe759c681e --- /dev/null +++ b/doc/install/CHANGES-broctl.txt @@ -0,0 +1 @@ +../../aux/broctl/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-btest.txt b/doc/install/CHANGES-btest.txt new file mode 120000 index 0000000000..1d09aed48b --- /dev/null +++ b/doc/install/CHANGES-btest.txt @@ -0,0 +1 @@ +../../aux/btest/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-capstats.txt b/doc/install/CHANGES-capstats.txt new file mode 120000 index 0000000000..e6440ca6a9 --- /dev/null +++ b/doc/install/CHANGES-capstats.txt @@ -0,0 +1 @@ +../../aux/broctl/aux/capstats/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-pysubnettree.txt b/doc/install/CHANGES-pysubnettree.txt new file mode 120000 index 0000000000..4067c558ba --- /dev/null +++ b/doc/install/CHANGES-pysubnettree.txt @@ -0,0 +1 @@ +../../aux/broctl/aux/pysubnettree/CHANGES \ No newline at end of file diff --git a/doc/install/CHANGES-trace-summary.txt b/doc/install/CHANGES-trace-summary.txt new file mode 120000 index 0000000000..92c76d6ee6 --- /dev/null +++ b/doc/install/CHANGES-trace-summary.txt @@ -0,0 +1 @@ +../../aux/broctl/aux/trace-summary/CHANGES \ No newline at end of file diff --git a/doc/install/NEWS.rst b/doc/install/NEWS.rst new file mode 120000 index 0000000000..8c4ba8c0d1 --- /dev/null +++ b/doc/install/NEWS.rst @@ -0,0 +1 @@ +../../NEWS \ No newline at end of file diff --git a/doc/install/changes.rst b/doc/install/changes.rst new file mode 100644 index 0000000000..5a1bd97220 --- /dev/null +++ b/doc/install/changes.rst @@ -0,0 +1,75 @@ + +=========================================== +Comprehensive Version History (aka CHANGES) +=========================================== + +.. contents:: + +--- +Bro +--- + +.. literalinclude:: CHANGES-bro.txt + +---------- +BroControl +---------- + +.. literalinclude:: CHANGES-broctl.txt + +-------- +Broccoli +-------- + +.. literalinclude:: CHANGES-broccoli.txt + +--------------- +Broccoli Python +--------------- + +.. literalinclude:: CHANGES-broccoli-python.txt + +------------- +Broccoli Ruby +------------- + +.. literalinclude:: CHANGES-broccoli-ruby.txt + +-------- +Capstats +-------- + +.. literalinclude:: CHANGES-capstats.txt + +------------- +Trace-Summary +------------- + +.. literalinclude:: CHANGES-trace-summary.txt + + +------ +BinPAC +------ + +.. literalinclude:: CHANGES-binpac.txt + +------- +Bro-Aux +------- + +.. literalinclude:: CHANGES-bro-aux.txt + +----- +BTest +----- + +.. literalinclude:: CHANGES-btest.txt + + +------------ +PySubnetTree +------------ + +.. literalinclude:: CHANGES-pysubnettree.txt + diff --git a/doc/install/guidelines.rst b/doc/install/guidelines.rst new file mode 100644 index 0000000000..f0b10eb8d1 --- /dev/null +++ b/doc/install/guidelines.rst @@ -0,0 +1,43 @@ + +.. _upgrade-guidelines: + +================== +General Guidelines +================== + +If you're doing an upgrade install (rather than a fresh install), +there's two suggested approaches: either install Bro using the same +installation prefix directory as before, or pick a new prefix and copy +local customizations over. In the following we summarize general +guidelines for upgrading, see the `Release Notes `_ for +version-specific information. + +Re-Using Previous Install Prefix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you choose to configure and install Bro with the same prefix +directory as before, local customization and configuration to files in +``$prefix/share/bro/site`` and ``$prefix/etc`` won't be overwritten +(``$prefix`` indicating the root of where Bro was installed). Also, logs +generated at run-time won't be touched by the upgrade. (But making +a backup of local changes before upgrading is still recommended.) + +After upgrading, remember to check ``$prefix/share/bro/site`` and +``$prefix/etc`` for ``.example`` files, which indicate the +distribution's version of the file differs from the local one, which may +include local changes. Review the differences, and make adjustments +as necessary (for differences that aren't the result of a local change, +use the new version's). + +Using a New Install prefix +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you want to install the newer version in a different prefix +directory than before, you can just copy local customization and +configuration files from ``$prefix/share/bro/site`` and ``$prefix/etc`` +to the new location (``$prefix`` indicating the root of where Bro was +originally installed). Make sure to review the files for difference +before copying and make adjustments as necessary (for differences that +aren't the result of a local change, use the new version's). Of +particular note, the copied version of ``$prefix/etc/broctl.cfg`` is +likely to need changes to the ``SpoolDir`` and ``LogDir`` settings. diff --git a/doc/install/index.rst b/doc/install/index.rst new file mode 100644 index 0000000000..12bdd3f4b6 --- /dev/null +++ b/doc/install/index.rst @@ -0,0 +1,13 @@ + +.. _installation: + +============ +Installation +============ + +.. toctree:: + :maxdepth: 2 + + install + upgrade + reporting-problems diff --git a/doc/install/install.rst b/doc/install/install.rst new file mode 100644 index 0000000000..1b775389f3 --- /dev/null +++ b/doc/install/install.rst @@ -0,0 +1,241 @@ +.. _CMake: http://www.cmake.org +.. _SWIG: http://www.swig.org +.. _Xcode: https://developer.apple.com/xcode/ +.. _MacPorts: http://www.macports.org +.. _Fink: http://www.finkproject.org +.. _Homebrew: http://mxcl.github.com/homebrew +.. _bro downloads page: http://bro.org/download/index.html + +.. _installing-bro: + +============== +Installing Bro +============== + +.. contents:: + +Prerequisites +============= + +Before installing Bro, you'll need to ensure that some dependencies +are in place. + +Required Dependencies +--------------------- + +Bro requires the following libraries and tools to be installed +before you begin: + + * Libpcap (http://www.tcpdump.org) + * OpenSSL libraries (http://www.openssl.org) + * BIND8 library + * Libmagic + * Libz + * Bash (for BroControl) + +To build Bro from source, the following additional dependencies are required: + + * CMake 2.6.3 or greater (http://www.cmake.org) + * SWIG (http://www.swig.org) + * Bison (GNU Parser Generator) + * Flex (Fast Lexical Analyzer) + * Libpcap headers (http://www.tcpdump.org) + * OpenSSL headers (http://www.openssl.org) + * libmagic headers + * zlib headers + * Perl + +To install the required dependencies, you can use: + +* RPM/RedHat-based Linux: + + .. console:: + + sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel + +* DEB/Debian-based Linux: + + .. console:: + + sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev + +* FreeBSD: + + Most required dependencies should come with a minimal FreeBSD install + except for the following. + + .. console:: + + sudo pkg_add -r bash cmake swig bison python + + Note that ``bash`` needs to be in ``PATH``, which by default it is + not. The FreeBSD package installs the binary into + ``/usr/local/bin``. + +* Mac OS X: + + Compiling source code on Macs requires first downloading Xcode_, + then going through its "Preferences..." -> "Downloads" menus to + install the "Command Line Tools" component. + + Lion (10.7) and Mountain Lion (10.8) come with all required + dependencies except for CMake_, SWIG_, and ``libmagic``. + + Distributions of these dependencies can likely be obtained from your + preferred Mac OS X package management system (e.g. MacPorts_, Fink_, + or Homebrew_). + + Specifically for MacPorts, the ``swig``, ``swig-ruby``, ``swig-python`` + and ``file`` packages provide the required dependencies. + + +Optional Dependencies +--------------------- + +Bro can make use of some optional libraries and tools if they are found at +build time: + + * LibGeoIP (for geo-locating IP addresses) + * gperftools (tcmalloc is used to improve memory and CPU usage) + * ipsumdump (for trace-summary; http://www.cs.ucla.edu/~kohler/ipsumdump) + * Ruby executable, library, and headers (for Broccoli Ruby bindings) + +LibGeoIP is probably the most interesting and can be easily installed +on most platforms: + +* RedHat Enterprise Linux: + + .. console:: + + sudo yum install geoip-devel sendmail + +* CentOS Linux: + + .. console:: + + sudo yum install GeoIP-devel sendmail + +* DEB/Debian-based Linux: + + .. console:: + + sudo apt-get install libgeoip-dev sendmail + +* FreeBSD using ports: + + .. console:: + + sudo pkg_add -r GeoIP + +* Mac OS X: + + Vanilla OS X installations don't ship with libGeoIP, but if + installed from your preferred package management system (e.g. + MacPorts, Fink, or Homebrew), they should be automatically detected + and Bro will compile against them. + +Additional steps may be needed to :ref:`get the right GeoIP database +`. + + +Installing Bro +============== + +Bro can be downloaded in either pre-built binary package or source +code forms. + + +Using Pre-Built Binary Release Packages +======================================= + +See the `bro downloads page`_ for currently supported/targeted +platforms for binary releases. + +* RPM + + .. console:: + + sudo yum localinstall Bro-*.rpm + +* DEB + + .. console:: + + sudo gdebi Bro-*.deb + +* MacOS Disk Image with Installer + + Just open the ``Bro-*.dmg`` and then run the ``.pkg`` installer. + Everything installed by the package will go into ``/opt/bro``. + +The primary install prefix for binary packages is ``/opt/bro``. +Non-MacOS packages that include BroControl also put variable/runtime +data (e.g. Bro logs) in ``/var/opt/bro``. + +Installing From Source +========================== + +Bro releases are bundled into source packages for convenience and +available from the `bro downloads page`_. Alternatively, the latest +Bro development version can be obtained through git repositories +hosted at ``git.bro.org``. See our `git development documentation +`_ for comprehensive +information on Bro's use of git revision control, but the short story +for downloading the full source code experience for Bro via git is: + +.. console:: + + git clone --recursive git://git.bro.org/bro + +.. note:: If you choose to clone the ``bro`` repository + non-recursively for a "minimal Bro experience", be aware that + compiling it depends on several of the other submodules as well. + +The typical way to build and install from source is (for more options, +run ``./configure --help``): + +.. console:: + + ./configure + make + make install + +The default installation path is ``/usr/local/bro``, which would typically +require root privileges when doing the ``make install``. A different +installation path can be chosen by specifying the ``--prefix`` option. +Note that ``/usr`` and ``/opt/bro`` are the +standard prefixes for binary Bro packages to be installed, so those are +typically not good choices unless you are creating such a package. + +Depending on the Bro package you downloaded, there may be auxiliary +tools and libraries available in the ``aux/`` directory. Some of them +will be automatically built and installed along with Bro. There are +``--disable-*`` options that can be given to the configure script to +turn off unwanted auxiliary projects that would otherwise be installed +automatically. Finally, use ``make install-aux`` to install some of +the other programs that are in the ``aux/bro-aux`` directory. + +OpenBSD users, please see our at `FAQ +`_ if you are having +problems installing Bro. + +Configure the Run-Time Environment +================================== + +Just remember that you may need to adjust your ``PATH`` environment variable +according to the platform/shell/package you're using. For example: + +Bourne-Shell Syntax: + +.. console:: + + export PATH=/usr/local/bro/bin:$PATH + +C-Shell Syntax: + +.. console:: + + setenv PATH /usr/local/bro/bin:$PATH + +Or substitute ``/opt/bro/bin`` instead if you installed from a binary package. + diff --git a/doc/install/release-notes.rst b/doc/install/release-notes.rst new file mode 100644 index 0000000000..e4aeec6db1 --- /dev/null +++ b/doc/install/release-notes.rst @@ -0,0 +1,13 @@ + +.. _release-notes: + +============= +Release Notes +============= + +.. contents:: + +.. include:: NEWS.rst + + + diff --git a/doc/intro/reporting-problems.rst b/doc/install/reporting-problems.rst similarity index 99% rename from doc/intro/reporting-problems.rst rename to doc/install/reporting-problems.rst index 903df76257..74f37644f7 100644 --- a/doc/intro/reporting-problems.rst +++ b/doc/install/reporting-problems.rst @@ -1,6 +1,6 @@ -Reporting Problems -================== +Reporting Problems (TODO: Move to www) +====================================== .. rst-class:: opening diff --git a/doc/install/upgrade.rst b/doc/install/upgrade.rst new file mode 100644 index 0000000000..696e96d7fc --- /dev/null +++ b/doc/install/upgrade.rst @@ -0,0 +1,10 @@ + +================================ +Upgrading From Previous Versions +================================ + +.. toctree:: + + guidelines + release-notes + changes diff --git a/doc/intro/architecture.png b/doc/intro/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..fc775160caafef9e83baccb49b1889f57ba9d87f GIT binary patch literal 139697 zcmeEu`yYmC+@DPF%P#WHwz03&&?Y~ z_gGlirCC_m9v`P0F7T9(9NIn(IxC}+`Ov$@l!J*7?5CEDSP^zB`% zvrbvYzAY}z!JK=ORwVQ~*ChT|<Rq2dM83#okrCzaa-x6z9;67h%oNU6(o)2*{D z!3pC(GbwM%iW4#56wOq_!A|kZ+hC` zNb(PbMZuE8O`Lj7BhD(d4)*LK-DxwHUSbVroKq`HUOD(;W>ivqYSs4nlo5U#OSTaY zce6j#gX;L=CKb2tH^&)Zt2e|~Z%FA0NZxWY^74EksC*Dj^|yl3N^@2{o$cpLolPW1`h>iW4L3omgFb~!ON!qJ#3JoXYf@oVWhr%2F< zL6eROfm0l3J9N*nrl8gMkCD+?Q=tovzdzm5eSbIi;_HrY*ERKIE_O#owf8xwoiY1$ z(qke>I|Yx5O#CYR?Lxl!2VGQ|cS}#jLj#LZR+^M!<&vtH3;+9azzAaL@a;C8HeL>H zUr!xDg~3qyO>&c&-+dt+)4S`m%c1hI=IGHC(Vc-5dURI#ZN-hVWf~Oz-7`r!CQSjj}HT=g}**1f2VE?cBnIE6&`Sed-AMHO14^8R1 zMV`_vJQu1Es<FWO>3fk)e|chsJE9)E1LVZx^!e~;MktTH<9Pum2M{0As5yTiCp57;mqO0 zcHQrcEPgKZ2!~87yrp>n_^< zHjWV-xFm>~m)8ua`}RGd;9PUWndCoLCU={!`A;14T(&lf+5fJ)_~4oKNB&UK@y!;| zvFKG(C_z0xforqj+bpr*#vEs=g--d@uEfIa*@@@1KLf+IEirONx>5kq{ZfFauKk&P zp`T7O?$-|9vojf5-jbfd8((|I^a{`I10g z5I9rE{GVghdgZ+L@_0Rn{B0&$ESVG{j!Nqf6^D@q|Iw2-m3u=`I=#%+xQ2NWy=4Wb z2~%P$wYCOJ4t#?dyY4NDf*p0!b)=og#O8a;5>x*U)8hzc_tnc8D?T{c>SbZzjm(cY z$lmKBJtuOkv7V!$K5ilxuWb3nR;0$LTV zmw?Q&lFr?#Dsr71+93L%`qzAcU9MJ3iJ=!DQW18I|3Ze16I13l9G-Ot!+A|uHCdFa zh=~2h9xid5{h@@|nod1FHlG5Z&Rv&)Q%AvD`R7(sgf!K#V;H&-z=xok1 zg-D9@9Qj9xE397h^OJ|}R-Rbp4BIhJ2_8a!dV<_*3RivW6ToR@x~t`EU!O8Nv~}?K z<8b$~%iznU-@0=04rH<@X@!yvz%0v6WYcfGYl$v;AUXI_)75Y!;7kWbEHx)QZS5Sy z>{7$%KPoIYW-R~JxI)+Rz&nb}S;1@{zlEqd#s@21IYA1Y zw}ULe{`EtcAOqK7o68;tQ)cUM5O~7uS@U51AW8MQ$=%6qNl#J8enm>?Qs8{YTGu%D z*v|?i-e%?OHm{DS+drf-62bP3bu^;;UqTuD!h&GwZ8|k=U7EYMVw?DvakbPqb}l@WlMR*gVrpyp`T6N2)-Qn^5zY3e^K$z#N zIl8wGr04n+Hl=e-KfPe767!}erPt^6-Yv2p^gkwNQaSATveJRc#Ut4!pY;Q%UKsvz z&(c#x@cPaQ^+KF_p(kWOYft%KPb;!#cv?2yedyQ$TGSPCQ@TP+Lm?~RihRZwzZR(s-9q}T2Edc6Cp34piWaqFLO;3e&d=pm{AZeSICH1)0bS6+Zi=plQwdW5 zdTD+AcAGOunM`O0CL+~B^#G-AI#7r?e? zb(^3z2Fb>uaz5@6gS%SZ)~EDU?EM?GmFBYTad-b7{F-|3ftEZ+-Aqxx28l|5FJsaw zF?v9-(QqAPsZ`C|-$5HA4#p|NJsMYu6t921DEkX@f}X!qqX&l5GUupsAPRE2Ngek^ zAogsLtZTAiW6cn8&F$YKKHrJ&eOKNM7XFKB`saU?g)QCuV|s8#TJz+mc{&?%sb#2f zWTW`fDWH_d@B2YB?2q1~oFsQOBc`|e#FA-HBVr6S?YsEhEh zhx%L3(h7{{HfhT5U;QlHdk2s%S`5B~I9T1(C|vPdxZI>ulGCpF<`}$7N5Q!ULwEl& zT88_NPZ~0PGI{Zb(*KTd7q2pLQ8>L`?q7iYuUIUbmt)7e+!W>aOz7WPT<(N#PN`@w zZxCuD-_}p}ray}HH;3zG_RW$)0(FTQ>`slz?=fQ1@gQy!c(KkJq#_vN^7iJKz2g+c%d1 z>|R1-ii3Uese~)I7|^9*U}A~qVl%#C<$DJ~Bt>f8{R@7m%VxKfgmyJZDI-a)G#n_k z&+?rCyKjB3pAAECHdfr;>IAWivdh3tQtec8&`7&vP0-9yd#xoQm#xZ@#p0r{vN*qH z292XMrW+_@Pwb_VsRS^cFdz(V6ZW9b+tZyoM1>2t8t>{8{c@4C9^^Q5Mi@3j;M-s2 ztM%Rg!MFE=zyMMV;f+1@4FJBs4R4_$_o-4;efnC8feKb<-{-Y8*#@KvB!AfFH(2BU zHJw8LlTxF#6tB-4vvrVuOkd?5KW?T+RG#|*I#9dK3U|L*npa~p8LbOYp}tZ%9|zlV zf%}tlSE#veWpMYVW#sF^#z0kJuNx~3i=`zI^*$r?efreCSk?Zz%DyjT&;+nhM(R&_BW-j=!#ms5`z*ynAl;xVGHT7h14|woD2YfcM8EeJC}aEpicPqUHG~`xw1D& z;F+A}@o(0t5PT?MzzHJ;z+A{6gDnsuATTCiqzM($6yr7R6I5*#Qa#YJzuN+CrZ2X@ z$gapO*ZANc5t3C7?6d2&@ZDO33y_?N;M*~g!3ZueXL70( zH5CyMiVcu}jzI5D?(a?6BeXPiC!x?^a-pv@WmL9(Rch5@%;wfh=@BE2X|=rD3h*2P)@kG4neDY3(As-9oWWbp*8V9NdKZOkuumR9!In^7 zUX3J831&P2XxX%G`4G6MfL#R%S-&W1{m8CnWh?=;Z7V!VSQ9z(Yoco}I36FSu}sr7C8UN)G{ zVh$pG0ZCsFr!f6KRN3oeZTSMoMcjZEcUDsT68o+rhZIyrCZOq+x3X8(8v~%B&$1MK zMhd-$H=q{;(wL^Nr>Ih=cM1%43W$@-q)D$07yCeK)Cvu~q9+VC`=vKaKGVLuR?ith zMQhgLFIdjbW=pM~mhxT3!bn*Eoi3MXbSKfYO9T?8i((wQ-D8avwkYeKE{znPp;Qf5ZP6Yksn~1%!eql4@OTp&xF<5VBSrM_tw5O{ zFqQ+8?mH?$=?4U?TzFZpda<@<$fx~%`wBwt?KTxe1fV35?n_J{0s`4vxx%OysFldQ zB_4209&|K4G;>lma;1#cTjsGGGPT=_UWhY;=EM5*j{Oe&lpcJ3k3d^&US8bLJlk(T zi7=?6B3h`30nFYwhG#ov=VQv)Y^R=lX$+oK18Op?gTc;Un4G0DujahTNTLjb z*Wy{gslGFo>~^8kwcE6}$nQk;I$k&p1#hC}tL&U<{42-`r4BS7ZEnh+wz`;;v2~S-{1KJ^o+EGeZh8WQ6Z=GvsI{?}~ zu(D5I5p(8m;lP^M(l~82y$(@>M*@P20>+@LT=4SdzgYAd!ky~N{|Dg#++Af7pqQpC zc((@JNL`cK_o+|AK{Jk$sD)rJvHeR}!tH@JXq``CZrM>JBrpvSl&1EEd0dBaAAcl@ zg``^rf3SM>wn;GIJ0Z+xGPu)Zn+T^9!Lz@QCGE9I(ZW^h7Pf11!~1YZJG_P+h-|;V zX}_+{OPl>2>3}Ef?=jZzNFO*ee-=1!yfKSwTCkhN`z^W8IIyn`_d) z$KjuLw?IhdjXVjktDxLVPL%ER87#EZ2O@WUES=hfk3!()IB5AL5~ z5j;{+Ex%8K#nOOlHPWN2_~8DQ9^%+z2&lZG;N?*?aZNjUvvCVB2}J9(3Gp-Up~!4$+%GZ)UEn zsnj+9hDW&Bh}8gi$BepRw*NeItG#)M4EpU4+`TeGR#>4VuV|H@+P?nB&wksl76v4^ z7fl116z2EgGW_VUpI?2*SEjZ;aeEgSWr8!FK`Q&e!RN;_eif~ffb?N0_#mGcOUq6h zxTRhVu_k_75AZ!Ds2}vqEuw9zdb-eCna)FPZ0c*w26QFKfpzoC&4VcIQl(SR+c`Xh zy=R`3)=1sr2@qa%LA3ncGBnsQM1d!$(whZRd(Wa)g+7$+d@d6$<6U#($42sHS_FQG zdy(X51H-QX8Gi>gu0D|UpzM$=njFIjBb4JhQSQ#;lshlm0pst;#z#UuspVQQ8!7v< zz7$J7--=Vyzt!pJ!)3i%{$bZ6to-}?#GEIUW0Ss5mF6}56#JICzUGGT0TLlV7w?xA z*T~?CtWg@K9dms~)0l3;UHoMrNrKSFMP2Xy}k(mire!ASk=Bruej`_@B zq|z5`%~#e3P6F-%>nb*;vM6DElrW!ygb6Odv#KC#?xlOvm znL=CzOi>*E@rP!!UvJdFA#kYgjHkUjF9d0F0bDklMcy`Pa-Ftrw4wAm5SFzmiZP?A zh=`!I2NykH8tfkQR#{Er2MK$IYrC#xok5(2GsU9>e2c zu;Vy9GkdFKEf2imvzAng|49832~a{(Gm+=vEx!|L>t{eod#7Fpv42lzyGsGRq4-{) zgy}|=-L6RjmSz7y@@d|HqVd|8pyc&ch3MPR!E`&iHgIYU(2MN~B0*{wdOU@;?6Q*w97bCzIcam2qywL#KHBYZ; zo4}C1apK-y(?HZL!fvvr9lToax(TkdpAockAgf7{)f!mmqtmYf>+bH7tVFe@`N?_x z;Ds5^iFrm%>J&nmFu>J8Rn-9C8)@Rk`irK>T90~)`dPY=lHKp=XfYr;reXB*t8{Pz zgHYK#ytfo3o6gJx(njQepin3#_NIXE;tQwB^j6(Y1$7T_hNHRzP*Zd7%0IPUUn};j z3VOps%Tydwb*VG|aYRZuFihXz!KrQ8en=}OMFsqpdhrlu6ttSdH`~ChCo}S4#yQ!u zS-=v8ZYcq|;WAiwU-7A~IYp1XdZFgzQKZ}%e^_;Nncr4)ni`OOE{Ia>Kl<$9(U$xO zmHM0%AbEQ2Z=mn`u(~k(Z4|gCpQ0|=^=`|>lyZkh8yi#c@zmlkCZne?>oJ>lh9cE&w8G|f|--o-sd->5?|g4{u>^8~nh-HLV+00+LX z`XN8wv8(ci%o_JP=W#-)o@XJr_S$S{d0jm~%I-?u z>gU5!Pl{HD<-za%U=S(Hs=}|@z*NLyuhnEj>xpKM>$Ez@!~xEf6ONN~($wVg=b-tg zgm^x#6w8*e7iY!zz`!5zJfc9#V=)?~>4c^*IPeeo^X-3PZD$UzSh>XcQy|HOf69f} zPi%S@eDRu6Fhy=avKI#5n0u>&dimCDpnJl;^I?E<6^UJPrLqW9>tvpmg0M}N)0;UW z=4DiWb1NpiZN5;*gYF0rJGt|OOtPY}>NGp_Xi%X~*oEQoL_9S$Bv)nX>D+f*Xe=>f z&BGd`>t(BMyslHUcyykCD}bI|853=oj9Q?MqHOfwJAc}W`JovSx}v^yUqC^EEC!b{ z`VzHqt`Ta&yZ0Ig(#5?eM&!%Ye0*STni5SK+$E!}_bf8xQqD>mk~d{ILqk0iwTab9 zJ7)VEW~iyXX+y$x6H%Yb0Mk|hF)`&`|HAh?%X3QxM$jSuVeUR#pQ8q;hMA-VUuSs3 z5AG!s)~VN|Tiqgnhx8^Ez>AT(NAK$fz!m3dve~r+@5<{lwZA=p^7MjW29}_bB*1;^ zCfRtATBK-k8eXL%RM1zUF;{Mmuytn`a*ezRl`tIO>eP0|CE_*l^l{EWVRFE@`KCC$ zEM&sHZqzHHp8WR+f`13NIy0tDxZ0#fs~gd%saf-U1j+Py7J`QL2W8X82o?2qAj}@K z%G%1{Ie@gw?#|W{v%b$QFzxJW>jBYE!DvpM3(l?>?cxyyd{55vM~KjCx(g&XKMs_v z4NFd*#DnW*AxCN_{Bf&(<2JjT-lfE~dQVu);}GT5B7OHeQ~qNfJ0E{?w2WFMM}=d= z-H+`y`XAG%@k_)z8`K6k^wZV3PmG9 zl3X;3SZcWOmm@SW@Z;F#@ ziMm~y+ewD{2Ar;#l(wMp3Wz@5zmXA5p=+4A5Dr`G!t6Dse_{dLUKG1H^~?v-PBfRUefS2Pj!6oh4D0tFOSUQ~A75scW&fw3Rv%lTkWP~{@D`NaDR7Eb zZ--mZ6}mIVhDHxSZ&E4BueJQ%c78*Agr0Nj`t64a>JKDF5+WB5Ig7Q^>G;BwsrQm zp8x$Rz;{XmDJgb0v7{m!Zo3-|_T1)~YRKJ-(;i|AkXqDssErkP*hWQ&&kqEIZq7MAJZ3%9(#=SGdZ>fd4wmeKib9Y+0xPOEeV@0Eu&aZ zY@_c0EvYiMfF%4Gs|A@N75t@&mV_$5u0%0UtA_$353CHb4SB$1o+xhbw7KsCIpD0i z)cinv_yho6Dq&1|m|~8J0VjWI^M`M-qNtyU2<@?DMi*qeE_8wm%Q0oBu$q$+v%$=AI#@X0^{HE9yXnWAS_@6+*C}^5PoHeYvB~#Trp=&aYjX2AC-m#HIL@*G740) zDSt5|F(b})uY+J!B`K&9?PjmWT+gZ$>%>qQ2592NvCjMWq4eI(s~PS}+qV266$pM~z{f5_M|VY_}!M^g;bw3Dqh5wTdgsxK3Z&XEZIn z;WhOb+ckIGn=LH0k$HW?#foY833r@2)9}UbSOAveu>$}rcO109zvA^)jyv9Bmjwmv zI=AA(OB=v$dRW&kNIkCLRR=R9NssP$f~;0Uk4HJe_2VucGhU_~&2aUZ}CwXrf zfMW+5kh$C#jn?xDMh8`l(QWOs*oHTM<(D>ZyUzG*x(vr241CXkp9SNq3>d6plVhkk z)8k@t!>C?z=vF39PBq8$zgmXk%%do7{n?*MmJg=?Dzp~1l|2^^V6WJ+-Y!#azs}U* zL9MiuS+lF($Fhu!U_@s?Z{9_XC zp9j2Sxs~9b7LJbshzH;QJM+N{qwC8UdN;ke=ioNbe>F3!*kVc;THxK?(b)Z8gQnjx zz4(f4sqDY=|JNY#15RC9#4a5)g#X*UzzAjsmdmd`%i~}d2T~sh?>)jKkMc76N@jcN zzpuo5E1a%-FlMP)aMk|PWWXdE%e`d5DoI3XJDZ}`4A2LlW&Ve@yFlwF>+cQ%tDzFP#Wx*Lb`M;1Q#{$cO-d7x*q zaMLsg0uUSlKY5*&eACaUqfh4Ndus!ISiTC%!D^~##ta?g(|VfA6Xjr<*Y9KD(s=sl zv%FUvAcdMfSwInIvap|jTPwrlHa58hD zs+}wU@D@I%-uv^IfPZ!QG31N3>uPXRY-r@Jk1FBSGP^v9y|v(x3V$pxr#|E6=!-C= z-ba&z)e?7Sn!O@aDJe%q`?=j;T1NK*6n^BN3u|?CP7dUlD-Aq4Jn@J~h^T!!@vRan^-Y+MSnV zmN?<((j=(l5ipqvK01gg5Z4GF;F*g@D6Oveq>Qk*;@Od60KimslSrdlFhgrWA9QEm0m_wpkk zxmED^=q;tIAPMf`E>cHqd4K3ycF?&OmB!vQ)ZifF3IVI9iH&-x|9o{$pi1zm6qmQB zVr&%Js-?doS#Eahj2c&egV>EKT4y|%$%>c@^Q?2ytnz7m*2;EcNsIfooH(hfYRz&@ zy1qoa#shTLC%7$K>}m91?r}-0u~c5+**rtX&qFm7xj!PpZ%s8`vh)P?0kWk}X!iT? zm7V-}aa@FRR3ya^KnKVKfUlPC>R3eJXEo1Xf^#kzK3R3VLnZasB@c{rbmSURt1IHv zJXKXqN5cx9@|1!E)jLCf-iEA)i*mZnW169Jizxe%+FQr+Z+Cc0MTFl|8=RqNF8iSX+E!Dxk0sY> z+I@vGyau*BlkHF6#)K>^??^IUV^=1y`$cSA@11P>xj0T~zXvr*nyX)|$GTCRlMo@I z77tyM(HPBs$4r*4tm$s{C{D{g!|s?A!^99P@R&TI7@Nm#n}-wVkobtGv!8um_jt~x z&vIbUks;xj&TETDGMoaG&dZy=(MK7Zo%V6mKLd;xuATdO^fbA9)I`P`N+8=jJWRE^ z?GW8Is9F1_MQDdj%4P_||LCH{sf1c8QNgC^+q7}1K*sdbdp|*w56?&5AGz0V+3xde zpTv=SDg-urr-1^X7|P95`dgox=*h}BAzarZN9|*$`@Dy-7Wog)s`TrnYKm)|CUY4+ zc6}8mLtnVdY98l(NU^!$nq?^)O690#VCCAhU}V!wik0SuLc7WLpBY|s@|)wRzk)F= zEV)|Tq|~c6gYw*&N~j{utXRV*$9?fhRR7Yo&$qnWa`k#%ohm<4I2$7&?6IaYDx>0B zDm|MK_&X3(d7akpNb=m8;!I z?GzCV_07@PSd?7eXWK)!L$9{WHF+l*VlyAoXA<;pMJ4H!3~Il+%_ZKajc1kr!jg7j zXYS6Qxog(6@JLm`1@)%c^6;pMpLhGWX21MlV~M3-M`G6r5!Ff+udLT^wE%0`imost ztmxt&;->dmb2GlJttv`GDO<_9%kp+>he};24-fr~n@os^E8AUHnMyRl*c^Iz$M?!7 zr)vpG7ltBdb;ktFU$&!PM4Gr;W+%3B*UWMAJ*blTJa(HSO!d2wxrdB3CQ1o?|41dW z=S}qUOaqG$XB>o=5HMYi&ss5&x-&+6sJ{(N0j^MpNIq}0kpW%D+t zpKR>@{1q`(w!S$Vhn_QMoGZs8RX;xD7|W$9p5$BedES+HUprmZtts%&+5?*~I|KT~ z2J!nQo?-VAzu)n;{as!e_vEsmTr}vzv>;al0E_z)C?+7rrsu0PHm2%*A*1-JpXk6v zp{3d5oRh$7*@UZf5ldw4z4HdtXDZ;97mC2KjQdTRS5Ei(_SC(iKYDSqi}$aIe+Yb9J!my;EE~ap7rHa=kVLyBXOU6s!8Wqw66LG-bb>S zW~x3d#6aiS`czc34JHY`yMot|e{-oC<{RW?=BoA6W#N=E{n z2w<_TJ5nNSHxJF9RJais^Q|r$1z@jsuJ9i~90wb94}K8TGGWGKmu!;=UjsO*v^vvt zssX3d+9-TYu{-mmhEAaFHwY|$k z53rlKc)_Yk^m|eZ@QJBz@@oBgyUgQ7VQbEjur_WR(yR+TOHp$z?lE3Za@{8lO!DQO zWP7WfPNM{|zg9cf+11p4h2&^xx{B(Q{Bh zhn100d&x#Pgma8W%pIwT(Fu96-mK_@q(qBD0;i8;r zAXS@bVfw~kEN)idH$)O*3V_Heu>AUn{$*dKWILB$I;-^Sl-)r0&D{Q*O;pec_{eXY z@9%wl)WUwXbJh09-yW;X)T&YkhQ2X7l>dRYE^GM|tyoZVQ^D?aZv`dBg1{A%SKe+L zgL6{(;%j~AJe~H-;~VP<0Obwe4co`zgYTHVS=T!50f!ZC%FWTZ1xy)i^&I*N!@$>6 z9|JlpTClQi2A_&0La}|^tVS7&U9p-8-H|t~@ZS}}p0Qs^5qJ6^yk;bqEc8b8DRf8u zZPm%sxa+Og9Zc{4OwqxKe#{P>Yr5%753KVvxg@3KbS6Aj-^U4~GwAfz=;Hpl^2Bqo ztoZ?wVH!P;X^P{XCP~`Y)v#*mCEA^d(>>7kZJX+~&Uf|C!u$m_F3GcJ)y-}4Oi54I zknu8Npr3EeICwp_+g~;b(c`%b-ajyT4G}J!O)6AcIK%&L=CY;M^E9}~C}dnv=oH44 zd;&aoJRcZ_#<#4mX)19eQW1aEPdBmU-xKt_c3-*b_j{4U)+R`6%)Hf%ubab8bZFd+Jm4-b42^=5bdyXe+Ttk&-6lYN(3dYxjI^A5} zur??6gR0&rnuagh%!=Rq_0{IA8B&z@ZqEy_z<^+~nz*UAi4VBcV0QS8JFRiay{5jJ+k5D(W5bmucOT0w+n+#Vl)rEf(93V8=02QpS}7VZP`?y zAJce&K5OWKmJwAzBgyeU55Izyn~#0+{}H4i|HR__vtrNwezdmQ=2GILNxYU>R~Xj6r*5>R&M-stYtjH^XmvCE!SwXfaVlHEE5Yy52j+qIaO zn*~ul2EtA79f`_9w!ZQnDzj17DWE9C2Xq1$=i0`}V<`b)u%&D&<= z(v6mrJugWzeAtwxp!e=TV^P=AOx&~-`>j06p@-h56xmE$I4+5~usK^-bR5#&tXtL) zUO#u$d2MJ=h)D8Q%PDIN;svloW*mOw-FMEKr_7%9gp}5AR+4f_tE)L9O)Q$fbt#44 zB23PuWv^H4_++#O_;OWtpyd1b%RZz+<_;hW6{QCB}cSuOLW?wNyOqZoRb*eo7WKOEe zy>r;My069>Tn;kwtoKvu$}_pBUpn~bf=+D*?ZsORdGsOZKzpx>CLvRo95WxFg3jTzH?kbe1+qRvd>qR4fQ*sM&P^@ zv5MX|ru1oTwN)o_8}7?G`=2Hr1%qQS@&Jv*x1+7H#j-BPDev~`6aViabWbV^NWerB z&!&9UQJvp;wQA;v^IRb%c!Cyk*4x{wg_MwGGxpI){}Lx^KR#ij-S*K9WQu*yVWj*k z6$D<--XQYsjkJ{NGa@Jj0-#G*BG?eaAvHd2BmonW#Sz3GjvolJw(>Sco zDKI!*)9&>K+C9=@>{5CrV*HlDjc#y(MnZM50s9LtTgES#_JqC+!lJUKG%Uk9TTx9% z)~w3|G1@Z1InT;vJFcqkh<1iYTd`s7JcQtmkBnotgV_j)avzUafvr#IshyFAPyT&( z5hYhwP^@e;_|>f0>N2oiR<5}&PC&gkYW%31awLvck=c^RYSRB+6?2mwm0gfVJ{G3U zd!h1Yca6yXjTa3A@Gq#NS5q^oDt1Tr8?-d;Q*LLqCY(wB-LHVwOBT7MWFsHB?tjMc z&kl%B%%8i|t<&{R%j{8yKM4^V><~RwZr0=M^1x$XwXevg0qRAH+1lGKijS~m;|qaw zN{|OeLq&gUiElq^Zsd{?vPR43!%)B45)AsI=DOP5XXeO0K=6FAP{5)kpCbh)-NeRr z=Sot>9VvXpiTqU|<(9uE?)0hz{ZUd#O?b{)SZkr6y2~AQvcotpLhaUxA5FF0N@Vi5 zz?I~~x4RF$`L=O`9&E&&)sZY0FQ9DLQqG@l<=%JNRz0)*I!v_VWfI&A_mgrPmNHir zSJ+Q;N_AL2Q7_WdbL~)^%e|iugd3$71rindHQ4J`wM?)>#-&6EfslsK2b=MehNKt8_g{#955}L9}*4p=}1;_tu$q;>4DFk6eu+B)!khUcvSsC3gl#FmhV1e z8@+mq?)LMD%Avx%);NQmz6|n>)8b%%7J-ae9`S0@#S0O?R6JaJ5QnNG3^Zc2&cnZV z%ZjgCfwq!9UVG|Wg2&fy^RkZ|ly)9a~xR9!WTA$}&}0@=k{ z)uG_{ipbK!m8zp9a|U1fq*?rjR@cdCgr{n?dlVI%fQqt)@M3&A1q)UGj7|;SO7nZ> zfSE(`_0KhQep(L^;x%URp!5oz8>%UpCejuVZfNa{%RrTk!TTX}OTN9ilky{{kHULQBr7+1)5G z)lGQ$;%m6QL$BRoS6tljw(3CP{u`I4at?pUsgLc3OPZn8;_c^Cyf=@$D)|*6qI4%t zn`bQCXRKO>Z@m1xEZP-Eu)lF4XRU8G*XKpz!+Di2+1B~Nrbph97sY7Nu$`Jq$K{S9|jsOBrxA<3Xv2T#gjp?ur>T6~#QWA3iBaL#!>6~V&kbu7ed7+y+5wQL*-{q$RCkEZ>~#-XUN&hBeW z#jDT1&Ns~+-+XS1(u;f=d4l)u)l?%|y7x(bq+!+DK(3x!Flg~GNNsG$SjY!$-ub4$ z@m4xV+M+pS-Wa~xyRm+HJ_FWyF6qhN?EE)}vn)n`4?na^&%Q5nM&-2SoV90}wH+!O zRSjzJ;xJ|Y5>lJTDo;B*gAL|bn9FAn&gVGD-|X>NJpTg+D#s>P1fWc^iF_z?_;bR4 z{ujWZg%4)RUWzT^!;a1dnP*HF@39KVnH68n^nZ zbz(M1A=~2hXWvQJ-p#L$m!wasiSSn%YP`BWMnFB2VT%`dD-%@4D}x0exa977#LXm$4cOh*<4$zC%Se!=Ex(WA2`vqZ6r+2clbZe_?M)0_|A54!a1zmhg znQ!&uC+?l0-UT2kZXG}wZ6{ogrVHkaJ*H(dxTs+o(Io+z$$^P_u!F4IIA)n8w2ch~fvZ;cb4 zrg?hzM6SQ`oc&}Y2!e{wyM)b>E=9mk@2I)kosw$fOocwLITQ<%`55nj5j$39J&oo9 zL6mnG2^XVg&-lgFFROQCWF5n(xyW)?^3&2;zg7**&KeygB&APHp9pn?ggcywTGxz~FM6*i~=kx`x{(BqS#H>yYtQGRJxjC7z|E+uF2`CdeF) zXt{gRf)<|+oqcU1$Z}cdvpb=45EOxZzgV8+?IY`l4tl|hAcFP=-nbhL-#dhw_gruo zs`F(%*7F>FUfXx}ID0PnF=DiN&g|jwr|M6Cn|?wW-SLwgG164yS<0&eUHj6^=pPs>(W9O!pxE{xs_J9ci;EPr5Lg_PGMU* zW>NcMvqW^+v)1!cQ|J$e;*Jl@^#SbER9B#~;Tl z^P+Ym;DN`=*u3FGH{Jdmx>VTD3ky!BvHQ#_q<03?)7cart9jXSxoJX^Aexy$w=Blj z)r3!EZ9+?820$X+PQT0(YzGv}{GQibdPGSGk7h3zS6KXmGfirNbq&e-Y53jO z?3&Af!4YLp`%l&<=7bLQeb-X-3g-U-u|Q70b&>lx{1@otpP%1K!sf53&AH%Lb6Vmo&Tsxvy%MObL zrR=#BvnH0k{N%z~5(@)EjH)g_*>T!goFf-(1%i+Oib(F|H!zY^TJr|YiaU{o)@WWN|r5Wk$1(M@jiyU^+L|NAmCYnQIaiS(Y^{_{eKGr2$`p9dU zsC)z<|MFIFBFG#~_cZr#qrYUy(bOd&M_iCAd7`GBzHaksgI@K(USojkRS5S5=2Iju z{)IF!xAo&ymh>Rf`4T0^^i5sUt1OR`e`oV z?0P0;3QpdR~O5C2a*aY?WSK zIp$2|X<|af&1m372~CJ_lt;<0vJ6ap8^fzKG0W}v@XP;|pfG3PbsF=XT;~l)l7RN) zU}M*xgRxrYCkk$-8EZw$=#M4y>Eez*L@s z_7dS#>VqF)R0UKt!hlf&8iY(76!)iQ_`zfLpyT`*m80g*qALD^A%5XMVwFFsRa2Dg znfxlR2owXH=Of0PH)9e3Z?}~G=}o6^shR zNp1Pcf8n3;*~d#!;WHqGl}Lmt9JFds=Ug)f2pTJd1*d|A7gpRU12CIu1EqA3YdWI~ z|1?Hkg)eB}s>x7ais(zUkALF&L0Rjd992REfCAZ+F!}nDL<>K5_V3;WOr>_&B*J z*1mPUg`U?sIR=6g(hxWROem`Pz+_))e505fZRuA&;w=t22hFVj7@OysIGnQxdcqM8 zj3z*>YlTxe4ks{*oI=Q-ra4?w414lV=yBbE&`5F@-w2TI0d4*xHQokS>~xy!!v|Z< zXSR`Fv#G}cZTL}p`s+F;M}B-Xn$lEcMi)YH$(-Sv3AVwZ4osE7FZym%uMhio-3pvG z1^O*mr|pU~pHrcLpU_1n*N)`H!Z6CT8dTGZIrSKg26*&c3xdV079K;|hm{Hp3h%xN z$5?#uk2dz~o)^ywr5wa4JWla?eT9#>j8B~K97PLlI4if}6ULaMjtKjT(?B4FNQOgd zKyM*HU;*3CTxhGX(5F@zjd9{1y>+<4u&ZHBmuN<$b2x~b0P03-O&$>0XvCpDrqYBQ zMIbB94r{rW{^}DP=7=ptMx6uj*)D$k0OonlZ`asDs(EaoL`vwB+3_SHPKs!(czJSz zLgutqi-HkNTmiD-i0+7{Jqpn2JWTS$Mucng5fb3(PKtH7ZO*Gr$qcuZX}Q+stFPM~ z{*{Z$bQE6%qU~$#c!q6*oa|E_qe9>WO8Qm@W0cesZsfIo*~hjN#>x^&PKwgu2 ztY$#HT`z5Z91|tq0G|<(Q(7_{jb{&~&QsyjsVNCmT*ESkBRunlBlF1UirU5&C-OyO ztv^{bL_MOn<8xBPlcX~F`5V*ZF8$nJNF6<2;=8m0r$~W*1>_W6jHYr*6_}so>xtgW zo)-*OmbJoIl;QwR2dh#3_fn&nT$lxs>kWS4kr)Iky718~$7wOfBB+A7 z64)e=u#3Oz@EZJMBstPR<32=wxwz zI2f5B;jJt2ASC~R5GL#z8@UA_oPjUX!oWFvO~?p$&mAcG8jrTFKPH)FNQmfDl9@sZ z8Z4$CBNd-oWDemMLb56Z5`;bT1Dx@=Zp{Tu<&E(KAWA%ipz*rq0Ve)47uoPkj+I?~ zaFaler7^67i@=9Z=1&C0iie`|x)hxF6Piw{b={ak9B|Az5Swj{dtL%q{KBka4EGbi z2Gd1J$F-ga3|nAleo~Vg2EnVuRU3|Fk4pR@&dig48khX__!&`nQgUuWld0?mSAIHC z#*iQX7;_91^M{4_D|wAan{mS~*^Q9+*fl1{oVz^eGcgc^J0Vma4W|N&TlkwsjuW2z zD@FQ>Sz?NRP@LbGF{jzHu7YLMpYNZYUuuMpiES&_K{HJiuXW^po z;tT=UMBzqasM+p_LB?mB$ZG_UL>4bUkkMZcLxK?tKDqaA>8$pUM?;@JLJSX1;*Zeal!9e4S zu9?OJe0>;m+xnZRH6W(aE8OFnw6sY+IDrBGiAAkPY?D;eA%vh^83fkh&{28nw7x;&9v4b9^;*(c(6rYG` zN&XqTAP9a5k=BgP{7HaIWsCfEox^Bs;bgjOqTMQuz2(5k*D#vSnFJyO{Nq479pUSUHSm{;(NSO=@A8V#jzQWPIsgi0RKn;|MoqX9W3!>*DtC!!wQW z&saNm-3lCz0=)q_oNLugPfCGhZ5U7dxirN&7E~=_V{wfIfkif!1?;&@luuacGwL!y zS6pJsu2n7Kdg;8YC|KJw?w7f^0+r%iR02cn(=QM81UNeKc ziU<^gYFjIflV1SoEkqFm{|0PCo1doB_>PpFr67B!y_&{s|`50tN|G6 zDL*q8KytD_|tdL)K2<}RL}?yQ|8P%21oeP&iN$w z#GvgtTDPqIxFC8PD=j{oOY|W?sXFyb6J+4d8GL!FCVzxfnA=2Y`Z?j6OCp#bX%Z=; z+|D`%0Z=?`5DSxJ6yn`hH#@~H!h@|y5Kf!;trlU+0geU1?T09_T_u>Z6G0CC0#lzW{)Vf5g-T9Ot^sfiV>u#Wn1MKw>c$ z#TRa7FaF_9xVRSN6kc2sGVMgecb*G2EOj0L7{U%dH3e5n0;p*nqyafrT^mC0=_G2!n;f%PO8ie)WXmZ8Na4Cbj-t`MQyh$NEeQ21E5fWfrs~Df#&=h~tQZjwE>pc7!p2(;j$umB=K!ko~&l*TD zuo3PQ#;WPZXx*U50I@J-)RZ^TWT#1ye>SsUp=A>P@?Fmbh6_sql7EKgEM(o9_cs3U zDjrGSR_aJz@yP`;IoCOlr$Ig1L`N*)LYmv9B>X+ELv_G$)P%{n%ZzBQJPfKH-B1WbXLzr<3)PTkDvK# zauR6LD#l0gq*r_)7=Yqa&YvB$CS{@@vxdo7Ul&j(w++r*O;m1If z)FRsp0Sy!x+Hn+rJTqVM7YnRlEpBt0F*q$u(FUCOCq9X2zwoB1m~h!@4~%63>7X;$ zWej9a&zJnw7G%u_Tc*gGXbx<0iAJ`=TJc!Mm~7>go`nDoG128jK(!T8NhZh`ULG@Q zN4(idzjCI^en8Fu#TjTyO;KrOi@2nKPEqI+KVv8;5%QX)BXdz~oQFFQQ#j+qc&fCO z1iLaO0zmF(e!Kw6c)1oOb5Z^fV9bSp7{{JoGK{|FFOS8Zt>O&%DB?fn8a5G% zy2eM0#jh9-OoR>xhdnbYXs)wu}=1mOa|K)?%GlGyjZFROew_9F#)< z$|GC0a?V9S^Dh$SmvaLEerQ&l6rb}DkLYjl&yc~NxYReil`r*YR^kcX3?Kp#r9cLw zF-XymB2(!fUFPk%8!Gk7K=B8%G*u0Z=MQF-tu*A1q6*OPmA~3CP_~S6q(U53oxF}p z1#etc!{5;u;}DEa;gZ)H5a~DNPaX?@6BjlC>oT~;Kslu*%r2C3pec|mN8;>jE!qm# zSj1>f#5g{@!NYF;wDa0vp~L)SjH>FKvZ8eg^C)sz9G2_s>p$@yLEUHtPQL=Z0XhBG zs2QFT1+>@0V<=XW^lKjG=>xj5G^^hb|Dl z74OHRXOIaCI69hFbnV9koFALYl3o#MoX&YqqTLyAIjFv56&0v@?)UcSR<5d%iXGtIDu zqjJchYy*Y97bX1YN5R)Aqiu>Tqk@Uke6!*`bRS+mi}p)u#;Pi_%V zz63~Y+rdjdz{(v{wUyg;z+xb;?ZlsWC0dBpqapz#o`zhaC2EyO5pnVux=@ruEk#C) z_`JsAuYkoj$1(uxnB%|zV)6I9Gz7b*Q*a4s=#f8@f(I0j&8)MX9Py#Ae}Lmoe(W>X$`KGMV5tm3vp?|yPX6d2 zztSbZxAdE!z*YJTr&oOwNUqj6L(?`1ApUhKKtVCBEHwclU6%R6bFst0WA^R36*vS1 zdINF@SE)Ik0tKcUhghs~fikV^Yt7JDEiGE8(?<(eG+8#ZScIY07&#8W zA3~_HTrd-0an}MVBenzq-)$Bzw{cUSp!h%91~pC&s|N#0B4=Bi#hU?u>{We@5fK^C zNMZP?q5kgh@Zo<9asZq0^fPwMM{wc5099qdOZwuk_>7x|@fiN{E&k5o{16!YJy_9& zx`Is>xX%3HxP;G-ryw{G2r5(oWZRFQF-C-3)0vEDqEhkZk6rwgJO`Po<{Sa5?1>R) zc^2W!pYxJ~f+~^HR@-rMTIQSiWgMr$e{i9}aOUC6Kl7J<(RVTbBPSq7`-`wcvkn3t z)pe@Tw8dDB6A1^~aT6Mb@X5B37%fjGsCMd~^Riz=G43ukKv87k6o=Z;lzyX!7h}m$ zZFp3C4i-rNTPVz`J#sv^3C~2s&;>!WB!0F2^oyjkM9?NBlO6{s`AN(^wQ5l^E zBh`SArGEer%R#a&{u7qsd^(Q+^oa++PWkhfU9N5Epd{%d_i%_vO@9tgIHEHy`TH?K zJeC+2mxccz0B9z+paiKT7R_iWKKZ+yUdcb(eQpH~M}gje9L}|BrYEXEEF4;XYN4q` zY%FHMZEmwlc}+2GuQS*Q$3ZdWu-(R32y!kb*$8xy?S&a#4aJE?N}Qve>~nD?f&-+uJjRGW?-hIBvIzH$9XK0TlR=HFT%^4ddqFZgNswn08G|l%?tkVZ{|PR zVK>qA1tUtP&$iA2k5=MiGLO_xPN2!IIl(`i(81Ao&3UlPH~fYVF_nMOTAqY&#S3{P z2p`<+ngUdesvI`)G*$i@2SWMLulNT(A;3{QC$%}%0BKd^ED4vuvd!b=tm~4obsj+E z53kBEA)_lz1{a32Gs0q)*!Y+FDJau9-n}Kr7Cg>t4;)5Cs=T7D>qkViiR4H|k-yr6 z6y*_*r|i}b=LsQkWfXP_flJwNk3#qejs6&wJ$uumYsydbHvhDM8S2GhEY}*3{9`T{ z#NQe4j00QQqmj0XO3%8s%D-?{bcN%N))_tL#48I}*53>=ee$P$(E?9vO3fku5h*)5 z0F-*<^@kOO{HoN$ZG;;1R@8%6w7q!QMvaZyb4q~lRhqCCu49sS&SObhP6~$0)K@z>D}Mqj zfxWVJZynB}nl=_!^HLqGb57^;hl=I|Y|VvwtBuo+;<+-EZ31g?kHoU6P8~?G#Kd^? zGXni`UOGpN>|uj{45lMY%TM+gq9p%}r>9^Iq)j1#qn_Q=uTE58WY!2*{^hYmPTjDO ztMV^NW?SVba*8t#&%N*7OyUHu z^bBB#;yQb2a#Cuyaiz^%qaM0M8*Js5FFMlC&@Fg;GknA=MA4}~aS<6uwz4hb)Fl66 zlV{-)h7J^Jx782ztI5lVkI=2pJ20IA`Xpbu&|Ng06AqtvHP>{N)2PCAA%=L{&w%=1o(j@MveA zGS5WQr1N-O(TjksKBnSndu3OwPs&3le3iy?gS(Cxivjrwz=}JPI>(78gyQhzB}*8W zaXF;`*^IMvo?!j6X8v;YxT98m$1DU=m*HlDK_=yAM6D@5*G_ab@033gGCapM?=WXH zb+*zIg4Id@Gfu0Ws3S~W)j5F5{G-hCw{2kKQ~1NL=9tlf4|n5&SR)Zr8UsQue~+90z>t$^RYxFO16TquY}0%)4}Lp-{uB_W$X`rU zX+EVB1~(U8vN~GzU_~PZNX$%~@S10unYicYc>{!vz8}B(*@ZwH&OZnd(4`eP5Cv{N z5S~r56*xf!v@$5apYT~jSfi-*FUnJ|P|G3lH>F`k@o+%B@YX3HEc1Y*f@F4Ueq-d*t%9#FItB;d4u%8RC4B)1uB?wUdBmd zVg^PyJ03U}aYwp zCTjkRuk-s_FFe$8_=qPmxlo&b>XH315BwCr%+>ibTe8^2Un7K<7U@aq;u(B$Y74Q2 zRq2jaT#~$&)LCLA{AauK z7kcr`Jlj7%Nk#tkxZ|2TUe_N^lt@BTn97GSGvGgk*OXGrdiX7v6+^7~)db|@d4O(* z#7-j2)n&w+SqiamC6I$+{t*v^tVP=W5spW6#07{9=NxABgiztK53=FyYo*+a0O6O# z`8+@T{alc$kiPVjQ}!KCZT{n0&4b-;1x~pF{R+q_zd%jzbSS_R{IVDXr&x8o_-{Y? zYe`s0&kLVd9BllrdXBgI05BY}6vb6@9>cD|s>9#Ic#D56aOsx(@yU4^Gox69UCQEa z02i|B+1XwdU!IYf!UB7o@QiY7PK4zdl(6dmZvCYJsm?3QgzV$%2QP~Ad0I0B9@44& z@U?%jS_}rTgMjk!GdT^Ud0rY#_wL5e`?f>Vyw&V~)7(h%fK+X+lx}HKh1z*90bJ=f%UHgPi10 zJ>@?#?|DdVXa!D>0=)q_J=da{oLU9)iQn{cEy)FeHtRsGA!9LBp9Lq1&RQ&Lp~YSc z%Cf4JuVPqE@KJcS%OneShO1^p(gKTFMuzhr%M~pxmc~MGYa|4GlKUSiTQ`rol z+b_%-&hZpnt_faE$J5QnMBx?p)F^C0Ag?beF=b9IXFNgi1zp&Ddt zAQVvLAHCt4@q~z*@+AMTWDa7df0~#S2<@yR=rYJNGX)ChN=6;}GC zNnvOMFV*5-{?J}M0KiUs{4)~RjITb43`RW{#yF}FM{%uIr{~YRb zD{xQ>^jokF>T)&NlTjdVP;w1g7KM1`&qb&f60b2@m||>e(O`j;f6M@&>~6*9+_Yj< zb0Fpd>7g>Ks@&GaH!8U(8qxgoCMJ0iSp27zP$>$t(&VW50||fETlvEt|Cv7?3kMc! zhoN7F%c+_Q%<$BNX#3UMjqvdTuR0v4`8P_$!jR z5g<0`7rs+=L5U*(ae$ETHcZiczG&qG9jui68zw9muiErd|&2W5) z&xqyc2X4R`IB_%5@x`C;@)P??BWdS=bvtret0ha>@C|^(U1~v;GnF_l!O}sGyNEP@ zsSrNc7X>m%zBFt8di$dS0LQ+nqw4~weZl^kw&dM8d6*=T-a4&G4x_JEoT+2Du>A*0TEXa(WC>d zT&?J95z|N}kS&LEEP{#G;sxARd@|xpbRt9}@CzaXM1XMtXF8;~aH1CxB`yj+{}Vt;~eRkwY0MjlyDG=)<49IY&68FLpR&uf{#5 zMC6LmB&xQ2$ym$*{p2Qq-$)EI?t;H04wH8q**c3YKGXrin2TXlFlcVS>LJiqBX>Xedlz zrXS-`q7R1gWrBAmmw#%$TywI_e##Ms$_}IwxyCSb6)v7(q@7MhZ$ZfP@BobXI8}(b zYD^GlibHZ>K5#B*dSiZ?*T71@bgUdgSx(j=34}dxb1p@OB-jXnWE|vEZfe{Z!i^(N z<1vb%Y7h3^V!TAH%fOFL+{$O8F&#ZEH~F9{dvo43%Mzo=la~-KaA^ zoXdr=5ubLAOyh8{$}GF$Kmz^e6bIPMFq<~XzI|HaotGNwD&|6G;3ll}Q~pY${J2FU z1{u%v#kRO;L|D$fcq*de6G1EzDPfaaVWocg__HR?Po!;Xn}4M9T!;QRL;-e;$s&Vg zOv|{gOwx1ki}<$}oh72g^lHuXz`&gm%rp45yZ z5;iElcsoxBG0&*rVl;wcKzu!y%5S)F4Z|D#y0ij^ra*5%4(*CH-xEXYF%OLo7PM zQE%wHcXw0rsEFjM25yu#c*N9O#K*kZn!7Qv90DFQ<`2PS06>Rv@~1;WFk?8IQ{oRd zC*b}zWM1lydf*?|jY^A!IMg|3##c=dKa(vgf)jz%ID*1P=C5Pc%6U^Z4(16bV*&{+ z{Gx|T%Gzb)Piw*e0XkxN0pL%)10)%4W(tY^Ou|O4hzZa~P&jDQ9ujrL*8zIH1t-RV z+Ck|W?y7eHFOykWt}rqz7^VE_07qX~67V6^XtCxHl?zqYk(aTCRwd-1H`uu;W$M%d zdNRR0J>XXgfdZI94HyPM)IkAF!JqmH1el`HR1wPVIL~~JurM}Pu}03$iTTqX zTtLgbO3650_~!)7p8(092neTGka5EhHyjgxj2P2;a|sW+t3`~%+b~S;0PJkOsGqwQ zol4fQQb08>jH*1$ANkuH;+uq{qm!t45TJUfR-oQhp!yk*dbea%!vE_E6dQtVPTUG~ zLkKpt>Br+VZPvEux!c{4!;|Kp7WC0M29^G92`r_uP;NW5W+VdRsJqwtO{ffh@$JNkeJg ztcA2`*#w@P5B_FvN5FYP5VWbDF(AQD4Pc6<0ET2ko-x5+?eMj`Xw)YsRk%OB`Bk4Z zV;E!Z$1E3Ez>W0G+{RubaB%>$v_vRde28Y_;W^j9XPbHA?s{}hnTfs18l50rd+02$Z5Uljkq3^V^81VcwWIm$Aw(MpZOrq0>GDyx!Bhr z>ztKB1%jEe>tcQtZ4R)pu!)Td1s5GC*UXF%_Sm4JPuTg#DXvqj zE!GTmu=|s(7p$O*AO>MUlMEaE$NHuCY6Ca@XYnm(t~>Pk31X&DdN8^cvSYf|Fx{uf zMdKqDjf|NO*rgg_UgLyiT63uNpJfsK*40+6K>eyf^$AG*TCXbGrBH$Nz^{+=A=|}v+DEWUVA9yBOgoH1 z#=P!uQ%2t`o%S3neR{Y4-b}un`EO~vW*4>FOm^P2hiufL75B9i9~++jvr7qVLfD4D z$2KO|p<(k1AKI(lHZ-?aGg7l5ecrimxa@o0Thgi1vhww$IWqL-b7bJ!%`89Q!T~sH z%{V${9C{lQiyv}wfm^tfvvDI)dfP=zIj_VY7pTskn>}e*J{Ac$27^jO3m^2k9JK+V zaEm7&u#?4$s6s{r5@yd4 zhi0GZhp=j4@l|ly=CQh{JEBu?etJ>)e6+J3RItf)UySv(p?G_sCeLy2mR>5h#Nyt!-fSJn+9YI zu%W0hecHP^_(;Z%gTW8932Ha$aXI}skv<0=E?1njr>xfon+~w7$A*n@Y^+2CF>SGV z!8kUq*x<>DHZ)BKxGtLcu}qlwn%+#k+q^}IKQ*2UH%SK~CuVI-5ED}{MRS*u9GuM8 zHg+250VN}E&5SuJ0P-P!V6vv#MIyAw~;zNEb!$t>i z9sQfH%b!oh?PBSD=#g^GN&RK5Rz}TeS$va&m}SP?sM0YxDZWoZ4Vigkk|srcqSlE& zIKwQfMaaN{%)SU=p}eMC9OjL{-pB=k0SuiZq!>7-FlE?~&CV?00n^Y2SJ=cEVm-iB z%CMl}I@^@xRS|yv%rE4&wCjs%>P$2MGCqTPfI>D*^Cl-p37P9w!5=2U1yiMUc7Jq{3z!)VaCJQ$ zb;1B37zrjE&SeDBAdsy)K*Jp|A{UkdPhuDg^}sCPv-4LSdETJ+n6NU@<{(GQWz#uk zBB1CYs{v=#iF7eixrkq^QMjOYGY<(~5ZzDZ@Hbj;fU@A9iUA--_AZ9e6HDi`v1T5F z{M`?xXlebyKVmT#ix7~oWeyOkty+P4RDtSeK2S8cU0C|F8P7!>^QX?T5-e@6KaD+g=L@Zs^J+cyfl}b%x=cpiWe7R^T7a z{F}$ndID$)9GUg>*B+JaTWlkZm)%xxf0BPpS-{yMJ}wF@ZBJe2v5^`ij!6$Y%z?lD zLkqLO3q2-a#}+Atu`0vf45A)pm?P&Jkb)mz=s){?`Slt<@Z`e+q~o}&FPHn@nVsSn zc_NbEEU1n(Qj#44W2mDjDn~t1?rIachnagD|IFVmXhgnv{W0mcd_QTbw`R*VJ^l2Ye9fg+m2c{j64%qfWipCOZd|n>leX% zU71tp+&_nd3S;Aok+;Z4CoA05pg@3MAjJBSe*nT17_`d{sxV*7*{s#ek9wi zL_1eUjD+h(j$Q=J2?bAO6a2%l7?=4+9EMeYgfSSOApyHTBRA%kJEV5)bxMept@e~WMYjj8z~OQuFg)p?##fZ$)$&m+)X4@+p~ zXZ*v8{FNBS1#SUQwkz~isak>hQi19dkovMxRh~<&0@w(!$#X+c84vu_fstG8S`e56N-2yho|Pj37lEUMQ)WwNdM2t2)kkWx*TUF8MpLB)dNe z2Wf=L?Z^a5!;MMu$9i#X;NVVa49#~k`s_pHR(e++I!o_ex=Zh_m3kXDZH(Soqikc}byZH7n4m;eZ5n<~aSX(}8I!QBBAP|01D+SJbB z+=Cdw5f;u~{SBSDsTeuawg?0l#-NZL!apZ~m}#te1%Jly2%$p=*fafv>#K)3f?1x% zDU2)wD}dUYp`jZAO~$~P1_F8zh|yBMWZ_!+!`%p=gUlENL!C?)Sa6{Z5E_T$n1rs{ zsuidw6)Hm$jmP=;PGp-G%#A^C zgT~BlgEKv}ZV3f9LerIwVXX5F7JVge`P;L?X2J)b$~TK^q?HB;7|xMXxjw9)8kIhD z>-el?@CHEgw_K0_Hu75a46 zw%f3sH1~^wd9!B7%TN77&KP`sc7g94oqvJi`k?20_(pITS<>oNoIm-+3iAb~{%0<% zF>EbDx?lkm=S(jPXUW@dy6oMA4?mMR4QgartxNin0nB;*NhV~cZHr(>a3NjRH5s_O za?*crCpAvvP^_1E1IzRXZ9X(+ez6v20}E|7ZL*=eoORASUt2~|eYhi*)d*Zw>ow#& zjWv|_hOEB+c@>PwUjY!q^rj_2`uPGB1qc}HRgWpez}vy11;eNX*BO(k&*|a2w?0S&EiJApoDDW!W;TnGiWUrFu{cWCn-xHKY#5*+iJt` zo*iLr+=#$kU-JWivDzngE{u0C1;L7fS1~X(vi5Fh2yR-fZ%mA54;8;|WypKljNd<<2FF`MhrQRV#6B^_k= zz`^W`iymlkCwzf3WpDv`1qund~B{{J7?ZGzWjIvjMZWh#JfF#;$*x`;EW11PFt_+RG+4&vISW^?Cng7mL;ypjLNUl+J!uQ#S;)-Y zK;TaU8x{nhCYa;cIvXZ@M9;Z}sV=}kme#g^%ao%w`Ntw|Kkd9!`GOx zA*1&%i!mlXVVf7W2)p<}&y9!^v3*pM=T4Py=fD;%ECpk zOm5uJxG`FIZuB0WGWIs(=RWSsP{AKM%03xg%xe!$i>0CTKj$8KtmYr`%+$HkVUsOo zpB+|(v$+FQTkNOqZanC3b}SAI10UOK@P|MguO*2B6!w184r5y%8k_8aZIkzTZ0O+c zJz|sqK1DUs)TUYgSF}4+_vWXw+5)o_e0Fv*A;+a83QDFp|Su!5^_u z4D-)SV5ZG3C^UkaC0X@x!4kSWK8@*Zhu{|~gw$t>(*MjmWK7Lid3Nd?S#9GjWWaX1 zPBuwSwC5P{5ead%smxxFj2pd~(ap_>)&qjrar#cjs5|WNh^>((}B4nc~Bsj{3n#r;s07)B`ecsdr@OpD@)R)*)ik zk2nSZ)ETcnB%OZotxTP|hv;{9Fc!laCBj*Bon*tv&RLR6vPI!qP?rIKC#Q?^3c!Y> zaGZ93@OJ;;kFe$R42OES(+8tMRuz5F*R}tcb@f=SK>eve^$AG*S*t43rC0%MEVkiT z&kapQY!qm|7jbjrAlocxz^%!o^3nXMQ;>L7A6jluDsoiI6 z;UAlMsds+fr46japXAA4$p;099LcfK^3r$k9@57>5`+tg7aJ^0EWS=+UU$#1=a%hi zOs4PBM?3|H3zaAz-2oT^;v_Vc9he)q4`>?v-8Bjk>lcuXo0dO-|L^Iu87uLpp+$tw z{2R(fyKRFRZK_PTShdBR@4<}88TR_4th~_y#4{Nxg*Ot~+?d|>p ztdNXw6Vqj9_ zOg_QOrjozU&3Jy4blT&3k$#8hIY%Zm%+q&M*P{r)WQTINmvc0AS|=jX*0I$g4S{2D z=H(`-Zr{frzB+IDgroK(j#Yqx!J>BypNhH5$edpHzw{ibk|MIgL$M{PBZ>JU&EN4U1->54nNb! zW>${Q7`B}zp0Pm&Z%Zx<>HLVK0Jg_k51Qc*Y|=(g9>K-*!A-U4pLyewQ2!Y@@=BX= zMfrlinrq`B5jB6y8~(_LI+ZcR0b_VYZ)(Ihv_%W_TgI|B?wl)R^px+IfI+Hd;L^+1 z-@JhW#G*I8t_CiB%>*1^Z3j%*7z|NU^ro{I)VV+TBMjV`7oj;WqU%uY^9Dcapyr%1 zu*8aS@b_4i{sD;|uDHP^=l^*;`Ji)SUJOP~h>L#_#@5RGX%23RX>l+pH|9`Q*~kfz zhvyXDponHQwa__#*b$d;algX3VjehxP}F~#KKWP!Pd=z_ER8{y`KW`7)?@v2DuTmG z$IP7`w$8vsv-;UNYVqN3TreLx+T!3XLK5jv;d&v&*I4k zF&gXZf3PKOy2BP@_(zXf<7Ik`b(Wmb(-8dG3jPKVYQ%R_RjFtVx?)6~#fAkqpiWj7 z;Bjm-&dI!s=#C9rpdktR(+Qett5%?1RiOF`NWEIFD%qu00c<8|C-6%KY^X{I8wYoi z=%}oVDJJS@@Yj~$A!VlTKR2PmNq_im?d2E}6Sk4r#wqjvEfZgQPbN2Hio{#x3uu$*d_mDSc-LpI%NL)m`ouCi|X z7K-<|jC$}*(bpaDh@#c$i{q>_|+>3KWI<}QQ+x3)vcJC>j+t^x6fBSVA z^VTeBf<^wefpqQHOKMiMIm>^Zyzt1gGHEtqstp#;&qv@d_;#T*ZPG$kT5~n2S$7R- z*D`#~6gDvDn){!>r;WQ?I`2LLQ`R1SO>TLxxwQRuk*<=p2D(1WufLgWzrLOW1W-M3 ztX5t=Raz}L8Fh&h%&{svdMK8DrGvct&u8VuFTT?!399(Ek<{$8mDK3_a;Crkrrdew zKV;lXpUS@xce%FG9ghLviCk)$fm2? zk6OZ(X?Qf$Y0l&~W%P41(z&qGdYed}^;*(m`a3Vnh>?%TxR>XOtkG6_ZL_)Tv+HJh zE?}Eiq{Z{(#m8QhNpnavP`%IAy5p+Sb)62so>Lha~ZIk@>x!C0|K->#`F)gE~CcF4nxL&=s9`(*^2mEY$ki|)kA*H_(g~$c>;4jeoG#HLDz=gh9|P}x*JQc zb+cOBG)DgUivEG4!wRx>-_2w|f2~DpeVU~HcoIZ1(K}`lL#N4EHAbF3o_9MR`pb**j zB8?~wroSqCtZ}S7n0biwmse*UBQ?1C*T#6?d@i?N@i!TK)k*ZKVD|u)=yd%WiRkmTKLI$S+?t` zCA8ib{8=79WIfYqZn4o9Zgl>nPEKi@?OP|=Ov;N1Dyz-Yn$QFNmJ-Ku{<0^Ua z_iM?kxBf-8IPAWp&xK1K_^TYYb$faBx)Vyi=RSUq9J7gC6w!Y6JJN5Bqq1-E%28^| zy?;GaPC0xh*|L*e^uoeU8#^~Xe(Ek+Cx7x$8zO0HPWzL*c*MG?TxlYeGYaT4#T`&) zzx}YZ>vd&vfpGEP@03F~XleHcuF*WXdiOo$xTg!Vi^p6m9iO~G_P*fRLRldVI_EsO z_Mi>?r$&NI1Nr2icgwo@laC6&d{}eprSkk?>)0vf6N~5nOGch@nH+J`8@XvMdElvM z%H@Y{EJcNj61_frnDjik@UJ=La(UsfF7oQ_*UOeiJx~h^ii_^LP7d8lKl?N19ocEE zJb$R3o62XaW6FaoS~aZ`A$MT-`^ zHE-Trnl^39TjR$1DrBQZ(y(DeS!S7Kcps@iuMVpf_@7sx`WCGJdC98*>stlv@g0x; zeo2j882{08v&b@1U9p+ieBqecWnyE#4hdUeVx!lKx%uD7tE2Cg?P@*w&{rFd?BnsVZZ{=`j(hc1$P-_yUJW6w>^7-9JI zt@kFa2|eYU1J+MDvZgu_Jv{wysAjGT)2$>&KXs((DvrYj{!UuxXBwV-PhV|-cV+Ep zuPAYa0Kl)_k>gh!@S~o5z@7PH{S$rzX;M*Zyn^w`Q-59JlMmn=yW5%a;vDsD(iX$i zn&Mm|ZzQZYy(rO3(;wZ&-7rG7+jK7(aPiYJ!`_*e*5s4F|LsRV`9Q!<&HPWrd34k) z>cz0Anzni_Jblv= zpL_uC_`T27b3qXrHvX^H`l(xPknMX8l70U4jC`@s?)O+4o|}q`zHu!+jmT$7Pd>@sB{lO<6@Vn!jGh~$^Ru_y>o2g^(_|Z>3;Ik&z1t*#L%a`xV&@Ko5 z;FAy7-*N7l(thX|nP%>ufKIR`cuZUYW~tS*Z6s5kxn+q@K45slpz~P^$biKyo_xfZ z;cx<|fG!N{e*A$!wN)!nKPpgt0#ZNLsmgLGR=^(gvEBLxfn8W{cAaFhZ3ZTr6$r!A zZ`?(Az(m%bksezeBYW<6jBJNnzoTXQ9S@X7%kL^Z_PSEWW|k&)mh%qTfEQWVs6M=R zxU8|=g;M<8t(HTbiVOBTQ1<-O1X<*{@M_6ryXeZ@?BXMKK4yeN*5G6AYO4d{bU54d@W_H|86n(xuI!}-HTRSd$*&Z!uIe`QT#F0HjHj9JXo z?g##Ef4SnK-^t-Sb*eQv;^3>~>FJ20f1uag)*X0DEt~ICOw#AdEDZDcLQd~`tkkt) z{Ri(Rhab?lHq@A_WVcHua;*rV7Ij^4PQ2?D*=w&mYx`%Kn%^HJ8{tK-%CcrQ-zPqF z(fQJ8;Jv)?#yX*{_D{WnoCAQ*-UIIXJ~*j4;z06Qym-2tzQOTz*Jb}*<*@zx)W&)A z8rl6%Z!+xs_n(mU_P@2Z&G%>~<8K(`jJ4JH-H(?$>ag#>-!J5_{d(7)dF&e5{YbQSZA>j#U`Kv^?bvw+XrnJRj4>M@zsjA zScOCF{=CO8kR99OJB1d@f{&h(b@!{i0e2hp8#(`o-cqx&z13#sNAJq*e;z3pjM7&< zvi9IfN6PsQ~I^W84+Q`e~w>z&VE46GS z^Jjk}QzuW7NAA8$j=6Ze$jpVZ2-|G)PIBZm+sW`lvbSyBex{5*akT8&xv5$h0bG>5 zde2=IZz1X~!v^cCA7D(r{;CugNx5;x*psu5O>ejz`wWn&e{U^2ZF_N@PwqxtacoxLz-~&&2piIDIHI{{!%$;r}g-Giuto=%cq|p|9j-vOD%u=vIO$O z8uNlWD|R=XoA6JyW7|e<8~YpCX`NOw>yvlohBHo(GakmoHget3-KCM|Yqoy0g7BP0 zA)=0jO((hTu@hu7y(q%ZcQlp-^2sM3$@8Pf$%S_nZv&(K(<9_JS9FsxN30{we%42( zyt#>fvZJ9i{^lLofAiCeHR(E7Ub}Y}S#IGX3uEPx=B@PCH(k!D+Ia-ixU;|rLsUdv z)W9`Vr$f}K07wYQ2EtbR%L~`GPAylg0qzJ5mrZ*^wzHm3FWmsjuFS(ekcaLrt2 z-dNAMW%QhTSANy!oMK(p+gDz`ZAWRPKkQnZ4vVFEOZ!}oK1$2`58Ne}6rm~YGi;cg zJ!CUk1#fTFdYymzujKyAua&`9X7Mk%O~&nimh{$jN#AH@OP$bIi)UZ(ac{YK^nTJ$ zYcXr;2XfQ-y7rG@s<-^*aMZ%qChqgNQ}EvJnB=e4wtT9jLaWa^fgUiCJ|N;Dt6jAM z^`HXPCm{7;k*XAzZUwLp;ITgcic2uUCT6<=XQ9yM7rPM6i&7fG^#51uEW^iLAiwUh zqJ~7EZ{(&wo?Z*-ya#TOrku-Dgb@tvz_SGjK`BSVx*S#Wh&)>o}ZPa?+M{@a5aY1h3x*a<} z`nCmEkVPQn6SA79CN)eK8@vrzUsbO3^M3Nu$Lq`W`dO00uP(pB5&&lm93rn=aH-sV zuwHTyOlQ!~d0#F$y7Dt0+sc>;M{EB2^~uhnY0G7$%lh5quv2Sf=&#?AyPp5f^4Iv_ zY-?RG#$_R&gvieF?4%=QBmF=%TKl!T%ZaxF zYHHS$b@ZY%TDR`&$}YR^EPpuRCHc*!C(Edq(0<(MBW2v63-w~Gv8=et3by`jRxZEQ zr(+vgeZ@BVar->3I)h$ic&L)DfyYdS7S$I}MR{Zrn@k9s(#kH`eJl zK<+v~|9XE@0XKHybp1M4d{&`}v|FXE_DZZWw>8?xYVBI<=K?ru{0azt`DBV*dB`KV zMh0GVxr`Xx#ZOO*zgXYC^UD+eAb*>=hwPVLNP0uAx&K}1bD({eB$dU{^z{+D=$9Sk znRgD8?)W=`)@YTrHjoqldav{zah;6oFhIKV?+_KWB*vOjv!1SXa~(MUuHDv=op;$$ zjz9Jl8QSwSd5Cs)cQjs9nLQpFI8cVX{$cJAYT{0zP+3ui@9r zQ^9BcRJrnSJ|js01JA!yh7Vo~i=sL^{{?mV{N(|SKV)s5zERn%6s21HbHX9EHcFtmuFVP8-yvK7b%gwL^}S?6y!xSt<{Pq& zcvtl~+AxqFA`y6ctpWk;s;ydq`ci@FTd?ZON>zC-y$a}qJRaxy`0o$+c0pTE;#9(DA>M`yL)HU(6a_Jo!)}vtJu0hvrv;>VLvrx5@GTPYxK+P13b*(@t`nz6w%mSN&DSOv7KBjlf5bK2R&pNkcYf?soBR zOOea)#ElsljMI)wR#j@!^l8&U4m$5bnL7Rq8Pv7JBn?KLaEu&w*W{qY{);zWmD`eq z30IE)z4XD8FKxB*R|d`3SXU0%yGDO;9pOE`Q855N;z`IQPw3lN{K*H@Ort?l+46Ts z>MJt(&0q9)hrF}J1Oe5iGbFQ^Ck^z4iZH_jWZYVI-c)XS?u5)1;u~_+y&rf!WT85L zr6VlAhQG)1j`_O`v&!=++3Q>_8OD_k5lbt<%oH2?b}wS-yfqLy%R+#TB`IgL#``EDsp>K751O2%Rq4j&j1jYk9q*0QMvVPjq%a z?o2+Z2>XW~`H0^J=OI)bK4yW7{)-;|wVn$I?7`VLmYzcolM{Dn$2ugE=H|!w(%?TX zs%w-KD9f(7k=*dqaV2Y9cwckBuC@PTjuFx=$!FBBM8C75V%?gM&mWZ!+MLM~Wu*I9 z*H8X1NH6};lnB?Hb%)$oetGn1<+?mNiFGjtWUjAt!~ngni@OsGvgK!$#J7pnia)T6 zApi(w1VGRa@PWay;c{_bw!HL{S+eDjL*<0+troD2M;^#* z8au5t9xXQnWxt_*og2;<1Jb?m1d3jP4=ea#$y*M;4=AT zT!v=t7l+HSyR0119mnQ_Gd8JqTkat@54=tW-(L8>KWT>M*Is?J8RcS9CHkYMtR`wx z+3X?_&ahf6pT6$zlMcfn!({)i&5B&iEURY)sL$8zwP(evARozT*S;bBPv1y+{7Y^a zJUSv+Kjc)|sRKR$tN>gy=kKH))^qiG!jtn_dl)GH$QgRb?YeFuH;jK!eydON`W{&M z)IwzVfxnflH+V<}>W@RBhM&Gsk^is%D1+D6uh=Cm#neEknZ-ff5EoqapfdSGbQ{d2 z*7X3{)4$0o@?rhytX9Y+KlG#GmHpH0qHBQonbO_+7}hZ3*@u+CdoW~&y&8xjaI2#dVg>7ZXv1f-rURF&q^s{kI`W23Ogd42Hr4Z(VF^9>>OzA130Q8}g!AWNpbv|FK- zzBgH4?N2DS0b^4`T(pRfod&9f3+7TEhyD6@7kx*4onaUfPUPHJeZS!&SyU z_OX0*%m%VN=GDw1rfC&?yL0ZbvF8@X)1B3>Q4_qcqiDNs*qQlpn+6r^nCLwwEgiok zH~X0!clma5YxZ`o376=5b5R+6z=v!#HKUMi4i`*d zVF)H;rkV8I`#19M%{P{VYmTq=3dgUmeqMfg`PR&{aYg>W*szm-wJt7Afu-EEkZFxo zRlbDLk%nhojR1Xc=sjRVS;a?@6Hf}&kv|tm2NiyFp^jEwlZ4=ixX3Zl;+qT|UDdq% zPCJVH=^D4!zx2NNnf^7pfwYMVyMHoJedLjHjIhyrO+1=)8G%$Qoe8W0KbI^wXy~3# zQ5kiQ9t4UtDVgglH<%;mC;*F4vf_X>GpO{r0Qk+E`bmZHld?oQh$*>0@Q{)q1F59MF_5ZFQAV-@LFdc}Q< z=Yb}OvE|!9W=x$@VLnd!Z$GX=_dUb6Kazjxx6E05+-KrmUHEMM%NkjgCq{OzDFN^$ zH}By=9RxHTl$MV=D0wDk2Bz~BgH^RvD^Ra0uuQ#TTP0hqz|yEd+PDzBxIpu5g1V54 z%~m&u*dMT)_=XOIx*E0?HRr~Z=IM`36SLfse6N`=FO7R9nL*gHo4o@%;sc9KeX((+ zrW<18=JqzAq|^6~H+GxwPjf0{-n!A+Os<0leg*$|^2)PMn4us0Y_f6!;#OS?zzu_I zinCa12J9)jme5|4tF9j-BS+p?(u)38$nHPmPtIwb?1BJc;#NvTl|do#R>AVuTo|7- z1%f*?>(E_p`0&p%s2pANB@%gS9+aB@bLG!}^w~I`GMH0&JuNO67xgCrj)P}}Tdrw( zlNwdD%-2sH%-fFPS65%#0_U4qq6Xl@F?F`ajayWlKl=A@evr1rzZ|W|OZBybCgZZ5 z*8>EClv_H*dJ_CI0}_9y$+{$H#g$T3mi2o_YO9(f-gt z_{61fP3HpVvh&AzI%^WF!#x3EF0D7T>JR=6n^*pgvWdOYrS=7Of|2E#;M3c{s-sXD zfyVY{g2M5?mdbyCA^%z!QIBG+Eh~KBzI-35<@$pPi*JuIb=RV`-cNBp#0`+Fir2tIiES7d#w7g9E#_k5#^w&)V*OU7n1eevGo5R)Y}xJ+$ZI|;^7eZ(^iSt& z=-4)7I*>HISfk5D^w-wiwE5{!xxAnZ-!O{I)-uvWe*;wC()nT;_bzFRF z)Z6dRkOmueplu$X>0^yqzo@HSI8nzu=vM0hIy@hci{}$P^dVO|+PMWS;#AI>Tj8!% zWZtUB+s4$K*d@23)>b}u$ZYJqR&N6Mge9PZ!rtsu z0+Y79AR1ns))@%wVVq%w2p!zDw{s4n*Q645$HU~6v%Bl>{NQs;h|P{QPBQd*gX=>5 zyg(Oy^@H${oVgT78mol@M0^9r$OB-el1m_{3Fpx3Km0FhQt9ONUm}=-x0?Y6JO=6jZ=0kk9J9u7nAB!a1aV5H zPv-p&k(bZV`z+oEi-sU(&S5TNZS|`%7(aNXx|?f*CO?Wc$H_h0{^oL@G+l{`rH-pP>+qr9{hua zk2$G2-w)tLk<)r`eRxH08x!DdQ%ZL5%PxGlsY(mkWXtXJZB)gp3}arHCdY26FJ-_n zb}xX3j2=w^zL@qeljEpwHNpFyVUb_5#5DTMomMdp8`eV+%zqha*I~t&V*lQ!`aTjk zX?)}Wd*+2%)Wqr0xO6a98x0sJztATjqe^qxVCzF=KzCfJS^ccc1t=vwAhy|{H~-*+ z(Tta#lULeqC_8j&k#a7RQz!T-|CU|W=c^$3Cqib-|5m43*2@2V%^wv;ePWH{!h|)8 zf;xXPb6t@IwdqjOXZ}XqlS|eikb!e4A%p?l3vadI6A!b6_xvyU(d=X|%i%H?b||f% zzs0QJS)rXDsw~P!`@+opxj@K;3uPu&Zq>nE^&A(Dg=8i_lz!rfC!W@ve}Pm;z%&A3 zTFgQ6XS`PaIRCAup>qnSnvN^Wx*b+!JtB|jVUx?bf8YmBtv=R2cTzd%Ln@i%02(y# zWBshkdOiN-tlUzt)?q`k<=Juq6}cxizP7n*O^0^!v(@x-Xny{n4gjI^-4Hu z#lA8Y)`dE&Ksx`_%dpE1HLJIiwO7?wDFZZuWoCwi2|yR|IaWSPtS{#11$Ygh|Kst} zhfY;7nZFvthCX`C?tf~4Df7?H->~*D)vj8BdQpMuTd?ZIGF3?~%?j9liHCje9KLyA zj21n_Ox7Vbq+G+TBX%OVRy1rrY}&y#Hci`dYzmmrH@0^=B!sai-6s?0hrjnQjs|Sp z7Jn|+?RINu+4tF@i+_Fuewj~ZmE19{x1gGtkaLV1SG-MV+$p!o3v=L$%@_cNlX^Hp zmo>}Zl`YqolP~O<&6dT}{?J!eVt&CN7cb?;X;nc_{-B{klnL^bm+qBcbU#(bPQ_oS z4I!_;>ENi-4IAlK%a+@6`axn$)yn_0JLJXLc0mOX##MYC>1ET3Y!)J77nPoNdF^cW~`Lu;Q~IVL3H@hy|=vMrnU3m`s9D; z2YBtmFwYb9#Zr;K$B3MRe?(v(3!($e^Q5D{%h1w>v#=;N3*muEGd3_Tz_yDYaG_3< zp7Qs*<+!KIPCdHV`NNz5TN(E0*JLW5d@i9yu9&9m1i1bxhc2Me=k+UKRm);xUYq(> zQZZY%g9#KgPMw*=5e8oGI!pS@>oRq=1JD%bm_-HuR%@>>0|SfwWc^)>2jvUL%!@_t z8JFo3#>;ubUzd4d8+{26yy2uVb>3tc*qT94TxbfKFh~tPk*3Kw=S8MId7m6#yz7zn zJv!_CLni|>fm8@}#tNnOEq}Idt-9=f;wYKU$O@)5UPaYdesG6w`Wsr85pT%+hzVPy zA7k|6-_Uc8XE3=Mmf^s#<=X4YKDoV2mfeSqk{JP_J$-O+UDS5^#PM?e$RfVgqLP65 z;~c;|dxbI{3DOuKF>O40l2jonz`D*XY9qM2VO5XS3e=+tRG)yKfk2qL%IH~;Mb*VW_j@*7_$595kQ-*HgZIau19d^qtM(c3covis$Q8O5s)a3d$=(`r5WLmjVz{Qma-{9(C> z51&#~c=C_rw5LeDUtOro3*O{7Nej+$n4Bbz`zN zVGU`GAMw!EbnUI=`dv($jyIeyZGSOR#_QEMYpBQKLhe5@WAeK){LlBxi(lI31LC43 z`G)}hE*Ji)2xVm-e(Vch3~gOY1~Qj#gZF${9^*Oj!CPhR0e6&**B>m0Y_n3zhm-2B zZ@A0av+~F*U)ngh>6g$>9P_Z;{G5I^Ch3Y4d{yX!X1`ML*k+w=vhrn%fMQag+6J zdAUS_q(fXtzWTwaNl+`XZ_TzuJb3Hf<=rI0R+;z{O+V~X^O(5*Gs4EM`&H< zc)CEa$1!~B;`0yRl575WvUJ+{0y*c=PxN=&Bfi?zT9@bL(bs1h4pC6RZ{@AW$H*-& z>bf-5_`@pVKQ>%C_0#wt``K&Z)elYA<%757niEfv&O2Yo_;>;o>qisVS2izDVP{5R zYSXrE6*IOfTz3VHLemI`gpkTw8M->IR^X>zf$C>Ke(Eb!<@Xb)03PhI6XX|+IyM#c z7+{a!wSxDU#{~{HYkZ7@EjAJ#TIUx+^s^Ye_;lMGGd8ltiyKP6VaLd>R~}yeF!rdw z%2s;oGjK22t!HOx+hn19_~Hw4#)yh19v=VZoBB&TZf4+LT&(2u5TDzf9*X$6h2_aP zH8z|UGT_W%a^OSfmJOe}Rr;=ft90wXr~GF7&a#}$l_~FiEMu>FNXEJ4dHVU59xK|L zxUHr^;5+%(1^vWFbh4^N;_>9|-izAQO&QcezGB`sSQKis{mbkRptL)ZLI`=cB*`uyBP37~;e!ZRM z-(apxeg6{~dv$?%Zcoj>ZT{O1WeA*TksD4pO${m>^`;{XJSnO%p7x>Kb^Qf$#lvMwjLx}i7kMPP#$H!~sx^Aetz$TPfA*dS$X90%lbyOWl#kwiSMECVPI*e_dY!Vi?B8Q~ z>2ctpGW4v2%Rfl?*8Q^c=J!j@jyuYrtvc#QNxqd&KA9#jTsMZkDMTy#EfU72vN9tj zm94c=#r?n~HODk=wcB&D!+J-^;V17V+ilWG*1%eS{*l}@@?yDaOl|A4FWOmFVf|3o zN*=ZCX%Qz|OzRkW(Ajjz!7}8W!^%Gh`1XUc%T^CcO}~D!PtP^<@!?yUGUao5VfdpJ zb!j9G9h;fzw{LZf7~Y?~&u?Vb8Gn$SIyaUNbzSZ`_ikI4VQcBStRO%C&F^H$xrbN8 zA0_>_9%b>j=)iTEGUZ?L;)u%ljTzsb$Rc3*oHC7_f8?hM>ot4)&y*on-ZA4`H%}mH z%j#E@HX)cz^;oSyJ*hzT2}nIzs4C5+Sb_BTj;%9m+|{8oJmhYxL zFQ;GqQORlFYx>LD4fDc~L1u%oHg4Q1b6Rn!#>K8-$Ex|ah?-A!oG|+DGGTP4s1yer zCns#D7t#pf9}Y$SFJ1qxYe)N6GVwVdvDs zT#lb*GUCBC`sAz%gg{a;7k#pU5XwlfG#P_r6beOMLa{PPGQo&6?AY8&t~%{PxvHem&(U*Tl#9kc=ka4? zA0hOu)JGDvWM;TxSwRYei3h2vcxlU3U-m$*g6GZha zfI3!NwF3350@b%*)w2bw(p?G_D0T=9&PRPC0ln`F$pmBDMRdxy64lwZi^=l$*8^yw z&hjEo<=D)Khe>TQ2RVyQ{FdwVk{3R{R!*yYyAzC;)N1<6V-p^dWBaTW^tp$@JdYdh z(AfsdL|~Qt3LE6+{J|1V`oCtMLuB$lj+fqH_#^rScw312GjHF#5&x;{Zm4*owXOVq zw+^g{hGL7Fb4=o-k@#Ev4BP6emfXn=VeNg7lb3HlRJu9dkLh|J`$w5_-S+lt)rhGL zJn*mE-iOGfCyxE^^5-D=mJ^_?$aO z%E(`>!{YMX@L+NN)(rZsT(|cRBTeFB`}wcDW6jY6lIx{%ao($q>OEYo04M`&tsIN> z@8?Tufr4H=mH^152uwh!Y1e@V%C&nf3AfNsT3`!_Tw1N)TP8ntl++Z{KSJsze?D(> zX-$ez0eyRAsTqH(7A9;=3A|Yh?@N9^esI>`u9e{jtV@UV^g*$?R>ju~)CROgFg=LG z7`@)$kH@b`V~+f<>vH+on`vEuVYvaT>wqD0%^tOBRB9$K(5G~8)EnbJe8hhlzeX-U ztB1$8Cm)F4prRHUfz9Sj<|-nz4xxu&YXpt!xMsAVj$CkT8W$ z?vJrUR7NKrl#SZ`OisSzF`4lANpjFH%AX6NQyhBrm*Mvhmv5dwM*4PcPX8PmW=Lsq zlW?%USrh%4Ic~7vh7{E({<`a?O&ePhi9dkJy@9OSqn|uJ{SJBPnqPhIg?P7K+sSE{ zpCx;(YhS0!`T-v`nf0oicS-rxk6ka^OEy;1Xbh=?QvGxcJ$1kVe%+O0C`svpRI z>uuz;OV5zK*0H1_pT@1)Bz6#5E~mBTWLU(sj+vt+#P}6!*|hO8Frhzsh_zbRiq9-$ z21EaNg1r9WXgOwE`^r=Rq>Eq2wfeV~!Pnd?Ph2s02^V*rWaw!p$Ss4qWaywD^)orh zA|t@t{YbxMtod>kxSgbJ^CmRU*T2=WC3tD2`A62VK5+sxYSg@J++N@Q6glz!O9INH zjSRl(Zh8Fj{VOW0pLwx8$eVLykXAUU~a| zIi~Nb3Bc}0=8wD@SMq78d=LyR5r7H=lmXMQqQ?ENUCp-g?1z7q`!3yAdaY-!bsc-{ zv8!Bj^QAI%^4T(UGkxP|;CncI%}EAde!Dz+$)F{!%Mg9r>Wu@|v|_mbirqB+`y=H( z_50rVyZ=J2x#<#_^3mBcq=$a)N&WMh)~-b(oj04Hn9^r?)Z0tKd|4JKXl3;xM@*Cu z%p7x=sS+ZU=mSHX+4VGqD(z|o{`(5xwExe4{v+Rg_njNr?p)s5v}q&jbos&q#G`%wmp9)7e2+*Qj0%+1GoE||OJ1<)B=(QA*XT|Xcg3U+ zhlrlVNaz6ICgnytp8xNE%cr0JTVGj0gHuCkyYhG`&%Zt~XCR?2_o;Y^sE>C`Pk@WQIu@utF;c1d0i>%~fgBEr6N$L`Rj>?Bc-^`Zj zUwtie=lw@N>k3{CW%-p>l$F{vVa`N$0;qvSN>%fmfC;1TWac!_zfmJ;+_<4MYTiQH zF29^C+jI$k4?;5P>LHK-z_eM-p)W03VTqZn8A7=8Je&8v3|Z|6xh+}g+r~cqgLKuu z=1!aOwalOQt-gw&-wvi6S6*dBX{pbB>RM;4Sy9&nX2POxW!jW4CqC) zFJ8DnKL1p6TZlJGHI(KpTggi8TS-$dauE|tqyVZn=Gh zozBK?1Y>Q@^hr|}y`|mJ5#quDc(~yhaUvh8F+*7AuLJlZ3|izv49xkzLa#dHN4|8R zZ2rs0^6gjF8=?FFLuX_i$BeE{4d#3x7nGiS=!e2j+E2D@17qU|AdcKW%_y|hHM6wj zJjbvM4)z4XVgpq#ne~FXeM@^)0(x%VZf?I0t~&qRhk4+rxTu-iTkYYrjI7XpC0TwI z<3(0bYcnQAUlbfOfD1!ln*(Z2JIr}rG*&%xFf*#cA7=E&90#2CgFgAzYrh7|HkbCR zH={1rmH9BP0^oc_Y=+lJjIZXEG=R{kiL~$3UfP2Z=Rv?)ob%Ku7yXM^OfWBoQ;li$ zsQ;O!h2{V*C_nYS4kiPtSWiL&2$Mu~5R$?~H0X^hG_XcX^<(CyZJqBN-a3nQn~{EXo-Nc)G^nYy~m_202@ln)@}8c z)nC=5LOA88e)thdz#>J+@xN0rFWyq%ASpdXxI1Dye=8agvFl@AJHoJ3f6*Rf*wc?#=lt5%@C zRbUB!a;tA?RQXmb@c*&`*h=gn9uNL(zPtE7gx$(EBAuj8du)`p&2X!r%*~U=4x`4< zC4Y#j14hIuq7yV6i=O@@U`}wRQ%=^HOts}++HpWGLAnSlgEFkz=S!`A<7$-W; zs)e?shfW*(0f^>(tQB=?1_n`+T&7FrZ?!Z?55stnBZNmK-@-p;!9iu*2*BVjn@!XW ztZ)Ob%)8{CVkI(&XswazFdyDY1{iMe;eWM*96?~{( zhDovPoFyOU0)L8#r46Q$3yWanZN`0QWQHj}mKy-xfMGbOj}Zv|7SnRc`O{Tn#QJ0G z)GcH-pda!BCp7Z+gguvtZw3VqjKeSboPRExuO0Qxl|@eAssG@Qf5ADIb6+NqD}s0Q z3~Fm&xgaGbXs!_lF%^e#yay~yb&8ELb>Ih;T5AukQ4{#X!FrEHf725SWBLO_TP8={ zLI+&KhM`JI0ynDH44;l9Tt)~}ccu#=31(i^ zW3>YHr2^F_AoXRXsyvro1#G8aeC`pDd`BrZ7H(10+jfEt(sl*gunHOT+{kPf(NVG4 zCp>7=rV?9fq2xxc!_>Gl72foS_%!nP?vOTCcY%A-sSW%izRB3=O>dSqvN||_$4cQ6 ze>zePgmMcf+uSi{8>-rYz@jN~^&wA`T@L-VY`ZEhor*@30*b!DA2^gb53h(72!0V0 zAllR30ZgWw>fOg#@rE9TdG5n5yv8>F8I^K_$L1F)41+IizEjOdP@R= z@pP_4ql{dgl%pja9fv!5#t#1K>+XzQ*Ma#27<%;${z;B`FwEqH7fS6dz7a@r=;?0& zcC`CnK%xg<+)Ot9fDcaj`XNd_CLiP+wSoZ)fS$9KK*&%jc3M-Ig?*CE7<%xq^WOoe z1JkVORDv(bI-tMWh5=LnWwwEVNi#4inM_lQXGi#lU$w7Rp#D^#`UIr@tW}li(y9P= zJ`2tVdfN+ZlfnbPj&1_>dr`Y&7f-$iP z;6zBLw4oUf1EXxtj7$1-Pun$d5Xbg3Y`7s|i}Zv6hwx#=BrFDxFf+HJPZK1Na%RP> z2(+-Y)LG+xF#4g2UmF*>@wb}@{z`B0Enn8pU{&Fq89(^DJ#*1q!#3w{(G55Fs~ucu zPTAHJigLv;q80OE{nRn#;@DA3MxcogJQpNN{@})> z6vIH=+YllTWMJ_jX~Thl;cq%qm-(lB6*+Q64{UN*nV7)UhB$!`{E2JRcBFrZI&0)r zp)zL(@~Kvdf%_8bBjU_BlIvt zpL9kQdi=8yco=mYlWEBv7SS+)|M0WT*YYSZiLF3s<8$}O7yi6K54qILxX53y(LfC=S11PGd}!nDMy{??;L=@kUD8GU~5E-ugMn4$z{Gypx_^|z(ma> zNA#=%=93c#uw-o_Zt&pxbIzkzgeMKu)c|Nj8T^qf6E>MKy#Pggl?a0RsXJxs!#$wj zlhzOMvWA$()pBGW3=dFD>WwrYEU9I45j03?Z#6L+$fO#*SJvp`JS@@=s7ikj!W^2R z;^?(BbVH?$&IPFU;Rjtz$JzpnwW7E2Mudn@?g@b5N!Fr6H2wuI=chiY{`B`6gkh=` z6lA46P|*_7s&W3DqpVUQki}P> zWob1*9H3-KX^^=aKUGji-iTE24=3XAphU?Z>#qWI7y|%}DpmS0tGt>LfNR6Ls5$G$ z_^7+ZC8X-mn+JfcMJU>+ia4rdc+>|5j$__+BEU#*h{=usArmI}Q>ix9R;@riszCJ# zNIhDtD%GV_0e_HZm+up*;7|{7A%UJ7o>Ij|7UR&FgHEb%_}GSKxp9MnZ^Q`&rk5nA zx!8~m01zoIZE&!bLqP*Bw2ukK_syFqAZ)%tEfn0aF{cwnPG*~PE^%?Nz@ncfjo!jE zkZDgmBo{bLbXOg)-=(;4>rjhTmPgpr{EY6m^L1&iAhzEzm7}pFib{K z4LB9&5%~uorhoxAH2Rwu$5>;_-z?*aMxIk0t^^G1;7L0@m~X^ZE7ci>%Hc!>1_l3Q z1wglBXU?W_Jpdzab51E!=dYb} zg?n+aTH>!Z%-?MRk?H{evhZYQZn-(;elYNgIS|CK0_$u4<_(8{)J8Gh^+vC zMsoz?Zz?AcHF7Hg7_QDZ00YsNI!7yFSP;aZE_msfwQ*>4l?}O>4V-kAoy$73^>bV} zdp;0TU0lh!J1NRoFTI7Ht}&*+g|t;Qg;OvermqLk!Gy*^J&A{*6E=>)*%4?D7xRa$ zO2*&kfAU9Rmyn4YAa|FNyWGWp1mdYac=Zy1r zcleWS$=%q)HS%y!>(mFe4s4R5f2Irkv002M$NklL1;o%KdOlNBKG52v)&s5uY|1dd%tnf_`49raN77_QY;tw24hK=lbo zJzA_P)umVgf8gf^qmTaFGgKE1n@VhEwjptM;O4+B3iEoyCdQ47cm)9Q6wJK>7Q2fhkRCGZD8rBc|W13DF z=`G1IiQeYSBjShN>?}R=hfMx(^C(u|Wh&Ns4u2~M_Xy@jKlP-ab^!90iE2&sn6h3C z!ajOT7=q1}_|vNbKgBgjJHpqv02h(%{4+GO!Q%mpFam!SNRbNDL&Qz>`CSVhXz&l- zjFXIf*7HMbt~b?&k5H8KK-tu;vjMT4SK{w>?gd0`iU2z{aB_+9Rd)W=hncE_yIEI{ z)e6*)3RHiHuzsvlmF55C3g7|zzyBdZB@qw$Y1c7g*uY|A4w;(*HVpk|x?*p^{)SB? zhY1}Jsi%RVMp)aC2~nTQ1;?7W_G&p=k|3Wiz8c z@YyT@6(Qs;0Tcwn$qPV>2LF+7X3g~rB!p-vE40y9KOBniDo2kAx?`Ss`$ZLObfWeK zojl=TITQsTFzbg1nQ6veL&ln`#P~2oc+|a!naecLLk1bDLT6yigOf}wBBMuJGD2PM zQMgKPpv;>+Tjt{z=!l8mL1-q8RgRj~#lOz*pp`YNpDI{ap8z?uikvLEfGuN5waN7L%pd$^@j-S%~Dl~F0~5yK2h43 z@IzQ2#LdMoc(4uVe_jZwfF3RPi_OUQcKUPopdGFCfC~Y1g+JwDXD)U^HFJ6hRLCm1 zdt48ccvxTrfxq)-P(uqOFv$5c>0}2Kzi6SIp%I%l#y=S5I5CqvEKuUVc(Gm_>8~HB zc@;|OmjE=FCTlfy{v4PQ;uC?2t$i4UT{k{LroU_l~Ypwk}&szJOz1h~v)K*AQ z64Og?Q@(&bGF^cpXv=H!-+ypo`P@RtY=33DOD6IG$*66J!3$f^>9B^@UQIkw*)w1^ z28a`)&5qX~2C2(8S(tG`K63+_y`O(aY*;GX(O7&9+fWZ7?h54B#AMW{_30+ViIid& z!zgxcCe4*WpKDcA(h$mt(VJB-P(&v89X<^YgupG&XqxTrmxg4v%a`NLeF#n_{#{{e z+7t=ZPku#IvnC}LhcEV(VJA64jW(cblK988up^^Yx*&OAZF%6-{Od5~XVZzEoey7; zu!MBunttQm9AeRN<8X^s*SBh;66&=H%;Lm)^z4yea)?mULIyH6kkc09-S(-5xT1va z-EO)6&pt=ox_)Gr=d3aKH$Kh;@8@yMSXv*qy~h$|i)QLLs86Z4%nk*~CW-KHS3ZFgCWnP{=ZS4ib;4__UF%Ge|0k>jYh@ZmD z!MXIziHq6#>oIQ^)9uCZ)Nzlvo<+O%Nwb9-ZbyZRGk6cMBK)oCVRXy}^5If^B2m~9 z8zc%pJ;my|0h#lG74w24Su+&b?EaluwEfj;D2G}ZA&a&LtktA#r1f#457?>%s>{=R zCsruvkH@B0)rp;h#3%fiw2qE5ho2q2V8f2(hk;EfZ2zp@e>tS$`pxk2C+KrH-Jb2y z^1FmKmfRoKmyaY|+S@SUVW^m9=a}E08vC!k1tx35X(!(RjDiAii5{^V5R%|Lixm<1 z)|N_(jTb;~#)TM5Ue3DCdiXLDi=KeZ2{tcf(oZO!u1T|*glATKObbDZ) z-A|`|ma3qz^skv!7s&Hu?=s;Y#w05#=i;*#=ONgFH>9W(t6ZtUvW5I%I3n8Zy~WN` z=}=W0j}cM$oacSIFWXU@#JJ-n-EF$!AB$lfuwntT_0b?)>y4d;z*aWkJFj%-&4Wv) z(HDQ-KK#5XR?54k{Rg9m7vaqay_Mmgs4i?R`Pu4&^+(BN>g^q~xxpeM0lRqEfHWbwpDmUq5;;SHiZ=#J zaVONekHjx8UJR57(i=Vzj^*86F(S0;$ByX<&26B_`sKmX1I8%gZ!$@sC%? z%AUa`yI+zh`_*?|e2!5%;q;w=AsASX8+GIPk#kbn+`cQ5!Kxx=Pq%~%ME)dV&PLbn zYLc23CC>G;fX~861D?Irfd&`p6y|xy-lTrcbH@0!eLHm?Uuzbc5;s`@FmE?rc5WAp|_UwF?`zo+qQ0OF~o zioeGF=qms3+9M1X! z&1V^P!3g^0QJDW%eKE} zx72!^QoP}g)D}LCKqE=&3pY|uGH?q4XgI88pTzyBfZ!_pwR5TLnOw0E$%7^bgAg$c z4gP74Ti++9nKyhM-U2(Mfk(tFc`(qH;uhWV_Dzqk#NK4heGTpxvhO0!R;_i}R++(< z-#9|co^sqQEBzc)^-}vyU-?~eg*|t&tB4EBnaveDTXsu;z-=dVHr%R-HRw6A(^N|K zi~ibp8w(azHgA!i;5Si4m*++y9DU)2ElgRHyEL5ecfI~4+&_A}zT4mT$mkjvKveWa znFL&|<-9ju)x;hGd(Lno+!+L-%Dr4RNA{MYWKMDn2>1Tn#}EFJ^pW-v*n-1D!iZ)| zZ&-@H;R-#nJUL?FJrtV`s|j&>`vbtF+V zB8)sirvw=?5t+6#x_fQoae@Bu%9);r!VQT~sXvcL##6`;!~zdGssr@kN~3{6>BjCr zy@w2JkIF9Z3m)MARGSjCQ{yLqiOCIE13MvIX(I}5FMm8Y7d8`n8fRAc;vNMVd~Nw?_m!oKLD9RCP#2SyGAA7JLzAVPJLNb zZ+1=k)+jV7!6ruyuJY_8|z5%-Ypr7LvxrdlXeRg!wBIs zVT?3jPE)yKF@Z(MX&)Pj3Vi#W+(ZP2jK^0Ea8z8InVN6ZGpE81=qszq2hOjupJHjM ztZ;`}T;=elIn(KyTe`|@0Aq3F^+@HD+8p9{H7)Hw>rKy+I+iD_EUkN42 z0=xzkO-$wp=1wa8a95imPwF%2H(n12#@k4gdRAbMgT5AmCi%5Ohi6_@tocvqdet+X z*?-x|$EwT0f^+Eo_2FKrAI;n5n>`ZLazbKYSI&Mt`uN2PMqY_M6#x(MfNMz_{qmmn zsI<8O;Bz}=ZM?_Z`woGt21-T*d2~WVROYL81ORcJ>b0mOg_wppmi^(p%kUgsj&Twe zGv&2S+;LAk4u>Ht4#!O3ao=7rJ!8Rz2T>Wumdau<`Qi%!6U*l1EJSJNO0xKljM(E% zFGkj)srA>@8eCA%P|eM_3a?F_md@}%g69(w(?b+Lx4ts)Pcnk!Jg6~y5|&&;6MXWX zWDaL6Rf_w$y9TDu#Y-?BD#s{oYPJ6)+CEaIRLuBN79flgNyV;tzG9oM+oUaB=+sZk z2K=PNbxg|V`{*I~CPC9k^u)<#u@<+dr8WN^ef*Iiqu3D6fV%Ja>|G;MvbUi85l-wBDu0qsL2 zaL&fV6$zHNn54s+@4MXONzJ|4~3JalT zca&#E6lBveB-_Jqc<%*Oee{fMo+DEM8YS)TP;$=uAmmC@3v+S(EPn}h!zZU7uSZ_Z z_4^~69e1@uw$;k`yBt1*L2POrH5taw5{2L=7^il*x*yf-REu+CE`tIaf&oZUnu%IN z(x<>5T!yoDMPY>{^bf7iJkmvhw0hGbmkb&R-Pb{6cpm}zUq^C=s`h(M2O{*^oK@5Y zwAN%lWN4KD63uq{OqN!9#HQJu6H1xNQ-FU6i}7@rsfTu?8Wo2?Lhm+ye83|1({MVm zdS$&l7LO8obKgcj8N-c5H4(%+=6%}yJ<-C!N^AK@EfAtK@1FQhZ@>2WwT_QJHDDyGRc zH()A$r;n`=5!jt4u@(bz4qG6YYq)Ps`eRkKEa%V2tX*hQzIMvPq^zr%q$<-^g|ELx zb|3t1;;CF)D{S%HCzvAIH+r49xtqGYGo5Q%h)*c9`94n< z$hPDG2nr70bF!cHA#i1fch+y&dGBD5L%JG6*toz2oazR&+zrH`37c==artVdTrL#+ zUtC|mP;Ggwa27*HJWXw)lzfok-1s#5nu5TPU{sgVuWP%0`ch@$2f`HAv~Glv*3_nR zwDOkV2&Y`_G#rpoSqya3UsyN z*tRpsImtg}1Px^RU(N04jSez^0P(lW0Re8AGZN2TD#yi06I=%&!8NwN#%=5{L^P|) zxgz@BCw>(v> zG`}Y0Dg}9^x&&<2r5iO4ttCnutFEWBrB`<6S8L)l7y1W+`XI0T8)&~R+590{j6kK# zBa}mBoG~Bntc(dcSgSt5!f`38a1cQ%-4gyh4X~GN8h`jZ>@vt)GqT=ss4sGX_}pWN znVfXcsgSa{wT&lbO8QtbL~(tqC?g^3n?-v9s3|Dw4?mcMG>sh9l#l7)g6EQ4~15*ls*t_gwQDSP&B zcGVD?(DL6oIsUrg8;J@kMX#%y3EX2(UcNtmRRtpioW&2|sLLHmBm}=f42UCkQsSTs zYl`XgO!%hOswM$~c8iw@_>6H+Ana4vZ`ZgX5a{K97b*dmvIN`X~KnnKC9dkAX2n!q~5iG79-Q7CKbcC3w0 z{L+HcmzbS8f3Q2>XmnogY7&!VB=&0)7we&3?|rvFq2dhB2I-qr7oa1 zbSvW))g2f-T4qDGuh-x)PGMu`;6oV2`wJvDl=5qauX4jH26;^PR3AscyLu2CY|J6A z7)>&;$`?v3tVkeqdA!i`GpWe(A1;|)4MDx9sm+@DBIOpx0Q(iUSa{upi>AM!hX1VJ zd_0lxv$8TQ6Y8p?%M~qKl`aNgM1RH09@z4nP1J*KGylR`o!qa}^)#J)8tZSWX-0Yn zZrK?Hj@TJN05ualj)6DbUHF3F#-ycosT1@D4}oC3hHb2gG%>Qw7+d?S{u+&51A~V zD8~{MzZ!Dh0`&ikND=Q*sDG9HEd7K?8^yU4DpJu21VrH=h4e3a$huVm~%QWd#p zvHdAS8KdKD4hJWB@pI|3k&#p?)h%Ii;u(fFjWTc|Mwl0+Tu<=Kzr<_Bk(%CDL z7$+)|wnzVKi`q}!^dtGw$Hme1ej=X`6%n+U*NShIdQ{~;)d?w3SDy|+sa`x~8BtJq zuu0}N5U{vDX*$-o?)Yl_>&R~1Z;e@c*|WWe_h>{na5NRC?Kg5nrb3|$DrLWBexweJ zn(`MJ9(S({&PU&Lo{6^X-Jg{z%EWz;fftNvE8p0I&lHrH{9*{wRYyshnoQ9i+{%$@ zGo}0h+E&Xl<`#y-d6`r5WG%1Cav1Hnw|9;UA9(h#tP#sAw`@Z;!jNB}$m+?Dv*$z+ zFTKY4=)dK42vnYruk3tyViQGOZ1?p?ura}JNuZlWop)$xM}=%EON2>zxm^UE>Gk1E ze}||9|0f;8B!rn6vIkKZ%=D!QzhC>~7HG7T!#Y5nOMGqaWEiU47q_=e?YH~rE3>AB zm;cwF8+?nM9Pmf884ZUB|L?w*Aow!9_Fn97L*4{BiO;f>Gv1b;f_C|so(5i8ie)$W zUN*|`>V>(+P}3V(05BIHl1qT$uC#d~VV?=0Qj?Q3r6(#K(n@M9sj7XO zF{20-m$jA`LIIW>j6W~7Oq!F<<>#x!8CU1qw*@Bs z27;S9c&oQV7`hCq0G1WqFZi@`sxJw3Us=oJPWPUAsOZY{rcmC}L9Un)h5Gv|0KaZk zlM9S2xKfscENkV7jf{gb?@q-^K&Li>2m}@nA=9f~76gtYH%x6eVF-ogGwCwQl|O^k zwx$>{#_6h?_$#wk^kYBsnXJRG|DrONoQElETwoLW6lYF2$ql!_n7}@0_sLO)H%{6f zE0br%BVa|}l74;~;d}_;Al|x&QQnG23DxpYi!Kg;w0s8_>up4!PP~SD7Owxx)azP( zXUFcZxVV~SifuMQR1fAm)K_?+Ox|N9`%1ff&aCkXFo_!Z6J`9D_qAaXe1uj3Yw3U| z7IFZ?HOa;iNsP@)QU2Fl6-*{Fl^x%%Ag$?7LRn+EAaL>1{r4k<+;DLbcl2 z%J;*253iV+#p1+fhxt|?Vr1+)uOCy@6OYVqlxS}5geGz<_A)R(uP`vf()k54M|n_SApt zUZ1Q=-s_jVh{Xb^dHXU-Q@47e4`JLs;pO(hR%RaGB#)!z4WLb3rDu~GE99o-UeuYZ z?c;x($tG-So3RFO;d3vymLAD~!c3fdx-wk_I34B3Rx}8T_=pm?LL37^T}AY$zapfl zK`%DGm0qa5 zG2SODXH8P#7{Cci8$b7Xklaa1@FX4MO%-Gsde*OxW7d(jR_t5CfdjGaz5GUjO2jYO zvzL?^4Dy>I&;D9rgd;%0X@mwwA2R)`C*x9>$90*{GNAC46nVA`6M`;I4n54*pk5h*sjDlkQ7kz5HxNg&N(J&u}{vdqD{2F zGgiEEXfDtwF0Pqa){CviHZ%N9ljcb*s}kKqdxB0*)b8t6S#UQ=jk=5QegChP@uBR) zmq}%CTZ~5mbV$NKYP>C5yjzwuZ5R(QyHoJNV#h}-wU+~%=w+IsjY@z&rTh?GY5YNbp(;)}Sa8pg9S66auZg)C2x>-LX7!t-a#Hy@!Z zn&R~sj*^1+_(9ET4EKmzM*EC#EXXM2M;l^B9sP(0*;hKVO#xme^}FujSk!Cbe<# zH!o=_Q?}6nX!8n71a?vQ+&8#{=0G4ZA1!rlW>-mC-pN5%*RBb|Ce}l)Iz$`Lz}7jk z()_{mTaRHA(esERr`4BDfhA=R!+RVQd9)@uyTObM5sB4;UAVA#)ip#$5`jyY*$b}pO+0aU=xw`w5OyCT_{*2mIQI&d=qini+82_0sni@^ z8y|^}d2_~-fUnPYyP!83X6^Ma_UXA=EOXW)&SL8v8220uOY_(PZuo{33}p z*I>tB{QP9PiD*Yy|4SCS6igf)oZh9T?|{9UOfemx+)eMKaH2Id>(-%;vpf?JF;j_Bf@ja}!bXJze@FbQWj*e7!#j(Si~`{bM&}2RC5+Ux z+~Y$}I=wZj8iMM4Pre(Cg3=Pfu(dOKXvt{*JX~zI?uY05l)BXjEBF(i49z`~X*hef z@(+7o2FR9Z#q!}>JI86f<9X9FW}~$uV7k&@St8}-{eyI(u=PyK@6lN^Sp`NFx%H!6 zd@T4_VE?R~MYGgcm7X0DwbxYqX=Ng)`=v>@s!BbZH=C5yMnNz^=w@=JX_xmm2vdBJuQU{(*iX)s~#o4gMDv>!us?3IHRj?%e;^Aqh;$S4>;@QA+GZMA>$h2 zy*-}p$O8uoGPgR}V2jPS<`Ely>NV@3>Y6-;bOUi^vUy4XfxOu0Y@!j;q?TrtbLqW@ zL?!Tj6DKOVE#To<<>#{9X-Wc!?X%bw7O+rC5hu6rfvPkbp~qULvYzBV-ca|Y=%h4` z3gTvP{H^kpxx&Zi)^>ES)-1}b=ip@EKJsAlk~LG*`jv{&`iy{*$ri{c<6F}&HTI9p zsRsIyX`aSMfPxF^cO&|l11v3>S;w^Y!Q~$L9Y&XDi7h+!uByIU8n@oVMQV|axC4FB zl{0yW7ftCAJrs}^X>fm~1*2&rNY8zW!O)+~5s(qUnky6Q!yhML;8d1ix-XA|Ca++Y z-~1%+)22^4xOzk%&w2w?Sv>hwx{_!23B-Zi&v^$&GLt;D$TQ0XRxvlR+(OJ!m?;Tzkp+*m)^A-4PaM zpp;=I>=ay-aiJ3qX%OEOGw*u*nq=LWb4Vw!vv=&Cz=)06z3rB&l~V5))6a^F>~n5z zmx#Z#aYboYNZ(dc7;f>dCg@|_+>2)H{H7}XZ|aYcPi)8$2w7hZcSwLtVYRvdb;qnU?thk)AWbU8OW zpCv7(LW*#jf=GA|4D#p;yglJ1(#@Ih~ttLt6F1kOSJ#TdFI{8hhzJiWY0I4FkP@!xs zYj&mK3orX-u(?0xOAQxe0#lNIb$ajyRFt11&NS9SR?aPb7(b@x{-uK;HKA#rx95oF z82kz2d?xl)ZLaS3pj^fE*QL4BlbwZS3~y7@ST!p*0WXJ?opIm4V|IMZ&Or)xcpXPK zo(4U^*7^BLSwM$7zxmOe@Wpd|99i98n+F$|X*z1McWXND?p6SZ0Ds>2e&o%@f1nfo z(S(@qBDI`a$mW1UoYX+SlF)U8o$4mUR2LvO(6ljx-gJ{DFFut){37)2zDfBJ8=&+s zgZaxx!=_Lji;9F#`~l6h0sKD2N*s#9JXG6}I~@$`g98Y_c+wb=jnY7a1;*sho)<*q zIS;5S1&N>}gLAKr4gjmV*(;xC*8p3z)Zd9v-*w3H>jM^)9=%=I$R?a|RbON!E$EI? z2h|?wGUXjJO4zzaKzbr_G54#~O%)RT$V%?pAb*!#)u;(5u%=XS@&#z5d|#zYnrr`Z z50`5YRE6Hqi*f-U&j67C!1(1$uT}gmMwwfgSN=O(qQ&_eUMs2-dr8P~&+dA9M2r(j(rq2U6OpXDz>r!7 zu!+?#snwQu)-m0VgGTXUiw!?1xE4oD^HHBLox;`1xB; zZ+ouxBNm41coKL+$E-lBx2;P*Jr~yEbb6UAX|k7zU0x^#lwwunfVjRbtb20o;Ee3j zxDs-=U8k{E3)xFn`+Zf>AE?Layc7 zPz`1KP;_?n_Se}1c~fpM2|aefW{eCXLy6e?u=Xzz|rn3AxN@`)u?VvnwfzbKO-xsyA7f%Rtye@1dDYykX&wMa2kKUsF$La9M{L10g41-DE z7teQLq=yo3T$*~gcHi_A(zhsmUk@_R7l(Md{$SN;C9L~ko~wgCxR3>57kq0n_nqu} z)u*jYVAy>nGUtp@4i?U$Ibxd4>J*yj)3oR8dQ|3G3PpHwpJD6_re^(mORHVwhMOZt zkq}0jsdqh-RZh3Uc+a^bHPz0mL?+jR6zT^ToE?Dggci>^z>7^RzG46}W;140KKtu| zc0$dlU^zRokKz#(`x`yF*_26{v9k4?znE!*K;oz1me#6BI;vrewQws_;w!8{J;yl&8pqdY~885c}F&#UG^;0E*nue7qD*7p@hbw_> zpP@+Ym>)*lg?9TGJExJj9~WN^6@~t#gK()?9NkphwZ-tj>+G4Z`W$U1V@k$9%2x{G zXB_>Pr8cxKyIr85Io%cB;o~=YWxVUL`$p0B%zl*FtX`*`Nln6nk%cK}je6QhtayT5 zd!qZm`ok%Y{MK}ns!kb#_RT1p6*EHsM*o|iRUSUPFW!dN5tAuh&}EJbL)OQSsgRAt zq0cxh)-#18>N|55Hk@H}uW?K3u;5l6Wp&7eTRbgR`%%v|wUIROh&Be_osLf!1K$Lx zk_lho=3{C47xA_l)Y!{bMz3TDAMW;!so|CuU{zr@Wd2g0V$kq!da^YnA#K0TXb;{q zRJZq@n^Uug+|0Q)tuevG9GmuxVdKY#?oh+DFBeT)(xMiM^5#4a&OF%=D&GK?69b=s z!!;2q^!JOs-K%j*%;M75+qn{%=hX!nVwuR(f<2GTr&*p}-A^;0q{T`)>&_#?hS5b= zP)AA|OF5S3(YKNAK+$W)rWMF2K6sQnjbywlDGI;m<|O+J|GVUhrauG7|MskWfE@C> z$i&raEW*S^B(w?d?cqtv1aUr=do`B6yFfB?*vU|}{fE1l zmj?`vdY$l=L%BJe*GXi+A}q5XT6uhJU*@>%j(f5&5gh#=4rVS(T4P4JGwyFJ(Pn^rdAeb>C#g1Ui%K3;E0 z!#v~R^pU_@?OzKrCtAw_+RH!BxEW#)T-0mDhQ*rVCk8oLXyYnVC6n~N{zc!hVZh^X zwV4@H=_$V?N^|*c?X~Zc-#(e%w2;5D1XVpI)eH!KHfaCXbn~Grrwrz|F;ood7^pS^ zK6DlymcJh;#dRPdK4i_~pu`(HEhj=X`(YHuKt5Gm3_8vmvDuCOYM&35=SAye2CsJ^ zQ<|FoO%(;`=tzsaUAZSIBEpQ={=E?c+VI~id?&4+kN!j!s{sX1ZTJb<;01XqrXCmg z^cNJXOP&TXacOP1v}`rt1NHjLn{zc)#G zclJ=1)xO))!7P2K2YG}OwcyrpH3MYxjOQjpXf1c^m_mkL4BG@Ep@<}u(<)_b^Aq0= zhDC?#b#>(WS-Hz^c}8G>~<4U8GUVfBwevwcxPL!`nLFy*d;9`=^kN zG6a>K?1^cOywv0w5gVb&v(tJF3|Bji*SA(ZJXF3yfwsU_FEehcUa`eLfO5^zyXH z_k{izhh?hu;{R%M*ZyS~_N&&O=1V=E2_qfa*HSKH|M=pFzITsZnt@E_$@=qc2Iw&Z z%rMjbI^SLbd|d$f#r)+2BN4yg^k(n0#ne2VP^y(`*)^7mHPW4{SEzh%F!p70_re=aJpNCzyPJ%dn=kj9J|33xk#6uiMJHT{$tSD!Zj` z=VuWb>E8LyI5De9G#{&p8_wF5=EnSkHA&RP1u<~=Nj^Vs+Eh)`UsA`v>9Gg69CKya zHDL{e9Dp?NoD^G0@11UnLa+Ldr@;%;877zQG^H$TeUBfaau}MZq}sKXNp<|DG3{V+ z08z#pj|<(SbaYIAzr#j08nX{Z>bM^8O}3A)ckx36LgxdHr>7HW#HqoW^(#N_l_#r_ zMP(r;AQHEOBZ$GUsGcOBzNB;$#41ge$x#4Ju?G0U9dZ$dij8F%TfKO3go+%wj6CBe zNFx`#P=Bs-M1bzLfj=1j{2uLA{j`|ZH97**H2gz9eoJOCL+=x4?qOtzd!F=s-TN#y z^574F`YKw3{lF*-99X*X*pgiGT=lpb0F|N+5RU+!VaX?wY=}xv`ZQ7zx@y=>3v2@L z6LK)^dvFaQK~KB1Sg>=#Vwyyd0x$Vot8q7Y(_ipUTr&(98Zbyc1AU|p$ zSn;97HdzSrWWsqrLZcRDW_urOF0$al)}O5if+?OZ^k~;W35VJd1EQDSS5dw^N7=fp zX)(=PXKihq)au@UCaNhs*HN07=x@DA(n;lGB9?})OnwMNS?3fFGQ^u^*mg}RHdxm(4|e{aVxLx+Xu zQR&X$2lS1}gi?7_rj*a;ZfyBZyctiu=gy87*4&$8#oC7(`!qvR&@)04k{qdP)Nl?)9yGd1c->H23-D!i?a{ef+bb+(L^-+H?_ zAV1wNEV1LwFUYzNBO-nO{69CU%Q8pqiBcv~F zTq<(19`LxJ^Ze_sSGdfBcWW1IO{GtZ{&B|_ZNDM;KP_>e(`95%$MTk3k2^%{{=2y8 z@5PPzPjmmhSl4vvWh?@`AhnN7(o?^(c)aqT84K?MGr?dH^B<%9>+OH!*EzZwi?VJs zHT`Yo|1?=)Yl4CQ6|bK9M^Aho^h4`ysOk|Y0U?y?Es{g&_!~6I_y4+%ehInZ4wQy; z?d$I>gSLB8T14aoNI|F;+~Mz&i2Qju_WEBZX)V|4+`YDS)=vUMKXh493mtX6FIse= zl#8Ow+f`SenIn6>=M(rtZ!)(eJoc}Y{ukm!cOhP0x;6M7-6Ib|-q_Hy<`~4#5@M*J zu4#k+!m=aq7IwP`%P_efPs)_pNs!qYq+!rgpXz{kWIj4*`$QB|gvjLkq`N`C@SkzKC6eA1>RUqd(e1zKqk@_U9KA;7qHCR%PC|m^aj-52PuR!9b3+CT(aEeLR`H5 zD$Lmd6SwPqG-2T;4dI1na2&UNPCq7Oe)n%=BeNxT&1_-&a8cdvY zbJn>PYo6gYc*l1CVAtJZ_9pW`1BEH!o|I=~4k<-L;P%KUa@01utK$_7Gln9xwo!w?5DjF391!19C}LHbmeE^O|n7P(m6)_Utp5!ISn2KI10#lVUDE$LKkl%AE9aNX)!(v`Cj> zsHS?>{$H4rQzfJB-TK!@J`KB@bP_xc4HPSEX`yx^EYD>6Or4J

Row8L1cf5Hxic z;=>E153D1QWT+!DReb86v?au5&DG^MmTR^Z$O?_`${(MmWn6&RZ4c^_MICsA4J;RI zIpKw#oX$aS=dRb+t$a7FzA~>kqtBOBN38%6p%cK{0+h?n)hVt3@Pq?c>Ea`CQnGYi zQjm2SmL+zJgrSgse8^FEHx!^l4 z;h;fa@AQfW;>FxO;o*nsjY0HI^!V=gWXc?_$*4)6RAt@nPxSZ<_N2F57eNiuh*y#A zpi3e``Ato15tdVcXP@eK^dM1369vAz1)07(NxnO$#!F|$*GnEOJgxG={AANR@S|H0Y7YW# z|A2U@DYIj0F1MysGDGa(*9Eg2y*$M>_TAs5lv$xv1Na_Cob};mnKELBV$J=2G>y z9K1rM-7l?Z4T+Y=|7eYcqE^KH>xIV6r)zg1b6YISoO2pB|bn87FwD))WLFN4%zRFaX6M_uLdEyK$8VL^hSAzvwkTS=>59_L-9Yvl?0)8UIer=BpdvXgmAi zVf2%8MuY%<)N9N%eBXk=rM2waH3%X`9p=#^dCG#LGRC=|q_huNRY!zPppZ)_$&QIo z-|f&+^=C7m5u5hN&B|jA?e%pa>#Mb-_Tx1VBs>dp9SysTp1_A3;rA3bAp&l*Zk!=% z(7~H&-t{|@sd2d6aHMAlVL=_UK!`>3u7Yr{3Lw`7NvL6LL*HtmP+O6c8}_WL zl&r!ie37FMBi@T}wKC5ko9`%l)B!XDd4-17Yg|{`ZPW<}Iq>;o3Jtas`i+VI5ZwfA zyZ;G+<$F4Q_9O||zGsH(bI6V_tNSB7ALj0^( zFS0U07F!n*m(ryBS4BFIgR)!Us}pYAmeUGwKRV^Ue(+er_ev`3L(^#<;5VQEbzO$~ zWp+i`uzne0e;IO?tDmwY1NbbIDe^x{4czIQO7^G!aR0>*S>_)XzL4$Bk(K=8>7SPr zTrw2jVg{1~fn|+7_v;{p?a5G?#Mjsi_{jUzQNWcObKtqT4fe@hMgTFS6gPrzt#xXe$1hphS<0GMNbL2WZP#JVlsKZSQ|TSe85!!JG9d zr@OiXj!fiw79t^h4wa)Vqu| zP5^>zf7S;P2st8~D&TW!5qq>0>=p8_nsn&lJ$l1W4wwJsj(D8BbB8N2Ak0M`@snJ| zE648$WEWDBZe|tVY4N>h?})$ek`E40{QOv3LIe|GS!^Y>Mt4owj9_7HTf9NEOI``g zS(5IX-XDQ^nHD_p9WY#Ux{g}9B)MfKM0H34Nfp(6{h5~5XPracW!|j-Enj(~IrE2@ zSsMZA8e`k5!P9?xb!4h#>Wj12Rv-N|;tnTLdCP$wN}HIep$^^E+Zt;uG6C22pT5eG9P z+xoh(#l5agDJi9$=#kI7e0JQg#>t2c%Ey)PW14XR$?K-h^3bggng5HKi@VjYL*0yu zf8;qYPi*MERHW5Jo4k+jvwMcjC)gD|-v(&K88DbPIhM*eH!J$ z6cjAjGiG(>lbtViMAdGEqi*8SdKT}(3H!d0S2<hLL;{VXNp8op)nSk~z-s{Z}I&n%os_ zE=sQkJ?;_-AX-CwU@nI{WZ)y1?k}{wo3U$qiTE@S=9Ph^M06e` zI)x5O-tqTcIibGsE+tuLK7R_oi+r*-{!*r}v?!?{kj!YpW2AD5yG*6^-bw7$02CNG16uc>*c`Jz-00 z>=Q7C7~`z^|Fc{ynm`^VqTj2yYfGw)@W^in+l#sSqI~<%5}gbj3P;P_uB~*zDxrhU z)+35*HEcGVBrUs4F`o&EkVY+&~<-~D;hF;n&L3W^9c zGf5MkezR!X?V9T5Ov{Tz%*RUx4d~(IGW5lr?RPlJaM!EU|9c_e|2)4P<$q%`m^ui> zCGp3^)ZLBqG)vVe zSisFz6OQd(xrjPxW_XuWH({yPk%!E)NF67(B#%&4rvFlI>1q=bQ331YqIb?&T%_rvg#?Whh z_GiYYMNhcX&En+%^2J8%LVuuM=>OhD;OA$!(1s6}!ucxXEi3i~slL|NSVccKdU1q= ziv8@cqI0fwciuW{;rehP8R*#CH+nx_I*dMNkET9Z89=bPM^DI!}q(br&Q>Pwp~y7(i0~WwI{{r7^k}$ zq)-}4^1QS#U?W8Ab98$IBk1YbM4aYs;n_AEE1;7ZD|3hhi=t9jQSzPKFGlyy zPpHkz{jl2WZ#DHUd&g1cCEYC(N!Ho;FZh|yyuPRlPAn$g%Rk>aH*-FA0voBLDQrDF z+oqRkI;F0KOKjdHBhHjBwikUBo%P=tKB#Y9g?_aZ->A(z{g68A!?6I`_F zV1l|?o+0QlwxXNmreQ(Q!DRHzw|KG%$QBPH`pL*O-Smo6qhe`@AqA?(p$i*nTh6c3 zeVQPzau62yNh~RS56@*Y^&p*w51yS-M5E$#7@gzp$oOj)Q%u zFvn0O!L*UB0S842b0KB;@(&|d{U8|47bq6Isdl7E;Ja|BVX-m^7a%49ok!_YDcCg) z<{KxHWqNX9bJm2CA6Jf~-onO62|1Yd>b0v2|2l~xQ0=fm=C*d94clihZmJ+LSl-+b#qXaI`-q(EuJi-GC z6XXT{8;`Pu_6n|fl{G}g5mjlf;{iD4{nq~F5|mHPIevehgXnFM66ifgR;0;X>0w-& z80`+6umWyIc?-}fH=fvWuvJ(}^bo^U-{;L7lXRa1SqxKM9qYx+8+cS1GJig5D&b|c znn-fm34323n^9cbu0_MXuSeY+hTW-`@DcqxM}4+V25BCARBr!rOVX&V9O zl@~hSo0Spj8(juW4SfHY;qh6C5-u(p-9rJy%Q*ZmWvxfqco&8LK{!hKe>85Ay@dlnIPUIbBD+<+6X6lfJD}cED(&;dP<(! zb4D0Qg87fk?G*S<$J%kTmem!itXh3Bfc?G*w{OkfE?}^QYF~%k8YbG~sM7iJM-*zl z7CHNrP6MJgygADB^2tQ(!93Dr!Bc#e8i0xDL0EdqgBIhNjK9T5Lr#|#oZlw%W}rZS ziAVj=epl?#M`wlwO@UAYltV*(HKI zvEeUlwU?x=tjCvAeb;e&bYmKq^dWj`5{GV>&ULRN1C^4UkboY;c5$ZPWDk#$YFP}- zFJ4a~S}W$v70p+|9ih#bqbLfSYl%z(Yr8=e8r1sSD0sh^`oyOi2T!)MOMVaO8}Pt= zsdb3%A;(ZqoJy=P%~YmdabndI!L&!b3f`?7-(>spLtqO-;kM&Ip0uGxw%@u&$_=-@ z80Ta8`^77@s$PXU>bT?5G^~QH*8(a&JMlyp2M4k*rQ?N_R7#h}kq(t$8jL|>OnnFe zcwG{q@8G>8PI}JKVg~APQ?{?mQFb>glo8ZEI=!@eYInOpNG)WuS-snNW}MBpQ4ZTr zM)*Gu&UB&*8EIA*iB#<>Uogi=P!w(e*GAA}g3xYjBDIh=P&Uv#+AsPA^e5dwfJKPL zk)p1`#g3W2oYk|ExilSRqeJDZmNZh-AkJp00+mJJ zk&D2FcL{1kpINjRvu8X7)Ewy3kA(Vx!45X;l&jW_8eRtaO6^h$_ft&#x=W9&`z1ME zYa?{-kpd{09BT(-H02y=bpw3`-`N&Tv{8QLpzhXPtFhtWs;2en*kh+5S6XOmQf z{XoJPj5~$x)7;BNp;&g|Sh)QJ{AD|puw&6^tgavc68NkvnCo|xIw9**#zpb_wp?2I ziiS)|Z>n+3KRrq6-6#b8ed+QJ!8{XL?pG>TGd=Y0aLrsfDCb$%&B7BACk4280!&-sjh!Vsm$!bB#f zFJG2?CH6@*-3xxABGV`;0P@#2SlSz={`|dlX zXYG)}zGpCSlkRBTk4&RYepc*H%m1OccZZ>> zC_MUAk7kE>Us*rt>q!FMS2hWuM@Xf2g`h|ytQAkkFC54Fu28}_^mBp6T6)(;G&72z~*Bz!-j&}`$;4$Vnx zNu8u2a$P<>nR^btc?k1;^UxJK-a^Rb+m~v@6<KMq&R@aGR{GFyOD*&&2l+Jqz)- z-vNV8k?sy_MD)AR{zXgej!}6TucbJae@fze!&lKSHFS2g<9iU?YR7&KxA^N>j)Tu1&+T zHUQ(IEurqQOzi_ym)r3}Jy}PhS4&LwI@ex$ropOD<5HFr6kXyqJejeG-^cUz4fy!Y zjU#*-MI+xMu7=>qhjnI2>5wx`<2frtvaOdE!*40H49;O{Yrp=zcrM0I zP1xE?Ay%}&nPeE{fS*hwZwQDkprf(!Y{gcx=ztzoP~q{>n_#37f5i=fZ!t!Nx3-Cl zKNZ5aYE<^^l)@;tLqLI)o)4BLS-9|W>Nk#&AOe1hyWcJDCUJdhhZiVREDLti5c%{Vo!Cg(X10$Tj}Hle(zha{%#|17yVR z;NO?gbL8jgeGW=NDzJ{$Vhi6q{BEUVBj~hZ{)gV;DTz>MIsssAXr3CL6^;X}C?H=U zR5_df^F_hXDo+Ib(&ySir~Lrmt?1R69NA>(C*o|>cio9%WzhOZ8PIa-H$T&`6+M{_~?SaQ!q2sM@GQ2h?ZO5M}DFHx*ZvY_dN z@`tmQ_T5P1gFnRCzNT}yndc*e$jL6YW>c%aP_o|e6oPpF+6lyR<>>ObA8S_8uXLsUi+4=R~3@n2ql=d#18c5WH zAW6hF#lb1k?OWy|1R>9i)2KBjm2ooPPzF2aIZ}IKdpbA9xT0l0a%&M6X>^Bd;-;2J z$qeR!j*#+%(&vI4ii}0i?z7jBI$iO978`v`-8p^kEuJZ-}PLd#4-O{X-3Im1gOw^hAm6^Ji zJ7tJ;YwBx+pMgSxdIGYu2jU;Op}vTx@lqsrA5VSMP+dMKMcgE-4p-r@ZOvafKk(fc zumyWDwfDRLy3SPIzHhgPeA0ImioiL6+ywBWl3P5No|#mO3~}#|0qxcCUBYPt#fitr zo&rHs`+0<_SIR&<8W%*Klku;-Wb`Ep=iY7k2(qCW{-_yUTPNSz>W||FHn~o(^5{(O z@K^jCZFZCc9g-ySc(x@(q~c1y@&^EBt9aeCf-mkgg|gBAKG=X?Nq8S1@D2?N{}#j! z&O(M*X0_9`GO=5Z{76BNj=5Qhb&XiL1==D_+}ZeyTR`m$<>r45khgO>eHIn-p{drc z(!Jp)r9a5BbNGix2C_^md0El-8YLKS2Av59Kw~iR>DYSKi(J&F$;1R~Fa+Q*jQprE zEyhNlIM=TMK{C+xnO2D-=w8=SDU@U9%;%6%K7*N&B~EOQkkbwxpr@JSA4W=m5`;Uh za9jog(p$p&k8IdhP$6QGnufWY(E^RctbHlln_Bolo8DVLhxI9V7t5a*I;|5SwgQA; zb_HNb*)s+(es;HTpjC z@uCc|+5AM>L%{n(#b;uN1V;_aoLPgfJL&Ii0mg@u#+!^~4||RK1kv)}6xy4v0I=WJ zjF~rT?k-{3NE$wGUj@9+=vl-Ap%lFRj10PJd)QK8?jK7pVV_2AAn{h#2}E8^FIM^? zsJTNa`bnIBO)T6-)q+tQMG_&YWXw-c&)(-VyfX9`TWKzdY)|#PjZwOBrXZsBFJpeT z#Td(U?_&q=Amz2Wx%q4gPp?4rvO|ix;t#YS#QERd2_IOy6MFo$bjiYswTDcidSLOp zKBN@>z+zmk0Wwi=h58+S{l|L!gnN+MV8yqe>GQbn6mq$byde^Z8;Q}}6EC?vhmNy* z0vD0uDu z@BI?T9JNFw_VKB-#&UM5!`>rY*uUDVPX9M*Zd4igxwChv&>t7%uYs*+~% zeaoOLO|T~d9$kQJE&!(E6hqT<1*II~sRoj01Wlh0PyyOilXV+?p84{`#z52$iq%~T zC2k1ZFANf!H7i2z-}H$1@nWG+-P(mH6M+JG7`k zb2g--5zMJZ_zk{KPm_F;*&@cbW~?tP$%BjQ|2TBY%GKlNQN!LEtNq)K_rdp6%};## zZu3;eOxO1p(cyUg%UCaT0aFZYapJ}}$7lP@1sn}AQTIGn(B4r+>G{+7>8lrVsl6UD z|8%4Cyj;<-qoLLm3>#>)sUYqH|x{9!80$#}wvFgh5Pr`09d%Xkj5@ik=$RqE*9u6K> zoZc8Okc{zkwrIGl9WiQRSFP8U+j}olS2(};kh@-vzQ0Dx{vQA-YJHGAwcF>&d*Ze; zA3^MI+JkE=SzhW7)-G7oaw^m)ycK_Dj^iBn9)to!Yd7DHNXE$JauY^ZKmkUK0;1Ax zz$p@ra!sGTXL9)L+RCSaklM-b{!W7{7`-`W>eL}zT&IK!E6x;kky+D4e* zXM=bhD_-Yk17aokqe{kt|14SC?%a0UPP&8my(@MCIxW5E)_{8V-L7?+aq0NAJ^>IKklpBkvE|0)>PJy7DGI8_|C+4I{d!Q;-)DsBx^L58l%tj$kpr8P7$fv0fW)D!u}pd&twNc;}Fmo)clV}&=&jrYHFGx1$n z{E}bdQG1Pkoz0Dwxy!{R&c zp9@Z_m+Mpft&#cxz7{rgnrRQ%a$H`j4zy_(cpex@_3(a$E+eH#QJCb0J9Ddk&Fr%} zU7?|Z+sNbk~lLX4Jqb%gw~t5eoN%{d!dqE zt!4C2m1?bPCO@E_HN=#`C4F9;#ye%L&k|J!va{aKdcQcuKKIPvF5KXpQ;(D?>>!(f zf?V&wa<1rYulkowc+aK$>9N`?)V8w;+IJpTS>jD>hWKjyj7#`+kMRk%Jrs?)W6dr; z(75Wf*(Kf{5Dw9L`el7H-Q23~a227ajVFJ-Xw98obA|SiXPgBL2l~e=0h>Vo1PF@| zH959V8$6--&1Sl@Z?psY!pC6EneCG#&^8S}nY-OJeWG|l@Yw>uc4_~6v@^ZZlt_A} zK*_fvX-LZcy?Q21i-naDqFJME>(rjZ4nZiyDyRW0L|ml^#?Sqoy~2fPWg-Dp3jvG8 zl>9Hh@b`{nh}IUpsh&fuNyZe?AoK4?uy27q-Y1ma0A^T1&=kgX(@6sX=TNtf82#f1|{b%GdvS9r0+fnIrBV>;yaw4%I**S;rTXZCiR3W ziebJJ?Ej??PBk&=JErwBm`SIn)6&m21UzFp!$bjwkC4tb__Hg)njXK56a>o)ncNpD&S z+)p3EuPrmvz6`D-t;P`8ddIapJ;w>YJ+Zm4AI1uMA-l?nIbA39hb!4`-<$o4DpYIE zGxWC`%=#RKvt~Tv|2M|{Cl>916*3TACW4JUx;N!zE7I@K720T0r_sI=(W}MKS919| z=v-tAT`cK2CY899;fGUQSyG@8*m0rS!G;gQfJyZ}IHc6h-Ff#-E+|z{+0iZL3P*Ct z>|GY6Qyh{mSdDxZd8eBnhwVzH`H=`#1%2aIGbWiK1PdU26cwfvz28B^KQ}F0(;gB- zqc9y|{!JF(iSuwJ_stVF@hQP4JR2L~O ziMEZau1Vcb7^X*qJ^Yqa|G&t^BB@g_I#zpywx2|)<426ncTCDVejzx^&gxxa3c;+c z+8kBRzrLB5$pzyp(7mGH&fDcH#iI$hJ)MI5sxksaO-`l5s8)TrY_>B7c|V}Me4^+x zfAkhvyepjYZWZ_6*4e;WLb+Dx=XbdAopx+hKf5xi|2DV)qaw-5B75jLp;=1No|a-l zG!3Fqe?i#VBEozSa*n+=9Sjs+7DpN0CV8GqHs*dI#4GHcwO>)mAHs+om_UD8LLT6X zY3SS=eoTXoiDBvL;qN17@O>ptqz+yOJRpS`!Ja;w34F@qQ2*17=H8}93?)znXPUn= z>v|v`A@E*~zr}6gzV93>9SN!86azxM7&fscm*zKyP$my=Y2xZaaz?A+t>W5`5p#%>=t;h{UqqyzjV}YeL#f?;E&Ry8VcdzSE`*?>B}uNfo!2aK z+0F+8+rZiHztGpuz;w|BZ868E)Pd~O%;CB%%XLlviVG=$K@)i@)SHyFvp5|tT3X0O z*kG+vjhRx|#cN2HpgFU&-bX&!bsiMq`e&>8F*5qF?LY>82=W`HF2Zjf4SoXY$_{RO z_hE6t_L*z`U?X}Mp{tTP(`OA->vt{N#8lQPG#C#8@Kt<{{FH^l2$r{uf?88c@4u^3 zo!c9s2g_hb_wDEe7TY%PQ=CtHdf&d1A%;gSh>0A%QrWyhFBt3pn6cI6mcqUs&h^A7 zK z909p&7pWgjv7k>3%Kg+DNc|eY-|$T+=jTGeREVJ48hoIt;Fj{j zp;g=OpIiSvJFyUSmj!Qf&YD8v17l!06=VhUMrDd&r8>B>7l+}8maFCRS)6~Nms%xN zR_=69F}Uxu1m0wdvzypKQF3wl=c!dg8_*p1``Sw`%C?dL`veZ(Zc4*u@-7UPi|mw}}$!g3GK@%HS-MMLVd&d0puhDY{5 zOdzASL#zrE!1wQ5f|U>GKY+IZDMN(nq`XT9e-kc+OZ`b8@xt%m%um>N1|&kOy&uGh zJRooC3m?S2a0}|})BOG7ZwJzR=KEV2o*6x1Jp@A%SsU(cWw#vWzegnW%4Xs-A5OJS z_|x@kIsL3c3UpJlOJ>zU?jHG}=mE*XXAL$}>z^9VU?qE&ogVacNp5l}ZUgH4wb>;M zbZj&0BDqnfS2ap=n}xrc_Xswkw6<{ASbslX5hLurAtDu)m{TqpZTI9?m`apxk)TS| z_EEYc{7ee$wWQL-iI5BjkP3BmW(rTOjbv|ZFlTfdr`yD}dYoct^;ubv={qgJ z+KX(3TOljxlq1GsHD(g(=#(c@HrkXLU#mUqrZ)bx)cepGPIxD+FrAIv4kKx5oLWR> zv~;BGRZ=8+?qwW$g2 zudnZG3Q#h4218dPW5BeNOzj;+{YvLyYkURTSCd+oiSvrKwP)UkbhDW@kptO-9j__h zU@#l(ISDw+S~rJQrxM}lrcL+E6u&;IRNWGAGwuoWa|*Sc5k`3U`%!H0{d5>>7y1&X z8j#%kB)ch(8}uL$V@(|US>WgX^)H9`vts`HZxZ~`-=0wbC}gHTUIMJcaVlc`nUtho zd-5as6e-*r+c1ySGI4(*U!p zrXu_+J6%8j(WrtITd%e}GmjX9OkF&`UJA6C5Uy>Alo3i0WT#DW%*?bfuIRM@!sI3l zxIy;h$_4opJ3U?ZIe@&TeFIhdX+lcxWY-s&(YCx_pVJDl^lJT67cAOlkS`K!kbIy| zyyl&D@A`|k(79N&wK07Z{i3tW!@_H&bPc6$^ut~w=n%0 zs>qI=H5~o|?bJzW4y_xsFDYMEpK=><;uNL}Z^*YEj}ltf5pbBKuKG#1_`^(r>9te`~{xarahaa4<;y;-#-HZH2E5C?My{!$zh?L2B#vhanHLGT^Aa7=?MA(H%ekx)AN`* zT?SKgFcnw0yKgGBl`7=M|KWSz4ZX2u!{`<5F+w;wMmKEEN@*oomSsknBu8mJg$b{! z8i8DtgdQ(O^JVTEO*}bf31o;<*{uXeBJGsPyaBFLT3|ZJXJxy4S!c%gGXC`$c)8KD z*?9jhe5&^V)L#Kszj)m1eY_D*Ah6skA}UYPMjLEJzPhglb&NZ zrubEgEy#kJjj&AyqaGxSv^)c}zLdUv_OCxr2b8m{E*2-@-&R^I#WKBdSTx8}Q1n6x-T`v5%wA5PO0i45Y|bCRHPcF=>!A6`=k@UI`ue7K z@-QEFWywDqjd7CcuB#-X{S>|j%8oeECd&-!z!V>xFN7pT15`kC2&m-wx2VQ%$%I@) za?Ed4bU&a(Mum3@z08bP$z20D0$sJqpQB1cbp#ScPPAf32E$yo__|5SM~j`Ru@tOI zP#PWfN^9NaMO}+S%7d^rp>S%-U|Dn**X9}mu%&27=|r zJ+=AkcKPex!5Vh$=ja`1Ttqg{PUS|q-?NZ;XWYYv4)TXMC}F{+fb~zMoTh;sNK)Dou5u4$)gkstrR*OX4H!Gw;{Bq|N{Ahzg{uV##5n#l5Es^}q%0GH%IMwH|jVsuk zTYW!)Pna`mWve9VMi^6m({X$j`e zlqDkds9ngpP(PCbw(znRCnJl%lP)ZQr=y9Sc0Xcn$bBXr$J*bO4n@t>cR{bgQj?+K zD0izLTTivs_M2_X+=KqoisgB)!e#F>#La`nt)|C1zy=2sen4foxtHUnsKI0pd zvs#W-GSh>}p^NL?JPRvG=GMw^pjc2{TJ^Y9%mX_vJfg2=Grb`4{UnEczNQs!*g=u- z4+fi?`?yc%4)B=YS)Q}=B$X*-b>=8HJ^Ub&*Og!*r1dK5KFxa+yIg5VgxIKVFW9dE zx||$?s(&{<9?AQ@@?D*srdE^}Bgss~c@bM(LuiZ9AK1T@@t7`7%2D>^CT_F~Hqu(r z+$4ZQL9Rt6Qww<$XU)a*{CP4U(Z>j|(K1UOx9>RwIa8I}0wSgTk&f`g^mDG35g$R+ z(WQ<7X>n7pQo~DM@QEzm*wuVa>#8G%I+k^84U39nxzOTW7b+Ok+jK%RNp{t)pG>t(ou7gFd+zgFFuzazWbKdN2p6-iX%>}fq!T$5XKIiF?zD-T3yaWw+ z|Dxyc17Gii8A+sd0EN~w+L`;lcB8%gF$yt&5+j$n*-W*`jr`Q4%nbVNZui@Y$Ql#3sJd5b0k^B6+e4=2SABG`U`Q*Pu`)eSsqYT#&AX_^`fbAJKQfzR zt)Jr7&CdfL&w3kMWb`^MXk;XSqB&6fIdHf#d(hI$N2II7L8#O9a5OpV*8|I4DOS!? z&(Yl0C#=j!6=V=g@iQq80Eng!bTr@w0bE(EAcK6r7s6c`n0AZrJ04clJDyYU#%{4(F^12M@*MMIG@k@|&(X1Dd64}>1gEDh?S4u9reYK_Sk?jMrxJvh=qE2De}`Xzn{5e2pE z1hukmJ%$ZnGiahQ3XtM@I*RpK?dHC9=zALrFE_K-w$R2J`@|QTFl#lSfsjryEcn&wihd3#vyN>7bPq z`cvB3J?;;H=_cq^yNs;!D4N|%eD78ePHU4}j_BthO-h-t-81|i+tsGvg+ldEE?@F7 z6kPtwp1|D7OpRq;#+M719RF9DrdqGSoUlD21VB`1)aUTMT#Q2o-wNL?gY z7UM>@7AhFEu`-5l`t-R}E@S*ctUV{U2kpuSmx;upFz?qs-Dw>NZhO}s1{np7q<{+zL{}6T^{4qPG#J;9EEKfP+$pVw zM3q$A=#VWQ?g21n<)$)}B9B#`+hXt04wpy7s_RZ-tv!)V9Hkl)V5X>b$AQ>7pvF6T zf9ycNtj5hc=$>oFLeBciCK+91*8Mgp-4oftb+*Sk9d|FLOXxiF+@IflI6t$Bp65x; z`tx%-zR}=%ZvY*MlU#|&XZmaRsgBEH=&815{fyzo`tZ2OjcTJ@P$~m z2aIBc4f5#R>x{4n_vue+KW3lSoqsd=Jggbh9ZC+{#mQXpfWP&YFB!5?cF);NJ!s%Cqr@ zU6f}=t^qYbgoHh?u7rVvt_OIb$R+i=+RWsVFvmIdS}c<6muvS1QI$Tmd@ZR0^S6>! zT}lvLYcC7-D6n$nXIiS`c>$+^dvfN$XY*=xNKE{_`J;dX?;Q!7x3kde3KmlRTl)g? z+Hrzu^=gVjaussziK@s-u0ejJYv3|{8sBN@FnDe* z4eS{r6jmjy&EeBA8+p=+iH3>dS9p@QTiKon{?Tfy8890)ZkU>J#=e?MAf0F)eNlrc zOleWQ{z_`2e#d)F@Rxy_0S4g${kH)=isxD(UDX`(M?$Y_ph%}(RVyE zV*pf}Qi7Oza=UlD)*gUiYOJc(TWDgxpYqqi<1Zh`AokT5R&|ld6Jgk}{m3EgXBy^h zr$6L=*Womx39omDRF}4Qq7qq!E|g&9=Q9oqXtr5*hj?T;#Dm4AN0$)NCp(t3qWA{| zaI)^FvFD7ZtzCL6$Y(LgRlu5y1efhhk$QgWt&xT*38>dw1&1Louv+{Et zs9{y%WHYCYl$@x>qzptpp_ml-?S65Y48tE?D4OJL2iwCLynBF6&i&0Afx3O_DYYaC zwLd<97qa#%NFv=JO|C-;osq=U?;GH}9>~`Ei?OlVzOCD_N{0!M1N*k8^iEm_r3`%Q z!c_6{KIh@j@q!$sDP&|DK+Tu`0Z!zCRe=}+3514ol;buRK{yn(C8uz=(*s!eJ2rK z7xo7*KURIAB{s9E=SL|-SJ$p{{Rs1ur_|R7dN##SN#M^(zb^Ha%fX#wC~f--Tapxe zj2rZmc3F_VM{{9;bBV^Ye3RIzz{@?Dp>d~d^Fb{1wiJQ`R8afMdd85%ak^3QKFjFR zmp-jWAh=?Z0@FVKLF?dgTKcw$d?KgFdqedmGCm^|H~Mz2wN2)TRhX-yYcT0=06*^+FJwSD^VrHNCTrce4c3!P@B| z?Ll9R|89)X>U@V#ooGt2ovN@m!jeuotm4`hP&?n<#@EfrU-eq8$W>{gnP1l9VX>jM z`^m%*6x0$+@U9dapt{7YA~@7z63XJ}VyO zf4Yy%vp$C&dP7;-_h%;Z%vB0Nx)_+;kJn)C6K0k-wQEjxvDA%KKaZP|v~#(L&Hx7Z z^-%Nw`tJA*PNdlK(j?x6Dy9#~;=c6u@wO~i#iDrp!nWRdTYlS(+Ow?)WbLF3t=5qX z5&h*|)k!4Y2Zx+&(;qzp0P5_Kh1^x;lAg!z)4Vy@(beL^$H5qfk-2YA0I`2ww+WlW zWui}#Wg-6Qei_~K$kpReeKlfu6C2SF{zeNA!6^x38$tS-7^-+z8Dm>2*{FHydft0+ z^e;`gXj7~l2d;w?LGlDU|4sDIn!)qBE~pa)FTOOL0Cm7 z3}RBlL|;!3<$8GNszo4gOCdv>^$hcH*+<6tY*GA47CfDjn+xyQS#NcSKzbX`XUB@p z{cg52XnLMmA_7 zr(-Y_VWqZ~sZg>gYACsTscTMdzGc=nA88uxh}u>K;z6vZ=3x7y?%s2dTUX3@(X_9& zuGxPXAX@3(=E`VfGFLIsrVcamN*u&vW#Z)TWxfeC-thI#&g321ys?Uvj3hqZrZSfB zlSS^@u1}2rc37L6Z?J*Q(XNo>j608$5{CoMrs=aYx5=A?sojh^MlON^yPbKz%Qv}p zaHOo~wZAm2X0$ z)x|VJ{>p>&a`PWn-&yr1ng!2BoR7DE6cBfpbX?~4C1mBJr0$t!CH5AerPqY{BS}4j z{tP@qG+RPv6-v<5FbrFwef8EV#s{<2L)sZ;oe>UJhlfv)p*T}?Ac$;~kXRr5 zYN=lQ=)XEikJQ%J(hAI7kD+6*6UP3V>$L=gg^QHE&l1-qb2!yo67Y<+Sq?s$F5g+t zgejig2L_KQI0rzE^(8Wk>o86RMX3iGQLk8TNkRUWHKKwD*KQ2S<>fVn6qzpR2c@&4`K7wJ%lvTL-cGYni=+PhBRnlFlJ>>R`Mb_!LEtkTa zJ-b_tWGJqFH&d_}xfRUC3Uz_i*Ic_8wLB+(Ibewi6E=RsUcH-I>G{nQapjN+)U|i! z4|{FydxGP2?2^5|5?f5$lf%Dpv*r3x9u6sC5uti_cWHDRUCIp*D`_F&8EKN%d13Cw1e`s(xvSWjQ<0NAR-$=;Q| z&&^6a>);HGz5?O%qxMadq9+Y3Q9WUQGVjQdW}Vsly9U>PwE*^LCT)&uA*U^uX9zDD zvLr#M)3k~yq|67C&Q1;R`srnpeUSH&{sdT6+@D!9tjqc#B$WRY8^s6Qu5ljybk&gXVcGDg&o))#s& zDvhBlb!;c%bc+sg@A}B>Rc37=Oj~WKq3z2Sb>2FvDbklF{3WD`vQ}({7pAC~b&Y+N zbKAg%;Iqn=C|5H}<*zuROK~uzhMTJ~W_ieHOK*H|mp{O|t5mGm=Idl1Pit@(W0YhH zq2FmG7$E9Rn-H@#3Gd|`%IIbc^M?ftS@{!|+zGPV5_p^1Cx4G8FN?b}UHL+7`r~SG z2FJP~arefe*H6W=oOS=9do8c{EG6~945SKRNTx7s_9{#-NueB#fB6`Ux9h`O#? zi=wi=M6|nVl>kHcELJIpwf%%ppAhSV@FK_*J6^ndm{W7sxLg1wd$Oh8$aD)^Q-YfoLU?S#lV4 zv+u@)t(3xmIYf@c&6cb%!>b+WNe_a)62gY@U>(KIf#0GbYMmDhr5m z4I!_11}>>a(|lW18+qP#L^3KxIhW@QC=Z#;QXlP-U$SKGbp2I!e<!L$CYrJu)NGa?=a>Uy?7c)9L(#~%IO=@*tbpBgvatO2)1s?} z=r<>k)(7lzO}l#KEN~6HM-+tj6&c$5@PSMX=KC}*kz5!PG7@pz_=tk^-af>o;K?9; zBgeC!T-ka?h1+u?H@y(%0PdR)hOsVG%KI^;TKG;CdyJ$oUAgd0fza#Y-g`RR*Q+|@ zs5cJ4cT;$aHZL)k>yualHX4{tGfIa8DU#mDXmA0d8CvI^D}hZCGlwHqmN&FsVZnUQ zFmrpE13pPd)y7lRo>SUTq`dcxa1-AuU|pOfCo91@M9l>0Ta1Z@BvoYMbMwV?#gBC` zX{49X_41CgqIf9x_&(p&Z?Nd2_7Gp9Yh)bK8nEUtiEa4Ry@w(+(zDS zN(7eTHhL6+EN?-YIg6Tj&2C?8R?E`$qCbb6GQ&>tn<=ZY(^wK3+=n?er-vbt|u5 z>`1-{UTXhz7ws#gYO>NN{)2_z^@5g?5SjUz(*gIOE+eK<%-SjK4jin8*1$IZno9@N!k@PkO@2;5x!b1 zU03OQ{*yWWT+p!EGZDXRTz_$bM!^zTGt&&Zf6%Mo`6(?=xRGw*hz7~Yu5!CG)n&jq zHb@_eL*_VS<4jJg%CkJ^S3MrIvmfVwf+lc`u(CMQu|dJflj>u2Rk0IZj%rP2mEVwD zNeHH%3w65_tnH|aR}^_?dXKQMs{#}Y#wnPc1(00$YSf5BTqv{Qs8{PzLPu1;sP_vV z3!RkEP7^qKN=x)is40LLN=SL3GzvHuiWU%?x+_XhnVtAz9TBU>(0tm< z)`pTVb7H-w>78?|dX<;Hmy4wz9|5sgIJS$OV|d#b~_x;&=Tz%OZJ5q zXtuLEf<8r?L}BJfpkYppBV-!`j}dRd3D?PlUFLmSNse;A@@kL0`*FLK zD}lluUqzDpbT`m&RR>3~o~rm-4t0~d-0J5WHCd?SgE5un(j@w)e>oSkE`#nF*oVr= zbPwtokQnn6^{&Xde_C)bKc%MnE9y=s)u1r}T=W(yd@J-n@n1_;RFn06SzAlxZ-8<^ z_F&phyrO=&lIE5jr;pdyVw!SA6YqvXlKqC24PR=5xR#NvBXWk5=~wbhNWT=t=F_RXhGT z&MWqH7Jr3LobXB-*0=EQXT@_voeedg@WyMd3Lju4M*A}Q_TQC7TJaRYC+oGv@Ns2h z!nA^g^e}hS-Ec~hPZwN(r&}AG5Zhv09@YBI?F9;7-YlnJsb^;4BfbI_6{I3~%LIRd z-yg&KmunlTuiZ8NIx$w3aZ+~oEpCMv?C^CvI{9`yQ({IO9wz=cpUr16*jZR0j!6nt z#O+o7oPYX&`sZx(-|1NLKc{2KuV$;ir9`v&DA2D5n>|Z6BD5q!hQ~Z+PaYYI+uMOd z)>Ilkrsy%Em{L>yYZOLlLJkapu1ZNTe92c7T*~9s3l${KTB3wLn7z(hE%vQwHWD9jDna|DO`K#~r7rw;7X zQOyi>k{o5<2HoVLAyP}7x$R_-R;6a~j}}hc?{UeqJFv_gWWW{EA3Y5c;$NNz)saZ` z-pP-+3>Av0I=QyhdC~K{v8liyIhdXXW1-DE3%R&1#1yG;2VbKJjyyK81_=vqFc|_A9MwXAaDF$F@oL^bcjahmR9-~5NtwIMQgwQe>9ziTa*9y{{<8z1Qit&VIUw% zD=N)Iq)SCaav&(uor6t6I+PG5-O@Q427-jd=)s85=@_}e#=G@X?xkvHIS$rD3q$<3YSP^pBDUe5=qH7=CUuxviALh$a6$>(j=d!k z<=;cMLo7hxUpU7-^eP)S7@jaT2_I_v@#`4K>{-D*D#bRiU;$oKwgzfhC}`%)xI7GcJEM z4T823Kcv*emY&^P)a$M7p6ldLb1p6A;Ytlm`bmnAz3VA)WL?1Z>*vA;f3es3e4mrv zLA1nnflc2&2OOQAZV8|tj72>+D9}Q^E#2X@#(u4JpuJczeZU_5X!e~A)!$sc%2ck3 zB6u|KUi2=5R7WR!)feAAMP;Tjly&f&UX|>Q9A}G|R`|Nt;1@zb@FSgW(ycu4dSAop z#4@?ccQMNmpr_F2>B=RLwsl~n+c_}B7gjdG@#ye%_*_72&WpgAM>?z*r1)a4=|Hsc z*F>PjKY69hUVDT*pxwrxHk4%Q)TcgNdBSV*+2A?I!|Kb%Z;%^B9<9mdr%9^h0wK7q zw32^5y=L+`=d%>$+zW8Y`@~$&PJ+BY+dwD6FC(ND@71gj%|fl}kK$mIbSU^(J`NPU zZ9x5;gr(Goth5g>C{-I)c-~a=DhVU111&T^@=pMXV^qgiayP3!{mH1L4-OUI$`Ag{ zCL9Nl;pFLW>Wpr(VAQ;WpDR5icp_2vLXq@^?9VLfju3w&8u@M1q++)^5{g;8G{+EHH zX6vHnHn^uxdVq1yp@&6EfR_bH;TLr?ndBssvf*q|PMn^5*Di(>u`?7Mg!Fjk=hv>g zi4rYuR7kFT;bP!8ly$fK_=BC}g;(R)HF6!lWlht@)zd4{m%xOTFIl`#JA7rcB0X;+Dlj-a(iUb9KC^-W>cwFatV5Fqj5%K} zf@$y0OWeQCjI;?K)Rp)Bc^7SRnwKn_5_rar)gP8^c-r2cf3Egyt#IvX3J1NUjS}_d zklam%Tz;)T&W?Qf$u=irF?)l2%xxvs<6AU$xOv&O`jNVcHCo`@I?UU=v)AG|?6cJaBpSce^$D?Z1_^5xW{t{*&;9M5ydQ#u}N1A_;M zQ~KGvkx$k|s$?9p#-x_isU^SbFcayvC^*Gl6(@umg?CH@Uw=0HXrml|J~f*D-_*$0 z=$)>71>G4vQpEzZX?6JgTfEkO2FO89#@Bs0k%3;9%@Y1V9VnLC7bAJcLMT4_#a^&c zoRXVJadwB4nxHr?MD+Av=^kU~uTPW0Op`$w`EHBVRZ-R-Zk0rIKn$8F7gKIkJe2Y} zR%5)d1Av@U12<>_C1|5nmBeAW#JbaENu5u4$0EO*CvPOO+;1nB#^$#V)B-%XnRgV0 z4L@x8Gg^Kju<#St#NS;?U1Ix~r-Z8}rW9UhrP(S!TweLxwf5WTz{HUD-B=K8ZXxO8 zww&iHmG`h7KG~{be%FvlkGUV-yn`tLr*F5xS?g9eQ2^SidIMTBg#U^o4kpvur-iL) zO8NUe9&(4XsR6#q9c1*2Hn6^Jxf(IHP~vE@Fp{|!1-&M1v~`tkIp^l~G8LaF#l zQ*SedMc2P9=ASuZj?S{zbdm{SYS`||Q~p`-U!MM}@~#K&3}-fFSC=EyK54YL5-Kc$Fp>N&fpE)c`skZeEt``R%Y&+_%2dD zk8WiohX-*j<}n0EfF(%>E8X)Qx}5obZD%_5abZZPnXGs$1|*l-fiA6^V`(?^7xufet^!9a^Kyc&HSxnj<6Qs`DC54F=RYuQ?|_y z-`sk4DomfIsG;QG@W8D9x>{jp=~wXvJ18+zs6pPm7Oq{{m}`4WUc0~dEt&-IecwVK z_@`2uX%b47C2HOE|3ptO8>M*QpZFJabr?e(2J?7e!Y21NOlJ=ORMs5C92$v*h&sQ2W$UPMp%tOI3N6YIN>C<2sl zZi3xswO#Y?P!6wGaTtZYdYinx&@BP_bNO}P#e%E|t+%%Yr3$-CE-Vninw{1wzg@^+ zv+kh1gJ?9ETDLuuM} zd(sH>bjTea!Wa8qJtoQ@Xm%~9x3=vct3#b&ns6bLK87#H%@9Ff=#yjKDTQK=@D`W0 zrWCF64^7eu&lopJ){o)G_x_rFHvIb^s@C;CRISTpMA#+VGn-X``)xwEw26|f=VJ0; z0ahg{C)ns+T-=Af(@v?c>Rj%Fx{2X&0Wn(vE1lM+49V`Xe5V1~YrN4whSbm94&)fy zLE>5(>+=nbw*@WYm3M!7<(38qq`B@J$CnR!Zp<;&RwB3Y=apmKHps*^s$)(b6-^=>CKBgwN4;Q))JT zG_|L8e-rw{b74;tkW+EVR8F+xWLg~X46N#KKBI{E_coWw*Ss|)aNPr&-Nkz2_KrVY z8D`vZv4m*+-99fU^cA&Lq9`8h{$O&+qe;U3tFQI$i!ZNjWvr7Z)2Hg^W!3@z*Q6*Z z0RP(>w@3)_uq&)?$13%0Sq}+wg zl z4~C3mE}E8@Zm-2rBk=7PVG;}_3*EXb2Z@*4JDSEaH&q{@0K~1@=I`0_>cG=K#%)O> z!IJ8}m3hn}*x7J7hwB2@!-!Y!(q3OOIl5uUteadl!lpN6o&I2n=_Qr3>T7SoW&f=8 zCl}`Q*LA&Z0ZJ>SfCAp*eCrZ`0mLn+$WwzY=#uKWRk3AGH( zvP`K=Zw5vpi5_e^UqrSYK%>Zx&=m7WH#ONKLc~tnlsYMye9Vl_4>z`Tdo`Z!?Mqpb z)BELj8oD^$nQhm`IyEMKJxHt(+Oo{phnKou-D5lIb3@3-Zl+3yy%tR*)`N}867{5i z`!VVJuM>49KN+W(2QvdY9U4%`9yY9;eu0fNdq}e8`nYx5LKUvZ7Qj?DL$# z)8<5Bj4?-rw%J$4b;3BmYe?vFfa|+d*k7)c4G1= zw{T_cp(be;vi9)%#gK4gfo}$be>S`$hhH~HG;g%)_&yxBgN_mPTmIXMkGJmxpe_lo zEsY)8xmxOF`bTYG+A=ahwsK9gA8nB7kIDwB_qKaR3IhEdR>YHAj&8(W4vyC+-H*j* zQ2d4hzx{5|{}G{D%Dn8{*qEUc6Ed0s(=66cgH%SR{{@qa7?#6Z7 z2O;qo+aLR~bGIfV#ilN6DD3#XD~4RX$Bs5rI`k&CN$iHhYd9Lz^xP!>#x^RQ-G3MB z#wk+J`+LiWh9=_jSWmk-`<*MUFU%vOvfzH~>reU6kFA$p=6c=&$SPz5f)+)X`988& zH2%2Qq3o#osO#XxT{9_usYE!(x@C-9Vz4H{-Swf?WbFmDPXUi52Usu=EbZBz8w>Pg zWI7Lesq9u;J3+_kCQZPUA_j;P{F$0+V)aMV=TtTbWd~0+xON%gZ}15JX{lFklaD=9 z=8-zkT=;$4llb(;tL5@**5$<^J&Uitu)#a|>8O+1~VO ziUt1z78#Gqc{`s_;Uuon)SE_MI{$k-?*Ba=H^I)ZiCwOvE1&gI=AFlW8qd>MnYb^L zMVBAe3{@o---Y>Qf2$fFM|Y5XKMvn}tstA9p>iu&DA@f98#kxmbK4TLHJ^!xAK7>2 zhvm4B_)0Iz)>I0MWYq<|ba|y_|M00i^z@b6;NL99zA@>m88AcI*?l<={KjVEn71HrBb=dlBkIU-%jTYUIlkC?6dq^qLn5xshUhgL zv~u*+v5}5@e)|{{|O8%E9c`sv-Si9c&ot@cg^?Lj$A#2`ZpTWh^mNFmS z5#}}xpXGLj&U#ZB0s>pGqYUFA%0rxFn(0~blTx5#?;OFCo?zj>Drh`Xd1 z$x(iIwX7S>=L8-aapx%P1ocZ?U3Yya1%JiraI#b6{*T+J@WbYiFk{0Ui(GmVY3KAW zzP+Knjg0+jRA0*Ob4r7qX4n7Ro5R3C8IZ-EpOP>D540#vP@-42JDt#EoX>{$ELSdr zp%jsPRPCAR8LWg-3RpPBmJtFQ15emf>PkTw2*8uNzF~LV)7g0(IL&*WOsHqZkTSh{ zfPuN@88=cIyhSrpRw`@$mxJt|n1)rB9A4l^37wO~No0~Cq7Vcv25{QC|Kf&N; z<6IhoK56O6z8PQFrc?g2@Az#44n4r*H(bE_@;G+iLi_=&8Pc+|@8ihk-^Y!{I{Uu2 zyUjv5=rpo~+y?%6o@tw2vCugD3e*s#yHqBdH@NJ8eu*bsx%h4IS5oC`h}f1-lMF{? z7G`x@J|cpX?J4dN1ECL7Fko@~i|@zWVCN&=th>pdOWefV*B>H6Hf|h6n2DD?*TKd{ zQ+R`UgH@DMn5x3A1eRMCPjn|BhR?B2Uxq!e*3%@M>z~qAI2~1+dohoCiiEbC`>iEo zna&(EQa}*DmVY$^N6o7V+UP$Vpfc3?b-fwq{WT7}O5esseNIR(K{GETJBwD~b5Es( z*eVnKU605sWBGoThem4Z#qLMy}%sec@n)ndmtS;CS{4g~@tHp_OTkvHr zsHe3M;rsDgdmY&SvUFT z)8?$VsYkMv4yd*P520mwctaLJY9;f?JC0Pk`bTPe!vzt>Ge-@=?n4zfGs(6R_R^4X zZFC59pS!EcD&y$LwvHnZSw0!Ei8R>e0ZlECg>37xd?%QTpn5(bHUkHxv!+UWG2Sg* zCSXEz=5!o%42X{@LQvSyY*6gey@+aQjs^~e#ZK(L%gz$M3`ITv8W>`d=WNi2_55qb z#xq%m8th25Y~!z5#?rKv&=zM>2sF=OOCCN6J(QSvl!SKx?ma!Oj65YJpEF;X@swQB zgM{ml*%6lnLK5$*CY11xx}PaXmlQhd*SbObPh$(V<2QhHI-dH*(xS&_x=B%1ZGM$s z!#x%ZPUJ-8FIx+!+Fvr>(84OjGopY{%qd~_$&+)1#)X$a*ItpbM zM^Os#?U?Lj2=N9)ciG4#cs`e6o>^PBlIidsD+|#RC zn7GZnnVkTi!|+~{k}k@Y5m2bJr;K}Rm^Z_~XHKQh+&;e#p4S!v<0ZmI*jCWF_3{Y~ zCZqANvpM8?ik)OQ9^vE06+y9>)I|9lTTUV zQuIAjMEG2&{Oy0LuXs(-*9yE#HyXl{ltj^1n$8SZCctf-&J3D0O$R|=4UzIMYaT+8 zK`4uSbMgf!d943V8Ufq8dmI>jhP@>L9n*)aR2=VM>lo%ht zy|yzueP;IRry?OJ5yX z{QiqSh~XQn6el?}JLjwF&IspejPIo%XWuW#c)gk&O$-s0iuBz4=5uwrjOc0W$WvxG zZ^iv@4bsw^5N4bzs1^O|!G_kDZLn*V~TMWaT`N--BLD$2Mr-y_+$k?OQ(xhIkGS zzg;fS4A1f8$%;nVDdvKn(s2&f_h^yqa(0NHlNJTKh}Y&wBQ%hqT(0T;jg!Wge7lr<=kPZF?ipW(xjU5JO?=-V4&z7}Vj8x4uL zgF~$ES-?sqKr)Aog!Qo^!Aeh-R!jlj7;pAXd8`l8%oQ$`iP|L$s5c-^N3AEdA4+lS z+FgY6*lnQ{SMMlaVJHr9!)p5~F~haHYm70K_X^XVv{q@*PZ9ms*{y?co7k8Y2Mc#D^uWf^6mdMdGeH7<+MI87*5K~8E9FVu4H`hYTSRn zsNDT3!#Okf@k^t1Lz9Kt?ZvR#%D|s3yzU+yj57l(SLt|Nm^`OLTF!4(CKeVy85-_< z*)BtiuJd!%5_{9AUe5c)q-ieH+DVw$SJ28J zHa=56Y9ek_HAcPU-^&P! zUPvOxW8qNhlJ{@LN;aogF;@bJS;LO;CwUJqt-G-S;cc7Yh@AP=5%R1mm3V$g7))-3 zrsP02Ru~Xlrn6G|3V*YoSZe0n1b67$f2ypHVb4DO%I4f_o}w;Q1E4rzzeDjg_@|iT zv4_Wib1jk*?0u#ff6)HmPCE6hxAHSGv*vT=QGS-QK6nB<`-uUp(pFX9V@ju`>BE zb?O7HdV5cZE%!V4^}nmAn4PeaRf(fg>eqWO3S2SeK+=cM^u{+p2KJ9>oifCI##XgA zU&T`bENOYsx3?TlBE7TnHB2-_4VP^E)~;RA_J5!5K))2t+B{Y5ZOP%8tyg58?U~%@ zZ3*!Hf;l6%WnzwYxFFm&l~Os^_!e~l&$yo^ahMfp`oToB9$yB20_f`{i3MGD0C8hgg?+T&`wLyZLCsDIB)OX8GePrd7u;IC&^#irD|jUq+d%!NvNy3X(SWQo zqHG_qy_?^5!z}1^P!ER6$l~O9d^*l=K6q^vf`5!sr(!5zpm8}N(| zvKVKF1g`;6!%aS|>ylV-#@GV&C+>*LWkIxE(s^G@sKE%*FbI)7EQ|krzbgpaj6!&~ zP>$n2quNG~(O3NGW4J)IVo*SD=KdrW2K0O(uaQ=?hdw&ra?}f)nokHl&A{TQ zYu6_aJ~BC_{tMYX4x`S*hkPOuRla3nG0xO%b*+Dlm2q)%tM z9_Y5Yodg2Pptyz71`>JG0PSW#$;xzdCb8827?b=uS}!CI*{PI1aQ%6{TW<5?`AVio zf4<$@TMAuwXt#BnpC?`k@+B-Amaf9d96aQwb%j>-RL4R%lY7VRq6~f+R zL0fI7cXg&Z^PnX-oCu{1p3^CuTyMb=m2)hg~kvbo8#`<;#EiWmdLSS(RiY z2p=?1@tYrF4)T7bUY{<>^4%I24N5DExQn4|hv?h+bY$`Vr5HA`db_mXRbQOsRWDun zC$02PpmhLB&(E`Q<_%tJ*`0;#Ih-Qx&1V*f2}bvqPZxj_?Z<@-&A0pyBbm=iQT$sq z_$(Z?0Y8JZ=!cejjbg&2(O_|fhK#2PrY)NYwCa1n{kFa=>zaMK&`fw#cTd3HQn+X> z8}I_PKby2=A=+hJU1TqCC)r~4w9o&^o&IF?0G!)Vl;|J~H?eR~37mI^+SuJPo+$t- zEKS5P@3?RqmBjP+iY>ikll|bp=6f|EYsCZmW~kka4lyo;F9Qk{GdQ})TkeN2LH6cM zfsH|7$kX-9P#j9__d=V|bfS`Bx=y&`LPHm8M`A>f*+JlPFtdpKcmXyTN+x*s{|PAU zc=hwTJ54WIS1yWh+)2K#9}OH3Vm|ps&$m*;*xqy zdH`d0@Z-}!TDqN63)}dENytZLDb%&Rqr~*5vcE)*$-VyufzYfmpZmYBRLd+aB>`xz zFG)G0iI8`^^Pv1KqqYx;}3q9-ra=~0fEr4(cI)#Ex@9LMTlS^G^HYWplWN#qm}yq!R{UV?+bK$9s9-Wo|Dp zXib(nrWAvrZMp_s=)4Laa{JT%63!%si*QSC9i3{lkdIxW1yEG#M9F67~4`s<3Q8Dv>p^v(hVdKP`(Z?iC?sB+MFEoY?&$*G_LoHqx;O zcOrjX8uSUXy5C6cE+GlC0fDN&FNZ~=7aGM6qbiS(#R=B0Yr%HNS)=Y>AFr=URvuyg ziThZDf+*AK4MMGF>G*!_jD1*qIx3U884l0#pH25}@IKr*W%%}$B3n>LEH=AX#~bIw zsN`bSU^Lj>xsTY_ss6J~$MRZ*1@68UKasCBo4loP&2bX9+WdHqRG>qn46D* z9*AWB=I4vuinw0$k(>ITj|A*o!e_9tT}UyU)Z4kh$^y9Fh^M3XX1yGESjnPySK+I$ zs-J7**A2!GHS(DvbiG_`8%I!VRJz6}jZwHR#IRgzrp2vsQr<2%h@-R0im^1>`W+2W z=`%-$BwgHl+KxCNy5k8>0DRPGru1D3*tXAgm(iBR*(o9MU)89xm|l(9_uEY2AJQ{Q z?rhmL5e1wIvWU-)i;%k#R)0$DTw2yqkU;Q3HPS^NMrl9r$fV3-*P$(E88HTW2=$iz z(D_}Xp4m2@*@eUC1}BpFfuC@(Bf`y{d{F(&|3LQa>%PRfi))_+sYl?ZML=`!lhq`b zmH_-4XkDd-yQxFJC6xXb$aA}Prm=pvImNXWxAn++f*;^SM^6r01M9q5-e&#rz%Udv z*FCD=?nFO7xKa6uxi`H$EwACEjGAp7=K}S$cVL6$yl76xPYczJ^F%|h?39|ww@|YH z{E)1ob4I#1OXQ*7TQ0_$tIC1%90K0D$p!Bn2WM6c9re@3C``4fdS^j+D0Fw~#KS5} z$lzri~V1&9}22PLIXEMG1XEUpqbw@tf4Htj=neR>W3$$Le6Q-RpXR;2c z_-$HGL3wybXNksi{`?~_)Z7~?by>lBs&58XXw>c3=guSDm13Ro{-UtjyKY#|UH2M_ zO=%%2jaV$KbgR%CYoG(+If%LUMlR`|Ci%;B*)h#{0U1akGI88?g4L!#gF8|HF8zM&IV1uA8%Pr_qu)2rn$F)K8h_gFF# zFF#iI^EOJ=^wN;MCgYy$a&;OLE#q8=vC)t^Xb5kCuv)FFF$c=o7)Pt*Pizaq-?Ii# zYAqHVmXn{|FTM92&JqBeR-WETaU#zqHuwH|l@`M@^^d%vB-hGCkM+sGj|eGdE3T~? zUCZ77kMb#OA);gvlx6$$PqRdk-ew zL*c~OnAY0`eM>#-neGy;LAwpLaNw;DTO8m;r_5Vg7EqtqrK!!doI6MCe}oUoLvk(} zum(;;EhR_CN|~lH(?-=2jzcN1WedRoiclo1U`BZk)lYKh7*9#pXUTh`JV*T4uNaSL z|95>rkJvX8$doMOby0N;U@p>b_ycS>%omgfDT{9zO@W)veWQw2!K*-bzwAv}bx4SH z^>X5jcC&V+3%@r4H3#+qPRDm^DZ|mPf zjo;jOY5N?Pq~At9+hj2qoivlLsy)YKu9f{iJCb}l*}6dCJ;~LjP8Z@`n4R9UA3AA@ za&niGG1mY>dsZhyj8`B;-QY9!=wWWNXIhVRIk^lC<<|I`K=-Sz@Oh=*E|j~m$>;le z$aO0`1STgb0q{S2tsOtezY2D$(JjOjVa-j(95+Uga$6 z3uuf-AB=sfp*w8NdPYc@3(Hdm1YIJYPmu=P_Ifqbz7;F^`?>Axm45uL}YJQ z^%onHKi15B{qU(@3~8t{>7Z&G9D5Wh(`%6*upQ;i*rbKn<+ktKkJ4LMySw!vFp%fvg+QzjmeoOCi8e zNABJ_K){s2EK~`Xc88)EGA1qTwBCXUm>S8k19@bUY~xeEsV_SjYyOhSES_C#_*CeI zkG2@2EO%9WbTpT>D?Mwj&Vaej3pE4}KqTNDf`k-;OcM-NTNm=vcITTq@zOS9rwFs# zq}xFw)x;E75EkaVbh9_(q9*i~ZXZkQ=FK-St%;vjfSbtakg7A^y=t`E5Dm4r+ zTS8R+v+_}n-81uaa71<~q>?oUGO?$##3cr3l&womQ_*$%e%ko@Sgu%ffZ05pQ-J@k z(P=9iU$cv~kXAWM*Y~ShI~{VQBRuTUQP=v2g>fdSg#7TOd!bBhF( z$~VncbdsuG_xal9Gg0CR`f+M+w^GdG4ac;cTKcZj4r}y7glmB9^b^RzYUN8OBV=YD zbXqLVNk}3A=|u3GE1m8A_Se_*Bh)54{_rdAv=o0R5g<+ZQ*e3a6ErH4>E z67ByEyw^USFc|Hh4^aou1u5uu7RZd*iWh91xbeDJ{n%k8)fs$1enzqWU2^g*>odmv zNqd``1j{jOCnU};9>PQkpeR^SgT1@hEvAPRaJ2{L-rCVnG$HtW5U)r2E>xF?Bi7+3 zP#NKv@6#39>{gS8fk36p!vw!oV*Aw3Mv*b{N%uU__oVu1Znsr zurgej{c{Eprc(WD6#ZxO_-5Niqr^73k*!s~8PKSnVjczk)bKNH!yzPYwwy)n?EZ*w zgU!2pUzffjnHPv*_>(O_Q!{crb4HxfCxy1tCs*J%am^0$OCs_1;XIa^r>7}Gqyb3j zT)I)R@NzN9GW4E@&tQatz*)1*=6x(F^Jvne4lZRe;p|Qr-`5E=0ZF$agZ?#OlCfO? znIc7MFSKTUH4U1hh`j=s04k+7M*iUXM!B4;c7LT7r`=v~vGE80rBJUVU*pyemr6{T zY1ImOhv9aR6bk8*^F+2{gL~)SJ)~wqRVp0T;oWq7>@F=|x@B@biPHa#{PoMuGQe-i zwSTk7hkw~?TfHbj%^Po5|6kM)&ZFjhJ#)jNT#I1GaB`kOlo$G5u}pdQBQGH%(q-kM zlY;4PM4x$uyIuVr5~Jkp`J4%Nr(3{hJqEe){nE?%!VBxdDi?+6VQT|s!ev<|$z!&} z<4;`$&G)INDYqJU>L2(TY zEtnhBxLpp#I2YX6hymJ(?6MUlX^IA4JP#OvVqx1_3evoaJVsbxrB2;U;{EPljKJ8I zxe(go?TQpmlh&XbzQd*H$c8|}mdUo=Nxk-g*x98Mz+I&i9Ce1WeyI{fnZJGpxXSRQ z3tDM4u$~>_wN%N~&w^SIN7?n|v2AcLfd%A``LgWRGi{a#%C=F8?=vgG$?(CX0_D8`FI<9^X zok#w+_BYnnOh4IAk_?DI2!(;ec%z*}hyBNfY2@~~!E{d@X-sYc!@IiwzZbySoDr>i z<#CL2#0RIHy#;Cc4zB<*9+reE57E3M;EeT-CsOczMS;``sqCvDO8`R z*LW?n7zt;C>~&#Xper%>DcChCfCa;%0qi^TT7~82b749fjj*vz=GbYY8(&R!91G=R zZNQvH)Vfr%f!HMK)}KYu+tRi}sp?x9$f=W7Pz_t6!ZOIqYrxSNB0hRU1JqYl?{S`HkL% z8A|?}VM-oH{p`x5UZW|g+C`y$o-!rv($Ks{wUcfhKFE5j$0ilev;fI8_#1&=wHfl; zLFw15--c=3zYxQ~J)gN>*xSH?A7LiQLuTRQiSw-b_5@8bWTDn9IJ7|{CYG{P=N=#uSlR;>*4@Z)gALm zPYX$b3mijpoEBQ{?@^g00@#ed1q=QR)SQ zk>GeG+n19Ze$|Wl-FJkv#o)LhI;A1r`uGd$el?`Z3FU9EE4afR!tHPpj5M=KC>4j_A;$-ziEYXd=CmzwC-C zQBk@n@jQQ20oNIQoX!a0zq(9LygLau66xJgCx2VuhsXf47Q-)~iGUq%bZwjqN`R(G z66(y}`@Ze=hp66(#76t}*0JNcPW6-W_QMH$E`y7JbFBj5%^3#!`;bRgS;4>SDa{QP zJwWmtis}(Ubx<%qL66Z94TDnx#F{8&w92s}N8hG`J3=Z@yNzeydDeF95Y|{HzGaggD*y84e-Ql3BbPDo#QEVL|A43G zPydg#3_({@i$j(;_j*1TdQl8(AK%G8YzDB&vG^`7=CL~QI4cYuh0wnz@(r8OJ4A$p zyJg&`1Jn%2zc=t5y!XTpc=4JC`B9OQZP&F#Z}vU=R?J{*;CpJBa=63}vq|!a zyu9Y$vJV1%9;uI>msyxbSO;WhH|lGL zn?A{3JhzuF2(>Saspp_RT8d8}L+|MIE}!7%2}i)<9SZCX`2&V#M2W=_cHb4VGtgc2?aWYrZ8rP~YRa9hkuZUQYO|g6 z#&7d=V;W9dfWB^|u-gdjI1e2}?@8s;TPxdOJi(x6Mu}o zV;jUb_GXp?`J#O+kMZzJh*;X{;1@&|3()L81tVJS3ubG=Xj?p?Rm)s{4>3-oM9iX| zZOkScSJa0BOH*e+7!os(IfjnVf2wHC~h9`yhQ)095_@!dT05sRe`IX(t{neRg*0=~V5P6Ui9zG$AKQa|z%V1NUj-1=e$Z1+Zve(2lY!kV8sf=-Zo_CCEE-8vM*GrU$Y)^o@ZAo=ztIk&uRP%z1WI~#+f zx4kC&hUQQ_p{m0ihVT2O7R3v}4`fX`Q>Uec9)CK^?gpgBHSJqr^%wTyyAW22WVnPA zFaSIUz42F(=V=>gJ9*I3mV7jc*6jOt@ha}VOwpcsyZp!!6Rxc$aNU49DNej`uD{cZ zGjIpE${)EZ7=YcghB{78+E+L1kEY)PQKE=x8d%Yz8(y~f8w^wZf71g$4Z&2J{}wBD zY#ey3pJO=AFD1=?fm#zORgEJ_3b40nZQ~haf+-zlIa4Y;k}Geg2&nk|heSSfVZbtV z>0sHNV(T)hblR_9ufi((vNFW2l1*Xnc^j+D1z_Fo%s3tcrFz3l&2{~ySIY;^Sy0e_ zi$n)h_`E}P#sm$|J=tHq@}^?X`#zC2>Y3J`fgrJL{(hV z+{SVNry8$#c>7c%=W8OY>q1YkU6B3_k2ViU+$zVwQP1F-u0{Pq%w>I^*2R>{8>0VI z$={9-jQp~qZ*_l#xv;JcA2($l+O%+;y93$5o=Hbt<#YXRPD>B*SJAq+b=&1HvF%~{ zYAp8pYr2@SWO6sNEy0Us;zL5NSN&dul`1fNtm>7;A1qt@(Lkj37LG-r@!$;K#}xnq z%X&QK@w5levf~z3o>mY^BEJ=ML`i|j~lx9eo zwbUch7BTwcl*Aewx+RtdfzHo7emlc8xchV^iCuX2HwY0(STM4k_XkNMC}tkQC~hvb zC_UPIIftR$Qt%QfiR?tDP6HH)xi-AC;QbZ@!qi=-nXb^icQuylUXZ|A5lu$Zp8q=` znlg!pzxYi_O#UM!e?$4zl8(MB$5kWBgO`-;@!abt=bo+;OUE_Z=lUl1H*@#AcQ8^j zo!9f{YSi`0#4d(lHdeIvRHzw`x!lhu4wtgx3gZYtU5OgL`5wbLzcZvJMH9c=(7doZfu%XX3U%}mx+<%QRF3f^mhD_bI-`J5Tgv)gS3olxcL zp3%oqq>^XP#ubbzhQvxz&GJRRW@>>y)P07bGQF1ds~zNI9J5UFVlcHc$p??{obf{1 z75JC07C(G^)kE6{p8swAhY#|QW4}EIwxe!xv-Z%(J+6J=wWrcO#@pW2KJZz;2_>)g z%IIu!SqRQ7uYp>0;t7s{Re$L`&$*NPDREKVSa0s%5OOxr5g*5K9>lbc(f0BOT$p?crU$gGX zPTvwIuepJt1wnip^h8-}D>fO|lnpg^x< z?Z9s7!1@EoZn;yd&VAbfo(py4^l$Way5x}IS)s#9GqZU(2&g$nRt_m0WW~vB9hRul z`B>3#)gGp;zlWCw;FZGpCT9Teh1tEMKw$bn8?1ib`2Q$4gP3bSLUapH4&}4nj zwKM@1VALL9fk(ZIe$2g>%4CiY{RKa%BJQjIqRpZw*LRvdlO*IvZ~(mRAyyT6bQxSWA?$5LBJ6aWblbYsL;+s zJ5RLHPAwXSQ`olpR2-g$qK4QJEsX~K9B~G<+mVOB13_dSl&R1HnWw6(tjerjzyDhQ zefIa|&8!5f@_sk(+V`Hb*Ix7fpJDHP&-uPoR*)~n&w8(*3v_+2u)`%njkl~3iwj=)vt9~KJ z1w1@RrtmWciFrnFUoa}Gt$a_Mc#ph!_n`mjqnEp+YWOcAgh>JS$gu6HQ;8OBxP8WHk9wZ08@gWiETv=JPM}39g+{hpqD; zwB@qLYO72MWc*BE&>^=^pD*b$7ZG-^@QPnYuky$JwmlgT#r{S{*ho?e0-$J=1SB`1x;EH_C1%sib94ZJE z#_3?KC00aH?lbX3<0Fdl0sydzw(yfAX=znFdrSLL3Ylya-}#4C{HCw$dumH5av0xAcK7=%pG$x$Fa4SSXLKx3v_<2snTB#Q~@zS?kDWCXXOH>dvW_LG=q-=CMx?!jAw^aHE(ZQcU|P zzWRbd@w0CkU*kL``l}pg+&T*nG`Iy=@w+qvyNW`5KeWGQAy_i$6^(@nTD`UOwmjns7>1iHP|Tsh&A$umaMW+K1By# zvIr(N$(nWoI7SQKRVPQ5l3kJ~04mB`@-%@IPqMIAj`)GjsM2x##C6R-k9(+~AfM8d z&6&GWLNMoFv@ub1%cJ)Hfmp3q%w|`%Cy}JrFqu_)NSY{QA1z4N3B+>AhuukEz56FG zM@D(^@}&>`!sW{!|GzF@{OJ!^KI(3_i4SfcU9NfWdzLF-`!CBg{@Wiczx?N~m*&_# z^4`mx+z7uJokLamhb(icI{KQ|Pb8%NXKK>%uK25D^&kgY41>90&yZL+A(MFm;kQ2LcQx=lvn{d&jq6F_3Vx-)pRp zEQdx9;vUe(;7unOKteYMP>m+)ng=vBYUjaaBj}uf>A4Qi#8-;tphC*4RcV-B>pB0( zP<@i7Y_*&7S7&epCN(${xVp7zuZ%*JG16fr@s>{`(&fwUQO&EI_)b>up52%nLz07CInp=>J=7(L9)zkU9MR6~(XlV{LQ=V?|D}tIfycYl&-iI}>D?c^Jo5!lSib!c$j-k!=!?H$dETr3w{`Im zrUT=0li{?NjQG_`{K#L)Ab_Tk8d-DxWIOwY<2;_C5UE?}&E_1ouQ zPG#&TUfB~TixMre=*mrgoInI7w)VlRh#AlP$s7{X$y~PPImhh3y;c5-6dn{XufJ+! zRelL8Xd!~<^UU5dhV4-bwMu}R91}kY5KsMqm*LbGgtARub}a4TAW|8}8qDFaOAl%n zPjs+RU->YqEoZ%J1P%rQ{R-B>I8L4AE+CNidENLKtTYHrdF7y}VWkG78ePJU_jWw! zZ4ROcvkZAOS1yfcG1?4;pxur-$EK7k6uHHZ_@c-OpCK(*levOt8*571r&V%1NT+>x zQ@G&zRizA&$}=raW~Jb2Gw_1nJi*B};vu8qK8wu!a8Lh7PBbM)kUl*@namXr4YV^w z{JGDNMQ`N~cf&vS&R>#Hh}y?rx!G6w&u03^mvyG-sfl79jI7Z`qF4G#8@brHQx9LkbL{LIJaXd2sp=8`!} zGPxw9ynZUaJZ;*iB}P?bA3L)MFfgthDkvFVcK456e){+SX!)*JylnY{Klty~>D+9nI+IUx&OhUt zd{olh=YP7)KBv`+Zx~}QA%SUTKB6l(Xxk*sK8y6-a6KJg9rNN>^tF3LbN-p2G~IpW zwstFIk?C~)6B`G_SkItn<4eKhdv4Hjg^x_*XoupccjQZ1uho*nI^06|CJqMxEi!ga9|} z^L_5TA{80*Y*cjSlKG?P z_*1BKFIgQDyTU;Ip6tV~utYY>>@AoXGzrnTsbe~+mPlTFoH0%;Q7pSDrYAKL)^2h+ z*n{T-LrobN4GoyFl^h+F6SWP|tR`_Jfd3Qkd;fCcdN`Qe5dTsB_;Tx8 z-y+Ws#muBMISrc|ahs0P*%Uvl)R_{LU!}jDm_3{&kl10E=lpvAz*lBR*tjO*$2Ca{ zKM2!xtdtf`&sESxky7-=@h@MvDJ{aR^qJ;s{^|>kDQUI#B`G9xUlL1nB}lVu-RNF< z7ydGz04R^jJ2P2bubE`O2L5~GpAOFLVFN$)JF?kMpn3zlU%@Icx;hXD^b?Q+ahN*E zeMg|iiH(6N{(8lL!!8Gk9MBmcJdkTb5-PKu$FdraYoy8^CNG1r_kfQ57*L0Uv|*nX z5bNXzE~=E(9G)lRB}9&H{A|WguV~HrtJ6wOyR=gV83%9bl*EpayxET>p_~>O$krJX zVU)}-{g3W%I0*mhS85Yqm?>H8oKxxrBUIo~Qdd|7-&l}H9pTC)^x|hsa%3q7>2Ba^ zUi!~`vCDp@bfvS~1j9c{NoOOZsgUxJIeuw}!IVE4mO1w7)9iAxS1dVS73iPhMoiJf zp8VrmCe-Nwg~X?V`543B`~1&*NwnN&&iKJ;{0cMK;|2f4!v>t9hL_1mLv$Wz+U08_ zz=V@*Q_s3O*1;zSA9v?}i(AEiey_M|{7ol>+Kiw6lfUMlowKbH#4@&^vr}nEUq#7- z$nHu<8OJ|X9&WK zQZdD=&WJ9Iuv?EiaicAT^k6Z}nKr~3Kcped^DkYv2Z^g&BdaDFft^O6KLfJUho_U< zDFhfp;)g;#4-U>#a*qRJfJs7wP+7}I=`rBA*n75Puo;4&q-ajmN+9{kW$z35M zgJ5%fwb@N&G7oO%FR}DWnL*t)LAZZ&Jb3dUPg{EM-T&~Rer?qj8x6;DJ=;5ttSes| zI#1<@MtbmZ*|b$}H&~fR8asbH*d99jRJFpV29DehI4Xl!`wf3!ZUcC+(NCLD8>_kh zl3U6B4qeK~U#-Zr0&UvcIP2_>adiCBsS3aDH?BaJhaEW?VUn_69B`mkT1=jjX4(@<^faqh(BOH_}OmXe2cYB7qS` zepAi;B|+qQ{a~ILC?0%w4~ZOA|Ej<4-<)UqNDt;`ZgN17D$%xobwAqrUG;qar@_p( zkE}N}cj+0Qw8`IvD*Qyqy~VrmGs^|;b5_p4)TIsa-~Z$3{$)TI$PFbMP$kOOn5 zI?;VaAjb)f7dartpb<|%a!^H>g+Yoze6EqKJjS6M5v!6Rg9+^%Osat&qzF)8t2TW8 zfT|FFJSjkKe>ZK|*Nz)#K{G zR-;Z((m!glk6pwLuc{Hw{L%_pEe_;tiiS^00J!25@@UL)H5m&=Mj{42vb`#X8?h@E zZslq{53oUH_=Z8ORFr|`BOxa?a#^{f%KNOx%BlhLO6h%;-Q zk^j^Wx}f~XGd9O}G??!5=u-(3V;Wel1t0D+wMwXM<45wgwg+*{jCwK`Rrn{}J%O$?e`ZeblYNPXEct52PDg=Y zQ{fo%gG_y>8g1b>0+-VbP}0$GY2B(*+caN(dbun zg#$bt%AwDnb8AvpLTA;UV_xqUc16do`RtS z(lj;0i-Anl@R}0y-NpsE=W&+9JO{!a3-=3&eV0pd#3M(TiWwZ3BfbQ|fR|M&Tcswm zp@zwDAs@uI4Z_ulvQs;Fo zbPZogptWHyt;`>p)Tl*d{-~%V&-TVZeIFXBT9@57`}#OU4-DXzJ*NT3V@BL8l@zo0Mf&jlj+$&6HN*^rb;<)}PX zvoy!v5wS&{JyHH8gOdXr3SmNchzjpPPcr1ARAcanK_lZb*jpqvu@yfwN+!+VWj^GW z&gCWD6a(ALA3_reDJSkZv2Zj@f*$rkAeuK=6|CHp*jQj*c9@3Jyea=-pZRP>CkYkO z7zGO_SO&#DST4RMV!el_NT622*vkq47nZ z@){}6!FK*3+DJ_{YX>SKZh|R)3L;v%@Iscc(y!Wzn(-8W^&~f#c}v&9kZbpqHe2SO zp1hZ4IY5Qn;6+hBMP?;gUOyG1l#PMU|B*-aXLXsFrn>|O8KEfRR72rmK!`_fD5f3y zS>&N;@H4xJsNkh)wO(~oO%Tk$V1T{Qwbk3heIweyFl6WkR9auC(sUpM?UFOM7y z79mHaMh>;57}g$FYEYpWs$<+#1Kk`2v!+d{0a5EZK(@wF;J5(7~24S#p5PxGBSM^k+(9GrsK|HwS9`WcX}P z=3$Vr9Cvtd-dK*jLb{c|<0lfUqWh%tVC`7qu{s%86W7)Xq4=4%b89&Qg(zOeuehmf)2baG7nKyfOqa@cu(80o0;IX~&-lrs!-;9A(vNU3 z&Vy*6WqMr=|C6{)Dm{Vs4pdZWZ6rb;eYD^3J^0ery4dsg{3Zqnz9uBRQelntTL&GvDm%VZfnn>%{2&)yG?RxSMB6Srl)T-#X zgRt)++b+nfFE>jnJ@!C zE<9+c#z7PhiaElBmK>KRK2s@2CH&HMJ=tUCfeV@<9v=9WYh@}v+3@4c$kz^(JCVxI zz@XYGawB7*JWrgQfOEq4z$9W}&6blQ)9K5e)sL_P1Lv>4OCddE%%npr9SrZm7pwTu zluv4O5D$^DC|P(CKBYhwnLpexL@xVuAiv_uZD|Cf@|Os+P?R+W=>Vqa>?xWhi#olt zpW}oNoW!Q|q@MVTE#HV~*+ZVE86N}e>zEZ?s*>q^2o;rdk+cG1icyrphxRxY$YK+3 z=n!A7bB{`yi*I}QW0QtLRPSZ0ej%FrCnJ>LTNbtK*pTAk6c-f+I6@#*{9vTjyhmRA&`lTR z2t$)NqwONy5}Ie_XiI%cV8oAvWTkpIpDZgR;bId+q9e<}2p^bgmwHY#J;t6~*<8XF za{@_+I_#w~_!g#-aiN~`M@la|@FS~K#FPJYk+FhS?#dtI(r~T#=3zKb)RXTVB(-YP zbN<++wJNeE%V@}2Ij9}1jr`H8Tr5uy(>?;J53sCDEl^W0qo z_=Og`_Nru6d4*-!TT^xAF?&e9oNcm+Q@JK4Xy#(0w1;cU(KjxNPrH<C9O1!;oxAfI5mCBxxS!8b2;-g&x^w zTw)Ff6Fs>N<5eR(kS7jfM=kr{DM|?}M{Pv_5_>eIp<3Z(tlf~9ur@We{3QD6V~wBo zq1L4lI1mW*0^~p(rcQEK5YWICw|@o!7X}3e0mhZ2YoLg>2RCG6ob$*M4&((PB^{)q zc{W0&Xb)YoArpLKUM@tJOPiycboLLeL9!+;FesaWlP4DyEI4V0D0%dM zm=&G*6@rm`#!m~ZBrgxjIT+&0QS4v}pRh!r9YQtaA-zW%T|_Q4tqLzxbj(Wb{9Pwn zDO68n&#@*Jg&e@CTE&J3S?rZoKEcJ_KB%3PcqI?3HGX=--1*Ci> zQRgoy@T2%4pZqhjJ@rM$QLM~@Sn!O6X!#6tgB?=Sb99BA!<1cB8~8_~G|4q%E3YXz;TBq% zF!9$e(3kX3_nJ~8?~(roUHKCZzWag`hbNDsapy8vN&tf@(UzYn{}sP*6@0lbIeEE= ziXHYgM=%wf*J%gT6oCF!NFN;P*EdCilOB}N~4XrH3*lH;)rJObV=P| z9_&Gfh&(YtYlD`D$Ul^wKQ%qd->gx?PKAmMXD)*tgnXuW%AYv+Q8Jl77GpwG{uJN7 zsYAb_Cmjv-PdR1&v--BbG)@mPDQBWFth7hmXq%=MX4Pra=99-fk;13rms>ipnZJ`w z<5x0yjGOI2haVmD zaDq#G(H4#KC^KHTR_Ng%7@?1yN;)W|VoG-?gj!@IC##7d3!eN`5O72d-Ly`l>`&5; zY0Od7u|QlQ=ls#1W7}SJ>||SZqRF80&xnyzw3E(SU9Mb{riW`D%3nUY)^LY(^+BR* z{wT7APF0EzO(|Z+H_O5h3&7$BO_Yphoy=bv$|GIc4y_7-vso?ZjOzR)6fg8jH~Wzu zMk*C&@<7L~o6OUFh^U_`1s=lqqjaLLRv z#+JE6cqw;^FRw}<&l6*#I{2v{9d?pYXKri$LsqzC4m8Th0pXC8`xEr!R(@@@fraeS zYd8@6xG{byNu0wu+L>dS*q35ySBc6=DMdwEKDPAH*_tJBT8K=`wfL2PF|ejT*%vWkWd8UrTCOMB7>sn> zc@!PA=necPEETOB2)_zqbLFO(_>?g58?nG9`OZJpf-hWBD9j}&XGN7k$YKXkiwr&@)6{YrtfD=5 zV-L-b=&Ul=Ie%P&U&u#4I7U&*WYo!(C^JkW3^RebR^;*!RZ?ruNPOEIr#^n@CqBbi zfpw0CH*%3Y2=XR?yi-^H6;yG`Sk=0dayBp1lmQU2%NYj{;-XgqK2Ey zEdv7<}o-e^_M$VQI;e%w-c?r-G_!YBa?Q9ccH7dLw`7uK9zR<<4IY%AezA zjpNPy;Ts1MFs=CN54pGmb*8yoqN@DEzv@tQKKP>85BPxBOr&KU64^boF*XIbb z#6djbB6ECf9lxS<)d=i50=)p)^&`~z?F0hc>}y2G!GWx5fPmECpphilReM0dlA^j~ z$=TW?^MHb=MkD(x55vfQS3Q}J_^DWfZbV;0dzix`G5L*MDL9^ZIB}q;6Niz)29b6d z&o)GYFIoA|=((RAAhv#`r4HG)%)=xy8|F?3^9{1{$3<-r)`x~qf# zKjVQ6y)mJaayo#o=u_-+oi3xHb_I64)QP?LVO)OFXnPNC$&-E2_)vV>;;j=>7^Nn| zjJsZcLSNxSi(dx_ZJ$Fj+}h3YQOvd+Y{tu|WgU7!IbXXZ4q?415evft8;b18gY$%^ zB4a3PCp%>mU8L=4f&uO1rM>UVQpY!?`Z?#HXK&_?N@~VFl$0BcG8aR>LNa_}Mbk>; zk-QWnEnm{hw(^Bk9B}myN+qBQ8cA~MIH}dUM&Mu|&bX_GN?$$jHorxU_{v%iD<`$48O>WrY;MZgT{RDa|~Kd(37joG40Ye_nE)> z#HLRgn3ab@DgQM{@}>-ek;PrffxY}h0vdQLfA@)+5Q-;r5>1|RhKG&ww@&f0*IW5Z z$BD~a9AliZ@rz6?q<-OFe8r3eEJK@Z z1Ha;7f<7{6^x!D}5eIJKpK^5Q2?oW%K*epT$hkP|P>EW0(p_oAM@Y#IDF5UWrs7vT zG`-2B!plSCqEP52A!YSn3RnaYa_5p3$mY3RkTWub+2^&gewz)Sqs{8KY^eQdDk(g+*`1bP8-5ROvkxDyC4pyj|DxBVC` z7)0Pv7(6s6nHCrMT10E)sezYezsVmESuNFG(%=R{!) zWWzi5QpTX{k{tW;m2D+FL=f29MdFlVdzCy`SSo*sQz~ze;UH-mo)84hubd};ulyAp zF(uUoskVJYfQ%1ADy2vM$x!|zGD^zK&-l(Mm1MaBkR3%d^PoAtZ0eNNvYpYh-wwZR z4nWEuK^i1x)ydhDGLz1lKe3fR=60?;rG4hkI*NxgpZ_>0_3(+WY|i>NAewqJ< zdF8@H5T9uK_-9+*mCKs{@Q|I(_(4mp+&C+0(*r+rR5Jf0C%POd_Yh`Qw9p)7mzDi(71?tt{8UB&$+Ph-61 zl=%}|`Da41R5qn3diV>XVo1y`6qJ9^Ws=&Pjq;FPQDf52_*TJT>W%y(sPlIM$lNdI zZ~e620>kdRZUlA|fnI>@=z;09b`t@{Jq7`OauCX~&|}X$u!L%q92Am{W(}O;rn3zP z_9@dCRnSY@9FCyVV-Dn!59hdA8*;xLUp_1U^6ZM3v%UBk%t?%F&^6OGL^hq`X(AWN zNFD-Q=0KWs<|zx=XGkUqQj|dSj%tq@?A%dBO9>P$ku+qnk$>oBoXJ6u z_;mgQ}B7EPbTS1aXZGsi*d{8JO9 z$Un`Me`tu8HQ`HBRqV1`rGtGGcsQ9=C4jZb%=jtH?h!w1$v+sl!h)JI>_x|};>asI zoTPcu!$Zg@&OaN9m8`Ji7as&u{GE9bBs=WY0sjXQu+mqy@#AkYht z19G4`&HY7yfj|TPbi-c<2S$}FD=){H7#<{Gz(``M8QiKQ6}mOJB)bOxXxJVTjbTxX zE*Hu#&1=xgfgWw;9Ue5eDkh59r*ZNli0lz;B;{08+a_x(mM=!q@TpwT4mvm)zv5y6 zPw}Z;kf*uqV9Nw%_#Hl#oIIdm>(Z4~(x{}%)i3_bhT62Olq(aG_<=^ZY7hFJ9BfBd zJChA-;$~jj4{8E?1?`bsT%6ysjl2+J-N%{>-^IvvG_H9I0%XK6)FRj zy&8(WCg46hDKH_aR9p3+(hV6T4F!))W~wuP80u5-vZR&#mxt9;<}XhUNo{&2gO_&6 z)VVD(m32%bBWlGeAIdKh6+iSTl1Huls}3e2go8w`hU|;RO1el_dNM~bwk$(6Sj5E& zG5JHAN8iK=9ezfER2Up2*ZB|rP(G6wx*-x>=d5CJyh+f<9UW~IC;~`aywt@HCgGv- zqQ+8H)Xu-y2$P4Q3J!u`s{oRu1C&SE&OcFe{Pp}nPuH_tmV-=8zLZt5Ggf+%9U7H~ zf-BERM){x}MDW}%bkeosr@7S16)q{*;0BjThfTDFUq~{3)dCbK5_s|KiCsrzgbr<8v|L{le@}Rn?6&rPI}Y63_?$FrJotB12guS2iiG~X1~jQ z3d6%>p7|4-1XPMLew*A?CA*#Q7XU;v(#8b?^VTR4BNHr~QOdZ^W9_G{_Rb4Gwpo+Q z<1+J&L4}nn@@%K3vJW!(i7$%EU;Nmq-yDaO`#6n0Vob>nB&~f3_DH}c87Euzn+~io zxq}S0+_`g6ixfZe!*b+S=IKox36AUFrgGL38@_$G-?)NDdks(g+}8ZFo%-yl%~tIiB_IhUXLyo8bcDMNCvAIDeQj)z(h?m&f{LMJB@n0cmU zMx*d0j%12WMyWaHnH)>jJ}Un_0o1p&M!Wizj@2GkBZ1;n9z#CZ#F-p51eup6DjNe)@}&u%!D1iNBp>lMMvFvl8|3LG{cFko?K+!9v2113N@{hPPCiK+>+tI1& zoUlki;6P!J&cvAQpY$$J77jfM-EFl z&lQE@*o%;ZB3Hc5mOt(=B$qh-q~`N4PDsgMCKU?O$+&a=rLbj>?<#iXB;Ai_Cm9Op zL~(rbsgyz%!cgSLu3W=cF2N8Fqb9 zrk7Nl4!99yg0PnUr#oVyUcgGycdmBZOArq(n0hbuA?6*ZtbcKa_5WgtO1m z9Qx#&{Y!teCm@pC;2{qG@#DJEpKx>hj3xZ5&jTmgRqQK+t+1p@=qd3~jyzWT)jD%t z{efHJ>f@ibSlH(!fycE7zwKO?*~msYhLb7p%s&*BKxrb!Hh8ludc!7O>DXSbQ&2WcSa6aaRzG5ztz6J5 zS*%7$WYTC&Ji6`XB~AVI-mcQfg+@r@)fq# z{g7cB`#tO(Sq|nMIkI5~U-l4DD*qLOGrf=_n~uF~H}fAB20uMlFk%SNY%BTT&H3Ab z>$0~y^_@f&JB1rE+aX6ORm%$%@#o{bnLj2J*+!l5#Hw9^M9YC)m-3W?;t%Ugr{bqM zy2BiLC_`+vQk3|wGUuNYap}lxvJKKLWnW!zA6=*a&@JWd8abvq{-uoS>Kj~>;aZ_e zA*dH^)iEkHOHv$I)fnI5T??JixU%j>nh;zhva4 zNr^(h#U>{y@`nR>Sm1z)>|kq)9W|*@Q(TK&8w{4^PBCaGK1|6{7oOUaDc3%B}8AbUg zITFbJOUN#zO3wKY1LZJUvnrO+R&GU){HsIN1NlJaT+#+WFih_wCz{)7q)G;aHjsr) zo;QIb7$G076FYdg#7uQ)x$U@;>7dr}2pwdSOFu1fPrvMGCCfPqF2TaDOWMIpCT-}< zJL{n<+mxd{`WCcos8LQ=S&={f#K!@0>exz#NbP}yI4~!bx{k_pHBaBPF<1Ty0`ADf zOo!O=qxhMBG*#T^Y|VRRZl$%Z1msIG!ciToN=1EIt@AuUrtqkXhLgM%j`W~DNh@`w z==_!V+&3InJ6+P*vL2QqR*Z=2SZl4WDW^JaSgCJvX~-&nxm2IjSKJJrt6e4{Aqur| zOrdE~Xa0(hvtYSPQc0F8g zG(lmch?0Xr(lsWGfh@VHBiafYSv(3=%^+p@Fx_D@+i&;LSrE?oJG5${>9At}06+jqL_t)1 zDp!2h7D0r&6of#k&cVw`nuBrqrw*C(7mng&AIfZ0Bmc5jj_DwE<_-+2Akd*iVD&%h z(ZAwJB@%FCG1qCZ4%kKuvPPJlj6j#Fe~!N-=zhffT;0Cf2}TJUCI% z9|xe?uqK_v71jI+@hJGrV_g2D&Ckd`d^;uhlyUfirVq+L>XAQc%1J`BrY%TXuqaXq zk5O;(#8NQ$sIUD`yEHHSLrL*N(|xjU``xg|xJx5&fDq^f$N@T7o$7@}V7|F;52zj= zv(Dj*0YwF-M~Dr@(m)n`4XCQqY#t1U`G(81FLT+a`}CFh&NO3P{%G(F^Nd0Ka2%Wa zr7-DU0_T#7NSQQQ0sHVvaOWSj!4Ead-~gQTle$t1vO>ya z%_XB`j5_;5G23h3(HiF*4l9+6PaY&jA%0Y5sZOEo$t~lLEEUgvM@D?*%`V-QO@*rX zNTtCp?3`8^Pr^`8fV5aOvrUYQpB^%HI#-rup4y3pX>8GP*YPdU&C*8#_wq+nieV*;&!>h(ZVG{qTS;d_)q5bkM=0xE-YI z#sLUXI<}iU{=swp;)kMnXp()NzqIf}kSrO!Xm`fKt{Z_JM4%TSJ9tn!rTs&IoBQ@g zHt;B8KvIhVfl{*KG5XAdfkqqIGwS33lS2un8d74Ap|H1Yc}Nq~=2D8_>r%uLzKmgHKvp*clii^(xQ${rueoq%L%t~M;}5gE>&U+F3|8@ zS0g#vqm=PcN|tRLNbHhn@D2gln#Nw)m*RYEO_NBun4>F%;={F$5}=pxvP#;G4FocO zR7d>8Ic-+^lxNnNP4*p*v%`gQju4ytkT^Upi`F4hFIHySSN^bFA_2I`!Wwmm|4f zNX#R5Z7|9{+c08N#V!iEtEFh0Bc^2h&?-~8Fo0p6WD3h`gk6vKntw{ke#X|}?J}cI z`|3Y|Y)4Jz+QEljcgZd>xzMLcJp7112}I&6Y|^W&g@HU+cO+}a*n}{Cl^4w_?mx|q z{H-{At#U-wtHfVzJSar^38mCau2Yi|68WX?*@v_&-4Sz+wC2C!5;2GqJNX}bTG&>e zDI7Ux_+-xgPkotbmmWwpkL_HqT1_nB| zO=m*dTfsPp8NTE$cEpz%b!>L2IJj4SYwp;iqn+$&qz~!hn6~Vu{-u>z#dukaWVo<{nuFyf1rpQKV&ieV$WkwC^*^iUx&Xf~Q`>*6+t7^z=F)Eg+6vVA(WdWawn>y zXZ~fEe()EY94L6v={vpQ0uOm!*&Hsk%@qR|;R|b7n3jKXO~0~*rWu>@ai52poFd0! zj}pOkOi(B##aEJvA6DrgXBr=lkFya!tO!G)77P_%{SI2S;v;}T1?_%J9^@bd!P>A#H%w$D`=rSu zt!q!7;#L08!Q;pI&onu>qzAXMX3WCQws2>9Q@dM@!2Ti7U&Fh9*mvX|Lclj@-?&|K zGiNY()ocI54rSY^Gy;u4BhUym0-FdhR?Q0#k7H=0?u;&Ue0Zx%%p>mlG#WXghiG@sbaUw-*=%Uj;E7a@o0%s9B6 z?FGoeJ$9Y>O^AReKh$1$aHIFe4gc7&V~ZCXgtjgV54I0vvUL-t-mV&fokL*07G|16 zpYe=mERT82V>WX3^#^mNHpO-( zFFPu49(^nylXE$ywD&+>#-m)e|w^JVSCci8iD;sV7>-s+L^ubm9NwS z#kcoAY9YV7*DI^-wMj&{EnAUk?s zI;{(bfN#+A4W1h}H}iS%;R%&*?!1EK#YaB@xp2p;Bke8%TqC|toaM}W`qQ5-HucAT z?8l1s^=EzRy?C>{=|$skR3Z9oz8_v zz&Cc++^oIGm?u!kk+JaL)vN8-uRQ6x@IB~=jlljQ;B(*C%U<=Q%2=KJMc_ zZcLQ+nlSk~oo$`lme;hX0b6 zykvRELmr|D6xSIOCtr`WeGTsEpqY)pAws~{g0By1FEpsxycjW`YslBpA%d#AdH@jU z1;_z7NS)%%ivTxq7vI?Dwr}#DV7d0hi@HlAa99!G{P#8CnuP~X3z-D{+OPfEIiY#- zlb^gi;t`L~B*~K}PnulM*XTK&wXhMm$PwUL@aF4duJ>AaSii5Mi~Qs`VBPBl$N@WG zo$gJG05@bWAbgYNW^UT`JjsHdH)mu&Zg<@XT3bcLx;y-cV`(i#kCr}YXlAv0=^!&HduhLam{%9m0$Ul zfySNheCOrOZ+`Qh?I%6yNz0=i^{Dash!-LLYp(qb<0cw`Ly7>`0%fkDw-+39d)Ak6 z?;3#}K%f^OJ8%#>h5bcQ1wxh5koMxc>zx6P;S(g++z1iS!Y;o%7nIKY42^Pac- z!$17P!ouTmk9*wm*vCG0dHBO0K4AL&-~auEe@MtHT6|6f{YO6Xk>e={ix7OyPeF!p z6OF(jMqpli00V7rXKR~J-K7!O1q3dMfudhv--RR5IqW+E^QB<=Y&FSRw(p5|0*$~v zA;2}T{kf0puDfnwd;H@cum5)bd7t-r%8t*3@L_Wo7IeLJSd;4?KQ4%%B244}N=-q* z045;~15vPGA}Y;5N~ENF1CdZtQ4ooVD5x|@4@NgkBu0-Kqie)q^?f+Ub3VW8cYVKq z?Yg#Scf9lUj_1CGBxEiksjbLd&=2UwE0`douMVbZ^s*~TU=(17pdAbPDAVCS`yBhU z#%SZ+pz;Ge?jjV|W5;%K$iisMD1hz3>R7>Z70!yKW&|g<1lJ{>YOadYTSplL7eG)?9;{GP@lM)It;jEht)MVWDEJTyT5%{x9ksPvtRk=$NG;X-+iwBBMl_yb z=Uwixyv!e>{fX--3+F{<()A~+4a4LTy}m#0jZYlV$4bRG$K4;m6Z|1Tn!#a5Y%MH5 zq;t!-<~u7aT^k3SAn@?>jRR{Jwf4a~?(g9$J{>KL{M1#-$4eJv+cvYS^|Gf7eXIapeXUEWymTsD(Q70H$^-7X9bJ+b7)bN_q=zo9H284}` zLiXDEdx6VWm`N|{qd0LE!M;V(;>r;9T>I)_qEp|$&o_r?AlV0--2|)o{{Dm6eHNqh z>pW^0Dbh8=sYOew=SPVe=Kh~F@r{$c!lx(kNWBx}xq|^_Jk{d#O ztNMTMgHJHT@0{j3$aCZBk}IWZGHoIF?=j?<6|Nizjq#K-@y{3k`?z}0wSFch>+dxk z2-Kg|YERnT1URd31-*j)holD*`R8XlU}Blf-akD32Y3BFY@RUWheLVM*kZNAPf(X@EXfqFC+as_kUA;;HvO+k^3Xjg|F&36vhhM6|sXcEN5flg!v-J=*QSM6ER*M%ETmUFqi^ZPO54 z&p5Ekpd&S9&cME+I79qixcXOT_04IP9C{uQAZy{tzYc@M^4jgZfNA&b0YivSRbN_S0i~+IR0>0N zm%O#}P+~4dcUj0|N17D5dti7wYgWAqfQuZrO(Xab_G&DnMP-D>ild#oo3`W5s5!vy z{ZWBb5OY$KC8@qU%xDaKg;!OeLcsL5p<99i?|kt-!_bhP&B&>U?UOJClk?_!X9^sh1f5uO@QP4PuzWj&Q6fJ0PCT4T`Hk`{fC zyFN<}u`A1QWiwr>RR0oP+<(Gmae(P7G}iS=6een5;bStzWNx8aO!0(oO5 zlVbx;??f6S<|7bK_Xu#h?Z#dX6xnS5qP8aEDs0TQuv9cZ$^o~IoKZk%O=GED*#5pF z{5zHAcil$15ti7MB=qcs-{=)**Xs2qHbFBx%+N3I7|x$Tm1WNVTS>GA1N=w9CVz=c z9{cGihDUhK!|1axRw)SyBTF-%aWCsk+5nt3pw;T#k2CY=Zum@K$E>p_!6-jrrs^Bq zP`ABaFil@g^IXf$PKRNw``*Wby^jR--O4!m<$UyJ#~XGx+E0SD`kXZ@%IE+WS5g7O z^=y6-SG%n=qM)??jAz5|I!O}0DcR`=r;J!d!IsHp#|YzVh;sM260y}NlK*-r7+n}N zU>G#8`NOd0P88>~Z*P$~=>Et5RP}fW{lqQQae&Crzj3XeIfwcH|ccLmrDkgm3*s&{3(!zL)M55+{-1d9D(@O z8wILP9fSQ!;8Jf}X>L6XCf5;eLi~Fha?Dg;J>NUvoAhnW==iEUFBrcYgfFL(pbXOH z!OfdLOfH@zRbqqkeaSWtV1gFOPtIxVEn(S_C6`kg*#evw}KINs(Ivo8113tGsHp?!eOtY zfO<#mk>A*ius9eNFw%Fv6*>xIY{49R-2n(`?MEk}3XU9sSs|wQ5Sj%BL0dY=t;lZ2 zN8lYRaF%?5b5MhL;EQ=Ur4(+e&LBaN635$iCw6PgZOBc#)f3zK1i%K2gjI#A} z{v7}awjV%;@3f<+?U`U~;GAp{g!}^XYnm;HxO6kp&8F9;3Ke{`19%Jaald-Hz& z&zFaafUEIH-9`nz%~#~p-&$%}xoyrVVEnACw5A#tEHs9o1v<282>rABbmQ#cd(D;F z8I@XV3HP?C5yt|df@d{U0tCJqfT#2<3jE|dOJ4@w`6qpNbGX)QeMbDU#Iw2=pwa-V zo4P#{PB^cBAd-e?VGQ76%eWT2|9Cq$@0FWveJHx;)J7$WQt5Agyw>ZR`J};zNYd1L zg!)znZ_NHVkYA)l=8O8A2lwcHX&qtNp!H>+*u#J*1n{Vn>X+^}*^#(;msU%k7A}MN&rD>{JUduwcRJK{Wt!&- zA02aSU)45a-H)5v03_kQ_y&gZ6&Tl(cC4X0)^9f|`Cju0dq`>mLG2&2rgn1PuyE(l zSK|Xs_dU5j-Kds6igvj%^+?P@`ubcm8=h`s{>+umZ?>#XFi^i)0Mo<(P$QE+%(Z+v z#~DnU*8xrN1@-bRp!PR(jimzX(vYfc)Aa;B0I3-TufKfRe4Nk<#Gu>TX!L8sCb<=A z!O%~`RnRxUjNau9xv(PH6j=Jczm98#bb58-a@?A;c&JmbhzN9*YxCpH))cS=<|&0L8vj`rKoytm)LeUkEF1xP6Up=D2)21B&L zBcrbvAZ^7{uJxwmW7P_nC$ol$Pqj>41fF%6X=M^W;!qPCu|7|W8a_9{?){ot@-+6X zn|T!it?OnCOp*j74*5PQT0!lg)3EhZr4s6F4KJp>%d69h7STqSyLi7sjX^bwlJ-nPMe=YV}I z+hEal0+^D#;j(HG!_AvK1m4h(|464z-r82v#rr z3lI(gLELYm=7Bl)XHoTIJt{UNwVr$*<@~^zPGxCge^c3#O&bb79b0XvMm(f8+U-m# zcO0$OR&SL?@zZ184-Wzx>)X-Pm1wP&#z?yUBUp-o2TNWTBCWasBQJ;4sfO%`G;uGe z^|P@HZ4qxCbx!yH5O+fDwWG>&3E27+_UCrl(s0~Dr8lxmB?Z2ukF6Tr$knNxK$D+? z3yVNNB>T6^`A4DHY1kJ-4TBeDwDqH!#`rqrp$BM3C+e425pPB~kk>B`8fJR$+~gi{#@Y9!1*OH5ukMm8&*%{%A#0hc}9xHIHm zZ>!Qdw))@T^G9x>4j)*nZvg+gn*7o)rm$U2kH>DFx!S3=r;P=ONS?4m{@PjCcTy$4 zGma~>)-o9LP8;i{m4UvDqDzJ|%WHad_;|r3V^pA8`GEEGo#3?4R?t4|= z%RA*=T}E3uT)DHoEbmuQN+H9&ek&INRRy>KK5Gc=#KPgatk6rYtA>Ze)I}2 zRSHWV!9dr^>I}Zdm4)*f^SyYr1^JcRC8M$$iQTGCmt1gd%lK<(fh(hKWux{b zQ2c4)rjNCHVJYoiK(Foau)7oDU-t$C#s4trzUbsJS#H<9L&f9rw+59`1l2rM-}pFF zKwrFbol}yLQjCChyHRJ13;sh|P(=%;f3-96f6=uppjXMgPY>wGDam{*g@g0@2e_LK~i)L)~>P7$W{I$JQ*zcbCbkbxyi=E|>oslWPA@$^lzk$0qBx zV-r*sHW9_hU{-4#+9CMLGR*c%Cgg+Ey-PTY9I$9-)c*{|LCPZf#y>_X@Z{04v4mC9 zwrfoduZaB;uRJ)CzTCReMX{s})&4tQ<3S0M6I-;JevpVba>Fv<1#s0D@{=3%K8<}K zF1GIvWZ4iYM1)Y9M_X5o|D)SKKLJW}^uQIrIo#{;pBMR;NlXV!3eOx1a{AYd|FP!Y z2TeoEZ6Wh=f4=zdqcQkkMUDEa>VJnl2fY3>n#zlVR9viJq~6T*P0NA;@$o314Uu1J z)k9oBiXmu!E5=2ZbDqRu=2Yf2dTsv~kaubfud^W1EYOYNcXxNEHGu>XAGT;YeOZ>- z;$elivP<>ET=lq@==1wrlVf&VZj1fjJzP8(zr2$91n2Z;%EirPMRdWeEM-`~a&v*h z<>o1P;NkxzNqa;lZ#G+OcZGTftae$TjVC-0ew|dEaAa}^s&lRqx8`cQ*iVvz(kj&5 zXKz6?PUztxm_urKx!2K5FC6l@pW+gQj(@63U=uzd6j^IXXb8koF=a6K@!07we)_Qd zC0!ND2P0j1X13!@JyU*6%-ukN9jL6NRjpPno!{NQ9<=Z^=~+FHIn% zwD7}_l!epsBafi_X4tX-AoA8#V5S`4;T_6RPwL?apeA^J6-YE&x}fq}?8+hzvh1EL zz`bO@CdYibMP733?Qq8dHHl|$>TkRXV-u*d@U2*V)vpOvQD%Txm{4o|vMbGGi)*-~ zZDMoe3N)UaH+t0U;z4>ZBYstpO_<4L)9J58zc=->$J50v^1DlFogGTN99X1SSppGQ zTu1>E^w^Yta%U;dA_p@jV|6`ATm-RM-}D{Wf{89zj0OE+ow*^3GyjePKh(c-xV!~|%`{g=PM;rqp}O?RHS&m` zgrZ_OthF>_CA@-PuK-tnL1!9*)^Wf7_4dPiKiog_sM_57`K%!f4)(!S_cLk{M2ZO> zqyCQK6S(M5*<2*rX`3W$o?k)OAmo?V1XecYNtwnrb2qGnvEevioHgVRj*y2Hdj4FW zt8cD(pE%HhA*KaSZ&1ieGaLI!d0t`he6>pS{5GQsO^#vIrbc^rC46p@5`&e7w+(-0 zx%cC>bB)8ox#T@9=`jcI&`&FD5-s01I!WEcaJMrW<{wBp**+3i^-Ag@n_C@tPh>w~ zI<;aTpf5S`l=FcpC7DhqzxW>hqF(N}R zm66)5EUzv#qcJXr!xvSsta??OO77Ou@{&vip;<>F;HG2w#xH%(HN0qsY58-VYW>`) zcaU97Qx;6?%0G7%qE2mUjEYNw@68d03u@gf=c)o*)1-C!F56iTNBSjbe|aim)85@-Eie&24OVr`&AStvN5zx;1uTfo*$Zrj>2wNIUvyNLDWH z?MI+swR4cSUA{sU3dC`>y?TTg8e@-7*vQ{UBAb^Ik^VELi)(S{>&=dA`ak1unJjS` z6*>2naykS|^^t|PND&EUFtumr8WQ4t1y3busa|@?cMYcTll;x`Mb3+Cpn4nD(w<<&k}vMBX=kWTDZ< z@f(Yv2co#`gCc{;)xQ? z+~P;jFvoy_Gj^dyz^M$Qp>?lYU-t$(pUiO@fK829c!dw2eLVaFskq|m<76!CN$E^9 zZ4$AWFpBmaU2-^DQ3PoHjz9=-ge6U#SqLf4Ww|Nmdhd%b^JY0DU}dw)DDW!&w~l1! zuWr?m?3n`ezNzF|WeRNVgKINwLS9yFYovBVrH%+9dZ#l|SButvJrWXE<4*Ja$n_h2 z^w~y+y~Vk{J#Z9AD&An@<#~p3=Mk;%w;#ZvFFvn<>rRR{dP3B?cCkKYTSBF8y{1~HKbK5q|JHv6PvO%*-DPr){#(JUlsY3YkvmrDN9s7n&S{}w zmEPR;G(9{x-tl*EVGGMFzt$+ia)4|uNQ9wPd2kJv%-KF(X!$%7E-*cYE3NmTtgjfE z9o^$I(%)EopUt@3rk-4(eoJ zWFc1-;dSi-&aY8&b~(F$w~_$m*v4AXwTsMSO~YIJw+3)c3<=-4oQboDvEFO4PxR{G z0hc~rOrA^g@tiEtb-q+qbI6gZ2$f1FiHk!eL^d5F5>IZ({leeWO#!8OIM1HaN{aM- zbzSd6p}n-IaFPieI)nJV8>e_>pI+(4pyHNdrOFX&0oyMT7QuzR1*>d8GDuSz~Uu>8HHc~-X6thIx@ zqt7qn8le7ZjBM^ngqa;vE;qIq`-D45dWmy?snt^|V-DH7_Y$)x`np};OoJK*-SeZZ zdnZbz)gt!ky}Ph+h4NOEfr235VYe3u>74^_DX&`5TTACH9DFS+Lf%K(J=(r=n|wx9@MqABk2DI} zt6R(|x`@|ydjbw3mZ&@B)ma6m8hRaj^Ns?CI*UF>%H?0l;I z++P>4NU^u|@jonneYAPv*o*a_)!2d$!zy>S3mOMoU6sWZbrd1rE{#pj`Da0cNyKp9 z(hYN5x`mXQf2sP+R5KgAm3^g*4?OcR`gE4;n+XMGK2E?CnknY0{ASXuOSs4jb}Fb^ zbl!L5PPh=xi5nKu&FGml)$xj!E=jX>1~JE==5VIO_t-a~-gNRM?YT7k@z%-$66(lt zT6DGu`twaI7~|&sfhRMcc2IPEWyXTV@GeI2%Ai{#F| ztVFQfY&x4zTrVk9Ro(7LX;~9dMH<;O9g(&GW#nP0SI>QII+AgCjf7fa_HN_SY_(AJ z4x-HqAHE#KXp_B&J(eaD#7JvFCFsOK#PbnEa>PrjYdnB*7LhLs$&=exc)`Lr|Bd=b z1GdnE1RdftzQ~7@$))En{Fh1x%xdIwO6MgQ!VV4{Fo>rbxIY5-QJ@X-0ri$#qpjqyBtK@qGhh3mW-s~fJRQA8m>i5 z@3pv3Hyx8yH1hSGK@ou>CFFWTSWBg!(+k{Ju8R8yq3QK=<8GWMnEij$pT8tef3h{f zjdM`{(tP_~Ec#s==2px35$+%J=MHPFej9MVpcXwU93OnU@#&0DQ94x6Moh2j1R1GR z)G(&Z*e*q@bLW0c(mn8+lP4A__U0f3dAdZBus~F74KLUXiD3RLoznve8LQT|1RwYz z_27wfK42!7U$w??I9wnn*Q>7wGe&&y0&*to^|3_peobc#F{l1;a~YqBMc{mq&Ww*@ z517VN&YM>IcnhkvzrR4y!9$__8=;`j0aKbQ;$Tu=oS&JsB5(@F@qqa&7e1r@yf|L>1&jJ) z8MIqL J0(yr0)33BMi7TK21d3o?g=4B~9{sS3*+N3hkBRZK{!uiTf6lw5AQsA1y41_R{}vjMaJ<>2?=Gm4Uo}iIYbbBYrAh3yD6K!+T#d?U2V2$N=TN(p=a7%!%24|kWpNaWQb>x4sGb4wZBTfqFz=;0ePI3nzT ztMe3MgfhanzTWq6_w}YI&Sy!oEu!pIE-X@K0a{lETl#zp4LhW;Q1ocgzky5kh}xlc zpPXm=f(cL6v_Ll{rQ97t&Qv{l72AB9`cuvF>cYKLjjtPh#=QrlS6S!oM%N;9jkahc zvzb;4c2Jy^+k=>m6F`GgA^vZF5U0_KKf_X?k8M_PQSW@?LHH=qs;aM=c*?2-F%gQn z8g?JDBMwG7L0hG5 zI?|j@!{af6N*{?Vt~z6L!n>v}Uf=aj>m>?6k$Sa3eoOCNjrG7vKd@p#jP(G?^6G&i zRcueIg}4_A1Ey{R&}3Di#!AU8NU)?22WeeskcN%W`%e+On-U*~YF=Lg+H zMC2CUY21a<5=SBmL8t=+Mi9MIQEkv21vaVO_kbcQXH~JN1Xsk)W;E1yvk)^NPVL`p zM)~7oNE}lf2^e*TO9N?b1P8%VSJvPY`Z}LB)+l%co}uPaIk;UArkD0*3{=)q{^<8Z z(dSkN<}9qaI#Wo4#pvnN(u}b^AQk+Xr!i(w#3H(1VSpv!$Zb00q=np5N()RpuIEe| zG-;wfx)jkJCs|Oj`MpzToVH0)M!G0Az(;ZJOPNW704z#FX5)815}L95t+tiRWcS6U z;;}ueIP+EiW@#ad#QFWK&yDVMxch>;U)>t8fI5_b9v-<*Pcft=&tUx(6ce6I^#W~J z7Y;1{U7bvi;oB^mwP{f&F0`R4FYe!c@Kze~3!d2jdLUwLTVXbn>m5#lTwozx zr$df%bIhNMVnrt3o4AwhvN2k_k-w`(DCCN?3y{Hm_byXM~hW(XLakPp*-&*P!ayrGAxYB0SB<@07dP zU`@k8Zca!CP%RZiuyPGeCm186Pc}_)*;o$5#3?ga`O1+N<=6k>K~dvhdq#m%%Rs^W z&@@qH5qyjnZ#LT=Ui&Dr%jMgf z!rG0?46>lfd}0iP;sg+Zv{$lMP709PrF?-IPms~sQaExnaMjr(x)cejd1n(|SL1#5K)dvB1aHHp z)*riy$O6BmrNrHq>G}N}i%eNuyb2HiSXE`a@W0Gg<|8KN zk~E~Y21vAOk)o*uLB!3noQYxyotY~ylMM9nE|ufvYiL2j<lPq5G@k4O)Rjab~0LzoidU>_Bv%F(!N z2&kGK)`>^26YQiIR6d4tWvd#-x>C)YD>SRpzG5vBO(zJQPuyvHokBAVyykR}xa~J)p3iMO3r$>mwC=F|f$r z?ps*obFH-*Ix$;{u@KvOrC@ts$!!2GiKJv>tQGX}9)A5Z2=BdhQ&wXk59-pyrcWoF zv0xCsDg@mlCNZd!)!nZ<+skX8`c1e(t^7#8Uii+q$G8K%@PwQp`kHO!44(vJPa1xT zW^F9T%;WXMuMv!3v@sG<>m{Am!rp;??FJZYzwH3AR&l5vVASW(u&VbsA%(Fgs4 zbxJ2K*PqDT$OGY6rE#*|AAFQ2y0Oai<7VD~t8`9>rihPu;e<`|$+HaGN(w8*xYL8N z3ic=tNF=#FZe^qs@udgZB86IdZdBZG>or4K&!!J%<8bFv{yt+=W%ulrd`b^+2V)~T zB!tQC^y!e3r_UTafA>JzB`JJ;8qCF$^!R$rtM4R|Rjib`CXDwL{cby<1W_Q)Hk>lAZ0Zi>ll|k3= zvL2LF^#XO;0^X0hpSqgvUhKGOI)1X{@^XIuv-r~LHN7LXZtg<^DY;a*;?9%H!tcVS z6k6C5k)BthtM&IO)dt(H%jydW-no9R`P#G(wU zxtXJwG!a2)GF0bdyC=LSq~uS6w@_k_D@!cg3P+NGEtc=gj6?d@@98XQQ z)fb-OTwmOqKb0G<>@eY*(}oc%kq~FoYa7cK{(ifiaZ`!%Os3D8P2G#?MPuz4tZ=Ev z{CIY~M~J=S;Fz_tr6AeV9G5u@MpocV`^zM(V}w&B?Qn5fK;A=0bVnGjR+J4C)WEsGk=)3g2p}i?s z`{0Cpc3>fGz4KAtT^!?qHX7|LHL#tO8FW!tR zK$-OQ3YobWnis`bacd(YU+ezW%i)p=?Mr}*Kv$dfLvE;W_0hs>K^?0T*me)C+mrRJ zsQ6M0`IDUeEVk3)6i5mM6G4hnpb7fw-ffZ~D&K-B?$ywK&f9GTjG?!g@@0tX&bJdS zow=OtnAK4T)Sr=dxx?$X7ZG_f$p8AR6Dn|Hjs91Jdlo|tdd0NL>&_u7y`J*~nGepc|w-5^4hE@n^9oG;Re1HWIWE?blpy}iemt=F+cl#qQ>=3LDJv-L%Y zZf+Vv-?RM4DcUu(S)=*f4t?}++jO}6?*3XJ2EA1YPsrSGyScMQDa)m`RgZg!yWEP{ zuCfGvB^REFhYOI(dRGY>VsJ3nowCppiTr#~vPKlB)j^&))nbF)lb@t=9Ybyx2yE zK4y&#JkR*$w{Ls$4QffzoUuSno&a5KgS zHRx)>hr=vn*grTPCP)1+=EWF)0RKk6w$&aRhcJ80dLf~YVW<~7-(`?R57)nuyt3a0 zZ<8#?U%v8@-$oO^|L9SS&a&E)r`Zhjaw~nxoiH;8rmzo>jq@i#XR$k4!%BNFIP$p_ zJkoyz!+qI>}--O^`fs3C!n(D+ZgH|o4BlNhjfpvh8Vaxq(LU2ippFp41o5#lqiDly-mL6ummf*V=DAFHpnF+cG=PhtT89N)L}XMPk_W zDR+y%24_R+KyJ%aE;T8P@`s7T=b@0$VR~!dR3gje&_g`&9Tj>Kwr7r!wS`}Y8(v4R zL@;N7Umt~g##&4j%1v<2hzN>pHLCYPAc%^&t70H;T1uJP#Zl9s4|vXYdV%@{U+UR+ zn5(Q~i3m40lO9lbLD$Oryy~)fx8DmTo464lkIS8X**#Uo=hB-wM17TZ{YEyH23=s? zawj-A+5=M&4|{}R>5Tb+-PSKqMQq>U>=*kU`r&bGvWjZuw@YeEaqq1Wz-tPud%JDn zG0ydS6qUu=uG=)nabJ6*z@SSm53=*9w_mEcH|}gFrC|ukO{DyhN`uW298!z(Ye%V; zH;wFi2g{$Prq60PgEGT35bXD_bgsD*liuH6P0&a`wtgmF6)u!0$;a|*Vd+GLK;$=` zN~=9hX5n{DZEUjVs_qycW=1yI`)_u(f!_81vgCtH!)EQnoT_$_9gcB9zmX{?-{{cq zSs(~$o3VLm8yfQOb+&e{L69UFH7@nwtLL-h<}GV)C$U!*&tE8#8TJpT359!|duY;x zEES1|8@yYtxV)f;HrT}f5*@D^bg()9+KYPO417qm+XV7M4Azk>eRupyj=W3KNMDV+ zQ&*Cg(XT5Cp+gVpV({MawZz+#-C6{JV6t-|(jzzV0skCsuQ-1_nDf~rhI zlr5K^=p7Xq--mW1^He`3rycaUFJ9y8$xqA=E&;cINeD10v^^JK zD0m52IIDc>!fXn;AIsfmg)mpRfZyECk+?LV{y!Cit zS0f81#5ujwF|uu*kEq-?FrRrRdId>j4eEOw4!(>hY`gZn^)-cloKKf7+!qL6^h^Nt zX|SDBW_;7j%ujIx7nY~JtAV9Yl$)xP>1rlboqZ*=b?PwU`crhEhFDQ*H3a zhzFlrg-*380cN>l@5qyl4%nfkMd_hBtfW$}h@X#5HLWhjYkpol5S|fwI!he$lltxH zmlJk3QtxRdGVeLyN%88eLLajUd)XGR36K-@Z7h3LTYcHH(cKzfL~Fj+y!yTnP0dPZ zwe5L_@e8VW=Xfg|7FQt?H%tPz*(KDn8eO?f`{?{O&~CQcof8}K6v5X>gz~Q@mL-0n zcc(*nu}>;abz}Kv?Ny66lTvRsNnA!wubDUht|kp?yo3)3GQJ3&;g8Et76K7ZnUQ`8 znIQp_8oFZt7@rE?;zLJ!R=q*|)!KgLNd)CpfF|De5x#UJLVJRD5j0(XnniOn z&B@dvO+m4_oi`*+K=D$PLRnkeedBjW6GeV%3VN3ii6637N=kDp?03*-@D4jvp1X(?uA%K-HvNZhty; z0DoTQG|42sKg1eEzYtk_8c`Vxu9zgT=DS9-o{9{4E^zd5<@WqN7y_Z_usL<%((v{0 zt0%+TJ7C)%!Ea1meIKMF2f|4r5Jq3Z?=pq$-)6cCJOZd%eg2JxZ$?a&cjedo;(pGj zmbXJVBc_C67yG_t2CKY7GHMmTpwXKgp3Qpgs0vzoj!corX}BaUJnlCj4iC2CwY}CB3Nl#h#gi)@nmt$LUI<?qRYR_-A5Y-N;s8dU}T~z~f62o=C*B}kcn_I>RdZgl8 zggJr|@YNh;?$%l`dR}3LrVl>poDE`>o#2EO(e7(_k8@KxHo+a>QT!Fs-D5&Nx6Zb* zd<&i>PZvJjI~&{s0-tR9J|Mk)4EGqG<5#mRH z4Mhzkc6%|vR{6uZ!b2zK(Gv1^I>X23R+dAOVlTLx+(1Btskwr_i=f#$DDpa|`t~s; z50{Qhl2hAvZGWg-3^=z}U|eG`GSh~CpNUl$UK`kT^}!-5NPSz^a>^HzCc0H6b>O}Y z-Z%DL1`1Hwdy)@*?ux6=38xgaCv#`ISPCRwm?JK(eM?o3SN#?DrN&hLO9!e}%3?}W zcxulYk3(Lx4SAKWRWzfpg%>w{VEdQSW)q){h#r^#e~IGgi2|b*>a#vjC3O%Xa({$Qbl41k3_0n+0CpkjhS|60RuQh}ncApO; z27Ve{O?;oT!Bu-75o$S`!JZ*eLtrzG2*_~B%Prc>N@!mcmQ>j+ol$U!zb2V{t9Nz3 zwtMx~l-rF*ZwC~Riti`M3YhcO`x!fA@<%_Tth+k3mk-NozD-2E84&VX*kr4J9=_1m zx@+})zIX3@EBu@ql!`adzmXoVg;!doN~~Rl6YZ&cnbO@o~yj0LQwl$_Ct%K2$C@tawxwT9Q0b(rj)wW9OaNI~oT6 zX>yVG8PdW~g`vDKL6Pp&IU$mu%FPTKJ0|Z^$T#ZUo;V>KmAiAyZ;u@#F0PmAv2m)5 zBtsuj-`jx(UY9yjH0q7GVe+gdHziuiW@42x!j5g5T}F2;jWaq6;F&*nS2*0|?Bjm= zls0YG5yx}g`efzRcXWSO=BwogOl=pe1;l;X1_XoNN;m0=>1h$9D)n@bC)M}Lk;m*F z$&onrA8q~kQt1G1#?Bt(NHE=jH4Wv0UMXAEyC5P{vw0R{ggDD>hd$w_^kV(5_oyr(_r8??LM07f{3Rq! z7oLZWrHU_*Q}9RAYsj_eO~8PL^wjK|$LKy#Lq67y3o`b6a^4zYR<^R>K{!gl{3sgl z{?XJ63o@avl%TvF6p-^++eUucdH8*L3rBgR+2cW<+m2DSrI(dI51@F|*8cLllp4}| zRI>bbRP8x-+lpNJ!-DtSyQ=3KDZ+O<)Ja}SWHRn+=I%M;fq}~&*4ef;lbtfWe2T9} zwxfRIh&Y|$jTO!9^Rn=Ubt-$i>uLN~4dbaZ7o2LgGmEvcj*71?>g)t*DTC42qIz5iNp zOvj6|aq=$ht$ws!!&dUS#^RasLd9baccPDZL32IgYI7=Ci6MDL86~K`;*UX-#KFIC6C=?YXEDwScgpjZ_`5jg zuZ8X@sTQUyAx6cF3pU`OX`E|qZ_t8ZDNB*nefW>ZE_yX4eDpk;LM4dv$zHTY3wP3=!0b;gd##YcoB45LS2%u9jQro>2;VmzpdLHCSab{9H+_^;#d>X< z%=?O%n8zqx+UXeVcUPo^x07HUWaf7%v*hOAjrg9?Ngp-MOCRFOZfTXk5nj#+#Fi)P|qN(8> z14Go$JQGOio59CY^jt>8YAyqJmtKaNfaK-n{T>_?6A}{I08!Rm9UR_dWr;aBIlbH8 z_y3-k_x|HY{_leVXXVZp_On#5IDUUc^5xMvbl3XR{R#sA&bwz{BFPCM#aub(-nhT8 z`oK@l30-K1@NF7k9*j`d5_bgdx!0Vnrrf_o*nhTZD!DDRl*&BSEa)zLX|`7~?`sm{ znZxpkn4=+np6A;)dcC^>%TMh^HC9(6r0B`QAw-S&$lB!R|G$^}GImH(;+ATgdj|h! zQGPEeiNy|Y1q#>A$lq6kK1Serf}^R_`>4&v{YC(e6G4N>m*#(spO5!peyFjD2s5fJ z<}R$Zz8EQ4>8@~}HgZ|vWy^Jm0aY_&=@~06$BIeEM%OI1OJkSVPLDqcZ<7{*c7T>Z zKaPxobk04M9Y)k9(+_U}dAt7)aMjpy7g1oJX6;ngb4Q%MV?F$e^UL_Chv!b?cLCoT zz1cYO>HFj&Z@D2m|IN^Q_Yp?OAw(ff!hxYbnE#edJVfDU@bR{khUT`;H^GJ?g)yr` zD%o&_mGCzf0W$Xiq2Ee(&DmlEEfX-yJ4IY_oCP%*wN*)bEg9 z(;^&|D$a#;oYgq;MJAv7uCX?=uL|#9;p?%b0!N=Fr-Gdn9)5A@)m+C54Ik7^n;-KVy;0I0Wfxi-3|sb+wrNL;za|GYqwD=V6kY zzIysBg+s8Htz@z(I+C7g@I3VC%bQ#)qV^Wfz2Bs`QLJklyWtD%2jd=aK)mWL7|n=O zPJEHLZEwdHeFJvN=sLiQ#FO%%M`u`;SKquZtIaaWBHk;#4=+fvoQ*`firj2kVOhNi zz4mzm5pOls0}w8gTJgj3^|t{KMpfUDV+r(;^O_Sh_eUXZ`;pivqmAnHY_9Pyj*`rW zJsmr4R;S0$7d`~=p#+bEaJI-%8v)1Va)rV6J z-*Lh6V2V$Ah4fEKHWdAD-8W<%=}ypIdoxppzKVj-wk$7xbUvT~)p>P~pT6c>QQZ>q?%e1RAzgy_V=v8VatexJLG+GTato4XoyD{7qfs-{8e{In6@)hGl zhF2~S$(%gV0a|2Rg2^Rx>@=1qJ3-B}Luy&)Oek?9d&%!UhZLlkf)h*4TYAMt*TSqk z6Y93lYaE&N|7|ij-ZJ< zj9w)V%^xY~O{V6|tgMzxA{p0D`Dh_HzO4Kf3n@NGeef=;KD9VDBqTC4_}taJPb!b2 z)ZOhF@5h^8oa%P$Lk5hD62j#4l-$bV7N1zwIamP{y3Agbb-Xu&T1YPh9F9X!lj%J4 znVr~IXSX}=V;^Vxe%NFZz!X9|dtO(lzZN)k@i5cnv$nxKT5~BH-(J?muu>;dst6>= zi3=t-_cv85bhYX=UsF`?3;2sm1mJlgeNsEDooN)1d)x#vx5o3q zGe<{r`1{hv;dm$foXSOjOsWTDicpFBsKq?oGW-rCH@Q~rmKI2$WY3PBx6}L#I9~M0 z@zUc!$StNlZEM26sy&kRd=j0k{^SPY9co_pzDd&9b9S$eM_lE^MZTptS6NlAGO!c0 zj|N*=e(8x#O&CeE`<|2I@%rey_$RM#Wgzsv{-4&YJe;j`jVBQ$$cT(xNn&fL)*h;@ zL=+KQN{UvCv{dcf>Y`N=6;(#9MMiC-!n7GuI+jj{RBCLk?RJP(r`pmomJ(%ZDfa|( zXFB)ad!Fz4p7T8CocDX*_xJvO-+RtU1@@C$K#A!%^oV&vz-9yWP-#;%eDR#nqv2x* zDq+=|6Ek{%n$Ppxh!Kq0yT-d|HObxd%MO$)w~QE)-BnP$hQ)L6VR%7&^UZa!NUv$s z{@ImXSk%(pnwpH4^)k}+i@_7G04*C4g|{j-_o+z>@f)UgGIYe{LHOH{rVr_dmxWn% zt}P@fjhAibG<@f|MwRrc>ep&<>Svn7Hv|pJT$aYI14!Y52iVsdi$4}C(zeDOIWs}^ z8{QT;bZ7wa_bD%ut?kuSn`KD_M4^JQxc2m`R^OBeq&FZsguHJpGx9?rw6|dw()yxa zd}_en=hhv@9H7Fn&z5uyfNwN>9Z0#&SR%6iK8^Uu?(P z*WBdi?3#Xhxv>L(y<=8m(()p)+1TjaP3eQ`7Af}au!bSa5l5>^=?gzSnAewH>Vp|P zPQCtBEAU!P-HXLnsW-pluG5+Q^t2g?=f@mQvg%8u@7#`5M&&*|8%gr;@ZiJ|=6Uf| zNdo5-Jv2@_aXmd5+T}u*A~n^3GD`MCC{Ta@@-m#xV|j$x?|(%4XoafY9Z#$A&F$Zp z&bgv#wL=DR=i~L5hTGUK2{E$e+d%ssb-0dMpL)h$0{dQJC1a(@ak4}?clOTpi|sDtBEI+^o!;p#A)%H7;G483VkM5pHU5Kk8gVa^y zDFkO2i^Y;#W3$=XRAOlg0i$xnZcM;*j9qT!+$uhvd%Z1$b&QjBwEz1EeCkp={AC*% z+179Ut07ME-$@Z{LudM0>5mgpMZ&kU)y#9cF-m#Gjm_Dp@yeY-58y8s++-JAx^Ccs z5$43%^4i*vVIoO zV<*YG6G};fC-$B&m;y3QEKr;*Ilw{+mvlSp?rHn~uEO(Un~e;?$_NkiUuQ$#2<%E1v!^- zn{}y{#0vhKvPk0dunoH|?Mw+#Ga9AfojighNPw=Yq;lnC6%e7L{etqZvA6}AQ;q+N zUe}$gW}>7LAl*6iMRUu`Q-1#C35;-y2TyQJu~mxYbkOTT!=o*Mv3uPf9GE(Q1S+Ea zZmY?7Do8a#84IJG`U*dV=6ubq@GKBFwm7|i)c#T0)FZc}7V}(tkuFos~DzkGpcuJXKZ8pa?zk5H_L4Kw`S_>`b%gP(_QI|2P8&#>&hsD>15c=D3+ic;5R z3f0a}*f-8-rMFpFgsF;P0EST@`1}N}Li4_DL)$gfH#0d{*w{@_5J7k;(7SpB$#n&b z-~UB}%v>(4rKQ>r_7p3(25&8&X91qFB}%bL^0hx~7~4T74P@*14<~dPC!wxqcoSto z0qr;TKO4_4QcCmDPtZqKXm-ZsDKLoX``LV2pGv_1gm(OF;m>Ow^WP*yLCmduAKkg3ZxLY=&kUH6z~AU)NRhrLnUn-N@>DMi*v?52 z1mlD{IQ9Iiwcu^8`9TJ2l)*17)YjWZ@{)0|hYFB*Sd*XcjgOh8mj|)AO%2%>aBzi8 z1G(88o{u)dv#0L_sUJJ`hoWqEz*YrBnnGx(la-zwy{%_*2zrtPFso?s)gHcOn`g|Z zdGBlY7WbWLQY1aBi7c`a!XOseV_J3xJVI|L7RYU5HFR#!bu~{#J~JwKpM0h}Ag~p; zJ0EVtw*_J;1SYavbd$wWX^7itilPvw$E_+J#*)QvL&THp{;cgyvkZ46k8|y5A`i~w z=VrKTNW>ln>zN;Z=ddXSn}rKFuRsKK?T`ucAo^dcLn&5LE2+=LPgLkDENqc)3wU7m zHi59|1+}!LMJzz!DVv+I*_+x3$fIZw+7Jap*?XTlNHUU~xcc@+-ju&$10KijVQ4&! zINu!s>|rZIqUB+f?)DGJXtwKJ3iyl`i~S>3vZxdKpM;_r-vNut{~ugmS8qlm_`8(d#X!K}XykD4`mwwYQp86hB+6*s)5D*rjG#O3m7PkE+>P z)oN9%rS0eY<9*L{z1O+kbIyIvxzGLF=Seg%)@P#Up$7l}OlXu2_Ntt@dWJzXSMQ)5 zVCPjq=Zmro005+f{{K(}S7-zQ0Q7gjb3a$Dfe9L{P}U>Z`;!Cz2~PzEmO2TAVwle-c&J?u?Beq zycshzFu1iVr5QyJ^#!niTATy|{s>V3&Lh;+#07h3-vB6r=NLeM9;3n@8Qz3{*A9{S zHWZPu6g`0%$_AiF2tYHGfUE>)>QO`%Ri%4}j=>yQlV5yn$s;>*xif)uONYan?-aV-sqLXM& zafp&VrG0^>R9{Fww_KFMwawFU0H7p;{c5zQe}X5O8zv`}2xR65l848=&N1_1>xP|FO|6O>bXW z`LMgYj2S>$+mGH0|LfZKpy%EnuU`>rmp{)o-)uvp75q^QAN7NY)w7>_eJB6ehCZ^>4MJm0|4&pK&8w_ zTQr710Dw+OlvtzI_3yo05f{kc1N=fH?Ex&INi= zK-Od^{|FvpDrk_Qh?2!7ne*R8@qJVGr&LL>(d)=i9R|onU&eRp%VtM4o2t(p)s3U`2i4RATg$tK`X5<-itX>8IgPw?6Ux1g+v+HxZ8>6GXulKCv_tlsQH ztk8i(O`!scM<{D#)ycD&RwY}4Uwk-jw`jM2SAO^UuD~~I`XUESKhn9`wkUSg1H=7+ z<%7Zp8s|JYt-Iv~*!AjCbFgBX6|%mRjD2C6P|c?Bs6b^Rh68O-QD2rb$K%H7_S5~v zeqaZ9J?DmT?)1Icu><}6+g0l z^TfKlwM8aJX4lPJYgDTfYF(>+%r!_6mVXjyEc*@n?`V@uOPU_+bPn<}IC8fHO9*%} z)x|%GQXCL&npg=75__HZhwpW=dTmXqincsP{$30AG}}dkb|=s8{Ar*u-JWPw?rB8Q zd&n2~HvD>}f?>O?vyEphF_(y|L)Dqq=^u3|H5^wJRd(sVw!Da9)*8Zy*of%6rcF{8 z?U}8Ztyj@kaTuv1&Kjg@Ju9x4zSeo%{jlnDUh$jzk;R5SRqsQ(_I~q*OaC$dBG%-F=HnEtmSg0<$B)3<%SGZKT@zTyJ z*h+$2O@8H!Zr-)3wERr&d>Ch?Vp)N^Yh~M_S6@^QTYO#rx(Zy?Zk%OYSG?%j-}se0 zLauqq-S}adX03tjO%Atrb>MV;`L?0|b5>VYct?2ZA9Y%$gcasGJ}bV6fL4D9!UFNW zVDjl_jqtbMi3ifIxG9#YW%(U4+ZcSny~wO^PT!T&wLKu_6rY@E5IrW9dt0jT`r!I- z*DfaT%+Gc!boQ*Mu%)o?xO(lyXQj{XpA+6a8&`M+FSe8qnC>6e-ZcF%qrvbjN5*sG zdBh#|FURim z`xHNj+tB_`=%3TS(0?<4sz?}xD^+5YR+Kg6#d&C$KsP}HvF7}vdF5CurKDYpT`MiR zKKes%y@1>Br}TP(pL=E65{T~YY=?#IG!2VT*b#T z@3aFpbbjj)b>0`c%HC0VA&F5GyIm{gp|*OfL!m=sP|C$}d;wR4LwgzUsz`}7C_VIg zvvGNRny_88&9L)?Gf#Th);FYdvhRCb6-SK}s|13mX^1yg&OXs%5v%4%fqi3p3?tBo z^zrq%3QEr?&ES`{ZNzREe?y5Gg=T)r=u`}WzLl?#_|P6JQj^|k$Yi))h$!YL2;%pa zQ%7{k#$;xs`yp!ujIzkChpr!8g2tXZ$2I?b`!M;X^o<Ub5Jl znOK|qF_-xv)5>Zq(}qRs@!1dEHR;?5(Y4nxWbO9yZnamP&Q&9m6RH~KB=hg)zs;3C z&#t%GFP%S}`F#CJ=MRNX3v1S$KmXhwd9!wx;;zwx%YyR-`l98hMnhul!8!55+qT}= z+wXXYYL@B`tq?PLseOKdZ&uwLo3i$dKQ|(lpwE6Zb z@LTiR2ex~!?iIX1Jn%jYJXHIeHFsy|_0!h{4ed6b?Vm%t+Mc-lJh)zbYjXX2SIAe6 ze~SynD(dT9r=dPS-~K$?;8>6F7x^HnmOi<$bHah7&Xn>sB&Z7iNC{-{{_wu;KOhX0>~%PQ?DrzzoL&c9`U z#~L^}q$AE3j+Q28@@7hNzvX6idxus0IqW&&ez7*#H+bXCNU*%@{qGhR$Gwl=J?8sT zzH#l&ZW#Z6qW|1}HJzDFS6yUrXJ!2ZQstdqI?79~UFl7JM-n;XPv(QSdH_IeC|XC$Jb3j}*W*sxdm(#&Y(0;Iez$kk8IYYu z$nO})O{v%I_#&T3Y5QAFW5azjVzcz4-+yerFVdE@zL%vw+(c}8 z_b5t7#fAt#7u9>xBLDNjyjU87NA92bT{bbFtDQhg9())Aom}g&zTf?6in+`cVQk5Y zhCg7>f(-f5o?QLzvu9wvA>c9KF$(^Gja7`WlY77D2`omGu%lyUbTNIT`c>9Z{^ZeS z9d>l)s#OG@Q2eScGL2H>ZOh!4hR73s^A34EJ> zdRz;Xrrc@A4`@aY0L$()OA06VdN@hhZ2zxAc~!?cDvhc;)_(Q=qY{-FYF{3T54XIl zq*3sfUCd?o;P`FjNyVtse6zbN_uWfEGPKSfZN99?R=rODYOt0_Is9{H!vcHE!eMBlMMjl^%e;8gro_~gY z)-$vbis4jax}2(9FE9S$5K;rkG89hqrai92mrsiVk<%+PTJ1KKR(19&H(a0FjP%CP zRzqA)T!ruCuAX&Pd_!M8ym^wk=EL!lqPwImLhs4Ji_c+vI?^8qA>t?c6AV9^Dbp}} zjm;s?ZLS}WEjGE0urd?H<}oe7RIbflc67x_`2}3|f&PpFKnuaKRo!s4@J;>*-noVD zf`6eqx|hHHyFEUzAK`H(hhTJvxM~G=p7pf^?=}ssy#D3KiZ$cqE0ewbJ(}VW+8fB% zhz5P7?fExr)m4`#dD-zW+(JQ^9^AhvnNvTvgj6kdoJ-U=9-Pb#?%eYB->`oA`;4x~n zLA!61C6>Z@O-p!fnE82`A}UkuR8VdNxMSvMIAx5qk8hM=l6N%x{7y$k@dq|$gyJ@B z7z*^2!RqM0Cs*J|M&4e?zCCF`ePb&a%K1WYy_<1nF>zs*;6DrGQ-41C0bPfmc>P!~ z5TBXpQQoJaPL4@Lf~_$UV-C))%(}xkgm&)>0Oc5Yf3za6xJZY>!hC0Q8MNS$ueZ4a zj{-_m_)7GC>;>1h@mOIddG`DIs%+qM&7T-EYb5@(1Fw0lAWh(#*RHV|rI@I+(*9G3 zyn?S4bWUK|F6^0d`?C$c_9AB3rj_@E-7s%5nfXS}XgaQ)Fkc&h3ma4c@qe!y=Wv<9 zW*Anup7w8Kycyv9DT;IKH`lPZ8pihp z3 z@6VEk4?Cx-Bc*TTSpcrl3;Z3+?XLUx?GZ~?Bj7jV$rF*hMd4(uPe(|zP(FqYAG;8^l$s-ZuGE*k4RUIevZbqsOUm$zGSa}^ zg1?<(0{W(H-tWvATp1;{(sS+3r;SaVW1CF~y24vqv`m7|GZ|xzwRLe%9#_^-%Mzn; z46P<4Hl+wI(|X!hm{V`M`dBuau87@com=P|7LuLi3XM1PeaXrx)@bW9bxz*+f z_P4-7o6(b>P|YC;+SL#YMl6Ru?bzMq#nROxoHEKZfLUfAe;koSZ+E0-(~tT4sb70x zQ4Wq{Bp5Y1JAjuOKJTfrttIx+SjE%>BUmU4!VnWqTD5L_BfU>ef8zC}E zc*F-8U@n1?^$;tZa!_<2LaVQBq$<;i_@exDJb>;+xJYXF8dv!D8$4M;B8tzjqkBR* z@0p%HxtQ1{O8@sWr{=w-v^KyN7`CIc@Y0MT-H_z2{)K+lQ;O6E(^nsqa2YDo74?W! z3$aT<*2GG}+W1NGd(kv&L}j8bS3Dzu*RI2=N^z|(y_KKf$H(9fmqX_g&6BoDkQEla z#DY>*WjHGI#%fdgEE1OKWTwKCO5<07ME=IjH{sn3s<`Twaie|Tu%ZIK*@8PEkS^eH zJ7b*Oya#(ML3E1X`|~5B4MVY=XDHa8^f}0B-Y(1^ct;E=kjTUSdEGC)gi04K(*b;$hL59M$w%0RYpPzG+&+SkGxY zHF5J7b!{r5@UeIK$BW>^tCl6&^kPst%S3IZeBr&m{d0j#a%v{MfWn7Rs--5d=DpQ& z#d6WOyY$Y9*l5xYE1hGZvl$vw12o-tJfi8kAIA?ut#Z6MwzF1xD2H~HGHAz=wl1LF z)$?ME91Q1Ls8NH+*uXyR4k@kOodgQLe5lrQKfYWWgi(#vTXu>z54sv{em!(GP{5vL zYniz?rCL|k)WlUcd2Bu}tpdoJc&xnqkafy9OZ5n8we-BIbI-l?`~Ci37xM_Z72-o3KT0O3ZK0;Y zVUys1a8@J8D~+8GF3cc6*qK?#)Lnzy7;FuJZGZ8ywNM{M#3VZ8kQakU>^nFP;lRQgjae zkJ*fCm)icllc284@!RjVUpWNFc2X+D`Df6xetDoUR^kAw>?+3hb8|)Zk>coE_av?H z{tJ(v~HG#>?Akz=#hjaEN>#$Hm)vr+u^p!1xMqV-JJMk>} zxea8Bx@{&1G&t`FwUZt|*~EH-rR&qau+N7>KSiG1XCZU=;QY z({#mpH`kP~be%T03_=mZ!AmXmuHXfAYq;94p3@&H>es9f{%8(e>8QtVSV6Q$&VUk) zev(ut|Ex&UcSEa&V1{3xb$9)X%=@`g`S&zeld2cRV(meKgZ{wMcs(vzONmm++%Uo3 z(a#c3^!42gV2$3K8!t?2Ed&US64&A0+3_+UH>1k0yvdEGL#COrlvA0a&KU+GiO->l zP8<)kg&3Q1gb9Lpsz8#jL>yiq$)QiC&w?@*dY}L!?g-RF$yi{Ao~Ke8Sq^$PCOk%w zhw0|jgzrLagjfY7n-&wdu8vkr2eV%`f084KMVUC!JQ>8Cm^afSQgnhR#XNY?_&AJJ zH>Fu(c7!o`)mlY4jKu)mEWR`o`or1K=T+_qZFd?ok92J4V?N)XS17!U`1Lw;`w$`{+-vY*W_0qt|PlOx(oVG?~PXNwO-0TBB9Daa!+`X~!1TT}sHE-$BCRSeq{a{6H za1nbZSBxJP<`pX)Y;pKjJka938W3VGn3f)$vS(5=j}|ctbZW^CdnWT-R+)|ntbwq| z+KOf7vJN%jDH+DT?oSHue{)b8k|ki5$<(t*Oq92!C=@OowTEbhN(P#gz&e=( z8&4$pY;v>dn}Z^)Wil^HAMs7U#+fl5YI=vO9HvRqC`o2>#t5&e*LX!5U&Ai zyg(ChtwG*e%$}}M!X3(K;yvF)(h*`A-PzMP^}HPVmD_Ug>|fIFUiJT@0Y2HhLc_EB z(pLTaDt-W(@SHPOa%~^n-H7G?Z>CM+^^YP$qcnjXKud9WP+H1Wx6m~;ieijL2~Y`i z36RXHjFFL3kKssfhMMxq$}09&zDi=hC3-=@DK%GU_DbIY1*e1QXE|PB zA|1hltZPB23jbiDb~}W1$E=Ph>V6`@LWsdKqjZ(>kwf4%T;^0;1_qihWoT~@b)?J> zYjBjZ6rz-bk|VR3QbSQ(G&rPCH2oUw&z&U$l2@Xmc($`pfmq=O(MuUYVstAE&xb~1 z)U3e{r4qEM1I1&z&!@M%#|}ml3tJL9!S7X>^r$Y~E&J zi$Uoh^Ijia0n+vB14!@}D?pU?-5(@i_<+Z5L_Z=&@yof&qU3|9W8tRkflLlM13$a4 zf~^Bex~0-vxfP0qFb)nYPp`E>Bd3wJvy8Fb8LRSaBWq!2e=oe7d9op=3;b>^Nu6`b z4?J60Ri9d6d(4uM?ZHlB5gqFbutiu|9eB7`y{xBRvQWmDR9kT8*KaR#G#sbj5gCE9 zfl9SNHbbyy#&en9P^h}A+GSQC4;+^7RN%bM7feirIb4QjY>l9|MSI8+ z5)~$~6X%+ZUb*iI41U#Y{FSTUv;Eq6Ok$gs>xjCzVpE&%1+=DSaTgY5hR-YjA0}T% zNB#UuNi{a934g0X#rKNbm&rk{Kta_eEmwy^#%MIPg=T{Z{VK_?8zti$SAuJJeNGBGf*oQH`V@Y}#yMUYa4c_KzKV}&VXja4U2Usi0t3>1 zjX6WfBmGEt|H~(5KUZ4v@fMDw;lt(%Gr@UhmEJnqNRxNbPbZ}ciWwL%)oi!Yq7&7X z%E4`Inn@X%zQ{#)C^Z~qOnp3f=-K~>m)BrRMQX*6fvU)RnVfo)h9#x~dd3fM@PbjK z>SQ%4CV^no4c_*N=_4zY2>PaM0ZX|=AW`AeWsUj3Dd{uWVlw>akmX;qo4TS$A)?nr zNDX_Dsy^M8&x0pw1Fk|-^EsN1kAbTiNXx)?-zhp4ZIK4E6^9AHEyinJX&DHlSR#xX zlaMXu>{WrE2El87fmIpgK?+0w`@)K<(xjIkhc&!YCn;zBc-MAfb65at5rfm;7bW35 zxm?9%gKR{E1q(4Vxdx4oq0l4DXewap%=aCyl|J+xkhqg>)DbA+9TY63xFK<0fL-zc z80SwNXxL`ao5_)56<1=aox}x>kz^+p*||R!0iuha@>Sgz=dUoDB`21F)|!32gy5zH zEOACUqkYq-m{JlzRqM&^J54rF0um?-Hj(072G6Gk`m^oIaYu7mwV^^LLSg+1BnnL(k8LH7w|<)%sw9o#G>y8~Jaa&BmRr%a;oGdXCr8UC#XDBtpE zRDM=swq*QGZ@3#@mQg!D^;^wS35F#<{2wvGQ5j@kd7ufR#4-1Qr)hCFQ>rbLN;j4; z@wp+};6XAn-h12-IxXl@X``)6S;rl+sgk)YVW74oOq2@h;9L8;9|RF9f3#f^pH4sJ zm$IA9QtZ#ZgXONo8qqv{*mG~3oljZG(3k|zsjSWkC$%mZKgo9S zUmOyIy1!MXk9JuP1uuelz(fV?lwJvMLQYW#&7&BkJ*5Pi%RRlX`XRO?hyOtN`Jww> z;y1PnvB26pW zu)QCJZ;c-O{cP||Qv3lB5Wd~cTQkL}xsv>%^h0!AV~(zYaE!EiWmtj%ksM&`!?A|7 zX?+!wz2^XrtM{^+b+?jJ${6&Y(sLetj9px>qwx(#_!Vx*x1_>X@OS*&RU$ZN`0~vb>q8P^BiOYxXANc-GOJ#~wA;2E z4Weej34|@y?xUy8Y%kbgo8;#GJwEz~uTfsJZoZDpQQ38aaUIU>~m^ z1i{C2j0oS2*3_Ogm?Msxrt%3o@4y036^YUGevloQeCx|VlNuuakDTB`ljjhYjATL> zCHKxUoeAX-7NsCqD`QH4UljZZ6OWau@TXv3$nZ;H4vXEnMd2uvm?vonUW5>U_Lj=z z)Wv9J`gA1QQWbaMa2Co6*oL4pi1aS!z3!|^GIQ?}6=aqqMeDJcCLacqb#z$mEqCR) z=|9N%LGg-i2ipiGQ!X|=CMZu0^h}07NwL9sYgI`$x;2Y`$8z2SmYprSCY9Au(=sQyyE z`g51A?8*@E=>cZd&Qb7}dJ((#_V$&J)RJhg@we%f)+}HQ4e#)i>@1~5p0|ol{r<#r z135%Ngf&Ve9=&SaMI3zj^wGp}y7(t5-SwXdeh)$yP1A7H)bS!Kyj+&ejQ#m?6}H$} z*FaV1NN(Spj089Ig|{{nEGa|Ym^-c-Z?_@Z5lrY<7>tEY4@|(iK_w3$C8kI_ zafS+s?3CcZrH9Dwc$k(lyg}8IPCHKQ`p?f5GOCH*EAy=}H!pBRqq3HShQjw_^MC%K zA59VGs7Yx>gS~zpQ|m(Ffx<128IE#V&r92 zbee2PE%ilb$%y=?M$_BET+AN(GJ{xpCX#L8!n)=-3}kpk;Z4 zmJnzdnicD3_$fC}bQ$EZij~69Z*ysjfufA?<>6sKEr{&hg=L~3BRl2J*L%of2- zAHv2H(;T09s3Xy--s01lGK;Nyv!blLyw|28xc?!b|7c_eK8cI7vlwjid2!Gx8@ zUvz#Q-+8xgH+nhsR)v=>Dy9&I@{_BBMDm!bW2ikPJ|K-O~|2mId zeVrddWW{01NYEq)Y=iz_Kwe({#|+yGP&t0mW>LlxV=t~dYB5f9J>QyyTiFZ;v!Kxb z8PHQKBTHL_OBINaRuXHl(OI3AsJ#i_oXX3-y&m z#g#U(6(>8Q13$6-X7X~Lo#k`RG|PcFvEG2|&sI-1x`xs8@$7TeYX^1>5AOn7-nwVw z(Mo*7`R2qhM1tcA4#}b~K(vdHVk_1jeKahh9{P>jYpoQP?@B2E+B+fNGE)^wg(JDT=r4EnwMQ=6`HCEOz7_T2Iwl>so4_jSi| ze1;}p+N0gjAt@_LWM=_~R4nV7|B0Lmwmo826IUoK6y{=3A>0pbsz9=Aft!?%_-&Sry4(G_l&L{I)yi z&Lf~q$tpIOLAmx7-=??1Om`~^K-nF&(*eb9ilKz%_w_Pj%hRp46NE2CGYsd7sKC8W z+<_+jO^{J6%0LkB=S_Pc%G1{T^(!t~#$*5l5{F=@4;LuULa9q(*mg)=JUAszco7`S zJ~)`*9xMFo&d}y7_-wlpi2%Qw6l;nx^P=2l_RX`B-aS(~*uUvS-9O{tu*7 zxRmf`9SSIKuIIylykhxIV{f`3qp;!|;u*#+jb5B!9np$LiDZJ!^)X_@cISJ@WABxT z`IDg92x^#McBW_r*w1itsoJ6v&Vl(fYa5K&90d(!MnZGkKa5A+W==^lky1p3qODXz zaq~0+f0koggGhdgpSWXVzh~T!pY+N+a7aAJH%%HqIW$T@>{OW(btv^gWhI1ipi(*w zE16Upi4&^0!V6}JO>QcJdTq;r^ZvC>8f zC~hyKK&b)-n7LPkvK#JR(ndmz8Erf*EoKUbcOg9WP^72{$F<|@RXiTQU%UdZHFLfB z_e2Cp+A}$7=$(IcaeR-2SZa-V^VKV8`m`yku@6dH+(QjgF1cy=%Xbl&iI{56!kq3 zj%6Ao(*>KgUiaDpI&L$GNh~w)kNViY+n3%T8*Fi^Cp@5wBp3LqaQErk@YWChvB+8f zuZn^9{f`qRm-pVs{&VFWTI$5YX6_YFFe6NbjYX4x-0Hr0Yh(0HDb)a?&w^vbOZ8Wv zxav?x^?G%1xgCBI{MD?wOio_*LNnw6KUN%T*{c+9 zx@lHPAW;bnMCyb1w7j6HnZnyWWY}$bZg-MgR9&%9qnB^1?g%*@(dWk-_&hQ8m!$ja zR-6>-1SHBXK_dIw(yo2=y+jba!9%i$=VmoPQ3XN;UJ=BHts#P_Zd%i2xB7Mg`6TO? zI|e_sYV#_Ythze66oi%&DpKb4R+SSa$gr<5Aku)Jnv-CEoB@K{uy4wL#UW%Exdh1MrhXo7d-)p+Up--i35xQ> z*lN8pcm4MJH0=5$wQI>N-S_)^%)!X*c1zZLUP|91_E?rzM0Cv6RY5xCHkWlY2mM&k zh?BMZNX*S1uO63X)dOiWWP>&rYdz{c>PxxC7eBCec6y$ z*yG2$Ed$_V9U7FPzs_E!+?QDr7YFOj5gpH|hYK+qPc5`i{H;<+E(|9R<4$oz!V*?mHSh4%%F}J~cu) zPmUE6I6+ha8$0++Pyx%(Y0jX2EL>}OFuf~%z{Nd;L#9uVXEx}Qtpu_j3gn|Q1C72t zJqrH#xFWGSNFvVDI#|jHV6AN;T^>u3KPyX|Cb4p_Rvg#~7q(+DAl{lr$>i+Z5_P6u zf%HpFe!RI}Z;F19Z)DaeG&l>cdBaSiEB_6d{1B{`y)8RXteudKP>`?_)D~OQMHCG+ zF$o>4GOtV4cYaNYuvx1v?2@$nJ)23D@IyvXF&ZC!$uGm*gK~+2 zWl0^k^X8BFAaOqq>^?R024cc`6A(<#{!Jd3?0m~zAMSxIHIdYZ{?5qu$6AuV-W>qj z;~ZOY&i)=xJt`tuS0lBr9Hy;RshU^=Ui|@kyW1OK6Il8+rI&>IY10%T$I%azj%@up zshGJLQT+BkehNWI_J&h-$9u2sT6c_8$(={A3n+}}5W|qB^|z|;R?_|9@!Ku@?ztvV z=uk)0q`Ip~7oF)!~^U&L2{oVZarT0~?VdcXaz_HU%*d^WL{%7itSQ3=8LV_G;lj zY0B2FbmShR=>YeYn-@cwsYuR3B<-dxd3AYaKOHD!A+*S$9mQ1uNe(Ty$MEZG1*nTk zNGBdc;pVmRZs6z@Ob$x4`M7Jj=ub9TfU;TOo9EBML;yig2+Hf@o_t-P`nRwsy=dCF(;$YpeRgg#ye-QluB+&Z3#Q zm~$+1Q#LdOnu>`Mtu7Nfy={P&FxW!4v!aC(li6>MVFQCJmBa0{+pyZDsiBCfGEAZ- z_?Kc?qdiAEWYArlDNk^$+#avK$~x_!t!T`mfLSIm%vPGdU^^E^Pm|d|_NH}2Pz<6n zv?-4^BfYXc_ZWJTX-UEYQxRD7?5_xmM=K?ggTi_<8EFuDcS}*QnH2ksAKn!XTwM+! z^3O+S?`>T$l?_7-Ge(gimXlojRfpHhsyO0B>%pV;6WbAp(2IO_sS4XWMTftGA{CK% z)%y+nR!KD($4`@Z_I^l}o{iqR#hKB=QSvC|Du|s6Y0j5u3*|G=v=&B}n?8H6?^0?N z{4go7A&YE7@TiZ*$5a+P#uc?lGAw;{8*$M>4EUiS^XYydgdVy{Q(Ylp59WTn?}BD9 zzn*y&jiHSoG{C5luT2sR`kD}>lKkirl7M_R1O;YG2A%=dW` z%}!ZwGowZ6HT8`)^S zj2dUd=S^+oAq3%iCm^zsHjyToj02;}AL%v|rX# z!k* zDUZEtetm35g08M(tC<*9p6aL4FoCiNMTYG-j`Q2ug{qbig~sg2S6bx{!Eqn`-jOEz zOQPoOtdo>EhH-3DMRoH7_{w@te*CzrqY*CO$+sHWWucoGd}AE(4SsJ=)aS~VPv;mt zGx1BAX6BSQ{`h8;v2B#GiC997sQ&gnN=xu~cIEw4l2Sr=`OYi99EUdKU4}`^_d_}N z{;Fvg-gG@5p}ljr{vu16@Xr>bGQl8YY{A+^eLi7!cW1RBTqLm}qUBY#905HfKydWB zHL=Pr{%ccrEX3i9mg7s%Ixyksy#4cmx0@~)K%>4R?ACP%{M*8U@Te-86#E?FKNT^;zO(p{FoD z=rl;++jYI!;YuSxL;o8Hy}nL*SB{2X4~Nj1V>l>mp3-gJk*Bo8RJ^ntz^4z4NNt4k zRrCO;jUWjnXJ26%zwG;Zs_wsFjc0OHrJD&vCB(j|sS?eJD;fujr-|0G(Y`62%`v#0 zrH#=lznaf_IkP+gMxH!dz%J^jM`)q*2$X; z-U6pMP*k%w?~)$q>zQ0fQhaGR9FdfAOi181JL%o=(7C!{QHfLI%=;E$SxS|bOoynnNT#L7)f zg@ye;bGjvimgcI|j01PPwgb~FdUkC_>mt+nQ^?6@v%5!=-kFSZ(zK60@8pg5W&NO4 zSx+*GqNLZ|^@W zURPMmnI2x&*SYQIl&2Ae7*FDBil#riRe!J8z_tnDWCGK@}!sToYAaCt8BbYF!E zak3lgX|HPX6=M)>5kFMqmn;i;?=mIfOB(1ZG>2{@Jsn?zm@oyG0`-Y|%;2ewmj$Q1 zZv#@E39}9c6<(;8DGTd3SXbhmNRDMPNd5R;pji|Ooyza=&`r4AfMu(es}ICIREbLg z7>Kn#Y`7+_E4Gmc1D4Na#hU6ov6dcNo%713ufHDTn4QDneQ|OZ{jP7^}rQIk)kHvdzbsC*)zYj#!%W>tSU#sc33exBG(mc*mt6 zQzCKzyzln@pTZq4UZE)FjnPUdxKD40vX2F>Kz822^+m$vM&eEn-+>eITt9y7sV&IV z#YD|F3EXrj@1v_vOP5H9db9c0bk^0lo{eE1(YtjqjusWtFCfK-+$gyL%ubSz$GO*f z=7bhu7jy#8Q)%q8@(asf<>b1U`e-DpTB(>7c4t4DNF9`~;4he8!ytClQ&%zK?*Myg|~Knt;b=&l#X%q zf^q~?132%JP!Wn%x774&HuM;N*ybTW`U_R#pco^{R>NWOUD^e05S>v2*ZFjlyS_0J zI{Xo_Z~Ij6i)O_`wnf)#207)T4-N8**0Qr^jlOOAs=Y_DSYD;ccRtY9<`s&4DCO_1 zx#D#E(d*d`-{5(!k;Wu1ssKyTrTNI~jSmIrEtu5XH^fUvqP|@oBEvVBoT0SjUI4`}^W&y)flCrbIP*nlrO29U~9GPl1 zgTfy+gslVj%h0%KBe1?eYKB>@=)0=62rQ^+r=l_O_NiC)kHlr9B zG1{~lO&g?o$yIr@Ud->#Lj~&^p&aCa(DBnak8J#*p<$|t6sEjP(&T~={9jfliqevQ zt7AU9;Ab!H5QP@3&^hF)Df~nQ30He#|?lP10gD z^F9ahIf_#w%Q_*(wM?dUn~N!@mbX$>>J_Z=3a$y#gUTcISY#VulHOf`8xZ}{>Z??}rAGx^svsP%&QBO7}MkzC<9OfL8y1Hlsoyw>ROhEy+pM{J-C9~%T z>>Z1b5ng+|x&f+EiRLt8(KRb_O%G&AQ3wkjcnDW)Kn75xY*dm|$NB!Ak$WkJ9zU=5 z>)~>5EJpUGK$q7(CPoNFf)ZQ3unlPMYuYzU zA&G{Z$-jxyL}OW5c{F7Hnh%iSxws?@=~gDw7nBtk^gUpvj6>;@>cIRwS4Hzd_3TEb zeQ;e7_1bZ=m_;IZoKn%f6w0cf{H*_)LbS?% z;tH^99V4Iehx}T8rY-UpV$p~Fv!aU$6(+pbEsXKOZ?v_|EN=XL3;|gBzLz5;?xgFL z(=^fbvx2+~HZ3D>e-fXY(9oaym7Jpq=S;0!bTfI8Bg#IQ_mq&I$1Bjlj(W}U)+$E- zBY?%#TtXHRp5zX1tC$GpWe?=yxn zFjwS914)PqC&fDawJY^*HTm=O$#bD-8L#+Dt_3V68HBDeFEK9=AoP_h0i#-Np6YN2 zK;AqMp%3FZ6T4cQvG}H(5^P;*Tcvtd+2^IiZ7xY@sYSNOBl=PMk2ML#)H+>ON6!GX z_ZeCKNSqXBIqyDSlD^Qch z9m_R_NCgozRJN(Od@Kz(sa8Vjdt}2pB2k>{COq=i$gWN(l2o8T&OB_aClQ#KGW8?f zj6D>!noTMS@4ekM)w?`Z{V2#o$O)4GundW?69BW6s@}}}41m_@cvUNU$yY6rA%z#r z@>6~$RaW&ZLt7cMcQIEct*7-(?-fR~IPS9PTW4Ky&<}`RR;dcBRGF(x)-;cDW8NXr zwNm+9;Ur2-)SWKn7!8$Bv7`T_u3u13h+vJ7TcnZL9|jM14+9qMRX;~-Vp@7Wx!6B~ z!HCW~6;`sPqaV)uK&I0=x=BJ}EP|dlmm!1l|`6 z=Th*Gs&C=S@XWIIw)f*Ba{ksJZLUX85J{cjn6#8^LPkYYoT8`2ivs z+N#`Mx8ls{OBEMFWB3`t$n@^b)G5omXDS~ry?Y8cd30_$(Bq#$@K1l-2$hOp8*NUZ z7h)cYTnR8->g;{E6>N$4cDy?q^4#U-Q+`6>tR^3kOW($@U6ar3G=ow9riZb576*Zf zZp<9o#)&Y_QKL84pIh3_*A6HE6uhi57IHHNnx95m0Z6|}-n#-WXULl~0gWuai!);N zh#-QbeM5aYut72%!>jVLc_me_T3$(MfZTP#f{=j=k+t=ej3Dvn_IPL2;DewmkC9Kk zXx+$LyZlkCtKxrCr>GYyU(Bn%m{t9zp3;?g7j(t80e=+(U$!>8hH=Ci!3CrU%?~yUnm7Ouuv**kusdX3& zVfpRMv#RJE|17Gkn98*LemPE5PE~&5d_Xyijm^;5Q0DgS$@yJ~y!_nw3weI z0uG9dL}OWxQ(X5HZ`nUR*{b_RsS@X#k6XW4vI$;5a>KUy)5@O!8F_y zZua&}89S1JzMjk|>lYgO@$GUv5t-#3Y za#vK~fTSj46HTg4A~E$**IT-J_>>u;yYevqurrJBPwuqd2ig|D70sr>q~~W>l%wMN zH+~m+%1pp*aXd>2I^P-$<)hfJE$77 z2InaN*^%_z;{i0^=EMH>J%cC_m8r0&v>=@)`X3@4y%3YG#6%fb!Pbm43{OgLKkCmb zcdYsTL}Lln5A%O50t$Lk0{!j|BolOaM1u3fKGY$tSPYh!vY6=^6dh*Fi<|n&cv8*~ z(-2;{${2=zpTi~I`%j-%z8+oo^l*luOe}=;KJp%fZV*q%$P-UACMj9xo%^)Ma1Ej& zNJdN2S(P2xlas*3=upHBVmi!AKyce}gUE$?YaR7h?+)O+oVTZE`@&Kcq>aewdG{F1 z{OpoXD&)OLVH+(3l(a7)s+Mak-+b}+S{{;}XHq6xxXz2(vnm(?E>>MG^rtujZNtK# zjVj=}k(L{CsE}A|V91C=E&Gtk^AimG;I@6MhX>{dq|_-|D7-I9XON1pA?BjK8H?so z_<<`hkODId282~EhaOH345Kg{KM!(+SRjUICW8!Oue0C;eyGk#fk4fz>b0r=X(7p( zg~uoUM}2%WFxa5kEz|`s-TW%Q-l^A!&D6`~5ptq`1S z(Gto)N(v4mE)#FxzYDEaQlg?=ZG65wC5r&Np*3u$=78J=96s_D7XdL3+mtN9ia%ZN zs0JNY{KQ`8{RshZBO^*^s8KPnF_4N&EuSJ$XNRrkT;&S6?A0?9AQJdOy~wtDG8_{` z`_o6rOfTchZ5Qn7>Xx)eZ5Hg#g8h(R3by)#H?EhPA3#kWn;lGo4^RRbbrPQo6kL-F z>mwVPh&Up&a8uO>ZA#SdT3XbZmG_oEOa0kR{O|5&aZ=N! zW={D({7F*67@;h6yJq`V((i`Vd~o~N!r`hT%e~)yW@Qu)^Dm8KoyW=KHteC%dV(%g zqw4Xd8vB%Q`gg%lWA)Rwxrh!xO`XvgGbO-+ffUEs;X}Lkduyig=}I5D8^uTndH`P! z8iI$5T26J{-O%z%lt?o{=U&`;xufPIs(d5_s_ac(~7;R%^soOp#^yMYp#pRCTUVQ~7 zp6-W)6&k6@ZJ_Ahi7eSqE_b`q{wR~O8<(N9BH83VNxIsV0@wte#!_Qy9B>qigHHZ^QW$WDSFEdhzY0De)~%qgsHnT6cygGYvQk|mcKZenqyKmR}km5%T-yhHIbwF zOu%LID_+~1XPb94t~hx(CR%kyQ_}c`gT6<3BmWkwPA)IYYidwSjWU(bgWr#WrwiUs z3doGRaL^21wR{EyO#=vG=h+(2|4C<(!mqPa&U2b$NMl5)))D-KeZO5rF>Wz81G5BO zm2T5-w`FqH^+dFFzXUp<1pHgvbJdV8!Jx^gDSI4zqerI7{=8|mlf(Ks`gdtn%q&Mso=;W$#L0i>a(;%paPbE-u+yogZ$qcjDvGmTL4zaJ3Ek zKAyD}`;&kF{Qj_9IlnDAU+45Z<%|ShpV3}{s!UGoGSxBoR4YPpLu)1Vk(mr3IW-bN zKU<(vLw`ahp^wp^pk$IUVZZF`Xs~fXQ){TA8oNt4cpXEa2Opvn1|GmOb%7lJOK%<6 z6}?Wnr&OPq4gkvL&Lh&CSjAL2u8#v$=twRSyr3-!%C5-oX#v1%zVwo8f^I z{_-VESaAq~(X)YFTxDqL^C9va_PQ`sh^5dJr1M4`NMfsrlLLFWF7Ks@PLP$Vmm%X!3lkVHb$)E;+aR2mHeu<9ReTPYr=0r6Cvz-y(uLnVqXTz5}p1gTTDKA)L_G<#d#V3ceI6vR*rTxh+?<lzuL4|^s;q>#*I)T$c!h@-E*zPD-N5NB8~G@L>Xv)X zbj3YF_hoi6LPQ1BF!Gvl-2Cx~k%;H($C5+!T0$M=`w8~xv6A;@A-&!n{ePUVJXZ_; zFXrQTw?>tCH$T3XrAqQyHTeB<(V3tUu!lX8-_|_(d*50&=v>9sGHT>2qo3}dZTVsL z9E2cfaIQ$%R(-lsSn=!C$(vB?wS44n7NW(k}SvL$yCHT%bAYmEha%W#YmY_uXZ>-h(8 zTA%ENuS~zmV&&K0=Z?<%>H1E){m85Vx(9zrgv-jx9!F(GB+eO*Y7;{z9WVEDdAEA~ zr^$AnLyQ^~vfy_5X_6_aNWRQ&FAw$387%jUjnf{>i;INcrqut2 zvqPvBR;}voLu{u)G{ijn)c;6RQb|F?rV-8;xkuyCETIow0vkb~j(AM|tz}|ox5i~= zSUXSi^Vzz*?=gg7hLL3Lr!*|+3FYPGqa26LP8ArbjQq1Y8oU~tzwh=%KgBDmlL+vf zz}N|mNAO?;&u5)K*%OC86Z%{I@FG``wcXGEGSUY5w;oH4pJ_qo>)uQiZkw|Fw;SF! zeYjQa6+QSdKQZNt6%b7`+vJMP=exsyS;^O?Bp5wu-36*#)d}K;MYt9%xLy4!bVWn) z>~nwwX_`Dj9E*(BM6wfmq4l@JETSIj{jE~yAO9-3GzqKeZB4X$3 z!75Ih(tPKe08BmN7g^Uljh8RXo6o9+ya=Le7Rj+o({m@Q$uLTAO4GLChP>(k!gV(V`h?TvI_rmvVur`~Ags$5ChgjPN6SvXqB(!* zUxm3iS%#*hFxqjG`k4B{l?2cqP#O< z!Qrs^D=j1h5<*5sru``2zx{Sv@aa!N(BSCkC?lGx7M+SFi_rdap8HSHglozj`w@o{ zxw!y;aqOWXin_laTNMaDi&vO~^u!)IR zwZ>HQo72DYX};f*nHGyTrID|sS4fh|PW6hLek(S2uUaq=cbqm7=}jKmZ2ux)x=3|A zE?#Aw-Jr*w+XV;Ln7Ht>a`q(TD`Y1m;l%GALBtaR0YjJ1JK;N#^(EL+n3dER874nr zweI_WQM3A1XzncsztyL7mzPI9bU$=SSA07;^-rR5&ieY1b=tO@Fn z=Ip{4Zo@iRDtLg?qESTKup_=LFw;VtyhzRRl^(3@3pU+eNT&VrxM=+LRRq+K0016F z_2vBB+=J?-X|sTU*HQfG9x|tQ9LCK=m7Z&+t%kB~oLRO-TyfnUUbLtOxryI+vVXZL zDR`#(KkMC$5TjpBZAwl)Yt+BlW|D>3K_j8^*^?UhK=Pft*dUG1*Lw@vn7%5UFu{0^ zHfOJ2OS19X1SmQYp9;|FubWqp#^hpqnAKMh0MU=n}9> zYCZ0t_yxU-SAp>q)8dm=K2<}eY8&w=1WOQk?p?H&>rB&r|c*E zh2Q2r)JTR0L_*O?lUlzN`RLz3*>4MFQnl78E=)pS_H=fR5pcOyt{<+Y8n{n!f4rZ8=i=9u)~VxThC?g%=M2tFWy-xEb{BlM z=2<#BN3t1XYfZcq(MS9}8PsLZr`IFVnN9EQsUdvh*UBr=4e#y1k&F8A$oC0T2dK^2 z1#9S7bEP!79Dd69xCZihrn|osW-&D+$?0L=#iTJg5E>wsZwYi7f5g{bVB4h*hZtVH z1S5evre=5l5biwmi6eui`%@tn(VNILlPMhdPSr=7dsoC6ripgKF`0BH`uE&Q)nl9k zPxWW)^Mz*if1TFuJA*;atIf990LBX*LFL`JYV_94rOCv(+A5BTkf!&CdS4(Ai06Mf zYw7@y$J54`uhu#zpRY3pVoG+w7XIV z-^m6KT4or68a?t0`hAGYh8BgQ)ANx+oxAR}f?oH@-JcFKda~(a6iWLyy~(5QdyWGL zW@pPO^h;LwM*lwZ4W#KhjBubW@p0MZ;Y2Rcad^`n^VxYN2nv;zmse<2G3hmDD$?Bw zO>=}^20@ZNx0UJfKsvIZFhLo@5)Jd{HRJq)Wk8plW4FtV?rWe-`nE-lEGYbZTzt0H za+-PsTn7Id@Rze-Hw2z+CrOrU*S+9{#JV65RAuVR1Yav;i@^*tdn5|>?Y@q4{#|4< zgH5U;e2)Wf8u2c|5GPq`g9TM( zc_ozMWcuk?M4b>Z^c#?Xj+&>BBJhnyKi-AMVWl?=U1YTGZLO}sY4ex%4VLeO1cs+5 zF|Cgf#HZ57s-EYneOZnkg<(l_(((tTO8C~cK8>0yAEJB*%B{`eQD~RtGC1^eqQQO~ zJ_muQNh;oJB^>xjCaqP zW`as90<@=+TyL`EBCL}o;`d!fNWHI`L|>YIXOEaC2z#BSWU(;Fs;aRGz!ru#*nakm znt~sHee=FN8WEJ4O&V;-wK8W$Y?UOD4v%{d_~%>v$7Cj7_-wnUz^_ZW>yOC`h!p30 zX^P@q2fpuV--~55LJS&8>&-HGm7<3MMpprUv@Y=6e#32oxy}w^$aQi$ zZ$#ckh#vI_ZZ?w((Ir08jIc|BQ?NNs_S;SUz}5nnHlV1B`L*YNZw}ED+j)^vlLFq@ z$0u`l*Yw}LKsWhEy=krLI#DY=3B?c{rt9_i8(=_w74MI&TIK35bG>V$w{ zQxmI(yNR<&=+}wQ7)#HY~`yBH4l0B;d-w;XIccllrdX!HenwVr6rg4od z6-kvPQ>ZLJkYvqslH|7zg@9kK>oDQR^SUwfM$**OBy_)^@sWy!u6m(AzMdhP;ALa$ z{Q$a7-A`5kozi~s>-6!^_}!8$`1N`|FdH8__$fEpM!5ti!C>yTEkDM(2zEeEn4DBY zbQlj=#jU4=T!W=Iwb|Pmst<usysw_88NZA4B}xjRPZw+Y7)yPz6X48)V<8+vrnFFrB8y~c;JDG#u-^x!l@t_TpkN&H=5`7;5 z?;HUD*c40IwFuyF#`*)O;ZCC9te~+ zj*g{uby^8%Tt=RqjYbw)rhL^^q&>n0m{`~~P=`#&n`tsZeV7^MbT zdd(tb8lnDWr4Q%baSs{`!LhV|{pYKmq z+U%`jVCF`kXFrHCn4zxjjyp%Ye*)`$c}a3ZcRx?sFv$Jq!}f2Wn>|{6=U$T9^0SI8i!6SV ze`(}D;04lIje|B2&fPjD*SFujfK&2!{@(q|;WZs|p7QNtUC=!)c|>62e!EC4TlhFl zY81tO@1)V_N<9bq1lNI8VI#H{jj1D<9#LWibV?#NUF?edngWs3XCMc+>5hlE;5 zwMQQJfmT%8Pj2|rrNxLs5k%uxovg4@9-3H}RibtpNc@G~AgGPJdOR1ekT&=Okt;ND zYuKeae#ayFQmQnCKZ}b)y}b~IhK41~$exQ4iG)$@{vxn4d#$p5?_3Rs!G-3=MO0O^iR9T zuae0k3O4oVjH-rP0s%mFb=Qyk3Ag3J&*cW*o1S(27@i&;vs+u!g_2S6%`rr%*yUOT zQHvRp7UG8e-HvpJ&#$~<{p_p7X;d(jn*S0<`+c3mZ|lNQAM)>fKb0Pzoa{cII`06h zAQ%|#r19HE6ND7XK-Kj)DAE ze{*xQ?$Q3_7mK5#UFkX zSnX1B)6}l#k2h41CmDI|BY%a|Hu9wveZNjH)({got!|1BbhBt%ZRo@kr-qE9Ia`4o zf;z|$+YDtuH21`2&U5?OgqjL(zF+S^`+NT&Z|Nx@{&re4p}X4%kgtVqOXm5B#HBK- z+JBa31nAdQNN0>^>hSm2R2I{5mQmT+5|qgn5{Xfmw8F{Whv;<&@OKzoe3it}P4`66 zz?a5+dwb)HcemsD?6MI(!cQUpX|>)I8fa2UMZveCGYbm~_E1tIO0KN9ij;%@;YL31 zp1=qRAoWqLY$Fjf`$+W8+cMA;GMF0ly(1~Y)mK4Scj0Ok7_8n(QHjgS%FcVmDb=d; zI7@gDiEu=pVCW{hiY~nLUPL02d!b55iZ!BF>aK7?5A;H!qe19fE0XMly7s~1|F)|= zJTlV^;)gihT)Bgbg^F06FQhVf|SqtvNGE%i+|%&p-NFEFnFjrZ?O)XVaUEjD~Dy@HWJ?Z z<$-4OVo5fyo#+C;+nnu5 z$F@ySWqZ7&Bry2i-Q*?%m_FEZuirCtc6L_rI{0w(Yu_-ah(hl_b2#x{0Pzoh@RRCw z%ep;5Z?|=rR~%$Oihl*5+kH}}4#|Mxs!c!iQD$mbB=lFrGzbY~3o^L@3)o5`3n;W7 zePzrT^nIsc$>9}n9(R5G8T}p0eZ8yoXH3OjwCgC`TU}U7hS2yMQUMqDn#qnomYB-^ zVTJ$$O85sZc3m(09Ei8qJradEA-U^tt*lI5QdI55jtJ@YJuL{vQB(T=%))8Hw`Rv< zArD`^PG8nrO=WA}wS3>t{AiGPc)UO>}HJ zPw;7wUZfBFBnpmF34WdrIF=+A`1*IBmb~D3p*$WoX-PE~Vut6w#&Lq+xq*#epo2$_ z5yMiF{c;m#@sHK-Y*eSI$M1OM6o@zqKaq#MDpUr1U@O-tiNdO3PuQ_Tc0TEB$QD~h zHmu4Idpk<$;Q6_c>g?2Qv_L#vs*(IOl+k@hn;-OSixmT-ZQu&4BJy-F7RmqxLRKWbpjVN>D%C2G zeK}kvu6w$JX(A>ss<&rUvsn9{>%Has3ZzG>OWzrPqlV21#FDMFY zZDdA-u8l-zN4ajMR~&7%9OVb=B?M`z;W@zzt+p;$SO?!v5GkYRA&!DW_fwDKEyB+8 z*uZYCiykCS1e3Vex7oi@h-y>zw39zP0=G`lY7PC|VP-#CDs zx97e_=;pY1Bk*BU^K)7XN5{7&W|J!m6}rz;L}r>{>sw0TxXYs3*NIG@Gm$cH$HN%< z{GDR*H-_LV_~71;s&KOfu*tZ~T0^cRL8om&zyQJ9JlRj1m>Um<1ns?Cv)OqZ(nkZ~ zCkH0-#e2BJN(Z4Cka-+Ro#8NPoE>rl`>F|wTH0M^67C)-rLk&J5SZ zVD4qf15@LOc^l0~&>|xvja2JN(1ieC7;qd$ZgE{Ct*EF-#a<{*k63ixdzYJ;bx6oz zP*B6uoaR_~l)kPM##&mR*55km80e9>mp;PZeuCIPD_3?nk>S4X*mhlr9(at4t6tRd zcg?;|IA~#5HzOyL{}ak#wYdvvlWG^t*_Kso$Q`PfeOpEF<|6XM8ifdqTC(>rsM1!Y7o89eIUUaymbNW=~DkAAI_KI z3>+9XVYCN_kQ3^>zu)m$t@elG$|oCT)CPBUDArpY_kq%K1ni0l5XK}zK3B9#H`o$a zWxQQ6yxShwi*6APEF-aLj6PR|QIEF(yfC-7%UyXC-f41I+vp6rEx6d8bCiI`d7Fvv6N6?UUcV2f-P($Q z5uQRkr1lPRve_E97{eDnP1p(cN&{|3k~-=EHeEOl42#0lZ$-!{ur7wsqmJ zZ-2=1aK2etTYm&HF^|IzK=qjb%W<~Z`Cy6d{3-k=pluYquZ-9@+R~yxvHU)!V(C6G z0|rAU2){p8EF|>cqdm~C1#nP6Ay}2wcl!M~_RZ1f^}g&PCNF=PY`LrH{I-~3I20cY zww4(IyxF-2Gw)|JA0!;3)2|b{py%@7Y=92Eu*`$;0*Jhu52L~B1NePAA@I77Jk%yk z+B$nnG~L{xs0&^()w_FWaP4b=IsRAS6g`m(34Oe>FJ%w^q%5*SXtB$Fe;o)>N0oxw zgV8h`06jqsr>Z?Tz*`7vGOu*QBSGnD_dC!F8GTy`sUP^yBTQu=|7|4q9bWWNeCxi} zTlk@jF!F;fo66z6{h*#q2jE&A*S*xaca>prWJOyY=l^o$DN~12U^V>5u#3*+ zt38+d9D@w69nIRWSsQ@Q;7HkzdLrVWf4Dt&4$g57ep#>9ZHhz>ejNCa z3R%~!Mtg1;djKYQd+OuEV!BV^QDDM$!t?@L0SU#ksBsU@S31aFW|hDwWCTXK_HY*a=ERo z?d~M!j8IU+v^BXXWZ6zLmxxF~>qPB<*7%CFQjQ#qXJqgr>9o%Xyo+#x;Wikpl~xzr zs_)A5eK#s-5F|@pf+?d&vLQ-tnlp3Mu^UP3v;DF)(z0yyMIbLo7t+?oCi;WD?DBsg zdnvN+^Jj@_(&`T*j+1nkr*Cc!(FoI|Z~kjyfn-%RTM#*AIS*B;$=3DNe?C#6&jFK& zxolevBP-c39^DOzXbz_?AyBUF+b?wZHVIoeEtXKv?}a*H4YmW%4us(^yyTMB-kzSW zmt7By0H6VMpO3t`^*d{X%>PU}i9^=A8fduhKp+k_HZfyo)(TCe8t(j4s_=v194A04 zy4rz82N1^ypiBX&g}BxS`gBILK)qq~gUF5?QDm5DJe=^^U(|N*i@@J|5iu_=zC%Zu z^meY+{QU821TTN5Y`<-82X>!ZY{3P1Q$`DXvsS$H=W*+EIxTu3B^OLKP>mfPWNQ&# z*Ks?aT1hvX5DiWXac40Zd;Shg5x5N8ZPN|9crv(K^5*y*h%Bih@?pEi!b`ksotkoIgAvqigj?49Kag8w>pt&-PKn`=i=J>OabQT@A^iQ$sEMhell|>iZ zu9LQ(OCJ}?MTWAu?b`wA=0oHGP>A5Uuuj6(w={JipacX3PfkzG569CyyuH-xc%zE| z9~d+=^zZ$=%RzNK(WkM5jtBY&iU^aT%C8%4r~ZJG%zOlN9&l>hJ=E%`U-8u*g-LHP zXZyyg_V>Tfu|rhbJ*O zJE-xdNF?V+I349JoXk2+ibXq-`Kvh53Qac1@(MhSj)k$lNt_?#Tyy`uDB9@SNd!hd z3}B0f{&|~u^cDiGn7^*~ybHVH^uxX{nRD=nVEfhHcN?yM zDC9(D+udD&;@kwBEI&WL#|J@hUgY);kUA_}ToT8|#*P5n=524lI)-Pe50Otd1yucd zr>p*2lEie_e**0pAn7ldF*rdTawolHa4hX8z(nCO_DEjmowL*J$P_sW*p2%%)~1`^ z-#h;0T^=R_uBDqr>py#PXruyCz$kT8RM&@1?_1vBTi$?6|7~+SyVw8`aPlIg4nRQw z#)>0=N(5a8lE!^jM9GdEIp35SUr-qC*)Pi$DUrXj7F(hul+LHwiz56# z(?*R`SZEnm$kk>irij9-UE1;yV4BAcGmNLvgRa8% zwUOhXnnue(IcQi4#BP0fsyXb+nw2I|v)MehN59apo8Tyz`BfWimku+OygNO{Jv>Hz z*gPR3y~Hd@h??q8KlvQcySQw#gJzITXWDBgi0gjE7Jv`vpPT_D@%7HJ&2?Uh*Y(6Q zqrqy5Xj-o`J-=H7jf}*?A>aop(8Uiv@*UM0&kSW4^aEDVPie72?~ia7okvCrLs%Jx zLHycX*Ks9tpU}=kdo_r8Z&u6`)S2))&Tb|;0HQESp~3mm=%b0c=(!XD@W^;})AZhw z{`MDZYkVLtTDqBqlCFERaR~JTLh`WhQ2}7v>3m!ce!}w(dQkpYhZbi)YzYLkv-J@N zjZ=Qeqsux-bh3tbe1W5ohdh)Hj3~&H#iOY&l%FVa2`K-x!FX^g7+P9EU-9-#dkeaa<+8y2#46S{UT$?wPG&yHeYzI9g#9GbZZU@S zLC0G=gVmS^`h?j6Mx}yB@H9{9Na!^&ti?RUSD@yT)DEk;{%bBAqNg|YgHoU+AP#x! zG@XE3X+X51Q%WezYNTW&`h$#?Z@@C*4}>PrTED~hTz&5uU0gO8=q-{inYVQq;qQ;U z00MgB{uHRTeSPAfv#lxY1m|9KsHI#_JbYs}#44>CGdsUnSu(#&`U0O&y_#WKVDEsR zAt{hz<#I)_-X=U1IYMUL$~KXvZ8$_+`#Th%^FP!o5|V@bg4b|I{WiD7MdyQafIc5m zj|udDa04y;S_g(T2+g8VA_shy} z-`fCiUWXHk`gqE8i?hA`{znH3+($tr<`Hstul|Xq0k2dOIR^v7U3@`1PbX2xgPQW9 zR5f}+$=6JZ<`D8{la9KT%M!}q)DnS+Bron+B8)yu@ut?h>-+Z8`Sz}L5XhR}`^|6e z|AG>GPJWt#A#u-meFZY3pOXI9uUrqpdai9pJ5($G+g80=t&s_3dk~rCR+FY+|0P1r3#kr;75&;O$p> zz4f)n4wV3?FQ2-frkvftZx2nL6L_`Ve~GXvaJF9_z&}+PTx^ap08fpnmsh%yitx}@ z;7k4#3rYxjFrf8q1b^_&gdI&gL4*X5%Ad)~8?70qpC@8k=xUc6u*U{4Q9=^Z#xO^+ zbp~M;k+SkdZnyZX{EjIc1EHk^WNhWD&1D`gORZOtO4OwqWJW~bA1?M#m$$>0vO^9T zbzA=_4$DSCUM4D+%hO;1$n$9x7C5L=bE^u z@9wUNW+kG#A*z?nKHYI|$4E+5$k^-r`Lyl`wC?;N*b1DGbsgpUvs5it?{@oN9&Y(x zSegaoUcR2T0ckm?Hv->y5_Q>l<_X`RH+ahvAN+6%&R~7NCcjMsAcj->wT#GXQi97+ zn)Xd+&#mwKwkVj>8@ve^e27MalBLI%&+16Y%%p=2bjjI!g9MDM zzZbqS#m7iwk`eDV^7iD(*=v$;a`G#8sG1DvT4N9W?a)DJ6?uZOt`&?b@B_nl90FIh zxdbO>HlA6q#&C|RMH9}~TZv{-QP{Y+JQV4F@x^E5K+>c6&K*yX}7H&X}I>jTML=_{iZOSVQ#v4R9|6ztgX`IUjZVUmQAj zzgjv4t*<}zMv08-+AjnB^EGh*0Fj0RAGSs^05YlLu&eFnLVtSzXd#}WdcdE7s&S<9 z{+Q755+!;7QV9w*e!gP`cI8FzgPP#&e)j}WmTtEhKM*rN;^W=Gfe)^`L-;8Qr3B>U z)OpIqsYN>oYGs#9+6?5tfR_^*^T88Vi8h+EThw9jm z&!^}ZVI2w#>S4oCig(G_gUzV3nytL7Vr6O+W*XDrH1#cydF?NvobUJ&b!m`iTP?z-L8l5Z(~#fLcwqTU~=c+^>x5Eblt!X2nAU} zsKMs;`o!d~S5c3X!Eda0cOFfE074dcpeFLLI^)*&eEXOp`h>mpbm4uQW&Bjfq}LeU zCm983w$D&KcgQ_rHAcW4m|McyZV*wbWdo2q-*6{&9IhSEZY$n+N_O0gyaDy_0K99-Ax8 zi1Jx3V=L`YI>UJKSGgoCVkGgqEj&xLwrRm_a!$b&Y3kmhccW!D@2Jj|yw#4Qp!^qG zql64ifvF@}^3wYH#5^UXWA(X>xqcuwkR_~-*N;sbt$d3Rxo@cpbTsV(8;nUMn3jAp zn#*cga3?zo$q{cUtnkt_q$kzy-$mAe(9O*4P0Mg@P!2G~TePBA)wF|fuwY|B0cb5MIQ_!zK4QtEAf&KYIZ)R@qq_UtJ*^WE4h6i@V6Z;WMuk zu+JDgu>HQdjm?7Selckq^t6IW7IY<^%aY-F<-kKMEiJ96tlUjC5^I16(RCzzx%+nM zPY$@5zwc6iMgnG^$9TsTn0RJJ`R?PjF~5hjAQo%gy!dybw8)o zUD;pyqW6IEA5?WzM*$52+t1(M_w`t9>$$Z}P1kTJz@CwMU_et#Yi@R>7g%3QADif` zEJ6~rBj8Fi3riWW+%a-AvW2%#0pOcb)0o@ zS$}#OKz9c}fMLHfdy-(KI#=X*=2>c+1EK)300LqY|Og-Jk0AepR+aC z8FapE<6yTZEBdMp9L1;WgrFZ2hkwiToyw}JQZ!g|_acsrcbJ_68M(Q+bDbS&$r3OV zhFk>lj(=GM1?5XoHT=RQk_nS7tmN-;m6soDDtG~mo_-DcZCYrLZ@tDwNYQgm^GqPa zUgLR$ST-zm&zL)MAzT5YAx znH=EJ2hG?|E7QkFf@niz)o{>A_<8|zi0y|8K*=2ku!(0p#71=)9(u*)j%ke1x;s-THhaA~zi~ffvj<{PFf7$Cuw& z8-`)JrmA&<>AM|K%WlfTsAkX6PCHb^t{<5!ooubL#ave~2o>iYz1%{}!rBOW6S1-s zF!eLbe>+7z3B=6e!1;GpR93Z33KlZld3nvX`zLfv@u@xg`B!XdnMaeU7ctCkE=tSW z5-Mk`!=#s-zxrx^JydGjQt;K~2h^CNqM}gxf`H^GGCzd6WuQ}{2TEDM%ldZN@82YK z%M*`}d>R@WA71FYyE`^v;Xvs|$XcFnTQ})#E;GUps%l2l_q-coRAl9Kbp>nZEmc^- z`q??Ydl@|kYp1ovg@qy5BMI*3_si7bCa$(Ib2o0?;9lsn)lU4nW&4o7>RLt&3Fv_b z17|iXeE{8|=wTIETdUk142FJf+y0gD5WM5m{oYcCmGxtGdHo|ec)m){&kgRo)^>vQ zNO*`VJhE@kkK!UTj{mEye_c&Gn04Ki@H(v~j|0SlJK%Q5L0Na5j^s_=Ayp|R@w0Ru za|yQV1U!}#Yj#n#LSE#+p?DMjY>DYKZ3Z3!UPj?bBwM0FncR@sL56mAHFZ|j50j?# zPqo#pt$>JqG796_3DQ{yM7n+I0j`TxdnZmYP7a~L)^pFLQ?5@yQ&Upby7W)DRz43% zlM+u);Sx_}PZjgq+X*B4g|)Tu&(D5a*YVz06)J(TnxBVAy*K(QG|B;MTw!S`Y{85y z@DDV8`=|YMW-U4~A_8K!v$JDhVDK5ceQWH)Mv8b$nE@kizfF7dc^qTJ#l`(ssi305 zs??e72EipNs$%~Id1#l7mrQ7M44Yopz@Vh@S9b8zd(Rc%nVs9%m^?dUQc_Y9dYR-L z+`ndY!|VV7rpHP0cgi?H@1n}jN7H%5H8pWJv2L;7zsr}Zdw6;!U{k3F4ekh~9Ll~|l`=^>m485ia`=5RT9BBra*#5G;GERPh&=K;%lWRQ+oy-F2 zG&xn>PL%lT2DRiEnDu|e)sADDu^p?cOc;a(oIC;&j)q-`R{NbmgQIF_7-!c;{I{GX zD>t{~=T8dyJO;e)nBRvGq6U_FH-W|GQu;XeAD8J~0dprUKzctQz=dr97CHdp1IlB< z&4&Z(!{)zo4$82|E#AI7x&YjhfXo)A`Bj@!h)c?qPf^92cfD=-ucoinuM17*bs1Mz zc9DVv-mN>C_rs7&PCh;x+~cXKsU(HctLFfRx~lz+RricHVQwXJGqcc!1~rhe|2I_z zazlmbJYoBbs6SQaW>gXkI8-|i)DX;hJWP;m)tH4Q8eegwO`3>b(xXSj)#@vFivBQ+ z6!^zCG_ZRZf+4R=mrhiAaNW@;2hmGXgW(@phj{gbf@62Md8r~cVSYdo3123*WmXHQn3F-dn zUZl$f>245d_%F;b!wj*@d-vXRzBu2bi(2~YCcp-vqGs+WnnnmNpevHKcEBlxs|7Tn zsPV&^^MeEYf)V6awFO35)e^X1iKp|WB~R!(7qlXxb#3>JP;S1{t<-e_^;ey^=D%*@P)!jp!I1R1w~i63u(&mypzgxgke{r=VF z7K4K(nMK2O3q~GKD-~a2Z!klI6E4dd(+!Ro7L8Y9lz*JRF1#lqLJia>gn-xDA|;ux zwM)1#9)rQ04;HLq-*91qME7`S-tz=E(F$xM4-Y}GI{?qB`i8-z$r(|OY-rpwvWIV#pERnt z_ywa*Nk?v1zRYhpe8S^?IXD3V!88$yf?fEpTypQS*VJ{&+HrLCfBYH~UqZ&xJT0Kx zIHx^XH_w1qMT*;V`CQw=i9Mt$ZxA6>cf6<@)+=&tL;OCIse%=Qjf|Ft;p@Aog5QcN z(FJUOFWm{bIneb4pJjJXPZJ4c#dRkUOlGeB9Uvi5WLneJ)ho20WY`3b+&_M|ha~fw zLj}!6n!O=86bf2O*EL7bEA8$cSu8*JXFZs$udn0a z;;p&1Vn+5Hu(A#|Yr?5LRqCP!)=83oK=T?J((dl?!7;7K^wd^E)#U2S<_|qXy79BfdZ8m8t$On`IP2M9yrf@D7WrO-dzG1=)D* z^r*g{zQ_@Id1T!^Yk!IU3t6MW=YpwfH691C3G5UJ4h>4v%54&(1rg!LbnkQ`=#?y# zWE6B;GldLn_t3&>8#L6^@}WZA#WwFtGSifq!7-WF?_6aJ|q2T)}3 zRHEGm|D6&4dHC08)d-J%!|*h3-PEKAwmZp}L{;VrSS)O4i-+*FB+WDK(l2j0<$=fr zEb6hb@pK+a;37{z$R*5PdU$xiV6gFpg&`mSNJ>h^Cd5@2<_AwCJ{PE!c+rs;1nx|> zzOi?{#E$VdxB7`pZ~#^{lIrO#R9h+FQC3RCvwl@B1vf$Dz%z{Dq)AdgRFmz+=^OBP z)i^ahEj>!SNMyC-ofgCb-l>h3Y%dF2Tg7{B0)0eDOFS+$F?ezA){^+imJCjti+Jk9H1q}+%iWbo6)7pPS0pMkV-RJ+1*~rWUWu$KhbjrEC8Z^m z4T=!gdld1*1(d8UL)z~A_|eA}Ng$oHCxjT`X?-Lrr5P0-ddK5!#~82!Sbg(a z!+do!k)Zwd?O?SP(B2)3i;Kgb)F+fs85+M6nanI>5#LHkPvqnC)}{C*3p)#o;Kz%; zm!}4Sr|BtasakJ!dxbk58sBHitEu4vCu+8sM+~UmnPYG3h}jSFkX8Zt9+Ybi)bNkzTSn84kco|~(E>2aU+oY*e zn=>Lle#tMV0E0ttMC6ZrZo-z^=+$}10zxJ#_s2gQeLkrEgkHDBS8@pF+uwQ`+lR2q zv9hR5iPJ<&88x%N*+d($?`ZeDGqL2=a@g93jeTTJ(~by)XF4I4Us^qUj(ka-8sN$r9xc$*omT*)zNUe?4-(xmpj_+E@G zC!}-LdF7l^yWJ9Ge<`sN8KD-WR-_1mlL?DO;U=d$BV?Tdb= z5tL3V54XpFfi!xx0RQt(=mGd}u^Qo{4Mwm393LLn!eZWX_M0C2u-Mpa-t9%RoZhr8 z-jx_TH!o$2xP*XXU~!QuCntxA5R-y}65;(v$Kr+(wDghi4`?jJa@GHah7)VWXC3Id zii_4|(I*yI_4M>oQd1qd4Ya-oJ)gsh?D3MIai>dE9iN=Eq>)06^zNGUSh{%ygksak z{4V-Mn$PlY2Jd!h9rP6E1qdPgq_$^E#nltjBG}ZUB$W2E?Om!dOA$_=jSQ~pn5)IJ zzjG(lJK6`tw}r^|jPV+>T9j;{e2L*A$;`^>vuz|~Xa8l%5CBJ4)iepHz!aO17CZX0iz*jp_NF&G+vj+88l$O|LrC#G}Fl9g>yvadbHX(|c zq}q&MDZoFydg@J1PHpP_Ct%(69)>H!6gD1IWtz6QggkGbUREsY`R&v zxl-mwh5sFiyjGiXZZ;7O2`#Y~$@xV^IOfz?1$7~i1-6=W?m28|BjYaY;0aczv<>l4S$+e3-3e4Iy)EjUSoieLCOAH$Y%I?!-s)Mo$G~^dKZECc)q8`E&G0C> zvZdt2Xhxos3+x9hOskY?&)3e&B`3LyfuqN8s^slY9;ryFj&aM_y6KFZZzbg|{eE$_ zOZ#GBSYK3Uc^d}SU69{q+VUfSBO(xlcL9=r^wnJ^1<&^D%`d3}^ZG3pGaPpLkwb5Q@X8ri_1CpD|lB!6IeSTv{cGNJzBXD>6Z)_G&l#&^VW*%KRkNM6siY zQ&5zfJgHsNhQ&x-9Q(Mh5DaJzE2WAa(z*jOgdeALlGMVz|`O9B?h0`KQ^K!_V zJ8F1%B)V^nlaqVxl+09?(o=|+PXczkd~5cwlkgCgu;lh^b891RHJ^U%w22qBsyMvn z%=G}TRqyrG!bI1^0F9Ni`BzEbOKn|U>!Fj1iVFGAzDaE(V`Bh0ZJzf2qSNrmNc1n* z$=y)$!Jk@mwJEQI!RJoxhYcf{+=+-!s}@kKoSd9IJR;`SH*j5SPV!_@x*X-geX%JW z9pFVtR4&C${^W=ti2UeMO*Wfq%fK_t7;vn;fMI?EQDF1F4CKA1j%L86W$aP(ETs&y zw4r2;30WeQW{0N!E@Z`ufm*t~tR=+4$f90#HjFLIqnlF7c6x@<_Zx4;Sxn0j58JuL z2|@T}2i=!wckm#YfDT%@??r;6J3mS}c3PP51@4P*qKYC$HqqpU&UQNwPu~VEpGEUf zZPcZt9W#3@5m3~XV+YS|zerT3Kz!|HtmQ&xnhqNsU3DklT6S+uek_HG>A zrF98pSn~0{3ZB}{Yic4Zof;Cn{kMrhEsFt~s0A~F0YD=G?^f+F9DKOUAAX0%mFD`y zK=(d)9{x^EhPC*P(O6cKRg8`b9R6|4G)qUzgQbXfENg)4Xk%jo8ylNiTy)@xnRXF1 z-MZATI0n%V#U(Cx^DfM#rBU*Ql+6@@p3DB1_68sH(;Tr4BJJ5W)91b%IibB7ing#F zqhYK&j#ES}O2Q>W*2L;2z$PN13YI7;c&m!Ca)LTON~Y1D?bg!HD&&htXg@^cl$%>u zV(dRJpvE6mOwl>WlL-Co+$32ffLn%L zdD!~%BjVSw#fM0?acnC;h*JU%1S))0F4WNM;wx20e@f^c1u z^`c4p5!y+QLL!y9SVw|1HHjs27P)$^4*fZ$k77<$33aw2|DfFXG4Yi_@Q*zCx+eStLq=_CL7YA1C#L@z4Om}<)wf@gW z;KMTGM^#i-0!lhaUbU5;=?6B`R@;_e*A3?zo2U!5cF)$WtW?$1+}N0tc*GA=Qc^Sx z4WkFvEdW_|zC8xW(oYD+6lLP%Bzl}$D)ba_6l|J0$)e#N`{iSH2-EZPS8Jh)7`zNRaVafvK}9MYw3GCpfH&z z;y`SM$mb&}l`mhKOe(W6u|`&dy$kK?@oxVeGeT5d|Eq{IKbcf*ibXO2Yfev(xTO-b zWO9JE2c=$r@2j3h3w$FiR z-&=Kslwd5@Ygj05l`9A_&@~~ASsZhB zwKd$WO`dpe!NP2lIi*rT_xwU^R5lMP?ndHgS{|rn7-6G82h+AM+%4p}rz*Yv9UJpK zV-vN|?Ob##8!)x1){gw>5?*maRtsRj-i&6FQx^7TC zhplt4-Q~It&ofnv7>o0Nl|h%j)(A$AdvKKgT6IsFw8qQ2xkH@X4L~La&E$)-k8`n7C)GhFuWE+75+3XGRN*+Ac#yzR7Ybi2)ez5fjc zW;~xpkt8KYyStIX!^6X5>D9l9$Qam>s;P-btEy`1>DeGE&Uv)7wvgp!~8W-2y z)BR^%T`%y?m8(kuQfi*sb1nL+WS#~7$i~VF2(q-5(nW>yx{GGH7Hdkc z_4P&%$)C$A7Ctr=U?rQ@KrsBe=-9Z_*hjK!;ijyzZ{e}jBtUJ~-gQ?m+-}o+wQg0Y zze47|wY4Skc?(C6c=KR!A#7^52%J)H7=o9N-=%h>1AD!rqm8+FCsa1oR@C240bTa{ zqWifTpxjoUp>cUQ0%jTT(Ll{H3B13EjgNKS`fCrGlZAFWjmq~aiYuP2hHrmV2a?=^ z^>P;=wd$NPIjNnkzRmtTLjt#diLBc|5rA?n7=-$FtL_R-}w zf)wlFu`~$e{aQFvQ?|m=MI12~GsyY)r(WIos<7k7oKJULx0gq&OUFLKUD60ZajhT8 zSarLZW((<}^Zj>JkCX^0IR+AETJ-et^4Q5Zk6^tZAn*7jBw&D~oHGrS1QoFIm%0Sa zOK@D-frN^wQgtmVJhz@W;Y#md)e`M1<`0pQ72K$_4cLB1%j;J0<7k$iZzA z+PeZ}b*I1o`$j|a*ca%!O!{BvuM%d!{#JBonV7&1Bk?8xS*xS*5MypeGXsZ`)6m#D zIsHNo-^4{3tvP7h$$?55l1*`zqjsw{lSog58u}P_UN}%kgUfF=mJ<0Gc?QilD_zy(1h%$*os0GWe(ai0;!EZiziJ*Bxip=Z`JYAAhRP zhQjE!U|qJ}BDDg^0{j7qh*W*%49Ri2ax(K&KQa_C!td55shA03WWWE6vKEVrvx)w* z<-CTyk*HX#Ir?o0x)eOMDHN3GA#-x&$27^7!Z|azc@YeHzP|@L9hP=hj6fx`%k|Do zDvz0jL941tOG+XX0!}fWN&bDJL+P)v9jqDfs;8$1a9RHjmlN;-O|4ch z>VDH5jt#^Dj#gjOllPgT-7c7sQ}(7J`~e!QL(K$eK)UEWE$FWfmT{LcL{n7Y*sp)L)* zjzCxx7WyAOHhCVRsbGW37f2Dg^(edD7=pswL{SKPtZfoh_XG{OS+$6jC^aqXG~1-( zdsADsS2yd1jw<^FY6uhT!z|3q8yT^%sQc*W+nH6@b?26-zI8yp`hYP{BO}ZAUKvTw z(Zp~=d$BQ)Mo-0EQu*IE5F`us7Es)$g%9Yg)jdGfo3Hmxzc9-h?N1SPDskEVrPsdA zS6!v5?*sNhC^B+b&x`rPhHS0mF7vO>BC4S4#ET4lFE9*3Ex_diU6rE`k~be@O~_C<~afq|S0yGwJFoGC+E5YmIM7aEQMumQ;(@QEB566W2D?g~8XY?CleQ zx)c)=Lqy?=2w{`%R(`VMxSqtf=@79nKd&lE&ydwHg3s7q9jw-?zL7RsZ%mFA&7RxEUB} zf5VW-bGZ`op3P%2(DiiRQfO7HU8ylnGfF&;nwmC41YS;c2&}m)2@EIB#1HS^K zX0M|Rt+SIS6EHy5Yo{XMOaMBZ_B#Uw36esv(RA760s}iXBdx`#96jS=W1lqCx|~nO z9%rABq^&v?XaetC4nH98D2HIIFm~GK?YZ7DO6FJswn_8s$k&-Pd~RSIi<%pLJcO1E zv!q`l!bw9#r7p9DxR4Mk6%DCo@}MQyPnt8UC8ph!7*Jx*v*q+suUbivG2Q#j| zRm*r9$zk6=w`Kq>0?Y=qdmSw;dzcb6b#X^WE?910ZnJTEk0ViWd~#9M&5a*9G}OVJ z+i}IxZ)0bo5U9e12Gr6&3zq-ccy7cZj#&wG5>obIaUUrule8M0I((FFS{#wqo{hn@ z2~{#gEqADy)N++c^KRQKVKk5wIvx$vqb?twgf+m=2lN=J&j1Hf0GyjK_4xZU2?PUfZJ-r znb~H?65(cHEZ|=a((}$B%o6dJBjx-|JUe7UZT-;qi%cmB0`&7&jR zuATi=KhG02sODSML2>%I9~T0|zugVN=AZ0OcHhx>#oxmNkiB=c*$jNV>hA6t&|zgK z-}5XscJ8emtAy%W7Z%#4Tj48UW$Rr}pnlOom#Z1@pWZe3m%gvs+b#Q5j6_(go~`z; zKF2#NVRENqNA`4CGj(@`qL)=v^sS#dpY>us3DZjUY^QIsfm{ysH~=GYaQ?0je$eC- z5|ihoDXcF>O^5qy4T&iL$!YU?J9m5jbRDE#my37X62_j1I3F7?-{|`j+DjXtzgZ}J zIon#1+MRC=c^Ok6@nip{>%w)v0g1`cA}u`L4P*$;-vyiCRJ@$8Ku~qMW6cWZT&4fw z;W{71iTV;-+Gn=f2=`kmJWZvQAJ?dy;JQ5NlbSNN?n3d-$o)}l&9O9VZmz_MhQkji zGei}1fPjFLn-TzL8@Q)WDLf`k<6U3`2D8@qJABiUnWDI;D6BN#f=J`xES;+9pP1*t zeDKI-K~qyk^#m`V!i0bz)a1O11hC)xOfZBu4z=a5va$k*`fF~khMXMgd952TA%ce8 z;6+7cBRC|0TtpRkB&wb(nk<=WG3vI(kQasU`48BF=MeU}(Q*#F0u{rL!7_6fxyZCg zA;$j4nI)#5DI4xA4}$Mzg0yCB^HbsFF&}4ttPJGj@GFmC?W^kgGs?Z z%@uf-tps!}N!_wS;%X{vQb<%wtO0d~bh}2GgN#!0|6MPk?0q(7x!((I>z1OwL>WtK zwvqQA5o&g~s5_gCL$oG`7!wlA_lF*>X4mQ(#)J`*qzL{qHB=B7N;{ZXRXg^1 z>EZkDJn+@IZ%SBCZ<^&|z>X(7JNvjtPD8_a+sPev+xFbD3ef(6CJ%+O1EW$|S@dQ5 z<2}wZ+zF7ww9<(X?Ul`M_Y0gFUaR4x<##QxZDo7+BraA~Y3qxm^IN|N{CuctY}^D0 zp@}#jD^7Xp55d#|D0+#C8*3f+eTXP0#lYSaC{{yE==$Sh;jwwE5iNU|myxpfvwj|% z3)f&2o{N#({L&QBzXVfb~poW(It5ws`vFCE*nih#l+j zxvIhs0gmjt+)o3Crz_{zoY$=)RLo-hJ>#8psJ6&HWmTiB06EkN2v037^}N@IP7))G zUxKlT$I~&hVa)J`AJ+rn_>auRFuNRv|5Oks|4wyCmn3Z*woiOuP2xha{$bU^jl&b| zfMzuMCevwfUcS(upQCG7okzhe(}jMcZPTc0=4l^1i_vcRUc#?P0L z_R0$x?s)`qaqqGEFDW& z_pI{p(YQA=2XXeF-YOL*rM=B##R7uI-PLkHFX_>32ywRmPJZOLK{gDath$D}agaIo zxUv$nb7h0PW7qkqeOd?8(cl(241YOIJME{;_I(8s+s)$odlhUVDv6ZM5$j<2ce}0S zvB;ZziGx1nyYkXASU+t$8N+ys893BahVo!EzmbvaLc z*;rc9ks8vD{Yq%$Gum0N==8(BD}4IiTqU+I^X7jh^n(SK{X%-L@KJ?3a6elNVY$#z zYL1M}Su$`X=g?gU`qN=cEIeqI=*`OA=M$^;y2k0+3fJmn&I)Y*wUM^ji~j3C2f3`2 zj`}H;@Ht@badUb?LFDo8Iw*Mr5VGx@V;@q%`g+AOUOusyX^*}AeE`?CfMIoe<9rO9 zIuR|6zfLR5%2t7q&)wYdw(LauybOvfH7{!H(-g6pAWd8`SFVI%Bj1 z=oiiiz6R`Om~uBt^5AK7T34ZM_1BtUsXF#Umev)`AzM0|dXtU_HM`NaSvNIt6$==F zro^?};@^h^eD4#hLL=|Kx74-`x z-oG9CQ^I*GCQJ4Lp8=Wb#hl-WWsYhrr&UYE@v{o+0!|(aHr#y?IiECvTw{|ahsj-0 zW``}asY&+^=Ma9Wdjob34)1N#&o1z+W!29Hq@P5t&~DIg05j+A;qm;-favKWW@X3f zO*u{o@2_v-Dj=sZ-VrzDKq`t+*V;zcTIJ*%c?o7F5}BrKagLhd_^R6e(GD9S2H}&0 z-<9)RDpF_r<)7O#z3o{HdgYxEed0G=c!Y~OL_YHC-K9Os1T~b_)AsPFnsfLy* zBjNqh9UOEu8ympgH%tj);14{-13Gfc%Glb68AKsN@^Ue4b6pML{j9)hix-3o{^dT{7GCkXQ{!d7 zqA{wrt7TYq?gM`?aw9%)5QLS%xR3|i4AOFqx3ZivKFL~th{TaLEXG?PhwnpOH-hX9 zH8pFnuu}z@j#B%B|0AKVAR(zy@0{7&a4iX6bJx-Bz_$AtR5-j2G@0qTIpIznJ;eDj?W<(6tm&sQny5c?i91J*sMR_^lypaQjqSVH zL}Lppy(+D1$MuoQ7lMqsq_ePu_HQy{>(bt(;L`Y4q%f6DUH@Q=eRYWfg`Pn)0yAq% z$MQIU7fANA#o}87_he z7^r!Hoal|OxAJMBH|0zPkszpXl>+OJGrCaZ)R`M69VBQFZJzy+<=l@Np@P<2FIM-T zAW_Q&)6qp>rw7wf?EKeMx-7@xiX1~Hycb`%cxOE$tl{TRjPdOaYwKnO(NQx^pX~@@ z42%XlIrWy*@zs#YIp!p`@%gE+{eOsU=9$h`24CdNPU(h`rgD+qH5uiW-XL9lrlI?^ zOzAprTmSxN#B!~SZMTmLeYO18nZ3fsm}qY9u}$WwJyA6(H^}=J*wwEXA?9zRVtJ*+ z6wOQtW0n$=IX~Kbv)jB?GOZbh%lr*5RaB4rblo_Q6hwm_poUTHET~pJI(+=n7at;i z4kv@)?#)=f@C|q#+>U-acWl-t@@7nj4KBj^GPe8^@EL~m%&OSIOZ+v9H4(p@ zK_Uohr&B%2483X)cBFep$ywy^zP}opDG~Zc_X=Q9q8}tc-{?&tJG*XoqcmWUolPc-!nFl`w3(N=8 zxwRkg@DH^R^QNY2+rK(=U%d4(uqcaeHmuppv7T4_G8}ZIPvrPim5P)ys<@Eam}bc$ zEOcD+F^|MYJfp)o?QP)p3)*!q&?!F9()XsnQ?)tN!(?z9P*$Z|YGI2$<$KEpw>uN2 z?%ZU}Gw`W^$c>zdyX#kF_LbZlv>m+<=Iz5i`;)h;~AQ`Lizh7l#M(?aa3%Rk#dA_Yt>%7Wox--dg{$99P=#+|Dc?_3J@)Q)<#bBb#TGeGzG0wK9@gLdeyr z850yqmoX9SMhsoDW8NgK@Tg~(rvG^147WkN-G9f-a1d7oaT(kcMuGz^L(y0buvN*I zhjdyA#~OU7yiqaq5m;1G3H3vEDMGqi9Ne|+E!0RXaV-#ksy1fV<-z`TSZDYB!REZE zBcwb4!)n_Eo%}d{8^t`!X0>#~zgMNu{u>l~v28%9itw*ZHrr;VX&8E{KS!?%r@*Nb zefPeeys=X9^K)jSUCPZ6j_2ey_CK?VgPoEH4Ss!SK{-LV6F)JQjY^jz`S%g;&6c{b zxwYtGbLyq3J&z%$o=H3qY8X4n6u#s8(uIxgFVl(BXC*dtzS)xcG0afY$*99dF!el% z|M{ewR+7#-Q$JebP%rV)whGD^!ifug@0b^P#T-*qjpu_fPk&2F2UTavIXM*9*Npz( z9Rsp%u*5-^9}&GXNg5~Z74gLE1!XE{mh)~i>uxUrU&EUZP7xdKVbd_C-D}q0lX|#E z@7TSP$dGG~31xe|AQf{0Q846{9!1g{CS!-k3(KJ0f@K+ugX_MLF-Om^9tbj;qsv3h zOien5gn7}?-GBINNH3=@GSRhWgXcpN`P|RbG&VTtS1vsII{DH3lrc^}y}a~qBcLOw zil8;dnBWX+LcOXYn@KQ!rDgpu>UK`VxyZ2D2Xo+c580jmqcXxcaV@JEu4-LG^rg~D zLbD?JYG*17%`B9E0+u-BO74mhxpWr8oX`94@m(l)=5NE`?@H(5~2ARs`mDj5yLw<*u<)3wx~pQ9y1UctoN?A{@N zMD&{f`#IoL+t#2XN&4@Nk?#`19qPF9k-)IQx+77c$3pAE8^ec>9*zQ%XBRy8eFmZ@ zLMz;{w#i)vU9Tja{?MTPYI`8;=-pcU=qzYaL~7$C`11T%JWfmUrp`MM=XF7Ve>+}5 z`Y0BXFAVc*&;%B zTWM(xMQLeT4Hri%TYF0YKnO4F{kr3_7NJCx%D=cJl-^H7*21QT=>o-LO-~B$E zSFewe-fy;gm@|R;46h$Xh1Z24q7dU{8F3TaA79AcN2XVN&zWRMO92z7=Bh@|)c;aO z_*HSB#*s8Sj?dXmbUSglNfnJcdYp9ftad}+=@YXu9Yv?!K`Pj-i?Irhu0QJJt4 zWHXn^O|AszCY~1@&aduQM@AvKkJ%+H7R@+OYiu`K9Z|sfA6JxT$~7j{ zEsAD=NOuVjGk)-1G@4iC$^LF@5P1`mD#A77H6-6@CoqQU<41QMUrN&2>1)Qr%prQA zd3S64`eKrxQ|-Hk1&jTpvLTS|hS^59lK;0XlP}KNd!ehN_4-+3@bn2EI>F;RK`24M zhN`wQr12RMLB2xb3uPTUhwtT5OW(ifX<|I_W{Dan46%G_P3uXe8O8qTQ9w3ItTZrv z@H(){%EuaSX#uG9|Z_kC#v--0=G5a(5b3Lgqz26 z5^gp!ag@Z~s1B<06pM9x8;AJFO#t#BjOTh2=_hK@%vJ1j~%ietC*io z3}hl+dPEPkZ4Al?{Eu<3JIR;A&(!?(_zGiCu79>~L5dW1kdr_nHS3R52g+NkZcWo( zLAUQGnPfz11j%2%3zCbP(7g~(TV4Y70M1_a6l??lfFwXsMoP;I?kEStZ}R$i(4=!U zBCf?cttCylR3SS$7X3F5*ifykw>;#*a|$V<@C!(qBtvOmAxup+Ok_H)aI~0(en+H* zqBnfC>E-cyQQ~s-XoNf9^tN~M_VID8b8`Lkb`|39X&EIci^dGcn2(qmgs%awB>C?@ znv2oA3}-ySg5dx5)<3Qzh5rbc;`;pme(0Zf5TwmV1_<6IUK6MN$6fz%K^dH6C&GVu z)c<|%N>C6vU}Zyk&OqzGj^*DMAOoJT|HsifA;5;?6oRAYsQK?1{QFa|36KM>MF0C7 zVOMlvp_ajQVM%;wm;E2U1dYEYdHO%iff??9Cn<^czbpB_+x36X>eZI=_GduiF(_Jl8`s$b1}Leado;{=`hiFERHs*U$34LjWr zwSQIU;J|JyV`Wv!L%L%eG+|hW_zU1P9MIrn@t*@q)qz)3RLtbDK>q&o59^BaAXQ7o z{b6-yp?aRg+2tjlk~k4GF%eg*OaqQdJ-1I9M?4e(1>1CgssI%oop&@OB;>sFT&mUyUydfr$T_$b=Z1P z`nASoSIHG;-Xu^w(^#@MbfjMyHe8ZZYp~Au|32Kr&5{JgklwS(Ps& zDgKX1boDC)t+}!eU#&FROv4{9Hwoqj_>42DWk<@zk!L9cId1HF@UpWlDek}@}^Yv!0mB88i(w^nC2Y{pGtQWv;&fvxrz zEyPmhv)$w4oR_PIj%+*)1WDmX$&t}rZo?=p35C1D1zYF&q39w)iA2))4{V7`yZy)2 zhkqAs8|Ji$v1xpCHHbz$9vY%T2ydG>a-wxCzQ5gxT_LuX%sk<5-* zMYgXwNtdvfKEiAv)r|DXN$?l5TOPi#R4s&a*m>t6tddAqIzVsk7GzCPT&c_e;S%8fXUq`gj04ZS{1OK!SmxODm76>L|(BrO)jT7t~Z z<`QY{B*4kO-YY`RV{m~_0Kl+SwT!@1uFO9dZ=(l@{lFg3fYrkkvqvL1s9PT?o6psq&r4nh!g4RSoiA}rxnA&r z_oF5%wLm!~nfcv%C*bOI=SFZ^5z7bJ_~EzYkc20iN?07zQ&x1M&` zMI*T6_PFx+1mBMDBX=;Xe7gHnQLVxcAWIs2xITVGdVr?@8~rOD;$bc?z`) z%1DkTWZ6u>k&*2}c9~?uKgA3`qYc}Xl4z+o@EyTz*e2(*5F$qtZyKM6i#7wIYfjP7 z2L0X7(uxH0?VnO#rpzwSSBt5+AAW>_JwEZE79hxNrMTmmXaKfcP{H!sRwJu<~yMm zqvN{i76#-fW!a!8Yd3)S{n$0QPF40E7PbY6UWOy$g;@Xa(`raTp2u1Oq345fvq!^B zdHe?mz!zveS+6Ta_~E5rtb!>saPX;;sH>K*+V|n=VDG`EdE?2@|N1v9Xxx0}2XOc0 zLCnwrad7;^Q)ON8h_CRM)K7t7gS$678>!2VovV}yYO=&U#hM|js6qoeEGCE-FXNmh zI$#|TE4-iXnfzb`uB-c9VWFe=y;$b^ec|1hbg5`iZKKl9oG(}tXFy*G>KKR%_3VV} z$09tN%9>GI?hW^8x)Br#EVu^RxpEK+X53b9EJ&g7Rbx?-Ejap7` z2JCmZQm*-Se5FsLrCRSCMxTG;7Uh+{pIoCDe-w|_JeAqp$n}!M1UMfOZ`4lZX4=g~ zn2jXclFo$nH{#ctUJ)z=jB_a5=W`8kCd--?;XZ9%meuTBxmuhm$%sKw>9Xu_$>R@F zjC=Cqv1(ioWH2+Ev2oP0q9w*d5;>Q#PH*|)eb+ZH41c=d;<8z6S&A6ky}zq7 zua3A?ltzxDs8mu?W}xBrvpI)TECRR|*x;JJ!Y?JBLjU&9Y6cSART$>=xT>@jrv8Sh zsNVX~vrtp#@Z(yw?;%YgbW*kt%DfUtbv6N9D)b*hmSJS?drz^(J@RrzL@`|=M`?BC zkf8mB&Ej-!qHs-JPGuS8?5>^TLY9=l45F{u_ZTNL3)=8fDe`q=VcwU!)B=F*m>HFn#K&X*fG>j;CI123Ve_V#aVvM&^Mt-) zioRK#`1)%Q5s$0$hkKb&&ySH7Y}n>98EdF1+-n^Lzo%c@@^}21r%uVh>3zUCd0UZ6 z%1$FfKrj%x?Lzg*GEm~76TevjRRfOt&BxU9v%tH}2%ELG7Vl|ISrj6AEei{a@ir<) zP{D4%Se$jRgdF_TYrnVTXruNu_C3na zrxm+du(+wpTJyhM9f<6-i$S^r( zKfrl#H%-O++~bCYlyq~1T>2O17z6DUAK!#wOxl zdK?^1BGH{Hhq6}dQZ?c6?moT?{FT@;AidVr_S<#(c0JEjcTgh8(8ZD9ya* z7$;NzC!qPkW6e?Mr-x%mJ}7X&GAkMehjx=?w4( zg(hsPvi4P8O@7*U22ZhA4;IWD`*L`ku6_E52rFT{VMSbQchL51fpo+d%NwBR#E(<1 zs|MJrZ^XQnMs~+wql{ShhU9=*PWk;3Q7|ZYjb3$f(`9KA#)@q`iJabNm;~^Q9*lv6 zZxPk}zd)W1eZukag-XtpvD?{3bqUI^F6H|TX(dd{pi4CB&om{M{9!D=w4*p3+Qqe{ zmKWWTRFBV(QTR??yVQT_@$8dala%vk2|_v^ZsfF6G25PAzAs75>iQo@<$BZ*w|R!XAL^iQaGO@M`lK zG!Q3kbNNky$2WUzVuU^YC7mlu?jj#57bK&|;zeaZ?jC%KU;7r*PpDNQXmJ>aLo^H_ z<(=ub^~mFCR&d5mh$UK+2wEd_*6XvmdfQ9CSVNXZ2Wj_X_8lNzZkA; z5~oW`zZ0Gu(bi+WXOB_18!-C0AGVZNlWOzFbmVMHnmG-C~Ztd8< zS{!JOWJ>x$@hYDWtU?s0SE3x&_v)Y0EFc%3(}m|RD zq5CdgujD@JGv+A?S5M!Ymjn`DxRSFU-DCU|fbc^6oF5Zo#DVS4ej0r4LGM*zu=mqP zdYCMt^*2#EkqdA)1Q$=YtKsEj{RRXqzY@N0Nw$iGH(D|bqZcJ`+OCnkXrhO!r6}U5 zM&ai7V=g3c6}TA(yM674vspDDyq8Tm>z_D!+jui|uq=_0`Z;MKRi6w?U-3gX@$`kO z>=JSSM>*OxysDB^WAH1_-2*;hh??>u{b9J7-Me(=OZ$?v&^R{Y%|mBT>%(i`j7>Dn zXBM8M1as#OJCQ2M&x`L~K(G?(Ex|_S!?@r&KhdT2M0S+uNpmmrS%SnvnPQctK8y5T z*675ImzJ?GwdECu>q`q4l^c%OSr8BM)!{r22(0$TLPM^IxANuPkwgEvSdQI&*yvvv z7$S$gV>0OgU&+`t1Rp=yB0jjwU#O91+735&Q>g1t_ri1Kzlb}98dSHbYb9?c1Z;<5 zN|{FjW41L5b`b^-4mgj|j&X)rZ?i8lwQKi;?<^Xk>z|xK!4Tf>V5G$5dQ!Be-Gn?G z0cr#I%gu|#&!6k4!f;d|wJpGy*h-_;Ij_Bz1S69rUzU%))EPK zTp};M!Ipg&Q|bao5qmB~tJ?-$e+tTJCogc&So`pj?mtktzM+kZa}ey!Hn81j_wkk4 zCBE2NWAzabH$>!@Y<_|+!2tFEMvP-$nS*ML>!Qk44o0lLi!Tqhx1-Rc(dpia%UD6? z^?^U>vN$11A*4|85e_x49gpfO*v!0B%>`J5`}GX4hGx$^PZ+gO$y4@4P9&mMQ~;ZU zf)7m!rZxm$NCp{y^non)N{EP%CnY77;sY-q$mS*q0edf=hjUnCFV^mXtoM~OleJt$ zDlF`O275gDQJva`pH}r2WP^Sn2<=UB#hP190I?YC6NZKiIg7eCU@)35ox{M24uOUYM@ns+uTDwqr3 zLfcim+qLhx_Lng9_r$E8uiHG=xQGJR=v`wn!M~fGEkJ2$nkfH@i#LdVsy4n-$Il;V z?Uy7T3kDlVWscBf!HHSIB)HLwnkEHCiEZtU0^#Ey!*03@vmiq?-qSWLffe7bDH&O= zLhyJ6k4F<3;o&;pK=p{ZQd23X9p+5bk%pSXP6v zZ;kE^MEthJVn5B0NQ2knkv4UrvgnaFRUOhkN7&ULqU;Fgb^HUu<8OE+8AEqRGb~0@ zSxC7}gUEn0QkH3+b8+U^Pr2g0Uw9a)oR7Zs(|K3gPu7YI4rw>%ty zI#yk~%@7<3?xXt__k$UvrxH0p5wF%r_+PwMxJ7xw+y20(hwD-w@v0cD_^KTpw-&J% z-i{_E;B86WWDQw(3ka?hDP_$G%-tSjrY=Uq<~&28jzO7G-wGi5*uk7VLu94$JT>?$AslM4 zg;=sY@4YOsr$fD#TqTy?DHE^Fu$5Jz0V|Fm7}aQYu`^sc?slS-Bg_VWRCe|kow{AT z!IqQH5AeHLv@S)p$dmBzDhyJos_C(GV{plfqY&Hz=LNveVwF9XWs||Z0c4Xk;UA}^ zrx_6s&oUZ&4kv?k`}5MdtpkAbdL{E}mt5N}75N}IaF6<=XQUQONya+s&eckNGD{%4 zeahezBP*2syHr>ns6yc~^QJ!{=W<1?lL+F{+HPb8UYQeiEF#MuJ!;F@TLRduZ7UV>k7V2SvFV9b=;&8e2Mr{v7>Xc!Qaw6YXI+1i3D1##y{IV-a zgQW4TynCAHcuSm2eo`{27NV+YS7LIhb6K!&{8+H74~L^T`Hq;Fln%(0rfD|kYyt)vyn;R3WQBDrn5KEt6`>#@TGfMDktLIlS*Tz2<4Q$KMRrh(L z*MWH)j|=Zd501ff!&`1DSf*@1wz*oXb(8&aD#2x2vw4fbLl6B0k6kn27{JZR>N2U` z{z_5LqzD$}C8%uwQXB)WZk(1Lsf>iXC-W__TiFcHw|6cufXggg0pB#1>d<3O!S0lk z`jgLOWIf<m0$e`W}Mb(#BB(9yxA&IYRSA16i@ z&s4A~f+k=gwuQ`iqV{|!iGKVp841z>y-?mh02f7BxOhaGYf3JE{$6I0(JxZE%FCF+ zC2}g%v6qT1HsPw26TEFFI?!n05T7Khy%%GCjTT>hU&z@-l4I#N9ofzE2&QY6NL z&o8$hLwJ%$0MZg0)-Altd*b^&4z*37qOBf_9!Np{A+t_u8%vbGMwj*)ju`jocSXi@ z$dNmTULB(SrjYNAJ?ONOU4q6_D7+Mqy$jCHVhp?J8_&yPeDw$aPu?qJxbk5fo%E(! z{uw@X##Q33dZ3o*?!j?e&c)!cSODueRFi>WfL`EQ$Nnm|Tl0K>e#sMwm1$0}pC=Q! zi-tvdTX>Sj$>Ah0U5ql_A8WaTCz&E_LZa2KGa}931mCjRZc1el!j=o_J9EuZDsRH+ag3 zcPxzs+r1Guf<(JIRr;3tBeg-4F#wklXQr5`T7fRM>Nb}N!a&wLx25yzL7KqK&+C;e zUAHQeKSm^|>?oBDN}jJ;MLm@(YlBwq>IML%#Pwc6gIlp8*h#-o$(8O3i_Q(nl<$P= zkTzf$&@q;dO2myjkAlc=4)YGCN^sjRaL<-({-q-PrPO>+`9wu_AZ3x@VafdbScn|7 zMMl&rtG}nnJ-NPXo*PJv-A^^}=XZtb4~>%}t?;Uu(Or*RP{&>GHqMAi+j)f1^0|B! z4c=F0fOAH5e-dlN=EXR78lpbao4%nd=0)STH~lVp`5O10iZm00r)eL+w?Tx9O5eC* z!swPsyI9f!$dM~GH?GOLLJ&&0l7De3WW==uBC*uGiuP6v4aa^&*bxUEiHksvc_sGC z?q*H9QAT0MI3gU2BA3^6=g6_jPb~Z|j0^*hhC=Y7853PQlb$2%G{y)hu|uj9%1RgV z6^E>}5Bu(slrwmc*R*_OqgHJ}>H>@fm-H6XCBc{M2fD)a_%uY#-*?86JvsZQz~*QB z6vD@dRIRU14Z}4js|V>p;k1+GRLlF7uqQz>0JC;9fl%jdj+f4tN8nV7O4t|S=Nu9D z9#}4MbUU0IXWl#lO%55BqSXx17)+$emI1}@v`!9CEk?K|&DhqLZB{RpOO7Vxzzhaa zvxurTI#|7g+B#-%fs;rLWN3O#%rN^B%paE4E7@7caPR=O1iyZRjoA!kbKE}{E7b)4$alTik?^f_1su<4$!NQR z4f9(|IygtKlPFTL`z^vgYb>cL;g&d=v3=6W?$O{HG`1RhnO2asqH)N{b5)H(x=K|1 zU}Czp2U3(>DP7I)w=fz{`m3K2QvEzun!6sjO4R+82n_yo-NWefubZ3fUgMFvK9%Ln zGt>M|8AC zv{#=`yD~C$+Y=b@KCnHl@&1SgBAg#MmD6%r_3C8k&|k?cSH5&D6EQ>ZtBg}W>XaTG zGa5{jayxR@*u3r%A^UZZBL~P0EMl@%t%L zn)5KKId_{D*>r-@7u4diGNl=5^eFacFPqL`SLT;JaHj1mCvuRK^+!PBBYNs%w4y=y zo(nw`bkIig%)!S0zzNZJgHb14_l#$A29BHM;9TBUPcU}6JMiVv1SB18?6udxW%Tn` zY>P0b`0UWT`1A68*D>X4KJnQxkj}7jkl*3&iU=55D|CfSyjIC`Z_mc=Y4as~inoQU zjOpSxQ)~4+b)e%Qb?*8Cdx4mm+5r>Zp6qT$nJah|DIAmRvpltTpO9XRM95>+c>JtK z=c7c7Xga*VR--F}V%sis>)fnsB#n}g@XE9{8t7{Gz5Pc2Quf$SK2vu@zfjGIL#u*1 zRQtDYfzg~eZYTP;y*43r%TB9_igXpO6cXhtBvXl-ZMdi{b-cmAZ+AyzHu>I~9rPtZXtnq?|1{La8rD{fkI)V*(d67%5Xr z0}-q!GO^}ETz*qa?v*=}TT}?hnA}g|@9!tomDm4K@NiPYw*;cOS~F}M)hj^Pn@beZ zmlqmMDSzU8i7ekf;R_@&T9vn0{F0XGWfF6AOC@hHj_2FytSjcMapQ7Nakc-eKeE2! zLKTE>DW%&SN-1N0AktA#yuI8~2#pBO^2GEiIx@T`KCw%BY8u`B6X|^Vop;_!`?W)l zmM@3PgcK-)?$)J-5(6A3jiGnKQT_Ou6KS&VD(Hm*H%iqdWO$i)yW=EbtE%aBVUc}r z=aYx1t6xh<@*3#o21Z_Mz*{Q?Mbi*Xz?e%ci-A}kqHVpi1T{gAA@eVQl6)Q?O~{82 zhZnn}s%yeUm}OIS+^e4J{@{_oR~te%*1G|XR~B%c9>+@s@(I*lr|q{Y$02V$*xYz> zinX3ue!VFJ@q~pS)6CIOh`5zaSCm<3WMa>B1_oYcX+lh=-O}0+`Qd4~67bsyPQBDF zpeO#KwLb6p;|FLaVI-unBXukeb%*r?X7B3Zy!E*RQ1ka}u~U9AwnBO_|3gSbOb*;k zjmRZO+o|wS=+o?>qsg!NstIGgJ+cJ_dP#9_#*(Y>>PbrBaId|TTZF?rq=0Pfqm;C( zXPS(RIKW0(EIs|+^ZFE0BvexD#hgsY`>ohZU7{vH`2Mj@wxEZbNq_ZD!`fW_e>jKcaf=Ys7SN>j9<^mlly~Tr>;#f*qvxCIaEme$}@(nHB9YGWz5mhAAqQg-A z_b1mW+pZ6aYzkd~u?bZi8}dGh1L+YC-W@cImZ{2MDXs$S6F@sjJ z-{pAeM;Q~fmB_E`o}T3+lF2qFpFkEB9MfhA=^5qiV5=Pf$bjtK^W`KEGAH7kJ1IOF z{YZJag#M5XS;#{=(A|zvVt3uoiGLfPRo=xrpY!OrSl2H@?6k;&7m+Q)O)H%~+)Qpe z*XI2(CdM)zN(MKU9w5FeJU)4*5_$|MDl9zfBTy%`%nJ{P5x?F0x?*cE`;apv$FtD? z@n&G7t1K9{L+5`n3#D8dML!A^EphfgilW@^^bB7KRT{nUHC8S&6(6b009?uBf#F5 zilG=}fE-FqO#&*c61nW?QoNs$YmcZQvF62kZ?xNW z>F|D(j1(^MRd+l;gT@Z^SUfdY>=EMm#tVbptFEd+(85n7NE{Leks32^Dqn=;~xr$G3zy_8sx~kFD24gL-Og=C~pcT_sZkO@GaUrodEK{T%1d z&^IqPCt$ zbbWvtCwF$_6&nX!;Xuam#!G>Y2njK{!G}y*iArGW(~Bh-G!14XiZ?6QeWzD^FHW9QX`KwSDYM0?1KcTv~s(@t;B`-YUNVm{)>da$TN&k{;FeZ zhg7pbV{$lOJ?O{tP&Y(RRY@qvRF6sv3@HbJzeM891)1i+r-2aFp5i2as6a08^1;R; zb|W|(1ior=^nV8PoXyo4^mF1tmXMxUbwXGNTLZ^SXge^R)oB)5jf1CAtUudqL&=ITSm;7v3x+flZN15Z4 z-9xfozd;lB6Z+#8(7Toz5#|T2ygBWEOhiF3c%J^rEC&D~NK$iK{Ym)**a%59)4*)q zL>Rx$9M?F$rJd zHqO+LsNSZB6?vno9uac6QSu;AS#mnBHeCb?aaLPa|H9D;g^K{~obKA<#}Bj&o=L0L z=g92kbc^SB*cie5-IAPejbRoPLgaw5g?j&WzDY5QZ+-O_okZc;g98KPOld~iE2$Qq zdslpp(E3RUKJUHz+XALM_ts3SE;>)`1MBPidLohE`$X2_JZx)NUkc49}$kMy73VetTNNjY>6N_aa z%)~?TE<``l<6KEaBFy?GWq~1n4+}8kvq+T;Is-r9VIZXTp8e>CtK+V)e7Nz$aPo>r z&=IMmbT`cN zfmYg|5Dk1>;Da*JvymO>G0D{44r5O@QIPOp-87?d@KX2Cgt)rTEO?-nAUHQwOBksfOJzwAU z&3=QCiB9Bj;ZF566t3-A%4%f5fVSaou;#}1))V;lQ$o3%cS&63+--p{##%0E$7`NN z>+WF6oLTttMOb~(MGt)$sg9@sbYDGn_4?Pz3e7yfL-<3Q|HdpclCK@yVZe>7eKLvK zz%fz3$xKv&wSt=@mY0z;f!N1JS*y2g#p1t%)RkEjj5$bcc`6d|nh>&>;^{a7I)$*j z0}GiM6bXZ~xJE^V>n(T;^Qs<+ISp;z2`>DsE$;b+PHs`@_izA)QJo|zap8@hmcR7F zbdW)mIW~*XA($iQlL!jT0w<6_KTF+fRC=MKQ6dDdnB{!uJR7laZa@y5{WGFI_;dC^ z$TLeLkUHcyvn^Re7%KxBfXw`J5nS-v)65W7?&K&gbeR@DWr5miiRN@PgD%II`eK&swG}hvKIPfh8O(tRR%56R;{yUSshF(hBEB>}mOi#h-VK8xx4}G(ZQJ zmYk##%9I(`G4o%QV~$t=#$B1PuX0F@85VesY)4xCTYu&FrgCFP>Cxkdx@>B3A3~U7 z2+(!xinOr|{v^7w7fjDX+kp2rq@s7;M9h23Px%ETessD>b{g1f}JmLPKEf8Q!5hy=*E`H{)1~~A=?%CzCxHXLumDog>{3vx+wuZ~OE?N9iOQ6TJ zZMjUKuw2*5?syOzFWdf^g~T2_M2IctmK{|PHbB_;Y;h=$PE}7YAJ32UYLV!36~e(- zad!z!&KSsdlOyp%J1RyF%En2Oz2{}{99S;;%-l?-Fe<`wN#x9XAfzqh9~aW{ z?`7(Ku_-DhcLyl()+gc_7QLo!1yex3X%BwAl#of52Z-6N19ZY(E3E%8NcCn>GOkT; z>x3tJEKE#e6&a8E@F6!f(s+G|_oO;_?2e%D&bO=RBXb?=aP6%!sg`-8cM7}rDa?Y2 zWXGQEXr?Sn>;#4JPG?8;lV48YN?O7PseQ-Xs4e&f!ltR%aqpm)lV3UE3niAI8LeM!NP@D}#pu~&-E4-7@G`tT0s@G)um==7Uetv=R4(jY2z@1lm>XC% z&vy|*UP)CR>1iitv4p`fehflJ^q>?Yy4H7!^L2 z!>gTi`t%*)OI#}Hi1FfDfSy)1%qWBtKBqu@SaUmG$iNRjHPlUm1NJa-9{hFv_a4bd zjAlw?N0{_F|8QSq6-S%WuML&x|CHpf;`s8d438lYJe%Sy^X!0(v;!SiQIMX0*``C$!%=fxMYF!0+U2~WftqsD8$%x46AhS51XbCOS5$RA0qg_xImfA?Gp!#^rp8&hKtoFv%WoBQRvyjD6Pi=(5p{Vr)oX1)K*-u(tH8)?|qYtwTB zrfl&JHi{V8CIs?0!c^{T^@Qlg4;>U?UqL=y_x+|5qC`d&cOaI%7;h=9P%_pJjC{(C zZ-}lAJ_9L|B;d>u&z$auy!ja6yW~HjG0?s_#PYI!mjCwTID-9TjR?R3%%RdAKi9=S z#-vpfIo+=VhAl%g7;uWCesn2QQwoQnVEp7|eTK0=JpQ8PM+Vg$*LR>z@F0+Zp*Vll zJ?n33_g^BP5F7ksv6E3}z>^AG6Kv#5I}addlUnnz1A29&w6Mm5AJ$hEtk3tFZYNXt1ScJ2dd3}z1E%IR zskkO{ha-d#dJGSc^7)k{qqAg3rvNcmKXq`$CpOI;9J=?cTh>SG5$Hw^QX^m76%x{* zFaE8u7pI!SxST-6&9t)Ut7Fkk^wf7-wu7p_f;?v{ESLQi?s-JjUjD$;v z5f5z-YF_2aGt4CKJvo$UgBXRVpb90I_#WpJrHQNJood8aS3GEY{XO~8^#^oAy@YOP z2|nzWfP%tq$(fsEg!Qq_dcu{QlG6TL74M+QfAo81W563U+ViY=m1a$3^7Mv2@G(H! zZ`b$=HZiBy>#Y+svs+YQMtN0qN$2^Vbl1PkPp}S$r5}8QTOA}yWh$_4oaJKSGjc!u zwP19?>#nZl>TaN;LwHI#Zw*8!xBMr&?#OqeLh9zelv9?6py~vYxud0oSCj3L?O*2< ze7orJS5o0mqtiB5k3_tFw^Qq}WDN;0r2PGugpXm0l!SE`KE37Zjnc9sUzS!a#oZOKgZ>XKVZuRbZQ`-tM8^4UHl+P$` zhj=~TKgTjkzeN=5GiSctBn+oGf7Pnk6NXJKWcqF^>SaN`v2`C zQIZdO1%b6jl}1wZLd!$z-cw>gHSdcN98OkRP|?s>rh`H6-l@oX?FH4RcO|}(R@rQ- zQ(5Mi4%=BSgZa8jIdb&a`|sgTeO0ofiOvH(J^Q+*D(bKRm5XUgyC%`DzRDb&iwo=X z>&5WC%KTlWCUg0LogE9!Z@@wMmy~I&y-kWBt>)Gg=Ep+iyXc<4ebRS<4|;TH4DEM2 z&L1chGve#{a27&aq z)Ay2G8Txgf!>ZRDK~(cfbnFd6es^apH}NZubCr6pe}p2JVB=#+ZsTGhL5+C|L-Af` z{A{j*3sUm`N%(Myd-@a1yl8t7W<4$H)02bF)%$dxZ<-4l zng(wmoJt|TpZ+Ds{~fI)H4%lyv#TLO*|%1gf7&U2q@e~aZ*Cf( z1-2g}i+StV6-UOK&v?oX=HIR}D*5K;aX}fGY1xd>(_c$#Eh9232x zA$nA3ZOtcFc)lUvfjPRU5QksR-bwnG6!#1{5R-k7QWWvI&sl2sZL-A}`VLUxJAgGl z@xV`=X(fNbXB7AJUYYoW1(?7I8F_$(F;fY@L$s#czz%C_%w<`Ps6CQZ)<;bLf;z{h zlG?85IO>{HTT&pDjN9b6?vNU2 zELc5FoiRUt+a{3vRrq-fyyY&;$aY_>i(6uvY*_zKzUp78f*Avz(jbBS%}8iE4wc9+ zul<8COE@7;@a>vXVZ+T1X-ji0Pr`8YnftBfvM&(z}FZkZ(0{2Y^rp=mPaRya=||i=eBxrfcTC# zfoeqf4NT4|?G(mrVel{U4WHOHG^+&a;u)1zJL%6pxqsbxc9eWr8&Bq>ot}dG-H+R) z{aMq>F}&|D#Y2dVDuT@=9b2vxbzv?R<|vhQ2ozv*Y~DoXPW!C(dj{1&ZYHQt0YIEu zTwnpcJ8#~O7o7sD)1<6P_Db5m!%}j6zNq7%S6Wf3!?@0=!>lFz*Z%@QuYgE@HsgdQ z>+i0^Zz6=F^H#}ST|soVTBy=&*t8Ftkl`Q?P#iV~=@_aiO^-(yA|tI9C32D|yEB(U zFQw$x?;=Mh{gS*cI%#octc#WQ>KS@*kxN?AU7gq|xOi<@f2zGkOZ{UR`1zGl9R>@L+AAZvjbgMo!fcVI ze9KCd4JH^-id22?OK(_GE8(k%bXYXog1e?e{(m z`n-V)bR6^PScymz0R(B9oNynDwZR(wb@L0ZI9%c4qJv)sJ<@-yls1y-yPV$;`N!9b zdK{r@TU$p8y0#04`@;m-G19bxCCXl2pGKigubfr51+pO7HCS7i$qFaLU3`|(rN6VV z;V9+1NdWIaI{J&~%~8r$fB|>0rR({HuTm7(G*6lJ6i)_cyiC?@(tZ2ZiUkAQ;0?7b z;oYA1Oye`FEb^X0^NZ@xNFpa7YI*a0b&Ih5K$1AVW+Gi9ig5@~jJE_7R7_TLM%%ul zwU42UFw~ARhzWXQ*4K3HlkKKk~Uzm%J|(TQ?g($cEnp)d zeiN!SQspucU5sh6B|XBrn(YGA=OBykBPl}ma_F!@+z`0&)0)aTZK*c0Ch~IVC8_TI zzU|?6-aVLMH2I0yLv#&eezs<+P!=Oaz2EoW?vli2D^_>|EDl_myDJ-Z%3pO|?jB}0 z&lq?)HJBVRG!@IM6Q*AxqrOX0#zhZaekv}!)*C7HL@7{QXO6n7K<;Cg$4p?F4lLls zTSdGS2#An~Qx1@}EA^16C>Z7W=s`&LFh8KHgG$$nZ2sI3xc$e`QFea=B{A_0A|sHF z3npF~iXaMESq1=!`ob_sz9?wPt-v~l27keM!TL>A`2n-8<^1)J+Ri<-oN=g_kJf~6 zSSY)S`}v2o!Vs;m8iuSjHN2J89GivJx{OMJ ziEN-NESxCqHS2HZvyvD05EF&4XRa=N6xrwlUT(vSr|rZvx3OZ%;;Kif=$B92<;dTa zq+Cu|hr}8%Y(;mM)LxTQMG#%+rEJ=V=3VZMe^s@H)7}N6OK5 zBO&vD*m~! zuJby19LFl5|0eS}T}B}3O9&y0UUs+u#z8>a6-Bcp?FVPDpCGu$xh1(#s(>%L+Voj- z1?t3(V;b8+=tafiSr*BwOZ(m9O$)G{C(6my89Xq^g1%^a^e^UYHP)}Oa@A=Ohwkzn zqp6dI&!*_$yb}H|{#m6Q-E{Xo= zx1~y{;30VQ`Fbdq$qtGt1xllOX|RXpeCWVAm{g+Ex|stpC84~~>K1S&(~7CAESM}8 zhZ*CuA9v^Y`t`E8xjpi!&_LTGv*01zK{yY2k&^jl7sXwJLI#kC-h~DRa7K~9$*h=k zAF}uC&>G57hWNt?&cZ+JJMcUfdJ5hE3)xep0dlC>C4yd8suGqo4ZR^;7^q7xJ<6{q zF7T{ilqyX|hT^f)WIVF3JM@=c_vkNN(=MJ5{Xc-#(ddXPnR;BXp| z%!mvAC~D#(nDj9tQZh|ZJP7}sDLLi-x6x*=3+gW0&CN`1(tSu(^@e-I@g{5-sZU<1RurtjTD*3n0tAaMz40F z;`3Nq=2!y*VW@esX8)MFrs?G(|Mz(4(B;mK;9^1?zh+83VtAArQkFJFyx)x2q3a3Y za-*bmZnIFmEZvze_7~CIoLdOD_fNG5Dmz4t*PaC{?P`I zW8~_6AIZO-$S~RxEZWx@;xoXb=?t%)qzG>c+9XSc_$_Kb%7krbyBdDs^^kk*oR`t| zfUjVyMV2+97jLk~)F0=R&z{nRkb{mWx6(xD)3}PHDFjyF^${foD&_Ponfm1&ReS3i z3#?n9s}{EHH9ju-Z68$|yS+Tv64a|24HQ9GZQBysNLRRspbDGlF0aG;C0)TxZE*=D z05acZ<=TZWcl;hm`rHIUz((X97{~5x*IMSVBeb02$Ms!N8`%I#VPCohY3G4`yuGam zLuMdam9ksrQSEg^Ws7MjC488#Ld9z-53`Na;AX2gRNhuF0{L28)L)(?H-5sq^!A&~ z4#Wx63X;YyMk^MNLCMv`v7TyJZ$e) zNg6io01O@{2$^j=D3zw9>GfnaGyw;ZZez!HBqF=u%SnDM2YZ}f@{3_<5u|$%k?E{R z#+r|&?z?8>p)rLcgh&zBM8pfV^|H`Do*#zLc0>WoP_>if9_+X-QS1w!&icbs1?%{i zA?=c(LwO2il)0Pj*!C5&BbtAJv3RemmgKada;zW;Y5n%H*7G8`_Ys84dTtOO+lM)H zUORKkJp`oc`Pwg3r~KJZ(`UKY4yZmItn78H|gvdG&I`!YCzaFVQ183bAUSFd_L9QYYBFmWcj7kl@5dLjvrjRb`~pqn?x)sjmsW{yRz(ArZBouUt@h@vxb9U=Wy2TxgT%;;ZhE5t?zpvv#!#vdNA z&vkIgd;e>C9hBxRO4iX|!$L6j+A^0Zwpn)IDHQ}@Hc>!NhHU7Q6g>Z3e>X}w*a7)v zoXUg;?G~q$*cWLp-p{o3@+WenE!n=&PK9p4_jzR+bZi*-%$Px8{Y?sjdWkXpfa-4j zt2N;3F4eFDabi(@%+^uaL6G=76z9L=#SO`B@1sj-7Eu3;!?9vX8G-|G>$=azei~!i ziVY+qke74HeFu#7oQv$>`e;$zs94ILVgl#o6VIS_xw58D8LM9C9m)Qu4+HL8UjfXi zx1F--U4NjHPd5iUK$QfJaBK__jSF)wK!|UOnAV`@VwG_b7vD;AlKBtE6ZDkGi!GYD zHwsW(4d5i;yenDjfrf|TUW6K0X#jHUEjhy>vHGduXC*6)jc;1D&Vm=chc zS59Y72?_WloAz-Lz3l=Cu%f7u5ybdRyM&doSoMx-2qdq|;k>!kZW_7}1fgD(;nDs@ zdgGx`|Ah3T?%A$7_B`Nta(hhAyeD_C5T3na$Kj$RNI(!L<&_5EV>ADNE8ZB9svlNA z6)7krCwA(|l6c~R153|qT!bmIS&o4=1wf0QNT|KvNDEOLWMcV)c=w{PvU;v{!Q3!= z5ML7Pyr(<_bz+ldlJ=gfgj4SsM=8%lr~kf0CgQ;B-pYdIi>A>|%KVms>SG0u9%S+j z*6{&W@&?%|_CaI-g)PeNSzmh4M!Ar#9o;z7r$I zBzp%4QfpO++EfMYuHs?bQWcbOkSpW_LXpTInxy)X$WpaPJk=Y%?th{&xk{kH^MF`H<>2#Ot?svP(JcHr%WL7+8RXf|kBihW4+Ozw zu#-E@?xQVd@xJL~N7Y)Su&-GQhQ=xA-134oXqE^b+q}|&5gWA_bo+{3qjBCWJhTL3 z&7op+1)mG0mos;}DNnl>Zm_l_q)Djj%~se(Z8HQsV7Ax5Il;w zK2X^jMTY^tg%g~uSltp`_&~-9a5sIDz7JaRo{RpF%L{6h_B6W9Z_eRvCl5XO+nnxw zJ*}2frA$#%z4X~yl5I!++o!iSYeGHmTwQEZB5#$6+xufbyYgGmc@;O1DxbSA%QIn+ z40$@qkkk7nmt) zl}ZQdR|6X8Xf8BW;xNsI$}7oc1Vp=qD7J?2JD7FymgD&=|D1x=7$Fw~K*;=lM>0e2 zFbA(9%|Wm*i_DqvX>^pRP=YRrf*U+=irPRCX5vK-$>d~3mz{3+?ZM@678QdCe)KFX zCB-H|f!jgr`C4ppVy44ksxNICsa$NOLH@Gk6icZXM5nQ1oqFe8AZ6zndI$~s1yx|h zN$hx&+@$X`bgI;x+a;4eI4|3?zWB>DIRw)5ZzgJ`wugAc%kxX0qDjN+DSW&2QhB(n zvf0Bg(g@#${|sWeSa5hX$3{Vle~f3NeMi z%qR!BSMy1y`;@Hu(mbqFvLN_@=FYQljcmG3@VM-Q=$Q0}wAh%xHR$LUMT`$I zJe#viV~J*17tiy7?3f~Z<9E}(fq@MC>O$F+bkgW~(p2Bpymi;JWegxliT*3vUjnE7 zH&BQLfY2d2c{u^`(us;I6B0?ONfz3VW5Y9AC&6qP*zUFBa`hwvPmHO!+Yv&fvOTqaWzPNh4+yWrXC<2%Tn1U^w0-Fe@GprSy$NP*IXKpdpgnUM4v zZ?Rx6mD1V9z5Lp2QV0?GZrMw+OQA_LiCSyA|3lQm5L|KGfPfMLdEhIE5ENaOI%qJO z8<4#x@59XtsA^q!yxQq@FmT7f1stlI$MMQ6Ux{7{=z#cCoJf;*F&2n@KwgBbU&8W` zmjb9_eI|*rIllHhgy1P1jeFXAjo+fK>Fo4JU8OoHL1SL{raL`tZB<$6V!T zrv2Lh47!4~_yQSp%0CiL{CsCIQ4%pg(JhPy_tNB<5+RBW9FO0Z*+8`#JQfy~!cQ9S zQE7DdK!ZOpEWh}xnv`1(T|h;~vIYm@qcNnAJg;z-2lWCRXy%Fp?k>okeFsSms23G6 zdl7rotO(0pHAVMz0FnhAm`Pv^{MD5;$9EFRY8a)Tt)XVi{Q;iZ;|Svx0xunHZ)JHB zv2F}|9WheezOicaj7d@#XH8@(Z!3zVurjT7r3wXjbpEn20E`}@UC)=$ zu;{^W#Hf@piJ5QC;_H~I@b8q-b)n*oJnq}vdMf69WhxwLid~nDg8d<5@v4So;H7w- z39BCo@rd>atTE>(7rr4*P~4G;cgiMP@|-^&@FRfAZ4HArSushYSLSfypNMcsdhY+o zqOq?{x%uFNcRU}{)t-ClO%&QAHp+rfABwI3rO|{VCft_dDP-k*$JqpgcowUhlzsyF z85hmToXfF~z4Ua(w;;U=6;-H*K<;Qvt;V}MUxTaKUxJkXH>s|Xi65^wd_GHA*5OL; zV{_z05~D216L5p)qpGlbIWJJNC8o6E2b%BAj8gM+rK-upf-&jdh7wN)y3H4CDx2+~ za*}y$%P9vymZGhkpNz4uvKvk?uygLpjO&M3p2lX5YvLm%UF6aa1cYr$~s+#s@G)yqZFyj z!NNUG*RFl;5SdEhdpsiwNLpwitgm|Wrx>vKlMVcAj`lcb71APd(5@R9ORz&vF_D{? z@VpLT9k3!|BOyU@-&$BI%}PkbupR~R4HA_E^r@8xW8H8#O??A2oFNsZ$=+ZJU03Of zIMZqMF2m*bia_%_Vj58DI0%@RP3d~QR0It5vg;nk@+vrhGY1eahY$<| z>P;P*+z%hFwl3Z=dNLhY9p6I&LXs~QtMirC;cd))m5Z4tcK^_aen0|rMoUr+Mtjix zdV<=yPk;lK*7RXP-`rprIu}-k9-7fP+F^iFet)S6m3Sd$)tRKF<8#6{`iya_|GGL& zm*BWgc>X9@@2t15z!rRy6bv&%Jy2n=ND7|}0EB{u@Lsf`0cV*=*>2k~%v|pxa2O{* z{BifEu_-GQFHxd>^cCmgE8ra2h zuAg^UGwoi4@&`fa_FSsQB+bkcO3$YMS@{NmV&>Cn-d$h5gr>jRlQ&KA{E&b z+$^Va*=1W1+cPda^}sZ>gZPF2VvGD87LF7j;AqHcvm8{R+xUrVjBVqWKJSgsT8nd0 zgV1{wx<`*Tbdb6%Fq%>@#9@+fa&k8Q6zJToL%#MGe*#Y2E`d~nG#eGwLLo_*;Ca^l zsTtjg^|W~pjn#9teJO@r2mA=y6_40=k3U0(?; zhfp`sN@aA=rm@OnT(s9+B)od(B+Gx!IEkya;+TH0P7d&q7b{g1*65?RzFG?+*ziKq zTqPkViWL2F_VeWjWZ_yV4SPb^Zg z1-zPANSQbG?)Vt-7X~b#9B&lQU~|{?{M7S5*Zo+fnzOSi_C9F zd>-l%XjcwEvPk;XL-4SJxf2T+y309wp)UE`q`{*UVn?X2&DG@vfKQws&6|{s1t!gb zHx9=aIlI14-B5+H?WYDxWoO;-x+^rJVrjUq6B#SgIcmN?Q5BCU-_zCQPfaY#&Q^QJ z6=5@$^sZV+KE1qGJAUdP@7kANCs8eRVSRL71x{K23#Y@#07?%#c&H~)UK6rlRoNc$hYV2w zRW<08-Q#tzHGec!gvji1dw5zaedv9xnA2T6r=K?%(R04TS$h3iNC7Rov3Rf7#(;JkrSw3+Q^o-|zZMx;VTEc)}6D8Z&6i5Rg<^!~1`JQ<$} z%+k|`r5|J>JuRM-*yiqMQ!Jyx;4PSA3p)IgrUeoiIDPeBZq z6T3z6b58b0Ee2t)#~V+yd7{0&Ju?t`;|C;)6^ONrEgAF{HgxLZ0XVG}jYO1SUzDE2 z_eHyDd)4-zK7V-$3kYf!zkSp#!|?@o*?3*4H0%`k$Xk7oPiJSTpf~Wk>RbK%WbW~B z9tB*>-H>gzWg{Sfm{OhiqruB?dK+7<0cT4om6Z1xEuMl1#+XB2&=-crpbd)}uH=iu_60t*NGWyFVTk?k@X+FBxy`+H zDgvm$Yx463t6^h_zOl4h&hkr~WRW=(1cas8g|?8h6&RrXBRKdvfd*qGFHzT4^mD2^ z>nPiH%Cz=tWeKzExhx!J`%yWR5gEdvy!inL?GStljg(vT)y@DJIXU^nF$5guuKR_T zXoP`u+lSg{#BsPiFhj|>B=)q{m}eRlonR)F5ZlEnf=91MnjxZ&M9=mAK_7Gk2+pdd zkFFf}eiH^2{tza%nPnX-@?0m+_^K*;21#Ev2+irJQs$I(P#l>`=nx1924b_NQY zl`l_%$Odk53T^hAm+D55mKk9U!q-jbw`&U5UR@g6^3v+efEfeEu!}EfFCyt2K?0acOp9LVKr}i9U z#&9C|5?>Aso7cr!!Pc_{8^kC1-fKx5grD|zZ>?>W+vQHdrJ)VXjv-X#2x_5oPS7P$ zVzSS=WFe=}XXQhr2o#~O05kVtR?D;lnvg)^6d+k|xzhI&tBYjBbq@H(Jcit@P*GjK zf<6@rNT}=HIwk_C9LAR%&LNigyE)t6O*3HuObNDixc@D;9_R_r_6V=Xs&x&0@tjlP3F-IA*aa>2|+nJra#?6T0L@S$J&hRJ0YL&hmL1fzB z@N9W~k>X6Ss6J^#-nUaTiN3ZY&bOCLx((&I`eUrLTTkszk=WF7+WQR<&TQ0&;Nt2B z<}V2Qx4Oo_SoiedWwBq`GU1KQsg`>A=}e%!v1>M@23f~>L{xC5rU{Eb4T>SBUQ&Wbk`Rp6@`6Orl>UaQp-(7zSytew&Q!`;;tHOfVn{{+%9z6GhZomknt=Yso9g+*9>P434ea@%j-D`C z{Xp6K!*tK;=AJiiVT%%l#KT0Nl9Rd^5c9 z0gJIcI#0q|>*+J`t%I%i(i|Dx3_E+rD)qu^;^Tpb%_rx8?|_F8=`oa1WAlxFs|#1y zFhI^l8pDgPRPMO!1n5ibo@3CL$3t^$T%2a zH8+-@73-m^bh(l7E${Mt=oO*NnD`CbMwByVU;=^Z=3CtE8m-tZ$cdJAqxdC!!mwiq z-y_J%c;;hB<93O}q>fE^-4WR;IQ!vJ&dk}qoo^~zYw0%h;q%o{6I+ZNeOGWIDNm(Nt;%xJf;Ya%Pv053?1B^Oh6F_F{8u?S+wE z!MrK|f$cKGx39MqFqKc%nq_mJj8_K)?pc_*VE&gu0hh_>C-@=`0TIO*Q^Vxvryr%I zFkW&TL~LX8wQbHE3=HzTr90*dJ_-k}J|TOrUT<+RUSgF#-*jB!$1cjLziVK6omm;q zM3@7m&*xt*$dcPTUl>4ddu%#MZMsSQqG9ATXrS+JNiHij;fsCV)_^2FKo%r&Zabjq zY3HG6m^w2WOXT5fC3JOF@2V9e1hx1AP6eb3@rF{DVgK!;ybljgM@OfBJ=|-b$xUm} z3@NR890;cTIv>&p`zq?lZ|*ZycBzNBfHA`A@2mBz*dDqu_#|qNCgm#=-QC@v=N1-<$M)U3V+;uh2y`sW2i&LpF~D9|$3+AUYd0q*W?$Pza-Omb z@h9FP9trIl_Y%5DVg2m=%}|gLyB~Z-S>G$Lu6yq!J8M6)+GQDa8}i*rCWLLAK$HSD znK0mvs(XMX(k~9L)3_WkxU=%Rm-UAZEV_vK#o(;b>Oue=4khes-zEc~8Z_fwah{X2 zEDUq{>3L4mFv>D~f>Oq~^11pLej{g;b{i-JiBq39Apn~yUEZ}Xpl6UuqAPwW@KY-q z_DM3PK4j~1_1lCc8Z~ESy7dca48jZgBam52H2>w(bW)BndhHow4J4jH~~o8Bx| za|^cCZU6+1)3I=#c+%vbmWZ_IbBws=Lb#FNmvlUUVouL>L1CB*c0YaN-8Eq7r62&F zi!t@CS(YC&f^TSFt*pp;=r$rSTb^zfyY>%^Np66mV?=laPoti}lrzy+4gm>iTeU`~ zPM@6J^@u)7a}k9A=xD=0gfO*RdRzuvQ}hvafrRgoccTt+e24>?s8wC%7j z!t>PxD!_{tn~C%KhDUIsrtcJ}I9Kmmsr5dvUk5f*o{1&XoCCyh>_k)Kd{K_~iiW1= zh5%HGeT;OzjubQvq^-)O<8HQp@)Cm%{loFGu(pm&3w!_(zj(mOh^>Iu5=I^g@Y8Ii zy2&HbC$#&#NhV)}y4VbpaX0`AR9gNnb``U5G*e8LL)DUs*eglojb6U^9Wl^J!jfB# zax-*B?smMG;qtw_>T|!ChdD#0%Zl#$uxa@I$S=DV|G|$ zbR~nHE~am|Uqv;dR`n1k$5gwW+>pia1;odre*bpnhL;8;LUhvr79(>eejK!Oa^Z4c z5V)@XkUw$XOMhs){K`j%r4_sPc2zxW-kn^5WRgWT+(YY$^_J23g!i_?yjIJ-^dgW! z4(z+i`wAD6zFs3C!3|e0k7nj+UOYw48opnrBoyUDGF$|kP(TsU4VK;bz90DhdJqe~ zsp^`5jU8G>Q{cVNy19gbJFTi}YH}N1A?i;i%K>i7e|{Sn?z+ZMH_cUD;0G%+Gx7ED zN8pXi4A%)qFhSeu@3}gk5P(x^{>vdfdc{jl&<6N@^SfsF)00Rnj3)|%w*yD=FGc6% zsHc%p=WMD5t0_H(MOtMis+N3k&usw{h&YSr9%6d#ph3JTnNo7RBB`+S8i*V<{kfC3EA)Pypl1KDN&Cjm$$0d<7!g7;4} z0cHc==|I~60}(Dj`pWctlh?6O-5tP=!ssLb51}o#Ut`=WAbH8UANXYub$#bi$y86< z34YXo?QePo>i-h~x)4y2A-WI(60Cv08s!BoM>mQ9G-U5#*->m_(ZTj;v|3Ad4f|K2 zIW_d}RlrztjA-<>@%uOK*O>eId^`>aBCc!Dldu4vln4;U6FE)yKhc+1PDt*fmwZAXI zMXl4B7cq&ji*|<+ay+Mt?c-3~VGpDnW-S682MWs(RtO(HfL-|S25ratS%Z8ZF^-df z`8Q!pMFb&Iz~uYh&e#Qyq{H{4jgn2y0z|H!Tlci@Itt2|bYfh#SKQDNrm#L=lc2AU zOnOo0tGHw?uGKB7Fj9DeMqa@5f=8R%SN)dpB`-7n!V!tkoaw$FphB5|5Gbwn|4vLK zC9y6*;wDz{zn$GD@pn2c?EpA$fu=LLDO>$uOeMH9u;>qlgT*rNfhCgB{>`QQvi60Y zE7Sn}ptOGa4fXZHg=qeaI{yUsHP1D5-QQ?ISLgBIq=?A%1}_-o^_F9rS&OJ|&4KzA z&nB_+zZ(U0iGhoOFr#2JQ~k+Mf#;VP1R9*`Sk<Y!2^3Y2$HI2YE!mT~HeyAlP!L z>s@*9`f$XLbWe(QZ1BVq@_0Teo=Nf4c{p|VeZf1(3)U|aJU3M7{lAnKTU-bokZ(Wu zKf4|#YD5b1=ADDodwV@)Wl;iE$<-lFz`3KEqXkcI5Xck@ncFib{t&?Z@fE>nL~`rk z0gRz?lK`j(|76})3fRBXc7T&X2RQJuPc#3uq*PN-G=98MhlB!;|1m8i7w9@8D~49 zCvdJKF&ZcyWF>az$R_UuH8*?_@LBw=<1bkyQXD-Y=mjhENbdJ&{i9CiU&qk3ii~{s zwrZcE^PfSC!uXGtf7ZfxSZ{=n!SDik;wX+o{VM-_3}xIceA*D3Yv-_;K>h)Cw3w+G z^t$F*|J2!TIhI-H{WB>f*!K#IS=}UF;qTQkVL_?^TGV6=Z|Ij?(iX4rMMEP;U(@TVsH*Nc`c}4*%Z?Nd1%ycKF@%pKa%l3PMtXi`a7tRKvZ&_ z`hO3O4oxppEQS+7c{wfU^Wi&elerl9yud3$QM}{7%IDo~dUHIUh7RH*ge*8I02 z|Jdx67|_VB*m0*Z|L5b)BA7uM09TX}?7zt&I0f*Cp*k5A>i+kyn6&;tbwn-KH{cLU zs|31W>aCv9R)A)jVhQcN|OJ(8J-vm7N=`^j62#a((2R zO=l{lqd_A3=>23X6LafkgBv%zv4D_lPQA*cZTl@mGuyHrp>pe)<_oLdj=I+Blpx=P zHUAJusG7=IV&4;;)1S686#DK5?6ipQp!sviGe5zp8VZeOZY11ihG;DRv0}I^V7S73 zhL3%R1NpNpKqJ4*8bG6~b!ggWJ*~ehapend3GZF3xfW)(k{;zkATj@BDe3yqo)gEc zq3qw=`hmlrpBKRWux+b0tG0Q|t0~#HdJ1K@;!sd%BdVMDYv;>I;;Sl^k&D{)?FiG( z?a_=y2eOdWXTnKG+|G3WD{jrJ4P{CBYA%O$4>S zWn2Sfsz+JAYSAH*tR2^SzUi*cUkjw9B8K%FdXg&t*ZTdnNtiEh7Pf+5qSkEjy}u&e zqw~R47AGHH=N_-L;R+J`eR`_T${vRjG&;-q>H?XS&v<`X{4sIMSzwtoK^kQrMjgL+TE8|)uOuNtzV ztU3*44DA?`MRDUp%sr`q$x3#I zsg?y%+~zhN;`Os=&yCPACUeTNHN7k@pTROdw)O&h{J{aHE9h;C|->yJEC*pWt>&q*-N?LhUy#0O8QI2E@{OcpT$hF`mLeM$V&T1H$4zrw0 z9;;&3@9F?YJ#y``lUbJCY3I3WZ;32&G0w&;(Wee2JjZCi&qG_kR2Lf>Vu!8#Eq74r z@Emmt*3+7RInOS-?y^th{C*;8wxK-JfT)##rj&YUKHBamqjrm@$ zVx&E!Uwz%_a~8KwdHMC2+3{j98k0~-oedk0jl>{ zmq{NDgx=;co97k5S{D{#p~V>c>!@bt-pabEkr#?iU`;5f|2Pu3h^|4^fu7^WTaEwR zXeMftt1jbQPRwZ}{vvJ8Z?X(dlQ}94lLa`Y6PKqJt-(@1D)L=&q^#ayh9~9~yh(?B z)x(!5*~JzvytI?H#e9go!@7fNIxDzL_sh;I*oSb0Zm zIt#}e$EC`g*J;vWaB~>3wWbiBHmQ`fI`Qr2I=tz}awS%BA_}Liu;9@OtjWjp(#sa> zj~qDl(MuHGTR_iS6vrhZ;9FKE@@Sm|?oIime&|X>0K(B_z2*+H`?b~KtEaVLUtm3~ zpoKS9nr`$?&&F9#5w-iL!xO4{#8_U1S0s#2_co-xs5baLD`2mWV}tg6yU@EfggJS~B12K?)&O;^bPub@j<)YFswQWYx6@ev+-`*oR&J z<3+Vfz<+}p{fKV6)&08z`-wuw>BW;5mO<^*aD`Ae)f_89NohDz!!-TwHI)j6cU72< z$zMs#A>tE0;Bd3#OI}9wn_i;j%C#H)IgtTG;QhsCZuN-`SX!GupIJF8^&_&NvO@#G zi+VXWh&sQHptnU_mJ0f0GSb>7r|bq2&Q4wXYOiy8@mXid?=LgOU)q%xFu=8Pnu;ob ztUGBs?oWP!U>uBoKQ6AaykW$5oGh|S{BeIsXk9cxku>Y4Dj3M*4e{=@0vTRwBzaCr zpA7-w#|^SuoyzSc^i24zFjQlQDaZhJeOw|{SLPDI zK5fgH50o~V^&hQw7j_ACcRqv+vv6I{uZ&`)`9Z^Wti|>2B7um>=n@Fq_c{bSbykMU^@ccZr1$u4vqz@Kq(=IA&`^FdYvsch0j6WQI%6Qg77r4vwC5pttEo>Q}%zrkF`;}c+hDF*zBHb&WhiaI_5Zp((h z!3UTFh?b0v_QX>u#8>l&niVh^M9cHSU2^bBZ>6;VctP(IK@5)A@PYJ{^|m-Yqyo_q zhTyCFHAEtl3tNcbH7WZLF?mF_HFQC>HKypddX* zCsppJU<}6)&GJ#Yg3Q=v{Zhk7U|eR0>jsRZ___Q^&*5@ijnsAq)uiK6)Qyb|x9>Y& zd-{-KuT0GwfRJm0_t)j^T!w}E2AI{5^zGDCRIm5J)hOmNp@;z3yd)ls{rIjr_p}++ z10qyhb0z*k>oYU^Z0P>6i8VcWN=gHk{l|6*t;&T6qWnX=U0WpK1~X%JwW%FJ-;5aC z^ytfef7D=2R*%v$Yx#*blQ54Swqbp~-H{HCk4Z?_}Wbnwr*hdM`RUMfO24qozS*6)a4uu8gQH!MYC zHS|2!HhPvBFx8qX<(4=Y>Ky@wu6R@vu2~f#4$WIn-cCJuFXRdU({H+B0c^B`58yBhOG`_) z%QBv?H%b@B;vnvavQtI4{7EIz*1b5X3V!8X-_d@UXc?3gTyzVUk4p9GM8LW0l=UT( zjwnxxIbiJC$BsTHsIXQy_JbZ6zQN38gio9{fH((hH5WkU)MWYhdf+72r_H`oEP70a z4Hwy->c#PO2$IPs{nJV4>LJf1|F0562K^?~RhCX$5uPm|(M~U3|8vETy?DhEu222v z`@4qtwJUi=bBP>=_G7JdbDNBKF+ss;_OrbKS{4jg>NwBMvD_x`bdq*Vz4sTv+*+De2O6 z+h2{Xu6k`7C+hEAQcHnvdWN0X(W|)n$zG`c_%)EE-|(14$D$q#fAez@qjMN=Z?MC& z;nX0##}=R7Je!@6L36C&i>TW zsXFYLB?jcqA|DSFWT`*52@(B#ETy|5mAu%$;+ zconMEUQgF?1w*Cei!omKS;&go$fHckhE)@7vUI71w=}#xaP(o&z=HIs!f|d&d79mAJmU?+x**DZogW@Wv1g$A` zgfHPE4!=TU(sr36*#^QLj!hnG9b75jAwxq^;4unfg37-ZE&pq|UDn7zcWkYc#QOKv zM*gVS65rHWh9{ilJ3o4{9LhJb8T+Gl*&=KAAgBdb*a|zGIC8o=GVekzn*^XFe@^5w z{bZUFS-*qLR9HSqqPS8e-{g&<()hAtKlXXi>O}d%4c!?dwEFX2patP3E9fC(snEb& zRf#~KV`YkU6T-@2V#L8ph|_Rcc3=tjBi!T`=HEn8#0c|GL5`U#^R|iQ^q&?$+}~xZ zQi1`uKPrTsHEi<$1N_=n8>7)fSQVPr9zqpT^hP-5*ZigHVR*x`+Rj1bJSc1<3O4NM zH!T8JlU)*mdD0K0V8r+Mfm4x$+2xMk zX@t;)O=34Kpg?6486XCN3^q#Mxbc>jVUqHvPC?6?S>O)|$>XzrU9|Z`H4*xY$QQ1U zr%s%h0z#Tca?+N5HUDH5WtWf#jb)AK{8QknUT@wWX&**{_+aU^cib7o+`(WC`C_o? zid=yk09M{NJmE~h$-5EV@RN&13L0CE?HKcT7I(m%N2>_qPsJ>9xb$o8n%t?V#J}^V zCNf~v*o22_8T)SVf=8(0yY^M;Z&8z*?6+NX=Iz)D&Cq@@;` z8$zSjn((Yoh*edJ`t`l}4KN;i)KMM73)81=p3Be#bG&;70=cYUY*;cHV5)BM)j00* zc?*oGP}_H+M15tf6|w6pr7B?K1BYtY{}gn5S|iLJFTpX~A%tQG23+J+mS*whQaaNGdy*wNv{q9es%|!_Dk02bG<@YEiu_Uj^HOL z&l;HXdC1-R#2%;3M9lfhyXH-=3SN^IqNaI-;#zUtI`Cg@QLr`8OKUzvI%^drqc^$s zvI65TY;m3?Dk(M%ky#_LV!D z-l7PgAOFwk-w*JM|K~{mlSz&ugH$@E{uoWN)z2Ora>)R!c+|cp_VXKaFb3i zKCFD9#;90~dmH-AEvdL#Wk8n>Pwl`+$axk|j}~w3XYEV{e#;o=oGd?fMnmgV(G4aK zu6k&(`cfEEthqg`Cd+<%LxaYZY|kz9ttW0$`(Ub-$NKdu3l@#0-~^$mZN}*@sUHM< zo$^UvW6$02zqGh0(UQ6GBjQrk5>lD2FR8gwk8iM`7K0M<=g{%@2Zb?Ged*{{_*~c^ zJ|SP3ageHPSc2=0_K)-Rhk^bM(WPghU!d^UJ!%PoTOay70XXdz;ZF>CoH|tlu&zve z2(-squTE80s%Z{rycWjjezYYjlx0*V$7|O?{QAjcdb3===)UP5YvPYz=S|d0^9iOL zfq=Wpn_%90IZ!kG)XernzRvIw(PaV9P$YA@WZe^z3EC!t3!?T)##i_CYY@z`CqeY!YzsWoeO>;hHoM0CE|V0o>SMVivKCoys#n>tMXF) zS+D>{p7@#6pr8 zpd(qzy6?4B*@=i#E2vJwJMZwOesb3f7qmimM{r8ygLkf;lS*HLYn`~Vtv~fzDIZ$Da23jn$iTMOxEx~A<1QdJJM4gmC}pGt zQz&M_6AYw8-u8`DTbhG(d@0s;Un;xs6~ds0rOBl%kGPKr$`4%lrI1R#KbCk>hC=F2 zLvtn}w6fPd$gt6Rad=|?76;w@Z`W1%Pe_Ih_4@lG2#Ng(^y{^WZ$XWb9n_O97kEh* zRJ)UUkV0o(u(BX1xteR;rzxk?Z#o=ZJri?Q$_9&I^yzW2MDafO=fVu%Uo1WMveiCTNCT%AY1LvOR+|)4ObP!?H*dU<0#_%} zdl&H_acxC15vuucAtas*mKA8AW21rXloV9}W9YCv8)HJ?+t3(q{s?&WxkkP?6ITsH zLt4eTmLO6fx?@xT*IrRxhO(J}*MFhRVMB_Pbkh?1z7RpsnbCQEsn@h1| zJ%@SIg8r;E=+tY^+zOc|0d{WKqG0;m-`aHO*a^+q&Z7EYhI zS(Mb}9c-cMn3!T}Nl}X`16#^VFxJRc8dE=9%i+?hiQr?8x)Y~Y^CM|2k_ip=lzFU^_wGd zB3V+yanjB1;Y7V%oAXLO!HZex9R!J*$@@U@QlGLgu4+$V=n?tw-sar)0c zXOn-d;pf{lfMm3OK59rIAgy=cZ)E39RJj)`-g^!zvE*;0$>3AQdF0~;-326pprFJ9 zmbOVxOF%}j(`-M2>9>yX0x!`xkzMr;8umT(r(?DMxkL0(kst*u*--uh8NzqyM{&@Y zTI3b8?2lad@SSQeyUDyisHb@wh60^f^PhH?KvZw%-^c#sgBZtY(@2nxIx{&z6HKxu&}P|d|1hE7bd ze@`U`hIG2@Nl})UEFW780>#X_A6eNf?9Z>-3<6don?W@a=ARqs&7ccs^mPG=q zg$|GfLF!?~Ao@GbaDRpY<9JA_`)^T5N(s8;kd*^Yv-agxu{5RzJYw;1s{J0Jw$-GGA$S#3pj{;Mb5-y zm5+qfmH*7sDhH??nCs3dY4Lx*1C$6U7()0mx=%2c{J-b6Ca`W4(ERMr^1p?_Dhg7r zoAncg{TWj;ikoAh4e&st?7%tF?TSokQ2F1bkdgp2BBY>23&Z|18vrnJU|9jl^EmDF zcVt7w1@1E_wo4?l|D7vca%dp#WEPYk`Fj~LPQZi|-@Ebo+O2w~YS{5`OtSz#jDh=S zwrz#z@%~k1L5Uc%{`|<_7`|6K+{rG$`5Yq?EB!|nXGDeg1+)2GE`jO)Tn{Zogfa)) z#*`>kM18y_dex?o(|K)4_j;C#_Z-ev>c~zv`waeG2Xfbq*_*>7LM_rg^;HEK1retD z-@tiN5SH)XctPwmzlE|ids-=oTxr4&eKxNw+>O^zUeYBc%Ux)w>bHWY}@46)lwrr)h|*33syR-?x+A24RkQ zol%Z6<~D58T5`kL;;FeF-#Tguz#fEjWmN=7%(#KZgCC^BAz42Io~R9t34S$C-09x1 zBx0I1e}ywwZ(tRUXp#mNw8SW<_l#-fmXAjx#df9#WlJX-F|-UZ5up(*z4NqYEZ*

){J0RRXHF!_h+g)IlRXU{!wh$A|V$)M|>xTIucM=IyBsE5~f?gTP;R04CU z%p7%mFr0f^2}vM5X38+4!1qL89?W6?9m{u+jkUmT>Xy z!9&-thVTJeCX05^ow~g&a(N2~HA}iqxt(FbXa5pC`zAoc74&lJGgT4q&BS0#eKjoa zXDKLxaom+)uf4HDE{D(kN)+;1xZBO%8{}!O)fw+-Alpl zFssM)+r2ny=^)dy4&2!IfaR!=WVu2@LQ)>fHTBekyK%kRPC8S$3z&+xUszc3W&2?$ ze>v-b&lXT``uG|Lv`73q%_&Y`#4HnB+mIT9#N(A4Gy4yOok2&ewzXKSg)AMMG-h`j z!O8ebA$_bTQ@cmP!R4ToV}l3g@I@oN+4zjPh|ZGp#w4 zRRH?#2ww4{Nm=z`wh!~)DqL9d`etAqY+&l@yF%D14O2)-m?*EQJv*pJtsdZWGZT=V z99>?DJdiH$a|YDHIz13~rbgUTE^c#Qdm1@Z>#-wOljqf4C7nrbq>7P7I}k+@m9^BC z6`4-Yuh6@sHH)B-KK?ee!bwQ*%vs@)RSl*D-O`&vQE z%ny08hL(R$-*%ebxo*CG`tO=s$UpTv(VtZyT(v=Xbib>8v9&4^(QUn$R- zJyhwryLXJBp^dUR^rmN}HQR1UZEi4Q+5B&D@sGnqW-~V!U*T0UKu$xW{E>`^51Mp( z_1Yab41bowb+2^5njaLgB#OM)-pS)=y1L^HUrG3AEYUjbhB_E)#Ly<}^Qf*^xjmbE zLiV*=r~inOMPc38h{#f8+h`a>Ly1NHXH^_ZL?z@L6`Oo(*+LISYOR8>p}@gdcER>i z-g)&osl9-g{Y_Y^0Dg8y1w+c)=4FyII7ddf@N40{OiA@Z_ry%BWo)O?O!!q3>R_&2 zJJrMGs^>m*cde1{X5krYxg6p4@b<;6(r;-L*T<~kwn$k2i+_M3bc>v=~YoTS|C$BBJi` z5^9#?b`iukG#Lw&MAywTW-4wXi6eRkY*-F;?TyNNsl7KF6{oWZg9H2Ip|7RyJ13EHM;IyfF4mj|*D7l`I-5HH3m=t2PS5N*EHQKS9lH zlvNm)o1ZQ47GI1&BdS`KDfxUPV6U9-XJ7KLE>A$VpPY?Yjw_DKx#!mf-l@=nSeLem zQ2(nN{J9&9(?KpcWlOvc>fyhSWRruUX5e)m0!tzr8}_z#k1Z7jgBMusaro`!O_4=q zW5Q6jK@-C?IYAfZh_maqtiom=j3PN5)^}!4>>&YLTd1Ny4x1V{5&UGmhSzemiZUo59)EQ%*VAx!aBCM(Dik_k$14J>y7z%3SZ#H z+Z}fUoEiKs2nXM)Z_aqRwi-7&{M*9(DS4c5aPKBIQTq;R;+ALI%R%vgTY5cPCdhHW zmu5aH;+$ll4^7w%epR6{mpE~<6=QSmhzlB+SC)&HPwCuPq(+&EBMBj6=_(xb5%-4k z^Z0FPfC!SHq?%x#%N`$~hE2?YNIbKS*)nY68 zGbo!k_p(zHEJN3g1khU<%CVPLJ|70)QQ1Z9UjLP@A$4_?_`CKy9EQO_^##1;s@E5h zJNnn(2W|#m`K^RN;=tcbfoY7|QyKfs0ekyVfD8z8t^HG7DJS)3+k6HRK(A3rHIU0X9qG9# z`si8#9H$koS-G$EdX+nFr>Q$czh&lMcZthq-Rr~xntPB`{ntzj9>ua-QT=po71D?u zpLGDR7|0S~N3X*thcB0JiYL)kL|Gq;lW*6c$2hhdI-IsO=ZW%RgeDgo2Fw=b^RK)a zm=?O6&)8j>CM90PqVKVA3dt4jUo<4#reA`MEwu*=WzfW@Y7BlKLf3<9+oKKh(XiM& zz^V45l{B8b3vHXM4w$-)V9XuhuSckp%e){WVf&1{6dK%EGz#v zhD=?%EmnoXrL-DYO!*icsJbk`lopO-T)qsZI#b=%^8{23chOqcy;QPAY}|t^vR5dT@JB$+K=9sMyz&6nD$=K5q8tf zYA>pfNuvC@ta-+1LiXb-mV`sJnq+IC);!~4>y8!yXxR0JF!>y9J5c$>=V{cLo<;#7 zS;HI5${?fjhzqV{H2k%OkL`2**$+_^Zd%2L`0Lm|bXwjc=w*B-m5xkc zT}PMqM743!2eSJdA9x)dBhYz+h?yz1G+Z+B6ft>P<6(;H$z#Yh<4nXmbnDuJm}E0h zOhp>@vZl72^k}w~{eyoQIk7s=ZS>AC;L29>L+q(;7;Ef}AuD}x1ZlKH?|LJm8DOGq zn9kK~au-EVtB&i7p-3Qf4>R?@D`yTx*ztjgKeCJZFB@w6kJ>hp?jp9C$0mv@Q$2U{=yU0@6N(8M79q`wowfaxP#Dq{*{DF@SbnwI1q%&@7#XnuYiav9ckDv z=SR@kKJ_h#*eFRh_Gp;3Mm*a>n^(bY#A;KPj{gPy4R7XLjvC{gQ`5_b2|xE2%sV-( zF9d<^(Ld<~T_PmtdzP)7D<5uN`FR}UpqreXe>o0d+ii0GY4%sE0!YV0{Y(j=%`#b4 z^VNC##kSRg1tlGo@coE1M}8s*s4GHp?_IlU?;7-;1#e_q#eyb%%i|q(q6Y^7PW?OD z0kOD|PYJPV*8PHTOzcUr$A;Dg==Q8%{g9C@EIqHwDoYsh zNI+dyrT3q(81dd%M=UWK5-dgLo*ta8+nL1Urit*Par4n9!q!y3k)Nfy*z{)_v8gLL z>7S4ceyzw%#&RkY);d@mkCC`DQk^$ez>})E%Rz0BRj=+4ErwGHL92!=IPZ+ayN>ZH-d}uMX!}7X8qsQu>diOtx_8L(x)rtT7}M2&mlO^Ip~>M^Y9x>KecHXMJ^u%SaX}8Y8XYMM#?=AEX@AdaIJ;MO-4n z4hABf_fdzeB%?;uM%!3DDC?rUPrN3554_96xCwm*qm`F$OP;a?t*lBi{%@US%|47w z^Xq~(yY7})pf=sdXJ;zwlfR%{J4d8Y=I?%1kx*~kO>fwC_{ha}gUm@gMOvV9b46I6 zuuLNa;lehFzFD>&HLw0S$}Msam8iy!py!?i^~daY%kMH}Uu|t2;aG;zeSE=xR~E&+ zor=74Nlm~rk8!Oh;Y0O0xH;xd=+4*v__TPu#)8mUwr>8aWAv)Csj_P>NHme#1~ph8 zR%Jj8Yp`PY+OV5Dnis9+w?9(}BMOkS&xonOO>*6C8pu&|t(#oZPF2XlMGLFwL z1-LxX$|(5=^^A`8iXr@0!TF~9jzU;HSTIX5v0OPDtnGz&hQ91-y7h5MgU+dqv5pl~RZ@`CiyRHPTN21IXQCePpME9Sc#AUE09Hb?3ggi9A1$SA0Hq4&vRL`CvBqg8kw1#VI0m znjn&mllZ5-Z^vcu2mj9VsEE;SVfG1Y>3()ZLo#zToyVz3-EK&OTC&JUWX-kE9sALT zY-Pdb=H>+pT4vJ#azCFE((}jiA$xP~yio?;*QPatlXI)xc-kDx=1X=t7t*MApc)tT zNhpo@-?^NjVEm$vUI|}m+BPDp4A#OTL|I>2)3UQ5rZP39?vEGNlp_j!DURim6ralX zI(hAS7J7?(DjzxB-03Ltj!2aEQQO@LS7~XOtX>&dAVE}J4Z56?)&m_I;=h_w0VjeK zcwD3(_sJIwXuu(3k7Mv0RaX;=H@7lZkdA~OsiNbjbvFvb4_6`^%Vkn|1h%bkEhK3l zpiF5I<~=WB;>w~Ez##VCD<;|I8E1Oi9C>tY&ZwY`MoN~L@p&I?dkHX(m( zG!pe$%=4v1v7SZQ*{9jK8ooYSP=`lBYs^dl2eVHMyfl^&^RBfFP zxnqP)DSlAAPV-I0MzqhYFT#pz>3jse`tlOn?CV1@hI_*NtYPj;^5#zoh zmow=GCIMY}^Hw9-R=4kyq_7!paBQMJN8n80Bmq}Fo*NFP!O&YBpLP}7L$u>E#mHz0 z$7}bc@*KV;0%sy4e+#`ievnkl-33##HSbMJ)mJC@s4VNOn$U7*{N7v`1B`3w9hM-A z+ivmax;@k^*BVzf%j)~mqgS7y?}0yPb-FwYYJeDH3!NP;ZYEjp34WiI`ujlL-qr_& zO$iJfTRc#*J)M*q{715d5zsxP*nP^*kW1veiX1$j8dNGQ(Ci;(n11>-sMELLf)}zT z@l3$zuir?LTLWc&t;(`3et3X}W3P`k4SH#yx)`inVNjv3!r?YL`D9+vFiG_(v9iS5 zT#NK7q_5ygOvej)BdVZ%DO?z3dJ%>&SYw0Y-rCr2#RnUw*F9gCKxWs3Xu};gS}R0Z z-VV-yDupBJ_crqioY{CR1)VdT_X-M-hscf!W~BbOGRl}+pFSM0?NKH3MI4*^@Rcej z5E4Y788YTyeYQ(^mD%=&Q>P0sxY#!y$F8{G(1 zDxcRKOJlw5g7J9&8S$clkXLGgVsiqt3P!WB%&TUJI3Ttv6_XUpEPZe%nhd->1SH8( z9L^i3dz29%6ryxy-LF0yV>yPybkMBYt{P%rcH2z2kq>IsBv`I82&+SAz&aT#0Tf+N*dE<&aLg5 z3qrF?gA?7y%&bV8xxc`0Fs!4P;Q+E0nN3^adL0I<;a zg4I{d%YZMp6m)RON|v&ZlL&AXfS7@;d)*M!rjM7fEM=umI=WaQBSX$ChLlX`^{bH3 zbmi^y(R4}P*KJ$yJD*VrYHx|EDxZJzI$5|H%v~K z2RAgRp}wq16Yyas+=@MNi`M)t8L>s42Zb?(T|D&Y;${s4FDmU(cd71G@m;8oPC(q3D!VTk$ z;jB0|k4&izTM$2hH|fM?^(tUOCm5BS#ksxKD^UK@grFrj>Uu&@+7ml@bu*{o=1(z&5*BiX5~P5C2z=k==Yb)|M1p0GiQhch2+#D0_JXX z!u^&<6CuA1chcDAg?54MzXlm3zm_+z#Hmy!AeBpDqL!cp#^fBKE7Y9^#jkgjC^?LS z_onusoilrz8UxW5z-9(WOp6Pbwz?cR;@a04%XR)_t>{S@cxhG8(Q=M=VbChrn^1Sr zeu#}ew~yoI&#lFm(2v9Htpzim32|N6PN;cOb)#XHzJ?b^<+MD1mPxz_PdQh~#&Lrn zFy#*P%Dsjgk)5QbpIhQVAvhlb2Eb!|6hv1)9yeo>dNLWnxS0YiqLW)ybc0k4ubAL6pyS#Xhyqt+um8p zKEzeLO*X98c<*Vc@3b8ylCRfH#2w`{lp1nKTV9J{Bs%{J!a>+b8bTegh%sg zWQKtWNfPyfJGQ*wk@gPDt9vCHS@2Em*ArPgnGey&t9y1SM{Sa^6|S+ZSG=L`RH84V zI3cTOsHqz4fi?ro;UWVOBwBKiBM+RQK^p%WM@C8g1d6G_(B62;I`Ww2CKt=N+B_2Z ze~1BADl-z5@pR@l75v}mjka#xjLPPAa$9&vsv32us#iktA4f!^k8S5@n2UktLx#iy zJ5@*Z_)0-1=QgF(z!O#)5{tqvXZc=Ru3e=vWtZ}@QRZp8jPCj#%KQ@L)>Y||s^7j$ zDs6-ES1z;14VuA~b;_)*JZ0_K8u}16Cix@z_o)>>qKh@2+QdfA56^!@=5{TmyHokA zaDH<_=fqAdFXj7{D_DPQ-Eh>#QPnq7c4} zNNvt}Z;7O)%=$97oFLJh_&h6cRAE$R00Fv?6qEbMU`cZhHir5RU%o4WiQs3wH`y&A z7d45wx|7ptV=wH@&S};i?lY4UmcetQ|;M{!o!bfNpRZLp_y)xa-#dvUq9>mVh#WU?DgO{5a>&TNw~Vg3n00 zSH(J>*Yf|ySHs=f+HW0JLyn*D{l z;GNGz@gnwkV0h|)ba7C?)mxUR5d%{KnrQbUQHOZzbL*M6l9Uy@io2uyGZDW0S^lHD z_hfOfGXo6>W##aC*~~S;PHuPHFHsT%Wg#qpDp+Ua^H#ULa9jAU)KGW~@$lx11!bbE zOaK>-^6{cX=TX)USnhjd7QT)NnTlFme^&u``5W zSTU?kWs>H&8+6YI$-sl(m9vuF%4*FF*MX*2*s>APW@S0f3YPluJ=rSZYmNvva~o47YjYJ?t66U-++f1N!TxUa>` zItUY5qgOcmGT>9D(EvGw(f*U4ViwbNH3jkNp*`iirA=d?gn0EobY$WWiJAn1HWw&3lAR*t$(K^Iwn&!GnMEp$Q z^kaBkj2}x0T!;SK^(C2Yy<9zxS%ViLS)jHWw+6JCx=U7ZCX;B&-co>YmG1#Y^TDB?HKbO%r(cz%pr{Lldn3p=3lMmCIKO4 z*Vvw2)8AhXy5T!}3^(a^XGGuYs(HfBRiw;5ssCRYMkp$ip{1P%67r=VhNPDnqnZ!U zVN_#RGyDq=KB_9;3_3A!R3aiK|9|$}A4s-aYm_&ZfB4Bwn$j-+_Qe+IOlnwuwH{@I zk1v|e|K%XQWql%F-|rwD7Q6p)IZKYffMz*Zl)=j}0RM2?BfDavO_Ul&nBHm5&VTf5f`Zw4WX zC>!ZjccbKcESPc%X1OM|8cfLjHE*D<;d@PF-mHO&MKP0um zQH$o^fM3wDl<4#J-eN;Nh)%sCR&poFnd&dP{5tk1I*%__(xgu7iJ;!5?Cwle#O^^K zl=D|sD5qcrrkC*pq?>;|t7jONKRaOT!f`YH=oJ(|z2dBy=!MZjSY2*Gc)R@rJCq%O znU_Ej&dw8fY~rG47lX!}F*8Yjr9^7ka9Vr<`|67;bo*M9R26=?_*TIuS*&77h9(jP zM^Iqc)3E_7D?#EOw7f++n0!Cs^C?{DW@hNpqah((JXFXVhAD}VI~yfdcd)(>+Srq4 zTb3B>p~7Sil8WY#;ejY=`}YveGmccKu*X>H6vEB1`1LI}e2?9%3nK~~>9o+=E2^!+ zRp^Vj8|o8P9_JBfL`4D`*H`x^AbNc6DGn z8Y8Z1b72kqAC@EUm)tcIMA&+I;p78n(X47JvfzqRG^mR^{$A$n%f7ns$>Uv6{dzTu zn^RvNqZ0OF;AWSF@e3|s>EL&x%RQaNXBtpRyEWV5Bl$QQxU1Dv=g&{iwsnsV?t7`| zi1~f`mgU9hng`mRrN^|-B|3a{&ZZP%UcjiK_=zoIXzVUwRNCzIezXK7?m*eZX;=at z>79Uz1N{9oN>-(9ItHg$GQpb}C*PQ4;2%3JX0Ykqa`61}+hW_w&)*B8)ej;Ek|`&- z*^|go_^Klrho`3kVq#F8?E>CNat^DiLw#dDqB}Hd1=MP*o zUwnxY%|Dngfw=z1v1p45vA=O~BJIc~Uq3$R1vmYt{@hL%VBoYOQInp!*dO|Bs1&(u zhXve5k3DExdO-XA8ClFUW6;uJ`rH_{K_@BmIFdT}UXA_k+WV#E1H{49rapH3oaGhL zmG_imoM{^z@ZF=+iJn@S`-XY@F^Rj(TTwgKdEc008P+JI!%azX$WPBPopx8ChP#2Y za|P=h?qcsj@p3YH?4NMz(YwbwfGGmM z>qD6H%$@$tVJR$@i%p$lT4x!q3h%d?lA=jB_9=cTe-eqr(gGIN-cmdCM7Ak~?~nBEKHD$mcCLlo`vV88g zca((w1rFMsr$l4#Jzr_MXYT1Qet7i^FPKFFzV0nTqh&sc6IbwLe5j|!tv+-0mXGhe zw!1l2fOqZ|*&)AYcV8ONGp;N0j*bx|}B61!8~NjXmu zny9?$NYSX{i!Wqxp^$ws3bbufp{{t%U^1rfXmf1T%`1h6A^dZyIv5K2%RfvGO$?}E zL3YrP6)M_R+cM^hJ{ipv2VRw$1>y0O+uDj#Gpt1@j|4hv3Z-|3~lm zMF6UUW6#8<-|m4F%oefnu&msLkHcT$$JKTev~q4iBQ`M5SF?Dcx6%Y5vx1P&wA;h_ z$Yi`#a))DGY?zS(m;``WRf+d+8y&e{bi`7N^O5?COUXvIvD>{LwhL~6JbQtTG(&__ zU3`bg|9;IB1GIM=w&4|2lDwl`@7NxZ8Kz)wU1jx-Y~l-E@KBp}>rvNXOolVs-dwWy=iWHvlkBTMc;nohp=q_*VsnHL zu+^5cjKyVig7%nczeLk9bMk7zIr4RSd@xnTh7o%$T~B?}Hodu@1L5rM*kUWp`|xP5 z&HpLGWop{{M$i^e>=N@4K}<2E)Ds|xe@y<1sh(YtebY$Y#qEi!u!@EQUWrjH&+*hv zZOWpKqS*cUjJ||Vf7&?^ZU9@~`eK!6qk%Ak$cO#a))+TnhJ@BU33?u_x<@M? z@o>yiky7YESY8*f12Q3{j3z&SN4SOgton6#lNX! zz4pqoAz|z4{5MgY$^g-jdRh-Sh|1Bu35!*pc|#?e=zSSN#vS^4?gGr)ZoEcg$_+Z# zkTYApgkRofU;MIfs@l6PoO2!IR}g+2iAHxE@Bp1&=khx^rr+$EAn3`GCh>^!_Zp*o zT9&;s+#{-xz!P;ygy+|KVnH|?{grx+($LY3FLGa;_uZ2-60cfQ+mFOR+Q+HA6wj<- zV~u}0CEEKM`Shh8msUIHn2Rm3se3VOa%*v5vY^s;ZIzC;o+=)CQ;yHM^QWNoLR%XKY3{=&Hy zS$F-kW$cy2n+-F5(3U0`-* zfU&shMB6cz33T-{496zMvHqZsd9mPa?*ZcU@-Hxco%mZ(nJi!)=5>x|1NQlVS!iWZ zg=N1J!7RkqX7o~BEGC_OcPURgs0pKU_)@{b7HSarjzR(02Fy~L_Sp0|B&U`&l2zED zePj6`gAPwZ%*VJO-{F3q%d?M@%OtyV;kmN$KD+Tjd$2~O0X&<3Xh1=U0IDKWaEt;n zDSMEDgr=Tm_h$45-VZ+G;X|Yo)aT=?IswYw>49Xzn^MY?2gJJF)$Y$~N-}3SXIu5o z@8@3MvN;{9Ekl?NkO^OGwLdW_ZZ1z$jC?i^HuF)jI0tu6N3uoo!}l#z?oVFJ4zj^p z4>q_J9E#!tivKPIJomGd5%AkF{MRg=Hn7ZqTTUMM0SDiEl`9vB`E6>yED`;pC(74m zhAgVY<$Ce<0ovOgbKmmF6fKMMB`7_9jCu>GjI`Zo3SC`P(XD%kt)tA7NX+jPB&ar& zp!xav%NsPbh$P_Jz9t_~o&@}m^NGPh;g~^Pr3Tllhcq!#q9F2qTIqaYCmO1tXge?>&)IaCxDB+w{vai86-0$$ja~1rd(oLrAaIfTbX} zr4of3ylpMk8;)z=(xhPv%ywwUQ91Fv!mSoAiyoeOv)!4;du(l{^NkXNwg%;>`3+U> za{_(I4x8K!6&!UQl>G(yqujytZCvwdw|-xLzvFJYoiaF8;tQ`E7_g@%O!2rTU{3Ug zn?4FZDDy>DxqCt-_-qZ%^VRYdkB<*l5&ncfGf7Rei!@Fqg9n-$F{_N;#M_Yl zF3GEn6}}kZB9PZ3x<{l(R}t+BT}!$Ppc2EH+Mqp!T8z+_)t8Ug--*HN3ByjeQx%A? zW)tA+b-!9-=)O)5F$6kEPfA6wKx`WreZH`!iShIt^@0!Cjp?!LrdYl{I*-j=H!lz-W;+yTz6Q)FT@!Jh4UbpL+8K6cw@>%$?J_=1=h_@hTzb3Q@D%sw z0euv*z3WbJy1#oIimo*s&3+a>1V#5P0Ydt=)xU!uF-gM|r_*?w#1rR(jbGEAR>pAz0 zVlysR29@HWPsjtIFZK;_>xRy@DbcS;^hfd=J2$ATwHI#cxxcD08otLPsH^V5L2gVK zNL85M+n|m$OiUAp1IE26!qCILs#^dyH~!NB1zaGQC0bX15=Wi4Ta{p1{;@z@aj(*JsP zf%E9`;IEwIoIdcF0F00L>8w!U=*Km<`)Z;74XV zLypUYyZq_od<|SIDm$S5fI`>&2?G~|AJU~_nmv#~u-*f zu9&|OefZD@KR}y4#^tRrs&jwqF5xk9`~;uN=LR&Ns2#%fZ*_gjzH@&&YqkyYosby? z+|G(TKF1c<{wlOZ$8g?yL^wUg?d92t`9478I74*lmIcuT$hjQv?wK+{1XQgh>sj)^ zOvMl&@U+12IiNs2E1GOIE87HtcOv$x5`)Hyx$7;=<7{nWb*8&>I-@zicp|N!1Pq?H zVK_K^)NU{E2aTiq#wIH`J!y1a@$WFAU}{^sL%bi(oapLl(UNa%o;CNLoA5HmeF?6; z1i@YFgzt(`1%LC`yyn1p3qbTX%Z)uhlun_C*)b4`S!~8ret(Ctaz4oP@j%bwZNPEP zY=Ql@HPH)IF%Y6|eVdIA#=J9OF<$3)h}nZ?4~|jw#PQlsD0w4hbLgMNC6fY2VXJ&O zB*9@9!>!lSXNiZ)>40opk-^EK$?axqGL>3?a4F#h!tR7{zuFFY!)d@VT{Nk7kF@&2 zo$WvIYJ(5xhpG8}BhTU8YQ6c7wIlaVj>aLXG_7d6(Ns-X$SDufD zE#gX@CkwseehpTJG?%EO&E~eB5vX>#NxNi9FY8P7r!b;5OM{V!a4z`xrR ztarUxvjIn}&6_SkHVguTL-xtto3mlG@Xz+`pcuGOwU$H^L2s|A(Sd{8wD|BxPq$(X zZ*O*E&c1=$SV_3^8*u#}iDaU;uK4dgdP%#^O3pd!5Vy|*J0~W&wgLSy0~K;K-)ZzE zZCA!9f?3^p-h^l|qU%5jip8p>0;CT}A_`~f#>-VYipd!v| z1Zt9H8$qbQ=Xhl%)y%eZx4JlV0Ff?#zJ?<^JOA9bPboIK z0n)jhp=?+@pmgJi%)>torr8-snM~(*^uQIPpu7l99BJbPVTXJlg^w_qT z_W7FasMiqD@-qQmRrzcjP73?5{UYHZZ{49!3MU!&gRf-6jG6?$-4Er%2gqXtfDlb0 zLp*w$a6yA|A|quIE5`6fBHQWUbR4LWXHI>BSY|#wHBo?Ji}2@KAA-tTJnFgaV9s$V zsm!HBz;5gc0Pb%K0EdFR!vn!$D{<=L5jDUs;iY6byw{~5$&{#fE_ffxYcQXoBC=i5e=`XNBV~&RlA?;LJ+8!z{KS;kVmNp*`g^wO;VuJD> z7L_vF#HuHQ);!CkfJk9o?6X2e(G%1&7wdlR0+-KHXl}H#%3&CpsEheZxbW#yUf0)8 z?v0u5cX-jpUemXbU=7-CYEVbGWvnjA-x zM(56`d!S0(Uxcy`=uRewGkDE?>3L2C|kVs&5 z!Du?kA@n`_7I#equ`BG`1fnY?9b5oS+lAk>HN1lfKy1Iazeaydz2ySY#oQy*V8f&S)*AII$ZfxG_*NIgFWaXl`NgKh3%G;dY?aaV z!9GyV+54cMbOK!C7?gNGvR7ToS{OEtD^C_Q5zCb;ekzqK_oT5}=!#UUB5}d%d~{mb znmR$psqyOSu>}eFh4nQk;gjp^g(ui~01{c=HxR$r;WFBDp7W0H)ZIY~Klq?nuKuh@ zTx%si<35i7qL*V}{WsoPkC=)3+< zIeUH_H?RrZu(n3C-Jh7*C~2YUt51T%yOow4RFih_?+cFxvd3m?{<6-(?z+#;2naZ> zkDIc>AQMYJF?fFb{^hF9H3ldg#!_|Jkm0yqrSbK55EvxM*+C|TYU+#6_ne91DB5}r zSCx2Nz%&aCTvpt?zQ#e1GFFBNT`$~y+mXJdrNs3^GZ&lDlX9Zydp6^xl69aE@g)I( zOUwp=#)XOx62P3^X7?aCjfys6_q|@15!EM~?+?Ap?H$X`r8;--h@j%^zXS-JmT8q7~rQfQgswYVcf}qZNZ&$(#(BF?x)i?RD16 zsrH2(=7=TR3sF^$_lGvxI3JjYicV1L)*U@p?+BYU4{UPf_0py7x$fgY?)fUe>^?f| zS4v}@j!A0^6MPh(& z7TWYIZNK~QA^;8#m-KbnvuZekRGW|=wruiH>d78Yc7MJK$1~~ zwn0SM_?>F^!&~bJebI*>LpI-3`mWc>u&bl3xBaF;)~SOi`QZKh;=f?If1=+OFq;7V zoPYl)wkZS*)RiLisJtI=rf9VwO<#2fX|TU++IFz~qWpiTd&{V}x@8NrarfYEfdD}Q z!D(EA2X_e`+`WO|E(s7EB6x7u#w}PNxI4k!;cfW7bFQ8H#vN~r^W*(u0Ns1nsx@oY zT(xSit#75>u-iHi=dsO_F5peD$`#elfnHJzBk+bymqK;qXhK;<`q`tQH@riw~R{+`nDcES0--Tu1P`PSkNV z2n3AYOr8}7{Sd%h_7_CF8tpMsc>A(AgQtOaG{9AXgZg&&$E%!Ve1Ygz2Unt{KkNX` z{fjz4nxV^7M+CIlhb&L7!^qc_Q;%gu1EGqIL*{Ms{ zvKtE$HEFofK~p0B!{w@W`L&O0+9=O*{i%U>Ws_KFfpqEO5Sj)S2hf6Vo4wj+43rO)t7E2T_p^K;RIS=B-Y#q(NMbp ziA#k;o5gJRghPEcx93@&pWP`uCvlgqQ`g_elHaqz2-MiU8eIww$l=)X)9P^}mQpJn zq=eerNLxhP6Y5>;;`hG8&h@ei#Wk)QJE1D(Wxt(fc%!c`JBaw#mA(;{h3*~%R-$JX-cV1QZG^tTU1TJST2zZR~?De>BL zy(}8G1G!W}jf_Z}9&$BDQ7TF6@XXhsc}AYxcD%;zsdypoU#uyfTMT)9V#s2icU{|Y zn9LG}EwaEpT$qsCdbANuT|oW)3aGhF*(9q8gVsfGJsFN-A0Tr`sR;T?S2qQ(%dz1`rDgt($Q zb3+uqX~PW$IrFX1st5{Utn8xhk!Y9Xpvz}AcgA#YAvEX>1CYIs3f;Kz3-0XJTNS6J znYn&70vgwd7S?HBkE#$QzzH6;9$jt~a%K9eOI~+l0C(NNP-sy#>s1dtqa1Y)Ry~@5_d(0bXnx*RzSVpbQ*vusN0DhdvUp#)@{8eQpe&TNy$At`n61 zQs8HD58hS}v_`APEa5F}*^gLBPdWjUEH9(aNO9{hubOpih>S^pyG*QlLWXCGbfxrS zn2KF|+VDErYqhz1IgT(Yp4GUo;&imI?_<vD(Z;u*ot7{-OEEFF`W{f6jA3n7`zGkIcL{j#!=Ki z77i;daqDFgO|{V-c!hCBbb~}@vA5)-5^Lh+h_$IiL_se_a&&|Iqmb9CmL#tIrKGOI z&BdUo0kDugnheF|tQVj2_?CS#*b|4ycDGKTY1`4R63%^QZROUBdhDF=BeD*HIN z$=YCod%KZgEh%Keq%}5+Hx8LcGX^$fxzvxW5(6Qz{I1pI}&uJ>yhUoWp-t| z^N}5=W~iT~n@rT#LTZ0B1RG8qIZ#MTgbm~RzA(uaPVcW&Q+rSejfqS?a|CEmrn2(Y zCJ~8&kj0l?yh#e`1Wy8#>~wT(G>Z%ekb`v8w4H158JobT64y|LA1+(<9aJ&jO9?#d zXgeGXl6YQu#@r8u%r+nL5 z>`9sFm8_Nq`lSx7ZQyL>STa?hK!cZN3G^j(oh1C~${Gi+>A|~}S!aUWJPYGD2P+l& z09-!ZAMKt#Guk5D(l3|atztY1DtF4YASAh5vQ;1;BCFbD(rSJ$Nvy~jMlWR;)I}s7 zN~xO6YAi^O&J;EKa>n~7v|jZAZ$ak{XR5+2IO*(kx}(fx%z4JGGuoDEe@Nh9{1~zv zOjyNvCyk5^J0A>`5gX(dI$r`cMQqq0{~c`TT^~a$DiW3u#&D*hf1W)kq=m@;jQO-J zWT!XLpNeEjhKi166gNQCn*hokC5lHD(;m8bLUP+yqaU{wE3#Y=o6JYgVrX~#d|LXW z$lF(P@ZTKEbX1gh_+ZySR6(s2C$$?o7sP8(S9l zzZW?~l3qfKoj1WTa=QN%C%6$y-i#u0R&=W)f(g1ZlOY341wC2(k~Ui=Kw-ghxgWuw`a2klsX8}flBWwZMuA-aJR<;F8RPBvSo|Yatb*kcs7{>~k>i8_U84Cs_a&(085)k{ zKfVC8=S%t{@}5Y>EbJh{TcWu0$fS7C!M~?HESZVjLix+Pf0=wt4J8M)qfk+vNpL*< zeP7c5kLE>xu6DmAnnUQ*B~;=^0kX9&<=Q9c||9+tR|iZQy&O0yQKl{qHzyK+Gtlkf7s>F$fU zLB`{Je`4`?MPe%>z&L^OY2K^^0+X>31(gOL<7icwqWJ9SE~cI|p27mQ)e*vwEY)dp zOArIU^hSezmja$sRr+fVWc)$uN&C-!{rri}qTeu{(TSt3LY@5~x(FJmCOanCnP68h z2kaDf=pV;LlT=tt(`hIGXZvT9;5CQ?Ueo^o9sMeuQ(H?2zS~xEN9pN&PCY`7JOauS zSd-Tq!h*rCVHu2d1`MTw=l$=<`Hr0p6Qi<1XFd}JnwCz3*{j&?ZDVSMTA}&hzM{jV z6Y*z~LkW_g!-aiG^<lQWmgogYMiSJ2|Ze+erf0w$Z2w($<%*H?wN3{iQH#pg6;j&H#91WwUKC_1$TnFv2}PC~Fvrl-tIE zGC(3;4LRRvmFbY`QwSn2EQ))&`mdMnRI+N=utU@$=euO*drT=cpenRC{hrv{L5bzVP56QO#_gv7GJ=w;qx3? z>7gnF5llXuL}2zt%;8xLThNt+@3?$c@Ur}|e7D4HhcYT?fjMBnQ8xA$AF#<7&;C=P zo)9YAq$U@!4>(wa7Tyv;gf?i44?qZGI23p}CWeyWQBXn?j%tud?LQsf^>1Y)ssd>Mj#+0q%c7Rbkd!;u+hM1>$&+jNCxUZzL25FkVxxy;)G=yFSYBg#jA>k z%f@3=CDxC9qzF}*YgGRmQyNamC$#hyizikUaV@Ed)~Y>uX$Ir2h7tyUcN+3(P9N45 z#-Y|H?2!Y@Py#4#myiytOMNli_GS>6HA|`rp7kdIFh~~>35LOZS?Ma~{64uLK~Qbw zdrjvP&5n!tYk!h z=p#s+x9Y!|>cA{v@?qmgJc48e_W5}O1q{B89s)%W%`f!4e|o7#3Zd`o>)VDq+d{+j zNstq$mrZ;{1QtHO!X+!N580}rg{s!?CP%=`Tl?O_4fDVs#1{8 z24_}$gdNS}U`c4R+nsEk-f<;4GpNQ1@`rOLuA9TFfs}Zmp7u||)c#Mz^?Jz=Mytv){sx&g;+upB z0;y&I(u>4A#8D;;UiFceiEBByY_ETY+RcXfqn_K)3aXeY=z_jsfiby97j1v z{2MHmSg>V?D%EmKrEJ4GriAX-4{M_&kokM=-=)Xafc#rargnT1e}Bo7C;ju77WRrJh4EwiP|Kmp-1)xM^*u>ub zB@6$@|1F~cD@jZwUi?!z{@0Ie;{Z50rJ+Oo*Z&XbMrJ(3_qQSvI;OvzOxq6)tt~EC z@p!+2?sIpE=D>kfwnkVIEO2m7H0L-F5#gfhu+cebyf!DPRk7ylu=j&9B=&BDyzE`M z3^y9#kRVp+{j;U{6$0UhU5mqgLmedD3C(0{#fdprhRcx`DGmOg(PN>(EJ$X29tYm= z;1-Cwv#AQxf3^7U-(KLv-7|wK@fflG`y z+*?hlEJM>WQvL0vT3||>j=0xOB8|p;eF-psXn*FtQMl|DZh^ILO$?Q^<`!S1y?_?J z%1?X4sY&5+t$0FhSf6$z~C7h~tMtkPFzQLtn=$?Qjka3l%%e2&z7#p}UCL?^a;UOv1=pS})64n#fVaOQsE79N7lJl^!;7mnOy*Jd?O3GI~= z!0ME}8a(ND1M}(!(~*{~;cM~6XE3a*EN5%A0u$bH|n9>~@%mh~J}x4`iqBACqmRkobJd#cF~>h6FH z$}k_~(O!$Fk$xlSPBGj;ztn27IZS(n_ys&jg!aPMXopgJ4fBM9V4R#ZAl@lY z(gwTyc*&@@V#TV{i6MhXn}9UDOs4aer~ONOz`I~Uq5&?Ny6zLjUY==Mus0ExRkI^*k! z(YG-lF3p8GVk_1~w{3Nx5yJKE^c17wNIqu0;te;M&HRwSfHdFGi?0~J$w*o>{xE^V z_R4&x)_xxFQgZX12n>Y!?s-~Vm6Zw|a8bUh+8nHM1Y!cc2i-RWuH2qI0x!}tNug`X zf7l`HJT}|=nfG&rQ$CL$sd8P@y@%Lnr{O55WRaiw{h~9ICx4##RjVea#*0>J{mx6x zoC)_&#{@~xB@b5Eunw!d^;K5p8;Qlbu2Ou+o=!b%zOCDDK7k)mcE0`zR&#xK%re&_ zU`N6I0WMmP=G*!@mgJNSZzm!W()5VKC;G~{aa{rao}OoDR)OEa+(|=a5?t-=%j~2v z659Q0%Rf`nFab76g+Z$?<2I!-gs-5Iet%m3(O zn&zCX9k2ahuy7axN2-`O`}wmcS=3imXqnvHgDSUkG6hGvk0=-~$wVCNi%k%fvdJW; z*ivr8Y4u0d=B{eY$H6Tab6fC4RL5-IQo*{pF=OLv{qdi-Hh0DKKC^k6+T8g+jtd;v zH+x({pVbJMM_1)e|FO%vVjNYLk&M8snIH#cY<2*&w0Tw5ld|XumQ7V}c;75^AV_&$ zwMo7Kr`gKQNv)BfR;jtS1~*_c)jj-KYrS6+DfvwP7p+%w{+VPdn=r*QIKNSY zWC0L~ki7=1j3?=h+F&mL|I|%?6+lJJGfT`qZ<(M?^s{@)Y`VTd^K4SspU{H5b!E)NUpBmPhr$Q|C*pQ_bEy zyHhRrc6tkNNYZSn2I)6uo0oO)nn_OAnZdxLpdT!Xuqb>EMW^;>Q72#OgS=z1vILH9 zqZgtN-*KaDMZvgqYi%42DM5E9pt7f`R=xODI40Gz0S?B3wb!)2wr1i9eCB1 zpa=3f{CWe1yb@wddEGJCSlX??lL@&@wC?Br9YDYmV4)0>d06_8l=#rPpidBJvi@Ty zpy=ne>I1rJrIiPL`^T&0Rnnj3)EXVRF9p@%TheYJt6Zf@NAep!E}yUzP4JGhIPosU zfb5hjcyYo3S9?JDA!pfliDUX?{DOh&E{IGd*o|jUh4Zp%5FE5WtO&IzIWZ<*4~&;U zcd&+YpwQt1coOWc&2Vwd?C|Fjhu7zlolJlO6;JiI?SS6p9~Me`=!H^-)bX`ZS{~9+ zY-Z4EPi#l{$FGNI0x=-(^%q)2U972SNM18T$8YuXYKr~=nDtd8`-WDb&G$3;(bls#db@tJgZQo&!?JvXIk#timo%p359tH+)cI%5a?^)JQo{qPlMlbS^;f#M z5&}eJ#f$%Zlvmo5%Dw{!4{b1-Zx)%?kI04f=M7e!VxTWC+%b~k$`xPvnw(1(KLaUI zl9IGF-^F9^aPAFma7Ks6wWLCYdE0;0{h`VlD6^E=Z9S>TuOX{{-D11B`g5CxV(F+d zULs=MsZOu1u9(C^H=2IzWL@HCx_UniA4`qNrvrtk(9@e4^b#w95Koo#WhRVy=4eMW zWdbuK@L00R)s$A(*9sTs+ff{FMAZ)eAC7H3ONci|VO>>5tX~Aa1$t_dHh$vZ0%Mtn zR%g6O+Q732H|=0eaLx{b;k2rAB9;k?32AqBS#)8dNG?}m!z9bJ`nJv5*ALw~$E7q@ z20Z*dp^65so+mVof4=|mk@Q`xFi2Ss@D4({^DQ2>=uB?o&i9d&#W!|tGUlP=4K%e$ zBPLp&EynfoerL?-OxHwH-|T~&)&ogwLG5tCl$x#Y8dd}wm<4thK4%7BcZ8$L>t0zg zP~u0sl`GiTdzU!db5csq>{$=nZi;nvU6V61mv;c(>M#9?EXk! z+h)pDO{vudM=^LFR-jz7!@`tj{vMmG!}7sGks=_}ZV@C^SlBd7c5U(r|Dmu0Qr96^ zubb#($HU*&vnJeHJbX@TMUh3xZM)L6)6?s`*j;z@gRoNY(NDx!khnqc-wRENA77 zwXndT^xpB>%IY3v9`zl6R{if-)p$nvaLSkI)~jRBZ$xHT$*`d3;=C7>WPuF(ZNpn% z`nK!YV7ba`$TF7TO15lY^Pj+ET=@_Ah*-2pJ*?`wL$^%L^k2D8*lez5a7Dc@N{!== zrPMU}=77k7w)Jx|Oz1QlNm0IP;ltFBG(r`Se>0Z8;_cP%`SgxtYHmfDkxt5|8O9Gc zL57wl^)U|uG80LcK&2CR;_Szr1WWkuI>0?ms5XmoFSk_?h?8FB%LHaAlyw)rBEQ>b zg#E)0GS4%1yRwHGcAvy4nDn4MI1GRVg$cMo6OAv&>P`=MZv9XYY(&Oh$S3!$;5KZw z5#fmsw-eWS7?Y`N|0$Vy&yjDZiPbB6y0^0GJJ~^Co9-uc`|J2PIPajvX}WOjeBL@4 z4=#hF%jBBn_QJPmVlS`|0epb!K4!=6hyE|7`D4G-^x={jUsZqp; zzcp0&W~KbDxrco9D+P|N$AlGl!_dIjd^78S?5tnDyPb3?d{fH!6d$pE{PV_Vu&NmuG9jDC~I*S;f`&$!X`&?D7_ zpn{Q0p*{9z&>uYa)ajfTjt;_WhC)9YmlypK?_VkltW9u(y}XwjTz$;M;T3&m$!d*A zoUx9)M!j&J^-Z-Y(1N+;IO0FZ?gA^L+?Nu=}OD>4E81+SOl)l=(1?$bV^0889yYzcC_31E#>OsU zsCA>4c3*QT3&(y`z!PsRFjR9weI5q0IAE8{+tUuwrz~0_|NQZ_r>y{`bAt9q3G2R2 z9{T`<5Np5boVXbFl7YJOq0`^+x2HNHixxlp_A5+V?{j`FOsR04faH!2Qc1ZD1P1lC z2(5r+Goz;PWP+b(p*h4gHFl%lI^_76YjAy*ySYDxL(e7ndV08usYFJ8n=>%cu;9h> z0`E~{aM^}Jo(fB%BB$P)P(R`%3d#x36Zk{UT&twM#IDW~Ip1yL&?`nMtOMqoae{{s zZ)jNCms&}B)U?Jw?37xDl2O-8?C)Z9mEQ{&u4r;~$>d#OOH>1kd3MU0YCtQCN1W?z zML}xpR(IbImt)!b;F6UsFqe)Ex(w#sN_pRs3h^Y{yUr`>GYv25AP&A$&m_G2!vgyY zf~XArM2Te`2r^`3wZk9YE?2%{h%DpWI1AO%{@Egy8XP5>4F0@C&dr7v{XO!ET^;$((lqdmr9j{-m zYw^dEZFlaaAqcoE06A>9)kE8XvHc6JF#+~s!WlaI$Me_OHRr2}hoe&g8fh)5O6*j0 z`~AOnNqmTSf0W)1Z=RJeJKpd0`y2`EEMb(%xWL2x2&b~-LJ{KV5;4YG^VKeZ3Plljw8E@;RIWhjoxd;R1O0;tKUT_54ydNfC z0+h;}-r)HARU50}@};#hwE>2lwc9XUqD z7@8=j44Z4cO6lZUWyx5toB&?1-it)Z`yB(EupJ@O^s;RH1%njCM~0HD#_CLxejsC+ zwu7b(oPotLwQivoo?!V=hQD2!6SGRzpY(1B4JmdRo_*CsFLb3nY0M`7S3sy?eOPY) z9w%Or8{#>J)IiJntbD4}w`3vrFf37Vp{qzPg$#kgp7eg}2sok9^kdtP2KXujnCA01 z8PAvmkqD~3DIUIkL(31UDy=-lup(dR?@_pO`+y~oex-OA0IHo&Il!j0wI3#5?f`s- z0;aPXmb_CbjkfmojtPD)M&Qfs{Lp!-{;57Ow#ewVsa16VW@M{g3wW3STE>p;niFQDpjr6I40 z20B#Cav7GzP~i;D^$_Grwc(27kKiNXcs}NSuDc_&UHy9ZZSaNk%2%?IFTO@$TlB5| zu8XKU4W+j~&hKbEKbi1xx}yA=CVPg8P>fd6(U7egVCup@!w^gSIbB8^^J+`m3uCUV z{~2R#x|uGdIu=W}*P4IK?P%H3J7%sXGWMPCx-w<)3vgQ1MMqhI#uhYR-=p<*69|3PYGOaz3X2rDPn3{8&<^W1&d|is}EOENlcp)&pPY zU-k_gT{Rc?>aKy5CE_{}feZh={r?|7L~P;j??PXM-3=YI%f;^Q>PQ2Yz289+dMwQU zkD{(JdVtMsqy7#uP>_DtFTeXA*ZEJibuOuFQgUEh)UufH(}#a$p2%DHhCUpi(?K%v z^Ayd$x{oDAfSm(;99*`iZ}z8u6zu=gEwEuDXtOJ5vv+_;z<}L#997}vm?+qBELn%_#>dlUcu6=dS5L13H#jb7_!mconNp9_LMf3?`GNve<+}9x;$4S zo_=)*+`~*{6>H@yE{=uYN5S;2#X=W+(=V`C=F`1HSflnyxhInq1L9ONKFGiZ&~r~- zwonaIhe=@{Jc3dWKk?`H%O$oB>kP@Hxz_Fw474hlGM^5=4{7dK%XhW5WgbjDKT339 z*!lRhUtey%TY=jg2+r!G=0IcO+e-}eBfd;X+?U0{rc4auy-8bJX1Uk+UPOh5@4-GG zn4&dTwLItyk5Aw?<0rSnJNH&OyqUi)NBx?1a}a(~0A?yO7R~kaMbC(ecix z?m>#Wf#Q6Tv<2|>(b@btFRn@N3C2Z5p;Bp+W{Zq3rEmGpEQ>FS-?lvd$@%e9xvfYeE*j^n;pgEtsj+mEmqU>3h!KS@k(wTCZFVQ)@NQY%{RLi7~kdhA# z)aI@@5kF1)zI|K0dyI{YOZm7B|At~{Kop;NDu8YgwQPI9@Ppx%ek=L(Y^sGOABfwfFG*Oq5;ld{7MA6BG-;GuQx2{8GR>m00Mv9c2BcM8W21b#)o z)Z@ZY1wWh73J6QIYNrkv4zOYcP#sanIrOBgEjN*=#fu8WKZAQPeCWrqS_Qf2V~do4 z?3<1dZRQ))$AT@nP$vz%Z3WKS%bR!&v+i~+s*i;)>WANSBr_ey;XlX*tG}UmJWjNG zq1>eBTRD>YdfSysn-nh=(^ldL=g=@u>y^UZrnK<&+wENmw~T}gNRISMafENL9ih2r z{>b9`F%>vSErYL!1}8atsqY=KJ;fdhbEH0ESw*8?Vsq? zmGBjdKU;NjP&%xHP;%t_U&d57W#R%GS$Rxe^w`SLlx>6=8KNTizAC|3>N8j?9mL+; z$%PRLpFIoRf2=?a4`-{HLGYl$jK)FU`RBszi~6|KN{x+cZ3S=Jq}0Zkr?2Am^Gx$v zE0W^%v*3jb52-J6IH^aNU<;=tzT$(Jux^7fUG`8xF#hi?e)Hp2^o1TKE4-7i&%>c2 z-R4?}9{A{MuJGui`)(4c7svqTFIa(gfCm-bkiB zq@$cKZu}h|r(j2-;rs$TCQCrrpnNxt-vSJg>BxTCbdoOoKzCG_YVRbg<~dCME9&Xx`mNS$u~muCV}Uk4_H)<(L#{sd9?oEehWOjBX+ zz32smfpGvE5);T3J0F*%@xk!IF3;h0B>io^sKd{nK!7ng#3Ikgg})~cKmTIlXBX6Z zN2H44L@UC*0>0`4S3Yl4>{D#L;Ywvx0h*TZ@W0Cn@&$`b@&gTAjTA?DP^n%+d{1PEsc_L3O)<>EBihR^m7K`=Uz7?Db7XHseRxfVH&oQiQ8<<6z2>WR zL2CNlG}Z_O5rU>&trf6pk`#$Peb>5wdH+vBgv(#v|DssX`SHp72^zR;inJpD{L&E@ zN{;&kEC?$G*X1sGLh-);F@W!tnq%;uM#_E~aih}La2k97I&a?=c79a-8#Q@qLk)Tf zp|4pL=hY=CDzI#VZq?&Mm!!`t0qn13lL&uc;};0@XS)7|N?BM%*%``tZo{gMpT>SN z{$o!aKeAZy(!)gnyt)>MmGe1Z;25D zS+yORDnjxbXWHAnp3kyzq%ajY7kx_SDX*tpW!t1NvcKpSCLiB$<6jwAsk`Y=mehi-{V3&7cKwycKj zt$gW>>Ok`%fR5<_Fevdc(ieS66rL3TjgR3GD)gD@V%gT@Ahmej?@klz34+Crj(epP)eR%^AoC3)1$_;`*80cnXZ9J4w3mP;i?vu`%9`p-%#vRa3!9_ z?_Segz757|!^%Jj(7>Tev&0v@Xj%jyGDrL2T;+?7^q1zXsVvfEd*N=i4|B+I(RE6Y zis9nE$G|=SM?a5Hlkne_kSxGeQluWK#sn40q^t1lIK82msN;3j#P{q4m*E_1N>Y5F zoE|RRN{kCE*xf+>$5{aHZ;@NJcF|!Aw>~oYVrNtoicxigWihH0Tu5c=>xZxYk{1aA-@>Q9RzCA`r{Ff6VfWj3j)oqS_~>qqS$S`a7WPh|U*@m8{8Y#?g_g z?f|rR;Yg|dfLXtczblR~K;g^pj$Miz8luXM02j1}K1S7Ylu(+Sde`%xg04HRkF==1 zWSTxCn{?<-@X-HDUHg?*U-HjZ^)j5_r?PGk)5#ap+oi>^rjrb9u}nV5kS%%SstC}u zL=kes=G`M)C~&HhaRFZ6lkB;lL-xDj$i-cg^0(>qJ^lx;LoTei-hQKjHDzFuP4sX= z4JdI1DNC+=>eo(|J1*<)Drf|teI5`U*UEH^ecKDskSq-%Q(Kijl(ewGR+h|CTNY0| z54?2f&K&$+_zurJv*E14x)yjGJW6r`RRx%`2tPA~{0Kp&tAw*!*<~X~I zSyFhCOf({HU%se?Gvs0aMcax6>8|y3Sk`*!4MhNn0o;96M1$29yKA9-D%&gi8Uk0#zj2|UE`Sk#2(*9;&pRE2IUj;GVjn%pS?N!ic0x`k{=KD2f%WpOds|= zTLFmFNyG1bm#B`B@E$D}=4oGqL>0i-1A@gd>((?&`{Tcp23bwwt3LqAu>zn$m_nLZ z03&xlfR?Rt9BtP(k_}Jz)O?$#w({mNDwN+ahZE-EYyo>Sig5OtS8ExSXww_V^tWjp z;VQ0dPv~ggg;V}_=9)riA8$q?%klxsed70`3e&O#wiLf2Bih34#NFH8N9HxurtB+G z`ar3EiG4egf^CTpQxUF#<1&2n2oWI~OE&sKSGt+Vn7ewM`*Ra{dY}V*I_zeR;pS)R z6SV$K)aObZS&aYfNz(VDD&u>q9n>LQT7RVX#xlzvjt{ns*XzPPvf?V(GdLqQ@%$Z-l)5!v1g2LMF&aYVgey!}Bt zYT&Xv9DP_zX~HCG_avl*r!6L)$o}6&eFIviKd68VReY(b;a}MMHGxgruZRvy-9|z~ zUnSn|37_iYFA_aez60Vw?U(FImlb>iprOW~v+7{a&0VpYdLNXB4Tmpk^O29}FlD;| zsXfV8bj{r~^nvG^$pB#LYEdF)`{6~t& zE@-fTux^l4tT-x2H7Iyh`8_WJO|L!e~6EMdjdI(Kek?EOYD(Up95qJ0 z6#ecm3}+y617(wke?k}`!)f8wtaJdN^Wv2MyUtV61!P`ijj|YdP7RdzKpy$QQ(T(O z4ds#L@J`X#nwG#{Hbii?$H|~yz6JSz15~vf6EDqd;$wqp;ydauz(P42c=RK)%`IET zQ;kN%OFbO?!^5snn=NiMefjR(xk*hi+c{wWfnSvI}T_?+VYTqT|n1HD7WE9g(-9gq{_UP zAaeLdJV`!PQMV7AeEn3n>v4E*x5)sLhm1?#_kB|>luf#%0Zibny!9c8vC&3tRP=6} ztR*q>B5^8}UUGrmKE@O?KYgq9md4RQGkJ(2ATiA?v3ZA578)NqnKZvDJVen#$h{Zy z?7$nA*5Ul*!etyqnI)a|o0LBpNF_2h?C}Al|6D;Fmx2;YXYGS7XYNpl=3gMLRXS`O zVoo&)V3f}>+U(jQT)dfTHF~`p2nn;uf*-blJ)dud!A!>#iSVVE_*|Ju66`uqE7ndK zvKz0|w$lTl5dqK_kd@W97w^=Yat)q4zF?jAbaK=xif|NN3;JZUE8_lQ6L2_`CDF0;KC@v- z>za93w8U~VCDTjVy2Fey&v-{p7W8TArJT_a*K|{59peH8w(EdTC z4rV`y;Z;&V@PN^(kZ#q5#q;5g(H^0)8|~AVLGQ|HXc`v3M<&CRObq;bI0&BIm&Af< zsz3?Rp54K2(77lekBa~ReC?kz3lxs2gkh_2r69x&@o>MGd1QkvozQ>+5#Y}{Nj9DD z9WRieiDa=Cp&TFzeO*&yua#$)c5{e+=NGffR(mysc8vvGkyuNCSjDUuDg-gOu;^d&<>wVw;h3!_@3Qo>32gr4kw|LaCVzN{Knr1 zI381xJxup3hu_#0WFdhwc)bx(dHjg%3RI2qX5UWsex>$0!|NTA7N7rI4^OC)JRq{A z-9Tc;XwBJAF@^;fus~`T?CNpXue4Co{mlX4pcxZkj+JWSMhQ5P<=2t!dJk9nR3%vr z<*^uV(g!5&q~JSdrT%0ZI#w})gFip6xo!^`uh9|x-aJ#yTnI6&m<_^+>rJD#zKB<< zXoCo&Np%-F4RwZmUKEC|OczSWEXc&5SKPNT4p^%_(*hfoMQ57YL`7Sq{cQEG;z}9k z{xF;FXean{L`U8alGLkBm=GQ;zkTX{IL0^;zHO(AEfd=_B}3OP)!mKZou6ULjo(w% zVZ)1S)@Sb8;O5pZY^8Bw0%v~1ZiuA)wU9F_id_#|%bcgpQm3aT?j2m_u|=Q>@w#Jj zbX%@1d$PF+Ee?UGcQidZF^^GFtt-UOU$T3Ed0w97=k?tkO9IQhlGFzqBQ5)$lN7q7 z*B{IzwPo!Yt&=_}khscl4ZXtn^(SRbi*9Q88cv)=ePUr<+l3u^dzTY&^E%S)R`fZE z$m~g(7D{(2*Kfr%Goq=;GYkgn7G0mXNb7Sjc9A}(vVe|6Q6p>WNc5?UpSEt!*&yP( zk}fMt%dn%?AqqZ%<9ChI!kzDqcq6;sT@sqLftz1q7$b2fFZrsoMWQthcYVgPof@Mw zx7zL89OKy7+;cLlD>PJ>iM4!nh$*4iJ$l!4|W9duCk#V3SvG;SkusA8Hg zM1+JtcK)>^ABvj7i*_hW1j|A%gt>1@#l0o&!`FRH2{D`yW98o~0NR%Mg_@J2zv-J# z$rN&u17#fU(i{`i8KNz+T#R!s&pX-c!69xY3e z!~LQG=Z-33Fx6pMxtH&?Scqik2T5|GV!omkd4c!IzAiewD#xQ$cI-*Wp2U|QwnXI1 zcroo(kBH>H{dr-KN52$uT(-xJc=O#0V^&*<5;*ents=w+*|uhG|0*bNqV@H)>JoWb z`fh($5kteNQ&TGKTX$B_Y78QTj``XErsK`*i*Mhm!W9E(wfVStK@MByTpP>Z3M^8h zt;n$!jS2$XF*JC`SotS{9p^tLWAn_2u8}dVsW^HL!YpCX%hsmWInD7p8gWc*ngo=E z@9V)L9e}w{+nsfS!xmXy0*6&EwMB6D%DP8MZ;7ra8bQa=`lF6S^9)`Pa5_u}uU-xl z#@dWKbO)917&5x84OTFj>&sL?7V zU~{iSdt9Zt$6~Q*0VH=@6jMq(oZ4V0Y9rW5&RM6@-J2xP@d2`1M@)`JIh6hfua=mg zlNeH35Ho0fMqHM2^u~mMR;767xcfcXXn8*4L`~MOnJ^R_-P8A&+@D8W#N1Dpp5dTb zk&ho^=7-N!3{;H;af#~JzRG29@&r9@--NHj6yGb~b7 z?6X73E4s8f#Eiv{>xud`<_MnoId1V{jeg#rYHQw`q!BVoijChIQ{&0vU#t3-!HDh< z3JW6Zs;@pZY?PB_=N=w6D8;#O&>XjMf}1je<{$3*ebR9HHaa{b&6J{PCn2X^Pz|ca z*C#$n-&J2E$$k}Yi6&aBv`UhFuFXW7L{`Odf~Z~p>p97YeC!XLvMv~?Lv9+I9|zWX zu&U9N)@pLpyPl~nsMigm7R!$dyDKNcRyJt+ayB;=anu7dDdtkr2ZzrXmX+E*OE_gy zQgO!O5F7Sj9u_>4J1`|_6v;^!ugS{Awd01T?0`LXvI3%q1+m4{$9R|xN+M&`sQ^N* z03?Auk~hS9nT&!r{<;V>U2X5FKQiuw-5@z?$KVgSlJ2lXhR6?;0ZA9uqNk^$TgYa~ zH$Y}EWvYKAoo5J^6y-2R&(ARzjKAFEF?4u z>J&94ho2&CM1of#Q{QSTkhN4B?Aw*IwAtMc9r?a+_ikB?N+d-0jBNWm9UqFezHOPd z(i$;;et75S6^y{N9?sc%JKwg_AgS8MZQ!Q%ocoBw5IAiE?&l6x3SzY<_p6bf>kqWM zS)r-bqF-aqF!2QvuYy{f6j+3mqA|+B3Q8XOyJm39p9?Vhh>MP{rw+rwa%P#Hn{ifw z%JyOFuLcE5j^FrtCtI$1f*tqu4!4SS-v2)Uzd%60JFa+2JaBaa*GKRVu}FwxQEo4K zBJ2O>D-Y}3tnSus*GhFJj>{{T0$XKe+_O%rFE{QBU#QuRn#<#ZJ>F-j=>Tx39kpK` zb%1T-BX{!AoGv!h4eYHBX?<$pxbm?6Aog$DIZ|z-EO=J7JNnv8uZr2Z(%QKgdSn8I~B-J1Lo5ibV$X z!G3T!hWl^wY*?F>@UbxN$BCoULR-?)&u7s@dFZ@IrdR@>ahknDb-bw-jdeDrFYgWE zp6e7YBjipAz8zsQIih>`{ex^QkoMO{RWY zvS2cwPT;BnjtlOK3^lRL)gq5h-Esr|HF>QwK>ZG13h2QOfAQs#+$#G6`s^b**Fpo@ zjF$&zy+cv=4gNVRo$fHicwK_dFAWVGJaL^3;))kt&*!T9#`0aG4%0=0&cP_|`A(sv zuzt#+6OymS&>b~KorJ3eMzGGvV2lR6ZpGz;XHIJah5m@)5apR+eZ&V`W%u+#Z2jNW zHqs>L^VKV{tbIrXKEXjRZ&SDowB@)>+F(*^&j1JZQ5KKk9#P(I;EEh=@*MNj+MeRVq)Z70f5eYqvH_f zJ>k5*{NJwywJ`=3#=dV{ea}P?4DQ9&8%6A}7H6gO^qv7Rt7hz5GMou!g!LujK9;~t zqXB(soIVq6bc_RhDWb@)v@Frw@zS>d@H~(%ToJ%KQUPrhf!@rI4|4|rU*c!*f%|%5 z$+YGWNRP+s@1L@803@~iJUD<#uq+OY3)vKlYXg2`3&3E)%wof9cNnKWdkh#%rhv;@ zIflIRDdH=LSt`zq=meSXm6*)32+of2_wmyxEQ0%*-F~ zSY>A*Va(3)W$9sDr4cq{)JFjtacjL^XN1P{EX9}da%TWm9dp-xJ|U_*2ZzgorsP?C zI9OV##BBrriZi&lJT&ANbsw$_(44C{Lx>IlKG-kYrs2>E0JqzS$pmb;Old1IM0=*! z|N5$?x!7R!zI@aJY*RJ+MMw4s2J7RC>I(TBOXE^}?qn#RB`)o2HLuju7&Z+;_4>I< z$Ca_o&x66Tl9>!k;wl7v53CROvet84nP5hznOKE4DE7RV9@o0;j80j%Yi626dsghe zm>*VLTcy>5vWZ}yjmvA!0U%#HS^*XPtU{nYx{=3ztU1thN{bU?u_Cjod}nTu1Hc*F zsZ=!)u+0I0qi1bq%7-)JV(+%LbPWf=#hC}A^QsN-@H$j<0GNaD;XoT_4uYm2H|7C* znOJbY8}B@XFiIz1?iz~fv*_UjZU?~MK`m0QK5#cLZ8qm;Zj@^W=inV0?9`7(m|vUK z&^zJYK8)09ilSUb8~i8GahY{D7`oKtRZ#a)4^K0X=(T^^3oH`-zy-cn z`brrKr(6r9O8TlE1l7|&s0FPQ^^Cy1Io;>1ixo!YP8nRCK%Oue?917iY&1BT;Nv@3WvI{?PR`bsz9AS$j%K+esB(78IUc$-*i z--RP;0C{cTxY7_u9n~CG9>Z}Ea9zM)t9H$-Eav`$`M%Y4by{30iK`vWTX-6kXW6GH zD~#IFGB_0a(W-9bQy92%aJcLX8=|jXYTMlfSZ5r4?&6uKAq4C~z&-~6QXJFv|MlTs zeC&7@KYx+d_7?L_5AUM#Pwo})b4Jl&`~(JmGpM>z%xN9hrW^p+p&H^##kIgVeQX?; z`|}1>{MMJAR}ZYs9j{{f*s;>Db;kr>ZkxxI1=&;#KZS&yZ!BvZqo!)JEIHgp5R0&W z-g&|0Q%0YxT4ojwfNU~>s|NVIO%AsJ#Bny2cMiD+)}Ygcfz_%Rv$%t^LE3&!?0AY` zQw*ag@E~Qp^P9ls4w-mZ>*(9gd>X}~M7q@!0@edmeNbZl!h$}?(Ds&B zS@A9Sd-2j+IIl+q%tAy;z@1=gTEO9ud-RKU1NgS?J#s2y#|KFlCFeC=vJ z=Aj#9x~K*E#8qL~?qu?LmQ7-uEbcJGm4KD2{u~wq74IShTx}CB!bt{FY;^#Lpg_EX zYL0##)gr(9@LR+f854ulM2*jnMKC~MbptvV2LSFNG(L639S*$XAZ9vBpPJJL*5-jt znFB!Ey5P}h?^dL5((OXC2EJ)UB4SOP7}!u?`q73~MN#smZ0X{fJo;xn+q@usaR;=xRd zgOQ4N(Ke$Fe7aEv8!6#!ebt&?Vco99mMQOS3%l}SK-#KrJevk}xH&|hDfeI?$RrN( z(E&X+qz8@V`l37N`Y^CAF7L%HWkO$qQH&6fAJ?5i_&HUvvxEl+)pUhBimC>o%{y)R zRzJSv--mHpxU)Pprq|&ESZ;mC72h&w#Ly`Q(8K_O+LsQn?=aGM1z6{F%DP<>TB5gM ze2bvCBL@2Dcq3&9c2N3km1ff z+m2*(i1m4mw%g-nflx%7K%8rV`BW5nz%Q*dL2CiW5$$%My4xn^ie`7Gx77il&3b7| z`uydF#XB>meX6|j5z+efj<2}^)t5<@uK>UfZ^eG)q8N>+#bVZ3bZ!Frw}mj7?f~$a z_A6^0CL_NBeuY5agXqzh`6nwo)cwT)typ$htUR$p9T_*Z{6(US3#-ODi?ej5Z3H~8 z{;>Y3#FXX?z)m6t1#GrXmclr3=2H7KN~*n|MyZ6`iQiJ-Ut@q;@B6Zq1Jp|0_XdWW z*3nMN#dY#%lkR6TX_n6L4>syYE{n6KMPLp4N|&A&AK^tdonlE0TsjB8qWSffuU#jT zd2rM!5Bk?nFuqL1;I^g>ng(^8+(LS+s@)KuUafRA@nE;wDm+|~a_EnE2h_vD6+K=3 z({#Z8=>Psd@p<_mv@*Y1PFrn2VK^d0o5*Ju^?quF^U3VE`gY8idBo3(mdPT`2Kfp; zbdZ||)MZJGAFay6Do?sMe*{#Khbny3l_ZZ7lE(I=Mtf2B-3~u&)zKF>CL4MDqVZCL zX&IxZovfv!Mu0_cKN}hzW@dwFIG zF8(-&mpyRJnpLpaI>!cgXW`PtG`xeUu3EktR+zw;nVtq%vIG_{EGxBUes|t^r}pfH z7hb5Dh9205fb96sOijX%vw47}D`Cxw-ughH?oaZxJ-x81QQG=B+4l6;=6HNKzJ^P|V<5Kapo?c-$H7v*jt4h#E0h@GEU}bT0zU ztt*#vaRX6J2oM5YjsPuJ>v9FKiG9*5n}DTkl|Voh`%r}sC6o%8XwO!@9|Npj51)$; zz|pO{Vc^t#@Z?R4iV&Uu`T>Z54`PS^5H|Ad0BgSpq3523T}S@`9{uuN_~dc;_V=dX z*MI&joYvloz{{`Az)kPG015EJ-JZ(z{0m{r=U;@_`s48bJo_~4dhk%OEMH(4hCY8E z{OI|o@!kN8JoPZF;zd6BHOTzr2ux*XaMKlT1BQM`#-D;4aKtu!{x$9W9_@er-vB(1 zd91*z$DWD7sim9XZ@-g;r#|XMS^<95`zlL{u;MOgVKzjT(xV+>V{5`jW zY+`PBxjFT_+)NzNHg^QLaS8*S``h$Js|XPOts>ao_emb@#j_o`sUQ;-cxZ<#-I52% z!!44~=}<);s_@}1?Qou&0>(pGvE?%`jGyZ{wCzvf`HNRfMDbC71U4=2fdxJIw_qjg z;v;>G$5mMTLHHDY#_Gg(z6&qE_#AkG5eVbAcE9%0%kc6)p1^VXC*a1aY1J9HG&uw7 z?%N4Ro_huGlj4v`C15z{hsc5L@Z{)g5Ffz;yepv?eqiA(IGBG5?pee4?qiHG?=7&h zDqn!Yl^oLWF>Ua#G0^)#xF4gKk6w5a5A^-n z3Alu@&gOcMP0STB_ogQYfO};#FUo2e=fv4FaA9h;xjZqz$V|PYGZS!p|4vx9U;$Q+ z3t-)rop5aQ0u*1t=ZAOhfs+&5b7?weC*j!Mop5;cqUk1HPMw2;dv?OXTHK!j>XU4`F_1V9J!^#Hk~&XYXFvkAHiMfBRwYp1p8N z(2Dt-JZ#G6-U{AK`B`1o!rv+_-BS+%p<^ZeLVY`U49;N(V1CCGoIHrOwr&qxn3;jm zgL^f*nw>lYdv_khdl>HR;wbFdc^D?gUXaT0buq}yW+ z5?j7KF?tLh+Oke-a~G`Jg6-l-Fjp(H|37{QZ%eExT;*NjUx*s!VX3l(`Gv|Zmhrk*< zl-vee?}q|QjT-|4G=JCAej~8=5ceTF>JJkk79-hUp9b5H4VFIE_Yw4suEV>rad#`3 zBTZaL)HoMU&vUTydsaFnZ@{u8>#30WyrBL*C;ifiyH6n6*#|!n&>ih&ShjzG$mks0 zyGjrH<|SmnuMMjo)Z(u`Q-ikk3$bLg9fmJd3^Zu!J&vN1A{bh`MMPxfps;ifR(@k0 z$ZaaDZ+LNQ1>Kz!KlA_nr%}IUJC1Zo*i(K}L}T@^pZHU7-1j@ccnJ@G>Xu-vY)0gJ z;kbJwhWHNYT`Zt_TO@K(H#A zzgW5|4JM(v*(6j+ZVYuMDUFoh0QV!(d*+{589JJ(IJ|JzEaaOdU=+m|Qg+cbq^8a) zf+4q(2B{31DudA2NM(|Yyny+(mNFCdzr?b$@+&VB_cP@ah$Af4O;2@eG6|IuT-mLp zvfPpGBjP_X#hY%vKndcB}mUWPiMsl^_s??|$c;Tx3j^#(y-qZe8_$ByZkk?IT% z6^C*k(`dDVmR$iCpQM);&+rS&&|??%__S4x;U-bflj)vTl1smKN9g#A>0jE{DHzG`wK?XPb(1lx8ljoFu=Tr0 z=T$Gc!liXUS0yxBIsz^xxgYJC8lkS)J^;OLdo%a3ZEWeJZ$80dqWL0Z{?H3`rWV1a zaKAMG$S_}wcAx5KWNoAuoWm^tV95q`BQ|W8UxTdogB2{w_f(CKDA_0Mbzx0%v^ZPJDJo~X>fEAOBtZ&$i%-~%7F0A7z=19l6xIXJbTe!*dF~-kN4{{-wB0Y_D4x+#e4tcjPyT9TSoBP~WBo1EXdHaCA4Y4skGO ztAr-ou%_KOT1O^QLy6ru5{@WJ$l# ziEA>vB9&FP^eX$Z58XZoatlnDA;dmeQ`NKbY2sVRLh!Euo#dY zOJKu3+U&Q4S6k$y59=q6aURf835v5u~G;fCLWO(hR6V5rLi~3b1j>HY0nz4^v}M!1rr~S zCTTo6#XW3QQ^>l{Vg`bnEby~Ag3ssjFU{-3WDr+w>IWwIAWZyT#~GVLxN?{31-IhRl`+_fze|C*u{-4KX@hd zr*s2LizTVa2qt-)B&GSq$x{<{+MSfFq5+i%XpKg6XQCv?qqzj>XsQt>5=z6|n}lp9 ze0Gr_uQCrHFg^B0L8GY=h?yB+01ViS_&a!dnQ&*t_H{Jz{7mib;we6z*at`%iD96t z61kcI2?OGVnuwz+!jYIcy5IyEKnGcKt)k6yBQF%2NJUO+NSy+a=|>_+)TGcsLdDG>a+%BQZs@(6bg3m!Nd~|xDsi}@H z+I&oUI_Q*EWUR5pxzZqV>3yAMl2VcucCDV6Ya~@<5Kn5A3;+&Oatp-LRFb9PMq>Q2 zIgZ1t3%dJp*_wk=Ep?58QC}q(EkkEaqzk??xg6rDkVa^61ZG5H{79!!oQQ~nFr+z@ z^#kSHAC9xmCYoQhjeG0`Xb;4tyhH}TP}T=Z7~g)3O79}+oZw-KRxq}ReK^*75#Bd?hOl-q zghgHpM~2E&GWtkVUT`{{g4+{y$2jE5cwA1w;cy5Jrz>=CEkW{m+=9zRvVOrSKV}|G z%0gqbQyh<2R$q8RKh5ht#h#iN0W5!qGh+TRGgCii90t;Y0Wg#eY&8FzkyNy5l5#q=SYYZAw16K;^$CDBU7B41-P4^QMP ztf+B44%h@rr!^5=f_OSxc)2xIMsk7T2u>Uyj zV2ZRG*oLHrpYB_^*pos$ODcC`hf`>&VVg^hVCH)x1p|P}#5Ptn%623|$wy*VKAH^q ziK#RvirmsFp~Y$y+KJ&1xU3{T#p*$){bbLDZ^W3WZF5Vz(2=GSWwgb$vym}Nf*kHx z<0YiOh7p4@{K!imxs;)erH=Xtm-rymb+!<}sjVdSfIkv3OGIT;V?Z@TTV)a?ce^R~ zMVrbE1M5P(k7?=zC!GTFK1d6?-OOAEk#q|&mPEo`>|=WJ-)nbuNfI#BFUd7fM>{dn zSRZ7nD;`HcOt7w*mY>&CwyJouR}|AaUB>h`5oN_~QB$953S9RVTPe1XyOa8O`m2 zjnuQ)7#3C3ND_^&Yaqq}ttWP30J8DTPxO33lXOC-)i(-OTZ^D)qQV0hxP!S73wQbD z7v~|C52+4W+k?cP&d@~bUbD!Ip!SQo-jASNQZYV8P`tR4Cbk~Zc%}8w(rytf7K_l* zY!us~vWYX>hqgY5%)OY>JycVlqnWQi%*9-Xqf=;++}ar|PQ`jOaJ>lc8$E%wh1Adn zTe~P{q9k@qB%(wrjNxJ+Ef@gtZeWEN{yD=D z5Np!wRQSiVIb_mah9HUa5E0d4?-1IX#Enf&3vtY1Or(D48yMltIqhr{E^mfp(MpY`x?GCk{ze>}12%!uLc|#WP9lE&g0sUW*f}mFu`kY53@wFU(sg3Q zM9e_>@zV~HBGA&sBoG+0MI)VN1{eT7@nlp}CvGI=)2)E0v|Mf`uO-9OHBxEiGLp!@ z6o=_ii9y`7$)_poS7yQ}Pp_2U*=8)z3)~$-QyuBR$|tXE6Ge;%SsW{7z3F2_{129B z7~f?=(?N_5kH^C=S0~xkU>iun5hvVZjF-WP!NHg%f%I$>De1&%nCgMVkYV^Wl0AYB zYm>M+rZRb`ZF*05${| zm)}VJl5O~u5-AvAT!tQ%6XVPk;obMOtBQcpR8M9xs_JDm8b8Y9CgTfAvf(XV_R z;%Prq0nr;91&h@#ILN;F}Q)}deZ|K01Q7K!OHCI=%f>TzAjN&NHUGDU6KlbQJg3w27n=O z$RN(=b%Av*n2)@c+DG093J9qfAByafcAMCGND@2LcH*9h?Tf^HBJv~nZW#dFNrww{ z%EPa~m*m|fc1$F%oGRqOF_0b%06qyxr&%#3Byka=6Jj@=Y;Zk07Z(KwaZly#u3Y6< zlb$DRv6R!WUwM)XPKb?Z22YfetazHtHbeeSkprveqPF63bVoB2`3veC zDa$aD`-p=x!Y0tuVGf+oaw55sL z(q=@CB1m|b834*tqY#2z7U!4YNSjw@i^z6^H^1uvJMIJA&Gj)g< z#9&nT3T8=Xv!pJx`bd>5CQGlxc4h=^EXGp;k)r^Ws`ikx6z3>|U?&kj zCO+sSaXV$7QWEPdjrdG`OEH1@2F!=z+{lQ4_!t06c(m!HO`OJfMBMZ#jAF_gJo$uE zu0yhaQ{5)Xs86cu;Gz>_1D*JX%#Yd{ah~NB8-y?nn?u8K;V{!Wq$D^8VSw^El+*>> z#Pnlj;%Z)gk>Oj{PRvu1Dv=ogjgo{(G-4;bEF*bNR(sgFh;6%IW%DJCopzG2(wVG+ zm96*u6kiZTV`n4@AXUIG*;HsGiZ13nDjgb_8E23OHy_^tBR66K zxe?=Spr@1Ez?v(qmEu|#REvxL9Amu?>riG3J85SUB$Z7a zA&gyC@|f#`OB{Ex_hUVx{fLlxpHx4X(MlTkf97jVr1gT?Qf|u`5>c|N2S#GY#MOhhbgXHbx&hRod^+=g$wCf_Xm&iu-E_wA&nZTh{(D8gnpLxd zel-csyd`ulO@R7C{9}eBlpb`L6UaXci#OF{>&lWCFnjR3gKb1>-9ov@p#*bTx#`h& zUi9HnyJR}K@L_&M$6@xW1|HEbM^EW*948Ivr2Z_2jgu$zI9SWp0Wh?)loaKnYWZZya z>7KRkypNSgPvn8Nu!!GhC(svd0Qev`k3IGn*p<3KwbvA3dT}9&i;GcQT8iRA)(%mE zpG|CM$kkBryZ1vEe^9&%evIpm%AiQha+romD4RnA<&-!ViC~;KPTgQyTrky0N(`i; zUwOOFB5T%CY~8t+#vl1~b~|A;o1ksmg#};RM~H?|bpej~bxc_z)k{ zy*=GH+h2l5H+>ha$C(Q(H;4fWgU*i4%f5+YvR7AHLvsu70jUmPPurX5w!chXvvpX0 zH;s8V_@zKDs>yDh9mkI!mo5QB>`?i);a`4sQjV71zY|MfuU?1+uf-VY&pc+^ykkMKN`@tlf! z}!%9x9}ka@os$1G;rK;=s=>u8`3ST7VsiPkq_l}(X6 zk++F*1DMD%U2U*ZF($4yoQ_s~)06=ac|wZqpHqp#yf`L3WqifGG^us_@cPoG6k z&sp+qyAc)Z&Cuv~;%=Ebl+#4}?S2(?v^T2S{3zy^m7%=69Od-8bnSZbjcUh_e%28o zWey(Q-A-F8+9d@-G1fm#LeBQhC}Cyl>V}s#vL}xmz?!KGIRhXNm9YZs$MDM|M{(rH zk-*j3+KQ7s{V2WX^Ay#N1qA0`e z2&SN@pa6x1h5RZmUy3U7hY0%zVBI(RczF~bkBbN&*u`!rtgmheFog)q zIDb*Wz~N(x?J?qDJaK4=`f^6A}=-m^#X?S;e`tNbeFCU9#IYjqx)c^bd(J%pF)QN?%8GK&5sj|27l`sGnHf4{og@;@E(18#dEK{y56BvT20J z4l#+H*hyo4OiL|NQ)mD(v5=&5u6Ggih%O;8; zF)`Ia{c|cRBfCdpel?knd#B_ALr=Q=;o@?NWF++@>95x`2~LksaI`aT1!QE7(#3)) zi?ee-o_-R`Y!t=wxVSs%R&v8X%orM(_wgJ;V}pESDe- zv+M#T)a{U5tWL6FK>HDn7ls>-ACrXy#-t#Lfe)}eEm?}zkzuG#u0tBhH#&(dGs8$s z)I0zu0GVgtkW>LG6$Yjvm8p^pEt<&yQ&0sUOq5np2WFs+1t%MAu&!4-0)5f)#!AC~9B-0naHQgidflPwBrfW6 zL?#5s6X}D>CM^OYpnM3>TqxN9P{I*yXNWMB_hSCy{K>`~3pRy&BTZ!upBDl)H^c<$ z|1`lsz`ZFMp>;AlAEcsWm+i;sTWD1q+`n`{CC6kYV{k#kE{sFu002M$NklI7yR$47ZOJIFf=7v&cXi-ycQqy`|*mE!!V6d4xpL59byHk)82 z!>d-SCEyAxXtO0vkR7EM;`k$v2h#j6iu98)TFEnmJP*px;bPOw2rFOv1LK<+N@e;! z(zxUv6U5BL_BM#BRN>_r)QwoE%P(;rY7DH&v7QH8@576tJ`WcI(%vS}7o<5~Qz<73R7nR@nzDgpccPcXo#AZx5C#mEWT+u6FJP07A25c0bm5 ziA4-X)m^1NTxWe#v|O)YuIa>DTcr&~(;r@y7y$A(V84}uMbdMP#dt~v{>IFPfyN@U z7r@*Djil$s!l9dtL^hjk0ir;Vi~tU1MLHJDtMyxI`jv+^?jj>OxUP`lHzKMXvdxIW z2*UtFPB|Xgy;j)uq^z$WY{kJCprY=utXoe0v$+-f8bP!~>8K&~7)VF_M;b3Zr;ot$$I1B2@_C}2jQ*2YlRX=ANKIwa zym<9EBH*|87#8PN;1RnA>!wqGCz;>@W1+VPUGFm$hHTtGwi*VGlL&B!`RaiO9^ff| z^{ZbE6GG-B^B&uQ{EE#WS76XTG!}~(#%%JGrR8f8j7l8GY~_SJ;}bxdSVdk@@6jDfmk<&n;PoH|B1q&HbQoXu@k z9_dv_&LkF0W`HhoDu&n`ZWt_?C{{N@$;9s9u+tI$k;Y5b`PZ;Y7fKB7BNKww8N(SY z3cN_VsOSAeJwzL)WL&XySc6iLk9s>~4CKw*0K0h#cI>Ldf^Bv>j5WaK(qkn2o*@^4 z5~Sl88BRS?m4=PqQo3S=*y~QLl##yCIz`4S$5K%H)L3dQwX7-zhKB)loDUCgYAO{2 zkuWeO832(gqP|lxpkg3?3?z*h%$A`E28_{fxcWJ=dl833c-lBzW2=(j01{RCOoXFOkfYnG zD*i_o|7z~(j{$Xzq<--;drn zJMnP)``IJUVdKV)*m2;*fa>&|IDn1oHe&bT(*wSZ=*1A~HKKgRP~uqqs{813SUfHl zQ;UjFR5TUY;})a7wTo)!Mg3ydcOqZAkBNQh^!|-J&hBG93XFL1+?s*u*6lt_P+6ew z1bapOzyVJbeK+H=Kc?u?bD4hp}(hW-Oe3A6mOvN+Q4>%EtU39*YTve;h%7fA9APv1`{Z zY+m(aFp@GD`f=pxRoK>jwjC0CLLYrT(km;Odada3FdrYv_sVPNKnE2=iWf=u3EfkwZbZ2FK$Ei+GUuYza3{2luxFBNp^dr z3Qw6*k5u7H%}2$6ih;3%0hIwTcG@bgl8(s*D=QoMRJ$qU9&xOPq2T|$-~SgHc0G>| z61su*!@ju|)(_%5icT`Z&%I3qYxNuO4Kttf_UaL(A7-`#l6C*#moO8_*5a^X>tm1N z(RJU2$KFWs?AZNNcIukV(@dKp{tf`3d@+Llo;^_}*lN*sLc!$e?ZAr-VkY_dag;$> zo|yMTs8>ul!H+{3Bf(T- zi*Vd=j(y@`ntT)X%bae`Td@{ki|2e|(N{YOK|U9pGsqq0Qk!Z2$TSYvOW z)D~|66Ud2FuRx|(@lCXTl{0%0InxA|70tz#9nYcl=n0(dDaF=<^;lk(6U11*AB-pm zbC;3D$6R1TPw=FF|eIldzN2f@R|jR4@A)j#4-7Zr=&r z=8I^tcfxKlV%OS*FdU&0b+_Vy*~@TB+YEb0I~JU(hUS4El59jTe!6)9wh^ojM<+>E zc(AJCK^z;dc+ns@i}*Q=Sv#xZ<2+j5MVUcyB!t;f-zux)^q{p~RPEp@AS<@xShtMB zUL1XHOMnr=#^RB#;JUej#^Oo2j*LOGg4Vv1Ui5YmlZ4{#-@k)1UO2Ocjd^(t(>lyl zMC3N^JsYiT5oD4;GWS*i?xq@Yy=dbMIeP(wyxps}%0VAp5_ zM~hydaU|53T7(XJyI|0Qo+|~LM-V)A6aNP2geHqsXff6BXQS<`U~e(<`zm9z(CPLI zc2lJoS5qaJnk>ShS`9r{2_1g1Rt_^us}`t>ms4}$ha`;_#p{|PHNjRx8wou7Z6MP+wfp*Xv8wHEi zE;wAl+&!ICKPs1|$|$tk9fIH8&f{wh%>ofCf~83u8z%d}{vK=Ggx8MaQ)eQ0RRq6A zU@a~PexbRF+L!XKtAwC6+UT8AsN?;kQZQR>g4rmIDJ``HeHHs2OVcP=+k^c~XJ``I z=~>5cY-kq-)Qe>|!Z4IEGQzAzCArUO6^u0!zNNmZAw0X3rSaJWEqya82cy4(_aVK7 z#qz=rNX$6bZBltWX!9$nZ?GVg$tet5sVom0@isPoTj^+S+V9eFgN4K?(*TK}@AvikP z1w9{|M&7peMzOCLnyrGP(<-f-I*uccovn=`zBo2K!G055Qz7V$O@iIk6&Uj^_70)F z$-wihX(3F;D4T?4^+&}(+GAkRqD2C`)G$;G_-K!15cGO|$W=#sb!n?LRDcoVdmJ{Q zxv5!bHq)Hn8D*oXNa=Ihg?5{`)+k=9w<*E^Qk0LHO~zwD+<>C0StQnIQ|5QJ@C^vt zQf%vEsM$jg!$XeiMn48lh7n`2Erb&}d~7iky#`wv1yt#9{!* zn_f)~ZFY%(Y>@~!gT*QMI>ik!`)0LS0>r(z`S%D$!fTz3D~V`eOc|@CN!p-_Z4`pN zs01q`atY@#;B+*xjXV)EEjFRE(xCyTh$EUVYaJwuV=O#90{36j-N5n-FwG-4;fdSxZ7m36mfzHMe5uKcKAoddtXYR;gJjCo{i~!bd;`e9_07le@FdJkL z;lFaZ?5vm2$PX}XSy_UYF3`t_0dQ6#d==k$T+VFr305LRS>F$)mzbU&dtmNj-?YTQ zVvN5412`lNE5Ao@SsOXyM1-Xg^d?K7&xThekEa&MJ#P=8bmq%8(Aoq3!*#7p}OT2FM9m4Z&E6SSNON%OMS z7}y7lB!8DxKI99|^;M11ekdYfI=G+%3vvC57(soRWDKY(0JMUuApscZJ%!)25uAoq z$R*Lk>}_4tkNZ1*R|UG zd-V7G0qZFry~2v;zzNajtOBuJ5VP->sAoKihX~-5;Jco zLOJOQGcbL!h;j@#H_ZDc%q@0QE!B|K^BMTW-Apgmig!Zvm&@=taS>4aJWlr0=kC|B zla!?m-+UOC-eF?0lpCoo{gBRyzt5rTIfrb6JuUrtdp9&>{nDVxExZSG8j3w_Z=&1&G6{?8u>9^468~4m)#2tF zf+`EwQQIJ(F3uXX2=Zv;2{ls!V~VS8fZ;u?UP|y+@qM&@)zSDMil%;_#MN2ILSA7h z7C&YHF^6FN(+4py){B=KHZx0oB=#;E1?;e~R&7J$OD6;ArcIOwHhYzax$_p#?}x!= z5BVNQCVn4^jTL#^`&qBnz~c15Peu)WJ`e2eE!d`;6$GAhJ=iF$YVM#R?1RVWgR8@e zmVa7=+^%0@0aFdIbkKVNB#l6t^d3G+yzXo~`V52XBACsX)liMKjdu8%wL^^&E}9QK z9v^&e2P`e^_zLxR&y@RNruS}V2P{o1QA?@@KS`PXy%sH9Q_VCo2C2bRHYYq#jo+N1G3dJpHm$ADD)5;- z3GAuu_kW`Q14DkuD=qHg#v|pII?M^Iu~}HWsUBNbmea@RWs_zs89+jQqm7S*08b&1 zOsPi-QI^!KRF#a8p;v1%;^5xBIC$_NT95nDZlq0R+d=#(WUn@yJkG+jU_B+Qfz3^7 zn=TvlwB|Le4L4TIVE5x>>waumQ-M|c=usEkcd)N&NF4@L20-d?osyhJZNbX95p!4# ziP$7@PTDBaB;awv(rm^(w{TL9KGKFqvD;u<%V{i)9I}JNN{~=t9}A${NSpoa5=N&{3ZtfUf5cQ%TYC(Z`;I@=3w3uBB0NCaDs7Ks^(#;T!pOZSVEI+ zfVPw0vtN3-`r$j3Z|FXPPJVU_f^|?hAE9lBh8RC&%rSo|7OZ7$G|;xeoX@cZq5;3` z@Z#)i&l5phg;jSKqAc3xnB^M?d3bb>8CB=DVZqE2a;=t)%6~b4?tVp|3B(QFB&I!j z&{$N0sbAhNS!E}}uArEVu&u*C8Hg&OjXdLN@E{RjCx7~FtgiK_e=)`?lx>=zbM-`xs;M zirEEK9!-x#nfkO-Lm8WU5b?ro6ufyC~jhzrk7uL`Kw4b%}b) zLA&&-f74I;!Bl;O*8+`ab9EZ;+>?|8^}6BrwYT{)x^XBWTZFZPFUFf)1WixIE{_gw z{{b;lu-CE^?hiOsrhYN#;%)?Y_bEc7<99_}x3WySzXvj75sGN5j&iKiqEer?T%f8% zBPGR8tw_q^PlPobw_tN^kmUv_OUCYtD#dV=~@32M^G#U(v8fKGTkti~b zK~|=Fyq6ValD**T!o!#_lsd%&w|lh8ECV$dnEab0rD_ti+wMsXOx?Kgg9Cp8-nMTq zYGABoOuBN~rIZ_|oJae2!|(T|UZz#o^cyh6EAd@(n{@7`aEqQYN5k=^*C7NKC9qI* zMc?`Hm-yvreYWx(a>zo{mFxi~9eUtMu6|JdYO*#^Gh7<|Ex9Vk1vF#nCrOqSu&g> z{c@orZ!{E_#b>^98kYH{bNVD)X-9oA1(U&Zu9BJ^zp+t1%T!5okA$brm`cgs%SDQab3o0iej2( zmvnF9gOcX_6pC6W0*z@iOQte1m0_swt%|kGL?fN)UB*d6l7>4SEQNDpa7|X)B2~+6 z29lG7S})-d-3|_m!%BvRNj|6E<**>Q96MIs)kg_G0# zHGC1yf6<&fkcrD!mTxX~Cx1r*ZNcvjnrF{BA?XIN&m0A<`u>YsH!kCuXV zb`+4ch8L}l+!chD&f?X?msGjU_SiAq0meIdjL#lAKbT&!1wzkP##ZnuTf&wjZzzs; z>q6b=Tt0Y=#R@Ou;?|CKyJ!g5b-EGF$h!?0Wq!v?Qt|fA* zEEQsyu;AnMap6LO-B#LIewS1dN#q+@@4nR#6b|7p+M)y~13C(Kj27{!i89y6(0&Nu z8x>EO?nkx3@_$ZDJml z(oWo4%*8R(p>&;Ja(&}*`bhy5NDT>gC}I6bk>Z!5Zeu^Q#_-aOoZR)OLe2Q+4J_X} z6(Wrm1+3_EnN7QNHq8f2xhWX~f6q>19hKJ*Tb6Pv`iGN*p5{UjN8I_fj(2TSqbaf! zaD)g!)HHJ#GgCDIJ z+RKRjsH$4ovGnhk7rgPNGcz|nd+_44?x7g?r4%Xd#G4Bd-3|EMp%lPT;;=l9=6Ze` z;|@=;BlEJxVhsH-6obNtd`Q%Z!}G()(@*Z3Gv?1)8M_nYy)-sr&gbgq~P7rE5RsLOw%~s*qdM0Rqsma;#_i%WS zqmkfi#LG6b@FvEKFVsmwbCEuhfN6mRTxuAj=#81LA#p(Co0K;R1LFbVGgNf@$ z-`z)1359%rzZq6cJ$uU)L)6`Ga&?Ht8yN>Z{u&2~%v1}UCyx7kBxA9+-wWfCUdSry zYCMoi)bmYUp$MP*>R4J(*k$n5qgYmghLXDZh8)2OlU+F8s5>BY>WaLuKbMt?X-K>N<1S9sxj1 z4K3svo|L?sJ2mLh05?xQ=cFx#EWHph7%DZg+_ReJ%t;+?2Rddgyt-JdSB3!E$7p{& zP{cvyK)8`eyk?28xFJ=oyYsDP9A4Ae|B_ZJAUbX5XMYgxW94l` z%lV?{I8qUQqqY`xb6l76Ay>w`x@EJFGWXp6ElnA!NAhUAsQL*d(*y=<5T7 zQDS1T2Tin4(7&9iis^K{!|AjJrzp-1Vx&<@Dj)g$p7U4KbSr0H|J^`SAcp_my{0(G zRS%kX3X_PU=`rOGWnw$;)7Bhi7`Z}0bl7eq%*I_z4roIu^?+U8{A;~ki9jA*eWAJj z7b8{*TQ9F*R&V_ufECc=S!aXR%zG2Q9EVu^-nwMh4v6k9QjCrPg=@)d%u>&V0<{& zb0+ltaMNooK;S1&k^!D1OTB%$j0ZIK+~PWw37Hu+SWTkDqx3=ZiP|=G{hF`Puo;n4 zc>BK>_%ONlnb`sso#OS{^1eV;C89Uwi&apgx^^+Ek(^yeddB{jt?SjB7S(Pf<$X(X z>gn3#H7ALKanJS`mc%Pa`eW&D0JaeXm)1OcVitSy#?L>W3~evO3=aw?>f+U|{3A1| zw@LJmGRNITznHP{3KpKY+}65TnOGI6vk1;k2D|aPX!FIdE<&lmof752YBM&a^9Mo^ zm*>Gluo_`jr+$3*&=wDQ))A6LtU~ps6}E0`>@E3>E&SI2akWo4T9!`KxvFfTcWEDX zykiE55_h0;=6J`Jn1mD*@EqxNeX0I(ZIu_i4{+Q?47}&jDfy8A&toW$6l5C(v{DF~ zL^=!MYQL=53v|0B&Ffer*~P>EJXWwyQTQ`(@*FmpCTb5D+~q(| zGX`9(Ls0%_I`Bf4j-Ew>pQBq2J(+Jw>6&t&@5b*i2G8unOTWzzAHrZ-JvU>Xb!TmC zWe;&e7?2M9$bT8~^yt_7GCKjz@J|9itk{LqD}-$JjAxgw|2s}`&Pe+1MPFu}UBhy> z(mh6xMNPnWuQtY=huq?;_W5v~_dzuz1H7o6%jJE~h5Y`~Lkq~P-3JqlUB7pwMF$-P zik#0A>aRz>-6tWK5;Y_JYCOEp+a$b6D>)&IP-N_J&1lf-nMgv`4mG2T+4WBAn8AA= zbf8Qj^f}Sf{e<@v4Ent8_~^|Q$)JOx@dA^$rE%YG-tG^iJ!g8%&X{?MEv=Yqy7r&q zmLOCl$)!E1DqctpJ}TSFL|_)#lcTsX;`yr`7sRx6#c;AaZ*tf}zlF%4FTiP^!(gG% z6Nd2ckosz^JAsHOaC*QcUS!OaRBJf$=-zN)#-BgdOg}{rRK1df{TbLNlT;!m=*Tpt z)Ib#F{}ALH1dwLg;G&9@vyy4OhrkJ{EfJJ-76Y;EAyo1Qgh8;AfmUHtXoblvtYlabmIc0H$pZ?JVnUtjoc~X@n-joLRZasEHILn0OU57fN3WW6bS~qJ ze|y)yO=uO_n^XIcL4tjLp3IEz?d5;co+k;td#`?0XK*%Kz`=@-C-%htYLK2LQsvMO z;cpOUNyrlY{|g0i`-8o!`rWb*Uw7WDK(9UIocDWtx1M+09PdiZ<1Np^bSiL`r)P4{ zekd$umY~1y;`%h=K`CVi`^CXWHVinNC!) zY9i@FiPa4j5tOztx(p&!4K@=bjoMM%D|zw6^wo(Ykgy%zF3q}w*dS@9oE5`dOZv%jbl|o>o8Tzk(iS{W z#hz7XF>psNM|M+U1~jTE(UT!jk;XdmA3*)0N!sP05G_vS6&e|tO#&TnJfEp0tpE0} zIX}!W666j?uBiUUjo_Ad17r`c7hIl5{?NgNt1D3%kvoxk4$U zZ@(8@0RLgn!N~6|;fG}YUg^L9+`JZI-rKuMuk#+%ef~S@JkNV%-oVc$ubq3;;tOC$ zlIFKG34~!5PEmteDbLaW*@ThDHO9-N2FPwjxMga}Q{LWo8iX7ZoET z!*D9=T2Y3Gg^2MpdgXc`?85!(IQ;RlkQ+PuoU*hkWe*DG zZpQ6KJUZ2~Y{hF~2@joL%>NPOJHunPbmWhvD$XK=nk27$#NC7|oyWOT-jrN9bHv*B zINzaTu@UC-yQey%I{O81I!hA$M-z0-ptnXr7e7CcpLjNsd+H_L9~KX^mLKW~-VVB8 z(I(EH@VAq0FRc^?p9{>@lC#Qe1ACNBocWN62vDm#kiCF$s0%Jb^(yRakEQFky}0hJ zJ#j?Ga;zxVv-^Qc$9qZ4>$R z!Gk8EGWR!0BaChyoz$HV7s9)lfiDR+A2ns+EeSxSlhaf5Hx@&zFkry`RRY~7C@TKhTJ;7xtHfKezOF-fE^wwxhJ%53El%@|Jv@z z`-B>=`Y`Mv3x7pfs?iCD~_LDT7Z6^eP2(Edua>ryI0x_F01 zA*U9b|l!}QsS+KpqZ3gvXnm3hecMx^I+RG8;9H*sC zhHB+&fTcswM+74eG9>}yxETKDfKl;NAtY3BKOl1U&kCYX==a$Mqf-uUT_{hd*QjXl zmH`@&CNbQyLGmPyM^z!}Y(&D0EZC2azy%&bLpH$WYxoMlQ6tgA2)`+v2&ODjr;UWOkP(wjhU>|?8i9%wO;(w?VMokKqst2$A-V83<45myP z;c&$9F)^cMf*M#oWY93UU{we2)>=)~dU0%^J!q72xzQR5C_x5uL6ij9MBg8Kf!ldv{)zeg%2Y z=sNYFjC*}lk|cBys>nTiei~s`JPQFXfD2wepTZ|`+;#?IcU`1Cb&p9RSD{qvyzS(~ z!_pLNiJ-;?ie)dju)Jd6X(l~|cb=NJ>RrWPLgL5PAnaoKMCyVHl<{YmVQm|=04qQ+ zUIN9j$1gE(R)ec(=moE|9Z=A2PM&c$mxr5Rc33LFrpj@ysk;)jltt)#+O<;We#w0` z(cOMF@`CVM#43TCXV|JcE)i+D-m^E2YBYF3P4!)p-TmvO=jQTL0qhqRdvV~_`{%v& zDzu=3j`aN`A5m2`w5?F}uhk5!>82)h%b%*7^H4Ke(&&|Z9Vm_?4;JfQ{I~fy%+p4u zHWZTIv1XUncTLDzG4TxFN=jThghjW*0g0ZQSR0SMpQGe+z%bZ7=)^p*;f0x0e4hQ9 zQ@2x+VeP;`7?G_mLi;J$xw{42o6H_>D9^7;N;;-|Nfg)`W1==91qt4JC0s+FPwXn- z2CnlZ*Ia2w;c*Fzj`)Z!h5DZtWh!oI6nT3<(mvZ98b_hxd=rYdMFV>}!Nm*gF)Vj> z4`3@7+%=E#y0(k7-K!IYS6eX|e2(zN(GIpWON0kg$W{;lCzS;@;nX@HT$_ zu=d!Fqjse=J=Pmzi5`ypT+bW)In89uXJcaL4MS+o8$9Xj^x#AosQ1~5GGw=|? zavz?xAE+vl4bHeY>b5W%p66qlSF>hx_}*>FJog0aTyF(=x8;b)#-!NXrNakM)FPby z=Lf^7jgH-Ujm=AFRw-F0$U$!|pMxpJ?bBA@}>If1Wq% zJW2(oeVZ>DWA@I!qiK`djfX;i9}KD9<_m6AByvJRp5e*r3pD4}?VhkxJo9S4pa*JE(c0vVV!Ujk>{_p7>qxc}2b%VC2u& zD9aLBOI_uE{V}TWW>xx#m|iSp-k*sh<}4EJ;DPyC#phv@-bnY__RbDXttUnI;;M@Y zE;QYl?6Xqc9y!o>+oAaMQDu+;D7$=mivUe+dxZ%g-XVfmciPfgOqsjP!U8olg$YKj zWgqJ^c^#ci&-eC36$-%a)8}ozt`~8|DjH7m`^ZX z(DpMaOA1?CrPoHIVvYd;b1Ywmj(jZWH1=q}ob<9^ySoA3|5N*B^5}YJ*zm023ny-?Qb>Mc9$0_)3 z8oYK9Yzte;i;J6cW#&euiG9>T-Qy?&kLS_UNVw!ex|} zQXUXwZ{&#cY@1ckD-oXmzRfdSE=18PCp9`{zt|!Z$$lw|HU>?u1a_04E!W zDMms#f*H4MLcwm3PZV%qIRoTiQ%Zgqg|wM+03UPq73qKJQ}C&xARr>1GQcIRC-oTG z_gGB_%BUH9o?Kprx0E4@ly8gEjY@z2m)lxsPukpl(;kMwYFK3eX#Q9yU)4L=MC!av zxzrK#BsyX-3|(>jpjbvuJZW94%?xX;ZvVC7SsVUyA;R(l880}s zZ`_b>!^hGJ+6bCz>ZOk@tW`MnmHvwIki~+BX!+Fry{ZxjCJZ3VCFTajY^eM` z%ryS&w?a>Yp7lk*i6-q+dM;D6!ca3cj$90$-Hyi`N!VSDUXXY(+zcMW`q#oteuTj8 zF;*-FTs+n3nm`f1e`Y&ga}ji);=Vb`4{5RE@eU;aSoXg+Q8=oEl69^M#5JmJFy@@{ zK2M(<%sN)m--J^fSgS+|!i!JNrH)xjV{V5feBw4Xcx-X1xOD&MX;R)@WYuE_j!VRa zn&$^`%QddYfGd712EKA^iJVJFzFuZz<;E*-cn})CPBDg-#`1)K%5rS^!JztWK2c|d z3MVY6EaM+GPtuDz+tAC!B1Q&|r=^7os%0WZ5Mkls7JH>CP0#;U4(F7X!*vYGkHW@f zm+}*1d}_uRINC95l$;)D-yhUB5&kMEFt11Iw6YmQGrxG)Tb=l8wye$yn<3g`Llyza zIZHRB`QJDT7Nj~&3JvoVviT_M-y12HCgzA(T$TtN%FfU{Z^CPN_BYl%)IsF5)YHDa z7(0%<-1zIBEkOO9x6a!M|Ds5PZp;_=bhygp-N(Vu?zOi3PgqSanUu)nwn=N6@a9Kr z4H*=o&3i8EliI&x_aWAC>T&LxK&yFNg09Sr_Q6%^qngl+VHQ9>Qo=7+KaG>Tl5GR8 zS98|(0L5ers@KP%j?6P|`SQ>ub%1m_%W&}z!Z`&W(|3>N!pQDF7;{d1dfyAv1R%9-ga&;{5(=_wdpggQ&I$L)?$m)Dzp;cjB5i{tI~kbAe(-wc?-XU{k*F?^^L@cCA!c8as1yZ z)2D657+p|8vKA{-U*9;vAveKG)6mc|g-QV(~%Shfv ze;h?uZvD-b`XV^`FX8FsJbKY&aU5Ft6eUtZhP1EYKsM8IL(+6G!{Ng9wEVk0l`hl{ z?e_d0gg|_e&3h(?DONHb%3~*I7nJVLz55Imr^{Zq`D_PIRD?36KI9c;$}w>C02^8O z`q8Ie!sD%hcwAQFBV-;)Mba5q_r4fd`LWpIJrVC#VifZxp@`6?gVM1u?y)d_s+Kf$ z#Lu7hfZs5%S&nPrLhG5Iu=CY5wtauOnTa3c4N4pT!*1P+=aj;FQnRHXFXN!ST;88+ zbAE)T$QK?cVT*s&V_!+*7;CSyXtYE-GsNTIkzy-n9co-W0~IYB59|i&&kR;uVv#cB zzLz-;k_@<-E0rkXP%bmGq^TVkzbf(QIlRF#t#1T1`%emzArjn)-UxCt z{Zg(UI(hx4japuUHGLC?2ae^8{$Ug}V?S>u#7=w}*7D1rB1y#ebRSDHGPeVDKQizc z?4v9ormQ(>3U3bw>M%D%WwB#!pqF=^6ibTry)OGc?Rn!w;JS~?|I^EU8=OdRBV=tG zi1Cl_yFu5@8u8nZ$;SIBz)Y`?nLNMBF;`+Fl60s4-}BAEaZeOHhASCW@>>CDApQT4 zx&Ndq|FHmM#cZiZ0AzDE#Ns16Nx%UuNU`%OOGj5u+4&DF0$&U(#&Mu9_~|+JrqW4X!?I zR)Q3Zqz*k#vp0-nspJr??Ks@-4mAs~Q8?L@?Oi|?mFCXfA>)hLNdD~Y^7?4LAi678 zLz@G6`Sif;F^P_zk;GRTV(WEx2fG!wyMl?}TNIp?4gc3-@DIl>^!&w1$>~9&hi9W< z=XaZ&i<4f-yUdQ4K3`QISNeJy^IZ(xT}MZe;AzgDk&&y6?==#_@wT*z{jc}wx5I?A zCQYCT?Cjc|tJl`UqwF@Hua4tRuXBK7-^wSr10(Cu$aPLUW1K(7zLY*yb%*o5S+<7P z{sH|4zdw#3?zD?@;IPjag?8A2LnrprieVpBa%P*v4pk+DY=13+)==+KD0nI1WQb4l zz+3@P9t|W*N+Xk~Fy_F3%;XRTLDQ$(WA!RJ`UHXOu6I!^a72$I`7C0SRh?p~G%y-a zCuYZ*uV%jFf;8!#C{M$#+&P@Ek63>Vm1sUW)@ef=k=bozE-ACu82I>AOxh{{AY#QX z#{JK%6y6ty>Ox@8R1|f-Zgg?aCuFICQIySsOk`yL{md7Ek+&Pq=n3neBG}`QI;+=ft7UAMy^=X+U_d z<>Hz;(CsWTZg({!yqG#!L94 zqTtP8(~HRVzk~n`*zqo{9QNUc?_wn26m&>Py~BeWvMmz247a1}bu~#1sllL4#r-q|i1UU8=y|}wRe)%OjZk8GWJqSU>JWHIH zQg*TY=}U#*Ck~ZQfB7HKX?kBir->9t1Ub3N#Di4nqAis$c_1po2oFa33hh5OpD?y! z0QfDRzPFH%K#=gFd2Z{}y$~Atr5DLZnoZa{yiTiJuw*J30CfKoa96nzNc(-HHfj8;!ew zWJulr6)j^KJQaKsaj|p)J|)oQ%b+A-VfRf$NvH?8$zJb-L4Nc;4L6U|vN4J4erkqr z_va>0y(6hk-mi0gmx z`FCw)ZZucjd=Ekb^*yQL<8Uh~CBdD+Xn5&kiQjQ#!C#_Jor3Z3(^(#qP6A1B-$`lp zgPk%v^Dr7r*m%iB2S^s78Ij2812k^)O~X)=bJs{h$*i%2K}f2(7_n60Y09rd>!!$M z^T9q4XX5jJoQXeL;2j2}aVoV@L#B}Fl*ARf@fOd=jpMjnrf1OHPk@AHEoelu=r)Hn#B(KXM*Z~+|7REZ;N|q;UFN~iLd>>f(?|uZeTyv zqqzH*)H%5OewR+#e|Lz;?z|^K@j?qbuaN7*>~Xarkqo|qW=58J{MieMSZf>rO_P$^ z#}(&vY(n&n(^0HJR{7fX)E|wDsj~V@XDIqU$BFUlfq5bjI_2$;LYx->9n_~~$lTIe z7)V`(87g#_;x3fx_ra1Tjf(|}$U-FI^^qxr;qAQAy7v(viI08O?1{9!Xchwek^Y#O zU$mICFOdnoY2aMVZ%O`fc6oU4AeM4>7r^m9ioe1A_pW-9AwaCyENI^#_^&gS{b+LuPL#)K01`B%`0grseh__P3_#8_N{0}qj61Hk% zvh_T6uu`euA>%mODafKzSmaNje1`Kq@@l;eq$SpN&|UIrYuk-pr}!2ELEtL|%ferR z|L%SnA{e#5ggLGCm5KAXkUx9mwwq-w#?}(LVwNd4sVLy|U3$P57?Rum+VvAR#@`6E z&l=bKMw}(gF6bJHC4Qb7w)Dl;yO=S4iL-VELR_(AROJFR)&_W!*A zNK%x)neCogWVm%;HZ>SZqN9IhWl62(R|H+2%2gS(;xq`o-<+<;1T+UK;@fEshmK^Y!L+hi`N8 z1T%bm=rUbE7QvQk5=TzGsEfbR!E=%h8?86=b~*$smpN(|RNopFB0YAXL2AQaR!X@T z!3A(#6zIm%D4|e$eG*5kub&^!dy=HO`{@slvJgR^k8|a((Dgan>*tgPz<>aQLSEr^ zsJLUCufL3Rz2+1~_JYN(|}{c83)?$ya6a;WZXdi2iynuc1T+G1_WK2~1rvUrD>HbLC4itcbb}xUs_5NtZEx`qJsH+bhi9)|LWiDEKc~+)qpb#kczW!PQ3!} zo%~e*4S#{(7&`YwbfRSiJx@v1VT1ml6!_&8xOEB8MGjeB~RRvtcQNY zgw}fNeOFhpzR4ZvThmjmh*C5u+Cc{tGa7^<7uJnDEWCo!fj3%YEWpB=OxM`JSTM5B zCOZsxpZoaq#lzaxJ;DEBj>#Ark)q%CN2gE3?s1F810N(Cot6SVzP55R!Y;@V@0h8V6<+-M z;k?P^*Mual*(hD~5q=9Lu=c$3emiKnp(298G+WLs3+hstFC2 zlpKz&KeydjQdADXsQg8lynd-_m#y>xpoLI69 z^nBQ1Ki#b8ZE(rA-7oJpC+{>fUbj=^{rdP)Aw!j3I85nfV%pLG4BhOtVVAHJ_(Ory z=^m~&deU0a)qb1XbuKs)!G^Sn1_v3KhMPTKob|W`KOLq(&fNK0CH)#ppt@l?{L8gwjgp<7 z%mC1%;aeyO*4R~Llz6is(vOyEv%`!co5@#@-@tY$PtT1nvI*D!8%TjZ@^8i5OfEw^ zs4r$B%5In!4$3D{`LqkSllN=a+t2Nmg5^b6Y{WOPk5mbWQhhAcdiyJTPBG_MVEmda z8?0qNg=agC-usopWExB=gOKJ(p+3JE97`IBmBR{0QvPFT_K0Na>IxWs`E8I$hQ ziyIypM&h&PKUwVto($^dPHSwX6cHt!%KH+Y%^xgW&cAltM{0Q^BD^AOR)M5l0^-R5 z50rDSTc`$tc}8!`Q&i5cJREd7MzP!J!Z8AjCtg=z02<)ANc@}qJNu`h$1o{0i9g6C z(xEgCpimxJ^jtDjtzgFp|KTtq|8jF-n-Q>LNik3B6p}-HHs-u~J%p;ffA{;|&3m_F zM{Id81pLti$}jL5me+PWzJFbNf6a!tVI=_7QTbNu?k#S8=k)ag16xsM2y9y)% zRSY79YE%ppMEw-l_Vq@l01{cqa`+)ht1Bp1Md&y%-4*z*;8(|jV{@<=$+`)e_!$0f zjgoq07@v+HcAKu9mnckJ^w-LeVUX4EcI2-7cK#1!sCF^kH8vDpkHC?-b8XvG`ko%Q zf?>k}FC}D|BInTdC@?Z7e2VYF7sD7t#%hH#Y(D^k3rFG~p zvcmp~0R{e&$+TN&uD-8LL>Xq%AX7V=!DzAiLg;}<;sS$LAGXQ+#i7aDzxqkfZqBPC zJbwFn#}ftG{pbN>9_qN=?+xEc!|ShOcja8d`N(kSy;>6aZgH~TT1!LF1{!d)z4ums zB!4V}U;T#_{;)k1oQ_{-GOJ)f_J%pE+N(&^LiXTOGKJ0{No^YdC{pSc3ZOPzs?$%}tjArFZ(ea;}&s~i&Xo1TX#Et*$=&g``0 zR%agz}7t%kh2ZS}R&RftBQM z`Hy8AfG?zgmf}aJR@wm*l$QOit!m-x<UHmL8dBC7rDQvp$($?NG)bCkQOUcMS>jJh%Mn^~_IucutK!9D z<(QF(F4WyJ*AdgNQe3orhy$(C+9~Clf7{<29F^QV-g1T7emw7M&A7Bq?rRMkTE1hB zHo+a$$;1w5okRQE(y-)gAoJwY{uXK*O^*h%KRD4&A5X1C(dWOV<@FYVPqU0$EQ_1; zJRwkZJ(}5LP+3<_)d;mXFua(P%s)DI(K{;{0c=i z7VQ30o3K6=>$A{ANS0<#v@v>E7TS~x4 zk|d-dQIx)Em<{)Gu_HsE|30gcJHu{CW_GG|KoT`f*yxBMOGr02w(h(W#1$}bzr#~B z+hz&lG16vcLU8OuMjFsQ5EUOc4AZW<^jkqpT#3MgL@ziB+HiDT(o_cK20%H1j#W6+ zCqhNO-_7)A!gC;aw5K-KMUWlIiZdYL4_%=CSVb?va^Agfpq}v}K*-IEA1X zGI3+1=Hr@yA~0q>IVk7t?<|EwduW}R9oVj|-p?DgtBIs}aYa+HQ6FGGVw?BpL{%-B z^qLT5?*&hwjj>Ve_yGUrg2~!M5zaZ3Da~_~w?Ac@yzE0W$@4PHkp1a;5TLHGpa!?J zQC#!}Ib2xhaTr2z{|?K)THEl##;1s6>!_xF3EG>V&MxaL$NycP(+bT}?}-e5)X_;i zwXA+DmAlkzGz5iHaB=L7rY@)sH5aSXl7E;6Zr-DfgT!u^HmjBV&r9KE5FxyoFH?s>esH(I}Y4 z`rMZ`YP!(7!*66*wNMkB-lCeEXGtd0V!p@kj(VNLRp1y<-6;?J(Iu>-Q}B}rt##D~ z|G));OOAEi`t$3@0#|Tls5kE^_gg&z)x-w3;C*F~Rx=*JlrDW^E|YJ`FN>mVUzvR| z*HO#NZdtd*O$RBCW+8vN;MA{3$eiv0h*jLYaDPctC4pYFBeKls#w4e^1b{&qSlN{i z=nzsiXNpoE#lh$P2OZ?c35~9mj)G?Xw;o9 z0);542AKNu2Oc}KztLOe&!5FqSa5V`t>|zY$eTNa`1xv{)}TF96LI9<;aDS)YB1axMJG&bvqeR79RiykVp`8TvO-Kp zpCJpkD<%R*$S!xYfa_|bX2nQ!gT!qZpT#lnio0OljYEG6u*(5hcLOC=RmVxhj#JnN zj6#8-w|vvcdRyQz5`#od8xD=6Wg_l0*?*$TV(|+~z!4WhT)$Nj@Q)u1)@p3g4@yL{ z?(rFKe8k~so_ahswx4;j9PLR<(`<2NC&9nPg-nbF2kpnA=}TG&iGi6P0mt^cBq$n) z)#Nb2=F*#ti5B9s?V0N+Nv^&lQ~XIIj`1qYXBa-*nkCh0YwT^!$Y82866YOu87DTe z)likA)iX)sNFsAEK9I`1bw>GOSMBEbT;v49K(v(IXhWg z>OiK=XGsi1ub89Sp$OF*C(IN<059lySCTL!J0tKxg}cv@8BfQpne@X76uDvF8hb+v z^cKOK3A7a^$^L3Bq$OZG<#fYXI3~aOR8r#>un|;|LBpehK}sDKUPq}F)vbkr`?Id0 z82n`qaiQo@xdF(A+OW6dCb}AP${4Wk9P;cuCwCXI%iZ0jrtg1>NRdP2X|cUn)Lqaz zXOcyD`03UK^wI3*#1}sc(1)cOupn8<+_PuKh-&zsn?{`M^RCd=R_gM#%E3(apYK4x z2ZSuY*5blFSlcHX2AJ_aa@TLdmc`CtI%UW`rHQv$1CB@6$4Z4pzz?vrrmh2Q1+uRq z*5I3oFfjDk+bBWwgVjZNOo&%pcL!GVAh-s6QwFC%-5}{vbOW1Y)gO5>+~P<})b3VV zsY`i}iecYp$Z($~kJ~ci=DFlR!Qao6Ub}Ks4l_dn$}j`}v;ZxX-(FIZWK6W~-(>f7 znh#dUSX3aB1?KdV0HNW%SOIT2q)`E##gQ3V zib?0Lh`OdIOaKua8t93$HNF%<0+s4%ezMunCv19{NpRsQgTE~kDY_XxGppmf7WP1R zVc1lBD#ur$I)5OhA16&CGb(|AzCA@Y6XC_K z6#+!@PRnt$08ci<95u*~gl9^$2ItFsv65vz&WbM+)2?quuTDp(bOzdK<}aXuR2=X= zK9-o@DK84jvs62u-3O1@LOmArN|J*=f9e^(LYziFp(V}6x0_n#|=QSiS}io;GX z+!AHJN=j;AzC@5}tkGwXI^3vbd_06=3?FdDzJc@IdiguD^8p({@ktRwr&XjPD`ATh zwV1gG?Q%OvBCUL|CI(s@zrk@RZ5+#YeJEd^mre62;SwR@^G{Bqu7!b$f^J`*FZ`V5mO|Zv6)cp+v%Ia?TcB)8=m7sZU3K zN05G6>yd>bwCQHV*A>qHp}2Vbcj%Dwx}YlI!k&@&XBNM6V_Z$2J2;bLWS2Xkr4k=> zye8$PXVZY9YlK5{xIOdF${+3GR`0dn8++JEt8vTuot6l-n$5}!*F&C$XXXkW!lljQns7@_b(%tg&N-4WW3C7H6tyMSV0c=f+I$T`WBnow47P*vnP-VMyuUL{O@ zP04Vi=c4jX$erkyt7C@8OJwY_euUDo2WZPqZ?6WD9y5@Byt%=!yh#o4FmI{wu%Wkc zF;e{i7t~xo8QEC{v5@HYbQV3v*9Ebb za$iUXGv#YHmrtNyi^k#4dZ`D=cz=Bsl-t+-BLML|)hPY|hRkH0<#U(GwT9 z>UFDOzHG;`kAjz+f(|hqDnbBQ-20Ufs^7MQ78-PyfK*4w4HZ!-s4l)kLoZIGik65T z$cJMJwD?jY-}7IBf<jHXNG$=&`Sw!+N+B$_x~YW3c+LmEc+vf)ek{DpmTax6EK}mMnxD|v^$~J>V|=u+ z^}ua4K0ejX6aL*G1deQ^-Y19*0&cM9*d(hrSEdn*Obj!wEcOijcr!$9uZ5+Nc-|nq z3tCeXxsiBJVVzv)rTq=(+ll7v+S6#ySlx=2W)VI?YX_hF#!JK+jCD>E5BbDoo5pe? z%G}aQJWBcRW(?eOca`<{;K(1IQ5)7qly%)=V6EYvUAYoL6-V439`D=-MD+btJ7^yl z0&{qkT&vJ8OQrEqK6mRM1&U!Y^|H&UkSC4S(5HznV{h9g8z*xwfio;X032A06Th4` z0@Qzf$A4!^G&l$X92x=v3I+)r|1{l9x3T+da@+a$T|qf%UvSIw3r&~xS;>BX+l*7q zG)faQD8g`I=WpbM4BH7vDn?>$WoPCXYfqXsdqa9?T@GVxX7T;1hq{~3l_Tqi+n;Lt z(xt%mE06Z5I+Rolr!2eK$Ff{7+FUX)I9sm>W47}zX<_v<^+S)E{&D}$1SK$#)WAU8*@F)3({)kEA)R@C)4_-bQ|14RM`Gzt{nc!7k zohb0odlN-7C~xK5qsDn?Av*fT^|PN^dYI5(GdU6Koqi% zjz_|x``}T4SP@60*J8Sw>dl?BLzU(jbpPBcprY7dsVq^KB*NiMlIyHaTP(Va!X(gR)tXRB5+@LP)73*#9 zMI+X`6-Un=!dlc0Y}|sWHZc9hy=lbCiluKtHgxPtFV1x~(Lu^muY*^{+Sp*1y}$qu z@!<7f&S=kezdLAc?U#(;^Cr%fil-sXTpun@LIV{%7&)}Dz5S*)tPUQY*vlYxi<)CT}X?awXx zT{pneKdEmVzvS@+e>(t96mkgE=F1B)I3>P{5+vG6M*kmE@4y^s7p)C)3L3IIk6@a+qP}nPQE)3wy6VNw4lr&)76K#-jp!xrM7c16)9Jw+LyulOrz ztEUy^RsN7Id6o8>NZMTn=WHY3yNa$Olpt0eJUv!AI-I3r&X}@3r@_ZSjYYYT-v$6ND@>$BkXzARbUV5nT`ck zpjr=Z9v<(8It>}2W-|KATI}78Hvn$cq!~*IQk^)1*!?j}MKNR$QDjdRKVnmA0a)-* zVsOZT#QeF0yAOe`zQ+5m-Ojg@xc18HEpkyIj6q1GM z(NRGVo1-D|W}KPj8DqA?*j)5Zbtx)Zk*nPm?|x=i>#1S@k4{U3`9_HnUEC~@Q+{KfJ#@fMS^mtZ*L^e zEe{)S@e%qrc8%*^SC++zZO}~VtapLF$}g^IyM-i-%3e3 zxHZ0$TqU8vvVZJXIG-yyDfLM=>Z{k?~ zJ|kFN|BXWWR}NX?CJdIjdZlIyBoZGR+GMq{BzA32zDREG$_UKU>joXL<=;Pa^U189 zBB>+=HMLM2Rih*vZxo)r4|EmNVHb?v;5AijhSGc+hQV1#3;BuX~Qfd{Ru66MEoVW)#{1tqI z#eF%iGfd-? z0>?ZunA#8C$}n>#S;qH$-3N4GQunC1m4Jl{zvz=_z zncaer%92>*;j5U>p^~bP^brQBU#X$=C z+fy2{fBv1l7-c#!c=If++Bmv-L>bk-vp<_Nso%G>26LTAh8$AJ0vXB?JQ3mgIN7nZ z%HF8r*EjpCV3h7#R;i$+iJ+^^gNUBCJ7d}T(_w^=l{eOSbze}byh((Qz_`jHzLqBH z6cjk^+T0zu*}95X-EH(eV-zZEQ~o{f8vlvzoE${09taA|hXo1=0g$iIaIRHAEJA_` z`8r!Q;Hap)o106SMn@2$a&855gD_6D#GwnYK$56W@ z;PPCle>$NPy;mTQrFI2`5#@yVf6!s2MNJvK^EJ-bWJZz=@e65N!(AeI0me{s1l1lL zeg1s`#6miI{TX~f<3weTpejK!zpm_Sm$dTBigOYny_#cG@5o5VQOomP-3oFN5TlHV zhE%@1uLnj%ihea3ogfv~nO{Mrb8_OJaekqc{K{qK!`fv<$#WdE$D|jU?f{Y8Xh36h z;I~d|59s#x*}gcKu-BsE({P)GJDl)WNe)>8ccRGu|Fvoi;HNP<{ylAs1p>BmN>BNe z&bi2fBOpQMXP2gj=1u~Kp3+*t?(Dz-E~WK#2STi0=ZD2DWt?zo8IFk+0zJe$YEI#H zuYXX>u*w?(?--#0nB;(PwqlnE4ebh53&o0v`KE%t$nx%fv|(EEUHM6WDEUh6;plq7 z>|czImn+bd$@dSp4n0fnRFbZvj0=g&(?EY8uV`5zx~%8FXlPk7!wTeJb@jTZOQDZ| z`H7YJE%xZuz4HV8hS6E;>CHp1w{7=G6(HD1^6#rQBR9zi15y`?ke*wvFy9 z*I8EYs{SXVurOHN!^M+=vNH%n)dRjdm<12`W8wLZ|CT8DL~|}tHl+_8H$GBmeB!YD ztUndM#8;*Z)9hk!D_xp`;|{(m=s9^1DW4F}XfLb`XjiBJ=}Aog*Bb+e`F9!5 zzyn_Ka->0mAaKBVH7ZYH{D=BELPKvDI8qA%yQ_i&zS|{fi`eeY49n-}xg0EE(GVfx zXJ7@3f@2vd1_nlA|1QOAlU{wdJnhw8iG+afVp|`?=$m602tV`>Dr93v3w%nW*(J3e zv-xMcLaPb^;OpO}84o|k$Ge@SlVC>r-Me>;)-TW-EXb$%=mjf7pDEB1T-RkiB@s)1 zI>LVt;xxctq_3bWO$KS?Adl-|RTea-($X_3JNt>lbrKr-1ko71j7fVYaCMCRxso`yn%AaoyUc>^ z`y_5(OC{$rkR@IO(h$GQH*F)YiN8?@YxO zG@xj7o_i*z>h&DyC+BT%nO`?-mtD8Hqkca5Hx*W2(r(I5bgN^y(9KpCY=E?4)YT5w z8J9SA`p|ZE?ek1Gxf!iBBL1`@xY56R@LGC^lJyKeZC`3`uL&dfBJd2cmeR&*U9m~{y=iZ$0uY{ z$fT|d(iNA30(W3Q4t%k5o*wL`q&=%I9|^FHmaa$!^{d9$hvm)S_jz1CmY9peyTF8s@@I%UXs!A zFSuPN!$ZX29HS+DqjmaXwZ0$zQIVzsRtcUcmnBGwh5U78;+yeeMCcEWvOPB!4)+uk z>RQbKCxQb>3PcuemK6@5z=>!y>0HpaEoQ63d(Vp8reC+qfXE)Okfx9gL#XrTTR;G3 z?ln*zH{g^l1wfMq&_fWDeMYhc;2@{$#|L(APyi%{1uhQD=$UX`Cw<|}rm_aoHepp$Fg%W} zNp|mqq(D(YT-XGSRt6i1m>YvSi@^vBhw`uM>(hPWh~Dl7js{A0PLF|4pKkFS5H>Tb z>!4e8do+tz(xds$8oGPGw(=9%0=3w7z(Q+&{Z>c4Z5t zsGHqy$$!Qe+2YEdFjB+W`y(rj{&&UycfkHG#DeURhzE+%@jCLYUtFJ4RpD~d63?w* z8ryyB8{tF`jDuV90`6Aaqps-C_aGp@d43?9%A^pS>wr2m&=Q?0@=vp8?-6#w+&~*4wz2&4$v^PAX1OPWzbijH=k`~?@i=4^u-24>?a+S6f4Mg{U5Q2rrc$fC zpv+=`pB;~b?EfueC1p4yn~;(uc2H&{g1y}u3d%D&x#*+-#-l z(XT9r)*fz&7vcw!Qg7;fOO@&0y|pSr4*bB15m(dfdnn?H^K51o5(S{oK$XD%01Zw^AVnnkcnpYa86WX~P+>rK zkxC-5Lh$mi0;@(andcb@`41S@!!pY!sA=wdgR9I2Ci1tl67`_A)ckfL$mu2(%)M&} zs9*?Bgk!yAvn#QdHCa*cdp9}GJj6?33LKnE9GP_|+?ht#-;ifBD76-L{V$0wJ_{B> zA%>gK1*M(cuU*s~0b?#loYJNY7p-H*FK6Q~G9Jc@CiC$$%~W6Xk@vVi%ehhB@@mPZ zW6`kiwoNJqEwnz|i#KZ3R%fZ{Duf6wyeHDRdknw=d~@40!sMgIiu^8Yt8RwD_@`Ib zjK*T091mw9=G|pOVj6JyV*O?wz;hZM@cwp->NUF{In zh;G+TjXjM?>b3WTc=L^o##3n%wFUWIxxvkQdbrPTGmm{LL>47%LOeQBtTHc~^e{65 zdQK=_(qI4DiZlKzY^Dj9Y7C-&Zw=tM+`RH@1I19rT0m=Fd?paHkc9+#0Us1TqZBHKUkK+gRG zq+{@c0`l7F=AZC_R{WKC?B{$uUc*Rfxp5WiKT!U9<B`oz0tl?guNDXh7PNAx$hd8KH7mX_BFLTouOzvM_E9ve-& zt(nm9lc#A_jtDqm__VKmyD&;{#(~WkXD2Phi!Elk=xpn*u|rZEx47Zya# z@c&+sOR13e|74&ci+=@6SJC4*NL}+%QxLmYPN^>Jq;%nn;w5;=knS^1eBt6h$UQIQ zJ3rg%L0Dz1&E%a0Ct<|E&i+V^QVXhik?X%>rRpBYc;;*Qm_L>fvSfIi_Gn(!lMB|@ zI5%$;!de2*I8IK}tTO339isC2%si^M4YF1Lf@8>Hle4hzut_wCPxwZhofE%tXNFw7 z>b!SaWNa;D1!#cCncoA?>Q3kNBV2&CPQJ;Lm1uu)!R)*}++&q5=2T}RQV5Q=

u( zl%B5W4L?R;>O1P02IJ8%m-2;OM5+-zTr8CYajSNtlhYehti^~c3BGU!0eFe= z@d$@MAPk1Y1?YmT88wYUTb3|eGY8kx zIei*$Ec3G$e?Hf*@~n%rg<|FT`+Y=LePWd)M&m$%B#0m(0H%I>gQ*>)r;w&2AN!}5 zbQt4=B+NK}OuT^yYb0X|hM#edcVVX15ZRmpF(;G<{MtW5lK={CdMwm)zBUZYZM4WI zl7lN%);+Fz-+kx*L%X{bf&xa7wzjZi3sSBMRH8dhnT%-Qn=gxpD1u^dU4qAs&O%pt z+mU~ZlJxFr>>q`2*wN_NhW>#KNIyDh-zqTqlFs^gs+q2~7u7Z8=X#hpE)|H5J!G}8 zB~!8!ErrOjlZyS=iq-3`&Ju=^O&V<39@6i^g6m+zE>Y|gG6iaU&3K%C);;fi?v+;C zqY`vmN5iEuctG1zitenDpoK&OgNsT`F}GDr8QxfGKXfgKnLJvl{GRVc9ExrPIM_qf zvN6{GAz&XVh#`T>mDUVH-m_b9-C570e}bn)>R*V1Gf@HVWiz=|QNP=5WN>uQZsb$3p6zcvmFj~O6)js9o+_fN1t{aj=8^R@G`0jqWe^Cet=8Bd=w>W58^>9!Qg z|GVHm$j3_@Bind?SqjdC1epOIe8=muzrTH0?6@>_R|P&3Ec{}LZ@)ifIMjGokl@HPa-=w z4GEu;Z&c?eArRQA*=8uu5M=Bn;)YJP^P%v)Yz^+@BU5=!K`%Y_I_BlNC7*yjW?@B) zjH#XQ%nyCcTNm680eissaiFSntG+0ct;fI@+oWH;pPz(Liu>L*t+V@kN+|s0%V3lJ zN7#M`#NymQM%_%b3wH=tfxXK&DxTsN5zWZh@U5%~61ZcZMa?c?aHlR`zMg6>jybfwWc zk7p&y0H;b_ot4Ci7}fmJQtze{ugb;IO#WlAmk<6q!JuRgpg+rtu)v;6zB3k;4jDTV zxjBDoK_P2f67Nn@!{h3n55dC+hY=@2pg6YA?#J}nR<b2@wK29+;VJj&zfc&T*tGV2J|wzp>~!q0C`%u_aab`ArgsDNYj>VP!>TX ze5xUblaE$LKFBJ*BXDp5PtUH%1A+Kncvx%LmrFZlbEBMja4n2G3xS%U>{zebEuE<*EE0YCt?svQ~l{qx&sx8Fu3j66eruSNwk zc=f30Cf%KvZ{dLxh1xfQ1^shRn@){{pB8w=Rs1#!=FM)+eh5u;=S02H1Y?gbCo~%A zsZr~PggFdxPn3+C-!u6lHmrwfFiKzr1H@mOqxdVa9rb*Bt@YD`PYiq$bppNK{oe;X zR`ox3xw7m>0QjVxrBGpjoX15rZ!44!daM=?FN&MM=KEU7zj^sUAVmxaw}pcG8Yv3+ zw}4Jjc4=${qWF2>ZYv<}$l|BMR99WjLE<`qkwgk4pb@+>Z^?CAVFqV8NE$~R6qr&> zcx1J4ygC*118`yB{vhMh{3EnMdQIj?U;J6D@*BzSg8+?$?RIEM8s)Vk0$(TWeJmDK zdY48Iu@_2?139}!`r@zo9k|@^Hl1hR-7}w7m&i5NN2QoniC17$*@1M$5CYat0vT-McKr*QK^6rUwyFCG*Z1}9Z8t`E(TXbs%PaNGj#)XsY=CEm z&Jop$E%`iPa09Epu;6E!q=)q`apobDPSshH%av8L2b9buS79OP&RM}=Y+_C%m+k`s z4Z|M@t6CBYOc;BNbXe=VS>)gGfl+>}vcq5D{?)S6EqD=l4)tzmIa-&4(V=VX5~FWB zH^=ThRUmvIRsDs8l#%%-ZdMTH-93Y%AUy zyBE>7e+2AcVy*3-G52-~)JCd!|MoAx^#UznO-e{Yhk$ATGaD)~T&UjDK<&nT^)mTW zWH>cK*D+MUc`XuFTa~-%j9bJ-_TfvtQ4b=8&M7s?8}n;Jvl0#p)$A+1y4-7>>4FWN zU|4t&2=%quyO2xskrO5B(!d;T+pd3Vw!QU5@KAK9)&2 z?`$p|8nK=7u3C#GU5lbTLz5*xS=AcKonL%&E-iBJyx3Aa^^DOBN9qIe0aEzbpRfSa zKfa<%^@i7k@g0?CJaeiXY|5A}S4&FjM!4;1GCZpxp8^TKTQ`Mutlt)`V#rQ^J1@d zVP;br2jkkXs0nr~=QZLo`X7R|P|4rg9)Tdit!mn@(D8};AKB?Z)jOZzjqBdO6T%P_ z1Yy4(_Cwc5iRnR63=N^tB!)Hcu^t(ye|+pQo!YY`6Zzmx{VG&9xAUW?C#`jp$U(`! zT)S$JJ`1T0hZe~_=UlD}wcsh%cj6=ocVW?0?wJ1F!)ho54Gk+C{}Z%b7QcQr?&sz; z7PGED_8DvNOUxGOxEw^)6li;bY{J?x?9?(pA& zG1MhFebs=aUDD{g+V1xS`@(r}L~VMn2LKGDSorI}+H&Tr^N7GxwR>6*0Ai0l`M6Pd z`}^;o+lVhoUE`)GcK)t`n4m1e^g~7kq*aY~+n=S9(uIWxXcu%$Jrj^|kn-LA%#-1M z%UJw-=aS&leSu*>>}jCDl>qSRE>=dPO#uWs+}m%2i`Susiqea#Cr~(j%jcMo{>6-G z(~A+we?60th49aEi|!0(BN7)uW5XCo1lV)1p+h(6|`}ZFwyi&h^rZe zzcj%Bt#7~lRw9bpSGXW?M%A>xO+b{wRjK!At~=p|tM&mgzIlhO)@LKWi6%4=OvaJd zKPTVzLdat(R?Oq}2maO@fL6d0E+I-}hfo1YXc*P6CJh-wKKm-bWA}au@j&vncq2+x zQv*}@Ja@+i<--E2n2dav0sR2|+u@DV^=wMo+Yatn2|{G|OJe*^0BZ6hh?=W*urSKv z@ToK&dO3_0f$n%RLW;|xWSi@CC0h3dZv1atUwRag5yc5Hvv%Kz>mK$IxUs1s>EFoB zV2L@DcX}6+9DKZR;oohE(n*0 z?`>(vKV4sVZdCco8Y&lO3;LjPv$|8nPd}7t1xsP^`P3o`^|QiaPdKD;j;Xl>Nx*s8 z_xMNFy3=P0uTL-W>3zCUf1IK@Oy?SX#U=wv3t$6kA^^mL6o)fQBnV0`io{I)B*a&6 zVb5%kL)Ua8ByR(4RT>GXVT5mDepS*58Sj{*Z3wDCZ%6dK1<+1M*rIPsb8yUiZxwaa z{Szw6`oCj}^nF5)II07P#FRKG+Ci=`Mm&0le3q`>l-oMdy!?2}3QfJ8oAm81 zY=miFJ7bj!1h+4R4ajXo5vpm?$kkJ1KzoVX%4L!2AwrgzC)O6uDY2Qp{@$?*DqLNK zl`bo_28qu(#b-63`Q1_pv!ndR(S$DA;d3weg$N>q-UFrOx?c7hLfYaH2bN=C)<~S~ zR$VOp^!Svn=sxghiR|J4_ucSCc>HlPKi!|BS4Ec7)!7FxoTmas}zXN?!qzn8{s%|Hr5u$!gk9$!h z^MjC;ur;o0qfgSKx^?P#GFQrO(SrJ+FA=?ze`^$Ey)=`(+cxj}t$)7{eZWY0GS=AI z^rNCeK0@?mJ!K?Jy}#wblPTutzhO3B_uNnO?3N~8K`oH81VMpo@r4^bjgp2>E5|eB zbR|8-ZPug!0>5gDpFdH&02U=Gf;^_LAr(D{q_2U1=}C=Jz_A6Hp!{!tf~k<#fVNCB z9o>dmt%f&+I?+mx;TYz%3i>jWX-&B$fAo0kS55@f&?IU@PU8NptZ961}njw05FDEof$58e0!IjyL@=32}p^8N0c zOJ7l6h8RjRs7Ap22b847u#lM}1?}DD0sA6}DE87UjPHaOF7R~2b&4JggbXZV?Jhrw zBbI$w10%esRQ*|Zp|I=^cttybLH=TQ51#_+O$lw8W@+!A5;Cqx!HD4m% zn$Y|JXwM;42-4!Wc&dG~_&tcg1S7P*?Q$nDUDZz_4y+l~g94m;IW79lKvb#Xc3 zRsI1`klvf6yRsSfZT2f%o_74)(E6NYAA{}G?R@Jm$c}aaxv?g$dOk2WC@$6&g>Z^+ z)I{$m<#4W?@zghsTl`Hl21YAMPo}qRLyhx<(3wB}CtjCb%ZbV`BjEI($TI_+ww()+ z*w4WcR|V>E^NW9;T-c-qQYAh1WI-}1<Hv$vs6-BJ0#ut$~>6i!B`)Ygp`|)Ixt84r&KGXsvEWn)4#=F@Jf`P%(M1N8aiI{Y60h-frb%WYjt3N!_YqPs|D~r=I5G?a!d`nt;}d$ zdK@)lkxlc3w}s#DgP@>|s2KJmX_>fsO4LbtqDK9UYB9s%k0U5bHx8xmh2q}Ir)B*A z;-@u2JU@L}LMld!)Tg<lktp8NnIv~&^V02@9s%Oj(i5cREfR(oP2o~&_@-MTVRtK*gZH8s8EkS4sP^! z(~4Bun`iV-wGJMj7g4^naWbMyGti?Mys?;X@GWmy%E=XM^L>caI-CGoTG_!XsC9tn zgEOA(yE*$FF@H?$C92v*+UQH0 z_AD$YAw|u#cBwBAhQ~1lG?F{ch6Z{6@(i9R$!l~Y;8EoU2x%ORN!7ZZ!7a>HUimw- zlOvOoJ&Mr06@_4puX2OTyU;+)>%*#DuB?}59udaNH=~fo+D;=Of9chuyajnG5KXP^0@I)3Y0wtOwbMZqct7lY1;SF^HS+0%sT9|>La6?{SV+7TgG)E;85 z?!Q{VLP~EG(+4h_{s^|*wkbd3g>YIS?QkQ?op7opb+k1)3cHy^*li3FR`(=H#ZAv+ zASLE2{lNN%zOxdndp-dzCH?E#cmG>~w>31Sm>uvyG2-fXvBjjJ20t9lw zmzUG0HpSeR?r>N7M}1FK?V^XwUTy7hFovXog1m6sozHSKt~?TmTJ3DEdG?GF0SN># z(Jj81z@epM^?!O$6i~C=+WepI`RryrTmo5l?)a6?`Pj;Mo$u%N;c`czZd!BR?3=t&J<|J|B>J9+Y5l_j(x^hIC{%h~UNh%!gj-iQZy} zb{u`eIT0O5IPj7OEnx}cJRyY$-K{|EdOE-5Vm@Z1yS?q>;w-f$PjZ9ZtJDpl+~CpG zv~y~1&Z;L(CTNXVn2J@yXg9Oyg$b$&HrM7`Mh>c)0vxg6fWG&!SVAKs=J!^T(}1re zMwFeL7zKI1TI_E-Ckb;aG~G+5fRcVVG8vZMt@j2P30VkQ7>z1&r=vL1lKN!$#&2NX z=M40{Y{F}?48Ue&qCa|dgB+aPxFoGzv}I?Ah)}TZ%?7-+mK7z{PHZ9r8s^2inz7_n z1@_(VA1n$8+;NUGflnc3pY~;8 zkROW<6b=qy>YPytx(~_o+o1uM(p*X$Ma1#=s3a8o0ahl{4i?f%yj?hH$W$wGvpdVb z%C*$u2IRew0o7SWkq6RXhQp~A7n=tp;hTcv0=y{N?i0Pm@*Kvd!fYJv-$|PxblWpJ zF?=d(=%~s&fpmQe*-0V|Md;)vb`l?r-~L_+hRq1Qh@`f|9$$0RV%1(0f;}l=OR&>1 zmU!jlz!V`RpP^MTvxuHkad!1O9)w6I1< z-4{9)k=4Moc#sTaPw^L$G=%9rKoB$lS;CGAM38vNiTFe4uj&G2|GTFPa+y6<0prg% zQq1A5oUnLQrsEIyyoh0c`N^(h`%kuQLUnaCl-{}zvVYpGg%g&{HO!I5q_;JHffuD^ zN?PLYV)SJ1hjqN-|3RiI-{VVl=;?FVeDeSy7oQLUa zz5?QP;EJRuC3j1B_lyq%iKgdeJ6pkV^@v0{s8}dM2w&kudArZ>D%OM8f9+1}zu?{? zOL%KD@xbdGoG?N_+I2*W=Sasjp72OXebd5zz47;Iv(}M>WQpxj2GQ|jIS^YOj_JmoL}ziL7O_ZA zOAgRIp>%jVw&}0PVybB;@W2NY*+<|#6US8S441_nUtCkz|AB0Sa?V8f;Uq4X)T6v$ zp@Q~axylE_U-#nLEiMjc{~pllqFSy&%q$PK0`YcuA~x4k(V&#E&9IU&o?bB46+>{T z4Jt{?jJT^n2si$y2EL6KuKgnDAeMApz}`DBT<4#g$PE}el|BuyvLGJSJlzWuunh=B zQ*_MgNRUIKFH8$E{gV(4h(N7xK@2O}EjyUp99X;ENSP<18F}{O2#nsU4V~=>e~c0L zIi^c5WIb0TmmAj;mAq82fesQ3`X?!JLqxGJz~qRVoxLNrW1e?Kt5UH3$G~EHB>i|%!|C$SEXtj3y^EX2j-~~nA%Xt0nCIoE|N(>J@_BA2C3!qEy{}dzAf2!|gO=8Kf&j`jH zs}ZqvgjoFMOwONmH7aZoh6P{%w42xw$i(3wyyFo7SQ0@&C73=K&`5*;9uH1BkE$3k zqQcr*1@2(ODn*>AnEk{9q5jU0scKXt^GiuY zs_aI74S1?vEw_SDJhfi4y_c)H>&pL!ayWdsOyp?>b^8iO$+zTDrZR;x_Nu3CQI4|S|#v#3r z){n&9*|t+`bk`Qz0ub=e_n-EPr8hh6+CP>52ee~+1RC3$Bl4X(}FC${(xJ; ze+O<fR?Szo~wvr zuSxK>VS1*7!ZpSR+@8N5c)VRK$sSD2`h^CVjKr!YdZ|nvVvp;0s4FET4taEFh<{Eb zm;+_k+7j#S_M!)sYYHFEzm&SSS-;oKpl~uk32kEjTb3u!;r_5SdCMfqP1Ehadi04* zV%uI4=L2HmzR%TF*IqO3su4bn+f$+hV1h|uY?DBP3^L_9JOlM97qC~EV27B+yU?l` zc=FV}MNIc-Nj^YtI0e2BB_9lkkss-ObWEBu>31gt2?`6c&9P4FI+aqg#@>qc3-LNh zno;Lis~w*GTj05%Lt1AU9vN*;5N6jAkFfO7KJ>e@5uZCZ}29qC6u!1`)aJmz6Wm@NJ|JtK=3F`2@qYy$zrQK=Zji$8w;nG62SM1os{@Ai?VKhI=o8`w-Gg_ZYLR z7ElzA$T?G^VuzS4MQY-Pbh@IRp*|w3PvD`S07hSTtz2*=oSiN;dNdG|V68n|S^N$h zf(dgjb=;(b+zDz%dPKY^s-WQsEC)(Z##jziFnCKaAwh{>{vPphCeQNwoG2?b=GkW7 z4!iKK?RUIBYHhlAbq%OqO0I$hCsa#NNb9e~=g7;?YNe)bEGxUk2_$FIfUMM^A5&tf z;K*r;;Q*F@DIV0q+v4ejB94CUhU4=uuSY^`3ApQ&)xQ*de!dt`>Po?(e@2PCDdstw zHR9Sfh&{_C3tpn3h!^U}34f&a1p9D@DLlDguoNi4Lk#MR2z-g^W!LZE7Q{^Ag4Bz^ z4_bRvcX=S^=htbZx#9}MUiU=fAkFq8OpIwbFC^+%sqVe6(1MrO*rShmj8qT*Y=)zn zETHJd@P|bdhaEWn(a{M2>0xCyW~tzaIW70EP@e7OkNi$R(ACfeGcO9^JH^zM5`2Qi zl?+jXgJ6^9&Kg~z!%@<~Vkur?mv-wXr6mb^q9KZNz9j0zj6N1bpyk%zG4hAU+f}Y5 zF(X6VXBE>g?T0#4nl5~&LU<|mIexw#MUt&(Syn*tN zJtm8ns+WW-j?>hKy}$$-$C8ryKMHs9?PN1DP*C^1kJ78bvZ?Mv*W|;b7A(-4sT~py zp+V$NhX6$e$;lG}IG8WeRj3(qS4Nr51~iaB4+U@Z%$2KF7sebm89k~5%(#OV;2@-m z7J$0wn+B(_C?f(iGf| zXeh(WI;W(#3?6Y~0&qlg_>V98w?Qao`_u8{M^XO-7(0I*Egzaxj^gw4Jf&=EIQBiR z^E;!){t%4VdXVcn<2jcP?AR`$82OGWGdsTFcfI?7`VCDSZ$h#|YXlU8OYjAw+6X*- z5$%uB)m+^GqkFpQ{!@hzC+ps8@?_Nh6oP@6)+lUi8d0`sthlrs&8ojZe0if_aZ!15 znQuIMIh8VNK1Ue?#JGThj{TAtFtwP2@dnKfzpobx=0x~h`4vD>qc2hCkM|)~%2QF~ z2(ufM0x^M?_@9x32PaY0&;9NaGZG>Qn^)K8CQ6-#>8TuYbIX6o@;e?wkD6p*1 z=8Jj-aq**IE*bVXDUT^kOsWUgJwFqR?@w6MZV&f&@v*#l$_{9=HX5U~rrGxIz8Z;1 zd`pDb6#thB$ifq%J4A4RhAzM)nI46R{=1+gbHjRPY4xi{C*1$A3$_ax89ad290Wia4k8vTNbUaraHy%kS%IGr&Muiu+?^^ygSt`h9%w1 zc7Ul%P>I+xlw31sl9`jRZE!{_$%qtNJbR8Q)Q0dRd|FAJsXztYmPJsQmTpefMB_&- zXIcMiXDk*U-kAR_>_)JAD-h{N$UICaa5YcA)}a6&GQw<} z8u3aiYKr~S;?HmfU{5U3$8lsDPp;?9_}GfN%Y*Bx56u<*6cyGcVr*R}wp0H=*4BQR zFQLi!u|(4DN)`H+%vv%dYs~}*{{tCGJBRV;8CVvF4oU~DyUSRw zx{i)zGu5Tbzm4n{-@Sstk+|MPXWwl}w|{rV-m$CgQn+?uyI{m#M%!VoxW1iI?^&xP zBRYk$lZqDeG0E$J^)X=MsMd`Vtd9xTbfqZ!AD0(!4Hh^WWWVogwKJwhEOf6qE# zUnSG@&U50wRF)(D?tp?!3^)1JSh0X%DSp64#_wrm28H6bU@#&d$R-#SvJPU{7I!oQ zR#2IHi^)6Sgew#^cYGih3q9G`p%MV=mucS3Ey^vVsIUt0= z4UZ%dKMjg`zyxdwU_d2ycG!{%@5JjN61@4&n#!g(|4{7|qW#Ellh*myH(3Bu{y2uc z;D>8x_ku4&waVR4styC5!$a{wRck8{qPC#ovO0qZgxEmjAcCm&i+w!xRq$qDLIE+E z?7|;I1>E|G(i06@(j|OrQsMs7q?*`obVF7j^cG+2%*t3vf$1GWHU%rvJAXDZMJ~8+ zODwe4Rk6l6{cgH!JE)>Q@iy$j=x}C+cL{3>%fuPzsPV(QUcxG@?Qw?twM1W_4$fe8 zrxzqsirm}gNA3A!O8?7J@bE^)V}2>d+MbzoUKld(i0&l%m|Z5J)`5;gM)X5e6beSe zeMSE{yBc;V&NotEI$LvJMp>bu@ocr>;K75M87%t@c$=vFY@*JBDM3XnT1ujGh3W3f zT%;_64i@mS*_C?BYvUDCT|V1fR`gF&cGrkr?wzEUd}|dDF;n< z4iAz6aQ{~PP)pxGODHPwcrp3ZYZI>aqr2ky^}|@fp9PI^#+7B|BHVjE%CTWy%6$Q} z-VYD<#+!eT(e9pejJ#SeHLe}hXdZRoio3Xbgh9*QgBk`t>`-;ulUw`&;-lW&S zLe1)lk}qJgPM)?h!?kLSv8s!ljlB5yKp$-VhG$HA!@kQ1{U;a+@s|+_M+&o!9wP4# z#!=nplp$LTdz0e6K7M00iA7PliO5Utj3)&aEu3{EM7;7;EO!+?H3So!TQ+9xAMQVD z8?lP1MBUXN*fnB!0L&ysTdpwnGSECHiFyo8jte%IiH?NwJ6Q21^KR*_U_=>hHfyY2 z={-Z#7xg5-jN<{a&H2#p_^%u#0Lv}okP+c+`@UzS#{bZ_3c-T%HpbMGLO6HOKtX|j zmu+AWb+f;mL%t>P<+C>LKV2wT3lx_MzT3YX*WgF^@%e|BIJgde|YV} z_6e+a#vC&NbwvnsZV-!W&IHNrHxP3dr|Q!2Ywr=(5?srWQS83YoEw- zbMLzA{)X<}UAuPeDoshkdxntYD@wUcv$=NQNXL)1gQ+ zH!J_!|2bNhY^`c-B^-xNn%Yh4fO~7K~#tySk^{rt_2a=m6K3= z&XK6Bj3k9e!v|YO5}N9uCmt(O7Zg_sR45Y=YtIE|Q!;sw;Z z-G!Ar`4v5{(VSZI*qy2pF0-TPS2dK)3v`Q$BD#WcKhf8lQ#ky>JFR#8`o8Q&a8Fjx z;P?IRt!4mYxRnpI7GPdNb9IO5cX6*$R$&wlXw%68hF{R|U+-8Mw#HP)y6z;M6mBtj{`WKa3R4-R9K+eDGZl zniTxG>wyfu?Y}0azma!~UM~~l7^-Xs`thpvS(`|u^Q{;uL~W=hIFH0|*}IMKZxQ9lmpc_-DQIK5=5 zVkwdk|L(bD{5XUMg4W&bMz-D6yC7P-Xne4#K7nK~x-mUxvq%w7B}|K9GW@Pf8NTb3 zY-QSRuczV+JXiEYb3WiuK<3ioMUVATnP7mGpn!}yj$S#LK+YojSUn++7Kb8`^ucP8 z0}2B8!A=LenHu2dS3enaHfp}Z zx2>S<4bw)VYf@SkLGj7~oi*jWqIXr3*=uk5n0P^x3SzJsc>}sD-MZ0nx|Ty7IZE{= z1*a$!3Jp#1&n9g$6k=0zWF~4nTeW-|ECS)(G&jS!=uo+6aQqypA1%;&{L0Zc0?p#v z7tCr;W7iLETF( zW{jHt0}XB`AhtzECP_KdUe*H-WO18<5o_~XPR5IYmxj!)rEQE@?|SA>}BWe z`zMfx_5(2O`gSjG@DAP?zDNGNJJk3Am=*PV>pqkxL?M2#oroedy2UL`81=)l`N!w< zyx+ZO7E1}l*z=LqY6|SXq{}!3L^^2qC0lYaVU*(y89h=U(}VO7jv3$}P8gI;dq~qP z5@RneC%3g)u{3Q$B%tRTv48?Fk#z26T-%N=Ls-&BxRb4A*XDg-sEQf?76v!P_)Tto zPNo|k>pd+{-}uw^P}*fUkq5lqeli(DcovClcwxCIzngI5@<)+D{HFj zNSO3(+orP@b(J{Km3I3DkM_ciGD>Y~uuWu$sJ+R^aL-%;xoQ8e5GSFseeL&@AN+9d z^&d8fUf=5*18sH)H*m0!AzZAqc}GAGHeA8{gInz;d{ph+;R8S=r1qg(gPKh7zDr7s z&?3E2EUFwa1&_#5+7Bm0wnXWvgh0haK-p$EAZNFKlI=ojPOywJh731bE%7@J4cM1| zBy#DH*326#O>Z{F*mNt#$fzDe925|%HY*_xH zM?~zW8rrc)DNwL%HX)({rNP zyytkB$>S40djctfR|fYVQ~1>Cdg`Z}-bUYSTnp2GTh8mh{=(I98yrIvIn;%9#P$ml zeBq(SI)5rz_;*6ivgP)Fxa@}5jsAoiVYfZPGn=C7Psf_g_w0i(n=o1{$C)6>aUcUL zr4`cbpvMA$@>BTW?dbcC?~PuU)~BIzq|i!b(36^!#B7MB<8Szj%xzi@6Vqu@W8FLI zooh@{_$)cw5(_oNc8tI<1CWs7qucr~ab(&x5#u%1DN#HgcuP&D`t-DVs)@lQuYe9N zI+t+Arn2MQN(EvkPrf5gd!w|kH-arRor(@&xgDdp@&^0rcy4puz65(r1Q5}HB*AxI zv0!^0taq@l$d$j-;40Y*=^o%o;&UN~R&37JzooV>qOUB3=TEPT7A7}84$zf(DM5_bXAS>3Poqj8<+CX&A57V>qZ|E3~eToPolQ~75Bi_UR!_nI&;-<=KP=1Bo=O2ZK3_mS` z)|pjL)0Di7vtCB@M@iJ;W|7z-UmCHc^tUvp{TPIH^Upn7`kbKhGCd~4{WN5H#{Gcm z>2Tdd3kiy1ALl6|?wcJgN0dDW0S}`61w7J21jZOU4K(KDwxb@o#e-kW@W!%?;isv~ ze6;XK5E`hMs-LcPE2#B*U$^Uh2In|MElV{|k%RGuPNplcs>H+6YgS$Td=y5tK ziM=w?zmQYO+m|B#I-rymaM9ShvKQEpm+XuDwZ$OSLT0;JIZiK)Rv5;x z?OWegh`KKTlvcYHn1z;L_)9gU!XlO^?52vzKe-XI;wni!G&L`e9ASHCbCK<1Flu+0 z+i}^>ftQQ?p`v_>$^=I+Eo_7EDW&v>W;SL9Xncn_Ual)Z$-k&o>jRlYVR{#(s-lBp~R3hOcR+I`c~Sp?f_+(&l6kl`W%L>L0JxSJMN&^k^<6cQs# z2jm`y41y`s)xVbYQy#dCcGs|#29+s?Bp%> zOhP;A?XJ=sR@L){-#kRjYn=?axY(7(k3~0I@ibU@Ky|*=LVU~!f~{U8?hbVP!gl#? z8FzerL7#v6?B#$K0^VP;G~S41@H}^~$JB5Bh9WixWk|0t0){!#2xduO=td57fA{$q zlRz0Qt6Ek?ylsgpqKNzb$^~u%PlRiFDFML-K?BDS{Qmr`n;j*N%yoel%$5}tU;F2+1RUz>|$)ZYU0iE^u zG?8+(pzblpRMvg1#P$Dz$v=dplXWjRSgbewhR$0MvBEx@+RO&fP+D?`jh1`i)AT%h zpu)c0K4u!K04nDKL&;1hU(A3vs$7>ppbGy@MB)2J z-3?(*xqi5w2JqSV5KA+Zd8ev|zUa8q<{;(PF+!oM)%d zT+#11Qe*yTjNZZ)7|hV`G3hKcVEi6u1KKGHh6a}nYDm+j0*gPHJ~`}hm?<}6{2Wnx zR=;*K1S5w7dAzmnn1KxTrWeBPybXN}6}AaPFC17#M-{STI}-XaJAm=?s>(OFbG}4w zET1(&t8WvHkF~VXxCK6hUOk<6FNibzm1||Gg@aD3=q@|`L@(TUGSTXkvr`ZS(G`;MY3f=g&wF4dI!m{h zU^j+#>1ci_P#iVH5EVa$Y)yJI&Q9B8PP>g8bQ*j~8FF(hQOK8g{q&tjVI)5vXY0Y? z%FKH5Hn*aitZ$YtpVkNp5f$O;mZwEGP_?4_a|G9wZ^R2_PL!>BgMJMf&MO+dCysejIb`ul9a5yC0>fFUem|Ix*k0_I}n- z(_D;o+_$GTk;+PS*44>3lWoF=2v;IBGBnEHbUnnL7hP7(+Zo{=K*A*%g4uF|C<%|A zag!k4FE0=;Rif8dQhgrL{Q}B~alErZYR1olTnOYrevD$z(_;$n(V_w>FM$#>nxLCm zF_&-V)pD2MUN&4mULc3k>`T8q4CG?M0s&et4Ivi-ETWI0E8bisG^YUd?LV6T*dj;v zEQ{&|cm4L?vxXy0>?IoI!_Ud6-w^XLDk^V5k#lsgt5S^~gF6!yCb3a8kQEl+H`p4= zN#|NQcn#^-u#z2iL=gC>j~9?5Awh)tCE2zr1yh2L1Y7bio`kQkqCoK#q`|u`X@}ss zlnJWI7>AD!*dRV`Zh!_g#Zb(g$P_&~WLcQeL@yMMq8iUnv5E zA2j7QqkJe)XUT@$Rcjtzu9xKDi_4{(qV-_nf+#J)w9IQ`yWaiw*+wktyp z#Y)zRu%GgUvyowL#Nv2_#^yyIXF7aiY)l=pqRqm#Joq}*fNw!P)w(-TIb|dkJsA`2 z4{M^Sp%OeW;0-O7@jHwyI27(e-@_U~E|)*X=$*YVUFKJIUVS|F`KeUM zm5a72@i!=!QqHoZW;&nOGo%mG1eP{kvFVp}B)~d*p_S|JgCgmuxJNc7u(*CBNqp4M z8Jkyfg=5>nxO;Ts(MgYuu7QccaL4FAO-3xZm%M@cnegZ6WUUm25QK1JDE99>^H+Uv0f;Dqn`*Gcp8KR9J7 z0x8`ZvL5JP=pV(i)^u{RMN;GX*UxPt@1bjQ*=WR%D;smdu$z>Y-%VIIj@^EV!V99T zWEURChK!kfw_y*KyGwsqXV)SoS$G+hkLx4k%D$~oe9jUzq4Ct{=E2~=r*WEnv;$jj zebdt(q{oY#+M9!|@0*YwbGRave1vn@Yf!`FU8=6(o^m3xfTZ2<#M5G3MjLe2blrrR z*f+rH5nVjH4UBM31!MRV=(pPNTy~4jUY|88YL7ckgLNAn8020OyYT_O;dyP%p-HK# z#bd1^+s~)Q-3kk5IKuk_f*TXhIXs~;^LMHF$Hrme0qAgOq{iHy&IIU6zS9|5q(l)y zP9iVtHXC4o16FuQ<0%nYo^^}e7o1C4`jL(t&~lq6BR8opPDFVIWN*Ea)u;WP9Stzs z>xaFOJG0pRwfQ2}oB5kHCf>z0Q6S7bolv6$N>&-#1lsTY5{@5}XzRyubie#woY_@8 z6`QGW?LYGsUyH9Y{md#y)`C^D5HBZAr$MvbYi^YY36tL;B-fy8U4XRLz|p8uEuPrR zKQV7Cpp+W-Ov#Ea(sw6!N8j!7g*Dlu1tfHBr1uIPgC!jr*Bg;!ZYBdit$J@K=_-E^ zr&YlN^=DJ!XLq)i}*Ym+qd;L!|gN_}cz$Ja&dH2%;*0WBw%x+J=-6 z8!xjm>zL)AxZYs+Ehp>WUs2QamN;7j7Z)nWDB|)1IWf?7FzZb3+&+an^pn!dywkZE zTe46H%N8%})NI^Q{AwnHw6aiRa&65us%@yX<0@|;g<9(fsS)6D>a5G>>`TUhghVeK z<5rMFpKMLz zv$${uiKoF5f-WUt(d~opvmRF-e zHc~Pwa64OCf|jYea`=*Qkoc}_1}IitI5@E?pB6@RGr`iQL14duLM{9skqA|vN@{vk zHq&}JcHBiii{bqC<&UwBjPW$p7Z_DOOV))7J9-Un>>e+`2m7a)KsbH{7zfIF<~d-? zgEb!eAlrtawZKKGR$EGEetnudKW)@)*IT?q-!Sk7vY0mRTpW+Kui9Xr|_6S%o)5d5zxV!h_>=4tWq8cYIeK8*^^%TSibtdE93UtDSG`;-$t`s{;I4Rs4Q(^za z;e8R2JUNN^@~oySmMAxd>Pn-}Zxc$zB#i4qr7P${QbntZ7ZUauO(4Id()h_cU((-% z?m#GC($f@(EzB@jDxu!IuEh=j2RQe)n= zL$js;wj&77Wi0nQ+rfQWyQ0&~p>4kDb5MyWQMgE)(MS#06z5sifo{y>1v1hM%Zi$B zk)5zgsnK8um&8~I{odTxPp86LJm13CvgA=~!<4eHMw=M5z0dd&wMVq2Fu5{yR?$k< zCI4%^yau;g;B+Ko)S9vS3v2MWeYtfaDNUo zqm?HKKx?n8Ist#*ZE;AEdEn*hI^e%>G|x>vYtRN`RnXrkxTB~sxb-z`iQg3%jgyzq zP$y9KDTQmkAx)o2B{5m-I!RpKd7Qu%y7R09!Rz)#CAv>?8{^y~=R{hL@H!yq%IG{_ z)ieKn?Ha!soD$1YXq809VWfivpCcdD?qOrsg|lfeCQ#s`Hdz-pliay!7k{1k2v${3BK{Wz5K`O!@bc=Vp|I#zupCmUJ8M za$vsfrNDER2%1H@PST32MW7wegzQ148bXsZA?G2t%r7Xej&Sdkp+hyjnQ~{nbuR!y z{UE6deQq;i0kK)2RKfCbhF=ZzWGBada^y_M)NQ@N>H=G#cnc@lIGqimgP^g<&|(kH zlBGMV{cJWYyI9sLS;Yy^oX^{8Pk%q&J7!LG?}~udP{h)em&?PvR`lNTP=Yb%wJG9G za2k+Y-Br<>c*dcLl4w-`)*sN`KNTD%$e^`}E*e6Xr8OzoRt8r#1M+eLn}2ez^BT4Y zvK#qW@X5ij*9ni4>Id)*jBQptw$$K$nw1N$_YtVAD@%!6YE$`K~P0 z{kca%Y z96!dodD+lWx`!1fuio!h$klhGUCRhd@_OrboWvx5kQks;)weNLx6J9xU9bDC>cl?$ zIAWHo1n8d&?yhnPZiFHw3tq|U{DM-+^M#L)wU*#bP5{eVdS`l%o)V$B8J+7a#Fx(v zy0xw^D-=ZKR``6$sxk}|RYOu!9G|;^8x&Vv$#d2I zreDs)>uINni8840Y%N8=F`=Bb9>^x}{zr}L5{EBpfFACUT%!g5tqhyz%(VixZspy@ z8$;lAC@5$6Y(0>EG-ui5gTYknf+xQwHkAPC2^gcM&DGXcFMUbQZ{CN4m^Ed~ek&UZ zM!$8_we!up%l*TrrgdHvu3wLrU9Zy4es4XeVNj|f@6ZA2eix(v0=X24xgOO0h06`4 zw;wd_nrDmj=fcWXQHv(jWAfW@cC}@+%Adu-a&@DAMG+JtfU3OSzZX8)J;wHXXJNT} z%y6>X#q^9ji8J3!I)Qhqyo>iVu$_|P zNGMZe>?iQ`;Adr{ml)faJy+$&5YHUX@Yd&}gCiY16^0F@|MHHZrY%I08zT`ZO6V@= z(6WV*AbE;0FQw-p+?r4a1Gp06bSvb`u2tZVK?tUQVHf)a zHfrsattE(Sh;r##tgfETf538P!V&chpd&G^mXVr%}s1B5JW#K%aq@bPK@*StdBNp~)8Fz{y(@ZEASRSv8-G z7LIPUh#$CV4^Q8T5Q}o}sE5)uHU`OIPefP8@@$`TYgBcgJ2qF&nI47}kK1*WfCdKE z&ONn8$xTnC-v>^>w{Km=y_GRlXEsOjY2m?y)TU4*wh$2fo~}P>S;ILPXabzG<h z_!%X-3XFyfbTh$~+0bxY0OqbUM78}gT~lg&_B|T!(jLld_^-br19FK4E|vL#CeGP5 zKQsVKUOnIkcvN{fo($YumDBNcx;1EqJy16GIAi?g0_}3`inEHA-qE;&;JaNZz97+gdkp&3+C{lr znHJdZ;+;Q?a49i}(!xjtk|YCIAirV_?ju%G`W7z6Lugk)%?u10u6`29cN zI8O*^V1+3mo9eEui|Vu)smb7b?NS&Zd`fh2u|2yQ3={Ib#J~Mj!A-1M zM@`e`mIZ)8^2?_Mp{!iVe5=+C(V)7t?1PQqWm6RPx0IB$sQX6d%%ly~etY>U`?W`| zenXUId@h1<)I!grfg@KKh-RCbQZ8D-hpcS*$M&kN<>Wx2WlEW$@3U9$KX$kz1^%aJ zXGr}D`*3`YlLn5)7-}=1D3b}3riEx;Fj)_0gFwy8D3I{82oNE=H)VQpzJ6I3veiC8 zit^2DEUy*m-cH*QY~0syB=$~7`oMkD!+F}h;9$Z5_%_5BP^39y0|ohzU?71ji4Ihf zPg5vHl$hB3QX|Wf4uU8a2(pF!L*S45m3Zfyx0ib;Zs(1p%=t`UAcODeZH$l*Y`mTz z>MebeOx*m_kfdVyvKCFG;-iG(BXY2D+RW@jj8gq*OyY?V5k3_$;o=p`!g}vV9u>g) zauuw$i7d%i=QP>NB|a7Gi+i7kkfbO;l2>I4q}9CEVW&Rp*YjXmM={QLE;c3S!57KV z9eSSFt>%gfDmA z$^s<(T&;q>C@v`%qN-bqwfV_1Q*T0<$3ppZb&&eZ-Vh8EIK)4rLcV2|kqIQa?-a5g z0Z1#t@wYsf;}~#U6Q^8CqoXM?jZ{E}iu~WoRm)?^vS{_BMpNS6IT@;4Nkg87E!aa+ zcNjSxbjc$gVj7B`T}_q;CSf{C+vNm16+|p6zcmWB*JOwNX{!^8AisMCGi=F8M7_Oi~8igv%@1FuM8l z!ld|oHI#jsGg#T~oyWXYTHeTSDZo?UVYu1mW$+AaBsK|x>ti5MgKj715|(Q%2WN+BJQ9rPBAUj>+$K;4gxTV4l>9j=48 z^AOhz8XfqZHf$eG=;P^{zf&L6jrWa%9;y^<#e|vu1pA_`t4^|e$`^|6>=;}5*e~)% zE-3x(LASnL;SC@|e*Cp7cy&jz=6Jf>U~@)c3>W#lFT?^6kB8U2pf6W`WI%b4=8wyL zhPd;5#v75^VFppg2X0xkqq zJ~`Z!c*VJG))i)My?ByX)Z_U2{1NXx1N!+5KrsxSPxCc&gXZ;=g_V1b%K`*Y(!%Tc8*XE{rt6sT_KHp?cDPxCAWI{GgY#d zd_F{REv%AsX^$x70 z3)08CBJf4NG~|`@h3@0LPQm4rlz#sF=;>k9A^#ptGVC=QGaw=qh(UDpI}-NsiTI#L zbxl_9V?5%Qa6i8Lc5{6TuHYR;9HLig$=qfJ<=dK(vprDn>G|Lp!9v;2J)A~72Z@%c zb$1eK&g~N-iBz;90#hVk0OHJwjqsQ3eiZqn4;u$VoMGDRkaeU2i`TI=Ej690%=h>r z#@XOYO}g~h4Iu0r!3PTCeCk0?<=O-MhsMr-c|?fNtQ`@Vj}nSzw-wuw`8lqcyjJKV zx&3S(zsM|_Xa!3EptxH!!QRke$?2AGm?q3iK=(8@Z!)yQH}Xi^weTQkC`!Qpq_uV= zAW#dLKe*U~gz0G+icj8m?QW2wp}-PI_6j&&Pdz+54g`K8d2K{y%{56)NR7*$;`m8m!8RgJCtvoCW5xHhc{&U*CViHnhe zJX(n5yAZNa`1!x!4-U=TI4CH3x5yvi+K&oJ(Ek_E0nq+5c>=hh@rC4A#M4fHbcV-5K%W++L3Q`qF)S>%og^Z5!`B@Ky35 z7-FCj&24sdN#2V|{JqvrCm)HjuX&yzTtTPR8`cEwT|ccERaC}3x4IiwyC~7{yyGHT zf{PZ1O6}?Jty@;~vKy<(wSIbGInuJ9L;W689{T6c*=YbPMt&9=i_`eCem;&wuTtq0 z0r)QCkS6KniZq7rr4uPBSKvgBgnrewBoUg)xyZEHaZ-5{FZ`uXGDvscU^|PMeQgnj z7G@hLD)=>QsHFbF;Z&Z`EJbl?58MjBjxF!R;{CO;Jt zr+97Lt0(XP?`?q0&; zS3@!CXtXO;(TfV+@9^VxQtV=JzMpcuiV`53#V+*48G`}B($E;tZk6+TX^jaNpD#Q8EQkw(44zFUyUhAihWT%b{@#Bl_S4< zUg-IQfAm{?H=7yy7SYGuj>{eQe(?P=ar^W!-gPt~=Qo+pN;Syan=jC_7J{yKB^Xu^ zhW#OAz00x>IdyyARjG)Pddp4KkbLK1aDKC1eAZl#qMEG}dO^=9OxSb`+~hHd-3slN zb{FtJxLy zW9E!v=Jz;5QvDueB#dJMpA~#h5L`V9JWpEPh{aDLg4H9N8B!rzu~Oe@svTHp&@i)c0sn-;ri3`?IO!N7 zhNR=eDPC(%0Jwq74TyOibuI}RTqg7m@I^aO9npCnbM1T4$`hBy>?_ zb-Rr6I=fjqoa5o+(L?_t=L;x{Zpgx3rWrr8s6jh=)+!)QRFv%Y3=`qZmfMTh{yed~ zMWi3EcpIN=jMV+tevEjwfUG>^elzmR>){?fm&%J z6C@udjQSL4%zy54taL$9wAiFp=#pFF`4~=8z>bxhESz!PTG0T`x|7gg(|-GFeXltn4W=%XA(U*Ehoj>;|NA`*2#E5Z@8 zB|!HPKfG@FC>OVTSt$8LnrCi@c1=zI#cVv*k$<}~`Ky<`_7DV!WGWG#IAUK|+8|t6 zilZuXPI%Y6r(2jD(LwM z;uj_4h87j|Ty!o$Pf^Wq^_!MVZG^dxp#zzwSA4ok&4b}U;NH?J?Eh%>s&FpoiJu~$kQ5n{&?<5W3z$#0F`j|A#q@!;x^_=-ECD%|%nhh^ebj+s=Vg!+IajoJ4Qu(SGaZZTucC&E=*%W%wW+Yi z9{Q86HCy)g_N|=E2l(O>AYK|wn=1lXA!MS1h06bW zFv15-@nP(WjUqW|YVSB*{OQaS75ab^&~mfIWSv}^ey$#vnS@uV|1*K5-1bGybSY)s z-U?sPp>US?>9f00J7XDoBXM{iIJ12C#ja0&RAt^xICm%}q zocLn=rNFr_stB1f7VzePg7BnVjh(r*pY0pm`h5Jtjat1L8USaI{7h_OA0R~A+=I_{ z22Y2yvPk}dd-yh9DylfD?4mmHLoI%eo3Q(W$>p*S4<;~4$4H71tR=QqUkjJ4`vZD@|Ak?f+n%P@iaMAcZSYz|cJ<}~DLs4hmOLpg z*{l*G$G5jzk4EW^2r70F`4uv{1;EDE+ME;rV#=hk8Qb&)8S_GP#Q;bYsB~|Jb}ns% z@hiN}{5$#aDPF2j-lzkhcD%VrC~^b(uZ_l%3Mj6g%wOCJ$5s6&mLD2g+c8>q9dNcF zD(`5hfH7a;;MMQ~I?p@X2z4wJC?~ohw%Q)>k2;jgMsWUDGsOQpuOg%5M$s7`=`kEe zpOYOY)b2wQ_xcys+&|(4wG%x+XBW_mFsG9b+}=U^Xb5mmdxsp)^BjKq>s?(;9^mZQ z_|Ux-u7AzC3AnHfvU%=U*^>x?({|?46^BoIV+Gz0g4kj<1d0NTwHM&q9PK8!G}=S5 z8S#GBaF%+v^E?@`jxKz!3kSrw4~W#d{x=gZW_MyDkrPY|LGZbJsAL$<+l`dKm>D?w z=8hwQpl&!?gI!|hjqn1OH<)RhKGobTCpVE7VS2Wv9O=zXs`g@d{(SOQ!Ke1$+zjnT z$Q@0cpvL7~uNnB${goxM)^3Z}*!wRa3|A0u-C}Ux+@}F|cnl%9z}?hRGdPb4Uo&EPMLcI;fKqH9dL!&-jC`U}W<9rxW=f z(E4deI6(@=XsatNm92O-R|X$}DNsT$#tLc)jPS(#oa2i|o}}qCRFncvup`a{ZgoCF z_k}*DC&WbOLYGUV8I_@c4ux+K)i5xO)*DSW>;TLkhlVmA3|{to#ea%8@BV&fG1k>X zR<-!xz!itrpZv@Pt0C0Odp`D4d|`DtYYLSmujbRFKp5@6PJS;smY9^14*s`9f*HU> zVvo`@8{2M&(yKp%?7gWShc@JnhD&%XO-?gh#owm;vPPqKuf|H-i=o9x>^a=I+3Qbp+nHhY~2ZL!3%GnF|qwW!~=KXm!U(uD4)+;y$qY1VP68g@T| z=cY`J^3TEt+HI(=N>U0cywT7X+|b0?RXMwzIvShZ1p9p{?E$u;qomyg4;4O>hcY~G zS;e*$S5w`&xdb3CIdT6RAGfiizKc?t#{=|x@@z$-%{U2nBs)81)<8(uEmBRx!tmGE z#G3;x_0#~@lWcAi^Tu)8M8C<3Jk%l+XC3^+U_VR-Pr{`fZ&0)91s8~`f#;fca)y{wHKd8_q4EEaW5aLgU zp4V-RG81ZZ>Jwvq%VL)AZ>WlsPfY+sk1=DL6|}Ph49$=nmZ2$5U$6hE9PVw%0|JU< zd@@DMqm?6)(;Bh#!I6=f8S(T!Yxq>F`__>i)3wf`ilg@iJ)fN+@?JG3leE%@IDAO{ zCOs2rzPrfH{>1H}A)5G;rnXgrhjXnke{}w@5G8N z)9wFJ2*)!Y5-l7GtEoBbvZdvmzMpNqSoOOy^AZ56dW7}%UKAjI@Apux7Yi5FifR1c zsVFNW%YQ2NioboIk$dW5MMq5}gLR3y9M(xeg~LsP=1k}ajeUeO?pu9ZN|r=01Ue`F zaVtcVlw}>$G2ck_ix34Szj6B3J2>g`Vhk8>q5iu71(5YneeQiZY$$+`5K302@5sx4 z7q>czm-g`Y595ld5decs_aZ?sXS+1akXdcYBBv6vaR!BSY~;VlqH} znPL%l>;I!85-(wX=m=Ii<3hA5=1#(bIMnxxv-^^$5&B}kUrymyLkH$Ui-Cc}yb3%> zV4u2e+wjf#KP)oQZy`GN(6J>Vr6zcWA1+LuLJOyA9N7pI{v-PnC_O&2qf=zNya;pE zCBm2J^kYv4%_!P|k8AIOUo+^6Z90={`4D%%EvEAQP>C22(L{hiN z-D6nCzij1b7ar|oE*0-mSJd{)(E^d#f2veovXTj_di?<+DX&T1t?;@16PMQBA{o+T zsM)7sKc^WHdj)rUWbDWoTzf3CW*^MT&|0mc1ssAmZD*)KNoR5g-45;|>=$WdU%c4_qnQ(5 zlSKP*@zal&O8C838mN=eZcvo8e-|fl2ZBd5R2j?0e0hm4XiU!#YDqRJ&Dg%k;h`Hi zP?_jUU*&x8g~yfhmgnVz^MUZ+I&V#PzFxS)5qOQ5DdrgBlTLrB6f9>Kj zjB-;aAv|7o=vxPsO-sGOo6sMmdqCojVR87Io%6 zGK;KZt@)YB;0j+B-h%uT|It)G&qoQYRxennbPDp1AK1pl#3p+-kVu605u^ej%Bw9LdEiu z&vWza)8K<(SCJfBAt#>sWk2-JTks=9N(FuJ8O zXV2HYu#gW~fGAV#5g$8ks!QdAG9)9Nn%iYN!Q@=ozE8<8T`OdqCx-=PGn-1(M(GTt zv5=k1C7-EuOocd1;gl{u-A%b2+BuutP4hi-nK{8J>LIw;Y-=PqLANuCQd}$1HQt}y zN-?_|YiG!;!J5-?Y6C!QGm@;O;B{IWmuSr-l2vCv%~BQf0@a_Rqk&}whKZy1Km065 z&4Gna=2S~^0Mtz#KlL;&95F$^QP++fR{XSbmkF*4jbsMA_8abDsrHPISqY8*H0Zg4 z3Y~US>P*P!L`qm)nW*s3kiEO|&M`RGmgV+%|ASaRaMik<>u10sXbIL7!H>8^VVt=Y zM6?n27+xAGzQ>~GC)#(>1i6+K$^fZ^!f_N`pU;?r-I7(m2KmcV)Xc2xc5xs$NnuI= z2Iy2ya`==YTYgw!+>2^!ks6o1W0dT{s3AftZsawDY|zvx9NZB6tSFfg%yQ(D0;`re zOJ`}-3h;;}-Im!^Sg}&eqJ*w^am5q~<7d@PxtPJAxgs@{;r%w{%-WB^6u&H+*%yo1 zYMCX=+BBLjIt<30 z_I|8Q?9I|#WBMP|p(?sBvs2#DrHn&2ZTK#On{<}ic$Kh3rM z(7B*;3Y^{7C`W_s{~_!hpeqZO{oxoBOl*5%XW~q3+qP{?Cdo`}+tvgV+s27)+x(x* z#rN*}?pklHv(DbV&smM?>guklU)7HKEF0BVE`U|R{v<2Nou@V_DZc)>u;^=uH(|6E ztSlE;To*O~p(Qy`lWGVLThbAL_wv-#5n{85w}OqNp5TC!^+g@ZO@mF-M{IJv_A`5^ ztz!wBKf~%=gwPrFQ_NUt8R%Tgwu>TZ(mR~k3iN@RC^3r`^2-~){`HaJ*5$#Xg^kF4 z%s@?nI}INS@YSRSbT@?ni5w0&ZPXfk>+}`jf4UR!tgQMqX1f}+g<3y z)-C5KvdybhtEj)lI#z%nnaI^&7iTILgsb6z1Y5;@o1VOTQ2ymcEOy5&0BL43wR_Q? z4|&xwva)RxID!np#;&Jzw%10VCt>C)E40|VEz=6xD|wyG7qF0yN_zl&bnxWzRHWJv zGmR3LN!v3xnu-VooMzy2jWfk5y(dnD8KVB`TGqx8sUn+ZGy6~%m{NYC!8p{fM8~aE zva2Bzk#6hn`jg7}0DiZL#%g8Jos@gJKir624bPMdPES=Tx*kT{4HcK3XEa7AG$lswIp}A`cqJgwc&BMB~0Tbf#pYF*%dvidI^pDcEyvfZ?524z{eQ zA)rCb7^vtoJ|Z#JAja9*^N@&cG!sWNeP%l)Sn241;tne_MiQNEcv7fQZd`1!MPS*a z`R0$AtL8rk0}p80FQdAuLs(0t%(niG=?z{#5T!qo<2SJHYHl;z5F}qimHEigX!~On zule@(f_FA##I2lxN=|raQ^EmH$jG#dSiheXw&%=6=j!B}PkEM@FQ??$x7$SUuWwh7 z*3bS;ogdG4muIbu*{#C`fy=3pV?zJ;QHz%=@>r;thUOA!<%7H)bRNndL2_qwm1`=k`V?r!i7?q5{GcThXfoX#+5k#^X(sbY^J?Y`|5%OA2_;a+Cd6v zt)`~m@~tUl~ zt1!RLpJ|=`u+*A}o9HeWVUj_i+X{pKLSt7K<`AO?wFXnHsi0YPEIgV<=EGrj&G#>4 ztbN`G8X`h8efcA*7&lm;*)xy8&A)cfkd0~N?2KbeB4nK;5$a(uwh8N3PH5|@P{9e2 znfXV4?;M8Oe>l5P&clk5w|=%qiZ+pHkX@>mu^S%9sF1a18V|u|DlpmFVTUghjklRI z#)G^29$Vs36^ocLlD)1)N9Sl-T~NQv^*vj@l};dQ+MZN#{%Q~Sc9Y2&IxuuH)Bp%= z*{=}0UNn8m=v({^wxbrn`eOC19k<%z8zOV9akA!<0@b2At2VaCF4hxN$fQpx;z-#6 z;_s@^j;tH6J;3@?NRS2Im#be}0Ik#uK{0+vdyD>}P&dW(gk-6XEjs(Ja@l_7(Mx>c zr?ak$;~~JOp*5};@4T}2h=$cbT|Q01t*iFa`)i<-_-) zdb0E#o8bDbtn|{DvNs>aY2Qx32d*JsSpSc@k0N3mbRWw|81yLB{o2sA>xHZELLf&Ux!s?1Ox)(|dEge0eVm|JqO9 z0*uxI5TuY_cAdIzt`P)!KiR(5I40jZx6Y3QUOWgHL&?*Dgx4YAK%N&HSX5z~u zMQ7D$ClRIJS&A@=Nr%93pKuDTedfVN7F`BsNMAHEY`@M&V*ofy@UvNtIh`&Snf0%^ zrq?c@YP=+7O+hrS`5+sw|6GaWxP>G;U>+sy=IMV!AEx=j_xz$!N=Fl99>AR`Wk1e0)L}craYV{Fw7zxl zKr%c>p4(3ZZZ<;5tHnZrfzCaqIyr<{#OYkxL50_~MVsbsb}fF`>`4{fCv_Soaq?0K z@59_HtJ;A@zD&@St5%}!Yk89wh`=Qy4FOTu@L8C^$CCsJgW&2whpvsCQX*rAbLs3# zSV(~U3v-aHi0}io5Q+>`^a5`EBQ=z8ATLID_#WXm_SJ6u+jM?MDhWLyTI3!cnZMstyVVoNr9Fn^8+t+LiC+r6C9E4G5p1&Up+_|WwDT03e20STy^`i&yP6ZM3@N=x!EW+zb7gJmORlSJW)pzX^+C!7Xk5)8Bj*p2 z^9ID2iwOTDsUqtI`57yP|42p)762k*^Q+2Y#g31Q;kdtEMuAD(?c3~dbYKoh1Ph}# zLCkiMyp8X0SP|Z7tcBT5d)g=2(p4HyzVJaf3{TUMVJdAS+H@Naq38N-!JA#Sh@jnw zm{}58fuP%j7)8Z|Fo1Z2*rw;LeF8?Aih2b*I=PV7`hrO8LBi0_l^Z9~8-(pPZ*qJ~ zsh`ab#VeEhl29fLML8R z)rLx2y`3pIJM?^!4e~6a7ZdCjHGgs$6yh*~9s&>$Zitau!x?>WCTM8G!$^pw5P|pw zq)()Q*1K?K1N`4g&jcVAIe$~(h#uLsT+-8@F`?Gaz;A&rkx0B&gBxBBh@3A!`Clzcbv+ED2xqFH)=r?Ln+ z%|nf6lesae)dkMdwmUJRdkpC4K;9~-XnB4NSd58Cy8mFR(WU%gHlY$$?T z7;))p6=V_h>`E3dx1Ffnb{z5vMS$O;YL$U)IPS^9c1Cj~^u zrAKAEUuc*efkyl5D*SzI^lOIWD<5(N@riiOZQm=lYIHXWFG|z($bl1Abz7Oll+5im z?6&s3ebQrH9)Uta7z+Zv7TJ@&{!_N%<(3${=)?_H4T#&1aI~4ishXDrU_{yg`e&Ew zXRj0lkT+yj4OLk>zWsY$jm$_Di^l-9AUdW<89qtOhJ?U2TT@_?7_t2vPtnS zQE#tIA!t}~6G;)f>SG9M_A^19F?t`Knd;*Mi!twC-BJY0Dgmjel+{+7z?X&2j4CTm z#h%{8_(e`ru@`*xmSm~MI^quWK_{PLmjuS$VIsIxA7iPGuM4ti>1(vY?JN5|+Z*bM z)SY|;AI9~X-~eOrWX(4FPm7-kh{dd!Wr2s6Xi*@$_kr6cApgODU`^mIE2H~@Tymy$ zW=#SZi#B(T4?7Bm+N?V)?NSXfhqDB5;o^6TT8{1%OBUD{rOkfM$mPYuu%#>^No)}= zs@z^&RF*0AG07dWi=U(Um3=Y0WOUT0+(9RhK$4N0s*H`Bdj!Z2rd?KgomP%Lt%Opr zDmK;{{;^!-B7K+FI!bJ*!<1kp7RXU(i(`pdd6i7s}|~Xu+@w^Yl%2YG?W?BQtZ8bW-J6r@z;Z+Mu}2ONe-rbmkkUTA~s^ zS0M7H-SnOwFm&GhzW!5@;x$89Dt+JJ58*a#J$0)D3FVVkq%L-enNn$Z(cGexf1PGN)F~4vZiCa@!2##70 zhdloD?e745qj7`Ev7{Ad{G;*8?b z5c{QAOvX2V7}KcRrFSsxt4yph%hD44%V|aEC6u=D@6tuoR80K6JMZbUxx`90qfQ()m?Hu_?v?`yC(D4ICrZycBZ5eralHVU+*L7?)*&CBoDl1Ej>Mk zohVdN#!Q$CAGS<$=8B=uq|&S^aFhryOKtAcTBCS zDSa3K*tOs$CL5XPtNnfc5I7jW(HG^)1(XU4VCPE=syufjA>Yt;z-^%L|VmVvQ6-7BlMBDBy1A0 z3BzkWPFqbAk+54Cp*&Sr*hZ4`S?u2hapZotN9MTNcHFX8)FWH8l^7WL&<4x&^PIT5 z@&oXDQ`C=s|%|oH1)1`mXRAVwd8pIW2_72g0C<$o9-#r7Fpo z2_$cw^%0}@U~eU{=*akpEe{Toi(T%>liluLzQq98V1K4Si`8bkE}r`9qq0=q_D{Pd z<2%{rOt7mA$w4Q*E1rXhKDK9!#6Cb!yUUL_2`8($40R%!>4CtXKmAD#iBOILil!o> zRx*b9d!2iuvT@g!ef--$mv{629uSqg-0%$XnvjZukeL4IlNRw#QNtv}B5Z)+cG_3+ zehr3EwfrjxK^MY;2dxA0wr+27m9`frHgFPJQ7RHuLd$;+`JdML6|b&#gHbq9z7Mu-Jg~62UINZcNK+JgsZn_r8xj6X92uc|B5vW|MCGI-GOS!h z+1T{A6m*G!+^R#Yuk9`Qms`_m{9Z@0wntNDzWO}D%VzL|PpIcBad9V(Phbb@Oo>_K z+AMxAl1tCybpDxsjNcth>TfhMypUw4L>KV}_tobJP4=*3Z*S&dCQByh2KEN1rybI` z@$sFIiF!`VU)tfnqLJ%^RNQLScxNDBG7S7U7qzJ$H}`<$FKW-?^T8=fjWSRh!aKPH zt-sYH`}VGWP~W-96Y!Sv%{hxJ{PgCq&3eCQ>azFYIL3m`{YUksO&4glseScl%8pAB z>k`W@ucD5;<}}{pS2RfSa3{*le$$dq_J;_kW$l_;tw3-5b2N(|ag(PBNm+Lv)~u0yZ;;-_`;Z_p zw->W`hO#@Vb-ted*zfIiV|KnJx@lDfd7!B&#|4C-mg|QF8eChL^}CL~QMW?{)?27r zFcxpn(!gkFVCXr{kbxd+guq1d^_Y!@dE~sM)iJ(S8-t|fPP>S3*=Dlbxsr<#B>*85 zXwsJ_{LHCb?rPrtv(%y$*)Oggs+OuKi1-j~k%uBoM_k?blRE;x2u_9LVf@##C-dD0 z{*UFO4Y2^b(c8wp@;e?TdIsMomt8K|QBT&mrVmUey$1q>b@LEag)Ez8;)%?x-eS~S zOWdtaEb}^o3PjhZW@<8XLy~`i;v{y8Lni(XDgyN0D_`jwDNyCg$28Dt8!CxWaoQ+K za%le5Rm6H_C?MP3yv-lj0Qll<3CiM~6aBTM=tn%uzl9O2AQ9dPvTujp4Ft;GZW#eM z?1qFsp_84MwNtj(%?*U`p!ZejA!Sj~*yD~rFv0rJ9hjvcVSPf(69yur2oYoJda0~G zmT!h96;|jO&A$JQ0dZnCtLtKx`lC64&(6W+{m%_|P*n0!?vHsRMM|c?C8h`h?v5hJ zSi*YiAVD};5;bEXWp@z>Xo`WyXI&=LJRc#>X$SBKH+flxM|)(w6#Pm`-^c7XPZ~H6 zPVoiq%6UddrSC9_~u` zE<9OKkR0>JYWP?bafkusxhe|`q_@Bz2H@mwKoNI>`Qt*ca`eC?BU5Sq2In57lzwi- zVhnJIXqm=kqXa_kk%1&=MKOe{1?D9_D{sP>|f^ zx|s<7-S$7b@UKfJnK00q8F!I;6%Fi&fRF%J9y6XI6Gb=>-rso-a3>yerXU4-@%~p6 z0Yg7P(mUQHvgSqKH~)D;+ko(iZLn* z=&P8<2b}{Ezo!{|HT%~Y|6fe~4-ikkKZqD87Pz?fkB@(&g5HT{WX{{<-lv|I{qha^ zc5S=m*fBqnpB5~(hu@Z65eibBWdsQVQZzcC4Fvp%zt)2k^;YV%UVCA6EXKK;U z6aNtQ|2b0NiU0*p{J-Y)zs!ZW8-zMI(P|aZeHO5}|MCYcaA3BA|Dyts|Dy*OAmPB| z-hZLf|4F)!5^xB#{}*e*f%Jo*U;-Kb-$eZ%D-6in7$Eu2=sRyf9q#{MKO>mYM?{7Z z$gi-!+u{GF5F^;(M>5js*H4b`*#E75AdHL%C?1&ndqw_h`#_HTKocJNLN>ks*Y?9Z zu|DE;umrY9{`>F1bSTj=XW$$E-vG7)1ndSZ9>zO@-#gkk{6mkq&VAm?p^+b;@OEJK zKkbufHB|11=BWxxedSQ(9h^_tdgdt?wrnO7m$3z>Ws?fGHB@k~c{-c4`eaL||5zG$ zWj(7|+!SE!5zijYD!}};y~inJRtTpUVeSH@7y*DZL6)juI>&Xsyq}H@1py;PMEYPy zXFAU5b#8b5y1Y)1@tV=r5qM(b?!4}r&p^h?8qiMoPFm;(zT)*xS>v|97o@1`=3`h5 zUG+Lrb+H+-xNylGMZ}=>h8rnuFzW|7b*xylxkjfI)21&{InoJ7b`gM#b$Tx3yiB@K z>FgQ6SoOvbotPxy4raSsBkq9y3w|~yRpEjwwGe^c9`FABw%86Wpu4O-!9TQvr-W3bxee+*qPkY zwB$_q{Wo+K2blD24wV_dsUlbd#b;g48jcvZoWRYVNSmnxtdmvv)8DS34oDRi^AH&b>f_=vxh;< zp#)4`h#2qi{Co{T>@wx{r^DXGg4bE^&f;v;ABe=Cf9G8Y^@!DD=xm+7_hv%Gui2bV zGo@!c92riyvQcbDfK1dzW4mWa&O&y>3OFQ)FB$UFzy;GpTbpBkI6~ZPYA-p)VSYI6 zh#%@eKW&#VH{eh2^DnDK1m{q!9wd4bmU#_=e7F?~n=xth@+0Kk}fUjWl^Px+V&aeWh* zNswx0?Jo(y`$d=^7Zv=R6w{%bnc*Z~rxD@CyRHC;!h7*Gr^V2#tNmodr+1w*8g}`` z4f-V$$%W9G)g6+n!(fMdV<$3lPvO&#O~bJ8Et;Eg5^c{DQ6yS(zfOFQCbC(J?kV}R zl&-P*2YTi8U%^6MZBZbHdI&QuV_Ca;uU>1~uc;OjzQ?28s{LFFdkxNn>c3S1xAAk; zR;|h>@p_Icu9lkX@I&1kr0ngnOh%3Tw;e5}Uf#zwefG{*Nr~e{2 z*4LF{C=^)yg|_>#%Yx|6sV-4u`^H}+sBLF}(jlH-7* zPk|8@<(5}g|1OosqV!bqhJl7Lr+=|uwH-d%gm<=IW2Z#T+(^(5huE~pbARU|cl*2X zEP3yIOYEoX;Ty|VhUfGEtZ^$j{D*i~=H>mtjb;5Le zvp=rgUD9_w1tNF8A9Q5@a{1SgE7w^=DCou&1LO0dF*N~ow1$`6mm_*$SXBocpfAA? z>FduZ8n_u}!iE!uzK2a$_(!qHRaO6)fln9nmQBNZVoaQTzt$(f3n}^;se->l)e~*x ztAryC8Ne42@_;G3Z9^ozQ3h^aLVqJ-!(8S&6I`uHVl++UpL<3*@(f(?%rduqvTdd1 zmRLWqLq}aAF&KL4_z5o>1M+u;!hzy|Btnt~0axqFr+}MQxsA0oIQKoRsx(8vhv()` zH>Nf{Vnx2xa%KVeX=a(5c7DngFbCbsLvi<<=s)3s4(%W~nKk|a*;PFO7zVz?s8Xkv z$y3~}=py`Lnm#iv=+Sg!?brk`%nkpJdeu4H-W~)BpG)JHb|YBn2p!NfiArCJJG3F^ z!U4aGm@j6_1iYJvM$plE_An8WoP?g8>ISh-gp-Fy{Xs>ax4XQYs(totH7dZg!>CyV zx!7$m_|cFF+v8gxF__SbT__0O)f2tPe*~B^(GTu{*tu+uiV(zfLW>fiNBQQcNZJV} zwVzY}s1&WyUOaU-ZrDA7V$)82TNi-I`-k{S3;;m@83BnQ0WKfg7=a^K@0y`cdVofz zQem04NJUKf_XNs|%{m0fu3%_Kv(~o)za87Q&Y*@gFjRM2u@asayMfDIoFn*`N?P)Z z2YjlPn6MS-H_|iAFP9$c>Pg@YqHtUTS;!M7la#)=)66%H7#TN*UmhGNQ5WJVHHp~$ zQ;@or-)U#Aztb_Y5)rTjbu1D07a10vY|m$VA3U|B8M6%|*HKe~G{>sFCTh@la-{VtuksVqG+e)3aV&hM7kE^*<5!7yj>G8zbTXDU z8WW39+-Y!Pd_fpgyn{?}_c@i%pxxyQK5>JZoZsy;X?n3dUpKHnspzBhiH+Puq^$my z+5Oy)B+g3uqtOJleYf!}?G?j+a=G?QxYF+Vv{#Gj>J#C7#^aEwIlSMq)mK$a!Tm|H zZUrVJ;RG{KbVa7sbs{afP?WgW*_*Kk-Zaf2lwK93#v)xm5!GyU`>o&Hx7sg60f2A% zsC@JEwqN8reqeU2(W*FZynAP5J}2eAm*rKILw>A|avv~Okn&ePQ#gr@NTTReHxStr zx(whOWfFg5>f2Cvse0Jy_46L#AGbYBP4sTYW4~0n495T#-0(Y+A0l(k1rvn1FTErM zc%)yD9>q$l%fLUWGss7tl4YQst8JBB$v#njNJ(^h?( zP&bAJ3R{bCN?@)~P!x4`u-YFn0e|;@$bidnOBvslorzqRNUV^8V7zsMO^x2gPS6;j2K^M+#ln0*>WUNEho32TI zbHJ(4FN}wD)x&p+DF~Uc$QHJi$|y<7h>j!ntW0*U!#NiQ-&M=1`4jep{uuOVD-e*c zN)p1~lyg0V6TEF4UfHiThwE$?rSu^>_K-a0D5^Zh8Bo+^AaXU$>P4Iv3q589l5uz3 z<{!q=f5AVcKVdmM&7L1b-1t=rWXAoKtL10`Xyod)s#qWU@J1jdk<{e~%MQ8U72lox z$W-su@q#j;q|@EVl{rg%J;~%%{28xLbpcZ1ZxNVQ2SI+d@poq9_YUcC2j}DPbr6TC z$S_L6KBiTxw85JAoVQLj?1r;8eqd1H^hryS1}y>{B5{pHDgP+EY}b zB?vQlhYOZ2={4ZiV-8_kabZTc<%<)icnA_&=-sFKq_wk|1>nh=GT?77&q(yrORzUz1DsB}%=W#-n~y6GEVm z2(~SmR44oHel6CL8YC9g>gR88iu9*uobtGH$>Ls7tCnZmyrh5$|1V|8KZHlYnz5Gn z1|kt7?@CZ=uAmc1()ZjesGEq@C1dkTQ-)VjhbG(NB&qSOQ%!~%WNoe{U>H^DM)N@A z+@0&}azMW%uHzLhqr-r~&u%pp=!uTLqH~TZ5D%H%ZES3JUwzGqm&__f_ZQ_g+pcPM z7}{_9`v;v%=J(GQeazu`_eyv(u|R(8#3AWy1S!uMH&znYuSZQjun;&4pe`vyzpe25 z@m%?eHb8xJW7!z>!@<4mvhrrvMhphwi^f9%rN7y|DFdyhZ803nmBS=%XUS?05RE8;hPB~WWpai~|6UE;A2ImC3thzU^D5)A%nc@99lmCEmb}%| zG2pHjN+I5~i&#&6iQZ^Wb(c;ap23e1A~FA(`{lRGMqtSiv=;U4TOjat%)rg~OdU)c z)PBGfpGFo8c$QwE%ABEm@4Jw`+n7}nbEtdK5Pqds&;L@7si&6%WwNEr`f0#0&QHbB z5~p_O_^d8mt8Bn=sHtAFJZ6RI<)PsBbfRJ1+?e#6%C;*;mT*1b`_QHT+FVH&V*J4} zcsL!{m`=}=3(=3rR7X~4V9@#Gf}s4gJuJA-zJhTfgT+CtvVidoie#uPFw->D33DS3 ztJ`f}*=~N5p$VquQv@3{H83$VLh$zSnMen2XsEq|x&-q`t2=VN$X)}agcVP9Qc+7$ zRzHm=SAsLv7c4?~kcJTH|wZGz^TC9slG(QEJiW(SlFN4!Blo~meW;BZ7EUz z9ba$pjhCX_L$mC*j+)mRkh)AbXB50t#?~@ZP(P2Ec8M`|c$ansrr9`?89$NZL79hw zIj0S9t?(I)<~y^P2~E&`ohYp@eVIZYGstL~+f%ZjWK;9e5X@{FB3BEq*5}3;#?}R zLzZOW=4zRF#y(bfQ}IV<33)bk=g(T+bcEF{hDxJh#SBM&(^&HY_dtCPdz!ARQjr=i z_NC+^wNCvGjAgs53VU5`p{orU62MzVQBEqZknBlwtfA41_5J6-tW}z>T-HqVuPutP zQx{;WZ%I={Tr&P1Xc_%4T>Mdpv`goE=LH4QPQzG}ei(77hv%&QKc)f1SXcZUvrif=#t#C_cmcu(U)o8#BC@Keots~(#p-i695gcP4s9O`B-{a)3z zrF~I|2>u~!Nd4L72-rh_T2}%JBLxNfYoTKe_1Xyp#YV|IrHJf(^d6z372v72RKgb3 z%oYu^eJb5c2!DF%7B)%7%E^nZYQ?=2S8qWlmH7)TPfRL}Sb^yu53qjY!J`{G>h67I zR2Q*sfxK`&8%swkm!sFJaF|5Ts4qssG;!^9>?zE7{X0T3E89>YN$UrV2l8c=N~eVp zU%2uqi28plid$t&?O))5`%^1X$XsU6D`e$|@rBw_;NmR>Z|y}C&(VoeiakeTAmO_X z^-|N~V8TQ7QWb_P>>2awnwk8H)*no45Dgh^@YwDf<{8S98^vRuV!mn63`-mBHuahn zjxwl6QcoSX8se(X_ieNyy?(<>feK+ZNk`Et&i@tZcI0V?^_$fupLeL*vI3Jd9%9PP z1cVAzCn99X)1^WcKL; zD1QfRSOpvJ!LrAf;21i-$VApROsp_Z{JjK1JM@kZWk&xLc>@E)BfR@#6TE`R?edt* z7^h=r566^b=v>&G}wy%B;fMB-2%PE;2Sw86T1^Bew=bXGd9?ehhuv|FR zrz;m8)~@hdjqrW-JqVdM3vAEUqZcBN{gdq-wDydkcs|@0SEL)fV!o9#3xDE0`l%_W z&rahV?g~ujtD|gYqbtYe0Uw+zX5zNrFA=b*B< z)NQtVMfk#rRSlWo68xF}i69nXS0H&ERK63YxK~5T7vn7w$uau-d_6crYpb0>QNg`b z#M!SU|CP-Xmv&G*rs9hRt^&~;B2k+1P3^Wz z0PLvh;_*q{dSECxhV^K4+JYF(<&lX?SSlJu>r_1Ma6azQg%`6|oV=TU*h+Y58UXD? z9s?9s^i|{x>{dK6&un9W4r#DAb7Dkz%>`Yf&?*yMx~sS-1Azb-0V1P1{8? zM&G=L&tiuZk=}?ImJq>#S?k?VkDP-~%EQX%1AvI8@p`Ub@2Mj8-roeT#K}<>kWDz z%+$7bhJZ(gCBuj?&fSyTsipUu)Z2>4Wb%1_W;Zp}x2%Jv{4~4F;;$!a+--tGwf2bV zH!UnqGD9fpP{T7?&l{FmW3jslj~`hj*;ejuyiC`+D9DgP*cb+!Ki@>e6~zv_eoA~p z0q)nNhqDV-MI|BoMuLF=Qg-e3)X;?mavt}51yvIdBrJVG*^sMjflQuSk&tRujv%Djpc!-lQ^V1TtZ0-&CnM+)mNp2zkJ=Y_H zS=p(9YY7A8Di`ce7QU8~kwl-oVeB|R=4_d#wn9>72eJZg5jd;UW}{l>3a!)Ya9PV! zfTdrfiqnXNVb$-&&K;kHHHzKr3U#NbV{VOl;v`3Faz5y87O%>lz09+xGh`nIzlHUR z^Qg+RM4gH~zS$$!MK`+f7vrvuVCEurlyJ*UiK;`T>^1wk!n<^>**8a0vU#J#big9A zn|4L+HbKRb^G?x?*gH+-ytgGyH9@y#W^se&`hGEgMW&}(=2_#r~nxKsbZb3r?{EJ z`pk05@^InA_MtOP%mv`yKaZXRTu#HDWT2CPC$ZTI9+6~OYB~VyJ1Buudj0E+mBhI6 z_G4)MnM2Q1Cv65R+zmONJBi5I3r+m0qCR@W@^ET;zL-=eBj2>a$`Hfvaoefu z=kxt8Vg~b#U-5np;ErEb%GJE6fyKow857xlYLA3){<9q+`Dq|llw6MdQ z>5{c%!=pn*<*~`b%VTGqgn}h5X69Vn5VHh)#DnIO`=~V0HjSEJacKnaQt??-KcPPq zVEYhMafRC?TvMnIz50(0gkg?_bntBCVN12cHHE_>J4Y`g8&hOi?JVc<8jrDFmcA|2 zwf0qn1RrOMl@UF=3B_rG%rJ6lYNs({xUxfKV&fMN3ukF>#lGm66k9H?KMqaehMQFNHObf7S9ipmDx>&MWzp z^xtZEz%CgQuF%L##Ne|dKBBEoZICOcm4L=SlzI*cppKsgF<||V;(vVGQzCC@ft=;9 z8S4DQjQi2}zdsukAAW$ijpTp01^)f~@68z*nAE+63uS$%3;ExUsQW<}>s>w0(7Cga zg2RNMp1v2t(eOLH4h$vm*?@_T2Ozt-lwvVZPBrc+A?`{<)S0&@0e zf412a>rb%dwqVHc&a6EOT98R{fZ0!8arkTlS-li&Okv@l(cAx zRX?$d8k}@0>1NOj0)fCh$OWZHB{8>&d^N{X+>7x$!>_~lH*_H5tj|B}@LGW}Dob;XIRy8VHm{I`eC7@n(1JN&nxJ(Yn&|*k1R`e|*ZH~%; zfXe!YMyp%bG6&m|`F<7L@47OD)|zb`j4dL2E>>}FbGJDS%%uFobvZjpIZ~c!)M9U` zJVUkLQ)j@&6wf6FFImykT&U(!HMI(4*_BLd_Sp1J32xX^=HXL3ait&Gixi43Z9`&A zZI`WO>6)N^efOwlhS*u%DLt={)r)JW&y%?~Tl9#Qve$VA=RS{rN!VQbj^ei33!`iC7=ztJ$9PYZ^%xoS@|J`NEaVJU6W9z`a!-#`R&uS*U$i z!JV2iU3Ah4?MvR$J#O*nU(ZWY&|>-C;u~u>I5mt@(awNw77n=713`^l$RU0NJH{-UmQrMu zNUu2-H+AW=GbMFjMC!4UL$NJ7v_kkRPrnayPWd5|7xE;WduN&JSfkZPY25%|&=V&% za;F_&;S%t%+kV96#(ni`Cst^T4W^%>CzVFf7FNg&C&`0nu_aD1W$h5xmw+JY$tXU7 z9A4^(=vm(G$c<(5q0Brh59zzAavxA0926$B40XjeGEzg<^b|E4hC#?{YGq`ym9*s6 zM@&m$l@Q~=sgjWJ5dUjbtcHg$2T_OmiS`Y+xnl)j`MykRNXUoJHTV1)Y8tNj{XkY) zfgv3UjRMA=U$T2EL3~@O;h`*T{6HvAe%zd4%YlcHebgPLFFg|OeMA6IRi({xDYnLD zq#u98d+|-9wW`m4KBkOLs^jpUS<5r0iK~Z+1HJ`Amux%^u@Z9Ec)meHs_Pz~ zFM!!9=R`!VQbUn~pb{%!c}k7Z)Zu2M3PRodh5MG{gTSgE0AW(^VL)LE_lV}XuP=J{RShBMv7vxoK&;o^=|LC zv7pKbJL*Xh#;}hG1 z`H$|hXDkMSN`=f5LPbQmqvQPGlTIrxA|56!J7`VfLjw#i@5-_CKk3FnQois~0=OUoZFt&OhV1Qnz$E^S=?f@gFfqb)8;!-RiL@IBa}lz4;<^0)fNV z2A;4_AXsDvA!IwXI3pH)J%In)PcFfpg_d1++u}jyA5#_%F*of9)er=frEDnC1^1R3 z77l3*2ZH8KoaQw>CH0Ms7B)6VRXSEqsw1%q<_-CDAhsb(vikEc)7o-vnrk*`8f$cp zv#Q_cavUmVY-!D0u)W}KJh8N3ziXDsY?aH}nC4h1!-e!b>9JaPxJ~Y(Jz|V49?tRD zHtt2fyR@+R$7uZ&yR4J%IxE!38!^Uqs+JpDw$eaDWkkEPyyWT&{p z4x*Yw`c%)SU*aUwzAr`3mqkFt+Z(|N#I-}}U)Cb<2F|ggsijL)=q~9e*id+C*kfs# zD07H})IAxt%pGPi_s@ZyDo9|9>z6>7(oLwPd?%1ODf`{85JwvnT6BHDRS7j>yv5-w z`QG+pj(|{@daj~D99zqN%j1?#l>@J;6b1et+wF)9(P7g(vnD!K=*RxLhg9wBxu3f> zy*oZj~*U3-dQg*2<}l4_fqIozpechTn+Zc7Ab!TkWP79tyM{Q$pbjS_%P3Xz9< zshpwKK(N!}`ofc2^#VF;_@?gRx_~_XZdoB(c8qI`eGEOAf6bsG#zcvQTmJs3(p!0g)cPJ#^~y}9yXLP!Z5D8lsX+13e@!KYeVY5LPK zq>1G;^OfDpqzMhazNX~TN3Q9fkKt>Xu_DWP#>~;3(=gVHq%?^aB)<51b@5Gb{8;zf z)MsF8kI>dJDpa|%SHSQ_hHU-qbQ6V!XdFirYj+~Iy*uV>QqCt}bmy&ASfm;+B>z7S zHHm2;jUcof3d6voQ*x4kU6ETRc{cH)(Q5Ppe<_8O4Cd3+bw94V(ED*0u5Q+f?D&t8 z`K8@Cr6$CMs&l5X+W4cG2!^qfq&bFS3AHEN^i$_S-4{ik^?MAycw7$JSYDkq^wxi+5ZFUugUD zz?MXBN04-IqGAIxCKd}7?>XCJs~CmeJF#A74+TK#5!1Y+L}a~Xk;8UEn$BGqEDS}w zeKhQm`P#rzZt*2-}CQ&Jynt9`ifabw1uCQ$_JIm|(t7W%#{>Zis&%#)m^^b12X?e z`^I&8Lrgcm@o8_Jt*gXDT_w_o%g7mdTEg@0_u2Kwq$J4P`!$Q#a%}Z=;0n;Pp>MC* z=@0ngrnad?KThg0Ej-D)K9Nw6Y=s!*66!58bS(Dy{m@BaDWJdw#~`R;IrIRk;~$nz zZ-~l{Z4JJ~_`hYY4?{?vx-GSh7GmDm>;A(;)*s9+4(?0zT^3oS1F3V^%mPwKq}OH%9D-En?jIqbM1*;_8h;GSKgPA(Ttv$%h4O~ZY? z+AzzPHFG#r zJ{j{>hI1*ou};k1ab?fm@9;n{9Ic|Oxx9^F^ws{4XO4V>nRd%R86BOzX^_kb(?UM` zFn6V}021c0{1*~nLVEGO|JUAiMl}&;Z44dhy@V=7FwzmEYXA`t5Tr?O0-*{by-Sl0 z(n1FT1*A$qN{A>;=^g1^>Aja7z}4M7d%oY_kIk8rGf7S+nfu?qE5XRMi+^ZI&CP8-K1<)`7zhK@8%1lw*DjD~bx) z22CzVnYxlFF_MEdhBr%&{wx*?F@4%vw-I1c=&M$@PoDYQo)e;N9kBhOwdOV{bnoFC zl4w}E(dG}wa9ga+J$2#4p0mI@%h){*jV$&zUuxqJq^vF52LY_S5<-3s zPuQ96reuzxL%=3Uv~-DH-AS8lyec!%ttt3HG4M(fx0Kj;fgshJLE-H?uNWZpDK@GYj+X z!i%v|s-u&6vbCsiCL26l6fS;6U29ui5Xyqa-vFGDBrE;s4M;1;(eTsbJ*zIIZVR@W z4vy~{`PE?OKF@WKa7WcAD@f$Oz+hhtQlPe#&z!n;8NM!63Kwzgax2mYy#Q6eJWja% z7mokMkt@m%hTN-4Y2neREtL#Vk{|jp`Pn>y;$=`<_cqxqTsJT7jL!6ov|wA8{=Q|mWmR=#7{*l*K>lo&{S?p%fd*Y3E# zHPSM^+qsY5MPpi(&jkU>y$kewc+o~UQR0lbd^z=!I0PA--t6?Qa5$>swC^FC9N*wz z2-W#!+FNUJR=)uSCVxeaeU@{13cdZ|o*xsD?qc2AR#0Vcbap$7N+|lxHdo>n<&1!) zX&H}NGEA+`tQ`~~*p8+;P009nBjP{A2Dg-$2tpd<%K@m>?mpo|Y>cZeGPCNs^`55rXT!Itg%+RW&{y8%vX^$U4J9#r5|HjE z2~3>k@4Rl!8?CL!8>mPyk9+rs)HV)g19Q-%neWh7m6eg>$*Oycb-P0-)KiG+nC$y| zs=|~xIm7R5GDv*@)d>&1dcc09s%|#;{1QfWz|qJ~sUDkfPiiW*b?tZXN3iy88VM1H zOtsR*L`^rhH4#I&Me=@lK?6aFwnnNPHD8-rf&!Pt7|_y%P%L63vcT zyP>adGBZZOws74}ji(}GEF49ZiSI>H1{d~V6L$IR+sp(n6Di|;xG5~0Ez?OF7UD$M z`hJMM#q??}YcCMo?+zJUh4js?6vwa)b@Z(D1l4ip*dgxR25(UBaupAaNoFj-xCYG! zYdLb^k`l$kBkv;)f(5nedyvYZCfX4g`1-PCJIgEs*N;bcB@x5AmCWZMgI0T=a&$TC zT1z>{Up-6o-hWY*eAL6uPZgG;Zq!Y!vO9rF4H?NtYCkUdZtuzcBtQld@0%I&P>p`g*tFwZ=wn#-hIR`jP}hE)6BQ;sX0uAu}I|Pe`6ZZEDBdv{$&i6D=+@} z%b8vmV)rtpXH(g$d~8m`y+WFIx0km#*~*_`oOm%h*~4>YZHw-Rk{&i-jwm#~!7Ta~ z-$Zj<+bF#9?VV)D6>gvVk$pvqJM1l!A(C>p;T5C#m~$2^v>Vn28HPa-d`L=I@MGcH zJB`MsFThejBXp4bn%y<+o?Qy^-}aor$S&u;>m}UzQq(NRku!bW<2vIv%;KMzEe=Aw z;Y+u5f3oiN9@rRtqG8VkT#XR#QAlA z-&LWA4;+2aRipZHUJ#F=T^9b8>O6{YbBZC+q{)kJw&ndWLQ#ogn8_TXR<)r~$M*hg znJk0X8f3Qajd#0?K`sHQItGxSYEgn3iQp$Y3gxOeJxbTlvOD~~YuvGEi@B3;Hr-AH zq*oFiDdtG*!Vm!NXi*M!5isi@CzwXXJU3n{U?;B1|6qxZ9LJW4D%KM~#D%ysDE3l7 zV|)2sbr|7o$uFt;b=FlT?v#u;Ox6b> z19OJv-~>ct)-r)P%~e~SB=wZ9a?fx_jEsWXgE!rDdiw;xE)!Nw>B0QFts9Rb8$Ogr zpsX6ODX<~KNiqH(FPT)D*@c6r)%3B=HS~AEcQz-cg#m~_dm(S5T~fMpnYji9{5r5R zg2X9g2hL2uwP<4{MoK5D`^Cr$iDF#O1PuP1M5)?|9{+;+Ki+9|a&rkQm3;LEb`;xx3T@XqZ=eSkJU(g{c9Q&Smp3ZZW z*XW%hpVXVQ*-#blG5P2dx47B$v@#}1bC*{D;3V8;71jicCTw#@cvBe#>aV_C4*xM zhNBlTt?@(PvvD+&_wT9qz0t+?M!Q$){fBG4Zr&XBYaq?{O-`vY=}K3*ze3-75Pdg* z-}-CG0Mux|r*8(-jXj$1rFvL6{QWPh@Ygq5z7R3QC?x!*a`~NBKcJivvCJF6Uo5-s zj<;&)Z@Tst`0CoIFKPC__|65NP?&oonCbHZ)YnH=Lsox+M+F(M*l2C=p>8rU6SMHp z98&z6*FAl}p?$xN1?4gJT;AKl2SdLFV6| z?>u_TY+s96>mmUuuZU(ZBuMx`KQxd)by>5-lWD8d(GF8zmW6)1P}JByaF@UGhQ6#e zpZcd|$P&@a%8~e4zAq2qj!PPbwj#}i`xy8S%my{bIg>#7>!U8`#wErxtQ2Ac?ZOB2C{djZxJ=)+}8-rGyUi~z6u}RVVklpOxH-S{9%q@ ze)kESXZpoeA}mGFNpbI}Cqk?!x9543rmg6f;?DvRx1FZ6$H4N#c72c>GZgBzA z@k!Gs{qk)|Xw;)~wCl|sL{>7X+OK;o6TC;##zXm76l_J$!t%>3KQMd=le-{IZ#7T{ z*+9=1rG)oJbO|ir&)f)yqSN_`jtP_6^0_D45Bfj`9mQg2VM7{VHU#HlrovR?YSOd? z>paIr?OntM;w<3X%D_ecXCQg7fxq*H+rF@sIFY6aEf4M+}MDKdx0Ev=P>z2hP z2XSJ2D?@VgaBcY*ja9XIE^)?9etuyVF{kD*zgW81J!LFFV)7$I+)Cg}+CAxA-6X!54RA!{+vBdm5x$SPjs_<4(oI-PWH{&=mHjiHVpMS&m|J1$|is0 zI{TH9MxCEw@wP?r*uL;t_?X%d-}}PUu}VIw6#lqT$K}-|UFfAs8U^D3LLzLPc`)j# zdXHoyrnR9&M}=)*Orj=6w$H>6kBUTaA=rL?LHex?FA0ALcqBr>=2w^n5+hws^CDCy zDg2)($A}Z7ckKsO?Wu@lLfM;sB`9b)7&Sf`mBqlQFGcW7@lqBQPdtU^tIgE@Hg~^iWyB|SR&bHafiI(Mn zyFI20jsbYZOH z`Dzf`m?}5fzt}YvdB5%! z2y8V_G6AHwtY>QUxFIE-Gp-5?~DW1H(eE z=-RcLpe$p-L@E|GHrexA?^jVzPK@2v#)@N~eiR&+*PT!9 zcadKRVr6tVWrcpy#f1#tgfUj3*xYVGGCnum+qLwe)$ic2=%q~mn)}%bnE17E5Q!JM z9>~^!6;Mt!)%z=d^IItrES-Q2=}#yAgGIs-dE|pexYr4vRfcf^}0drSk>rqgyVQt4P`&vtk$a*H|Sq;Bcq6Swp^iwx*C`)9iDpN z03s)Hyk9=*IbN=t_S|R)bXWNVCj9hsQapv_Da(D7)QsN^?ch`0GqlrbFnJoRH#b3u zzGdQ=pVzaDJeZ5Fr~g+|YY0_mFs*TgcyL>)M5%E6FRSH@vT0=h%@gMcSKY}O;*xF8 z)oaBkE8v1idgzoYhxoW{>Fyx&`77A1f5sMIbg40_^P=HEYP{%`vE#nNY6#$B?3Ub; zdhSqov~G9Hd+O}2<6cJ7Id^?_%cqkMuKX%9dr16!56PAFCXn*c*Uy7sU^>#KXG8i?>D{-dXaLtIxMJ$SRu`elb~fo8|E)QmrKi+of_&<|i61 zpZH9Pie=FWYI=sfGGO`L1_zu|Q|wwXn)a&1*Q2Z1Y-6BnbPTO&WzH7ftPc{+s|lky zR`xr;da*8gyM-fFAH!G-qGF`c;^N|tCJ$6O%+S%e=#T;O2V4`evnp2Z2L|zMqDk@SeL@V)uJCbkGkRhS+_%Wg0p0?*!nFmoDtsLIin$JJx z&ol!vGSByvn6L(42*_3Ho}myEjT)frDuZB)Sa?uMm~Is`43mq34dY1xX;(@eBT7)P zZkxy3R0a9eYNN-alurO%Jx4<1v60Q~gWP_yBbjqN@97Mr;^@{k&s^7&jN{lH>8C3r<= zV&7zI&zG8?zt8!wtec#@sZ#n`C%c&fg~<#)FGQDyzi%M4&Xy?w2JTudIQ$_XOwjdL z4P(RrGmjQ4QBQMxvqcQo}i&UrgnEMVjDXK^w`!sdq?LWUZ$bTVrbX+gD{d17N zJ4U2{R_7hw-#7jYc`4zAhZ2e=KVtpkwSRYL(cYo|?@PcC{Lc`-o#OwuA^gr6jlY*- UbI^aVLjxWUWtC-$?;H951Ey%n-T(jq literal 0 HcmV?d00001 diff --git a/doc/intro/index.rst b/doc/intro/index.rst index e4c46d7f92..7ba6c070f8 100644 --- a/doc/intro/index.rst +++ b/doc/intro/index.rst @@ -3,13 +3,245 @@ Introduction ============ -.. toctree:: - :maxdepth: 2 +.. contents:: - overview - quickstart - install - upgrade - changes - reporting-problems +Overview +-------- +Bro is a passive, open-source network traffic analyzer. It is +primarily a security monitor that inspects all traffic on a link in +depth for signs of suspicious activity. More generally, however, +Bro supports a wide range of traffic analysis tasks even outside of +the security domain, including performance measurements and helping +with trouble-shooting. + +The most immediate benefit that a site gains from deploying Bro is an +extensive set of *log files* that record a network's activity in +high-level terms. These logs include not only a comprehensive record +of every connection seen on the wire, but also application-layer +transcripts such as, e.g., all HTTP sessions with their requested +URIs, key headers, MIME types, and server responses; DNS requests with +replies; SSL certificates; key content of SMTP sessions; and much +more. By default, Bro writes all this information into well-structured +tab-separated log files suitable for post-processing with external +software. Users can however also chose from a set of alternative +output formats and backends to interface directly with, e.g., external +databases. + +In addition to the logs, Bro comes with built-in functionality for a +range of analysis and detection tasks, including extracting files from +HTTP sessions, detecting malware by interfacing to external +registries, reporting vulnerable versions of software seen on the +network, identifying popular web applications, detecting SSH +brute-forcing, validating SSL certificate chains, and much more. + +However, the key to understanding Bro lies in realizing that even +though the system comes with such powerful functionality out of the +box, fundamentally it represents a *platform* for traffic analyses +that's fully customizable and extensible: Bro provides users with a +domain-specific, Turing-complete *scripting language* for expressing +arbitrary analysis tasks. Conceptually, you can think of Bro as a +"domain-specific Python" (or Perl): just like Python, the system comes +with a large set of pre-built functionality (the "standard library"), +yet you are not limited to what the system ships with but can put Bro +to use in novel ways by writing your own code. Indeed, all of Bro's +default analyses, including all the logging, is the result of such +scripts; there's no specific analysis hard-coded into the core of +system. + +Bro runs on commodity hardware and hence provides a low-cost +alternative to expensive proprietary solutions. Despite the price tag, +however, Bro actually goes far beyond the capabilities of other +network monitoring tools, which typically remain limited to a small +set of hard-coded analysis tasks. We emphasize in particular that Bro +is *not* a classic signature-based intrusion detection system (IDS). +While it supports such standard functionality as well, Bro's scripting +language indeed facilitates a much broader spectrum of very different +approaches to finding malicious activity, including semantic misuse +detection, anomaly detection, and behavioral analysis. + +A large variety of sites deploy Bro operationally for protecting their +cyberinfrastructure, including many universities, research labs, +supercomputing centers, open-science communities, and major +corporations. Bro specifically targets high-speed, high-volume network +monitoring, and an increasing number of sites are now using the system +to monitor their 10GE networks, with some already moving on to 100GE +links. Bro accommodates such high-performance settings by supporting +scalable load-balancing: large sites typically run "Bro Clusters" in +which a high-speed frontend load-balancer distributes the traffic +across an appropriate number of backend PCs, all running dedicated Bro +instances on their individual traffic slices. A central manager system +coordinates the process, synchronizing state across the backends and +providing the operators with a central management interface for +configuration and access to aggregated logs. Bro's integrated +management framework, BroControl, supports such cluster setups +out-of-the-box. + +Features +-------- + +Bro supports a wide range of analyses through its scripting language. +Yet even without further customization it comes with a powerful set of +features. + +- Deployment + + * Runs on commodity hardware on standard UNIX-style systems + (including Linux, FreeBSD, and MacOS). + + * Fully passive traffic analysis off a network tap or monitoring + port. + + * Standard libpcap interface for capturing packets. + + * Real-time and offline analysis. + + * Cluster-support for large-scale deployments. + + * Unified management framework for operating both standalone and + cluster setups. + + * Open-source under a BSD license. + +- Analysis + + * Comprehensive logging of activity for offline analysis and + forensics. + + * Port-independent analysis of application-layer protocols. + + * Support for many application-layer protocols (including DNS, + FTP, HTTP, IRC, SMTP, SSH, SSL). + + * Analysis of file content exchanged over application-layer + protocols, including MD5/SHA1 computation for fingerprinting. + + * Comprehensive IPv6 support. + + * Tunnel detection and analysis (including Ayiya, Teredo, GTPv1). + Bro decapsulates the tunnels and then proceeds to analyze their + content as if no tunnel was in place. + + * Extensive sanity checks during protocol analysis. + + * Support for IDS-style pattern matching. + +- Scripting Language + + * Turing-complete language for expression arbitrary analysis + tasks. + + * Event-based programming model. + + * Domain-specific data types such as IP addresses (transparently + handling both IPv4 and IPv6), port numbers, and timers. + + * Extensive support for tracking and managing network state over + time. + +- Interfacing + + * Default output to well-structured ASCII logs. + + * Alternative backends for ElasticSearch and DataSeries. Further + database interfaces in preparation. + + * Real-time integration of external input into analyses. Live + database input in preparation. + + * External C library for exchanging Bro events with external + programs. Comes with Perl, Python, and Ruby bindings. + + * Ability to trigger arbitrary external processes from within + the scripting language. + + +History +------- + +.. figure:: history.png + :width: 600 + :align: center + :alt: Bro History Timeline + :target: history.png + + Timeline of Bro's History (click to enlarge). + +Bro's history goes back much further than many people realize. `Vern +Paxson `_ designed and implemented the +initial version almost two decades ago. +Vern began work on the code in 1995 as a researcher at the `Lawrence +Berkeley National Laboratory (LBNL) `_. Berkeley +Lab began operational deployment in 1996, and the USENIX Security +Symposium published the original Bro paper in 1998 (later refined in a +subsequent `journal publication `_). +In 2003, the +`National Science Foundation (NSF) `_ began +supporting research and advanced development on Bro at the +`International Computer Science Institute (ICSI) +`_, where Vern now leads the `Networking +and Security group `_. Over the years, a growing +team of ICSI researchers and students kept adding novel functionality +to Bro, while LBNL continued its support with funding from the +`Department of Energy (DOE) `_. + +Much of Bro's capabilities originate in academic research projects, +with results often published at top-tier conferences. However, the key +to Bro's success was its ability to bridge the traditional gap between +academia and operations from early on, which provided the research +with crucial grounding to ensure that developed approaches stand up to +the challenges of the real world. Yet, with Bro's operational user +community growing over time, the research-centric development model +eventually became a bottleneck to the system's evolution: research +grants do not tend to support the more mundane parts of software +development and maintenance, even though those prove crucial for the +end-user experience. While Bro's capabilities always went beyond those +of traditional systems, a successful deployment used to require +significant technical expertise, typically with a large upfront +investment in tackling Bro's steep learning curve. In 2010, NSF set +out to address this gap by awarding ICSI a grant dedicated solely to +Bro development out of its SDCI program. +With that support in place, the `National Center for +Supercomputing Applications (NCSA) `_ +joined the team as a core partner, and the Bro Project began to +completely overhaul many of the user-visible parts of the system for +the 2.0 release. Since that version came out, Bro has experienced an +tremendous growth in new deployments across a diverse range of +settings, and the Bro team is now working to build on this success by +further advancing the system's capabilities to address the challenges +of future networks. + +Architecture +------------ + +.. figure:: architecture.png + :width: 400 + :align: center + :alt: Bro Architecture + :target: {{docroot}}/images/architecture.png + + Bro's internal architecture. + +Architecturally, Bro is layered into two major components. Its *event +engine* (or *core*) reduces the incoming packet stream into a series +of higher-level *events*. These events reflect network activity in +policy-neutral terms, i.e., they describe *what* has been seen, but +not *why*, or whether it is significant. For example, every HTTP +request on the wire turns into a corresponding ``http_request`` event +that carries with it the involved IP addresses and ports, the URI +being requested, and the HTTP version in use. The event however does +not convey any further *interpretation*, e.g., of whether that URI +corresponds to a known malware site. + +Such semantics are instead derived by Bro's second main component, the +*script interpreter*, which executes a set of *event handlers* written +in Bro's custom scripting language. These scripts can express a site's +security policy, i.e., what actions to take when the monitor detects +different types of activity. More generally they can derive any +desired properties and statistics from the input traffic. Bro's +language comes with extensive domain-specific types and support +functionality; and, crucially, allows scripts to maintain state +over time, enabling them to track and correlate the evolution of what +they observe across connection and host boundaries. Bro scripts can +generate real-time alerts and also execute arbitrary external programs +on demand, e.g., to trigger an active response to an attack. diff --git a/doc/intro/install.rst b/doc/intro/install.rst deleted file mode 120000 index 37675c714b..0000000000 --- a/doc/intro/install.rst +++ /dev/null @@ -1 +0,0 @@ -../../INSTALL \ No newline at end of file diff --git a/doc/intro/overview.rst b/doc/intro/overview.rst deleted file mode 100644 index acb9c970d5..0000000000 --- a/doc/intro/overview.rst +++ /dev/null @@ -1,5 +0,0 @@ - -================== -Overview (Missing) -================== - diff --git a/doc/intro/upgrade.rst b/doc/intro/upgrade.rst deleted file mode 100644 index 539757537d..0000000000 --- a/doc/intro/upgrade.rst +++ /dev/null @@ -1,308 +0,0 @@ - -========================================== -Upgrading From the Previous Version of Bro -========================================== - -.. rst-class:: opening - - This guide details specific differences between Bro versions - that may be important for users to know as they work on updating - their Bro deployment/configuration to the later version. - -.. contents:: - - -Upgrading From Bro 2.0 to 2.1 -============================= - -In Bro 2.1, IPv6 is enabled by default. Therefore, when building Bro from -source, the "--enable-brov6" configure option has been removed because it -is no longer relevant. - -Other configure changes include renaming the "--enable-perftools" option -to "--enable-perftools-debug" to indicate that the option is only relevant -for debugging the heap. One other change involves what happens when -tcmalloc (part of Google perftools) is found at configure time. On Linux, -it will automatically be linked with Bro, but on other platforms you -need to use the "--enable-perftools" option to enable linking to tcmalloc. - -There are a couple of changes to the Bro scripting language to better -support IPv6. First, IPv6 literals appearing in a Bro script must now be -enclosed in square brackets (for example, ``[fe80::db15]``). For subnet -literals, the slash "/" appears after the closing square bracket (for -example, ``[fe80:1234::]/32``). Second, when an IP address variable or IP -address literal is enclosed in pipes (for example, ``|[fe80::db15]|``) the -result is now the size of the address in bits (32 for IPv4 and 128 for IPv6). - -In the Bro scripting language, "match" and "using" are no longer reserved -keywords. - -Some built-in functions have been removed: "addr_to_count" (use -"addr_to_counts" instead), "bro_has_ipv6" (this is no longer relevant -because Bro now always supports IPv6), "active_connection" (use -"connection_exists" instead), and "connection_record" (use "lookup_connection" -instead). - -The "NFS3::mode2string" built-in function has been renamed to "file_mode". - -Some built-in functions have been changed: "exit" (now takes the exit code -as a parameter), "to_port" (now takes a string as parameter instead -of a count and transport protocol, but "count_to_port" is still available), -"connect" (now takes an additional string parameter specifying the zone of -a non-global IPv6 address), and "listen" (now takes three additional -parameters to enable listening on IPv6 addresses). - -Some Bro script variables have been renamed: "LogAscii::header_prefix" -has been renamed to "LogAscii::meta_prefix", "LogAscii::include_header" -has been renamed to "LogAscii::include_meta". - -Some Bro script variables have been removed: "tunnel_port", -"parse_udp_tunnels", "use_connection_compressor", "cc_handle_resets", -"cc_handle_only_syns", and "cc_instantiate_on_data". - -A couple events have changed: the "icmp_redirect" event now includes -the target and destination addresses and any Neighbor Discovery options -in the message, and the last parameter of the "dns_AAAA_reply" event has -been removed because it was unused. - -The format of the ASCII log files has changed very slightly. Two new lines -are automatically added, one to record the time when the log was opened, -and the other to record the time when the log was closed. - -In BroControl, the option (in broctl.cfg) "CFlowAddr" was renamed -to "CFlowAddress". - - -Upgrading From Bro 1.5 to 2.0 -============================= - -As the version number jump suggests, Bro 2.0 is a major upgrade and -lots of things have changed. Most importantly, we have rewritten -almost all of Bro's default scripts from scratch, using quite -different structure now and focusing more on operational deployment. -The result is a system that works much better "out of the box", even -without much initial site-specific configuration. The down-side is -that 1.x configurations will need to be adapted to work with the new -version. The two rules of thumb are: - - (1) If you have written your own Bro scripts - that do not depend on any of the standard scripts formerly - found in ``policy/``, they will most likely just keep working - (although you might want to adapt them to use some of the new - features, like the new logging framework; see below). - - (2) If you have custom code that depends on specifics of 1.x - default scripts (including most configuration tuning), that is - unlikely to work with 2.x. We recommend to start by using just - the new scripts first, and then port over any customizations - incrementally as necessary (they may be much easier to do now, - or even unnecessary). Send mail to the Bro user mailing list - if you need help. - -Below we summarize changes from 1.x to 2.x in more detail. This list -isn't complete, see the :download:`CHANGES ` file in the -distribution for the full story. - -Default Scripts -=============== - -Organization ------------- - -In versions before 2.0, Bro scripts were all maintained in a flat -directory called ``policy/`` in the source tree. This directory is now -renamed to ``scripts/`` and contains major subdirectories ``base/``, -``policy/``, and ``site/``, each of which may also be subdivided -further. - -The contents of the new ``scripts/`` directory, like the old/flat -``policy/`` still gets installed under the ``share/bro`` -subdirectory of the installation prefix path just like previous -versions. For example, if Bro was compiled like ``./configure ---prefix=/usr/local/bro && make && make install``, then the script -hierarchy can be found in ``/usr/local/bro/share/bro``. - -The main -subdirectories of that hierarchy are as follows: - -- ``base/`` contains all scripts that are loaded by Bro by default - (unless the ``-b`` command line option is used to run Bro in a - minimal configuration). Note that is a major conceptual change: - rather than not loading anything by default, Bro now uses an - extensive set of default scripts out of the box. - - The scripts under this directory generally either accumulate/log - useful state/protocol information for monitored traffic, configure a - default/recommended mode of operation, or provide extra Bro - scripting-layer functionality that has no significant performance cost. - -- ``policy/`` contains all scripts that a user will need to explicitly - tell Bro to load. These are scripts that implement - functionality/analysis that not all users may want to use and may have - more significant performance costs. For a new installation, you - should go through these and see what appears useful to load. - -- ``site/`` remains a directory that can be used to store locally - developed scripts. It now comes with some preinstalled example - scripts that contain recommended default configurations going beyond - the ``base/`` setup. E.g. ``local.bro`` loads extra scripts from - ``policy/`` and does extra tuning. These files can be customized in - place without being overwritten by upgrades/reinstalls, unlike - scripts in other directories. - -With version 2.0, the default ``BROPATH`` is set to automatically -search for scripts in ``policy/``, ``site/`` and their parent -directory, but **not** ``base/``. Generally, everything under -``base/`` is loaded automatically, but for users of the ``-b`` option, -it's important to know that loading a script in that directory -requires the extra ``base/`` path qualification. For example, the -following two scripts: - -* ``$PREFIX/share/bro/base/protocols/ssl/main.bro`` -* ``$PREFIX/share/bro/policy/protocols/ssl/validate-certs.bro`` - -are referenced from another Bro script like: - -.. code:: bro - - @load base/protocols/ssl/main - @load protocols/ssl/validate-certs - -Notice how ``policy/`` can be omitted as a convenience in the second -case. ``@load`` can now also use relative path, e.g., ``@load -../main``. - - -Logging Framework ------------------ - -- The logs generated by scripts that ship with Bro are entirely redone - to use a standardized, machine parsable format via the new logging - framework. Generally, the log content has been restructured towards - making it more directly useful to operations. Also, several - analyzers have been significantly extended and thus now log more - information. Take a look at ``ssl.log``. - - * A particular format change that may be useful to note is that the - ``conn.log`` ``service`` field is derived from DPD instead of - well-known ports (while that was already possible in 1.5, it was - not the default). - - * Also, ``conn.log`` now reports raw number of packets/bytes per - endpoint. - -- The new logging framework makes it possible to extend, customize, - and filter logs very easily. See the :doc:`logging framework ` - for more information on usage. - -- A common pattern found in the new scripts is to store logging stream - records for protocols inside the ``connection`` records so that - state can be collected until enough is seen to log a coherent unit - of information regarding the activity of that connection. This - state is now frequently seen/accessible in event handlers, for - example, like ``c$`` where ```` is replaced by - the name of the protocol. This field is added to the ``connection`` - record by ``redef``'ing it in a - ``base/protocols//main.bro`` script. - -- The logging code has been rewritten internally, with script-level - interface and output backend now clearly separated. While ASCII - logging is still the default, we will add further output types in - the future (binary format, direct database logging). - - -Notice Framework ----------------- - -The way users interact with "notices" has changed significantly in -order to make it easier to define a site policy and more extensible -for adding customized actions. See the :doc:`notice framework `. - - -New Default Settings --------------------- - -- Dynamic Protocol Detection (DPD) is now enabled/loaded by default. - -- The default packet filter now examines all packets instead of - dynamically building a filter based on which protocol analysis scripts - are loaded. See ``PacketFilter::all_packets`` for how to revert to old - behavior. - -API Changes ------------ - -- The ``@prefixes`` directive works differently now. - Any added prefixes are now searched for and loaded *after* all input - files have been parsed. After all input files are parsed, Bro - searches ``BROPATH`` for prefixed, flattened versions of all of the - parsed input files. For example, if ``lcl`` is in ``@prefixes``, and - ``site.bro`` is loaded, then a file named ``lcl.site.bro`` that's in - ``BROPATH`` would end up being automatically loaded as well. Packages - work similarly, e.g. loading ``protocols/http`` means a file named - ``lcl.protocols.http.bro`` in ``BROPATH`` gets loaded automatically. - -- The ``make_addr`` BIF now returns a ``subnet`` versus an ``addr`` - - -Variable Naming ---------------- - -- ``Module`` is more widely used for namespacing. E.g. the new - ``site.bro`` exports the ``local_nets`` identifier (among other - things) into the ``Site`` module. - -- Identifiers may have been renamed to conform to new `scripting - conventions - `_ - - -BroControl -========== - -BroControl looks pretty much similar to the version coming with Bro 1.x, -but has been cleaned up and streamlined significantly internally. - -BroControl has a new ``process`` command to process a trace on disk -offline using a similar configuration to what BroControl installs for -live analysis. - -BroControl now has an extensive plugin interface for adding new -commands and options. Note that this is still considered experimental. - -We have removed the ``analysis`` command, and BroControl currently -does not send daily alarm summaries anymore (this may be restored -later). - -Removed Functionality -===================== - -We have remove a bunch of functionality that was rarely used and/or -had not been maintained for a while already: - - - The ``net`` script data type. - - The ``alarm`` statement; use the notice framework instead. - - Trace rewriting. - - DFA state expiration in regexp engine. - - Active mapping. - - Native DAG support (may come back eventually) - - ClamAV support. - - The connection compressor is now disabled by default, and will - be removed in the future. - -Development Infrastructure -========================== - -Bro development has moved from using SVN to Git for revision control. -Users that want to use the latest Bro development snapshot by checking it out -from the source repositories should see the `development process -`_. Note that all the various -sub-components now reside in their own repositories. However, the -top-level Bro repository includes them as git submodules so it's easy -to check them all out simultaneously. - -Bro now uses `CMake `_ for its build system so -that is a new required dependency when building from source. - -Bro now comes with a growing suite of regression tests in -``testing/``. diff --git a/doc/intro/quickstart.rst b/doc/quickstart/index.rst similarity index 87% rename from doc/intro/quickstart.rst rename to doc/quickstart/index.rst index 9f64e36d89..a626d3b058 100644 --- a/doc/intro/quickstart.rst +++ b/doc/quickstart/index.rst @@ -1,14 +1,10 @@ +.. _quickstart: + ================= Quick Start Guide ================= -.. rst-class:: opening - - The short story for getting Bro up and running in a simple configuration - for analysis of either live traffic from a network interface or a packet - capture trace file. - .. contents:: Installation @@ -16,14 +12,13 @@ Installation Bro works on most modern, Unix-based systems and requires no custom hardware. It can be downloaded in either pre-built binary package or -source code forms. See :doc:`Installing Bro ` for instructions -on how to install Bro. +source code forms. See :ref:`installing-bro` for instructions on how to +install Bro. Below, ``$PREFIX`` is used to reference the Bro +installation root directory, which by default is ``/usr/local/`` if +you install from source. -.. note:: Below, ``$PREFIX`` is used to reference the Bro installation - root directory. - -Using BroControl -================ +Managing Bro with BroControl +============================ BroControl is an interactive shell for easily operating/managing Bro installations on a single system or even across multiple systems in a @@ -68,9 +63,10 @@ policy and output the results in ``$PREFIX/logs``. .. note:: The user starting BroControl needs permission to capture network traffic. If you are not root, you may need to grant further - privileges to the account you're using; see the :doc:`FAQ `. - Also, if it looks like Bro is not seeing any traffic, check out - the FAQ entry on checksum offloading. + privileges to the account you're using; see the `FAQ + `_. Also, if it looks + like Bro is not seeing any traffic, check out the FAQ entry on + checksum offloading. You can leave it running for now, but to stop this Bro instance you would do: @@ -115,20 +111,18 @@ columns (shortened for brevity) show a request to the root of Bro website:: Some logs are worth explicit mention: - ``weird.log`` - Contains unusual/exceptional activity that can indicate - malformed connections, traffic that doesn't conform to a particular - protocol, malfunctioning/misconfigured hardware, or even an attacker - attempting to avoid/confuse a sensor. Without context, it's hard to - judge whether this category of activity is interesting and so that is - left up to the user to configure. + ``conn.log`` + Contains an entry for every connection seen on the wire, with + basic properties such as time and duration, originator and + responder IP addresses, services and ports, payload size, and + much more. This log provides a comprehensive record of the + network's activity. ``notice.log`` Identifies specific activity that Bro recognizes as potentially interesting, odd, or bad. In Bro-speak, such activity is called a "notice". - By default, ``BroControl`` regularly takes all the logs from ``$PREFIX/logs/current`` and archives/compresses them to a directory named by date, e.g. ``$PREFIX/logs/2011-10-06``. The frequency at @@ -302,21 +296,26 @@ tweak the most basic options. Here's some suggestions on what to explore next: * We only looked at how to change options declared in the notice framework, there's many more options to look at in other script packages. +* Continue reading with :ref:`using-bro` chapter which goes into more + depth on working with Bro; then look at :ref:`writing-scripts` for + learning how to start writing your own scripts. * Look at the scripts in ``$PREFIX/share/bro/policy`` for further ones - you may want to load. + you may want to load; you can browse their documentation at the + :ref:`overview of script packages `. * Reading the code of scripts that ship with Bro is also a great way to gain - understanding of the language and how you can start writing your own custom - analysis. -* Review the :doc:`FAQ `. + further understanding of the language and how scripts tend to be + structured. +* Review the `FAQ `_. * Continue reading below for another mini-tutorial on using Bro as a standalone command-line utility. -Bro, the Command-Line Utility +Bro as a Command-Line Utility ============================= -If you prefer not to use BroControl (e.g. don't need its automation and -management features), here's how to directly control Bro for your analysis -activities. +If you prefer not to use BroControl (e.g. don't need its automation +and management features), here's how to directly control Bro for your +analysis activities from the command line for both live traffic and +offline working from traces. Monitoring Live Traffic ----------------------- @@ -420,3 +419,19 @@ are "load this script if it hasn't already been loaded". to be searched for scripts. See the default search path by doing ``bro --help``. +Running Bro Without Installing +------------------------------ + +For developers that wish to run Bro directly from the ``build/`` +directory (i.e., without performing ``make install``), they will have +to first adjust ``BROPATH`` and ``BROMAGIC`` to look for scripts and +additional files inside the build directory. Sourcing either +``build/bro-path-dev.sh`` or ``build/bro-path-dev.csh`` as appropriate +for the current shell accomplishes this and also augments your +``PATH`` so you can use the Bro binary directly:: + + ./configure + make + source build/bro-path-dev.sh + bro + diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 02cd97e3b1..a91a716189 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -1,4 +1,6 @@ +.. _writing-scripts: + =================== Writing Bro Scripts =================== diff --git a/doc/scripts/packages.rst b/doc/scripts/packages.rst index d968e2ba41..9f01a91e91 100644 --- a/doc/scripts/packages.rst +++ b/doc/scripts/packages.rst @@ -1,5 +1,7 @@ .. This is a stub doc to which broxygen appends during the build process +.. _script-packages: + Bro Script Packages =================== diff --git a/doc/using/index.rst b/doc/using/index.rst index fc979dd30a..092d5e1b92 100644 --- a/doc/using/index.rst +++ b/doc/using/index.rst @@ -1,4 +1,6 @@ +.. _using-bro: + ========= Using Bro ========= From f3950da009ef0ec06b3f55f5dc2223e3f80a9415 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 20 Aug 2013 09:54:31 -0500 Subject: [PATCH 238/881] Unlock mutex in raw input reader error cases - BIT-1060 --- src/input/readers/Raw.cc | 32 ++++++++++++++++++++++---------- src/input/readers/Raw.h | 2 ++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/input/readers/Raw.cc b/src/input/readers/Raw.cc index fecf9a7ddc..e7a5af3e79 100644 --- a/src/input/readers/Raw.cc +++ b/src/input/readers/Raw.cc @@ -90,6 +90,24 @@ void Raw::ClosePipeEnd(int i) pipes[i] = -1; } +bool Raw::LockForkMutex() + { + int res = pthread_mutex_lock(&fork_mutex); + if ( res == 0 ) + return true; + Error(Fmt("cannot lock fork mutex: %d", res)); + return false; + } + +bool Raw::UnlockForkMutex() + { + int res = pthread_mutex_unlock(&fork_mutex); + if ( res == 0 ) + return true; + Error(Fmt("cannot unlock fork mutex: %d", res)); + return false; + } + bool Raw::Execute() { // TODO: AFAICT, pipe/fork/exec should be thread-safe, but actually having @@ -99,15 +117,12 @@ bool Raw::Execute() // individually or sequentially, that issue never crops up... ("never" // meaning I haven't seen in it in hundreds of tests using 50+ threads // where before I'd see the issue w/ just 2 threads ~33% of the time). - int lock_rval = pthread_mutex_lock(&fork_mutex); - if ( lock_rval != 0 ) - { - Error(Fmt("cannot lock fork mutex: %d", lock_rval)); + if ( ! LockForkMutex() ) return false; - } if ( pipe(pipes) != 0 || pipe(pipes+2) || pipe(pipes+4) ) { + UnlockForkMutex(); Error(Fmt("Could not open pipe: %d", errno)); return false; } @@ -115,6 +130,7 @@ bool Raw::Execute() childpid = fork(); if ( childpid < 0 ) { + UnlockForkMutex(); Error(Fmt("Could not create child process: %d", errno)); return false; } @@ -144,12 +160,8 @@ bool Raw::Execute() else { // we are the parent - lock_rval = pthread_mutex_unlock(&fork_mutex); - if ( lock_rval != 0 ) - { - Error(Fmt("cannot unlock fork mutex: %d", lock_rval)); + if ( ! UnlockForkMutex() ) return false; - } ClosePipeEnd(stdout_out); if ( Info().mode == MODE_STREAM ) diff --git a/src/input/readers/Raw.h b/src/input/readers/Raw.h index 8c05b54576..bd5c11acfd 100644 --- a/src/input/readers/Raw.h +++ b/src/input/readers/Raw.h @@ -32,6 +32,8 @@ protected: private: void ClosePipeEnd(int i); + bool LockForkMutex(); + bool UnlockForkMutex(); bool OpenInput(); bool CloseInput(); From b42249c3d6d9fc4c639ce6c8f1a6cb6c1efc1132 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 20 Aug 2013 13:59:04 -0700 Subject: [PATCH 239/881] Switching to relative submodule paths --- .gitmodules | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitmodules b/.gitmodules index 87826d2ef6..afac9bfc6b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,24 +1,24 @@ [submodule "aux/bro-aux"] path = aux/bro-aux - url = git://git.bro.org/bro-aux + url = ../bro-aux [submodule "aux/binpac"] path = aux/binpac - url = git://git.bro.org/binpac + url = ../binpac [submodule "aux/broccoli"] path = aux/broccoli - url = git://git.bro.org/broccoli + url = ../broccoli [submodule "aux/broctl"] path = aux/broctl - url = git://git.bro.org/broctl + url = ../broctl [submodule "aux/btest"] path = aux/btest - url = git://git.bro.org/btest + url = ../btest [submodule "cmake"] path = cmake - url = git://git.bro.org/cmake + url = ../cmake [submodule "magic"] path = magic - url = git://git.bro.org/bromagic + url = ../bromagic [submodule "src/3rdparty"] path = src/3rdparty - url = git://git.bro.org/bro-3rdparty + url = ../bro-3rdparty From bc819750b950acfa2940b1a6c8b58381818698e3 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 20 Aug 2013 13:59:28 -0700 Subject: [PATCH 240/881] Updating submodule(s). [nomail] --- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aux/binpac b/aux/binpac index 00674ed07d..ff22fa7299 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 00674ed07d702252b00675b5060647d9e811cdd7 +Subproject commit ff22fa7299d460d9c4b7f6c7269e2d3aafa06b21 diff --git a/aux/bro-aux b/aux/bro-aux index 15f5dca84d..0b6fce59fc 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 15f5dca84d08224b9b738f263de68f8b0b9439e9 +Subproject commit 0b6fce59fc503fb22d87d5f0cdfeb162885189e2 diff --git a/aux/broccoli b/aux/broccoli index 7ddfa3212d..a0b18634e5 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 7ddfa3212d1fd0822588d4a96158f1a30c755afe +Subproject commit a0b18634e5840dca59bd6ca4c486a761f37c076e diff --git a/aux/broctl b/aux/broctl index 43913d5064..e94b0d7f83 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 43913d50645f69b2b833773511f8de2fd6b3222c +Subproject commit e94b0d7f831fc58abf84dcddafa143cb95e068f2 From 57af99064a1947e07bad0d2341b702b4605a0e85 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 20 Aug 2013 15:56:09 -0700 Subject: [PATCH 241/881] Breaking lines in using/*. --- doc/using/index.rst | 128 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 13 deletions(-) diff --git a/doc/using/index.rst b/doc/using/index.rst index 092d5e1b92..df2b48bf48 100644 --- a/doc/using/index.rst +++ b/doc/using/index.rst @@ -5,25 +5,74 @@ Using Bro ========= -Once Bro has been deployed in an environment and monitoring live traffic, it will, in its default configuration, begin to produce human-readable ASCII logs. Each log file, produced by Bro's Logging Framework, is populated with organized, connection-oriented data. As the log files are simple ASCII data, working with the data contained in them can be done from a command line terminal once you have been familiarized with the types of data that can be found in each log file. +Once Bro has been deployed in an environment and monitoring live +traffic, it will, in its default configuration, begin to produce +human-readable ASCII logs. Each log file, produced by Bro's Logging +Framework, is populated with organized, connection-oriented data. As +the log files are simple ASCII data, working with the data contained +in them can be done from a command line terminal once you have been +familiarized with the types of data that can be found in each log +file. ---------------------- Structure of Log Files ---------------------- -The log files produced by Bro adhere to a structure as defined by the scripts that produced through which they were produced. However, as each log file has been produced using the Logging Framework, there are similarities shared by each log file. Without breaking into the scripting aspect of Bro, a bird's eye view of how the log files are produced would progress as follows. The script's author defines the kinds of data, such as the originating IP address or the duration of a connection, which will be used as fields in the log file. The author then decides what behavior should generate a log file entry, these behaviors can range from a connection having been completed or an HTTP GET method being issued by an originator. Once these behaviors have been observed, the data is passed to the Logging Framework which, in turn, adds an entry to the appropriate log file. While the fields of the log entries can be modified by the user, the Logging Framework makes use of a header entry in each log file to ensure that it remains self-describing. This header entry can be see by running the unix utility ``head`` and outputting the first eight lines of the file. +The log files produced by Bro adhere to a structure as defined by the +scripts that produced through which they were produced. However, as +each log file has been produced using the Logging Framework, there are +similarities shared by each log file. Without breaking into the +scripting aspect of Bro, a bird's eye view of how the log files are +produced would progress as follows. The script's author defines the +kinds of data, such as the originating IP address or the duration of a +connection, which will be used as fields in the log file. The author +then decides what behavior should generate a log file entry, these +behaviors can range from a connection having been completed or an HTTP +GET method being issued by an originator. Once these behaviors have +been observed, the data is passed to the Logging Framework which, in +turn, adds an entry to the appropriate log file. While the fields of +the log entries can be modified by the user, the Logging Framework +makes use of a header entry in each log file to ensure that it remains +self-describing. This header entry can be see by running the unix +utility ``head`` and outputting the first eight lines of the file. .. btest:: using_bro_cmd_line_01 @TEST-EXEC: btest-rst-cmd head -8 ${TESTBASE}/Baseline/core.pppoe/conn.log -The sample above shows the header for a ``conn.log`` file which gives a detailed account of each connection as seen by Bro. As you can see, header includes information such as what separators are being used for various types of data, what an empty field looks like and what an unset field looks like. In this example, the default TAB separator is being used as the delimiter between fiends (\x09 is the tab character in hex). It also lists the comma as the separator for set data, the string "(empty)" as the indicator for an empty field and the '-' character as the indicator for a field that hasn't been set. The timestamp for when the file was created is included under "#open". The header then goes on to detail the fields being listed in the file and the data types of those fields in #fields and #types respectively. These two entries are often the two most significant points of interest as they detail not only the field name but the data type used. Navigating through the different log files produced by Bro, often requires the use of different elements of the unix tool chain such as ``sed``, ``awk``, or ``grep`` and having the field definitions readily available will save the user some mental leg work. The field names are also a key resource for using the ``bro-cut`` utility included with Bro. +The sample above shows the header for a ``conn.log`` file which gives +a detailed account of each connection as seen by Bro. As you can see, +header includes information such as what separators are being used for +various types of data, what an empty field looks like and what an +unset field looks like. In this example, the default TAB separator is +being used as the delimiter between fiends (\x09 is the tab character +in hex). It also lists the comma as the separator for set data, the +string "(empty)" as the indicator for an empty field and the '-' +character as the indicator for a field that hasn't been set. The +timestamp for when the file was created is included under "#open". +The header then goes on to detail the fields being listed in the file +and the data types of those fields in #fields and #types respectively. +These two entries are often the two most significant points of +interest as they detail not only the field name but the data type +used. Navigating through the different log files produced by Bro, +often requires the use of different elements of the unix tool chain +such as ``sed``, ``awk``, or ``grep`` and having the field definitions +readily available will save the user some mental leg work. The field +names are also a key resource for using the ``bro-cut`` utility +included with Bro. ------------- Using bro-cut ------------- -The ``bro-cut`` utility can be used in place of other tools to build terminal commands that remain flexible and accurate independent of possible changes that can be made to the log file itself. It accomplishes this by parsing the header in each file and allowing the user to refer to the specific columnar data available. In contrast tools like ``awk`` require the user to refer to fields referenced by their position. For example, the two commands listed below produce the same output given a default configuration of Bro. +The ``bro-cut`` utility can be used in place of other tools to build +terminal commands that remain flexible and accurate independent of +possible changes that can be made to the log file itself. It +accomplishes this by parsing the header in each file and allowing the +user to refer to the specific columnar data available. In contrast +tools like ``awk`` require the user to refer to fields referenced by +their position. For example, the two commands listed below produce +the same output given a default configuration of Bro. .. btest:: using_bro_bro_cut_01 @@ -34,27 +83,64 @@ The ``bro-cut`` utility can be used in place of other tools to build terminal co @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/conn.log | btest-rst-cmd -c "cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration " bro-cut id.orig_h id.orig_p id.resp_h duration -While the output is similar, the advantages to using bro-cut over awk lay in that, while awk is flexible and powerful, ``bro-cut`` was specifically designed to work with log files. Firstly, the ``bro-cut`` output includes only the log file entries, while the ``awk`` output includes the header parts of the log file, which would require the user to use a secondary utility to suppress those lines. Secondly, since ``bro-cut`` uses the field descriptors to identify and extract data, it allows for flexibility independent of the format and contents of the log file. It's not uncommon for a Bro configuration to add extra fields to various log files as required by the environment. In this case, the fields in the ``awk`` command would have to be altered to compensate for the new position whereas the ``bro-cut`` output would not change. +While the output is similar, the advantages to using bro-cut over awk +lay in that, while awk is flexible and powerful, ``bro-cut`` was +specifically designed to work with log files. Firstly, the +``bro-cut`` output includes only the log file entries, while the +``awk`` output includes the header parts of the log file, which would +require the user to use a secondary utility to suppress those lines. +Secondly, since ``bro-cut`` uses the field descriptors to identify and +extract data, it allows for flexibility independent of the format and +contents of the log file. It's not uncommon for a Bro configuration +to add extra fields to various log files as required by the +environment. In this case, the fields in the ``awk`` command would +have to be altered to compensate for the new position whereas the +``bro-cut`` output would not change. -As you may have noticed, the command for ``bro-cut`` uses the output redirection through the ``cat`` command and ``|`` operator. Whereas tools like ``awk`` allow you to indicate the log file as a command line option, bro-cut only takes input through redirection such as ``|`` and ``<``. There are a couple of ways to direct log file data into ``bro-cut``, each dependent upon the type of log file you're processing. A caveat of its use, however, is that the 8 lines of header data must be present. In its default setup, Bro will rotate log files on an hourly basis, moving the current log file into a directory with format ``YYYY-MM-DD`` and gzip compressing the file with a file format that includes the log file type and time range of the file. In the case of processing a compressed log file you simply adjust your command line tools to use the complementary z* versions of commands such as cat (``zcat``), ``grep`` (``zgrep``), and ``head`` (``zhead``). +As you may have noticed, the command for ``bro-cut`` uses the output +redirection through the ``cat`` command and ``|`` operator. Whereas +tools like ``awk`` allow you to indicate the log file as a command +line option, bro-cut only takes input through redirection such as +``|`` and ``<``. There are a couple of ways to direct log file data +into ``bro-cut``, each dependent upon the type of log file you're +processing. A caveat of its use, however, is that the 8 lines of +header data must be present. In its default setup, Bro will rotate +log files on an hourly basis, moving the current log file into a +directory with format ``YYYY-MM-DD`` and gzip compressing the file +with a file format that includes the log file type and time range of +the file. In the case of processing a compressed log file you simply +adjust your command line tools to use the complementary z* versions of +commands such as cat (``zcat``), ``grep`` (``zgrep``), and ``head`` +(``zhead``). ....................... Working with timestamps ....................... -The ``bro-cut`` accepts the flag ``-d`` to convert the epoch time values in the log files to human-readable format. The following command includes the human readable time stamp, the unique identifier and the HTTP host and HTTP uri as parsed from the ``http.log`` file. +The ``bro-cut`` accepts the flag ``-d`` to convert the epoch time +values in the log files to human-readable format. The following +command includes the human readable time stamp, the unique identifier +and the HTTP host and HTTP uri as parsed from the ``http.log`` file. .. btest:: using_bro_bro_cut_time_01 @TEST-EXEC: btest-rst-cmd -c "bro-cut -d ts uid host uri < http.log" bro-cut -d ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log -Often times log files from multiple sources are stored in UTC time to allow easy correlation. Converting the timestamp from a log file to UTC can be accomplished with the ``-u`` command. +Often times log files from multiple sources are stored in UTC time to +allow easy correlation. Converting the timestamp from a log file to +UTC can be accomplished with the ``-u`` command. .. btest:: using_bro_bro_cut_time_02 @TEST-EXEC: btest-rst-cmd -c "bro-cut -u ts uid host uri < http.log" bro-cut -u ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log -The default time format when using the ``-d`` or ``-u`` is the ``strftime`` format string %Y-%m-%dT%H:%M:%S%z which results in a string with year, month, day of month, followed by hour, minutes, seconds and the timezone offset. The default ``strftime`` can be altered by using the ``-D`` and ``-U`` flags. For example, to format the timestamp in the US-typical "Middle Endian" you could use a format string of: %d-%m-%YT%H:%M:%S%z +The default time format when using the ``-d`` or ``-u`` is the +``strftime`` format string %Y-%m-%dT%H:%M:%S%z which results in a +string with year, month, day of month, followed by hour, minutes, +seconds and the timezone offset. The default ``strftime`` can be +altered by using the ``-D`` and ``-U`` flags. For example, to format +the timestamp in the US-typical "Middle Endian" you could use a format +string of: %d-%m-%YT%H:%M:%S%z .. btest:: using_bro_bro_cut_time_03 @@ -64,18 +150,34 @@ The default time format when using the ``-d`` or ``-u`` is the ``strftime`` form Working with Log Files ---------------------- -While Bro can do signature based analysis, its primary focus is on behavioral detection which alters the practice of log review from "reactionary review" to a process a little more akin to a hunting trip. A common progression of review includes correlating a session across multiple log files. As a connection is processed by Bro, a unique identifier is assigned to each session. This unique identifier is almost always included in any log file entry specific to that connection and can be used to cross-reference log files. +While Bro can do signature based analysis, its primary focus is on +behavioral detection which alters the practice of log review from +"reactionary review" to a process a little more akin to a hunting +trip. A common progression of review includes correlating a session +across multiple log files. As a connection is processed by Bro, a +unique identifier is assigned to each session. This unique identifier +is almost always included in any log file entry specific to that +connection and can be used to cross-reference log files. -A simple example would be to cross-reference a UID seen in a ``conn.log`` file. Here, we're looking for the connection with the largest number of bytes from the responder by redirecting the output for ``cat conn.log`` into bro-cut to extract the UID and the resp_bytes, then sorting that output by the resp_bytes field. +A simple example would be to cross-reference a UID seen in a +``conn.log`` file. Here, we're looking for the connection with the +largest number of bytes from the responder by redirecting the output +for ``cat conn.log`` into bro-cut to extract the UID and the +resp_bytes, then sorting that output by the resp_bytes field. .. btest:: using_bro_practical_02 @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_02/conn.log | bro-cut uid resp_bytes | btest-rst-cmd -c "cat conn.log | bro-cut uid resp_bytes | btest-rst-cmd sort -nrk2" sort -nrk2 -With the UID of the largest response, it can be crossreferenced with the UIDs in the ``http.log`` file. +With the UID of the largest response, it can be crossreferenced with +the UIDs in the ``http.log`` file. .. btest:: using_bro_practical_03 @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_02/http.log | bro-cut uid id.resp_h method status_code host uri | btest-rst-cmd -c "cat http.log | bro-cut uid id.resp_h method status_code host uri | grep j4u32Pc5bif" grep j4u32Pc5bif -As you can see there are multiple HTTP GET requests within the session that Bro identified and logged. Given that HTTP is a stream protocol, it can have multiple GET/POST/etc requests in a stream and Bro is able to extract and track that information for you, giving you an in-depth and structured view into HTTP traffic on your network. +As you can see there are multiple HTTP GET requests within the session +that Bro identified and logged. Given that HTTP is a stream protocol, +it can have multiple GET/POST/etc requests in a stream and Bro is able +to extract and track that information for you, giving you an in-depth +and structured view into HTTP traffic on your network. From 73a5106bd983dd5e0db4c884437f35c55db17aa3 Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Wed, 21 Aug 2013 07:29:22 -0400 Subject: [PATCH 242/881] Fix some reporter.log errors by adding a few extra key membership checks. --- scripts/base/frameworks/sumstats/cluster.bro | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index 9c343ad15d..0a84ef93ea 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -357,12 +357,16 @@ function request_all_current_keys(uid: string, ss_name: string, cleanup: bool) event SumStats::send_no_key(uid: string, ss_name: string) { #print "send_no_key"; + + if ( uid !in done_with ) + done_with[uid] = 0; + ++done_with[uid]; if ( Cluster::worker_count == done_with[uid] ) { delete done_with[uid]; - if ( |stats_keys[uid]| > 0 ) + if ( uid in stats_keys && |stats_keys[uid]| > 0 ) { #print "we need more keys!"; # Now that we have a key from each worker, lets @@ -426,6 +430,9 @@ event SumStats::cluster_send_result(uid: string, ss_name: string, key: Key, resu key_requests[uid] = compose_results(key_requests[uid], result); # Mark that a worker is done. + if ( uid !in done_with ) + done_with[uid] = 0; + ++done_with[uid]; #if ( Cluster::worker_count == done_with[uid] ) From 22b1e78ec11f13211e8a822ed06439e7673924dd Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 21 Aug 2013 14:08:14 -0400 Subject: [PATCH 243/881] Changing how threshold reseting happens (actually do it on managers!) --- scripts/base/frameworks/sumstats/cluster.bro | 9 +++------ scripts/base/frameworks/sumstats/main.bro | 6 ------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index 0a84ef93ea..73cbfe3cd3 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -60,7 +60,7 @@ export { # Add events to the cluster framework to make this work. redef Cluster::manager2worker_events += /SumStats::cluster_(ss_request|get_result|threshold_crossed)/; -redef Cluster::manager2worker_events += /SumStats::(thresholds_reset|get_a_key)/; +redef Cluster::manager2worker_events += /SumStats::(get_a_key)/; redef Cluster::worker2manager_events += /SumStats::cluster_(ss_response|send_result|key_intermediate_response)/; redef Cluster::worker2manager_events += /SumStats::(send_a_key|send_no_key)/; @@ -223,11 +223,6 @@ event SumStats::cluster_threshold_crossed(ss_name: string, key: SumStats::Key, t threshold_tracker[ss_name][key] = thold_index; } -event SumStats::thresholds_reset(ss_name: string) - { - delete threshold_tracker[ss_name]; - } - @endif @@ -274,6 +269,8 @@ event SumStats::finish_epoch(ss: SumStat) event SumStats::cluster_ss_request(uid, ss$name, T); done_with[uid] = 0; + reset(ss); + #print fmt("get_key by uid: %s", uid); event SumStats::get_a_key(uid, ss$name, T); } diff --git a/scripts/base/frameworks/sumstats/main.bro b/scripts/base/frameworks/sumstats/main.bro index 282b03da6b..293ad6ac65 100644 --- a/scripts/base/frameworks/sumstats/main.bro +++ b/scripts/base/frameworks/sumstats/main.bro @@ -153,11 +153,6 @@ export { ## Returns: The result for the requested sumstat key. global request_key: function(ss_name: string, key: Key): Result; - ## This event is generated when thresholds are reset for a SumStat. - ## - ## name: SumStats name that thresholds were reset for. - global thresholds_reset: event(name: string); - ## Helper function to represent a :bro:type:`SumStats::Key` value as ## a simple string. ## @@ -321,7 +316,6 @@ function reset(ss: SumStat) { delete threshold_tracker[ss$name]; threshold_tracker[ss$name] = table(); - event SumStats::thresholds_reset(ss$name); } } From 2091bbbf6f5a689a804f296e872ba1cd70b6323a Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 21 Aug 2013 14:47:05 -0400 Subject: [PATCH 244/881] Fixing a problem with resetting sumstats on managers in the wrong location. --- scripts/base/frameworks/sumstats/cluster.bro | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index 73cbfe3cd3..6c72d5ff17 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -269,8 +269,7 @@ event SumStats::finish_epoch(ss: SumStat) event SumStats::cluster_ss_request(uid, ss$name, T); done_with[uid] = 0; - reset(ss); - + #print fmt("get_key by uid: %s", uid); event SumStats::get_a_key(uid, ss$name, T); } @@ -292,6 +291,12 @@ function data_added(ss: SumStat, key: Key, result: Result) function handle_end_of_result_collection(uid: string, ss_name: string, key: Key, cleanup: bool) { + if ( uid !in key_requests ) + { + Reporter::warning(fmt("Tried to handle end of result collection with missing uid in key_request sumstat:%s, key:%s.", ss_name, key)); + return; + } + #print fmt("worker_count:%d :: done_with:%d", Cluster::worker_count, done_with[uid]); local ss = stats_store[ss_name]; local ir = key_requests[uid]; @@ -376,6 +381,8 @@ event SumStats::send_no_key(uid: string, ss_name: string) local ss = stats_store[ss_name]; if ( ss?$epoch_finished ) ss$epoch_finished(network_time()); + + reset(ss); } } } @@ -410,6 +417,8 @@ event SumStats::send_a_key(uid: string, ss_name: string, key: Key) local ss = stats_store[ss_name]; if ( ss?$epoch_finished ) ss$epoch_finished(network_time()); + + reset(ss); } } } @@ -430,6 +439,7 @@ event SumStats::cluster_send_result(uid: string, ss_name: string, key: Key, resu if ( uid !in done_with ) done_with[uid] = 0; + #print fmt("MANAGER: got a result for %s %s from %s", uid, key, get_event_peer()$descr); ++done_with[uid]; #if ( Cluster::worker_count == done_with[uid] ) @@ -443,7 +453,7 @@ event SumStats::cluster_send_result(uid: string, ss_name: string, key: Key, resu event SumStats::cluster_key_intermediate_response(ss_name: string, key: Key) { #print fmt("MANAGER: receiving intermediate key data from %s", get_event_peer()$descr); - #print fmt("MANAGER: requesting key data for %s", key2str(key)); + #print fmt("MANAGER: requesting key data for %s", key); if ( ss_name in outstanding_global_views && |outstanding_global_views[ss_name]| > max_outstanding_global_views ) @@ -458,9 +468,11 @@ event SumStats::cluster_key_intermediate_response(ss_name: string, key: Key) local uid = unique_id(""); done_with[uid] = 0; + #print fmt("requesting results for: %s", uid); event SumStats::cluster_get_result(uid, ss_name, key, F); when ( uid in done_with && Cluster::worker_count == done_with[uid] ) { + #print fmt("workers: %d done: %d", Cluster::worker_count, done_with[uid]); handle_end_of_result_collection(uid, ss_name, key, F); } timeout 1.1min From 8432f05bdb06ef9c4e02e1f7c962be765675329a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 21 Aug 2013 14:28:52 -0500 Subject: [PATCH 245/881] Fix memory leak w/ when statements - BIT-1058 Specifically if the condition of a when statement uses an index expression (e.g. table lookup). --- src/Trigger.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Trigger.cc b/src/Trigger.cc index a567528232..ed5d0e18f6 100644 --- a/src/Trigger.cc +++ b/src/Trigger.cc @@ -44,7 +44,10 @@ TraversalCode TriggerTraversalCallback::PreExpr(const Expr* expr) BroObj::SuppressErrors no_errors; Val* v = e->Eval(trigger->frame); if ( v ) + { trigger->Register(v); + Unref(v); + } break; } From b3a5c5f412d0699fde42b75ace75200dbb94a065 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 21 Aug 2013 19:11:34 -0400 Subject: [PATCH 246/881] Tiny fix to correct a reporter message. --- scripts/base/protocols/smtp/entities.bro | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/base/protocols/smtp/entities.bro b/scripts/base/protocols/smtp/entities.bro index d21ba8722d..4f6b6855f3 100644 --- a/scripts/base/protocols/smtp/entities.bro +++ b/scripts/base/protocols/smtp/entities.bro @@ -27,8 +27,10 @@ export { event mime_begin_entity(c: connection) &priority=10 { - c$smtp$entity = Entity(); - ++c$smtp_state$mime_depth; + if ( c?$smtp ) + c$smtp$entity = Entity(); + if ( c?$smtp_state ) + ++c$smtp_state$mime_depth; } event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 From 40d849a2c5ea27b681eec06aedf19078cb5e0421 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 22 Aug 2013 08:44:12 -0700 Subject: [PATCH 247/881] Updating CHANGES and VERSION. --- CHANGES | 18 ++++++++++++++++++ VERSION | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 94dac20038..aad7cf3dad 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,22 @@ +2.1-1117 | 2013-08-22 08:44:12 -0700 + + * A number of input framework fixes and corresponding test stability + improvements. (Jon Siwek) + + * Make memory leak tests able to time out. (Jon Siwek) + + * Fix a compiler warning regarding strncat misuse. (Jon Siwek) + +2.1-1103 | 2013-08-21 19:11:34 -0400 + + * A number of sumstats fixes. (Seth Hall, Vlad Grigorescu) + + * Fix memory leak w/ when statements. Addresses BIT-1058. (Jon + Siwek) + + * Switching to relative submodule paths (Robin Sommer) + 2.1-1089 | 2013-08-19 11:25:11 -0700 * Fix bloom filters' dependence on size_t. (Jon Siwek, Matthias diff --git a/VERSION b/VERSION index b12d8dfdd9..0d110b6b13 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-1089 +2.1-1117 From 1e9227a9e962c25166a280c8b4f1cf8c56fabc18 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 22 Aug 2013 08:57:45 -0700 Subject: [PATCH 248/881] Applying doc updates from BIT-1063. (Anthony Verez) notice.rst wasn't up-to-date in this branch, so I first copied it over from master. --- doc/frameworks/notice.rst | 31 +++++++++++++++---------------- doc/quickstart/index.rst | 13 +++++-------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/doc/frameworks/notice.rst b/doc/frameworks/notice.rst index dd0be42f02..1630459b46 100644 --- a/doc/frameworks/notice.rst +++ b/doc/frameworks/notice.rst @@ -1,5 +1,4 @@ -================ Notice Framework ================ @@ -87,21 +86,21 @@ directly make modifications to the :bro:see:`Notice::Info` record given as the argument to the hook. Here's a simple example which tells Bro to send an email for all notices of -type :bro:see:`SSH::Login` if the server is 10.0.0.1: +type :bro:see:`SSH::Password_Guessing` if the server is 10.0.0.1: .. code:: bro hook Notice::policy(n: Notice::Info) { - if ( n$note == SSH::Login && n$id$resp_h == 10.0.0.1 ) + if ( n$note == SSH::Password_Guessing && n$id$resp_h == 10.0.0.1 ) add n$actions[Notice::ACTION_EMAIL]; } .. note:: - Keep in mind that the semantics of the SSH::Login notice are - such that it is only raised when Bro heuristically detects a successful - login. No apparently failed logins will raise this notice. + Keep in mind that the semantics of the :bro:see:`SSH::Password_Guessing` + notice are such that it is only raised when Bro heuristically detects + a failed login. Hooks can also have priorities applied to order their execution like events with a default priority of 0. Greater values are executed first. Setting @@ -111,7 +110,7 @@ a hook body to run before default hook bodies might look like this: hook Notice::policy(n: Notice::Info) &priority=5 { - if ( n$note == SSH::Login && n$id$resp_h == 10.0.0.1 ) + if ( n$note == SSH::Password_Guessing && n$id$resp_h == 10.0.0.1 ) add n$actions[Notice::ACTION_EMAIL]; } @@ -174,16 +173,16 @@ Raising Notices A script should raise a notice for any occurrence that a user may want to be notified about or take action on. For example, whenever the base -SSH analysis scripts sees an SSH session where it is heuristically -guessed to be a successful login, it raises a Notice of the type -:bro:see:`SSH::Login`. The code in the base SSH analysis script looks -like this: +SSH analysis scripts sees enough failed logins to a given host, it +raises a notice of the type :bro:see:`SSH::Password_Guessing`. The code +in the base SSH analysis script which raises the notice looks like this: .. code:: bro - NOTICE([$note=SSH::Login, - $msg="Heuristically detected successful SSH login.", - $conn=c]); + NOTICE([$note=Password_Guessing, + $msg=fmt("%s appears to be guessing SSH passwords (seen in %d connections).", key$host, r$num), + $src=key$host, + $identifier=cat(key$host)]); :bro:see:`NOTICE` is a normal function in the global namespace which wraps a function within the ``Notice`` namespace. It takes a single @@ -340,7 +339,7 @@ included below. hook Notice::policy(n: Notice::Info) { if ( n?$conn && n$conn?$http && n$conn$http?$host ) - n$email_body_sections[|email_body_sections|] = fmt("HTTP host header: %s", n$conn$http$host); + n$email_body_sections[|n$email_body_sections|] = fmt("HTTP host header: %s", n$conn$http$host); } @@ -349,7 +348,7 @@ Cluster Considerations As a user/developer of Bro, the main cluster concern with the notice framework is understanding what runs where. When a notice is generated on a worker, the -worker checks to see if the notice shoudl be suppressed based on information +worker checks to see if the notice should be suppressed based on information locally maintained in the worker process. If it's not being suppressed, the worker forwards the notice directly to the manager and does no more local processing. The manager then runs the :bro:see:`Notice::policy` hook and diff --git a/doc/quickstart/index.rst b/doc/quickstart/index.rst index a626d3b058..89de40e948 100644 --- a/doc/quickstart/index.rst +++ b/doc/quickstart/index.rst @@ -264,14 +264,11 @@ that only takes the email action for SSH logins to a defined set of servers: 192.168.1.102, } &redef; - redef Notice::policy += { - [$action = Notice::ACTION_EMAIL, - $pred(n: Notice::Info) = - { - return n$note == SSH::Login && n$id$resp_h in watched_servers; - } - ] - }; + hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSH::SUCCESSFUL_LOGIN && n$id$resp_h in watched_servers ) + add n$actions[Notice::ACTION_EMAIL]; + } You'll just have to trust the syntax for now, but what we've done is first declare our own variable to hold a set of watched addresses, From 29ce98a1d83423ca695a5551fddee3c40356ce74 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 22 Aug 2013 10:37:29 -0700 Subject: [PATCH 249/881] Updating submodule(s). [nomail] --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index be7c653dcd..50d426ba09 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit be7c653dcdc30384d4d17359d19d94540fdedaa5 +Subproject commit 50d426ba09adc6ae6127cce93d59057c0f09abb1 From 89ae4ffd051080315ec0a9ef3ce8bdeca3180be6 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 22 Aug 2013 16:37:58 -0500 Subject: [PATCH 250/881] Add options to limit extracted file sizes w/ 100MB default. --- doc/scripts/DocSourcesList.cmake | 2 + scripts/base/files/extract/main.bro | 29 +- src/file_analysis/AnalyzerSet.cc | 8 + src/file_analysis/AnalyzerSet.h | 8 + src/file_analysis/File.cc | 20 +- src/file_analysis/File.h | 8 + src/file_analysis/Manager.cc | 11 + src/file_analysis/Manager.h | 13 + .../analyzer/extract/CMakeLists.txt | 2 + src/file_analysis/analyzer/extract/Extract.cc | 74 ++- src/file_analysis/analyzer/extract/Extract.h | 14 +- src/file_analysis/analyzer/extract/Plugin.cc | 5 + src/file_analysis/analyzer/extract/events.bif | 19 + .../analyzer/extract/functions.bif | 19 + .../canonified_loaded_scripts.log | 2 + .../canonified_loaded_scripts.log | 2 + .../scripts.base.files.extract.limit/1.out | 1 + .../scripts.base.files.extract.limit/2.out | 3 + .../scripts.base.files.extract.limit/3.out | 2 + .../extract_files.1 | 72 +++ .../extract_files.2 | 157 +++++++ .../extract_files.3 | 425 ++++++++++++++++++ .../scripts/base/files/extract/limit.bro | 44 ++ 23 files changed, 929 insertions(+), 11 deletions(-) create mode 100644 src/file_analysis/analyzer/extract/events.bif create mode 100644 src/file_analysis/analyzer/extract/functions.bif create mode 100644 testing/btest/Baseline/scripts.base.files.extract.limit/1.out create mode 100644 testing/btest/Baseline/scripts.base.files.extract.limit/2.out create mode 100644 testing/btest/Baseline/scripts.base.files.extract.limit/3.out create mode 100644 testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.1 create mode 100644 testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.2 create mode 100644 testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.3 create mode 100644 testing/btest/scripts/base/files/extract/limit.bro diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index 7abc3e6bb8..9137066337 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -36,6 +36,8 @@ rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_DNS.events.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_FTP.events.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_FTP.functions.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_File.events.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_FileExtract.events.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_FileExtract.functions.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_FileHash.events.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Finger.events.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_GTPv1.events.bif.bro) diff --git a/scripts/base/files/extract/main.bro b/scripts/base/files/extract/main.bro index 70e61c8529..f9fb9df009 100644 --- a/scripts/base/files/extract/main.bro +++ b/scripts/base/files/extract/main.bro @@ -7,6 +7,10 @@ export { ## The prefix where files are extracted to. const prefix = "./extract_files/" &redef; + ## The default max size for extracted files (they won't exceed this + ## number of bytes), 100MB. + const default_limit = 104857600; + redef record Files::Info += { ## Local filenames of extracted file. extracted: string &optional &log; @@ -17,9 +21,32 @@ export { ## This field is used in the core by the extraction plugin ## to know where to write the file to. It's also optional extract_filename: string &optional; + ## The maximum allowed file size in bytes of *extract_filename*. + ## Once reached, a :bro:see:`file_extraction_limit` event is + ## raised and the analyzer will be removed unless + ## :bro:see:`FileExtract::set_limit` is called to increase the + ## limit. A value of zero means "no limit". + extract_limit: count &default=default_limit; }; + + ## Sets the maximum allowed extracted file size. + ## + ## f: A file that's being extracted. + ## + ## args: Arguments that identify a file extraction analyzer. + ## + ## n: Allowed number of bytes to be extracted. + ## + ## Returns: false if a file extraction analyzer wasn't active for + ## the file, else true. + global set_limit: function(f: fa_file, args: Files::AnalyzerArgs, n: count): bool; } +function set_limit(f: fa_file, args: Files::AnalyzerArgs, n: count): bool + { + return __set_limit(f$id, args, n); + } + function on_add(f: fa_file, args: Files::AnalyzerArgs) { if ( ! args?$extract_filename ) @@ -35,4 +62,4 @@ event bro_init() &priority=10 # Create the extraction directory. mkdir(prefix); - } \ No newline at end of file + } diff --git a/src/file_analysis/AnalyzerSet.cc b/src/file_analysis/AnalyzerSet.cc index f7abc01dc2..6fc3d2dfd0 100644 --- a/src/file_analysis/AnalyzerSet.cc +++ b/src/file_analysis/AnalyzerSet.cc @@ -35,6 +35,14 @@ AnalyzerSet::~AnalyzerSet() delete analyzer_hash; } +Analyzer* AnalyzerSet::Find(file_analysis::Tag tag, RecordVal* args) + { + HashKey* key = GetKey(tag, args); + Analyzer* rval = analyzer_map.Lookup(key); + delete key; + return rval; + } + bool AnalyzerSet::Add(file_analysis::Tag tag, RecordVal* args) { HashKey* key = GetKey(tag, args); diff --git a/src/file_analysis/AnalyzerSet.h b/src/file_analysis/AnalyzerSet.h index 42a54f4943..38eddb8967 100644 --- a/src/file_analysis/AnalyzerSet.h +++ b/src/file_analysis/AnalyzerSet.h @@ -37,6 +37,14 @@ public: */ ~AnalyzerSet(); + /** + * Looks up an analyzer by its tag and arguments. + * @param tag an analyzer tag. + * @param args an \c AnalyzerArgs record. + * @return pointer to an analyzer instance, or a null pointer if not found. + */ + Analyzer* Find(file_analysis::Tag tag, RecordVal* args); + /** * Attach an analyzer to #file immediately. * @param tag the analyzer tag of the file analyzer to add. diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index 1197cd06f6..55b28763c8 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -14,6 +14,8 @@ #include "analyzer/Analyzer.h" #include "analyzer/Manager.h" +#include "analyzer/extract/Extract.h" + using namespace file_analysis; static Val* empty_connection_table() @@ -203,6 +205,22 @@ void File::SetTimeoutInterval(double interval) val->Assign(timeout_interval_idx, new Val(interval, TYPE_INTERVAL)); } +bool File::SetExtractionLimit(RecordVal* args, uint64 bytes) + { + Analyzer* a = analyzers.Find(file_mgr->GetComponentTag("EXTRACT"), args); + + if ( ! a ) + return false; + + Extract* e = dynamic_cast(a); + + if ( ! e ) + return false; + + e->SetLimit(bytes); + return true; + } + void File::IncrementByteCount(uint64 size, int field_idx) { uint64 old = LookupFieldDefaultCount(field_idx); @@ -458,7 +476,7 @@ void File::FileEvent(EventHandlerPtr h, val_list* vl) } } - if ( h == file_new || h == file_timeout ) + if ( h == file_new || h == file_timeout || h == file_extraction_limit ) { // immediate feedback is required for these events. mgr.Drain(); diff --git a/src/file_analysis/File.h b/src/file_analysis/File.h index 12c1e061a8..6354c1c7e9 100644 --- a/src/file_analysis/File.h +++ b/src/file_analysis/File.h @@ -56,6 +56,14 @@ public: */ void SetTimeoutInterval(double interval); + /** + * Change the maximum size that an attached extraction analyzer is allowed. + * @param args the file extraction analyzer whose limit needs changed. + * @param bytes new limit. + * @return false if no extraction analyzer is active, else true. + */ + bool SetExtractionLimit(RecordVal* args, uint64 bytes); + /** * @return value of the "id" field from #val record. */ diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index 5975133356..7bfd5167ba 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -184,6 +184,17 @@ bool Manager::SetTimeoutInterval(const string& file_id, double interval) const return true; } +bool Manager::SetExtractionLimit(const string& file_id, RecordVal* args, + uint64 n) const + { + File* file = LookupFile(file_id); + + if ( ! file ) + return false; + + return file->SetExtractionLimit(args, n); + } + bool Manager::AddAnalyzer(const string& file_id, file_analysis::Tag tag, RecordVal* args) const { diff --git a/src/file_analysis/Manager.h b/src/file_analysis/Manager.h index dcf33edc99..cdfac00520 100644 --- a/src/file_analysis/Manager.h +++ b/src/file_analysis/Manager.h @@ -173,6 +173,19 @@ public: */ bool SetTimeoutInterval(const string& file_id, double interval) const; + /** + * Sets a limit on the maximum size allowed for extracting the file + * to local disk; + * @param file_id the file identifier/hash. + * @param args a \c AnalyzerArgs value which describes a file analyzer, + * which should be a file extraction analyzer. + * @param n the new extraction limit, in bytes. + * @return false if file identifier and analyzer did not map to anything, + * else true. + */ + bool SetExtractionLimit(const string& file_id, RecordVal* args, + uint64 n) const; + /** * Queue attachment of an analzer to the file identifier. Multiple * analyzers of a given type can be attached per file identifier at a time diff --git a/src/file_analysis/analyzer/extract/CMakeLists.txt b/src/file_analysis/analyzer/extract/CMakeLists.txt index e413196db2..5f96f4f01b 100644 --- a/src/file_analysis/analyzer/extract/CMakeLists.txt +++ b/src/file_analysis/analyzer/extract/CMakeLists.txt @@ -5,4 +5,6 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} bro_plugin_begin(Bro FileExtract) bro_plugin_cc(Extract.cc Plugin.cc ../../Analyzer.cc) +bro_plugin_bif(events.bif) +bro_plugin_bif(functions.bif) bro_plugin_end() diff --git a/src/file_analysis/analyzer/extract/Extract.cc b/src/file_analysis/analyzer/extract/Extract.cc index 28b5cf5a63..504ffd9112 100644 --- a/src/file_analysis/analyzer/extract/Extract.cc +++ b/src/file_analysis/analyzer/extract/Extract.cc @@ -4,13 +4,15 @@ #include "Extract.h" #include "util.h" +#include "Event.h" #include "file_analysis/Manager.h" using namespace file_analysis; -Extract::Extract(RecordVal* args, File* file, const string& arg_filename) +Extract::Extract(RecordVal* args, File* file, const string& arg_filename, + uint64 arg_limit) : file_analysis::Analyzer(file_mgr->GetComponentTag("EXTRACT"), args, file), - filename(arg_filename) + filename(arg_filename), limit(arg_limit) { fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666); @@ -29,15 +31,51 @@ Extract::~Extract() safe_close(fd); } -file_analysis::Analyzer* Extract::Instantiate(RecordVal* args, File* file) +static Val* get_extract_field_val(RecordVal* args, const char* name) { using BifType::Record::Files::AnalyzerArgs; - Val* v = args->Lookup(AnalyzerArgs->FieldOffset("extract_filename")); + Val* rval = args->Lookup(AnalyzerArgs->FieldOffset(name)); - if ( ! v ) + if ( ! rval ) + reporter->Error("File extraction analyzer missing arg field: %s", name); + + return rval; + } + +file_analysis::Analyzer* Extract::Instantiate(RecordVal* args, File* file) + { + Val* fname = get_extract_field_val(args, "extract_filename"); + Val* limit = get_extract_field_val(args, "extract_limit"); + + if ( ! fname || ! limit ) return 0; - return new Extract(args, file, v->AsString()->CheckString()); + return new Extract(args, file, fname->AsString()->CheckString(), + limit->AsCount()); + } + +static bool check_limit_exceeded(uint64 lim, uint64 off, uint64 len, uint64* n) + { + if ( lim == 0 ) + { + *n = len; + return false; + } + + if ( off >= lim ) + { + *n = 0; + return true; + } + + *n = lim - off; + + if ( len > *n ) + return true; + else + *n = len; + + return false; } bool Extract::DeliverChunk(const u_char* data, uint64 len, uint64 offset) @@ -45,6 +83,26 @@ bool Extract::DeliverChunk(const u_char* data, uint64 len, uint64 offset) if ( ! fd ) return false; - safe_pwrite(fd, data, len, offset); - return true; + uint64 towrite = 0; + bool limit_exceeded = check_limit_exceeded(limit, offset, len, &towrite); + + if ( limit_exceeded && file_extraction_limit ) + { + File* f = GetFile(); + val_list* vl = new val_list(); + vl->append(f->GetVal()->Ref()); + vl->append(Args()->Ref()); + vl->append(new Val(limit, TYPE_COUNT)); + vl->append(new Val(offset, TYPE_COUNT)); + vl->append(new Val(len, TYPE_COUNT)); + f->FileEvent(file_extraction_limit, vl); + + // Limit may have been modified by BIF, re-check it. + limit_exceeded = check_limit_exceeded(limit, offset, len, &towrite); + } + + if ( towrite > 0 ) + safe_pwrite(fd, data, towrite, offset); + + return ( ! limit_exceeded ); } diff --git a/src/file_analysis/analyzer/extract/Extract.h b/src/file_analysis/analyzer/extract/Extract.h index 85d2a9e7a8..00c4dbe2b7 100644 --- a/src/file_analysis/analyzer/extract/Extract.h +++ b/src/file_analysis/analyzer/extract/Extract.h @@ -9,6 +9,8 @@ #include "File.h" #include "Analyzer.h" +#include "analyzer/extract/events.bif.h" + namespace file_analysis { /** @@ -41,6 +43,13 @@ public: */ static file_analysis::Analyzer* Instantiate(RecordVal* args, File* file); + /** + * Sets the maximum allowed extracted file size. A value of zero means + * "no limit". + * @param bytes number of bytes allowed to be extracted + */ + void SetLimit(uint64 bytes) { limit = bytes; } + protected: /** @@ -49,12 +58,15 @@ protected: * @param file the file to which the analyzer will be attached. * @param arg_filename a file system path which specifies the local file * to which the contents of the file will be extracted/written. + * @param arg_limit the maximum allowed file size. */ - Extract(RecordVal* args, File* file, const string& arg_filename); + Extract(RecordVal* args, File* file, const string& arg_filename, + uint64 arg_limit); private: string filename; int fd; + uint64 limit; }; } // namespace file_analysis diff --git a/src/file_analysis/analyzer/extract/Plugin.cc b/src/file_analysis/analyzer/extract/Plugin.cc index f6cde57f03..39a8fad95f 100644 --- a/src/file_analysis/analyzer/extract/Plugin.cc +++ b/src/file_analysis/analyzer/extract/Plugin.cc @@ -18,6 +18,11 @@ protected: AddComponent(new ::file_analysis::Component("EXTRACT", ::file_analysis::Extract::Instantiate)); + + extern std::list > __bif_events_init(); + AddBifInitFunction(&__bif_events_init); + extern std::list > __bif_functions_init(); + AddBifInitFunction(&__bif_functions_init); } }; diff --git a/src/file_analysis/analyzer/extract/events.bif b/src/file_analysis/analyzer/extract/events.bif new file mode 100644 index 0000000000..dc16d066e6 --- /dev/null +++ b/src/file_analysis/analyzer/extract/events.bif @@ -0,0 +1,19 @@ +## This event is generated when a file extraction analyzer is about +## to exceed the maximum permitted file size allowed by +## *extract_size_limit* field of :bro:see:`Files::AnalyzerArgs`. +## The analyzer is automatically removed from file *f*. +## +## f: The file. +## +## args: Arguments that identify a particular file extraction analyzer. +## This is only provided to be able to pass along to +## :bro:see:`FileExtract::set_limit`. +## +## limit: The limit, in bytes, the extracted file is about to breach. +## +## offset: The offset at which a file chunk is about to be written. +## +## len:: The length of the file chunk about to be written. +## +## .. bro:see:: Files::add_analyzer Files::ANALYZER_EXTRACT +event file_extraction_limit%(f: fa_file, args: any, limit: count, offset: count, len: count%); diff --git a/src/file_analysis/analyzer/extract/functions.bif b/src/file_analysis/analyzer/extract/functions.bif new file mode 100644 index 0000000000..15370402e3 --- /dev/null +++ b/src/file_analysis/analyzer/extract/functions.bif @@ -0,0 +1,19 @@ +##! Internal functions used by the extraction file analyzer. + +module FileExtract; + +%%{ +#include "file_analysis/Manager.h" +%%} + +## :bro:see:`FileExtract::set_limit`. +function FileExtract::__set_limit%(file_id: string, args: any, n: count%): bool + %{ + using BifType::Record::Files::AnalyzerArgs; + RecordVal* rv = args->AsRecordVal()->CoerceTo(AnalyzerArgs); + bool result = file_mgr->SetExtractionLimit(file_id->CheckString(), rv, n); + Unref(rv); + return new Val(result, TYPE_BOOL); + %} + +module GLOBAL; diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index 545bf70e7e..2cc2140a28 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -25,6 +25,8 @@ scripts/base/init-bare.bro build/scripts/base/bif/plugins/Bro_DNP3.events.bif.bro build/scripts/base/bif/plugins/Bro_DNS.events.bif.bro build/scripts/base/bif/plugins/Bro_File.events.bif.bro + build/scripts/base/bif/plugins/Bro_FileExtract.events.bif.bro + build/scripts/base/bif/plugins/Bro_FileExtract.functions.bif.bro build/scripts/base/bif/plugins/Bro_FileHash.events.bif.bro build/scripts/base/bif/plugins/Bro_Finger.events.bif.bro build/scripts/base/bif/plugins/Bro_FTP.events.bif.bro diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index d37fbb117c..1997857721 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -25,6 +25,8 @@ scripts/base/init-bare.bro build/scripts/base/bif/plugins/Bro_DNP3.events.bif.bro build/scripts/base/bif/plugins/Bro_DNS.events.bif.bro build/scripts/base/bif/plugins/Bro_File.events.bif.bro + build/scripts/base/bif/plugins/Bro_FileExtract.events.bif.bro + build/scripts/base/bif/plugins/Bro_FileExtract.functions.bif.bro build/scripts/base/bif/plugins/Bro_FileHash.events.bif.bro build/scripts/base/bif/plugins/Bro_Finger.events.bif.bro build/scripts/base/bif/plugins/Bro_FTP.events.bif.bro diff --git a/testing/btest/Baseline/scripts.base.files.extract.limit/1.out b/testing/btest/Baseline/scripts.base.files.extract.limit/1.out new file mode 100644 index 0000000000..f767bfcccd --- /dev/null +++ b/testing/btest/Baseline/scripts.base.files.extract.limit/1.out @@ -0,0 +1 @@ +file_extraction_limit, 3000, 2896, 1448 diff --git a/testing/btest/Baseline/scripts.base.files.extract.limit/2.out b/testing/btest/Baseline/scripts.base.files.extract.limit/2.out new file mode 100644 index 0000000000..bdf1f9d171 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.files.extract.limit/2.out @@ -0,0 +1,3 @@ +file_extraction_limit, 3000, 2896, 1448 +T +file_extraction_limit, 6000, 5792, 1448 diff --git a/testing/btest/Baseline/scripts.base.files.extract.limit/3.out b/testing/btest/Baseline/scripts.base.files.extract.limit/3.out new file mode 100644 index 0000000000..b6da9537b7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.files.extract.limit/3.out @@ -0,0 +1,2 @@ +file_extraction_limit, 7000, 5792, 1448 +T diff --git a/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.1 b/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.1 new file mode 100644 index 0000000000..9f858a7cc7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.1 @@ -0,0 +1,72 @@ +The National Center for Supercomputing Applications 1/28/92 +Anonymous FTP Server General Information + +This file contains information about the general structure, as well as +information on how to obtain files and documentation from the FTP server. +NCSA software and documentation can also be obtained through the the U.S. +Mail. Instructions are included for using this method as well. + +Information about the Software Development Group and NCSA software can be +found in the /ncsapubs directory in a file called TechResCatalog. + + +THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE +SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION, +WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. + + +_____________________________________________________________ + +FTP INSTRUCTIONS + +Most NCSA Software is released into the public domain. That is, for these +programs, the public domain has all rights for future licensing, resale, +and publication of available packages. If you are connected to Internet +(NSFNET, ARPANET, MILNET, etc) you may download NCSA software and documentation and source code if it is available, at no charge from the anonymous file +transfer protocol (FTP) server at NCSA where you got this file. The procedure +you should follow to do so is presented below. If you have any questions +regarding this procedure or whether you are connected to Internet, consult your local system administration or network expert. + +1. Log on to a host at your site that is connected to the Internet and is + running software supporting the FTP command. + +2. Invoke FTP on most systems by entering the Internet address of the server. + Type the following at the shell (usually "%") prompt: + + % ftp ftp.ncsa.uiuc.edu + +3. Log in by entering anonymous for the name. + +4. Enter your local email address (login@host) for the password. + +5. Enter the following at the "ftp>" prompt to copy a text file from our + server to your local host: + + ftp> get filename + + where "filename" is the name of the file you want a copy of. For example, + to get a copy of this file from the server enter: + + ftp> get README.FIRST + + To get a copy of our software brochure, enter: + + ftp> cd ncsapubs + get TechResCatalog + + NOTE: Some of the filenames on the server are rather long to aid in + identification. Some operating systems may have problems with names + this long. To change the name the file will have on your local + machine type the following at the "ftp>" prompt ("remoteName" is the + name of the file on the server and "localName" is the name you want + the file to have on your local machine): + + ftp> get remoteName localName + + Example: + + ftp> get TechResCatalog catalog.txt + + +6. For files that are not text files (almost everything else) you will need to + specify that you want to transfer binary files. Do this by ty \ No newline at end of file diff --git a/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.2 b/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.2 new file mode 100644 index 0000000000..41f96858de --- /dev/null +++ b/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.2 @@ -0,0 +1,157 @@ +The National Center for Supercomputing Applications 1/28/92 +Anonymous FTP Server General Information + +This file contains information about the general structure, as well as +information on how to obtain files and documentation from the FTP server. +NCSA software and documentation can also be obtained through the the U.S. +Mail. Instructions are included for using this method as well. + +Information about the Software Development Group and NCSA software can be +found in the /ncsapubs directory in a file called TechResCatalog. + + +THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE +SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION, +WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. + + +_____________________________________________________________ + +FTP INSTRUCTIONS + +Most NCSA Software is released into the public domain. That is, for these +programs, the public domain has all rights for future licensing, resale, +and publication of available packages. If you are connected to Internet +(NSFNET, ARPANET, MILNET, etc) you may download NCSA software and documentation and source code if it is available, at no charge from the anonymous file +transfer protocol (FTP) server at NCSA where you got this file. The procedure +you should follow to do so is presented below. If you have any questions +regarding this procedure or whether you are connected to Internet, consult your local system administration or network expert. + +1. Log on to a host at your site that is connected to the Internet and is + running software supporting the FTP command. + +2. Invoke FTP on most systems by entering the Internet address of the server. + Type the following at the shell (usually "%") prompt: + + % ftp ftp.ncsa.uiuc.edu + +3. Log in by entering anonymous for the name. + +4. Enter your local email address (login@host) for the password. + +5. Enter the following at the "ftp>" prompt to copy a text file from our + server to your local host: + + ftp> get filename + + where "filename" is the name of the file you want a copy of. For example, + to get a copy of this file from the server enter: + + ftp> get README.FIRST + + To get a copy of our software brochure, enter: + + ftp> cd ncsapubs + get TechResCatalog + + NOTE: Some of the filenames on the server are rather long to aid in + identification. Some operating systems may have problems with names + this long. To change the name the file will have on your local + machine type the following at the "ftp>" prompt ("remoteName" is the + name of the file on the server and "localName" is the name you want + the file to have on your local machine): + + ftp> get remoteName localName + + Example: + + ftp> get TechResCatalog catalog.txt + + +6. For files that are not text files (almost everything else) you will need to + specify that you want to transfer binary files. Do this by typing the + following at the "ftp>" prompt: + + ftp> type binary + + You can now use the "get" command to download binary files. To switch back + to ASCII text transfers type: + + ftp> type ascii + +7. The "ls" and "cd" commands can be used at the "ftp>" prompt to list and + change directories as in the shell. + +8. Enter "quit" or "bye" to exit FTP and return to your local host. + + +_____________________________________________________________ + +FTP SOFTWARE BY MAIL + +To obtain an order form, send your request to the following address: + +FTP Archive Tapes +c/o Debbie Shirley +152 Computing Applications Building +605 East Springfield Avenue +Champaign, IL 61820 + +or call: +Debbie at (217) 244-4130 + + +_____________________________________________________________ + +VIRUS INFORMATION + +The Software Development Group at NCSA is very virus-conscious. We routinely +check our machines for viruses and recommend that you do so also. For the +Macintoshes we use Disinfectant. You can obtain a copy of Disinfectant from +the /Mac/Utilities directory. + +If you use Microsoft DOS or Windows you can find the latest virus scan from +the anonymous site oak.oakland.edu in the /SimTel/msdos/virus directory. + +_____________________________________________________________ + +GENERAL INFORMATION + + +DIRECTORY STRUCTURE + +The FTP server is organized as specified below: + + /Mac Macintosh software + /PC IBM PC software + /Unix Software for machines running UNIX or equivalent OS + /Unix/SGI Software that primarily runs on Silicon Graphics + machines only + /Visualization Software tools for data visualization. + /Web World Wide Web tools, including Mosaic, httpd, + and html editors. + /HDF Hierarchical Data Format applications and tools + /Samples Samples that can be used with most of NCSA software + tools + /Documentation Currently being constructed, check each application's + directory for documentation + /ncsapubs Information produced by the Publications group, + including Metacenter announcements, data link & access, + a software listing, start-up guides, and other + reference documents. + /misc Miscellaneous documentation and software + /incoming directory for contributions + /outgoing swap directory + +Information for a particular application can be found in the README file, +located in the same directory as the application. The README files contain +information on new features, known bugs, compile information, and other +important notes. + +All directories on the FTP server contain an INDEX file. These files outline +the hierarchical structure of the directory and (recursively) all files and +directories contained within it. The INDEX at the root level contains the +structure of the enire server listing all files and directories on it. The +INDEX file in each software directory contains additional information about +each file. The letter in parenthesis after the file name indicates how the +file should be downloaded \ No newline at end of file diff --git a/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.3 b/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.3 new file mode 100644 index 0000000000..ffa6b5b161 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.files.extract.limit/extract_files.3 @@ -0,0 +1,425 @@ +The National Center for Supercomputing Applications 1/28/92 +Anonymous FTP Server General Information + +This file contains information about the general structure, as well as +information on how to obtain files and documentation from the FTP server. +NCSA software and documentation can also be obtained through the the U.S. +Mail. Instructions are included for using this method as well. + +Information about the Software Development Group and NCSA software can be +found in the /ncsapubs directory in a file called TechResCatalog. + + +THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE +SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION, +WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. + + +_____________________________________________________________ + +FTP INSTRUCTIONS + +Most NCSA Software is released into the public domain. That is, for these +programs, the public domain has all rights for future licensing, resale, +and publication of available packages. If you are connected to Internet +(NSFNET, ARPANET, MILNET, etc) you may download NCSA software and documentation and source code if it is available, at no charge from the anonymous file +transfer protocol (FTP) server at NCSA where you got this file. The procedure +you should follow to do so is presented below. If you have any questions +regarding this procedure or whether you are connected to Internet, consult your local system administration or network expert. + +1. Log on to a host at your site that is connected to the Internet and is + running software supporting the FTP command. + +2. Invoke FTP on most systems by entering the Internet address of the server. + Type the following at the shell (usually "%") prompt: + + % ftp ftp.ncsa.uiuc.edu + +3. Log in by entering anonymous for the name. + +4. Enter your local email address (login@host) for the password. + +5. Enter the following at the "ftp>" prompt to copy a text file from our + server to your local host: + + ftp> get filename + + where "filename" is the name of the file you want a copy of. For example, + to get a copy of this file from the server enter: + + ftp> get README.FIRST + + To get a copy of our software brochure, enter: + + ftp> cd ncsapubs + get TechResCatalog + + NOTE: Some of the filenames on the server are rather long to aid in + identification. Some operating systems may have problems with names + this long. To change the name the file will have on your local + machine type the following at the "ftp>" prompt ("remoteName" is the + name of the file on the server and "localName" is the name you want + the file to have on your local machine): + + ftp> get remoteName localName + + Example: + + ftp> get TechResCatalog catalog.txt + + +6. For files that are not text files (almost everything else) you will need to + specify that you want to transfer binary files. Do this by typing the + following at the "ftp>" prompt: + + ftp> type binary + + You can now use the "get" command to download binary files. To switch back + to ASCII text transfers type: + + ftp> type ascii + +7. The "ls" and "cd" commands can be used at the "ftp>" prompt to list and + change directories as in the shell. + +8. Enter "quit" or "bye" to exit FTP and return to your local host. + + +_____________________________________________________________ + +FTP SOFTWARE BY MAIL + +To obtain an order form, send your request to the following address: + +FTP Archive Tapes +c/o Debbie Shirley +152 Computing Applications Building +605 East Springfield Avenue +Champaign, IL 61820 + +or call: +Debbie at (217) 244-4130 + + +_____________________________________________________________ + +VIRUS INFORMATION + +The Software Development Group at NCSA is very virus-conscious. We routinely +check our machines for viruses and recommend that you do so also. For the +Macintoshes we use Disinfectant. You can obtain a copy of Disinfectant from +the /Mac/Utilities directory. + +If you use Microsoft DOS or Windows you can find the latest virus scan from +the anonymous site oak.oakland.edu in the /SimTel/msdos/virus directory. + +_____________________________________________________________ + +GENERAL INFORMATION + + +DIRECTORY STRUCTURE + +The FTP server is organized as specified below: + + /Mac Macintosh software + /PC IBM PC software + /Unix Software for machines running UNIX or equivalent OS + /Unix/SGI Software that primarily runs on Silicon Graphics + machines only + /Visualization Software tools for data visualization. + /Web World Wide Web tools, including Mosaic, httpd, + and html editors. + /HDF Hierarchical Data Format applications and tools + /Samples Samples that can be used with most of NCSA software + tools + /Documentation Currently being constructed, check each application's + directory for documentation + /ncsapubs Information produced by the Publications group, + including Metacenter announcements, data link & access, + a software listing, start-up guides, and other + reference documents. + /misc Miscellaneous documentation and software + /incoming directory for contributions + /outgoing swap directory + +Information for a particular application can be found in the README file, +located in the same directory as the application. The README files contain +information on new features, known bugs, compile information, and other +important notes. + +All directories on the FTP server contain an INDEX file. These files outline +the hierarchical structure of the directory and (recursively) all files and +directories contained within it. The INDEX at the root level contains the +structure of the enire server listing all files and directories on it. The +INDEX file in each software directory contains additional information about +each file. The letter in parenthesis after the file name indicates how the +file should be downloaded: ascii (a), binary (b), or mac binary (m). + +The "misc" directories found in some software tool directories contain +supplementary code or other information. Refer to the README file in that +directory for a description of what is contained within the "misc" directory. + +The "contrib" directories contain contributed software. This directory usually +contains NCSA source that has been modified by people outside of NCSA as well +as binaries compiled on different platforms not available to the Software +Development Group. If you have modified NCSA software or would like to share +some code please contact the developer of the source so arrangemnts can be +made to upload it to the "incoming" directory. If you are downloading +software from the "contrib" directory please note that this software is not +supported by NCSA and has not been checked for viruses (see statement on +viruses above). NCSA may not be held responsible for anything resulting from +use of the contributed software. *** RUN AT YOUR OWN RISK *** + + +FILE NAMES + +All file names consist of the name of the tool, the version number, and one or +more extensions. The extensions identify what type of information is contained +in the file, and what format it is in. For example, here is a list of files in +the /Mac/DataScope directory: + + DataScope2.0.1.asc.tar.Z + DataScope2.0.1.src.sit.hqx + DataScope2.0.1.smp.sit.hqx + DataScope2.0.1.mac.sit.hqx + DataScope2.0.1.msw.sit.hqx + +The first three character extension indicates what type of data can be found in +that file (ASCII documentation, source, samples, etc.). The other extensions +indicate what format the files are in. The extensions ".tar" and ".sit" +indicate types of archives, and the ".Z" and ".hqx" indicate compression and +encoding schemes. (See below for instructions on extracting files that have +been archived and/or compressed.) Following are a list of extensions and their +meanings: + + .sn3 Sun 3 executables + .sn4 Sun 4 executables + .386 Sun 386i executables + .sgi Silicon Graphics Iris executables + .dgl Silicon Graphics Iris using DGL executables + .rs6 IBM RS6000 executables + .cv2 Convex 2 executables + .cv3 Convex 3 executables + .cr2 Cray 2 executables + .crY CrayYMP executables + .d31 DEC 3100 executables + .m88 Motorola 88k executables + .m68 Motorola 68k executables + .exe IBM PC executables + .mac Macintosh executables + .src source code + .smp sample files + .asc ASCII text documentation + .msw Microsoft Word documentation + .ps postscript documentation + .man formatted man page + .shar Bourne shell archive + .sit archive created by Macintosh application, StuffIt + .hqx encoded with Macintosh application, BinHex + .sea Self extracting Macintosh archive + .tar archive created with UNIX tar command + .Z compressed with UNIX compress command + +The files in the PC directory are the only exception to this naming convention. +In order to conform with the DOS convention of eight character file names and +one, three character extension, the names for PC files are slightly different. +Whenever possible the scheme outlined above is used, but the names are usually +abbreviated and all but one of the dots "." have been omitted. + + +_______________________________________________________________________________ +EXTRACTING ARCHIVED FILES + + +INSTRUCTIONS FOR MACINTOSH FILES + +If a file ends with the extension ".sit" it must be unstuffed with either the +shareware program StuffIt or the Public Domain program UnStuffIt. Files ending +with the ".hqx" must be decoded with BinHex. These programs can be found on +the FTP server in the /Mac/Utilities directory. Note that the BinHex program +must be downloaded with MacBinary enabled, and the StuffIt program must be +decoded before it can be used. Files downloaded from the server may be both +Stuffed (".sit" extension) and BinHexed (".hqx" extension). These files must +be first decoded and then unstuffed. + +To decode a file with the ".hqx" extension (a BinHexed file): + + 1. Download the file to your Macintosh. + 2. Start the application BinHex by double-clicking on it. + 3. From the "File" menu in BinHex, choose "UpLoad -> Application". + 4. Choose the ".hqx" file to be decoded and select "Open". + 5. The suggested file name will appear in a dialog box. + 6. Select "Save" to decode the file. + +To uncompress a file with the ".sit" extension (a Stuffed file): + + 1. Download the file to your Macintosh. + 2. Start the application Stuffit by double-clicking on it. + 3. From the "File" menu in Stuffit, choose "Open Archive...". + 4. Choose the ".sit" file to be unstuffed and select "Open". A window with + all the files contained in the stuffed file will appear. + 5. Choose "Select All" in the "Edit" menu to select all of the files. + 6. Click on the "Extract" box at the bottom of the window. + 7. Select "Save All" in the dialog box to save all the selected files in + the current directory. + + +INSTRUCTIONS FOR PC FILES + +Most IBM PC files are archived and compressed using the pkzip utility. +(If you do not have the pkzip utility on your PC, you may obtain it from the +FTP server by anonymous ftp. The file you need is called pkz110.exe and it +is located in /PC/Telnet/contributions. Set the ftp mode to binary and "get" +the file pkz110.exe. Then, on your PC, run PKZ110.EXE with no arguments and +several files will be self-extracted, including one called PKUNZIP.EXE. It +may then be convenient to copy PKUNZIP.EXE to the directory where you have +placed, or are going to place, your Telnet files.) +To extract these files, first download the file with the ".zip" extension to +your PC and then type the following at the DOS prompt: + + > pkunzip -d filename.zip + +where "filename" is the name of the file you want to unarchive. + + +INSTRUCTIONS FOR UNIX FILES + +Most files on the FTP server will be both tarred and compressed. For more +information on the "tar" and "compress" commands you can type "man tar" and +"man compress" at your shell prompt to see the online manual page for these +commands, or ask your system administrator for help. You should first +uncompress and then unarchive files ending in ".tar.Z" with the following +procedure. + +Files with the ".Z" extension have been compressed with the UNIX "compress" +command. To uncompress these files type the following at the shell prompt: + + % uncompress filename.Z + +where "filename.Z" is the name of the file ending with the ".Z" extension that +you wish to uncompress. + +Files with the ".tar" extension have been archived with the UNIX "tar" command. +To extract the files type the following at the shell prompt: + + % tar xf filename.tar + +Some files are archived using a shell archive utility and are indicated as such +with the ".shar" extension. To extract the files type the following at the +shell prompt: + + % sh filename.shar + + +_______________________________________________________________________________ +DOCUMENTATION + +NCSA offers users several documentation formats for its programs including +ASCII text, Microsoft Word, and postscript. If one of these formats does not +fit your needs, documentaion can be obtained through the mail at the following +address: + +Documentation Orders +c/o Debbie Shirley +152 Computing Applications Building +605 East Springfield Avenue +Champaign, IL 61820 + +or call: + +(217) 244-4130 + +Members of the Software Development Group within NCSA are currently working +on videotapes that demonstrate and also offer tutorials for NCSA programs. A +note will be posted here when these tapes are available for distribution. + + +ASCII FORMAT + +ASCII text files are provided for all software and are indicated with the +".asc" extension. Helpful figures and diagrams obviously cannot be included +in this form of documentation. We suggest you use the other forms of +documentation if possible. + + +MICROSOFT WORD FORMAT + +If you are a Macintosh user, please download documents with the ".msw" +extension. These files should also be stuffed and BinHexed (information on +extracting these files from the archive is contained earlier in this file). +The documents can be previewed and printed using the Microsoft Word +application. Word documents contain text, images, and formatting. + + +POSTSCRIPT FORMAT + +If you are a UNIX user and/or have access to a postscript printer, please +download files with the ".pos" extension. The documents can be previewed using +a poscript previewer or can be printed directly to a poscript printer using a +command like "lpr". + + +_______________________________________________________________________________ +BUG REPORTS AND SUPPORT + +The Software Development Group at NCSA is very interested in how the software +tools developed here are being used. Please send any comments or suggestions +you may have to the appropriate address. + +NOTE: This is a new kind of shareware. You share your science and +successes with us, and we can get more resources to share more +NCSA software with you. + +If you want to see more NCSA software, please send us a letter, + email or US Mail, telling us what you are doing with our software. +We need to know: + + (1) What science you are working on - an abstract of your + work would be fine. + + (2) How NCSA software has helped you, for example, by increasing + your productivity or allowing you to do things you could + not do before. + +We encourage you to cite the use of any NCSA software you have used in +your publications. A bibliography of your work would be extremely +helpful. + + +NCSA Telnet for the Macintosh: Please allow ***time*** for a response. + +Bug reports, questions, suggestions may be sent to the addresses below. + + mactelnet@ncsa.uiuc.edu (Internet) + +NCSA Telnet for PCs: Please allow ***time*** for a response. + +Bug reports, questions, suggestions may be sent to: + pctelnet@ncsa.uiuc.edu (Internet) + +All other NCSA software: + +Bug reports should be emailed to the adresses below. Be sure to check the +BUGS NOTES section of the README file before sending email. +Please allow ***time*** for a response. + + bugs@ncsa.uiuc.edu (Internet) + + +Questions regarding NCSA developed software tools may be sent to the address +below. Please allow ***time*** for a response. + + softdev@ncsa.uiuc.edu (Internet) +_______________________________________________________________________________ +COPYRIGHTS AND TRADEMARKS + +Apple +Motorola +Digital Equipment Corp. +Silicon Graphics Inc. +International Business Machines +Sun Microsystems +UNIX +StuffIt +Microsoft diff --git a/testing/btest/scripts/base/files/extract/limit.bro b/testing/btest/scripts/base/files/extract/limit.bro new file mode 100644 index 0000000000..3a2271e361 --- /dev/null +++ b/testing/btest/scripts/base/files/extract/limit.bro @@ -0,0 +1,44 @@ +# @TEST-EXEC: bro -b -r $TRACES/ftp/retr.trace %INPUT max_extract=3000 efname=1 +# @TEST-EXEC: btest-diff extract_files/1 +# @TEST-EXEC: btest-diff 1.out +# @TEST-EXEC: bro -b -r $TRACES/ftp/retr.trace %INPUT max_extract=3000 efname=2 double_it=T +# @TEST-EXEC: btest-diff extract_files/2 +# @TEST-EXEC: btest-diff 2.out +# @TEST-EXEC: bro -b -r $TRACES/ftp/retr.trace %INPUT max_extract=7000 efname=3 unlimit_it=T +# @TEST-EXEC: btest-diff extract_files/3 +# @TEST-EXEC: btest-diff 3.out + +@load base/files/extract +@load base/protocols/ftp + +global outfile: file; +const max_extract: count = 0 &redef; +const double_it: bool = F &redef; +const unlimit_it: bool = F &redef; +const efname: string = "0" &redef; +global doubled: bool = F; + +event file_new(f: fa_file) + { + Files::add_analyzer(f, Files::ANALYZER_EXTRACT, + [$extract_filename=efname, $extract_limit=max_extract]); + } + +event file_extraction_limit(f: fa_file, args: any, limit: count, offset: count, len: count) + { + print outfile, "file_extraction_limit", limit, offset, len; + + if ( double_it && ! doubled ) + { + doubled = T; + print outfile, FileExtract::set_limit(f, args, max_extract*2); + } + + if ( unlimit_it ) + print outfile, FileExtract::set_limit(f, args, 0); + } + +event bro_init() + { + outfile = open(fmt("%s.out", efname)); + } From 814d827c44043a01f65ed7d6f52f9b635471c6dc Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 22 Aug 2013 17:03:50 -0500 Subject: [PATCH 251/881] Use macros to create file analyzer plugin classes. --- .../analyzer/data_event/Plugin.cc | 26 +++----------- src/file_analysis/analyzer/extract/Plugin.cc | 33 ++++------------- src/file_analysis/analyzer/hash/Plugin.cc | 36 ++++--------------- src/file_analysis/analyzer/unified2/Plugin.cc | 35 ++++-------------- src/plugin/Macros.h | 14 ++++++++ 5 files changed, 37 insertions(+), 107 deletions(-) diff --git a/src/file_analysis/analyzer/data_event/Plugin.cc b/src/file_analysis/analyzer/data_event/Plugin.cc index 7eb637f3a5..c2812a9af9 100644 --- a/src/file_analysis/analyzer/data_event/Plugin.cc +++ b/src/file_analysis/analyzer/data_event/Plugin.cc @@ -1,26 +1,8 @@ #include "plugin/Plugin.h" -#include "file_analysis/Component.h" #include "DataEvent.h" -namespace plugin { namespace Bro_FileDataEvent { - -class Plugin : public plugin::Plugin { -protected: - void InitPreScript() - { - SetName("Bro::FileDataEvent"); - SetVersion(-1); - SetAPIVersion(BRO_PLUGIN_API_VERSION); - SetDynamicPlugin(false); - - SetDescription("Delivers file content via events"); - - AddComponent(new ::file_analysis::Component("DATA_EVENT", - ::file_analysis::DataEvent::Instantiate)); - } -}; - -Plugin __plugin; - -} } +BRO_PLUGIN_BEGIN(Bro, FileDataEvent) + BRO_PLUGIN_DESCRIPTION("Delivers file content via events"); + BRO_PLUGIN_FILE_ANALYZER("DATA_EVENT", DataEvent); +BRO_PLUGIN_END diff --git a/src/file_analysis/analyzer/extract/Plugin.cc b/src/file_analysis/analyzer/extract/Plugin.cc index 39a8fad95f..599301188e 100644 --- a/src/file_analysis/analyzer/extract/Plugin.cc +++ b/src/file_analysis/analyzer/extract/Plugin.cc @@ -1,31 +1,10 @@ #include "plugin/Plugin.h" -#include "file_analysis/Component.h" #include "Extract.h" -namespace plugin { namespace Bro_FileExtract { - -class Plugin : public plugin::Plugin { -protected: - void InitPreScript() - { - SetName("Bro::FileExtract"); - SetVersion(-1); - SetAPIVersion(BRO_PLUGIN_API_VERSION); - SetDynamicPlugin(false); - - SetDescription("Extract file content to local file system"); - - AddComponent(new ::file_analysis::Component("EXTRACT", - ::file_analysis::Extract::Instantiate)); - - extern std::list > __bif_events_init(); - AddBifInitFunction(&__bif_events_init); - extern std::list > __bif_functions_init(); - AddBifInitFunction(&__bif_functions_init); - } -}; - -Plugin __plugin; - -} } +BRO_PLUGIN_BEGIN(Bro, FileExtract) + BRO_PLUGIN_DESCRIPTION("Extract file content to local file system"); + BRO_PLUGIN_FILE_ANALYZER("EXTRACT", Extract); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(functions); +BRO_PLUGIN_END diff --git a/src/file_analysis/analyzer/hash/Plugin.cc b/src/file_analysis/analyzer/hash/Plugin.cc index 1a7254105e..29453c0bfb 100644 --- a/src/file_analysis/analyzer/hash/Plugin.cc +++ b/src/file_analysis/analyzer/hash/Plugin.cc @@ -1,33 +1,11 @@ #include "plugin/Plugin.h" -#include "file_analysis/Component.h" #include "Hash.h" -namespace plugin { namespace Bro_FileHash { - -class Plugin : public plugin::Plugin { -protected: - void InitPreScript() - { - SetName("Bro::FileHash"); - SetVersion(-1); - SetAPIVersion(BRO_PLUGIN_API_VERSION); - SetDynamicPlugin(false); - - SetDescription("Hash file content"); - - AddComponent(new ::file_analysis::Component("MD5", - ::file_analysis::MD5::Instantiate)); - AddComponent(new ::file_analysis::Component("SHA1", - ::file_analysis::SHA1::Instantiate)); - AddComponent(new ::file_analysis::Component("SHA256", - ::file_analysis::SHA256::Instantiate)); - - extern std::list > __bif_events_init(); - AddBifInitFunction(&__bif_events_init); - } -}; - -Plugin __plugin; - -} } +BRO_PLUGIN_BEGIN(Bro, FileHash) + BRO_PLUGIN_DESCRIPTION("Hash file content"); + BRO_PLUGIN_FILE_ANALYZER("MD5", MD5); + BRO_PLUGIN_FILE_ANALYZER("SHA1", SHA1); + BRO_PLUGIN_FILE_ANALYZER("SHA256", SHA256); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/file_analysis/analyzer/unified2/Plugin.cc b/src/file_analysis/analyzer/unified2/Plugin.cc index 130ed89ce9..e94168eae1 100644 --- a/src/file_analysis/analyzer/unified2/Plugin.cc +++ b/src/file_analysis/analyzer/unified2/Plugin.cc @@ -2,34 +2,11 @@ #include "plugin/Plugin.h" -#include "file_analysis/Component.h" - #include "Unified2.h" -namespace plugin { namespace Bro_Unified2 { - -class Plugin : public plugin::Plugin { -protected: - void InitPreScript() - { - SetName("Bro::Unified2"); - SetVersion(-1); - SetAPIVersion(BRO_PLUGIN_API_VERSION); - SetDynamicPlugin(false); - - SetDescription("Analyze Unified2 alert files."); - - AddComponent(new ::file_analysis::Component("UNIFIED2", - ::file_analysis::Unified2::Instantiate)); - - extern std::list > __bif_events_init(); - AddBifInitFunction(&__bif_events_init); - - extern std::list > __bif_types_init(); - AddBifInitFunction(&__bif_types_init); - } -}; - -Plugin __plugin; - -} } +BRO_PLUGIN_BEGIN(Bro, Unified2) + BRO_PLUGIN_DESCRIPTION("Analyze Unified2 alert files."); + BRO_PLUGIN_FILE_ANALYZER("UNIFIED2", Unified2); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(types); +BRO_PLUGIN_END diff --git a/src/plugin/Macros.h b/src/plugin/Macros.h index f5c1a41cfa..9362642e91 100644 --- a/src/plugin/Macros.h +++ b/src/plugin/Macros.h @@ -9,6 +9,7 @@ #define PLUGIN_MACROS_H #include "analyzer/Component.h" +#include "file_analysis/Component.h" /** * The current plugin API version. Plugins that won't match this version will @@ -91,6 +92,19 @@ #define BRO_PLUGIN_ANALYZER(tag, cls) \ AddComponent(new ::analyzer::Component(tag, ::analyzer::cls::InstantiateAnalyzer)); +/** + * Defines a component implementing a file analyzer. + * + * @param tag A string with the analyzer's tag. This must be unique across + * all loaded analyzers and will translate into a corresponding \c ANALYZER_* + * constant at the script-layer. + * + * @param cls The class that implements the analyzer. It must be derived + * (directly or indirectly) from file_analysis::Analyzer. + */ +#define BRO_PLUGIN_FILE_ANALYZER(tag, cls) \ + AddComponent(new ::file_analysis::Component(tag, ::file_analysis::cls::Instantiate)); + /** * Defines a component implementing a protocol analyzer class that will * not be instantiated dynamically. This is for two use-cases: (1) abstract From 399899c49be4e8278885274e5e758080b8ef7a6f Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 22 Aug 2013 15:55:44 -0700 Subject: [PATCH 252/881] Pass over the Using Bro section. I edited the text little bit, reorganized the structure somewhat and extended some parts. I've also simplified the tests a bit, using some of the BTest tweaks commited in parallel. --- aux/btest | 2 +- doc/frameworks/logging.rst | 2 + doc/using/index.rst | 295 +++++++++++------- .../btest-doc.sphinx.using_bro#1 | 19 ++ .../btest-doc.sphinx.using_bro#2 | 15 + .../btest-doc.sphinx.using_bro#3 | 15 + .../btest-doc.sphinx.using_bro#4 | 10 + .../btest-doc.sphinx.using_bro#5 | 10 + .../btest-doc.sphinx.using_bro#6 | 10 + .../btest-doc.sphinx.using_bro#7 | 9 + .../btest-doc.sphinx.using_bro#8 | 6 + testing/btest/btest.cfg | 5 +- testing/btest/doc/sphinx/test.btest | 3 - testing/btest/doc/sphinx/using_bro.btest | 1 + testing/btest/doc/sphinx/using_bro.btest#2 | 1 + testing/btest/doc/sphinx/using_bro.btest#3 | 1 + testing/btest/doc/sphinx/using_bro.btest#4 | 1 + testing/btest/doc/sphinx/using_bro.btest#5 | 1 + testing/btest/doc/sphinx/using_bro.btest#6 | 1 + testing/btest/doc/sphinx/using_bro.btest#7 | 1 + testing/btest/doc/sphinx/using_bro.btest#8 | 1 + testing/scripts/diff-remove-timestamps | 2 +- testing/scripts/rst-filter | 5 + 23 files changed, 296 insertions(+), 120 deletions(-) create mode 100644 testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 create mode 100644 testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 create mode 100644 testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 create mode 100644 testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 create mode 100644 testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 create mode 100644 testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 create mode 100644 testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 create mode 100644 testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 delete mode 100644 testing/btest/doc/sphinx/test.btest create mode 100644 testing/btest/doc/sphinx/using_bro.btest create mode 100644 testing/btest/doc/sphinx/using_bro.btest#2 create mode 100644 testing/btest/doc/sphinx/using_bro.btest#3 create mode 100644 testing/btest/doc/sphinx/using_bro.btest#4 create mode 100644 testing/btest/doc/sphinx/using_bro.btest#5 create mode 100644 testing/btest/doc/sphinx/using_bro.btest#6 create mode 100644 testing/btest/doc/sphinx/using_bro.btest#7 create mode 100644 testing/btest/doc/sphinx/using_bro.btest#8 create mode 100755 testing/scripts/rst-filter diff --git a/aux/btest b/aux/btest index 69606f8f3c..063b055621 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 69606f8f3cc84d694ca1da14868a5fecd4abbc96 +Subproject commit 063b05562172c9cae160cf8df899afe366d1b108 diff --git a/doc/frameworks/logging.rst b/doc/frameworks/logging.rst index 06935647d3..9c8df62043 100644 --- a/doc/frameworks/logging.rst +++ b/doc/frameworks/logging.rst @@ -1,4 +1,6 @@ +.. _framework-logging: + ================= Logging Framework ================= diff --git a/doc/using/index.rst b/doc/using/index.rst index df2b48bf48..c9226fadd2 100644 --- a/doc/using/index.rst +++ b/doc/using/index.rst @@ -5,97 +5,155 @@ Using Bro ========= +.. contents:: + Once Bro has been deployed in an environment and monitoring live traffic, it will, in its default configuration, begin to produce -human-readable ASCII logs. Each log file, produced by Bro's Logging -Framework, is populated with organized, connection-oriented data. As -the log files are simple ASCII data, working with the data contained -in them can be done from a command line terminal once you have been -familiarized with the types of data that can be found in each log -file. +human-readable ASCII logs. Each log file, produced by Bro's +:ref:`framework-logging`, is populated with organized, mostly +connection-oriented data. As the standard log files are simple ASCII +data, working with the data contained in them can be done from a +command line terminal once you have been familiarized with the types +of data that can be found in each file. In the following, we work +through the logs general structure and then examine some standard ways +of working with them. ---------------------- -Structure of Log Files +Working with Log Files ---------------------- -The log files produced by Bro adhere to a structure as defined by the -scripts that produced through which they were produced. However, as -each log file has been produced using the Logging Framework, there are -similarities shared by each log file. Without breaking into the -scripting aspect of Bro, a bird's eye view of how the log files are -produced would progress as follows. The script's author defines the -kinds of data, such as the originating IP address or the duration of a -connection, which will be used as fields in the log file. The author -then decides what behavior should generate a log file entry, these -behaviors can range from a connection having been completed or an HTTP -GET method being issued by an originator. Once these behaviors have -been observed, the data is passed to the Logging Framework which, in -turn, adds an entry to the appropriate log file. While the fields of -the log entries can be modified by the user, the Logging Framework -makes use of a header entry in each log file to ensure that it remains -self-describing. This header entry can be see by running the unix -utility ``head`` and outputting the first eight lines of the file. +Generally, all of Bro's log files are produced by a corresponding +script that defines their individual structure. However, as each log +file flows through the Logging Framework, there share a set of +structural similarities. Without breaking into the scripting aspect of +Bro here, a bird's eye view of how the log files are produced would +progress as follows. The script's author defines the kinds of data, +such as the originating IP address or the duration of a connection, +which will make up the fields (i.e., columns) of the log file. The +author then decides what network activity should generate a single log +file entry (i.e., one line); that could, e.g., be a connection having +been completed or an HTTP ``GET`` method being issued by an +originator. When these behaviors are observed during operation, the +data is passed to the Logging Framework which, in turn, adds the entry +to the appropriate log file. -.. btest:: using_bro_cmd_line_01 +As the fields of the log entries can be further customized by the +user, the Logging Framework makes use of a header block to ensure that +it remains self-describing. This header entry can be see by running +the Unix utility ``head`` and outputting the first lines of the file: + +.. btest:: using_bro - @TEST-EXEC: btest-rst-cmd head -8 ${TESTBASE}/Baseline/core.pppoe/conn.log + @TEST-EXEC: btest-rst-cmd "bro -r $TRACES/wikipedia.trace && head -15 conn.log" -The sample above shows the header for a ``conn.log`` file which gives -a detailed account of each connection as seen by Bro. As you can see, -header includes information such as what separators are being used for +As you can see, the header consists of lines prefixed by ``#`` and +includes information such as what separators are being used for various types of data, what an empty field looks like and what an unset field looks like. In this example, the default TAB separator is -being used as the delimiter between fiends (\x09 is the tab character -in hex). It also lists the comma as the separator for set data, the -string "(empty)" as the indicator for an empty field and the '-' -character as the indicator for a field that hasn't been set. The -timestamp for when the file was created is included under "#open". -The header then goes on to detail the fields being listed in the file -and the data types of those fields in #fields and #types respectively. -These two entries are often the two most significant points of -interest as they detail not only the field name but the data type -used. Navigating through the different log files produced by Bro, -often requires the use of different elements of the unix tool chain -such as ``sed``, ``awk``, or ``grep`` and having the field definitions -readily available will save the user some mental leg work. The field -names are also a key resource for using the ``bro-cut`` utility -included with Bro. +being used as the delimiter between fields (``\x09`` is the tab +character in hex). It also lists the comma as the separator for set +data, the string ``(empty)`` as the indicator for an empty field and +the ``-`` character as the indicator for a field that hasn't been set. +The timestamp for when the file was created is included under +``#open``. The header then goes on to detail the fields being listed +in the file and the data types of those fields in ``#fields`` and +``#types``, respectively. These two entries are often the two most +significant points of interest as they detail not only the field names +but the data types used. When navigating through the different log +files with tools like ``sed``, ``awk``, or ``grep``, having the field +definitions readily available saves the user some mental leg work. The +field names are also a key resource for using the :ref:`bro-cut +` utility included with Bro, see below. -------------- -Using bro-cut -------------- +Next to the header follows the main content; in this example we see 7 +connections with their key properties, such as originator and +responder IP addresses (note how Bro transparely handles both IPv4 and +IPv6), transport-layer ports, application-layer services - the +``service`` field is filled ias Bro determines a specific protocol to +be in use, independent of the connection's ports - payload size, and +more. See :bro:type:`Conn::Info` for a description of all fields. + +In addition to ``conn.log``, Bro generates many further logs by +default, including: + +``dpd.log`` + A summary of protocols encountered on non-standard ports. + +``dns.log`` + All DNS activity. + +``ftp.log`` + A log of FTP session-level activity. + +``files.log`` + Summaries of files transfered over the network. This information + is aggregrated from different protocols, including HTTP, FTP, and + SMTP. + +``http.log`` + A summary of all HTTP requests with their replies. + +``known_certs.log`` + SSL certificates seen in use. + +``smtp.log`` + A summary of SMTP activity. + +``ssl.log`` + A record of SSL sessions, including certificates being used. + +``weird.log`` + A log of unexpected protocol-level activity. Whenever Bro's + protocol analysis encounters a situation it would not expect + (e.g., an RFC violation) is logs it in this file. Note that in + practice, real-world networks tend to exhibit a large number of + such "crud" that is usually not worth following up on. + +As you can see, some log files are specific to a particular protocol, +while others aggregate information across different types of activity. + +.. _bro-cut: + +Using ``bro-cut`` +----------------- The ``bro-cut`` utility can be used in place of other tools to build terminal commands that remain flexible and accurate independent of -possible changes that can be made to the log file itself. It -accomplishes this by parsing the header in each file and allowing the -user to refer to the specific columnar data available. In contrast -tools like ``awk`` require the user to refer to fields referenced by -their position. For example, the two commands listed below produce -the same output given a default configuration of Bro. +possible changes to log file itself. It accomplishes this by parsing +the header in each file and allowing the user to refer to the specific +columnar data available (in contrast to tools like ``awk`` that +require the user to refer to fields referenced by their position). +For example, the following command extracts just the given columns +from a ``conn.log``: -.. btest:: using_bro_bro_cut_01 +.. btest:: using_bro - @TEST-EXEC: btest-rst-cmd awk \'{print \$3, \$4, \$5, \$6, \$9}\' ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/conn.log + @TEST-EXEC: btest-rst-cmd -n 10 "cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration" -.. btest:: using_bro_bro_cut_02 +The correspding ``awk`` command would look like this: - @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/conn.log | btest-rst-cmd -c "cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration " bro-cut id.orig_h id.orig_p id.resp_h duration +.. btest:: using_bro + @TEST-EXEC: btest-rst-cmd -n 10 awk \'/^[^#]/ {print \$3, \$4, \$5, \$6, \$9}\' conn.log -While the output is similar, the advantages to using bro-cut over awk -lay in that, while awk is flexible and powerful, ``bro-cut`` was -specifically designed to work with log files. Firstly, the +While the output is similar, the advantages to using bro-cut over +``awk`` lay in that, while ``awk`` is flexible and powerful, ``bro-cut`` +was specifically designed to work with Bro's log files. Firstly, the ``bro-cut`` output includes only the log file entries, while the -``awk`` output includes the header parts of the log file, which would -require the user to use a secondary utility to suppress those lines. -Secondly, since ``bro-cut`` uses the field descriptors to identify and -extract data, it allows for flexibility independent of the format and -contents of the log file. It's not uncommon for a Bro configuration -to add extra fields to various log files as required by the -environment. In this case, the fields in the ``awk`` command would -have to be altered to compensate for the new position whereas the -``bro-cut`` output would not change. +``awk`` solution needs to skip the header manually. Secondly, since +``bro-cut`` uses the field descriptors to identify and extract data, +it allows for flexibility independent of the format and contents of +the log file. It's not uncommon for a Bro configuration to add extra +fields to various log files as required by the environment. In this +case, the fields in the ``awk`` command would have to be altered to +compensate for the new position whereas the ``bro-cut`` output would +not change. + +.. note:: + + The sequence of field names given to ``bro-cut`` determines the + output order, which means you can also use ``bro-cut`` to reorder + fields. That can be helpful when piping into, e.g., ``sort``. As you may have noticed, the command for ``bro-cut`` uses the output redirection through the ``cat`` command and ``|`` operator. Whereas @@ -104,51 +162,60 @@ line option, bro-cut only takes input through redirection such as ``|`` and ``<``. There are a couple of ways to direct log file data into ``bro-cut``, each dependent upon the type of log file you're processing. A caveat of its use, however, is that the 8 lines of -header data must be present. In its default setup, Bro will rotate -log files on an hourly basis, moving the current log file into a -directory with format ``YYYY-MM-DD`` and gzip compressing the file -with a file format that includes the log file type and time range of -the file. In the case of processing a compressed log file you simply -adjust your command line tools to use the complementary z* versions of -commands such as cat (``zcat``), ``grep`` (``zgrep``), and ``head`` -(``zhead``). +header data must be present. -....................... -Working with timestamps -....................... +.. note:: -The ``bro-cut`` accepts the flag ``-d`` to convert the epoch time -values in the log files to human-readable format. The following -command includes the human readable time stamp, the unique identifier -and the HTTP host and HTTP uri as parsed from the ``http.log`` file. + ``bro-cut`` provides an option ``-c`` to include a corresponding + format header into the output, which allows to chain multiple + ``bro-cut`` instances or perform further post-processing that + evaluates the header information. -.. btest:: using_bro_bro_cut_time_01 +In its default setup, Bro will rotate log files on an hourly basis, +moving the current log file into a directory with format +``YYYY-MM-DD`` and gzip compressing the file with a file format that +includes the log file type and time range of the file. In the case of +processing a compressed log file you simply adjust your command line +tools to use the complementary ``z*`` versions of commands such as cat +(``zcat``), ``grep`` (``zgrep``), and ``head`` (``zhead``). - @TEST-EXEC: btest-rst-cmd -c "bro-cut -d ts uid host uri < http.log" bro-cut -d ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log +Working with Timestamps +----------------------- + +``bro-cut`` accepts the flag ``-d`` to convert the epoch time values +in the log files to human-readable format. The following command +includes the human readable time stamp, the unique identifier and the +HTTP ``Host`` and HTTP ``URI`` as extracted from the ``http.log`` +file: + +.. btest:: using_bro + + @TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -d ts uid host uri < http.log" Often times log files from multiple sources are stored in UTC time to allow easy correlation. Converting the timestamp from a log file to -UTC can be accomplished with the ``-u`` command. +UTC can be accomplished with the ``-u`` option: -.. btest:: using_bro_bro_cut_time_02 +.. btest:: using_bro - @TEST-EXEC: btest-rst-cmd -c "bro-cut -u ts uid host uri < http.log" bro-cut -u ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log + @TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -u ts uid host uri < http.log" The default time format when using the ``-d`` or ``-u`` is the -``strftime`` format string %Y-%m-%dT%H:%M:%S%z which results in a +``strftime`` format string ``%Y-%m-%dT%H:%M:%S%z`` which results in a string with year, month, day of month, followed by hour, minutes, -seconds and the timezone offset. The default ``strftime`` can be -altered by using the ``-D`` and ``-U`` flags. For example, to format -the timestamp in the US-typical "Middle Endian" you could use a format -string of: %d-%m-%YT%H:%M:%S%z +seconds and the timezone offset. The default format can be altered by +using the ``-D`` and ``-U`` flags, using the standard ``strftime`` +syntax. For example, to format the timestamp in the US-typical "Middle +Endian" you could use a format string of: ``%d-%m-%YT%H:%M:%S%z`` -.. btest:: using_bro_bro_cut_time_03 +.. btest:: using_bro - @TEST-EXEC: btest-rst-cmd -c "bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log" bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_01/http.log + @TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log" ----------------------- -Working with Log Files ----------------------- +See ``man strfime`` for more options for the format string. + +Using UIDs +---------- While Bro can do signature based analysis, its primary focus is on behavioral detection which alters the practice of log review from @@ -156,8 +223,8 @@ behavioral detection which alters the practice of log review from trip. A common progression of review includes correlating a session across multiple log files. As a connection is processed by Bro, a unique identifier is assigned to each session. This unique identifier -is almost always included in any log file entry specific to that -connection and can be used to cross-reference log files. +is generally included in any log file entry associated with that +connection and can be used to cross-reference different log files. A simple example would be to cross-reference a UID seen in a ``conn.log`` file. Here, we're looking for the connection with the @@ -165,19 +232,21 @@ largest number of bytes from the responder by redirecting the output for ``cat conn.log`` into bro-cut to extract the UID and the resp_bytes, then sorting that output by the resp_bytes field. -.. btest:: using_bro_practical_02 +.. btest:: using_bro - @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_02/conn.log | bro-cut uid resp_bytes | btest-rst-cmd -c "cat conn.log | bro-cut uid resp_bytes | btest-rst-cmd sort -nrk2" sort -nrk2 - -With the UID of the largest response, it can be crossreferenced with -the UIDs in the ``http.log`` file. + @TEST-EXEC: btest-rst-cmd "cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5" -.. btest:: using_bro_practical_03 +Taking the UID of the first of the top responses, we can now +crossreference that with the UIDs in the ``http.log`` file. - @TEST-EXEC: cat ${TESTBASE}/Baseline/doc.manual.using_bro_sandbox_02/http.log | bro-cut uid id.resp_h method status_code host uri | btest-rst-cmd -c "cat http.log | bro-cut uid id.resp_h method status_code host uri | grep j4u32Pc5bif" grep j4u32Pc5bif +.. btest:: using_bro + + @TEST-EXEC: btest-rst-cmd "cat http.log | bro-cut uid id.resp_h method status_code host uri | grep VW0XPVINV8a" + +As you can see there are two HTTP ``GET`` requests within the +session that Bro identified and logged. Given that HTTP is a stream +protocol, it can have multiple ``GET``/``POST``/etc requests in a +stream and Bro is able to extract and track that information for you, +giving you an in-depth and structured view into HTTP traffic on your +network. -As you can see there are multiple HTTP GET requests within the session -that Bro identified and logged. Given that HTTP is a stream protocol, -it can have multiple GET/POST/etc requests in a stream and Bro is able -to extract and track that information for you, giving you an in-depth -and structured view into HTTP traffic on your network. diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 new file mode 100644 index 0000000000..1512c0c8ef --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 @@ -0,0 +1,19 @@ +.. code-block:: none + + # bro -r wikipedia.trace && head -15 conn.log + #separator \x09 + #set_separator , + #empty_field (empty) + #unset_field - + #path conn + #open 2013-08-22-22-52-46 + #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents + #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] + 1300475167.096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 73 0 0 (empty) + 1300475167.097012 arKYeMETxOg fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp - - - - S0 - 0 D 1 199 0 0 (empty) + 1300475167.099816 k6kgXLOoSKl 141.142.220.50 5353 224.0.0.251 5353 udp - - - - S0 - 0 D 1 179 0 0 (empty) + 1300475168.853899 TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF - 0 Dd 1 66 1 117 (empty) + 1300475168.854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF - 0 Dd 1 80 1 127 (empty) + 1300475168.854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF - 0 Dd 1 66 1 211 (empty) + 1300475168.857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF - 0 Dd 1 66 1 117 (empty) + diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 new file mode 100644 index 0000000000..13ddfbb931 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 @@ -0,0 +1,15 @@ +.. code-block:: none + + # cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration + 141.142.220.202 5353 224.0.0.251 - + fe80::217:f2ff:fed7:cf65 5353 ff02::fb - + 141.142.220.50 5353 224.0.0.251 - + 141.142.220.118 43927 141.142.2.2 0.000435 + 141.142.220.118 37676 141.142.2.2 0.000420 + 141.142.220.118 40526 141.142.2.2 0.000392 + 141.142.220.118 32902 141.142.2.2 0.000317 + 141.142.220.118 59816 141.142.2.2 0.000343 + 141.142.220.118 59714 141.142.2.2 0.000375 + 141.142.220.118 58206 141.142.2.2 0.000339 + [...] + diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 new file mode 100644 index 0000000000..8a35312c44 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 @@ -0,0 +1,15 @@ +.. code-block:: none + + # awk '/^[^#]/ {print $3, $4, $5, $6, $9}' conn.log + 141.142.220.202 5353 224.0.0.251 5353 - + fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 - + 141.142.220.50 5353 224.0.0.251 5353 - + 141.142.220.118 43927 141.142.2.2 53 0.000435 + 141.142.220.118 37676 141.142.2.2 53 0.000420 + 141.142.220.118 40526 141.142.2.2 53 0.000392 + 141.142.220.118 32902 141.142.2.2 53 0.000317 + 141.142.220.118 59816 141.142.2.2 53 0.000343 + 141.142.220.118 59714 141.142.2.2 53 0.000375 + 141.142.220.118 58206 141.142.2.2 53 0.000339 + [...] + diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 new file mode 100644 index 0000000000..f171bab392 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 @@ -0,0 +1,10 @@ +.. code-block:: none + + # bro-cut -d ts uid host uri < http.log + 2011-03-18T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css + 2011-03-18T19:06:08+0000 VW0XPVINV8a upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png + 2011-03-18T19:06:08+0000 3PKsZ2Uye21 upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png + 2011-03-18T19:06:08+0000 GSxOnSLghOa upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png + 2011-03-18T19:06:08+0000 Tw8jXtpTGu6 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png + [...] + diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 new file mode 100644 index 0000000000..491930cbc1 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 @@ -0,0 +1,10 @@ +.. code-block:: none + + # bro-cut -u ts uid host uri < http.log + 2011-03-18T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css + 2011-03-18T19:06:08+0000 VW0XPVINV8a upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png + 2011-03-18T19:06:08+0000 3PKsZ2Uye21 upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png + 2011-03-18T19:06:08+0000 GSxOnSLghOa upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png + 2011-03-18T19:06:08+0000 Tw8jXtpTGu6 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png + [...] + diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 new file mode 100644 index 0000000000..a2b2316257 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 @@ -0,0 +1,10 @@ +.. code-block:: none + + # bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log + 18-03-2011T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css + 18-03-2011T19:06:08+0000 VW0XPVINV8a upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png + 18-03-2011T19:06:08+0000 3PKsZ2Uye21 upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png + 18-03-2011T19:06:08+0000 GSxOnSLghOa upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png + 18-03-2011T19:06:08+0000 Tw8jXtpTGu6 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png + [...] + diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 new file mode 100644 index 0000000000..bdbf0e20a0 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 @@ -0,0 +1,9 @@ +.. code-block:: none + + # cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5 + VW0XPVINV8a 734 + Tw8jXtpTGu6 734 + GSxOnSLghOa 734 + 0Q4FH8sESw5 734 + P654jzLoe3a 733 + diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 new file mode 100644 index 0000000000..67d0417de8 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 @@ -0,0 +1,6 @@ +.. code-block:: none + + # cat http.log | bro-cut uid id.resp_h method status_code host uri | grep VW0XPVINV8a + VW0XPVINV8a 208.80.152.3 GET 304 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png + VW0XPVINV8a 208.80.152.3 GET 304 upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png + diff --git a/testing/btest/btest.cfg b/testing/btest/btest.cfg index 3bfdea79d8..da0487f5ef 100644 --- a/testing/btest/btest.cfg +++ b/testing/btest/btest.cfg @@ -4,7 +4,7 @@ TmpDir = %(testbase)s/.tmp BaselineDir = %(testbase)s/Baseline IgnoreDirs = .svn CVS .tmp IgnoreFiles = *.tmp *.swp #* *.trace .DS_Store -Finalizer = btest-diff-rst +PartFinalizer = btest-diff-rst [environment] BROPATH=`bash -c %(testbase)s/../../build/bro-path-dev` @@ -18,6 +18,7 @@ TRACES=%(testbase)s/Traces SCRIPTS=%(testbase)s/../scripts DIST=%(testbase)s/../.. BUILD=%(testbase)s/../../build -TEST_DIFF_CANONIFIER=$SCRIPTS/diff-canonifier +TEST_DIFF_CANONIFIER=%(testbase)s/../scripts/diff-canonifier TMPDIR=%(testbase)s/.tmp BRO_PROFILER_FILE=%(testbase)s/.tmp/script-coverage.XXXXXX +BTEST_RST_FILTER=$SCRIPTS/rst-filter diff --git a/testing/btest/doc/sphinx/test.btest b/testing/btest/doc/sphinx/test.btest deleted file mode 100644 index f2f1bcff53..0000000000 --- a/testing/btest/doc/sphinx/test.btest +++ /dev/null @@ -1,3 +0,0 @@ -@TEST-COPY-FILE: ${TRACES}/wikipedia.trace -@TEST-EXEC: btest-rst-cmd bro -r wikipedia.trace -@TEST-EXEC: btest-rst-cmd "cat http.log | bro-cut ts id.orig_h | head -5" diff --git a/testing/btest/doc/sphinx/using_bro.btest b/testing/btest/doc/sphinx/using_bro.btest new file mode 100644 index 0000000000..3551104043 --- /dev/null +++ b/testing/btest/doc/sphinx/using_bro.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd "bro -r $TRACES/wikipedia.trace && head -15 conn.log" diff --git a/testing/btest/doc/sphinx/using_bro.btest#2 b/testing/btest/doc/sphinx/using_bro.btest#2 new file mode 100644 index 0000000000..afa29e6184 --- /dev/null +++ b/testing/btest/doc/sphinx/using_bro.btest#2 @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd -n 10 "cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration" diff --git a/testing/btest/doc/sphinx/using_bro.btest#3 b/testing/btest/doc/sphinx/using_bro.btest#3 new file mode 100644 index 0000000000..a3ce44357e --- /dev/null +++ b/testing/btest/doc/sphinx/using_bro.btest#3 @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd -n 10 awk \'/^[^#]/ {print \$3, \$4, \$5, \$6, \$9}\' conn.log diff --git a/testing/btest/doc/sphinx/using_bro.btest#4 b/testing/btest/doc/sphinx/using_bro.btest#4 new file mode 100644 index 0000000000..ce10bba56a --- /dev/null +++ b/testing/btest/doc/sphinx/using_bro.btest#4 @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -d ts uid host uri < http.log" diff --git a/testing/btest/doc/sphinx/using_bro.btest#5 b/testing/btest/doc/sphinx/using_bro.btest#5 new file mode 100644 index 0000000000..786aebffab --- /dev/null +++ b/testing/btest/doc/sphinx/using_bro.btest#5 @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -u ts uid host uri < http.log" diff --git a/testing/btest/doc/sphinx/using_bro.btest#6 b/testing/btest/doc/sphinx/using_bro.btest#6 new file mode 100644 index 0000000000..cc52531b9c --- /dev/null +++ b/testing/btest/doc/sphinx/using_bro.btest#6 @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log" diff --git a/testing/btest/doc/sphinx/using_bro.btest#7 b/testing/btest/doc/sphinx/using_bro.btest#7 new file mode 100644 index 0000000000..4662f67c88 --- /dev/null +++ b/testing/btest/doc/sphinx/using_bro.btest#7 @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd "cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5" diff --git a/testing/btest/doc/sphinx/using_bro.btest#8 b/testing/btest/doc/sphinx/using_bro.btest#8 new file mode 100644 index 0000000000..dfb7b3a715 --- /dev/null +++ b/testing/btest/doc/sphinx/using_bro.btest#8 @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd "cat http.log | bro-cut uid id.resp_h method status_code host uri | grep VW0XPVINV8a" diff --git a/testing/scripts/diff-remove-timestamps b/testing/scripts/diff-remove-timestamps index 138b901743..44422f6f55 100755 --- a/testing/scripts/diff-remove-timestamps +++ b/testing/scripts/diff-remove-timestamps @@ -11,4 +11,4 @@ fi # The first sed uses a "basic" regexp, the 2nd a "modern:. sed 's/[0-9]\{10\}\.[0-9]\{2,8\}/XXXXXXXXXX.XXXXXX/g' | \ -$sed 's/^#(open|close).(19|20)..-..-..-..-..-..$/#\1 XXXX-XX-XX-XX-XX-XX/g' +$sed 's/^ *#(open|close).(19|20)..-..-..-..-..-..$/#\1 XXXX-XX-XX-XX-XX-XX/g' diff --git a/testing/scripts/rst-filter b/testing/scripts/rst-filter new file mode 100755 index 0000000000..b06d5efd5e --- /dev/null +++ b/testing/scripts/rst-filter @@ -0,0 +1,5 @@ +# /usr/bin/env bash +# +# Filters the output of btest-rst-cmd. + +sed "s#${TRACES}/\{0,1\}##g" From 315aa9d2f59b71712972fac9c192156789f0c696 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 22 Aug 2013 16:33:11 -0700 Subject: [PATCH 253/881] Updating submodule(s). [nomail] --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 50d426ba09..35bb074c1c 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 50d426ba09adc6ae6127cce93d59057c0f09abb1 +Subproject commit 35bb074c1c5173e44689df680a24ba13fea39a11 From 1cf535dbbb5922b503212b9b976f87125b326768 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 22 Aug 2013 16:33:32 -0700 Subject: [PATCH 254/881] Updating submodule. --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 063b055621..35bb074c1c 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 063b05562172c9cae160cf8df899afe366d1b108 +Subproject commit 35bb074c1c5173e44689df680a24ba13fea39a11 From 17d0ecd388581d702c27a4eea259cc5bcc0ca465 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 23 Aug 2013 11:53:58 -0500 Subject: [PATCH 255/881] File extraction tweaks. - Default extraction limit of 100MB now provided via a tuning script loaded in local.bro so that command-line Bro is unlimited by default. - Extraction directory is now created on request of file extraction rather than unconditionally in bro_init(). --- doc/scripts/DocSourcesList.cmake | 1 + scripts/base/files/extract/main.bro | 8 +++----- scripts/policy/tuning/defaults/__load__.bro | 3 ++- scripts/policy/tuning/defaults/extracted_file_limits.bro | 4 ++++ scripts/test-all-policy.bro | 1 + 5 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 scripts/policy/tuning/defaults/extracted_file_limits.bro diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index 9137066337..cf82618377 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -266,6 +266,7 @@ rest_target(${psd} policy/protocols/ssl/extract-certs-pem.bro) rest_target(${psd} policy/protocols/ssl/known-certs.bro) rest_target(${psd} policy/protocols/ssl/notary.bro) rest_target(${psd} policy/protocols/ssl/validate-certs.bro) +rest_target(${psd} policy/tuning/defaults/extracted_file_limits.bro) rest_target(${psd} policy/tuning/defaults/packet-fragments.bro) rest_target(${psd} policy/tuning/defaults/warnings.bro) rest_target(${psd} policy/tuning/logs-to-elasticsearch.bro) diff --git a/scripts/base/files/extract/main.bro b/scripts/base/files/extract/main.bro index f9fb9df009..7030cac148 100644 --- a/scripts/base/files/extract/main.bro +++ b/scripts/base/files/extract/main.bro @@ -8,8 +8,8 @@ export { const prefix = "./extract_files/" &redef; ## The default max size for extracted files (they won't exceed this - ## number of bytes), 100MB. - const default_limit = 104857600; + ## number of bytes), unlimited. + const default_limit = 0 &redef; redef record Files::Info += { ## Local filenames of extracted file. @@ -54,12 +54,10 @@ function on_add(f: fa_file, args: Files::AnalyzerArgs) f$info$extracted = args$extract_filename; args$extract_filename = build_path_compressed(prefix, args$extract_filename); + mkdir(prefix); } event bro_init() &priority=10 { Files::register_analyzer_add_callback(Files::ANALYZER_EXTRACT, on_add); - - # Create the extraction directory. - mkdir(prefix); } diff --git a/scripts/policy/tuning/defaults/__load__.bro b/scripts/policy/tuning/defaults/__load__.bro index ffc760e5f7..fd52f92401 100644 --- a/scripts/policy/tuning/defaults/__load__.bro +++ b/scripts/policy/tuning/defaults/__load__.bro @@ -1,2 +1,3 @@ @load ./packet-fragments -@load ./warnings \ No newline at end of file +@load ./warnings +@load ./extracted_file_limits.bro diff --git a/scripts/policy/tuning/defaults/extracted_file_limits.bro b/scripts/policy/tuning/defaults/extracted_file_limits.bro new file mode 100644 index 0000000000..8e2731b99e --- /dev/null +++ b/scripts/policy/tuning/defaults/extracted_file_limits.bro @@ -0,0 +1,4 @@ +@load base/files/extract + +# 100 MB. +redef FileExtract::default_limit = 104857600; diff --git a/scripts/test-all-policy.bro b/scripts/test-all-policy.bro index 63b9b5998c..d6383af38b 100644 --- a/scripts/test-all-policy.bro +++ b/scripts/test-all-policy.bro @@ -89,6 +89,7 @@ @load protocols/ssl/validate-certs.bro @load tuning/__load__.bro @load tuning/defaults/__load__.bro +@load tuning/defaults/extracted_file_limits.bro @load tuning/defaults/packet-fragments.bro @load tuning/defaults/warnings.bro @load tuning/logs-to-elasticsearch.bro From 288ef20a4e8ae939238728ed4b1cb8c07b36eb5a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 23 Aug 2013 11:57:37 -0500 Subject: [PATCH 256/881] Fix wrong documentation for mkdir BIF. --- src/bro.bif | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bro.bif b/src/bro.bif index 68a8d5114c..e2a4ba62a9 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -3897,8 +3897,8 @@ function flush_all%(%): bool ## ## f: The directory name. ## -## Returns: Returns true if the operation succeeds, or false if the -## creation fails or if *f* exists already. +## Returns: Returns true if the operation succeeds or if *f* already exists, +## and false if the file creation fails. ## ## .. bro:see:: active_file open_for_append close write_file ## get_file_name set_buf flush_all enable_raw_output From 6dbbce8e0582db89c6a69148c73bf0e517f07cbc Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 23 Aug 2013 11:58:17 -0500 Subject: [PATCH 257/881] Remove code relict pointed out by Bernhard. The condition should never be true, it's leftover from my hacking/debugging code. --- src/input/readers/Raw.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/readers/Raw.cc b/src/input/readers/Raw.cc index 7e26f8d133..2a890eab4e 100644 --- a/src/input/readers/Raw.cc +++ b/src/input/readers/Raw.cc @@ -433,7 +433,7 @@ int64_t Raw::GetLine(FILE* arg_file) } - if ( errno == 0 || errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR ) + if ( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR ) return -2; else From 3e3ca1bb74808d76daf2df58775f04cab3848e3c Mon Sep 17 00:00:00 2001 From: Hui Lin Date: Fri, 23 Aug 2013 18:10:30 -0500 Subject: [PATCH 258/881] fixed number of object bug in dnp3-protocol pac; update two base test trases --- src/analyzer/protocol/dnp3/dnp3-protocol.pac | 8 +- .../coverage | 2 +- .../output | 1407 +---------------- .../coverage | 2 +- .../dnp3.log | 4 +- .../scripts.base.protocols.dnp3.events/output | 92 +- .../base/protocols/dnp3/dnp3_link_only.bro | 2 +- 7 files changed, 181 insertions(+), 1336 deletions(-) diff --git a/src/analyzer/protocol/dnp3/dnp3-protocol.pac b/src/analyzer/protocol/dnp3/dnp3-protocol.pac index 02fbd678cc..9407b000eb 100644 --- a/src/analyzer/protocol/dnp3/dnp3-protocol.pac +++ b/src/analyzer/protocol/dnp3/dnp3-protocol.pac @@ -112,10 +112,10 @@ type Request_Objects(function_code: uint8) = record { type Response_Objects(function_code: uint8) = record { object_header: Object_Header(function_code); data: case (object_header.object_type_field) of { - 0x0101 -> biwoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) ]; - 0x0301 -> diwoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) ]; - 0x0a01 -> bowoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) ]; - 0x0c03 -> bocmd_PM: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) ]; + 0x0101 -> biwoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) + 1 ]; + 0x0301 -> diwoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) + 1 ]; + 0x0a01 -> bowoflag: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) + 1 ]; + 0x0c03 -> bocmd_PM: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ ( object_header.number_of_item / 8 ) + 1 ]; default -> ojbects: Response_Data_Object(function_code, object_header.qualifier_field, object_header.object_type_field )[ object_header.number_of_item]; }; }; diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_link_only/coverage b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_link_only/coverage index afb1e836e7..e49a3133a9 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_link_only/coverage +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_link_only/coverage @@ -1 +1 @@ -6 of 51 events triggered by trace +7 of 51 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_link_only/output b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_link_only/output index 1462ae8fed..0ddd6632ba 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_link_only/output +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_link_only/output @@ -1,3 +1,6 @@ +dnp3_header_block, T, 25605, 11, 196, 1, 100 +dnp3_application_request_header, T, 1 +dnp3_object_header, T, 15361, 6, 0, 65535, 65535 dnp3_header_block, F, 25605, 255, 68, 100, 1 dnp3_application_response_header, F, 129, 5120 dnp3_object_header, F, 257, 1, 1024, 0, 1023 @@ -257,1860 +260,622 @@ dnp3_object_prefix, F, 0 dnp3_response_data_object, F, 0 dnp3_object_prefix, F, 0 dnp3_response_data_object, F, 0 -dnp3_object_header, F, 2562, 1, 512, 0, 511 dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 +dnp3_response_data_object, F, 10 +dnp3_object_header, F, 513, 0, 256, 0, 255 dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_prefix, F, 0 -dnp3_response_data_object, F, 1 -dnp3_object_header, F, 7685, 1, 276, 0, 275 -dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 1013547336 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 3108291338 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 3118098121 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 979783186 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 1013100050 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 976559429 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 1069427906 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 1114636174 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 982332387 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 987182644 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 3121874082 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 dnp3_response_data_object, F, 255 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 dnp3_object_prefix, F, 0 -dnp3_analog_input_SPwFlag, F, 1, 0 -dnp3_response_data_object, F, 255 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 257, 1, 1, 257, 257 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 286, 5, 0, 16777235, 16861313 +dnp3_object_header, F, 26940, 1, 4294964795, 49930, 47428 +dnp3_object_header, F, 457, 102, 0, 65535, 65535 +dnp3_object_header, F, 55993, 1, 4294962261, 19986, 14950 +dnp3_object_header, F, 274, 174, 0, 0, 0 dnp3_header_block, F, 25605, 255, 68, 100, 1 dnp3_application_response_header, F, 129, 5120 dnp3_object_header, F, 7685, 1, 224, 276, 499 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.events/coverage b/testing/btest/Baseline/scripts.base.protocols.dnp3.events/coverage index c5fd310309..d44974b182 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.events/coverage +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.events/coverage @@ -1 +1 @@ -9 of 51 events triggered by trace +11 of 51 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.events/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.events/dnp3.log index cee757a05a..be1b99f57f 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.events/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.events/dnp3.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-24-03 +#open 2013-08-23-23-05-27 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count 1097501938.504844 UWkUyAuUGXf 10.0.0.8 2789 10.0.0.3 20000 - UNSOLICITED_RESPONSE 4096 @@ -72,4 +72,4 @@ 1178206045.032815 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 1178206045.557097 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 1178206046.086403 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 -#close 2013-08-12-18-24-03 +#close 2013-08-23-23-05-27 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.events/output b/testing/btest/Baseline/scripts.base.protocols.dnp3.events/output index 5ed62b79ac..10fadba2ff 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.events/output +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.events/output @@ -335,11 +335,50 @@ dnp3_object_header, T, 15361, 6, 0, 65535, 65535 dnp3_header_block, F, 25605, 78, 68, 3, 4 dnp3_application_response_header, F, 129, 0 dnp3_object_header, F, 257, 0, 6, 0, 5 -dnp3_object_header, F, 522, 2, 4294705410, 17104896, 16843009 -dnp3_object_header, F, 276, 5, 0, 0, 21 -dnp3_object_header, F, 2304, 0, 1, 0, 0 dnp3_object_prefix, F, 0 -dnp3_debug_byte, F, \0\0\0\x1e^C\0\0^F\xc5\0\0\0\xc7\0\0\0\xc8\0\0\0^A\0\0\0%\x1c\0\0^N\x1c\0\0^P\x1c\0\0 +dnp3_response_data_object, F, 2 +dnp3_object_header, F, 2562, 0, 6, 0, 5 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 5125, 0, 1, 0, 0 +dnp3_object_prefix, F, 0 +dnp3_counter_32woFlag, F, 0 +dnp3_response_data_object, F, 255 +dnp3_object_header, F, 5385, 0, 1, 0, 0 +dnp3_object_prefix, F, 0 +dnp3_frozen_counter_32woFlag, F, 0 +dnp3_response_data_object, F, 255 +dnp3_object_header, F, 7683, 0, 7, 0, 6 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 197 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 199 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 200 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 1 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 7205 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 7182 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 7184 dnp3_response_data_object, F, 255 dnp3_header_block, F, 25605, 10, 68, 6, 4 dnp3_application_response_header, F, 130, 0 @@ -427,9 +466,50 @@ dnp3_object_header, T, 15361, 6, 0, 65535, 65535 dnp3_header_block, F, 25605, 78, 68, 3, 4 dnp3_application_response_header, F, 129, 0 dnp3_object_header, F, 257, 0, 6, 0, 5 -dnp3_object_header, F, 6410, 2, 2155643138, 2164588544, 25264385 dnp3_object_prefix, F, 0 -dnp3_debug_byte, F, ^A^T^E\0\0\0 \0\0\0^U^I\0\0\0\0\0\0\0\x1e^C\0\0^F\xca\0\0\0\xcb\0\0\0\xc9\0\0\0\xff\xff\xff\xfff!\0\0Y!\0\0K!\0\0 +dnp3_response_data_object, F, 25 +dnp3_object_header, F, 2562, 0, 6, 0, 5 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 129 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 129 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 129 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_prefix, F, 0 +dnp3_response_data_object, F, 1 +dnp3_object_header, F, 5125, 0, 1, 0, 0 +dnp3_object_prefix, F, 0 +dnp3_counter_32woFlag, F, 32 +dnp3_response_data_object, F, 255 +dnp3_object_header, F, 5385, 0, 1, 0, 0 +dnp3_object_prefix, F, 0 +dnp3_frozen_counter_32woFlag, F, 0 +dnp3_response_data_object, F, 255 +dnp3_object_header, F, 7683, 0, 7, 0, 6 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 202 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 203 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 201 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 18446744073709551615 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 8550 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 8537 +dnp3_response_data_object, F, 255 +dnp3_object_prefix, F, 0 +dnp3_analog_input_32woFlag, F, 8523 dnp3_response_data_object, F, 255 dnp3_header_block, T, 25605, 8, 196, 4, 3 dnp3_application_request_header, T, 14 diff --git a/testing/btest/scripts/base/protocols/dnp3/dnp3_link_only.bro b/testing/btest/scripts/base/protocols/dnp3/dnp3_link_only.bro index 1ea8df743f..867382148b 100644 --- a/testing/btest/scripts/base/protocols/dnp3/dnp3_link_only.bro +++ b/testing/btest/scripts/base/protocols/dnp3/dnp3_link_only.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro -r $TRACES/dnp3/dnp3_link_only.pcap %DIR/events.bro >output +# @TEST-EXEC: bro -C -r $TRACES/dnp3/dnp3_link_only.pcap %DIR/events.bro >output # @TEST-EXEC: btest-diff output # @TEST-EXEC: cat output | awk '{print $1}' | sort | uniq | wc -l >covered # @TEST-EXEC: cat ${DIST}/src/analyzer/protocol/dnp3/events.bif | grep "^event dnp3_" | wc -l >total From 72d2cd363eb8dc3e41f83d73152b9923c6723afc Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 26 Aug 2013 13:57:42 -0400 Subject: [PATCH 259/881] Removed the when statement from general use in the sumstats cluster code. --- scripts/base/frameworks/sumstats/cluster.bro | 170 +++---------------- 1 file changed, 26 insertions(+), 144 deletions(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index 6c72d5ff17..b6c0668f40 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -95,37 +95,6 @@ function data_added(ss: SumStat, key: Key, result: Result) } } -#event SumStats::send_data(uid: string, ss_name: string, cleanup: bool) -# { -# #print fmt("WORKER %s: sending data for uid %s...", Cluster::node, uid); -# -# local local_data: ResultTable = table(); -# local incoming_data: ResultTable = cleanup ? data : copy(data); -# -# local num_added = 0; -# for ( key in incoming_data ) -# { -# local_data[key] = incoming_data[key]; -# delete incoming_data[key]; -# -# # Only send cluster_send_in_groups_of at a time. Queue another -# # event to send the next group. -# if ( cluster_send_in_groups_of == ++num_added ) -# break; -# } -# -# local done = F; -# # If data is empty, this sumstat is done. -# if ( |incoming_data| == 0 ) -# done = T; -# -# # Note: copy is needed to compensate serialization caching issue. This should be -# # changed to something else later. -# event SumStats::cluster_ss_response(uid, ss_name, copy(local_data), done, cleanup); -# if ( ! done ) -# schedule 0.01 sec { SumStats::send_data(uid, T) }; -# } - event SumStats::get_a_key(uid: string, ss_name: string, cleanup: bool) { if ( uid in sending_results ) @@ -204,6 +173,8 @@ event SumStats::cluster_get_result(uid: string, ss_name: string, key: Key, clean { if ( ss_name in result_store && key in result_store[ss_name] ) { + # Note: copy is needed to compensate serialization caching issue. This should be + # changed to something else later. event SumStats::cluster_send_result(uid, ss_name, key, copy(result_store[ss_name][key]), cleanup); } else @@ -231,7 +202,12 @@ event SumStats::cluster_threshold_crossed(ss_name: string, key: SumStats::Key, t # This variable is maintained by manager nodes as they collect and aggregate # results. # Index on a uid. -global stats_keys: table[string] of set[Key] &create_expire=1min; +global stats_keys: table[string] of set[Key] &create_expire=1min + &expire_func=function(s: table[string] of set[Key], idx: string): interval + { + Reporter::warning(fmt("SumStat key request for the %s SumStat took longer than 1 minute and was automatically cancelled.", idx)); + return 0secs; + }; # This variable is maintained by manager nodes to track how many "dones" they # collected per collection unique id. Once the number of results for a uid @@ -246,11 +222,15 @@ global done_with: table[string] of count &create_expire=1min &default=0; # Indexed on a uid. global key_requests: table[string] of Result &create_expire=1min; +# Store uids for dynamic requests here to avoid cleanup on the uid. +# (This needs to be done differently!) +global dynamic_requests: set[string] &create_expire=1min; + # This variable is maintained by managers to prevent overwhelming communication due # to too many intermediate updates. Each sumstat is tracked separately so that # one won't overwhelm and degrade other quieter sumstats. # Indexed on a sumstat id. -global outstanding_global_views: table[string] of count &create_expire=1min &default=0; +global outstanding_global_views: table[string] of count &read_expire=1min &default=0; const zero_time = double_to_time(0.0); # Managers handle logging. @@ -337,12 +317,6 @@ function request_all_current_keys(uid: string, ss_name: string, cleanup: bool) { done_with[uid] = 0; event SumStats::cluster_get_result(uid, ss_name, key, cleanup); - when ( uid in done_with && Cluster::worker_count == done_with[uid] ) - { - #print "done getting result"; - handle_end_of_result_collection(uid, ss_name, key, cleanup); - request_all_current_keys(uid, ss_name, cleanup); - } delete stats_keys[uid][key]; break; # only a single key } @@ -392,7 +366,7 @@ event SumStats::send_a_key(uid: string, ss_name: string, key: Key) #print fmt("send_a_key %s", key); if ( uid !in stats_keys ) { - # no clue what happened here + Reporter::warning(fmt("Manager received a uid for an unknown request. SumStat: %s, Key: %s", ss_name, key)); return; } @@ -442,11 +416,14 @@ event SumStats::cluster_send_result(uid: string, ss_name: string, key: Key, resu #print fmt("MANAGER: got a result for %s %s from %s", uid, key, get_event_peer()$descr); ++done_with[uid]; - #if ( Cluster::worker_count == done_with[uid] ) - # { - # print "done"; - # handle_end_of_result_collection(uid, ss_name, key, cleanup); - # } + if ( uid !in dynamic_requests && + uid in done_with && Cluster::worker_count == done_with[uid] ) + { + handle_end_of_result_collection(uid, ss_name, key, cleanup); + + if ( cleanup ) + request_all_current_keys(uid, ss_name, cleanup); + } } # Managers handle intermediate updates here. @@ -470,110 +447,14 @@ event SumStats::cluster_key_intermediate_response(ss_name: string, key: Key) done_with[uid] = 0; #print fmt("requesting results for: %s", uid); event SumStats::cluster_get_result(uid, ss_name, key, F); - when ( uid in done_with && Cluster::worker_count == done_with[uid] ) - { - #print fmt("workers: %d done: %d", Cluster::worker_count, done_with[uid]); - handle_end_of_result_collection(uid, ss_name, key, F); - } - timeout 1.1min - { - Reporter::warning(fmt("Dynamic SumStat intermediate key request for %s (%s) took longer than 1 minute and was automatically cancelled.", ss_name, key)); - } - } -#event SumStats::cluster_ss_response(uid: string, ss_name: string, data: ResultTable, done: bool, cleanup: bool) -# { -# #print fmt("MANAGER: receiving results from %s", get_event_peer()$descr); -# -# # Mark another worker as being "done" for this uid. -# if ( done ) -# ++done_with[uid]; -# -# # We had better only be getting requests for stuff that exists. -# if ( ss_name !in stats_store ) -# return; -# -# if ( uid !in stats_keys ) -# stats_keys[uid] = table(); -# -# local local_data = stats_keys[uid]; -# local ss = stats_store[ss_name]; -# -# for ( key in data ) -# { -# if ( key in local_data ) -# local_data[key] = compose_results(local_data[key], data[key]); -# else -# local_data[key] = data[key]; -# -# # If a stat is done being collected, thresholds for each key -# # need to be checked so we're doing it here to avoid doubly -# # iterating over each key. -# if ( Cluster::worker_count == done_with[uid] ) -# { -# if ( check_thresholds(ss, key, local_data[key], 1.0) ) -# { -# threshold_crossed(ss, key, local_data[key]); -# event SumStats::cluster_threshold_crossed(ss$name, key, threshold_tracker[ss$name][key]); -# } -# } -# } -# -# # If the data has been collected from all peers, we are done and ready to finish. -# if ( cleanup && Cluster::worker_count == done_with[uid] ) -# { -# local now = network_time(); -# if ( ss?$epoch_result ) -# { -# for ( key in local_data ) -# ss$epoch_result(now, key, local_data[key]); -# } -# -# if ( ss?$epoch_finished ) -# ss$epoch_finished(now); -# -# # Clean up -# delete stats_keys[uid]; -# delete done_with[uid]; -# reset(ss); -# } -# } - -#function request(ss_name: string): ResultTable -# { -# # This only needs to be implemented this way for cluster compatibility. -# local uid = unique_id("dyn-"); -# stats_keys[uid] = table(); -# done_with[uid] = 0; -# event SumStats::cluster_ss_request(uid, ss_name, F); -# -# return when ( uid in done_with && Cluster::worker_count == done_with[uid] ) -# { -# if ( uid in stats_keys ) -# { -# local ss_result = stats_keys[uid]; -# # Clean up -# delete stats_keys[uid]; -# delete done_with[uid]; -# reset(stats_store[ss_name]); -# return ss_result; -# } -# else -# return table(); -# } -# timeout 1.1min -# { -# Reporter::warning(fmt("Dynamic SumStat request for %s took longer than 1 minute and was automatically cancelled.", ss_name)); -# return table(); -# } -# } - function request_key(ss_name: string, key: Key): Result { local uid = unique_id(""); done_with[uid] = 0; key_requests[uid] = table(); + add dynamic_requests[uid]; event SumStats::cluster_get_result(uid, ss_name, key, F); return when ( uid in done_with && Cluster::worker_count == done_with[uid] ) @@ -583,13 +464,14 @@ function request_key(ss_name: string, key: Key): Result # Clean up delete key_requests[uid]; delete done_with[uid]; + delete dynamic_requests[uid]; return result; } timeout 1.1min { - Reporter::warning(fmt("Dynamic SumStat key request for %s (%s) took longer than 1 minute and was automatically cancelled.", ss_name, key)); - return table(); + Reporter::warning(fmt("Dynamic SumStat key request for %s in SumStat %s took longer than 1 minute and was automatically cancelled.", key, ss_name)); + return Result(); } } From ea89e30a9cfc247d67acf45cd6da01e260124090 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 26 Aug 2013 15:29:27 -0400 Subject: [PATCH 260/881] One more tiny SumStats change to clean up cluster state. --- scripts/base/frameworks/sumstats/cluster.bro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/base/frameworks/sumstats/cluster.bro b/scripts/base/frameworks/sumstats/cluster.bro index b6c0668f40..f2b937586d 100644 --- a/scripts/base/frameworks/sumstats/cluster.bro +++ b/scripts/base/frameworks/sumstats/cluster.bro @@ -205,7 +205,7 @@ event SumStats::cluster_threshold_crossed(ss_name: string, key: SumStats::Key, t global stats_keys: table[string] of set[Key] &create_expire=1min &expire_func=function(s: table[string] of set[Key], idx: string): interval { - Reporter::warning(fmt("SumStat key request for the %s SumStat took longer than 1 minute and was automatically cancelled.", idx)); + Reporter::warning(fmt("SumStat key request for the %s SumStat uid took longer than 1 minute and was automatically cancelled.", idx)); return 0secs; }; @@ -356,6 +356,7 @@ event SumStats::send_no_key(uid: string, ss_name: string) if ( ss?$epoch_finished ) ss$epoch_finished(network_time()); + delete stats_keys[uid]; reset(ss); } } From 22bf3e1196b6e62896271a694993166e40e240e8 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 26 Aug 2013 15:31:17 -0500 Subject: [PATCH 261/881] Increase UIDs to 96 bits w/ C/F prefix - BIT-1016 - The bit-length is adjustable via redef'ing bits_per_uid. - Prefix 'C' is used for connection UIDS (including IP tunnels) and 'F' for files. --- scripts/base/init-bare.bro | 4 + src/CMakeLists.txt | 1 + src/Conn.cc | 7 +- src/Conn.h | 7 +- src/NetVar.cc | 4 + src/NetVar.h | 2 + src/TunnelEncapsulation.cc | 5 +- src/TunnelEncapsulation.h | 9 +- src/UID.cc | 43 + src/UID.h | 85 + src/file_analysis/Manager.cc | 8 +- src/file_analysis/Manager.h | 2 +- testing/btest/Baseline/core.checksums/bad.out | 58 +- .../btest/Baseline/core.checksums/good.out | 30 +- testing/btest/Baseline/core.conn-uid/output | 86 +- testing/btest/Baseline/core.ipv6-frag/dns.log | 10 +- testing/btest/Baseline/core.pppoe/conn.log | 18 +- .../Baseline/core.print-bpf-filters/conn.log | 6 +- testing/btest/Baseline/core.q-in-q/conn.log | 8 +- .../Baseline/core.tunnels.ayiya/conn.log | 20 +- .../Baseline/core.tunnels.ayiya/http.log | 10 +- .../Baseline/core.tunnels.ayiya/tunnel.log | 12 +- .../conn.log | 10 +- .../http.log | 8 +- .../tunnel.log | 12 +- .../core.tunnels.gtp.false_gtp/conn.log | 6 +- .../core.tunnels.gtp.false_gtp/dns.log | 6 +- .../core.tunnels.gtp.inner_ipv6/conn.log | 10 +- .../core.tunnels.gtp.inner_ipv6/tunnel.log | 8 +- .../core.tunnels.gtp.inner_teredo/conn.log | 38 +- .../core.tunnels.gtp.inner_teredo/tunnel.log | 40 +- .../conn.log | 8 +- .../core.tunnels.gtp.opt_header/conn.log | 8 +- .../core.tunnels.gtp.opt_header/tunnel.log | 8 +- .../core.tunnels.gtp.outer_ip_frag/conn.log | 8 +- .../core.tunnels.gtp.outer_ip_frag/http.log | 6 +- .../core.tunnels.gtp.outer_ip_frag/tunnel.log | 8 +- .../dpd.log | 6 +- .../tunnel.log | 8 +- .../Baseline/core.tunnels.ip-in-ip/output | 16 +- .../core.tunnels.ip-tunnel-uid/output | 22 +- .../Baseline/core.tunnels.teredo/conn.log | 46 +- .../Baseline/core.tunnels.teredo/http.log | 12 +- .../Baseline/core.tunnels.teredo/tunnel.log | 16 +- .../conn.log | 18 +- .../http.log | 8 +- .../tunnel.log | 16 +- .../weird.log | 8 +- .../btest/Baseline/core.vlan-mpls/conn.log | 10 +- .../istate.events-ssl/receiver.http.log | 6 +- .../istate.events-ssl/sender.http.log | 6 +- .../Baseline/istate.events/receiver.http.log | 6 +- .../Baseline/istate.events/sender.http.log | 6 +- .../files.log | 6 +- .../http.log | 6 +- .../conn.select | 68 +- .../http.select | 28 +- .../http.log | 32 +- .../alarm-mail.txt | 2 +- .../dhcp.log | 6 +- .../dhcp.log | 6 +- .../dnp3.log | 6 +- .../dnp3.log | 6 +- .../dnp3.log | 6 +- .../dnp3.log | 14 +- .../dnp3.log | 10 +- .../dnp3.log | 6 +- .../dnp3.log | 6 +- .../dnp3.log | 8 +- .../dnp3.log | 6 +- .../dnp3.log | 136 +- .../dns.log | 6 +- .../dns.log | 8 +- .../weird.log | 8 +- .../dns.log | 6 +- .../conn.log | 14 +- .../ftp.log | 16 +- .../conn.log | 16 +- .../ftp.log | 18 +- .../conn.log | 8 +- .../notice.log | 6 +- .../ssl.log | 8 +- .../http.log | 6 +- .../http.log | 102 +- .../weird.log | 102 +- .../http.log | 14 +- .../http.log | 6 +- .../scripts.base.protocols.irc.basic/irc.log | 12 +- .../modbus.log | 8 +- .../weird.log | 6 +- .../modbus.log | 39966 ++++++++-------- .../modbus_register_change.log | 84 +- .../modbus.log | 10 +- .../smtp.log | 6 +- .../socks.log | 6 +- .../socks.log | 6 +- .../scripts.base.protocols.ssl.basic/ssl.log | 6 +- .../ssl.log | 6 +- .../syslog.log | 6 +- .../dns.log | 6 +- .../signatures.eval-condition/conn.log | 14 +- .../frameworks/file-analysis/input/basic.bro | 2 +- testing/scripts/diff-remove-file-ids | 8 +- 103 files changed, 20911 insertions(+), 20772 deletions(-) create mode 100644 src/UID.cc create mode 100644 src/UID.h diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index cc69fd702e..d22aa067d8 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -3080,6 +3080,10 @@ const snaplen = 8192 &redef; ## instances. If left unset, Bro will use a temporary local seed. const global_hash_seed: string = "" &redef; +## Number of bits in UIDs that are generated to identify connections and +## files. The larger the value, the more confidence in UID uniqueness. +const bits_per_uid: count = 96 &redef; + # Load BiFs defined by plugins. @load base/bif/plugins diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e64dcbb9f6..c881cc4df1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -325,6 +325,7 @@ set(bro_SRCS Trigger.cc TunnelEncapsulation.cc Type.cc + UID.cc Val.cc Var.cc bsd-getopt-long.c diff --git a/src/Conn.cc b/src/Conn.cc index fb6ca3d810..e653211583 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -160,8 +160,6 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, TimerMgr::Tag* tag = current_iosrc->GetCurrentTag(); conn_timer_mgr = tag ? new TimerMgr::Tag(*tag) : 0; - uid = 0; // Will set later. - if ( arg_encap ) encapsulation = new EncapsulationStack(*arg_encap); else @@ -380,10 +378,9 @@ RecordVal* Connection::BuildConnVal() conn_val->Assign(8, new StringVal("")); // history if ( ! uid ) - uid = calculate_unique_id(); + uid = Bro::UID(bits_per_uid); - char tmp[20]; - conn_val->Assign(9, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62))); + conn_val->Assign(9, new StringVal(uid.Base62("C").c_str())); if ( encapsulation && encapsulation->Depth() > 0 ) conn_val->Assign(10, encapsulation->GetVectorVal()); diff --git a/src/Conn.h b/src/Conn.h index 95c521d875..d982d3879d 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -13,6 +13,7 @@ #include "RuleMatcher.h" #include "IPAddr.h" #include "TunnelEncapsulation.h" +#include "UID.h" #include "analyzer/Tag.h" #include "analyzer/Analyzer.h" @@ -252,9 +253,9 @@ public: // Sets the transport protocol in use. void SetTransport(TransportProto arg_proto) { proto = arg_proto; } - void SetUID(uint64 arg_uid) { uid = arg_uid; } + void SetUID(Bro::UID arg_uid) { uid = arg_uid; } - uint64 GetUID() const { return uid; } + Bro::UID GetUID() const { return uid; } const EncapsulationStack* GetEncapsulation() const { return encapsulation; } @@ -321,7 +322,7 @@ protected: analyzer::TransportLayerAnalyzer* root_analyzer; analyzer::pia::PIA* primary_PIA; - uint64 uid; // Globally unique connection ID. + Bro::UID uid; // Globally unique connection ID. }; class ConnectionTimer : public Timer { diff --git a/src/NetVar.cc b/src/NetVar.cc index cf80759173..dad0547059 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -240,6 +240,8 @@ StringVal* cmd_line_bpf_filter; StringVal* global_hash_seed; +bro_uint_t bits_per_uid; + OpaqueType* md5_type; OpaqueType* sha1_type; OpaqueType* sha256_type; @@ -309,6 +311,8 @@ void init_general_global_var() global_hash_seed = opt_internal_string("global_hash_seed"); + bits_per_uid = opt_internal_unsigned("bits_per_uid"); + md5_type = new OpaqueType("md5"); sha1_type = new OpaqueType("sha1"); sha256_type = new OpaqueType("sha256"); diff --git a/src/NetVar.h b/src/NetVar.h index 9a14525d4a..aa808abb59 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -244,6 +244,8 @@ extern StringVal* cmd_line_bpf_filter; extern StringVal* global_hash_seed; +extern bro_uint_t bits_per_uid; + class OpaqueType; extern OpaqueType* md5_type; extern OpaqueType* sha1_type; diff --git a/src/TunnelEncapsulation.cc b/src/TunnelEncapsulation.cc index edbabef81f..6330236dc2 100644 --- a/src/TunnelEncapsulation.cc +++ b/src/TunnelEncapsulation.cc @@ -11,7 +11,7 @@ EncapsulatingConn::EncapsulatingConn(Connection* c, BifEnum::Tunnel::Type t) { if ( ! uid ) { - uid = calculate_unique_id(); + uid = Bro::UID(bits_per_uid); c->SetUID(uid); } } @@ -28,8 +28,7 @@ RecordVal* EncapsulatingConn::GetRecordVal() const rv->Assign(0, id_val); rv->Assign(1, new EnumVal(type, BifType::Enum::Tunnel::Type)); - char tmp[20]; - rv->Assign(2, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62))); + rv->Assign(2, new StringVal(uid.Base62("C").c_str())); return rv; } diff --git a/src/TunnelEncapsulation.h b/src/TunnelEncapsulation.h index a43f7c0b57..23f8966ee7 100644 --- a/src/TunnelEncapsulation.h +++ b/src/TunnelEncapsulation.h @@ -7,6 +7,7 @@ #include "NetVar.h" #include "IPAddr.h" #include "Val.h" +#include "UID.h" #include class Connection; @@ -25,7 +26,7 @@ public: */ EncapsulatingConn() : src_port(0), dst_port(0), proto(TRANSPORT_UNKNOWN), - type(BifEnum::Tunnel::NONE), uid(0) + type(BifEnum::Tunnel::NONE), uid() {} /** @@ -39,9 +40,9 @@ public: */ EncapsulatingConn(const IPAddr& s, const IPAddr& d) : src_addr(s), dst_addr(d), src_port(0), dst_port(0), - proto(TRANSPORT_UNKNOWN), type(BifEnum::Tunnel::IP) + proto(TRANSPORT_UNKNOWN), type(BifEnum::Tunnel::IP), + uid(Bro::UID(bits_per_uid)) { - uid = calculate_unique_id(); } /** @@ -108,7 +109,7 @@ protected: uint16 dst_port; TransportProto proto; BifEnum::Tunnel::Type type; - uint64 uid; + Bro::UID uid; }; /** diff --git a/src/UID.cc b/src/UID.cc new file mode 100644 index 0000000000..e71bf9fafc --- /dev/null +++ b/src/UID.cc @@ -0,0 +1,43 @@ +#include + +#include "UID.h" + +using namespace Bro; +using namespace std; + +void UID::Set(bro_uint_t bits, const std::vector& v) + { + uid.clear(); + + div_t res = div(bits, 64); + int size = res.rem ? res.quot + 1 : res.quot; + + for ( int i = 0; i < size; ++i ) + uid.push_back(i < v.size() ? v[i] : calculate_unique_id()); + + if ( res.rem ) + uid[0] >>= 64 - res.rem; + } + +string UID::Base62(const std::string& prefix) const + { + char tmp[64]; // technically, this should dynamically scale based on size + string rval(prefix); + + for ( size_t i = 0; i < uid.size(); ++i ) + rval.append(uitoa_n(uid[i], tmp, sizeof(tmp), 62)); + + return rval; + } + +bool Bro::operator==(const UID& u1, const UID& u2) + { + if ( u1.uid.size() != u2.uid.size() ) + return false; + + for ( size_t i = 0; i < u1.uid.size(); ++i ) + if ( u1.uid[i] != u2.uid[i] ) + return false; + + return true; + } diff --git a/src/UID.h b/src/UID.h new file mode 100644 index 0000000000..6fcad4e989 --- /dev/null +++ b/src/UID.h @@ -0,0 +1,85 @@ +#ifndef BRO_UID_H +#define BRO_UID_H + +#include +#include + +#include "util.h" + +namespace Bro { + +/** + * A class for creating/manager UIDs of arbitrary bit-length and converting + * them to human-readable strings in Base62 format. + */ +class UID { +public: + + /** + * Default ctor. The UID is uninitialized and in string format is + * represented by an empty string. + */ + UID() {} + + /** + * Construct a UID of a given bit-length, optionally from given values. + * @see UID::Set + */ + UID(bro_uint_t bits, const std::vector& v = std::vector()) + { Set(bits, v); } + + /** + * Copy constructor. + */ + UID(const UID& other) { uid = other.uid; } + + /** + * Inititialize a UID of a given bit-length, optionally from given values. + * @param bits The desired length in bits of the UID. + * @param v A vector of values with which to initialize the UID. + * If empty or doesn't contain enough values to satisfy \a bits, + * then values are automatically generated using + * calculate_unique_id(). If \a bits isn't evenly divisible by + * 64, then a value is truncated to bit in desired bit-length. + */ + void Set(bro_uint_t bits, + const std::vector& v = std::vector()); + + /** + * Returns a base62 (characters 0-9, A-Z, a-z) representation of the UID. + * @param prefix An optional string prefix. + * @return a base62 string representing the UID. + */ + std::string Base62(const std::string& prefix = "") const; + + /** + * @return false if the UID instance was create via the default ctor + * and not yet initialized w/ Set(). + * TODO: this would be better as an "explicit" conversion operator (C++11) + */ + operator bool() const { return ( ! uid.empty() ); } + + /** + * Assignment operator. + */ + UID& operator=(const UID& other) { uid = other.uid; return *this; } + + /** + * UID equality operator. + */ + friend bool operator==(const UID& u1, const UID& u2); + + /** + * UID inequality operator. + */ + friend bool operator!=(const UID& u1, const UID& u2) + { return ! ( u1 == u2 ); } + +private: + + std::vector uid; +}; + +} // namespace Bro + +#endif diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index 7bfd5167ba..77441f8264 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -9,6 +9,7 @@ #include "Analyzer.h" #include "Var.h" #include "Event.h" +#include "UID.h" #include "plugin/Manager.h" @@ -57,15 +58,16 @@ string Manager::HashHandle(const string& handle) const if ( salt.empty() ) salt = BifConst::Files::salt->CheckString(); - char tmp[20]; uint64 hash[2]; string msg(handle + salt); MD5(reinterpret_cast(msg.data()), msg.size(), reinterpret_cast(hash)); - uitoa_n(hash[0], tmp, sizeof(tmp), 62); - return tmp; + vector v; + v.push_back(hash[0]); + v.push_back(hash[1]); + return Bro::UID(bits_per_uid, v).Base62("F"); } void Manager::SetHandle(const string& handle) diff --git a/src/file_analysis/Manager.h b/src/file_analysis/Manager.h index cdfac00520..1d72d0eae9 100644 --- a/src/file_analysis/Manager.h +++ b/src/file_analysis/Manager.h @@ -62,7 +62,7 @@ public: /** * Creates a file identifier from a unique file handle string. * @param handle a unique string which identifies a single file. - * @return a prettified MD5 hash of \a handle, truncated to 64-bits. + * @return a prettified MD5 hash of \a handle, truncated to 96-bits. */ string HashHandle(const string& handle) const; diff --git a/testing/btest/Baseline/core.checksums/bad.out b/testing/btest/Baseline/core.checksums/bad.out index 94b141c9e1..148b04e952 100644 --- a/testing/btest/Baseline/core.checksums/bad.out +++ b/testing/btest/Baseline/core.checksums/bad.out @@ -3,101 +3,101 @@ #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-18-03-01 +#open 2013-08-26-19-02-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1332784981.078396 - - - - - bad_IP_checksum - F bro -#close 2012-03-26-18-03-01 +#close 2013-08-26-19-02-06 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-18-01-25 +#open 2013-08-26-19-02-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1332784885.686428 UWkUyAuUGXf 127.0.0.1 30000 127.0.0.1 80 bad_TCP_checksum - F bro -#close 2012-03-26-18-01-25 +1332784885.686428 CXWv6p3arKYeMETxOg 127.0.0.1 30000 127.0.0.1 80 bad_TCP_checksum - F bro +#close 2013-08-26-19-02-06 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-18-02-13 +#open 2013-08-26-19-02-07 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1332784933.501023 UWkUyAuUGXf 127.0.0.1 30000 127.0.0.1 13000 bad_UDP_checksum - F bro -#close 2012-03-26-18-02-13 +1332784933.501023 CXWv6p3arKYeMETxOg 127.0.0.1 30000 127.0.0.1 13000 bad_UDP_checksum - F bro +#close 2013-08-26-19-02-07 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-04-10-16-29-23 +#open 2013-08-26-19-02-07 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1334075363.536871 UWkUyAuUGXf 192.168.1.100 8 192.168.1.101 0 bad_ICMP_checksum - F bro -#close 2012-04-10-16-29-23 +1334075363.536871 CXWv6p3arKYeMETxOg 192.168.1.100 8 192.168.1.101 0 bad_ICMP_checksum - F bro +#close 2013-08-26-19-02-07 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-18-06-50 +#open 2013-08-26-19-02-08 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1332785210.013051 - - - - - routing0_hdr - F bro -1332785210.013051 UWkUyAuUGXf 2001:4f8:4:7:2e0:81ff:fe52:ffff 30000 2001:78:1:32::2 80 bad_TCP_checksum - F bro -#close 2012-03-26-18-06-50 +1332785210.013051 CXWv6p3arKYeMETxOg 2001:4f8:4:7:2e0:81ff:fe52:ffff 30000 2001:78:1:32::2 80 bad_TCP_checksum - F bro +#close 2013-08-26-19-02-08 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-17-23-00 +#open 2013-08-26-19-02-09 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1332782580.798420 - - - - - routing0_hdr - F bro -1332782580.798420 UWkUyAuUGXf 2001:4f8:4:7:2e0:81ff:fe52:ffff 30000 2001:78:1:32::2 13000 bad_UDP_checksum - F bro -#close 2012-03-26-17-23-00 +1332782580.798420 CXWv6p3arKYeMETxOg 2001:4f8:4:7:2e0:81ff:fe52:ffff 30000 2001:78:1:32::2 13000 bad_UDP_checksum - F bro +#close 2013-08-26-19-02-09 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-04-10-16-25-11 +#open 2013-08-26-19-02-09 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1334075111.800086 - - - - - routing0_hdr - F bro -1334075111.800086 UWkUyAuUGXf 2001:4f8:4:7:2e0:81ff:fe52:ffff 128 2001:78:1:32::1 129 bad_ICMP_checksum - F bro -#close 2012-04-10-16-25-11 +1334075111.800086 CXWv6p3arKYeMETxOg 2001:4f8:4:7:2e0:81ff:fe52:ffff 128 2001:78:1:32::1 129 bad_ICMP_checksum - F bro +#close 2013-08-26-19-02-09 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-18-07-30 +#open 2013-08-26-19-02-10 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1332785250.469132 UWkUyAuUGXf 2001:4f8:4:7:2e0:81ff:fe52:ffff 30000 2001:4f8:4:7:2e0:81ff:fe52:9a6b 80 bad_TCP_checksum - F bro -#close 2012-03-26-18-07-30 +1332785250.469132 CXWv6p3arKYeMETxOg 2001:4f8:4:7:2e0:81ff:fe52:ffff 30000 2001:4f8:4:7:2e0:81ff:fe52:9a6b 80 bad_TCP_checksum - F bro +#close 2013-08-26-19-02-10 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-17-02-22 +#open 2013-08-26-19-02-10 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1332781342.923813 UWkUyAuUGXf 2001:4f8:4:7:2e0:81ff:fe52:ffff 30000 2001:4f8:4:7:2e0:81ff:fe52:9a6b 13000 bad_UDP_checksum - F bro -#close 2012-03-26-17-02-22 +1332781342.923813 CXWv6p3arKYeMETxOg 2001:4f8:4:7:2e0:81ff:fe52:ffff 30000 2001:4f8:4:7:2e0:81ff:fe52:9a6b 13000 bad_UDP_checksum - F bro +#close 2013-08-26-19-02-10 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-04-10-16-22-19 +#open 2013-08-26-19-02-11 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1334074939.467194 UWkUyAuUGXf 2001:4f8:4:7:2e0:81ff:fe52:ffff 128 2001:4f8:4:7:2e0:81ff:fe52:9a6b 129 bad_ICMP_checksum - F bro -#close 2012-04-10-16-22-19 +1334074939.467194 CXWv6p3arKYeMETxOg 2001:4f8:4:7:2e0:81ff:fe52:ffff 128 2001:4f8:4:7:2e0:81ff:fe52:9a6b 129 bad_ICMP_checksum - F bro +#close 2013-08-26-19-02-11 diff --git a/testing/btest/Baseline/core.checksums/good.out b/testing/btest/Baseline/core.checksums/good.out index a47931a15c..2aed7f280d 100644 --- a/testing/btest/Baseline/core.checksums/good.out +++ b/testing/btest/Baseline/core.checksums/good.out @@ -3,68 +3,68 @@ #empty_field (empty) #unset_field - #path weird -#open 2012-04-10-16-22-19 +#open 2013-08-26-19-34-56 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1334074939.467194 UWkUyAuUGXf 2001:4f8:4:7:2e0:81ff:fe52:ffff 128 2001:4f8:4:7:2e0:81ff:fe52:9a6b 129 bad_ICMP_checksum - F bro -#close 2012-04-10-16-22-19 +1334074939.467194 CXWv6p3arKYeMETxOg 2001:4f8:4:7:2e0:81ff:fe52:ffff 128 2001:4f8:4:7:2e0:81ff:fe52:9a6b 129 bad_ICMP_checksum - F bro +#close 2013-08-26-19-34-56 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-18-05-25 +#open 2013-08-26-19-34-57 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1332785125.596793 - - - - - routing0_hdr - F bro -#close 2012-03-26-18-05-25 +#close 2013-08-26-19-34-57 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-03-26-17-21-48 +#open 2013-08-26-19-34-57 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1332782508.592037 - - - - - routing0_hdr - F bro -#close 2012-03-26-17-21-48 +#close 2013-08-26-19-34-57 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-04-10-16-23-47 +#open 2013-08-26-19-34-57 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1334075027.053380 - - - - - routing0_hdr - F bro -#close 2012-04-10-16-23-47 +#close 2013-08-26-19-34-57 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-04-10-16-23-47 +#open 2013-08-26-19-34-57 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1334075027.053380 - - - - - routing0_hdr - F bro -#close 2012-04-10-16-23-47 +#close 2013-08-26-19-34-57 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-04-10-16-23-47 +#open 2013-08-26-19-34-57 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1334075027.053380 - - - - - routing0_hdr - F bro -#close 2012-04-10-16-23-47 +#close 2013-08-26-19-34-57 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path weird -#open 2012-04-10-16-23-47 +#open 2013-08-26-19-34-57 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1334075027.053380 - - - - - routing0_hdr - F bro -#close 2012-04-10-16-23-47 +#close 2013-08-26-19-34-57 diff --git a/testing/btest/Baseline/core.conn-uid/output b/testing/btest/Baseline/core.conn-uid/output index c77eda4f04..1209518158 100644 --- a/testing/btest/Baseline/core.conn-uid/output +++ b/testing/btest/Baseline/core.conn-uid/output @@ -1,43 +1,43 @@ -[orig_h=141.142.220.202, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], UWkUyAuUGXf -[orig_h=fe80::217:f2ff:fed7:cf65, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], arKYeMETxOg -[orig_h=141.142.220.50, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], k6kgXLOoSKl -[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp], nQcgTWjvg4c -[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], j4u32Pc5bif -[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], j4u32Pc5bif -[orig_h=141.142.220.118, orig_p=43927/udp, resp_h=141.142.2.2, resp_p=53/udp], TEfuqmmG4bh -[orig_h=141.142.220.118, orig_p=37676/udp, resp_h=141.142.2.2, resp_p=53/udp], FrJExwHcSal -[orig_h=141.142.220.118, orig_p=40526/udp, resp_h=141.142.2.2, resp_p=53/udp], 5OKnoww6xl4 -[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], 3PKsZ2Uye21 -[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], VW0XPVINV8a -[orig_h=141.142.220.118, orig_p=32902/udp, resp_h=141.142.2.2, resp_p=53/udp], fRFu0wcOle6 -[orig_h=141.142.220.118, orig_p=59816/udp, resp_h=141.142.2.2, resp_p=53/udp], qSsw6ESzHV4 -[orig_h=141.142.220.118, orig_p=59714/udp, resp_h=141.142.2.2, resp_p=53/udp], iE6yhOq3SF -[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], GSxOnSLghOa -[orig_h=141.142.220.118, orig_p=58206/udp, resp_h=141.142.2.2, resp_p=53/udp], qCaWGmzFtM5 -[orig_h=141.142.220.118, orig_p=38911/udp, resp_h=141.142.2.2, resp_p=53/udp], 70MGiRM1Qf4 -[orig_h=141.142.220.118, orig_p=59746/udp, resp_h=141.142.2.2, resp_p=53/udp], h5DsfNtYzi1 -[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], P654jzLoe3a -[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], Tw8jXtpTGu6 -[orig_h=141.142.220.118, orig_p=45000/udp, resp_h=141.142.2.2, resp_p=53/udp], c4Zw9TmAE05 -[orig_h=141.142.220.118, orig_p=48479/udp, resp_h=141.142.2.2, resp_p=53/udp], EAr0uf4mhq -[orig_h=141.142.220.118, orig_p=48128/udp, resp_h=141.142.2.2, resp_p=53/udp], GvmoxJFXdTa -[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], 0Q4FH8sESw5 -[orig_h=141.142.220.118, orig_p=56056/udp, resp_h=141.142.2.2, resp_p=53/udp], slFea8xwSmb -[orig_h=141.142.220.118, orig_p=55092/udp, resp_h=141.142.2.2, resp_p=53/udp], UfGkYA2HI2g -[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], i2rO3KD1Syg -[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], VW0XPVINV8a -[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], 3PKsZ2Uye21 -[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], GSxOnSLghOa -[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], Tw8jXtpTGu6 -[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], P654jzLoe3a -[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], 0Q4FH8sESw5 -[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], i2rO3KD1Syg -[orig_h=141.142.220.235, orig_p=6705/tcp, resp_h=173.192.163.128, resp_p=80/tcp], 2cx26uAvUPl -[orig_h=141.142.220.235, orig_p=6705/tcp, resp_h=173.192.163.128, resp_p=80/tcp], 2cx26uAvUPl -[orig_h=141.142.220.44, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], BWaU4aSuwkc -[orig_h=141.142.220.226, orig_p=137/udp, resp_h=141.142.220.255, resp_p=137/udp], 10XodEwRycf -[orig_h=fe80::3074:17d5:2052:c324, orig_p=65373/udp, resp_h=ff02::1:3, resp_p=5355/udp], zno26fFZkrh -[orig_h=141.142.220.226, orig_p=55131/udp, resp_h=224.0.0.252, resp_p=5355/udp], v5rgkJBig5l -[orig_h=fe80::3074:17d5:2052:c324, orig_p=54213/udp, resp_h=ff02::1:3, resp_p=5355/udp], eWZCH7OONC1 -[orig_h=141.142.220.226, orig_p=55671/udp, resp_h=224.0.0.252, resp_p=5355/udp], 0Pwk3ntf8O3 -[orig_h=141.142.220.238, orig_p=56641/udp, resp_h=141.142.220.255, resp_p=137/udp], 0HKorjr8Zp7 +[orig_h=141.142.220.202, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], CXWv6p3arKYeMETxOg +[orig_h=fe80::217:f2ff:fed7:cf65, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], CjhGID4nQcgTWjvg4c +[orig_h=141.142.220.50, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], CCvvfg3TEfuqmmG4bh +[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp], CsRx2w45OKnoww6xl4 +[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], CRJuHdVW0XPVINV8a +[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], CRJuHdVW0XPVINV8a +[orig_h=141.142.220.118, orig_p=43927/udp, resp_h=141.142.2.2, resp_p=53/udp], CPbrpk1qSsw6ESzHV4 +[orig_h=141.142.220.118, orig_p=37676/udp, resp_h=141.142.2.2, resp_p=53/udp], C6pKV8GSxOnSLghOa +[orig_h=141.142.220.118, orig_p=40526/udp, resp_h=141.142.2.2, resp_p=53/udp], CIPOse170MGiRM1Qf4 +[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], C7XEbhP654jzLoe3a +[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], CJ3xTn1c4Zw9TmAE05 +[orig_h=141.142.220.118, orig_p=32902/udp, resp_h=141.142.2.2, resp_p=53/udp], CMXxB5GvmoxJFXdTa +[orig_h=141.142.220.118, orig_p=59816/udp, resp_h=141.142.2.2, resp_p=53/udp], Caby8b1slFea8xwSmb +[orig_h=141.142.220.118, orig_p=59714/udp, resp_h=141.142.2.2, resp_p=53/udp], Che1bq3i2rO3KD1Syg +[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], C3SfNE4BWaU4aSuwkc +[orig_h=141.142.220.118, orig_p=58206/udp, resp_h=141.142.2.2, resp_p=53/udp], CEle3f3zno26fFZkrh +[orig_h=141.142.220.118, orig_p=38911/udp, resp_h=141.142.2.2, resp_p=53/udp], CwSkQu4eWZCH7OONC1 +[orig_h=141.142.220.118, orig_p=59746/udp, resp_h=141.142.2.2, resp_p=53/udp], CfTOmO0HKorjr8Zp7 +[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], CzA03V1VcgagLjnO92 +[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], CyAhVIzHqb7t7kv28 +[orig_h=141.142.220.118, orig_p=45000/udp, resp_h=141.142.2.2, resp_p=53/udp], Cab0vO1xNYSS2hJkle +[orig_h=141.142.220.118, orig_p=48479/udp, resp_h=141.142.2.2, resp_p=53/udp], Cx2FqO23omNawSNrxj +[orig_h=141.142.220.118, orig_p=48128/udp, resp_h=141.142.2.2, resp_p=53/udp], Cx3C534wEyF3OvvcQe +[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], CkDsfG2YIeWJmXWNWj +[orig_h=141.142.220.118, orig_p=56056/udp, resp_h=141.142.2.2, resp_p=53/udp], CUKS0W3HFYOnBqSE5e +[orig_h=141.142.220.118, orig_p=55092/udp, resp_h=141.142.2.2, resp_p=53/udp], CRrfvP2lalMAYOCLhj +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], Cn78a440HlxuyZKs6f +[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], CJ3xTn1c4Zw9TmAE05 +[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], C7XEbhP654jzLoe3a +[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], C3SfNE4BWaU4aSuwkc +[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], CyAhVIzHqb7t7kv28 +[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], CzA03V1VcgagLjnO92 +[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], CkDsfG2YIeWJmXWNWj +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], Cn78a440HlxuyZKs6f +[orig_h=141.142.220.235, orig_p=6705/tcp, resp_h=173.192.163.128, resp_p=80/tcp], CUof3F2yAIid8QS3dk +[orig_h=141.142.220.235, orig_p=6705/tcp, resp_h=173.192.163.128, resp_p=80/tcp], CUof3F2yAIid8QS3dk +[orig_h=141.142.220.44, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], CojBOU3CXcLHl1r6x1 +[orig_h=141.142.220.226, orig_p=137/udp, resp_h=141.142.220.255, resp_p=137/udp], CJzVQRGJrX6V15ik7 +[orig_h=fe80::3074:17d5:2052:c324, orig_p=65373/udp, resp_h=ff02::1:3, resp_p=5355/udp], ClAbxY1nmdjCuo0Le2 +[orig_h=141.142.220.226, orig_p=55131/udp, resp_h=224.0.0.252, resp_p=5355/udp], CwG0BF1VXE0gWgs78 +[orig_h=fe80::3074:17d5:2052:c324, orig_p=54213/udp, resp_h=ff02::1:3, resp_p=5355/udp], CisNaL1Cm73CiNOmcg +[orig_h=141.142.220.226, orig_p=55671/udp, resp_h=224.0.0.252, resp_p=5355/udp], CBQnJn22qN8TOeeZil +[orig_h=141.142.220.238, orig_p=56641/udp, resp_h=141.142.220.255, resp_p=137/udp], CbEsuD3dgDDngdlbKf diff --git a/testing/btest/Baseline/core.ipv6-frag/dns.log b/testing/btest/Baseline/core.ipv6-frag/dns.log index 97fb552c0d..69aec7e222 100644 --- a/testing/btest/Baseline/core.ipv6-frag/dns.log +++ b/testing/btest/Baseline/core.ipv6-frag/dns.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path dns -#open 2013-05-17-14-28-17 +#open 2013-08-26-19-02-10 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected #types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] bool -1331084278.438444 UWkUyAuUGXf 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51850 2607:f740:b::f93 53 udp 3903 txtpadding_323.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR T F T F 0 This TXT record should be ignored 1.000000 F -1331084293.592245 arKYeMETxOg 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51851 2607:f740:b::f93 53 udp 40849 txtpadding_3230.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR T F T F 0 This TXT record should be ignored 1.000000 F -1331084298.593081 arKYeMETxOg 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51851 2607:f740:b::f93 53 udp 40849 txtpadding_3230.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT - - F F T F 0 - - F -#close 2013-05-17-14-28-17 +1331084278.438444 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51850 2607:f740:b::f93 53 udp 3903 txtpadding_323.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR T F T F 0 This TXT record should be ignored 1.000000 F +1331084293.592245 CjhGID4nQcgTWjvg4c 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51851 2607:f740:b::f93 53 udp 40849 txtpadding_3230.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR T F T F 0 This TXT record should be ignored 1.000000 F +1331084298.593081 CjhGID4nQcgTWjvg4c 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51851 2607:f740:b::f93 53 udp 40849 txtpadding_3230.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT - - F F T F 0 - - F +#close 2013-08-26-19-02-10 diff --git a/testing/btest/Baseline/core.pppoe/conn.log b/testing/btest/Baseline/core.pppoe/conn.log index 002b8a7ca0..641696bf64 100644 --- a/testing/btest/Baseline/core.pppoe/conn.log +++ b/testing/btest/Baseline/core.pppoe/conn.log @@ -3,14 +3,14 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-24-05-04-16 +#open 2013-08-26-19-02-12 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1284385418.014560 TEfuqmmG4bh fe80::c801:eff:fe88:8 547 fe80::ce05:eff:fe88:0 546 udp - 0.096000 192 0 S0 - 0 D 2 288 0 0 (empty) -1284385417.962560 j4u32Pc5bif fe80::ce05:eff:fe88:0 546 ff02::1:2 547 udp - 0.078000 114 0 S0 - 0 D 2 210 0 0 (empty) -1284385411.091560 arKYeMETxOg fe80::c801:eff:fe88:8 136 ff02::1 135 icmp - - - - OTH - 0 - 1 64 0 0 (empty) -1284385411.035560 UWkUyAuUGXf fe80::c801:eff:fe88:8 143 ff02::16 0 icmp - 0.835000 160 0 OTH - 0 - 8 608 0 0 (empty) -1284385451.658560 FrJExwHcSal fc00:0:2:100::1:1 128 fc00::1 129 icmp - 0.156000 260 260 OTH - 0 - 5 500 5 500 (empty) -1284385413.027560 nQcgTWjvg4c fe80::c801:eff:fe88:8 134 fe80::ce05:eff:fe88:0 133 icmp - - - - OTH - 0 - 1 64 0 0 (empty) -1284385412.963560 k6kgXLOoSKl fe80::ce05:eff:fe88:0 133 ff02::2 134 icmp - - - - OTH - 0 - 1 48 0 0 (empty) -#close 2012-10-24-05-04-16 +1284385418.014560 CPbrpk1qSsw6ESzHV4 fe80::c801:eff:fe88:8 547 fe80::ce05:eff:fe88:0 546 udp - 0.096000 192 0 S0 - 0 D 2 288 0 0 (empty) +1284385417.962560 CRJuHdVW0XPVINV8a fe80::ce05:eff:fe88:0 546 ff02::1:2 547 udp - 0.078000 114 0 S0 - 0 D 2 210 0 0 (empty) +1284385411.091560 CjhGID4nQcgTWjvg4c fe80::c801:eff:fe88:8 136 ff02::1 135 icmp - - - - OTH - 0 - 1 64 0 0 (empty) +1284385411.035560 CXWv6p3arKYeMETxOg fe80::c801:eff:fe88:8 143 ff02::16 0 icmp - 0.835000 160 0 OTH - 0 - 8 608 0 0 (empty) +1284385451.658560 C6pKV8GSxOnSLghOa fc00:0:2:100::1:1 128 fc00::1 129 icmp - 0.156000 260 260 OTH - 0 - 5 500 5 500 (empty) +1284385413.027560 CsRx2w45OKnoww6xl4 fe80::c801:eff:fe88:8 134 fe80::ce05:eff:fe88:0 133 icmp - - - - OTH - 0 - 1 64 0 0 (empty) +1284385412.963560 CCvvfg3TEfuqmmG4bh fe80::ce05:eff:fe88:0 133 ff02::2 134 icmp - - - - OTH - 0 - 1 48 0 0 (empty) +#close 2013-08-26-19-02-12 diff --git a/testing/btest/Baseline/core.print-bpf-filters/conn.log b/testing/btest/Baseline/core.print-bpf-filters/conn.log index 2b2cbc606b..e874d27959 100644 --- a/testing/btest/Baseline/core.print-bpf-filters/conn.log +++ b/testing/btest/Baseline/core.print-bpf-filters/conn.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path conn -#open 2013-08-12-18-24-50 +#open 2013-08-26-19-02-14 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1278600802.069419 UWkUyAuUGXf 10.20.80.1 50343 10.0.0.15 80 tcp - 0.004152 9 3429 SF - 0 ShADadfF 7 381 7 3801 (empty) -#close 2013-08-12-18-24-50 +1278600802.069419 CXWv6p3arKYeMETxOg 10.20.80.1 50343 10.0.0.15 80 tcp - 0.004152 9 3429 SF - 0 ShADadfF 7 381 7 3801 (empty) +#close 2013-08-26-19-02-14 diff --git a/testing/btest/Baseline/core.q-in-q/conn.log b/testing/btest/Baseline/core.q-in-q/conn.log index 00b1b9894f..9a6e2a235f 100644 --- a/testing/btest/Baseline/core.q-in-q/conn.log +++ b/testing/btest/Baseline/core.q-in-q/conn.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path conn -#open 2013-03-22-16-36-54 +#open 2013-08-26-19-02-13 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1363900699.548138 UWkUyAuUGXf 172.19.51.37 47808 172.19.51.63 47808 udp - 0.000100 36 0 S0 - 0 D 2 92 0 0 (empty) -1363900699.549647 arKYeMETxOg 193.1.186.60 9875 224.2.127.254 9875 udp - 0.000139 552 0 S0 - 0 D 2 608 0 0 (empty) -#close 2013-03-22-16-36-54 +1363900699.548138 CXWv6p3arKYeMETxOg 172.19.51.37 47808 172.19.51.63 47808 udp - 0.000100 36 0 S0 - 0 D 2 92 0 0 (empty) +1363900699.549647 CjhGID4nQcgTWjvg4c 193.1.186.60 9875 224.2.127.254 9875 udp - 0.000139 552 0 S0 - 0 D 2 608 0 0 (empty) +#close 2013-08-26-19-02-13 diff --git a/testing/btest/Baseline/core.tunnels.ayiya/conn.log b/testing/btest/Baseline/core.tunnels.ayiya/conn.log index 7646fa574a..8efd9fa5ac 100644 --- a/testing/btest/Baseline/core.tunnels.ayiya/conn.log +++ b/testing/btest/Baseline/core.tunnels.ayiya/conn.log @@ -3,15 +3,15 @@ #empty_field (empty) #unset_field - #path conn -#open 2009-11-08-04-41-57 +#open 2013-08-26-18-38-29 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1257655301.595604 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 tcp http 2.101052 2981 4665 S1 - 0 ShADad 10 3605 11 5329 k6kgXLOoSKl -1257655296.585034 k6kgXLOoSKl 192.168.3.101 53859 216.14.98.22 5072 udp ayiya 20.879001 5129 6109 SF - 0 Dd 21 5717 13 6473 (empty) -1257655293.629048 UWkUyAuUGXf 192.168.3.101 53796 216.14.98.22 5072 udp ayiya - - - SHR - 0 d 0 0 1 176 (empty) -1257655296.585333 FrJExwHcSal :: 135 ff02::1:ff00:2 136 icmp - - - - OTH - 0 - 1 64 0 0 k6kgXLOoSKl -1257655293.629048 arKYeMETxOg 2001:4978:f:4c::1 128 2001:4978:f:4c::2 129 icmp - 23.834987 168 56 OTH - 0 - 3 312 1 104 UWkUyAuUGXf,k6kgXLOoSKl -1257655296.585188 TEfuqmmG4bh fe80::216:cbff:fe9a:4cb9 131 ff02::1:ff00:2 130 icmp - 0.919988 32 0 OTH - 0 - 2 144 0 0 k6kgXLOoSKl -1257655296.585151 j4u32Pc5bif fe80::216:cbff:fe9a:4cb9 131 ff02::2:f901:d225 130 icmp - 0.719947 32 0 OTH - 0 - 2 144 0 0 k6kgXLOoSKl -1257655296.585034 nQcgTWjvg4c fe80::216:cbff:fe9a:4cb9 131 ff02::1:ff9a:4cb9 130 icmp - 4.922880 32 0 OTH - 0 - 2 144 0 0 k6kgXLOoSKl -#close 2009-11-08-04-41-57 +1257655301.595604 CIPOse170MGiRM1Qf4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 tcp http 2.101052 2981 4665 S1 - 0 ShADad 10 3605 11 5329 CCvvfg3TEfuqmmG4bh +1257655296.585034 CCvvfg3TEfuqmmG4bh 192.168.3.101 53859 216.14.98.22 5072 udp ayiya 20.879001 5129 6109 SF - 0 Dd 21 5717 13 6473 (empty) +1257655293.629048 CXWv6p3arKYeMETxOg 192.168.3.101 53796 216.14.98.22 5072 udp ayiya - - - SHR - 0 d 0 0 1 176 (empty) +1257655296.585333 C6pKV8GSxOnSLghOa :: 135 ff02::1:ff00:2 136 icmp - - - - OTH - 0 - 1 64 0 0 CCvvfg3TEfuqmmG4bh +1257655293.629048 CjhGID4nQcgTWjvg4c 2001:4978:f:4c::1 128 2001:4978:f:4c::2 129 icmp - 23.834987 168 56 OTH - 0 - 3 312 1 104 CXWv6p3arKYeMETxOg,CCvvfg3TEfuqmmG4bh +1257655296.585188 CPbrpk1qSsw6ESzHV4 fe80::216:cbff:fe9a:4cb9 131 ff02::1:ff00:2 130 icmp - 0.919988 32 0 OTH - 0 - 2 144 0 0 CCvvfg3TEfuqmmG4bh +1257655296.585151 CRJuHdVW0XPVINV8a fe80::216:cbff:fe9a:4cb9 131 ff02::2:f901:d225 130 icmp - 0.719947 32 0 OTH - 0 - 2 144 0 0 CCvvfg3TEfuqmmG4bh +1257655296.585034 CsRx2w45OKnoww6xl4 fe80::216:cbff:fe9a:4cb9 131 ff02::1:ff9a:4cb9 130 icmp - 4.922880 32 0 OTH - 0 - 2 144 0 0 CCvvfg3TEfuqmmG4bh +#close 2013-08-26-18-38-29 diff --git a/testing/btest/Baseline/core.tunnels.ayiya/http.log b/testing/btest/Baseline/core.tunnels.ayiya/http.log index cc0cf32148..7fa21931d0 100644 --- a/testing/btest/Baseline/core.tunnels.ayiya/http.log +++ b/testing/btest/Baseline/core.tunnels.ayiya/http.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-21-12-29 +#open 2013-08-26-19-34-59 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1257655301.652206 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 10102 200 OK - - - (empty) - - - - - meGKu6goEyd text/html -1257655302.514424 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 2 GET ipv6.google.com /csi?v=3&s=webhp&action=&tran=undefined&e=17259,19771,21517,21766,21887,22212&ei=BUz2Su7PMJTglQfz3NzCAw&rt=prt.77,xjs.565,ol.645 http://ipv6.google.com/ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 0 204 No Content - - - (empty) - - - - - - - -1257655303.603569 5OKnoww6xl4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 3 GET ipv6.google.com /gen_204?atyp=i&ct=fade&cad=1254&ei=BUz2Su7PMJTglQfz3NzCAw&zx=1257655303600 http://ipv6.google.com/ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 0 204 No Content - - - (empty) - - - - - - - -#close 2013-07-25-21-12-29 +1257655301.652206 CIPOse170MGiRM1Qf4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 10102 200 OK - - - (empty) - - - - - FYAtjT24MvCBUs5K5f text/html +1257655302.514424 CIPOse170MGiRM1Qf4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 2 GET ipv6.google.com /csi?v=3&s=webhp&action=&tran=undefined&e=17259,19771,21517,21766,21887,22212&ei=BUz2Su7PMJTglQfz3NzCAw&rt=prt.77,xjs.565,ol.645 http://ipv6.google.com/ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 0 204 No Content - - - (empty) - - - - - - - +1257655303.603569 CIPOse170MGiRM1Qf4 2001:4978:f:4c::2 53382 2001:4860:b002::68 80 3 GET ipv6.google.com /gen_204?atyp=i&ct=fade&cad=1254&ei=BUz2Su7PMJTglQfz3NzCAw&zx=1257655303600 http://ipv6.google.com/ Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.15pre) Gecko/2009091516 Camino/2.0b4 (like Firefox/3.0.15pre) 0 0 204 No Content - - - (empty) - - - - - - - +#close 2013-08-26-19-34-59 diff --git a/testing/btest/Baseline/core.tunnels.ayiya/tunnel.log b/testing/btest/Baseline/core.tunnels.ayiya/tunnel.log index 60e0a4a108..050192c32e 100644 --- a/testing/btest/Baseline/core.tunnels.ayiya/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.ayiya/tunnel.log @@ -3,11 +3,11 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2009-11-08-04-41-33 +#open 2013-08-26-19-02-15 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1257655293.629048 UWkUyAuUGXf 192.168.3.101 53796 216.14.98.22 5072 Tunnel::AYIYA Tunnel::DISCOVER -1257655296.585034 k6kgXLOoSKl 192.168.3.101 53859 216.14.98.22 5072 Tunnel::AYIYA Tunnel::DISCOVER -1257655317.464035 k6kgXLOoSKl 192.168.3.101 53859 216.14.98.22 5072 Tunnel::AYIYA Tunnel::CLOSE -1257655317.464035 UWkUyAuUGXf 192.168.3.101 53796 216.14.98.22 5072 Tunnel::AYIYA Tunnel::CLOSE -#close 2009-11-08-04-41-57 +1257655293.629048 CXWv6p3arKYeMETxOg 192.168.3.101 53796 216.14.98.22 5072 Tunnel::AYIYA Tunnel::DISCOVER +1257655296.585034 CCvvfg3TEfuqmmG4bh 192.168.3.101 53859 216.14.98.22 5072 Tunnel::AYIYA Tunnel::DISCOVER +1257655317.464035 CCvvfg3TEfuqmmG4bh 192.168.3.101 53859 216.14.98.22 5072 Tunnel::AYIYA Tunnel::CLOSE +1257655317.464035 CXWv6p3arKYeMETxOg 192.168.3.101 53796 216.14.98.22 5072 Tunnel::AYIYA Tunnel::CLOSE +#close 2013-08-26-19-02-15 diff --git a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/conn.log b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/conn.log index e2861b4ae1..d696f70259 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/conn.log +++ b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/conn.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-19-17-03-55 +#open 2013-08-26-18-38-29 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1333458850.321642 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 tcp http 0.257902 1138 63424 S3 - 0 ShADadf 29 2310 49 65396 UWkUyAuUGXf,k6kgXLOoSKl -1333458850.325787 k6kgXLOoSKl 207.233.125.40 2152 167.55.105.244 2152 udp gtpv1 0.251127 65788 0 S0 - 0 D 49 67160 0 0 (empty) -1333458850.321642 UWkUyAuUGXf 167.55.105.244 5906 207.233.125.40 2152 udp gtpv1 0.257902 2542 0 S0 - 0 D 29 3354 0 0 (empty) -#close 2012-10-19-17-03-55 +1333458850.321642 CjhGID4nQcgTWjvg4c 10.131.17.170 51803 173.199.115.168 80 tcp http 0.257902 1138 63424 S3 - 0 ShADadf 29 2310 49 65396 CXWv6p3arKYeMETxOg,CCvvfg3TEfuqmmG4bh +1333458850.325787 CCvvfg3TEfuqmmG4bh 207.233.125.40 2152 167.55.105.244 2152 udp gtpv1 0.251127 65788 0 S0 - 0 D 49 67160 0 0 (empty) +1333458850.321642 CXWv6p3arKYeMETxOg 167.55.105.244 5906 207.233.125.40 2152 udp gtpv1 0.257902 2542 0 S0 - 0 D 29 3354 0 0 (empty) +#close 2013-08-26-18-38-29 diff --git a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log index 8f9ac07c96..f8715d86c2 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log +++ b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/http.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-16-23-41 +#open 2013-08-26-19-02-16 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1333458850.340368 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 1 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=4&cac=1&t=728x90&cb=1333458879 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&channel=4&cb=1333458905296 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - - - 6jqjOyeITn5 application/x-shockwave-flash -1333458850.399501 arKYeMETxOg 10.131.17.170 51803 173.199.115.168 80 2 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=0&cac=1&t=728x90&cb=1333458881 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&cb=1333458920207 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - - - A0xot7xPc22 application/x-shockwave-flash -#close 2013-07-25-16-23-41 +1333458850.340368 CjhGID4nQcgTWjvg4c 10.131.17.170 51803 173.199.115.168 80 1 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=4&cac=1&t=728x90&cb=1333458879 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&channel=4&cb=1333458905296 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - - - FHKKd91EMHBEK0hbdg application/x-shockwave-flash +1333458850.399501 CjhGID4nQcgTWjvg4c 10.131.17.170 51803 173.199.115.168 80 2 GET cdn.epicgameads.com /ads/flash/728x90_nx8com.swf?clickTAG=http://www.epicgameads.com/ads/bannerclickPage.php?id=e3ubwU6IF&pd=1&adid=0&icpc=1&axid=0&uctt=1&channel=0&cac=1&t=728x90&cb=1333458881 http://www.epicgameads.com/ads/banneriframe.php?id=e3ubwU6IF&t=728x90&cb=1333458920207 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) 0 31461 200 OK - - - (empty) - - - - - Fu64Vqjy6nBop9nRd application/x-shockwave-flash +#close 2013-08-26-19-02-16 diff --git a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/tunnel.log index 233ad1c850..4c3a5a89a4 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.gtp.different_dl_and_ul/tunnel.log @@ -3,11 +3,11 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2012-10-19-17-03-55 +#open 2013-08-26-19-34-59 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1333458850.321642 UWkUyAuUGXf 167.55.105.244 5906 207.233.125.40 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.325787 k6kgXLOoSKl 207.233.125.40 2152 167.55.105.244 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.579544 k6kgXLOoSKl 207.233.125.40 2152 167.55.105.244 2152 Tunnel::GTPv1 Tunnel::CLOSE -1333458850.579544 UWkUyAuUGXf 167.55.105.244 5906 207.233.125.40 2152 Tunnel::GTPv1 Tunnel::CLOSE -#close 2012-10-19-17-03-55 +1333458850.321642 CXWv6p3arKYeMETxOg 167.55.105.244 5906 207.233.125.40 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.325787 CCvvfg3TEfuqmmG4bh 207.233.125.40 2152 167.55.105.244 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.579544 CCvvfg3TEfuqmmG4bh 207.233.125.40 2152 167.55.105.244 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.579544 CXWv6p3arKYeMETxOg 167.55.105.244 5906 207.233.125.40 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2013-08-26-19-34-59 diff --git a/testing/btest/Baseline/core.tunnels.gtp.false_gtp/conn.log b/testing/btest/Baseline/core.tunnels.gtp.false_gtp/conn.log index 1234558195..4b65626908 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.false_gtp/conn.log +++ b/testing/btest/Baseline/core.tunnels.gtp.false_gtp/conn.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-19-17-07-44 +#open 2013-08-26-19-02-17 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1333458871.219794 UWkUyAuUGXf 10.131.24.6 2152 195.178.38.3 53 udp dns - - - S0 - 0 D 1 64 0 0 (empty) -#close 2012-10-19-17-07-44 +1333458871.219794 CXWv6p3arKYeMETxOg 10.131.24.6 2152 195.178.38.3 53 udp dns - - - S0 - 0 D 1 64 0 0 (empty) +#close 2013-08-26-19-02-17 diff --git a/testing/btest/Baseline/core.tunnels.gtp.false_gtp/dns.log b/testing/btest/Baseline/core.tunnels.gtp.false_gtp/dns.log index a293d6ff6a..d1b3b53389 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.false_gtp/dns.log +++ b/testing/btest/Baseline/core.tunnels.gtp.false_gtp/dns.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dns -#open 2012-10-19-17-07-44 +#open 2013-08-26-19-35-00 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected #types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] bool -1333458871.219794 UWkUyAuUGXf 10.131.24.6 2152 195.178.38.3 53 udp 27595 abcd.efg.hijklm.nm 1 C_INTERNET 1 A - - F F T F 0 - - F -#close 2012-10-19-17-07-44 +1333458871.219794 CXWv6p3arKYeMETxOg 10.131.24.6 2152 195.178.38.3 53 udp 27595 abcd.efg.hijklm.nm 1 C_INTERNET 1 A - - F F T F 0 - - F +#close 2013-08-26-19-35-00 diff --git a/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/conn.log b/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/conn.log index 326205172a..ee444fe4f1 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/conn.log +++ b/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/conn.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-19-17-21-27 +#open 2013-08-26-18-38-30 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1333458851.770000 arKYeMETxOg fe80::224c:4fff:fe43:414c 1234 ff02::1:3 5355 udp dns - - - S0 - 0 D 1 80 0 0 UWkUyAuUGXf -1333458851.770000 UWkUyAuUGXf 118.92.124.41 2152 118.92.124.72 2152 udp gtpv1 0.199236 152 0 S0 - 0 D 2 208 0 0 (empty) -1333458851.969236 k6kgXLOoSKl fe80::224c:4fff:fe43:414c 133 ff02::2 134 icmp - - - - OTH - 0 - 1 56 0 0 UWkUyAuUGXf -#close 2012-10-19-17-21-27 +1333458851.770000 CjhGID4nQcgTWjvg4c fe80::224c:4fff:fe43:414c 1234 ff02::1:3 5355 udp dns - - - S0 - 0 D 1 80 0 0 CXWv6p3arKYeMETxOg +1333458851.770000 CXWv6p3arKYeMETxOg 118.92.124.41 2152 118.92.124.72 2152 udp gtpv1 0.199236 152 0 S0 - 0 D 2 208 0 0 (empty) +1333458851.969236 CCvvfg3TEfuqmmG4bh fe80::224c:4fff:fe43:414c 133 ff02::2 134 icmp - - - - OTH - 0 - 1 56 0 0 CXWv6p3arKYeMETxOg +#close 2013-08-26-18-38-30 diff --git a/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/tunnel.log index dfae2ba269..2f7602118c 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.gtp.inner_ipv6/tunnel.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2012-10-19-17-21-27 +#open 2013-08-26-19-02-17 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1333458851.770000 UWkUyAuUGXf 118.92.124.41 2152 118.92.124.72 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458851.969236 UWkUyAuUGXf 118.92.124.41 2152 118.92.124.72 2152 Tunnel::GTPv1 Tunnel::CLOSE -#close 2012-10-19-17-21-27 +1333458851.770000 CXWv6p3arKYeMETxOg 118.92.124.41 2152 118.92.124.72 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458851.969236 CXWv6p3arKYeMETxOg 118.92.124.41 2152 118.92.124.72 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2013-08-26-19-02-17 diff --git a/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/conn.log b/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/conn.log index 9c3e1f6f66..9ec1472184 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/conn.log +++ b/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/conn.log @@ -3,24 +3,24 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-19-17-34-25 +#open 2013-08-26-18-38-30 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1333458850.037956 qCaWGmzFtM5 10.131.112.102 51403 94.245.121.253 3544 udp teredo - - - SHR - 0 d 0 0 1 84 GSxOnSLghOa -1333458850.040098 70MGiRM1Qf4 174.94.190.229 2152 190.104.181.57 2152 udp gtpv1 0.003698 192 0 S0 - 0 D 2 248 0 0 (empty) -1333458850.016620 nQcgTWjvg4c 172.24.16.121 61901 94.245.121.251 3544 udp teredo - - - S0 - 0 D 1 80 0 0 k6kgXLOoSKl -1333458850.029781 FrJExwHcSal 172.24.16.67 52298 94.245.121.253 3544 udp teredo - - - S0 - 0 D 1 88 0 0 TEfuqmmG4bh -1333458850.035456 VW0XPVINV8a 190.104.181.210 2152 190.104.181.125 2152 udp gtpv1 0.000004 194 0 S0 - 0 D 2 250 0 0 (empty) -1333458850.016620 k6kgXLOoSKl 174.94.190.229 2152 190.104.181.62 2152 udp gtpv1 0.016267 88 92 SF - 0 Dd 1 116 1 120 (empty) -1333458850.029781 TEfuqmmG4bh 190.104.181.254 2152 190.104.181.62 2152 udp gtpv1 0.000002 192 0 S0 - 0 D 2 248 0 0 (empty) -1333458850.035460 iE6yhOq3SF 172.27.159.9 63912 94.245.121.254 3544 udp teredo - - - S0 - 0 D 1 89 0 0 VW0XPVINV8a -1333458850.037956 GSxOnSLghOa 190.104.181.57 2152 190.104.181.222 2152 udp gtpv1 - - - S0 - 0 D 1 120 0 0 (empty) -1333458850.014199 UWkUyAuUGXf 174.94.190.213 2152 190.104.181.57 2152 udp gtpv1 - - - S0 - 0 D 1 124 0 0 (empty) -1333458850.040098 h5DsfNtYzi1 172.24.203.81 54447 65.55.158.118 3544 udp teredo 0.003698 120 0 S0 - 0 D 2 176 0 0 70MGiRM1Qf4 -1333458850.029783 5OKnoww6xl4 172.24.16.67 52298 65.55.158.118 3544 udp teredo - - - S0 - 0 D 1 88 0 0 TEfuqmmG4bh -1333458850.032887 3PKsZ2Uye21 10.131.42.160 62069 94.245.121.253 3544 udp teredo - - - SHR - 0 d 0 0 1 84 k6kgXLOoSKl -1333458850.014199 arKYeMETxOg 172.24.204.200 56528 65.55.158.118 3544 udp teredo - - - S0 - 0 D 1 88 0 0 UWkUyAuUGXf -1333458850.035456 fRFu0wcOle6 172.27.159.9 63912 94.245.121.253 3544 udp teredo - - - S0 - 0 D 1 89 0 0 VW0XPVINV8a -1333458850.016620 j4u32Pc5bif 2001:0:5ef5:79fb:38b8:1695:2b37:be8e 128 2002:2571:c817::2571:c817 129 icmp - - - - OTH - 0 - 1 52 0 0 nQcgTWjvg4c -1333458850.035456 qSsw6ESzHV4 fe80::ffff:ffff:fffe 133 ff02::2 134 icmp - 0.000004 0 0 OTH - 0 - 2 96 0 0 fRFu0wcOle6,iE6yhOq3SF -#close 2012-10-19-17-34-25 +1333458850.037956 CEle3f3zno26fFZkrh 10.131.112.102 51403 94.245.121.253 3544 udp teredo - - - SHR - 0 d 0 0 1 84 C3SfNE4BWaU4aSuwkc +1333458850.040098 CwSkQu4eWZCH7OONC1 174.94.190.229 2152 190.104.181.57 2152 udp gtpv1 0.003698 192 0 S0 - 0 D 2 248 0 0 (empty) +1333458850.016620 CsRx2w45OKnoww6xl4 172.24.16.121 61901 94.245.121.251 3544 udp teredo - - - S0 - 0 D 1 80 0 0 CCvvfg3TEfuqmmG4bh +1333458850.029781 C6pKV8GSxOnSLghOa 172.24.16.67 52298 94.245.121.253 3544 udp teredo - - - S0 - 0 D 1 88 0 0 CPbrpk1qSsw6ESzHV4 +1333458850.035456 CJ3xTn1c4Zw9TmAE05 190.104.181.210 2152 190.104.181.125 2152 udp gtpv1 0.000004 194 0 S0 - 0 D 2 250 0 0 (empty) +1333458850.016620 CCvvfg3TEfuqmmG4bh 174.94.190.229 2152 190.104.181.62 2152 udp gtpv1 0.016267 88 92 SF - 0 Dd 1 116 1 120 (empty) +1333458850.029781 CPbrpk1qSsw6ESzHV4 190.104.181.254 2152 190.104.181.62 2152 udp gtpv1 0.000002 192 0 S0 - 0 D 2 248 0 0 (empty) +1333458850.035460 Che1bq3i2rO3KD1Syg 172.27.159.9 63912 94.245.121.254 3544 udp teredo - - - S0 - 0 D 1 89 0 0 CJ3xTn1c4Zw9TmAE05 +1333458850.037956 C3SfNE4BWaU4aSuwkc 190.104.181.57 2152 190.104.181.222 2152 udp gtpv1 - - - S0 - 0 D 1 120 0 0 (empty) +1333458850.014199 CXWv6p3arKYeMETxOg 174.94.190.213 2152 190.104.181.57 2152 udp gtpv1 - - - S0 - 0 D 1 124 0 0 (empty) +1333458850.040098 CfTOmO0HKorjr8Zp7 172.24.203.81 54447 65.55.158.118 3544 udp teredo 0.003698 120 0 S0 - 0 D 2 176 0 0 CwSkQu4eWZCH7OONC1 +1333458850.029783 CIPOse170MGiRM1Qf4 172.24.16.67 52298 65.55.158.118 3544 udp teredo - - - S0 - 0 D 1 88 0 0 CPbrpk1qSsw6ESzHV4 +1333458850.032887 C7XEbhP654jzLoe3a 10.131.42.160 62069 94.245.121.253 3544 udp teredo - - - SHR - 0 d 0 0 1 84 CCvvfg3TEfuqmmG4bh +1333458850.014199 CjhGID4nQcgTWjvg4c 172.24.204.200 56528 65.55.158.118 3544 udp teredo - - - S0 - 0 D 1 88 0 0 CXWv6p3arKYeMETxOg +1333458850.035456 CMXxB5GvmoxJFXdTa 172.27.159.9 63912 94.245.121.253 3544 udp teredo - - - S0 - 0 D 1 89 0 0 CJ3xTn1c4Zw9TmAE05 +1333458850.016620 CRJuHdVW0XPVINV8a 2001:0:5ef5:79fb:38b8:1695:2b37:be8e 128 2002:2571:c817::2571:c817 129 icmp - - - - OTH - 0 - 1 52 0 0 CsRx2w45OKnoww6xl4 +1333458850.035456 Caby8b1slFea8xwSmb fe80::ffff:ffff:fffe 133 ff02::2 134 icmp - 0.000004 0 0 OTH - 0 - 2 96 0 0 Che1bq3i2rO3KD1Syg,CMXxB5GvmoxJFXdTa +#close 2013-08-26-18-38-30 diff --git a/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/tunnel.log index 904fcc7db6..a847e18f0f 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.gtp.inner_teredo/tunnel.log @@ -3,25 +3,25 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2012-10-19-17-34-25 +#open 2013-08-26-19-02-17 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1333458850.014199 UWkUyAuUGXf 174.94.190.213 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.016620 k6kgXLOoSKl 174.94.190.229 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.016620 nQcgTWjvg4c 172.24.16.121 61901 94.245.121.251 3544 Tunnel::TEREDO Tunnel::DISCOVER -1333458850.029781 TEfuqmmG4bh 190.104.181.254 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.035456 VW0XPVINV8a 190.104.181.210 2152 190.104.181.125 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.035456 fRFu0wcOle6 172.27.159.9 63912 94.245.121.253 3544 Tunnel::TEREDO Tunnel::DISCOVER -1333458850.035460 iE6yhOq3SF 172.27.159.9 63912 94.245.121.254 3544 Tunnel::TEREDO Tunnel::DISCOVER -1333458850.037956 GSxOnSLghOa 190.104.181.57 2152 190.104.181.222 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.040098 70MGiRM1Qf4 174.94.190.229 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.043796 70MGiRM1Qf4 174.94.190.229 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::CLOSE -1333458850.043796 nQcgTWjvg4c 172.24.16.121 61901 94.245.121.251 3544 Tunnel::TEREDO Tunnel::CLOSE -1333458850.043796 VW0XPVINV8a 190.104.181.210 2152 190.104.181.125 2152 Tunnel::GTPv1 Tunnel::CLOSE -1333458850.043796 k6kgXLOoSKl 174.94.190.229 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::CLOSE -1333458850.043796 TEfuqmmG4bh 190.104.181.254 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::CLOSE -1333458850.043796 iE6yhOq3SF 172.27.159.9 63912 94.245.121.254 3544 Tunnel::TEREDO Tunnel::CLOSE -1333458850.043796 GSxOnSLghOa 190.104.181.57 2152 190.104.181.222 2152 Tunnel::GTPv1 Tunnel::CLOSE -1333458850.043796 UWkUyAuUGXf 174.94.190.213 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::CLOSE -1333458850.043796 fRFu0wcOle6 172.27.159.9 63912 94.245.121.253 3544 Tunnel::TEREDO Tunnel::CLOSE -#close 2012-10-19-17-34-25 +1333458850.014199 CXWv6p3arKYeMETxOg 174.94.190.213 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.016620 CCvvfg3TEfuqmmG4bh 174.94.190.229 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.016620 CsRx2w45OKnoww6xl4 172.24.16.121 61901 94.245.121.251 3544 Tunnel::TEREDO Tunnel::DISCOVER +1333458850.029781 CPbrpk1qSsw6ESzHV4 190.104.181.254 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.035456 CJ3xTn1c4Zw9TmAE05 190.104.181.210 2152 190.104.181.125 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.035456 CMXxB5GvmoxJFXdTa 172.27.159.9 63912 94.245.121.253 3544 Tunnel::TEREDO Tunnel::DISCOVER +1333458850.035460 Che1bq3i2rO3KD1Syg 172.27.159.9 63912 94.245.121.254 3544 Tunnel::TEREDO Tunnel::DISCOVER +1333458850.037956 C3SfNE4BWaU4aSuwkc 190.104.181.57 2152 190.104.181.222 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.040098 CwSkQu4eWZCH7OONC1 174.94.190.229 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.043796 CwSkQu4eWZCH7OONC1 174.94.190.229 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 CsRx2w45OKnoww6xl4 172.24.16.121 61901 94.245.121.251 3544 Tunnel::TEREDO Tunnel::CLOSE +1333458850.043796 CJ3xTn1c4Zw9TmAE05 190.104.181.210 2152 190.104.181.125 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 CCvvfg3TEfuqmmG4bh 174.94.190.229 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 CPbrpk1qSsw6ESzHV4 190.104.181.254 2152 190.104.181.62 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 Che1bq3i2rO3KD1Syg 172.27.159.9 63912 94.245.121.254 3544 Tunnel::TEREDO Tunnel::CLOSE +1333458850.043796 C3SfNE4BWaU4aSuwkc 190.104.181.57 2152 190.104.181.222 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 CXWv6p3arKYeMETxOg 174.94.190.213 2152 190.104.181.57 2152 Tunnel::GTPv1 Tunnel::CLOSE +1333458850.043796 CMXxB5GvmoxJFXdTa 172.27.159.9 63912 94.245.121.253 3544 Tunnel::TEREDO Tunnel::CLOSE +#close 2013-08-26-19-02-17 diff --git a/testing/btest/Baseline/core.tunnels.gtp.not_user_plane_data/conn.log b/testing/btest/Baseline/core.tunnels.gtp.not_user_plane_data/conn.log index ad6e4fb2c4..06426dd65e 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.not_user_plane_data/conn.log +++ b/testing/btest/Baseline/core.tunnels.gtp.not_user_plane_data/conn.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-19-17-46-48 +#open 2013-08-26-19-02-18 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1333458850.532814 UWkUyAuUGXf 247.56.43.90 2152 247.56.43.248 2152 udp - - - - S0 - 0 D 1 52 0 0 (empty) -1333458850.867091 arKYeMETxOg 247.56.43.214 2152 237.56.101.238 2152 udp - 0.028676 12 14 SF - 0 Dd 1 40 1 42 (empty) -#close 2012-10-19-17-46-48 +1333458850.532814 CXWv6p3arKYeMETxOg 247.56.43.90 2152 247.56.43.248 2152 udp - - - - S0 - 0 D 1 52 0 0 (empty) +1333458850.867091 CjhGID4nQcgTWjvg4c 247.56.43.214 2152 237.56.101.238 2152 udp - 0.028676 12 14 SF - 0 Dd 1 40 1 42 (empty) +#close 2013-08-26-19-02-18 diff --git a/testing/btest/Baseline/core.tunnels.gtp.opt_header/conn.log b/testing/btest/Baseline/core.tunnels.gtp.opt_header/conn.log index 9f250903f2..cd33ef39f8 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.opt_header/conn.log +++ b/testing/btest/Baseline/core.tunnels.gtp.opt_header/conn.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-19-17-19-16 +#open 2013-08-26-18-38-31 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1333458852.011535 arKYeMETxOg 10.222.10.10 44960 173.194.69.188 5228 tcp ssl 0.573499 704 1026 S1 - 0 ShADad 17 1604 14 1762 UWkUyAuUGXf -1333458852.011535 UWkUyAuUGXf 79.188.154.91 2152 243.149.173.198 2152 udp gtpv1 0.573499 1740 1930 SF - 0 Dd 17 2216 14 2322 (empty) -#close 2012-10-19-17-19-16 +1333458852.011535 CjhGID4nQcgTWjvg4c 10.222.10.10 44960 173.194.69.188 5228 tcp ssl 0.573499 704 1026 S1 - 0 ShADad 17 1604 14 1762 CXWv6p3arKYeMETxOg +1333458852.011535 CXWv6p3arKYeMETxOg 79.188.154.91 2152 243.149.173.198 2152 udp gtpv1 0.573499 1740 1930 SF - 0 Dd 17 2216 14 2322 (empty) +#close 2013-08-26-18-38-31 diff --git a/testing/btest/Baseline/core.tunnels.gtp.opt_header/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.opt_header/tunnel.log index a421f399ec..f3490db955 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.opt_header/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.gtp.opt_header/tunnel.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2012-10-19-17-19-16 +#open 2013-08-26-19-02-18 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1333458852.011535 UWkUyAuUGXf 79.188.154.91 2152 243.149.173.198 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458852.585034 UWkUyAuUGXf 79.188.154.91 2152 243.149.173.198 2152 Tunnel::GTPv1 Tunnel::CLOSE -#close 2012-10-19-17-19-16 +1333458852.011535 CXWv6p3arKYeMETxOg 79.188.154.91 2152 243.149.173.198 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458852.585034 CXWv6p3arKYeMETxOg 79.188.154.91 2152 243.149.173.198 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2013-08-26-19-02-18 diff --git a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/conn.log b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/conn.log index b5f61564cf..bc21b87714 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/conn.log +++ b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/conn.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-19-16-44-02 +#open 2013-08-26-18-38-31 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1333458850.364667 arKYeMETxOg 10.131.47.185 1923 79.101.110.141 80 tcp http 0.069783 2100 56702 SF - 0 ShADadfF 27 3204 41 52594 UWkUyAuUGXf -1333458850.364667 UWkUyAuUGXf 239.114.155.111 2152 63.94.149.181 2152 udp gtpv1 0.069813 3420 52922 SF - 0 Dd 27 4176 41 54070 (empty) -#close 2012-10-19-16-44-02 +1333458850.364667 CjhGID4nQcgTWjvg4c 10.131.47.185 1923 79.101.110.141 80 tcp http 0.069783 2100 56702 SF - 0 ShADadfF 27 3204 41 52594 CXWv6p3arKYeMETxOg +1333458850.364667 CXWv6p3arKYeMETxOg 239.114.155.111 2152 63.94.149.181 2152 udp gtpv1 0.069813 3420 52922 SF - 0 Dd 27 4176 41 54070 (empty) +#close 2013-08-26-18-38-31 diff --git a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log index 45b88b7813..20408a08fe 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log +++ b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-21-12-32 +#open 2013-08-26-19-02-18 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1333458850.375568 arKYeMETxOg 10.131.47.185 1923 79.101.110.141 80 1 GET o-o.preferred.telekomrs-beg1.v2.lscache8.c.youtube.com /videoplayback?upn=MTU2MDY5NzQ5OTM0NTI3NDY4NDc&sparams=algorithm,burst,cp,factor,id,ip,ipbits,itag,source,upn,expire&fexp=912300,907210&algorithm=throttle-factor&itag=34&ip=212.0.0.0&burst=40&sver=3&signature=832FB1042E20780CFCA77A4DB5EA64AC593E8627.D1166C7E8365732E52DAFD68076DAE0146E0AE01&source=youtube&expire=1333484980&key=yt1&ipbits=8&factor=1.25&cp=U0hSSFRTUl9NSkNOMl9MTVZKOjh5eEN2SG8tZF84&id=ebf1e932d4bd1286&cm2=1 http://s.ytimg.com/yt/swfbin/watch_as3-vflqrJwOA.swf Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko; X-SBLSP) Chrome/17.0.963.83 Safari/535.11 0 56320 206 Partial Content - - - (empty) - - - - - oypNlaRdgs7 application/octet-stream -#close 2013-07-25-21-12-32 +1333458850.375568 CjhGID4nQcgTWjvg4c 10.131.47.185 1923 79.101.110.141 80 1 GET o-o.preferred.telekomrs-beg1.v2.lscache8.c.youtube.com /videoplayback?upn=MTU2MDY5NzQ5OTM0NTI3NDY4NDc&sparams=algorithm,burst,cp,factor,id,ip,ipbits,itag,source,upn,expire&fexp=912300,907210&algorithm=throttle-factor&itag=34&ip=212.0.0.0&burst=40&sver=3&signature=832FB1042E20780CFCA77A4DB5EA64AC593E8627.D1166C7E8365732E52DAFD68076DAE0146E0AE01&source=youtube&expire=1333484980&key=yt1&ipbits=8&factor=1.25&cp=U0hSSFRTUl9NSkNOMl9MTVZKOjh5eEN2SG8tZF84&id=ebf1e932d4bd1286&cm2=1 http://s.ytimg.com/yt/swfbin/watch_as3-vflqrJwOA.swf Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko; X-SBLSP) Chrome/17.0.963.83 Safari/535.11 0 56320 206 Partial Content - - - (empty) - - - - - FNJkBA1b8FSHt5N8jl application/octet-stream +#close 2013-08-26-19-02-18 diff --git a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/tunnel.log index 54c4acd0d6..ba82f055ea 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.gtp.outer_ip_frag/tunnel.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2012-10-19-16-44-02 +#open 2013-08-26-19-35-01 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1333458850.364667 UWkUyAuUGXf 239.114.155.111 2152 63.94.149.181 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458850.434480 UWkUyAuUGXf 239.114.155.111 2152 63.94.149.181 2152 Tunnel::GTPv1 Tunnel::CLOSE -#close 2012-10-19-16-44-02 +1333458850.364667 CXWv6p3arKYeMETxOg 239.114.155.111 2152 63.94.149.181 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458850.434480 CXWv6p3arKYeMETxOg 239.114.155.111 2152 63.94.149.181 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2013-08-26-19-35-01 diff --git a/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/dpd.log b/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/dpd.log index fcd110f8ab..2dbe011a5a 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/dpd.log +++ b/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/dpd.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dpd -#open 2013-01-25-21-49-19 +#open 2013-08-26-19-02-18 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto analyzer failure_reason #types time string addr port addr port enum string string -1333458853.075889 UWkUyAuUGXf 173.86.159.28 2152 213.72.147.186 2152 udp GTPV1 Truncated GTPv1 [0\xff\x00\xac\x98\x13\x01LE\x00\x05\xc8G\xea@\x00\x80\x06\xb6\x83\x0a\x83w&\xd9\x14\x9c\x04\xd9\xc2\x00P\xddh\xb4\x8f41eV...] -#close 2013-01-25-21-49-19 +1333458853.075889 CXWv6p3arKYeMETxOg 173.86.159.28 2152 213.72.147.186 2152 udp GTPV1 Truncated GTPv1 [0\xff\x00\xac\x98\x13\x01LE\x00\x05\xc8G\xea@\x00\x80\x06\xb6\x83\x0a\x83w&\xd9\x14\x9c\x04\xd9\xc2\x00P\xddh\xb4\x8f41eV...] +#close 2013-08-26-19-02-18 diff --git a/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/tunnel.log b/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/tunnel.log index 070a754702..c70c8536b7 100644 --- a/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.gtp.unknown_or_too_short/tunnel.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2013-01-25-21-49-19 +#open 2013-08-26-19-35-01 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1333458853.034734 UWkUyAuUGXf 173.86.159.28 2152 213.72.147.186 2152 Tunnel::GTPv1 Tunnel::DISCOVER -1333458853.108391 UWkUyAuUGXf 173.86.159.28 2152 213.72.147.186 2152 Tunnel::GTPv1 Tunnel::CLOSE -#close 2013-01-25-21-49-19 +1333458853.034734 CXWv6p3arKYeMETxOg 173.86.159.28 2152 213.72.147.186 2152 Tunnel::GTPv1 Tunnel::DISCOVER +1333458853.108391 CXWv6p3arKYeMETxOg 173.86.159.28 2152 213.72.147.186 2152 Tunnel::GTPv1 Tunnel::CLOSE +#close 2013-08-26-19-35-01 diff --git a/testing/btest/Baseline/core.tunnels.ip-in-ip/output b/testing/btest/Baseline/core.tunnels.ip-in-ip/output index 4c8738290f..08a350c3a7 100644 --- a/testing/btest/Baseline/core.tunnels.ip-in-ip/output +++ b/testing/btest/Baseline/core.tunnels.ip-in-ip/output @@ -1,22 +1,22 @@ new_connection: tunnel conn_id: [orig_h=dead::beef, orig_p=30000/udp, resp_h=cafe::babe, resp_p=13000/udp] - encap: [[cid=[orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=0/unknown, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + encap: [[cid=[orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=0/unknown, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] new_connection: tunnel conn_id: [orig_h=dead::beef, orig_p=30000/udp, resp_h=cafe::babe, resp_p=13000/udp] - encap: [[cid=[orig_h=feed::beef, orig_p=0/unknown, resp_h=feed::cafe, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf], [cid=[orig_h=babe::beef, orig_p=0/unknown, resp_h=dead::babe, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=arKYeMETxOg]] + encap: [[cid=[orig_h=feed::beef, orig_p=0/unknown, resp_h=feed::cafe, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg], [cid=[orig_h=babe::beef, orig_p=0/unknown, resp_h=dead::babe, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CjhGID4nQcgTWjvg4c]] new_connection: tunnel conn_id: [orig_h=dead::beef, orig_p=30000/udp, resp_h=cafe::babe, resp_p=13000/udp] - encap: [[cid=[orig_h=1.2.3.4, orig_p=0/unknown, resp_h=5.6.7.8, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + encap: [[cid=[orig_h=1.2.3.4, orig_p=0/unknown, resp_h=5.6.7.8, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] new_connection: tunnel conn_id: [orig_h=70.55.213.211, orig_p=31337/tcp, resp_h=192.88.99.1, resp_p=80/tcp] - encap: [[cid=[orig_h=2002:4637:d5d3::4637:d5d3, orig_p=0/unknown, resp_h=2001:4860:0:2001::68, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + encap: [[cid=[orig_h=2002:4637:d5d3::4637:d5d3, orig_p=0/unknown, resp_h=2001:4860:0:2001::68, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] new_connection: tunnel conn_id: [orig_h=10.0.0.1, orig_p=30000/udp, resp_h=10.0.0.2, resp_p=13000/udp] - encap: [[cid=[orig_h=1.2.3.4, orig_p=0/unknown, resp_h=5.6.7.8, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + encap: [[cid=[orig_h=1.2.3.4, orig_p=0/unknown, resp_h=5.6.7.8, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] new_connection: tunnel conn_id: [orig_h=dead::beef, orig_p=30000/udp, resp_h=cafe::babe, resp_p=13000/udp] - encap: [[cid=[orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=0/unknown, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + encap: [[cid=[orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=0/unknown, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] tunnel_changed: conn_id: [orig_h=dead::beef, orig_p=30000/udp, resp_h=cafe::babe, resp_p=13000/udp] - old: [[cid=[orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=0/unknown, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] - new: [[cid=[orig_h=feed::beef, orig_p=0/unknown, resp_h=feed::cafe, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=k6kgXLOoSKl]] + old: [[cid=[orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=0/unknown, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] + new: [[cid=[orig_h=feed::beef, orig_p=0/unknown, resp_h=feed::cafe, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CCvvfg3TEfuqmmG4bh]] diff --git a/testing/btest/Baseline/core.tunnels.ip-tunnel-uid/output b/testing/btest/Baseline/core.tunnels.ip-tunnel-uid/output index afb5837b23..5f683413d4 100644 --- a/testing/btest/Baseline/core.tunnels.ip-tunnel-uid/output +++ b/testing/btest/Baseline/core.tunnels.ip-tunnel-uid/output @@ -1,33 +1,33 @@ new_connection: tunnel conn_id: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - encap: [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + encap: [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] NEW_PACKET: [orig_h=2001:db8:0:1::1, orig_p=128/icmp, resp_h=2001:db8:0:1::2, resp_p=129/icmp] - [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=UWkUyAuUGXf]] + [[cid=[orig_h=10.0.0.1, orig_p=0/unknown, resp_h=10.0.0.2, resp_p=0/unknown], tunnel_type=Tunnel::IP, uid=CXWv6p3arKYeMETxOg]] diff --git a/testing/btest/Baseline/core.tunnels.teredo/conn.log b/testing/btest/Baseline/core.tunnels.teredo/conn.log index 8bb55e11d2..20d5a270ce 100644 --- a/testing/btest/Baseline/core.tunnels.teredo/conn.log +++ b/testing/btest/Baseline/core.tunnels.teredo/conn.log @@ -3,28 +3,28 @@ #empty_field (empty) #unset_field - #path conn -#open 2013-08-04-03-28-45 +#open 2013-08-26-18-38-32 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1210953047.736921 arKYeMETxOg 192.168.2.16 1576 75.126.130.163 80 tcp - 0.000357 0 0 SHR - 0 fA 1 40 1 40 (empty) -1210953050.867067 k6kgXLOoSKl 192.168.2.16 1577 75.126.203.78 80 tcp - 0.000387 0 0 SHR - 0 fA 1 40 1 40 (empty) -1210953057.833364 5OKnoww6xl4 192.168.2.16 1577 75.126.203.78 80 tcp - 0.079208 0 0 SH - 0 Fa 1 40 1 40 (empty) -1210953058.007081 VW0XPVINV8a 192.168.2.16 1576 75.126.130.163 80 tcp - - - - RSTOS0 - 0 R 1 40 0 0 (empty) -1210953057.834454 3PKsZ2Uye21 192.168.2.16 1578 75.126.203.78 80 tcp http 0.407908 790 171 RSTO - 0 ShADadR 6 1038 4 335 (empty) -1210953058.350065 fRFu0wcOle6 192.168.2.16 1920 192.168.2.1 53 udp dns 0.223055 66 438 SF - 0 Dd 2 122 2 494 (empty) -1210953058.577231 qSsw6ESzHV4 192.168.2.16 137 192.168.2.255 137 udp dns 1.499261 150 0 S0 - 0 D 3 234 0 0 (empty) -1210953074.264819 Tw8jXtpTGu6 192.168.2.16 1920 192.168.2.1 53 udp dns 0.297723 123 598 SF - 0 Dd 3 207 3 682 (empty) -1210953061.312379 70MGiRM1Qf4 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 tcp http 12.810848 1675 10467 S1 - 0 ShADad 10 2279 12 11191 GSxOnSLghOa -1210953076.058333 EAr0uf4mhq 192.168.2.16 1578 75.126.203.78 80 tcp - - - - RSTRH - 0 r 0 0 1 40 (empty) -1210953074.055744 h5DsfNtYzi1 192.168.2.16 1577 75.126.203.78 80 tcp - - - - RSTRH - 0 r 0 0 1 40 (empty) -1210953074.057124 P654jzLoe3a 192.168.2.16 1576 75.126.130.163 80 tcp - - - - RSTRH - 0 r 0 0 1 40 (empty) -1210953074.570439 c4Zw9TmAE05 192.168.2.16 1580 67.228.110.120 80 tcp http 0.466677 469 3916 SF - 0 ShADadFf 7 757 6 4164 (empty) -1210953052.202579 nQcgTWjvg4c 192.168.2.16 3797 65.55.158.80 3544 udp teredo 8.928880 129 48 SF - 0 Dd 2 185 1 76 (empty) -1210953060.829233 GSxOnSLghOa 192.168.2.16 3797 83.170.1.38 32900 udp teredo 13.293994 2359 11243 SF - 0 Dd 12 2695 13 11607 (empty) -1210953058.933954 iE6yhOq3SF 0.0.0.0 68 255.255.255.255 67 udp dhcp - - - S0 - 0 D 1 328 0 0 (empty) -1210953052.324629 TEfuqmmG4bh 192.168.2.16 3797 65.55.158.81 3544 udp - - - - SHR - 0 d 0 0 1 137 (empty) -1210953046.591933 UWkUyAuUGXf 192.168.2.16 138 192.168.2.255 138 udp - 28.448321 416 0 S0 - 0 D 2 472 0 0 (empty) -1210953052.324629 FrJExwHcSal fe80::8000:f227:bec8:61af 134 fe80::8000:ffff:ffff:fffd 133 icmp - - - - OTH - 0 - 1 88 0 0 TEfuqmmG4bh -1210953060.829303 qCaWGmzFtM5 2001:0:4137:9e50:8000:f12a:b9c8:2815 128 2001:4860:0:2001::68 129 icmp - 0.463615 4 4 OTH - 0 - 1 52 1 52 GSxOnSLghOa,nQcgTWjvg4c -1210953052.202579 j4u32Pc5bif fe80::8000:ffff:ffff:fffd 133 ff02::2 134 icmp - - - - OTH - 0 - 1 64 0 0 nQcgTWjvg4c -#close 2013-08-04-03-28-45 +1210953047.736921 CjhGID4nQcgTWjvg4c 192.168.2.16 1576 75.126.130.163 80 tcp - 0.000357 0 0 SHR - 0 fA 1 40 1 40 (empty) +1210953050.867067 CCvvfg3TEfuqmmG4bh 192.168.2.16 1577 75.126.203.78 80 tcp - 0.000387 0 0 SHR - 0 fA 1 40 1 40 (empty) +1210953057.833364 CIPOse170MGiRM1Qf4 192.168.2.16 1577 75.126.203.78 80 tcp - 0.079208 0 0 SH - 0 Fa 1 40 1 40 (empty) +1210953058.007081 CJ3xTn1c4Zw9TmAE05 192.168.2.16 1576 75.126.130.163 80 tcp - - - - RSTOS0 - 0 R 1 40 0 0 (empty) +1210953057.834454 C7XEbhP654jzLoe3a 192.168.2.16 1578 75.126.203.78 80 tcp http 0.407908 790 171 RSTO - 0 ShADadR 6 1038 4 335 (empty) +1210953058.350065 CMXxB5GvmoxJFXdTa 192.168.2.16 1920 192.168.2.1 53 udp dns 0.223055 66 438 SF - 0 Dd 2 122 2 494 (empty) +1210953058.577231 Caby8b1slFea8xwSmb 192.168.2.16 137 192.168.2.255 137 udp dns 1.499261 150 0 S0 - 0 D 3 234 0 0 (empty) +1210953074.264819 CyAhVIzHqb7t7kv28 192.168.2.16 1920 192.168.2.1 53 udp dns 0.297723 123 598 SF - 0 Dd 3 207 3 682 (empty) +1210953061.312379 CwSkQu4eWZCH7OONC1 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 tcp http 12.810848 1675 10467 S1 - 0 ShADad 10 2279 12 11191 C3SfNE4BWaU4aSuwkc +1210953076.058333 Cx2FqO23omNawSNrxj 192.168.2.16 1578 75.126.203.78 80 tcp - - - - RSTRH - 0 r 0 0 1 40 (empty) +1210953074.055744 CfTOmO0HKorjr8Zp7 192.168.2.16 1577 75.126.203.78 80 tcp - - - - RSTRH - 0 r 0 0 1 40 (empty) +1210953074.057124 CzA03V1VcgagLjnO92 192.168.2.16 1576 75.126.130.163 80 tcp - - - - RSTRH - 0 r 0 0 1 40 (empty) +1210953074.570439 Cab0vO1xNYSS2hJkle 192.168.2.16 1580 67.228.110.120 80 tcp http 0.466677 469 3916 SF - 0 ShADadFf 7 757 6 4164 (empty) +1210953052.202579 CsRx2w45OKnoww6xl4 192.168.2.16 3797 65.55.158.80 3544 udp teredo 8.928880 129 48 SF - 0 Dd 2 185 1 76 (empty) +1210953060.829233 C3SfNE4BWaU4aSuwkc 192.168.2.16 3797 83.170.1.38 32900 udp teredo 13.293994 2359 11243 SF - 0 Dd 12 2695 13 11607 (empty) +1210953058.933954 Che1bq3i2rO3KD1Syg 0.0.0.0 68 255.255.255.255 67 udp dhcp - - - S0 - 0 D 1 328 0 0 (empty) +1210953052.324629 CPbrpk1qSsw6ESzHV4 192.168.2.16 3797 65.55.158.81 3544 udp - - - - SHR - 0 d 0 0 1 137 (empty) +1210953046.591933 CXWv6p3arKYeMETxOg 192.168.2.16 138 192.168.2.255 138 udp - 28.448321 416 0 S0 - 0 D 2 472 0 0 (empty) +1210953052.324629 C6pKV8GSxOnSLghOa fe80::8000:f227:bec8:61af 134 fe80::8000:ffff:ffff:fffd 133 icmp - - - - OTH - 0 - 1 88 0 0 CPbrpk1qSsw6ESzHV4 +1210953060.829303 CEle3f3zno26fFZkrh 2001:0:4137:9e50:8000:f12a:b9c8:2815 128 2001:4860:0:2001::68 129 icmp - 0.463615 4 4 OTH - 0 - 1 52 1 52 C3SfNE4BWaU4aSuwkc,CsRx2w45OKnoww6xl4 +1210953052.202579 CRJuHdVW0XPVINV8a fe80::8000:ffff:ffff:fffd 133 ff02::2 134 icmp - - - - OTH - 0 - 1 64 0 0 CsRx2w45OKnoww6xl4 +#close 2013-08-26-18-38-32 diff --git a/testing/btest/Baseline/core.tunnels.teredo/http.log b/testing/btest/Baseline/core.tunnels.teredo/http.log index 1ecf0884e2..f2422ac4b0 100644 --- a/testing/btest/Baseline/core.tunnels.teredo/http.log +++ b/testing/btest/Baseline/core.tunnels.teredo/http.log @@ -3,11 +3,11 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-16-23-17 +#open 2013-08-26-19-35-02 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1210953057.917183 3PKsZ2Uye21 192.168.2.16 1578 75.126.203.78 80 1 POST download913.avast.com /cgi-bin/iavs4stats.cgi - Syncer/4.80 (av_pro-1169;f) 589 0 204 - - - (empty) - - - tZX578lAmo3 text/plain - - -1210953061.585996 70MGiRM1Qf4 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 6640 200 OK - - - (empty) - - - - - nkfWSsPnjX7 text/html -1210953073.381474 70MGiRM1Qf4 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 2 GET ipv6.google.com /search?hl=en&q=Wireshark+!&btnG=Google+Search http://ipv6.google.com/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 25119 200 OK - - - (empty) - - - - - fk5lVax7K37 text/html -1210953074.674817 c4Zw9TmAE05 192.168.2.16 1580 67.228.110.120 80 1 GET www.wireshark.org / http://ipv6.google.com/search?hl=en&q=Wireshark+%21&btnG=Google+Search Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 11845 200 OK - - - (empty) - - - - - 6wF1NFmBUza application/xml -#close 2013-07-25-16-23-17 +1210953057.917183 C7XEbhP654jzLoe3a 192.168.2.16 1578 75.126.203.78 80 1 POST download913.avast.com /cgi-bin/iavs4stats.cgi - Syncer/4.80 (av_pro-1169;f) 589 0 204 - - - (empty) - - - Fp32SIJztq0Szn5Qc text/plain - - +1210953061.585996 CwSkQu4eWZCH7OONC1 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 6640 200 OK - - - (empty) - - - - - FNFYdH11h5iQcoD3a2 text/html +1210953073.381474 CwSkQu4eWZCH7OONC1 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 2 GET ipv6.google.com /search?hl=en&q=Wireshark+!&btnG=Google+Search http://ipv6.google.com/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 25119 200 OK - - - (empty) - - - - - FHD5nv1iSVFZVM0aH7 text/html +1210953074.674817 Cab0vO1xNYSS2hJkle 192.168.2.16 1580 67.228.110.120 80 1 GET www.wireshark.org / http://ipv6.google.com/search?hl=en&q=Wireshark+%21&btnG=Google+Search Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 11845 200 OK - - - (empty) - - - - - FS7lUf2cJFAVBCu6w6 application/xml +#close 2013-08-26-19-35-02 diff --git a/testing/btest/Baseline/core.tunnels.teredo/tunnel.log b/testing/btest/Baseline/core.tunnels.teredo/tunnel.log index 120089caa0..e611eeb679 100644 --- a/testing/btest/Baseline/core.tunnels.teredo/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.teredo/tunnel.log @@ -3,13 +3,13 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2008-05-16-15-50-52 +#open 2013-08-26-19-02-19 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1210953052.202579 nQcgTWjvg4c 192.168.2.16 3797 65.55.158.80 3544 Tunnel::TEREDO Tunnel::DISCOVER -1210953052.324629 TEfuqmmG4bh 192.168.2.16 3797 65.55.158.81 3544 Tunnel::TEREDO Tunnel::DISCOVER -1210953061.292918 GSxOnSLghOa 192.168.2.16 3797 83.170.1.38 32900 Tunnel::TEREDO Tunnel::DISCOVER -1210953076.058333 nQcgTWjvg4c 192.168.2.16 3797 65.55.158.80 3544 Tunnel::TEREDO Tunnel::CLOSE -1210953076.058333 GSxOnSLghOa 192.168.2.16 3797 83.170.1.38 32900 Tunnel::TEREDO Tunnel::CLOSE -1210953076.058333 TEfuqmmG4bh 192.168.2.16 3797 65.55.158.81 3544 Tunnel::TEREDO Tunnel::CLOSE -#close 2008-05-16-15-51-16 +1210953052.202579 CsRx2w45OKnoww6xl4 192.168.2.16 3797 65.55.158.80 3544 Tunnel::TEREDO Tunnel::DISCOVER +1210953052.324629 CPbrpk1qSsw6ESzHV4 192.168.2.16 3797 65.55.158.81 3544 Tunnel::TEREDO Tunnel::DISCOVER +1210953061.292918 C3SfNE4BWaU4aSuwkc 192.168.2.16 3797 83.170.1.38 32900 Tunnel::TEREDO Tunnel::DISCOVER +1210953076.058333 CsRx2w45OKnoww6xl4 192.168.2.16 3797 65.55.158.80 3544 Tunnel::TEREDO Tunnel::CLOSE +1210953076.058333 C3SfNE4BWaU4aSuwkc 192.168.2.16 3797 83.170.1.38 32900 Tunnel::TEREDO Tunnel::CLOSE +1210953076.058333 CPbrpk1qSsw6ESzHV4 192.168.2.16 3797 65.55.158.81 3544 Tunnel::TEREDO Tunnel::CLOSE +#close 2013-08-26-19-02-19 diff --git a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/conn.log b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/conn.log index 9d4bf86d57..e42ab8749b 100644 --- a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/conn.log +++ b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/conn.log @@ -3,14 +3,14 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-06-19-17-39-37 +#open 2013-08-26-18-38-32 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1340127577.354166 FrJExwHcSal 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 tcp http 0.052829 1675 10467 S1 - 0 ShADad 10 2279 12 11191 j4u32Pc5bif -1340127577.336558 UWkUyAuUGXf 192.168.2.16 3797 65.55.158.80 3544 udp teredo 0.010291 129 52 SF - 0 Dd 2 185 1 80 (empty) -1340127577.341510 j4u32Pc5bif 192.168.2.16 3797 83.170.1.38 32900 udp teredo 0.065485 2367 11243 SF - 0 Dd 12 2703 13 11607 (empty) -1340127577.339015 k6kgXLOoSKl 192.168.2.16 3797 65.55.158.81 3544 udp - - - - SHR - 0 d 0 0 1 137 (empty) -1340127577.339015 nQcgTWjvg4c fe80::8000:f227:bec8:61af 134 fe80::8000:ffff:ffff:fffd 133 icmp - - - - OTH - 0 - 1 88 0 0 k6kgXLOoSKl -1340127577.343969 TEfuqmmG4bh 2001:0:4137:9e50:8000:f12a:b9c8:2815 128 2001:4860:0:2001::68 129 icmp - 0.007778 4 4 OTH - 0 - 1 52 1 52 UWkUyAuUGXf,j4u32Pc5bif -1340127577.336558 arKYeMETxOg fe80::8000:ffff:ffff:fffd 133 ff02::2 134 icmp - - - - OTH - 0 - 1 64 0 0 UWkUyAuUGXf -#close 2012-06-19-17-39-37 +1340127577.354166 C6pKV8GSxOnSLghOa 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 tcp http 0.052829 1675 10467 S1 - 0 ShADad 10 2279 12 11191 CRJuHdVW0XPVINV8a +1340127577.336558 CXWv6p3arKYeMETxOg 192.168.2.16 3797 65.55.158.80 3544 udp teredo 0.010291 129 52 SF - 0 Dd 2 185 1 80 (empty) +1340127577.341510 CRJuHdVW0XPVINV8a 192.168.2.16 3797 83.170.1.38 32900 udp teredo 0.065485 2367 11243 SF - 0 Dd 12 2703 13 11607 (empty) +1340127577.339015 CCvvfg3TEfuqmmG4bh 192.168.2.16 3797 65.55.158.81 3544 udp - - - - SHR - 0 d 0 0 1 137 (empty) +1340127577.339015 CsRx2w45OKnoww6xl4 fe80::8000:f227:bec8:61af 134 fe80::8000:ffff:ffff:fffd 133 icmp - - - - OTH - 0 - 1 88 0 0 CCvvfg3TEfuqmmG4bh +1340127577.343969 CPbrpk1qSsw6ESzHV4 2001:0:4137:9e50:8000:f12a:b9c8:2815 128 2001:4860:0:2001::68 129 icmp - 0.007778 4 4 OTH - 0 - 1 52 1 52 CXWv6p3arKYeMETxOg,CRJuHdVW0XPVINV8a +1340127577.336558 CjhGID4nQcgTWjvg4c fe80::8000:ffff:ffff:fffd 133 ff02::2 134 icmp - - - - OTH - 0 - 1 64 0 0 CXWv6p3arKYeMETxOg +#close 2013-08-26-18-38-32 diff --git a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/http.log b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/http.log index 0c8c448e30..6d91b844de 100644 --- a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/http.log +++ b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/http.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-16-22-21 +#open 2013-08-26-19-35-02 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1340127577.361683 FrJExwHcSal 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 6640 200 OK - - - (empty) - - - - - RzAMHHXJral text/html -1340127577.379360 FrJExwHcSal 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 2 GET ipv6.google.com /search?hl=en&q=Wireshark+!&btnG=Google+Search http://ipv6.google.com/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 25119 200 OK - - - (empty) - - - - - vOmb3ToMKRg text/html -#close 2013-07-25-16-22-21 +1340127577.361683 C6pKV8GSxOnSLghOa 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 1 GET ipv6.google.com / - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 6640 200 OK - - - (empty) - - - - - FWSTWv4EZLVlc2Zywi text/html +1340127577.379360 C6pKV8GSxOnSLghOa 2001:0:4137:9e50:8000:f12a:b9c8:2815 1286 2001:4860:0:2001::68 80 2 GET ipv6.google.com /search?hl=en&q=Wireshark+!&btnG=Google+Search http://ipv6.google.com/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9b5) Gecko/2008032620 Firefox/3.0b5 0 25119 200 OK - - - (empty) - - - - - FGKV3B3jz083xhGO13 text/html +#close 2013-08-26-19-35-02 diff --git a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/tunnel.log b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/tunnel.log index 86c2c94c04..f988a996f8 100644 --- a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/tunnel.log +++ b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/tunnel.log @@ -3,13 +3,13 @@ #empty_field (empty) #unset_field - #path tunnel -#open 2012-06-19-17-39-37 +#open 2013-08-26-19-02-20 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p tunnel_type action #types time string addr port addr port enum enum -1340127577.336558 UWkUyAuUGXf 192.168.2.16 3797 65.55.158.80 3544 Tunnel::TEREDO Tunnel::DISCOVER -1340127577.339015 k6kgXLOoSKl 192.168.2.16 3797 65.55.158.81 3544 Tunnel::TEREDO Tunnel::DISCOVER -1340127577.351747 j4u32Pc5bif 192.168.2.16 3797 83.170.1.38 32900 Tunnel::TEREDO Tunnel::DISCOVER -1340127577.406995 UWkUyAuUGXf 192.168.2.16 3797 65.55.158.80 3544 Tunnel::TEREDO Tunnel::CLOSE -1340127577.406995 j4u32Pc5bif 192.168.2.16 3797 83.170.1.38 32900 Tunnel::TEREDO Tunnel::CLOSE -1340127577.406995 k6kgXLOoSKl 192.168.2.16 3797 65.55.158.81 3544 Tunnel::TEREDO Tunnel::CLOSE -#close 2012-06-19-17-39-37 +1340127577.336558 CXWv6p3arKYeMETxOg 192.168.2.16 3797 65.55.158.80 3544 Tunnel::TEREDO Tunnel::DISCOVER +1340127577.339015 CCvvfg3TEfuqmmG4bh 192.168.2.16 3797 65.55.158.81 3544 Tunnel::TEREDO Tunnel::DISCOVER +1340127577.351747 CRJuHdVW0XPVINV8a 192.168.2.16 3797 83.170.1.38 32900 Tunnel::TEREDO Tunnel::DISCOVER +1340127577.406995 CXWv6p3arKYeMETxOg 192.168.2.16 3797 65.55.158.80 3544 Tunnel::TEREDO Tunnel::CLOSE +1340127577.406995 CRJuHdVW0XPVINV8a 192.168.2.16 3797 83.170.1.38 32900 Tunnel::TEREDO Tunnel::CLOSE +1340127577.406995 CCvvfg3TEfuqmmG4bh 192.168.2.16 3797 65.55.158.81 3544 Tunnel::TEREDO Tunnel::CLOSE +#close 2013-08-26-19-02-20 diff --git a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/weird.log b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/weird.log index 764b78656a..bec4732a8f 100644 --- a/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/weird.log +++ b/testing/btest/Baseline/core.tunnels.teredo_bubble_with_payload/weird.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path weird -#open 2012-10-02-16-53-03 +#open 2013-08-26-19-46-43 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1340127577.341510 j4u32Pc5bif 192.168.2.16 3797 83.170.1.38 32900 Teredo_bubble_with_payload - F bro -1340127577.346849 UWkUyAuUGXf 192.168.2.16 3797 65.55.158.80 3544 Teredo_bubble_with_payload - F bro -#close 2012-10-02-16-53-03 +1340127577.341510 CRJuHdVW0XPVINV8a 192.168.2.16 3797 83.170.1.38 32900 Teredo_bubble_with_payload - F bro +1340127577.346849 CXWv6p3arKYeMETxOg 192.168.2.16 3797 65.55.158.80 3544 Teredo_bubble_with_payload - F bro +#close 2013-08-26-19-46-43 diff --git a/testing/btest/Baseline/core.vlan-mpls/conn.log b/testing/btest/Baseline/core.vlan-mpls/conn.log index d4cc8370a5..26a46e51cf 100644 --- a/testing/btest/Baseline/core.vlan-mpls/conn.log +++ b/testing/btest/Baseline/core.vlan-mpls/conn.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path conn -#open 2005-10-07-23-23-55 +#open 2013-08-26-19-02-20 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -952109346.874907 UWkUyAuUGXf 10.1.2.1 11001 10.34.0.1 23 tcp - 2.102560 26 0 SH - 0 SADF 11 470 0 0 (empty) -1128727435.450898 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 tcp http 1.733303 98 9417 SF - 0 ShADdFaf 12 730 10 9945 (empty) -1278600802.069419 k6kgXLOoSKl 10.20.80.1 50343 10.0.0.15 80 tcp - 0.004152 9 3429 SF - 0 ShADadfF 7 381 7 3801 (empty) -#close 2010-07-08-14-53-22 +952109346.874907 CXWv6p3arKYeMETxOg 10.1.2.1 11001 10.34.0.1 23 tcp - 2.102560 26 0 SH - 0 SADF 11 470 0 0 (empty) +1128727435.450898 CjhGID4nQcgTWjvg4c 141.42.64.125 56730 125.190.109.199 80 tcp http 1.733303 98 9417 SF - 0 ShADdFaf 12 730 10 9945 (empty) +1278600802.069419 CCvvfg3TEfuqmmG4bh 10.20.80.1 50343 10.0.0.15 80 tcp - 0.004152 9 3429 SF - 0 ShADadfF 7 381 7 3801 (empty) +#close 2013-08-26-19-02-20 diff --git a/testing/btest/Baseline/istate.events-ssl/receiver.http.log b/testing/btest/Baseline/istate.events-ssl/receiver.http.log index dd61de5424..58d6f075f2 100644 --- a/testing/btest/Baseline/istate.events-ssl/receiver.http.log +++ b/testing/btest/Baseline/istate.events-ssl/receiver.http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-21-10-36 +#open 2013-08-26-19-36-03 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1374786635.573905 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - -#close 2013-07-25-21-10-37 +1377545762.339375 CjhGID4nQcgTWjvg4c 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - +#close 2013-08-26-19-36-04 diff --git a/testing/btest/Baseline/istate.events-ssl/sender.http.log b/testing/btest/Baseline/istate.events-ssl/sender.http.log index dd61de5424..58d6f075f2 100644 --- a/testing/btest/Baseline/istate.events-ssl/sender.http.log +++ b/testing/btest/Baseline/istate.events-ssl/sender.http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-21-10-36 +#open 2013-08-26-19-36-03 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1374786635.573905 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - -#close 2013-07-25-21-10-37 +1377545762.339375 CjhGID4nQcgTWjvg4c 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - +#close 2013-08-26-19-36-04 diff --git a/testing/btest/Baseline/istate.events/receiver.http.log b/testing/btest/Baseline/istate.events/receiver.http.log index aebe4dea7b..58d6f075f2 100644 --- a/testing/btest/Baseline/istate.events/receiver.http.log +++ b/testing/btest/Baseline/istate.events/receiver.http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-20-26-59 +#open 2013-08-26-19-36-03 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1374784018.898860 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - -#close 2013-07-25-20-27-00 +1377545762.339375 CjhGID4nQcgTWjvg4c 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - +#close 2013-08-26-19-36-04 diff --git a/testing/btest/Baseline/istate.events/sender.http.log b/testing/btest/Baseline/istate.events/sender.http.log index b70ba733bd..ed1f15c8ab 100644 --- a/testing/btest/Baseline/istate.events/sender.http.log +++ b/testing/btest/Baseline/istate.events/sender.http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-21-05-37 +#open 2013-08-26-19-03-34 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1374786336.338273 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - -#close 2013-07-25-21-05-38 +1377543813.907864 CjhGID4nQcgTWjvg4c 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - - - - - +#close 2013-08-26-19-03-35 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/files.log b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/files.log index 344ffa7802..447d991f3e 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/files.log +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/files.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path files -#open 2013-08-14-04-50-17 +#open 2013-08-26-18-39-03 #fields ts fuid tx_hosts rx_hosts conn_uids source depth analyzers mime_type filename duration local_orig is_orig seen_bytes total_bytes missing_bytes overflow_bytes timedout parent_fuid md5 sha1 sha256 extracted #types time string table[addr] table[addr] table[string] string count table[string] string string interval bool bool count count count count bool string string string string string -1362692527.009721 G75mcAsU764 192.150.187.43 141.142.228.5 UWkUyAuUGXf HTTP 0 SHA256,DATA_EVENT,MD5,EXTRACT,SHA1 text/plain - 0.000054 - F 4705 4705 0 0 F - 397168fd09991a0e712254df7bc639ac 1dd7ac0398df6cbc0696445a91ec681facf4dc47 4e7c7ef0984119447e743e3ec77e1de52713e345cde03fe7df753a35849bed18 G75mcAsU764-file -#close 2013-08-14-04-50-17 +1362692527.009721 FakNcS1Jfe01uljb3 192.150.187.43 141.142.228.5 CXWv6p3arKYeMETxOg HTTP 0 SHA256,DATA_EVENT,MD5,EXTRACT,SHA1 text/plain - 0.000054 - F 4705 4705 0 0 F - 397168fd09991a0e712254df7bc639ac 1dd7ac0398df6cbc0696445a91ec681facf4dc47 4e7c7ef0984119447e743e3ec77e1de52713e345cde03fe7df753a35849bed18 FakNcS1Jfe01uljb3-file +#close 2013-08-26-18-39-03 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-odd-url/http.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-odd-url/http.log index a5331e8753..3ac1f21307 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-odd-url/http.log +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-odd-url/http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-18-54-41 +#open 2013-08-26-18-39-58 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1315799856.264750 UWkUyAuUGXf 10.0.1.104 64216 193.40.5.162 80 1 GET lepo.it.da.ut.ee /~cect/teoreetilised seminarid_2010/arheoloogia_uurimisr\xfchma_seminar/Joyce et al - The Languages of Archaeology ~ Dialogue, Narrative and Writing.pdf - Wget/1.12 (darwin10.8.0) 0 346 404 Not Found - - - (empty) - - - - - oijbBDPA7Ue text/html -#close 2013-07-25-18-54-41 +1315799856.264750 CXWv6p3arKYeMETxOg 10.0.1.104 64216 193.40.5.162 80 1 GET lepo.it.da.ut.ee /~cect/teoreetilised seminarid_2010/arheoloogia_uurimisr\xfchma_seminar/Joyce et al - The Languages of Archaeology ~ Dialogue, Narrative and Writing.pdf - Wget/1.12 (darwin10.8.0) 0 346 404 Not Found - - - (empty) - - - - - FGNm7b3eXjhJLfvOWl text/html +#close 2013-08-26-18-39-58 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.wikipedia/conn.select b/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.wikipedia/conn.select index e284fc0882..bdae1a8f73 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.wikipedia/conn.select +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.wikipedia/conn.select @@ -1,34 +1,34 @@ -1300475167.09654|UWkUyAuUGXf|141.142.220.202|5353|224.0.0.251|5353|udp|dns||||S0||0|D|1|73|0|0|(empty) -1300475167.09701|arKYeMETxOg|fe80::217:f2ff:fed7:cf65|5353|ff02::fb|5353|udp|||||S0||0|D|1|199|0|0|(empty) -1300475167.09982|k6kgXLOoSKl|141.142.220.50|5353|224.0.0.251|5353|udp|||||S0||0|D|1|179|0|0|(empty) -1300475168.652|nQcgTWjvg4c|141.142.220.118|35634|208.80.152.2|80|tcp||0.0613288879394531|463|350|OTH||0|DdA|2|567|1|402|(empty) -1300475168.72401|j4u32Pc5bif|141.142.220.118|48649|208.80.152.118|80|tcp|http|0.1199049949646|525|232|S1||0|ShADad|4|741|3|396|(empty) -1300475168.8539|TEfuqmmG4bh|141.142.220.118|43927|141.142.2.2|53|udp|dns|0.000435113906860352|38|89|SF||0|Dd|1|66|1|117|(empty) -1300475168.85438|FrJExwHcSal|141.142.220.118|37676|141.142.2.2|53|udp|dns|0.000420093536376953|52|99|SF||0|Dd|1|80|1|127|(empty) -1300475168.85484|5OKnoww6xl4|141.142.220.118|40526|141.142.2.2|53|udp|dns|0.000391960144042969|38|183|SF||0|Dd|1|66|1|211|(empty) -1300475168.85531|3PKsZ2Uye21|141.142.220.118|49996|208.80.152.3|80|tcp|http|0.218501091003418|1171|733|S1||0|ShADad|6|1491|4|949|(empty) -1300475168.85533|VW0XPVINV8a|141.142.220.118|49997|208.80.152.3|80|tcp|http|0.219720125198364|1125|734|S1||0|ShADad|6|1445|4|950|(empty) -1300475168.85796|fRFu0wcOle6|141.142.220.118|32902|141.142.2.2|53|udp|dns|0.000317096710205078|38|89|SF||0|Dd|1|66|1|117|(empty) -1300475168.85831|qSsw6ESzHV4|141.142.220.118|59816|141.142.2.2|53|udp|dns|0.000343084335327148|52|99|SF||0|Dd|1|80|1|127|(empty) -1300475168.85871|iE6yhOq3SF|141.142.220.118|59714|141.142.2.2|53|udp|dns|0.000375032424926758|38|183|SF||0|Dd|1|66|1|211|(empty) -1300475168.85916|GSxOnSLghOa|141.142.220.118|49998|208.80.152.3|80|tcp|http|0.215893030166626|1130|734|S1||0|ShADad|6|1450|4|950|(empty) -1300475168.89164|qCaWGmzFtM5|141.142.220.118|58206|141.142.2.2|53|udp|dns|0.000339031219482422|38|89|SF||0|Dd|1|66|1|117|(empty) -1300475168.89204|70MGiRM1Qf4|141.142.220.118|38911|141.142.2.2|53|udp|dns|0.000334978103637695|52|99|SF||0|Dd|1|80|1|127|(empty) -1300475168.89241|h5DsfNtYzi1|141.142.220.118|59746|141.142.2.2|53|udp|dns|0.000420808792114258|38|183|SF||0|Dd|1|66|1|211|(empty) -1300475168.89291|P654jzLoe3a|141.142.220.118|49999|208.80.152.3|80|tcp|http|0.220960855484009|1137|733|S1||0|ShADad|6|1457|4|949|(empty) -1300475168.89294|Tw8jXtpTGu6|141.142.220.118|50000|208.80.152.3|80|tcp|http|0.229603052139282|1148|734|S1||0|ShADad|6|1468|4|950|(empty) -1300475168.89399|c4Zw9TmAE05|141.142.220.118|45000|141.142.2.2|53|udp|dns|0.000384092330932617|38|89|SF||0|Dd|1|66|1|117|(empty) -1300475168.89442|EAr0uf4mhq|141.142.220.118|48479|141.142.2.2|53|udp|dns|0.000316858291625977|52|99|SF||0|Dd|1|80|1|127|(empty) -1300475168.89479|GvmoxJFXdTa|141.142.220.118|48128|141.142.2.2|53|udp|dns|0.000422954559326172|38|183|SF||0|Dd|1|66|1|211|(empty) -1300475168.89527|0Q4FH8sESw5|141.142.220.118|50001|208.80.152.3|80|tcp|http|0.227283954620361|1178|734|S1||0|ShADad|6|1498|4|950|(empty) -1300475168.90175|slFea8xwSmb|141.142.220.118|56056|141.142.2.2|53|udp|dns|0.000402212142944336|36|131|SF||0|Dd|1|64|1|159|(empty) -1300475168.9022|UfGkYA2HI2g|141.142.220.118|55092|141.142.2.2|53|udp|dns|0.000374078750610352|36|198|SF||0|Dd|1|64|1|226|(empty) -1300475168.90264|i2rO3KD1Syg|141.142.220.118|35642|208.80.152.2|80|tcp|http|0.120040893554688|534|412|S1||0|ShADad|4|750|3|576|(empty) -1300475169.78033|2cx26uAvUPl|141.142.220.235|6705|173.192.163.128|80|tcp|||||OTH||0|h|0|0|1|48|(empty) -1300475169.89944|BWaU4aSuwkc|141.142.220.44|5353|224.0.0.251|5353|udp|dns||||S0||0|D|1|85|0|0|(empty) -1300475170.86238|10XodEwRycf|141.142.220.226|137|141.142.220.255|137|udp|dns|2.61301684379578|350|0|S0||0|D|7|546|0|0|(empty) -1300475171.67537|zno26fFZkrh|fe80::3074:17d5:2052:c324|65373|ff02::1:3|5355|udp|dns|0.100096225738525|66|0|S0||0|D|2|162|0|0|(empty) -1300475171.67708|v5rgkJBig5l|141.142.220.226|55131|224.0.0.252|5355|udp|dns|0.100020885467529|66|0|S0||0|D|2|122|0|0|(empty) -1300475173.11675|eWZCH7OONC1|fe80::3074:17d5:2052:c324|54213|ff02::1:3|5355|udp|dns|0.0998010635375977|66|0|S0||0|D|2|162|0|0|(empty) -1300475173.11736|0Pwk3ntf8O3|141.142.220.226|55671|224.0.0.252|5355|udp|dns|0.0998489856719971|66|0|S0||0|D|2|122|0|0|(empty) -1300475173.15368|0HKorjr8Zp7|141.142.220.238|56641|141.142.220.255|137|udp|dns||||S0||0|D|1|78|0|0|(empty) +1300475167.09653|CXWv6p3arKYeMETxOg|141.142.220.202|5353|224.0.0.251|5353|udp|dns||||S0||0|D|1|73|0|0|(empty) +1300475167.09701|CjhGID4nQcgTWjvg4c|fe80::217:f2ff:fed7:cf65|5353|ff02::fb|5353|udp|||||S0||0|D|1|199|0|0|(empty) +1300475167.09982|CCvvfg3TEfuqmmG4bh|141.142.220.50|5353|224.0.0.251|5353|udp|||||S0||0|D|1|179|0|0|(empty) +1300475168.652|CsRx2w45OKnoww6xl4|141.142.220.118|35634|208.80.152.2|80|tcp||0.0613288879394531|463|350|OTH||0|DdA|2|567|1|402|(empty) +1300475168.72401|CRJuHdVW0XPVINV8a|141.142.220.118|48649|208.80.152.118|80|tcp|http|0.1199049949646|525|232|S1||0|ShADad|4|741|3|396|(empty) +1300475168.8539|CPbrpk1qSsw6ESzHV4|141.142.220.118|43927|141.142.2.2|53|udp|dns|0.000435113906860352|38|89|SF||0|Dd|1|66|1|117|(empty) +1300475168.85438|C6pKV8GSxOnSLghOa|141.142.220.118|37676|141.142.2.2|53|udp|dns|0.000420093536376953|52|99|SF||0|Dd|1|80|1|127|(empty) +1300475168.85484|CIPOse170MGiRM1Qf4|141.142.220.118|40526|141.142.2.2|53|udp|dns|0.000391960144042969|38|183|SF||0|Dd|1|66|1|211|(empty) +1300475168.8553|C7XEbhP654jzLoe3a|141.142.220.118|49996|208.80.152.3|80|tcp|http|0.218501091003418|1171|733|S1||0|ShADad|6|1491|4|949|(empty) +1300475168.85533|CJ3xTn1c4Zw9TmAE05|141.142.220.118|49997|208.80.152.3|80|tcp|http|0.219720125198364|1125|734|S1||0|ShADad|6|1445|4|950|(empty) +1300475168.85796|CMXxB5GvmoxJFXdTa|141.142.220.118|32902|141.142.2.2|53|udp|dns|0.000317096710205078|38|89|SF||0|Dd|1|66|1|117|(empty) +1300475168.85831|Caby8b1slFea8xwSmb|141.142.220.118|59816|141.142.2.2|53|udp|dns|0.000343084335327148|52|99|SF||0|Dd|1|80|1|127|(empty) +1300475168.85871|Che1bq3i2rO3KD1Syg|141.142.220.118|59714|141.142.2.2|53|udp|dns|0.000375032424926758|38|183|SF||0|Dd|1|66|1|211|(empty) +1300475168.85916|C3SfNE4BWaU4aSuwkc|141.142.220.118|49998|208.80.152.3|80|tcp|http|0.215893030166626|1130|734|S1||0|ShADad|6|1450|4|950|(empty) +1300475168.89164|CEle3f3zno26fFZkrh|141.142.220.118|58206|141.142.2.2|53|udp|dns|0.000339031219482422|38|89|SF||0|Dd|1|66|1|117|(empty) +1300475168.89204|CwSkQu4eWZCH7OONC1|141.142.220.118|38911|141.142.2.2|53|udp|dns|0.000334978103637695|52|99|SF||0|Dd|1|80|1|127|(empty) +1300475168.89241|CfTOmO0HKorjr8Zp7|141.142.220.118|59746|141.142.2.2|53|udp|dns|0.000420808792114258|38|183|SF||0|Dd|1|66|1|211|(empty) +1300475168.89291|CzA03V1VcgagLjnO92|141.142.220.118|49999|208.80.152.3|80|tcp|http|0.220960855484009|1137|733|S1||0|ShADad|6|1457|4|949|(empty) +1300475168.89294|CyAhVIzHqb7t7kv28|141.142.220.118|50000|208.80.152.3|80|tcp|http|0.229603052139282|1148|734|S1||0|ShADad|6|1468|4|950|(empty) +1300475168.89399|Cab0vO1xNYSS2hJkle|141.142.220.118|45000|141.142.2.2|53|udp|dns|0.000384092330932617|38|89|SF||0|Dd|1|66|1|117|(empty) +1300475168.89442|Cx2FqO23omNawSNrxj|141.142.220.118|48479|141.142.2.2|53|udp|dns|0.000316858291625977|52|99|SF||0|Dd|1|80|1|127|(empty) +1300475168.89479|Cx3C534wEyF3OvvcQe|141.142.220.118|48128|141.142.2.2|53|udp|dns|0.000422954559326172|38|183|SF||0|Dd|1|66|1|211|(empty) +1300475168.89527|CkDsfG2YIeWJmXWNWj|141.142.220.118|50001|208.80.152.3|80|tcp|http|0.227283954620361|1178|734|S1||0|ShADad|6|1498|4|950|(empty) +1300475168.90175|CUKS0W3HFYOnBqSE5e|141.142.220.118|56056|141.142.2.2|53|udp|dns|0.000402212142944336|36|131|SF||0|Dd|1|64|1|159|(empty) +1300475168.90219|CRrfvP2lalMAYOCLhj|141.142.220.118|55092|141.142.2.2|53|udp|dns|0.000374078750610352|36|198|SF||0|Dd|1|64|1|226|(empty) +1300475168.90264|Cn78a440HlxuyZKs6f|141.142.220.118|35642|208.80.152.2|80|tcp|http|0.120040893554688|534|412|S1||0|ShADad|4|750|3|576|(empty) +1300475169.78033|CUof3F2yAIid8QS3dk|141.142.220.235|6705|173.192.163.128|80|tcp|||||OTH||0|h|0|0|1|48|(empty) +1300475169.89944|CojBOU3CXcLHl1r6x1|141.142.220.44|5353|224.0.0.251|5353|udp|dns||||S0||0|D|1|85|0|0|(empty) +1300475170.86238|CJzVQRGJrX6V15ik7|141.142.220.226|137|141.142.220.255|137|udp|dns|2.61301684379578|350|0|S0||0|D|7|546|0|0|(empty) +1300475171.67537|ClAbxY1nmdjCuo0Le2|fe80::3074:17d5:2052:c324|65373|ff02::1:3|5355|udp|dns|0.100096225738525|66|0|S0||0|D|2|162|0|0|(empty) +1300475171.67708|CwG0BF1VXE0gWgs78|141.142.220.226|55131|224.0.0.252|5355|udp|dns|0.100020885467529|66|0|S0||0|D|2|122|0|0|(empty) +1300475173.11675|CisNaL1Cm73CiNOmcg|fe80::3074:17d5:2052:c324|54213|ff02::1:3|5355|udp|dns|0.0998010635375977|66|0|S0||0|D|2|162|0|0|(empty) +1300475173.11736|CBQnJn22qN8TOeeZil|141.142.220.226|55671|224.0.0.252|5355|udp|dns|0.0998489856719971|66|0|S0||0|D|2|122|0|0|(empty) +1300475173.15368|CbEsuD3dgDDngdlbKf|141.142.220.238|56641|141.142.220.255|137|udp|dns||||S0||0|D|1|78|0|0|(empty) diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.wikipedia/http.select b/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.wikipedia/http.select index a228fa2e11..5c584af41b 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.wikipedia/http.select +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.sqlite.wikipedia/http.select @@ -1,14 +1,14 @@ -1300475168.78402|j4u32Pc5bif|141.142.220.118|48649|208.80.152.118|80|1|GET|bits.wikimedia.org|/skins-1.5/monobook/main.css|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.91602|VW0XPVINV8a|141.142.220.118|49997|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/6/63/Wikipedia-logo.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.91618|3PKsZ2Uye21|141.142.220.118|49996|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.91836|GSxOnSLghOa|141.142.220.118|49998|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/b/bd/Bookshelf-40x201_6.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.9523|P654jzLoe3a|141.142.220.118|49999|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/4/4a/Wiktionary-logo-en-35px.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.95231|Tw8jXtpTGu6|141.142.220.118|50000|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.95482|0Q4FH8sESw5|141.142.220.118|50001|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/thumb/f/fa/Wikiquote-logo.svg/35px-Wikiquote-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.96269|i2rO3KD1Syg|141.142.220.118|35642|208.80.152.2|80|1|GET|meta.wikimedia.org|/images/wikimedia-button.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.97593|VW0XPVINV8a|141.142.220.118|49997|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.97644|3PKsZ2Uye21|141.142.220.118|49996|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/d/df/Wikispecies-logo.svg/35px-Wikispecies-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475168.97926|GSxOnSLghOa|141.142.220.118|49998|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/4/4c/Wikisource-logo.svg/35px-Wikisource-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475169.01459|P654jzLoe3a|141.142.220.118|49999|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475169.01462|Tw8jXtpTGu6|141.142.220.118|50000|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| -1300475169.01493|0Q4FH8sESw5|141.142.220.118|50001|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.78402|CRJuHdVW0XPVINV8a|141.142.220.118|48649|208.80.152.118|80|1|GET|bits.wikimedia.org|/skins-1.5/monobook/main.css|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.91602|CJ3xTn1c4Zw9TmAE05|141.142.220.118|49997|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/6/63/Wikipedia-logo.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.91618|C7XEbhP654jzLoe3a|141.142.220.118|49996|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.91836|C3SfNE4BWaU4aSuwkc|141.142.220.118|49998|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/b/bd/Bookshelf-40x201_6.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.9523|CzA03V1VcgagLjnO92|141.142.220.118|49999|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/4/4a/Wiktionary-logo-en-35px.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.95231|CyAhVIzHqb7t7kv28|141.142.220.118|50000|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.95482|CkDsfG2YIeWJmXWNWj|141.142.220.118|50001|208.80.152.3|80|1|GET|upload.wikimedia.org|/wikipedia/commons/thumb/f/fa/Wikiquote-logo.svg/35px-Wikiquote-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.96269|Cn78a440HlxuyZKs6f|141.142.220.118|35642|208.80.152.2|80|1|GET|meta.wikimedia.org|/images/wikimedia-button.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.97593|CJ3xTn1c4Zw9TmAE05|141.142.220.118|49997|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.97644|C7XEbhP654jzLoe3a|141.142.220.118|49996|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/d/df/Wikispecies-logo.svg/35px-Wikispecies-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475168.97926|C3SfNE4BWaU4aSuwkc|141.142.220.118|49998|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/4/4c/Wikisource-logo.svg/35px-Wikisource-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475169.01459|CzA03V1VcgagLjnO92|141.142.220.118|49999|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475169.01462|CyAhVIzHqb7t7kv28|141.142.220.118|50000|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| +1300475169.01493|CkDsfG2YIeWJmXWNWj|141.142.220.118|50001|208.80.152.3|80|2|GET|upload.wikimedia.org|/wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png|http://www.wikipedia.org/|Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15|0|0|304|Not Modified||||(empty)||||||| diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.writer-path-conflict/http.log b/testing/btest/Baseline/scripts.base.frameworks.logging.writer-path-conflict/http.log index 8f9d553d9a..11b742eaa1 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.writer-path-conflict/http.log +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.writer-path-conflict/http.log @@ -3,21 +3,21 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-23-05-48-35 +#open 2013-08-26-19-03-59 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1300475168.784020 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 1 GET bits.wikimedia.org /skins-1.5/monobook/main.css http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.916018 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.916183 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.918358 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.952307 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.952296 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/4/4a/Wiktionary-logo-en-35px.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.954820 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikiquote-logo.svg/35px-Wikiquote-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.962687 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 1 GET meta.wikimedia.org /images/wikimedia-button.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.975934 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.976436 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/d/df/Wikispecies-logo.svg/35px-Wikispecies-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475168.979264 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4c/Wikisource-logo.svg/35px-Wikisource-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475169.014619 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475169.014593 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -1300475169.014927 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - -#close 2013-07-23-05-48-35 +1300475168.784020 CRJuHdVW0XPVINV8a 141.142.220.118 48649 208.80.152.118 80 1 GET bits.wikimedia.org /skins-1.5/monobook/main.css http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.916018 CJ3xTn1c4Zw9TmAE05 141.142.220.118 49997 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.916183 C7XEbhP654jzLoe3a 141.142.220.118 49996 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.918358 C3SfNE4BWaU4aSuwkc 141.142.220.118 49998 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.952307 CyAhVIzHqb7t7kv28 141.142.220.118 50000 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.952296 CzA03V1VcgagLjnO92 141.142.220.118 49999 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/4/4a/Wiktionary-logo-en-35px.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.954820 CkDsfG2YIeWJmXWNWj 141.142.220.118 50001 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikiquote-logo.svg/35px-Wikiquote-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.962687 Cn78a440HlxuyZKs6f 141.142.220.118 35642 208.80.152.2 80 1 GET meta.wikimedia.org /images/wikimedia-button.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.975934 CJ3xTn1c4Zw9TmAE05 141.142.220.118 49997 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.976436 C7XEbhP654jzLoe3a 141.142.220.118 49996 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/d/df/Wikispecies-logo.svg/35px-Wikispecies-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475168.979264 C3SfNE4BWaU4aSuwkc 141.142.220.118 49998 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4c/Wikisource-logo.svg/35px-Wikisource-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475169.014619 CyAhVIzHqb7t7kv28 141.142.220.118 50000 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475169.014593 CzA03V1VcgagLjnO92 141.142.220.118 49999 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +1300475169.014927 CkDsfG2YIeWJmXWNWj 141.142.220.118 50001 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified - - - (empty) - - - - - - - +#close 2013-08-26-19-03-59 diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt b/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt index e2cd51edd1..081e71ac58 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt +++ b/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt @@ -1,4 +1,4 @@ -> 2005-10-07-23:23:55 Test_Notice 141.42.64.125:56730/tcp -> 125.190.109.199:80/tcp (uid arKYeMETxOg) +> 2005-10-07-23:23:55 Test_Notice 141.42.64.125:56730/tcp -> 125.190.109.199:80/tcp (uid CjhGID4nQcgTWjvg4c) test # 141.42.64.125 = 125.190.109.199 = diff --git a/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-all-msg-types/dhcp.log b/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-all-msg-types/dhcp.log index b52d455a4a..d4f048bed2 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-all-msg-types/dhcp.log +++ b/testing/btest/Baseline/scripts.base.protocols.dhcp.dhcp-all-msg-types/dhcp.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dhcp -#open 2013-07-31-21-00-49 +#open 2013-08-26-19-04-04 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p mac assigned_ip lease_time trans_id #types time string addr port addr port string addr interval count -1370200444.371332 nQcgTWjvg4c 128.2.6.189 68 128.2.6.152 67 90:b1:1c:99:49:29 128.2.6.189 900.000000 1984 -#close 2013-07-31-21-00-50 +1370200444.371332 CsRx2w45OKnoww6xl4 128.2.6.189 68 128.2.6.152 67 90:b1:1c:99:49:29 128.2.6.189 900.000000 1984 +#close 2013-08-26-19-04-04 diff --git a/testing/btest/Baseline/scripts.base.protocols.dhcp.inform/dhcp.log b/testing/btest/Baseline/scripts.base.protocols.dhcp.inform/dhcp.log index 51b4a28f9c..871fd7c5c3 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dhcp.inform/dhcp.log +++ b/testing/btest/Baseline/scripts.base.protocols.dhcp.inform/dhcp.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dhcp -#open 2013-08-03-01-18-52 +#open 2013-08-26-19-04-04 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p mac assigned_ip lease_time trans_id #types time string addr port addr port string addr interval count -1374432420.191205 UWkUyAuUGXf 128.2.6.122 68 128.2.6.152 67 90:b1:1c:99:49:29 128.2.6.122 0.000000 2754407505 -#close 2013-08-03-01-18-52 +1374432420.191205 CXWv6p3arKYeMETxOg 128.2.6.122 68 128.2.6.152 67 90:b1:1c:99:49:29 128.2.6.122 0.000000 2754407505 +#close 2013-08-26-19-04-04 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/dnp3.log index 072b762f63..68931eb81e 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_del_measure/dnp3.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-23-58 +#open 2013-08-26-19-04-04 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1324503054.884183 UWkUyAuUGXf 130.126.142.250 49413 130.126.140.229 20000 DELAY_MEASURE RESPONSE 0 -#close 2013-08-12-18-23-58 +1324503054.884183 CXWv6p3arKYeMETxOg 130.126.142.250 49413 130.126.140.229 20000 DELAY_MEASURE RESPONSE 0 +#close 2013-08-26-19-04-04 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/dnp3.log index bdb8fdbccf..90c7e9dfd3 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_en_spon/dnp3.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-23-59 +#open 2013-08-26-19-04-04 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1324916729.150101 UWkUyAuUGXf 130.126.142.250 50059 130.126.140.229 20000 ENABLE_UNSOLICITED RESPONSE 0 -#close 2013-08-12-18-23-59 +1324916729.150101 CXWv6p3arKYeMETxOg 130.126.142.250 50059 130.126.140.229 20000 ENABLE_UNSOLICITED RESPONSE 0 +#close 2013-08-26-19-04-04 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/dnp3.log index 23fd75b825..4a1fb6329a 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_del/dnp3.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-23-59 +#open 2013-08-26-19-04-05 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1325044377.992570 UWkUyAuUGXf 130.126.142.250 50301 130.126.140.229 20000 DELETE_FILE RESPONSE 0 -#close 2013-08-12-18-23-59 +1325044377.992570 CXWv6p3arKYeMETxOg 130.126.142.250 50301 130.126.140.229 20000 DELETE_FILE RESPONSE 0 +#close 2013-08-26-19-04-05 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/dnp3.log index c1462aa9f9..9db6d6468d 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_read/dnp3.log @@ -3,12 +3,12 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-24-00 +#open 2013-08-26-19-04-05 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1325036012.621691 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 OPEN_FILE RESPONSE 4096 -1325036016.729050 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 READ RESPONSE 4096 -1325036019.765502 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 WRITE RESPONSE 0 -1325036022.292689 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 WRITE RESPONSE 0 -1325036024.820857 UWkUyAuUGXf 130.126.142.250 50276 130.126.140.229 20000 CLOSE_FILE RESPONSE 0 -#close 2013-08-12-18-24-00 +1325036012.621691 CXWv6p3arKYeMETxOg 130.126.142.250 50276 130.126.140.229 20000 OPEN_FILE RESPONSE 4096 +1325036016.729050 CXWv6p3arKYeMETxOg 130.126.142.250 50276 130.126.140.229 20000 READ RESPONSE 4096 +1325036019.765502 CXWv6p3arKYeMETxOg 130.126.142.250 50276 130.126.140.229 20000 WRITE RESPONSE 0 +1325036022.292689 CXWv6p3arKYeMETxOg 130.126.142.250 50276 130.126.140.229 20000 WRITE RESPONSE 0 +1325036024.820857 CXWv6p3arKYeMETxOg 130.126.142.250 50276 130.126.140.229 20000 CLOSE_FILE RESPONSE 0 +#close 2013-08-26-19-04-05 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_write/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_write/dnp3.log index 938635872b..56f2fc4740 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_write/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_file_write/dnp3.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-24-00 +#open 2013-08-26-19-04-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1325043635.216629 UWkUyAuUGXf 130.126.142.250 50300 130.126.140.229 20000 OPEN_FILE RESPONSE 0 -1325043637.790287 UWkUyAuUGXf 130.126.142.250 50300 130.126.140.229 20000 WRITE RESPONSE 0 -1325043638.820071 UWkUyAuUGXf 130.126.142.250 50300 130.126.140.229 20000 CLOSE_FILE RESPONSE 0 -#close 2013-08-12-18-24-00 +1325043635.216629 CXWv6p3arKYeMETxOg 130.126.142.250 50300 130.126.140.229 20000 OPEN_FILE RESPONSE 0 +1325043637.790287 CXWv6p3arKYeMETxOg 130.126.142.250 50300 130.126.140.229 20000 WRITE RESPONSE 0 +1325043638.820071 CXWv6p3arKYeMETxOg 130.126.142.250 50300 130.126.140.229 20000 CLOSE_FILE RESPONSE 0 +#close 2013-08-26-19-04-06 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_read/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_read/dnp3.log index 7ef4eb5530..8722dc79b6 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_read/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_read/dnp3.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-24-01 +#open 2013-08-26-19-04-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1324327256.650425 UWkUyAuUGXf 130.126.142.250 51006 130.126.140.229 20000 READ RESPONSE 0 -#close 2013-08-12-18-24-01 +1324327256.650425 CXWv6p3arKYeMETxOg 130.126.142.250 51006 130.126.140.229 20000 READ RESPONSE 0 +#close 2013-08-26-19-04-06 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_rec_time/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_rec_time/dnp3.log index da756402e4..2c7bde67ea 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_rec_time/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_rec_time/dnp3.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-24-02 +#open 2013-08-26-19-04-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1324502980.465157 UWkUyAuUGXf 130.126.142.250 49412 130.126.140.229 20000 RECORD_CURRENT_TIME RESPONSE 0 -#close 2013-08-12-18-24-02 +1324502980.465157 CXWv6p3arKYeMETxOg 130.126.142.250 49412 130.126.140.229 20000 RECORD_CURRENT_TIME RESPONSE 0 +#close 2013-08-26-19-04-06 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_select_operate/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_select_operate/dnp3.log index 9ea651e533..8d2409b212 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_select_operate/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_select_operate/dnp3.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-24-02 +#open 2013-08-26-19-04-07 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1324501739.752598 UWkUyAuUGXf 130.126.142.250 49404 130.126.140.229 20000 SELECT RESPONSE 0 -1324501743.758738 UWkUyAuUGXf 130.126.142.250 49404 130.126.140.229 20000 OPERATE RESPONSE 0 -#close 2013-08-12-18-24-02 +1324501739.752598 CXWv6p3arKYeMETxOg 130.126.142.250 49404 130.126.140.229 20000 SELECT RESPONSE 0 +1324501743.758738 CXWv6p3arKYeMETxOg 130.126.142.250 49404 130.126.140.229 20000 OPERATE RESPONSE 0 +#close 2013-08-26-19-04-07 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_write/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_write/dnp3.log index b185003e68..9ea9fc2677 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_write/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.dnp3_write/dnp3.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-12-18-24-03 +#open 2013-08-26-19-04-07 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1324502912.898449 UWkUyAuUGXf 130.126.142.250 49411 130.126.140.229 20000 WRITE RESPONSE 0 -#close 2013-08-12-18-24-03 +1324502912.898449 CXWv6p3arKYeMETxOg 130.126.142.250 49411 130.126.140.229 20000 WRITE RESPONSE 0 +#close 2013-08-26-19-04-07 diff --git a/testing/btest/Baseline/scripts.base.protocols.dnp3.events/dnp3.log b/testing/btest/Baseline/scripts.base.protocols.dnp3.events/dnp3.log index be1b99f57f..cc6fddc791 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dnp3.events/dnp3.log +++ b/testing/btest/Baseline/scripts.base.protocols.dnp3.events/dnp3.log @@ -3,73 +3,73 @@ #empty_field (empty) #unset_field - #path dnp3 -#open 2013-08-23-23-05-27 +#open 2013-08-26-19-47-53 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fc_request fc_reply iin #types time string addr port addr port string string count -1097501938.504844 UWkUyAuUGXf 10.0.0.8 2789 10.0.0.3 20000 - UNSOLICITED_RESPONSE 4096 -1097501941.569134 UWkUyAuUGXf 10.0.0.8 2789 10.0.0.3 20000 WRITE RESPONSE 0 -1097502061.912093 UWkUyAuUGXf 10.0.0.8 2789 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 0 -1097502623.047417 arKYeMETxOg 10.0.0.8 2803 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097504102.257400 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 - UNSOLICITED_RESPONSE 4096 -1097504103.409070 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 WRITE RESPONSE 0 -1097504186.667107 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 ENABLE_UNSOLICITED RESPONSE 0 -1097504195.106257 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097504196.566493 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504197.887726 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504199.597084 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504200.719510 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504202.513608 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504203.324245 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504204.663060 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504205.750705 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504210.792443 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 -1097504223.905294 k6kgXLOoSKl 10.0.0.8 2828 10.0.0.3 20000 COLD_RESTART RESPONSE 0 -1097505719.083365 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 COLD_RESTART UNSOLICITED_RESPONSE 0 -1097505719.083898 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097505719.084451 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - RESPONSE 0 -1097505754.654239 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 READ RESPONSE 32768 -1097505754.654731 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 32768 -1097505754.756391 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 32768 -1097505754.864882 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 WRITE RESPONSE 0 -1097505754.977534 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 READ RESPONSE 0 -1097505769.716268 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097505784.797836 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097505799.908753 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097505839.916865 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097505880.043946 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097505920.204187 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097505960.308661 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097506000.396024 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097506013.373353 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 ENABLE_UNSOLICITED RESPONSE 0 -1097506013.373850 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097506020.703162 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 ENABLE_UNSOLICITED RESPONSE 0 -1097506028.446245 nQcgTWjvg4c 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 -1097507785.885063 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 - UNSOLICITED_RESPONSE 36864 -1097507788.624309 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 36864 -1097507788.834395 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 WRITE RESPONSE 32768 -1097507788.944297 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 32768 -1097507789.167700 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 WRITE RESPONSE 32768 -1097507789.274806 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 32768 -1097507789.484975 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 WRITE RESPONSE 0 -1097507789.797226 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 READ RESPONSE 0 -1097507835.030339 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 WARM_RESTART RESPONSE 0 -1097507856.091024 j4u32Pc5bif 10.0.0.8 1086 10.0.0.3 20000 WARM_RESTART RESPONSE 0 -1097510947.094289 TEfuqmmG4bh 10.0.0.8 1159 10.0.0.3 20000 - UNSOLICITED_RESPONSE 256 -1097510959.359091 TEfuqmmG4bh 10.0.0.8 1159 10.0.0.3 20000 DISABLE_UNSOLICITED - - -1097512255.236054 FrJExwHcSal 10.0.0.8 1184 10.0.0.3 20000 - UNSOLICITED_RESPONSE 4096 -1097512264.723894 FrJExwHcSal 10.0.0.8 1184 10.0.0.3 20000 STOP_APPL RESPONSE 4097 -1097512267.537969 FrJExwHcSal 10.0.0.8 1184 10.0.0.3 20000 STOP_APPL RESPONSE 4097 -1097513177.297272 5OKnoww6xl4 10.0.0.9 1084 10.0.0.3 20000 - UNSOLICITED_RESPONSE 38145 -1097513182.837583 5OKnoww6xl4 10.0.0.9 1084 10.0.0.3 20000 STOP_APPL - - -1178205958.184068 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 0 -1178205982.425227 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 -1178205984.486492 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 -1178205985.311235 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 -1178205986.029976 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 -1178205986.556099 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 -1178206042.953163 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 -1178206044.500956 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 -1178206045.032815 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 -1178206045.557097 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 -1178206046.086403 3PKsZ2Uye21 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 -#close 2013-08-23-23-05-27 +1097501938.504844 CXWv6p3arKYeMETxOg 10.0.0.8 2789 10.0.0.3 20000 - UNSOLICITED_RESPONSE 4096 +1097501941.569134 CXWv6p3arKYeMETxOg 10.0.0.8 2789 10.0.0.3 20000 WRITE RESPONSE 0 +1097502061.912093 CXWv6p3arKYeMETxOg 10.0.0.8 2789 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 0 +1097502623.047417 CjhGID4nQcgTWjvg4c 10.0.0.8 2803 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097504102.257400 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 - UNSOLICITED_RESPONSE 4096 +1097504103.409070 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 WRITE RESPONSE 0 +1097504186.667107 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 ENABLE_UNSOLICITED RESPONSE 0 +1097504195.106257 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097504196.566493 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504197.887726 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504199.597084 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504200.719510 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504202.513608 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504203.324245 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504204.663060 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504205.750705 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504210.792443 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 CONFIRM UNSOLICITED_RESPONSE 0 +1097504223.905294 CCvvfg3TEfuqmmG4bh 10.0.0.8 2828 10.0.0.3 20000 COLD_RESTART RESPONSE 0 +1097505719.083365 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 COLD_RESTART UNSOLICITED_RESPONSE 0 +1097505719.083898 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097505719.084451 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - RESPONSE 0 +1097505754.654239 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 READ RESPONSE 32768 +1097505754.654731 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 32768 +1097505754.756391 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 32768 +1097505754.864882 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 WRITE RESPONSE 0 +1097505754.977534 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 READ RESPONSE 0 +1097505769.716268 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097505784.797836 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097505799.908753 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097505839.916865 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097505880.043946 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097505920.204187 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097505960.308661 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097506000.396024 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097506013.373353 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 ENABLE_UNSOLICITED RESPONSE 0 +1097506013.373850 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097506020.703162 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 ENABLE_UNSOLICITED RESPONSE 0 +1097506028.446245 CsRx2w45OKnoww6xl4 10.0.0.9 1080 10.0.0.3 20000 - UNSOLICITED_RESPONSE 0 +1097507785.885063 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 - UNSOLICITED_RESPONSE 36864 +1097507788.624309 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 36864 +1097507788.834395 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 WRITE RESPONSE 32768 +1097507788.944297 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 32768 +1097507789.167700 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 WRITE RESPONSE 32768 +1097507789.274806 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 DISABLE_UNSOLICITED RESPONSE 32768 +1097507789.484975 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 WRITE RESPONSE 0 +1097507789.797226 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 READ RESPONSE 0 +1097507835.030339 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 WARM_RESTART RESPONSE 0 +1097507856.091024 CRJuHdVW0XPVINV8a 10.0.0.8 1086 10.0.0.3 20000 WARM_RESTART RESPONSE 0 +1097510947.094289 CPbrpk1qSsw6ESzHV4 10.0.0.8 1159 10.0.0.3 20000 - UNSOLICITED_RESPONSE 256 +1097510959.359091 CPbrpk1qSsw6ESzHV4 10.0.0.8 1159 10.0.0.3 20000 DISABLE_UNSOLICITED - - +1097512255.236054 C6pKV8GSxOnSLghOa 10.0.0.8 1184 10.0.0.3 20000 - UNSOLICITED_RESPONSE 4096 +1097512264.723894 C6pKV8GSxOnSLghOa 10.0.0.8 1184 10.0.0.3 20000 STOP_APPL RESPONSE 4097 +1097512267.537969 C6pKV8GSxOnSLghOa 10.0.0.8 1184 10.0.0.3 20000 STOP_APPL RESPONSE 4097 +1097513177.297272 CIPOse170MGiRM1Qf4 10.0.0.9 1084 10.0.0.3 20000 - UNSOLICITED_RESPONSE 38145 +1097513182.837583 CIPOse170MGiRM1Qf4 10.0.0.9 1084 10.0.0.3 20000 STOP_APPL - - +1178205958.184068 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 0 +1178205982.425227 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 +1178205984.486492 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 +1178205985.311235 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 +1178205986.029976 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 +1178205986.556099 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 SELECT RESPONSE 4 +1178206042.953163 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 +1178206044.500956 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 +1178206045.032815 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 +1178206045.557097 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 +1178206046.086403 C7XEbhP654jzLoe3a 192.168.66.33 1167 192.168.66.34 20000 READ RESPONSE 6 +#close 2013-08-26-19-47-53 diff --git a/testing/btest/Baseline/scripts.base.protocols.dns.dns-key/dns.log b/testing/btest/Baseline/scripts.base.protocols.dns.dns-key/dns.log index 722d2c3912..35289b82dd 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dns.dns-key/dns.log +++ b/testing/btest/Baseline/scripts.base.protocols.dns.dns-key/dns.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dns -#open 2013-07-25-20-29-44 +#open 2013-08-26-19-04-08 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected #types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] bool -1359565680.761790 UWkUyAuUGXf 192.168.6.10 53209 192.168.129.36 53 udp 41477 paypal.com 1 C_INTERNET 48 DNSKEY 0 NOERROR F F T F 1 - - F -#close 2013-07-25-20-29-44 +1359565680.761790 CXWv6p3arKYeMETxOg 192.168.6.10 53209 192.168.129.36 53 udp 41477 paypal.com 1 C_INTERNET 48 DNSKEY 0 NOERROR F F T F 1 - - F +#close 2013-08-26-19-04-08 diff --git a/testing/btest/Baseline/scripts.base.protocols.dns.duplicate-reponses/dns.log b/testing/btest/Baseline/scripts.base.protocols.dns.duplicate-reponses/dns.log index ca071ee8ef..6af017fa49 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dns.duplicate-reponses/dns.log +++ b/testing/btest/Baseline/scripts.base.protocols.dns.duplicate-reponses/dns.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path dns -#open 2013-07-18-13-21-52 +#open 2013-08-26-19-04-08 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected #types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] bool -1363716396.798072 UWkUyAuUGXf 55.247.223.174 27285 222.195.43.124 53 udp 21140 www.cmu.edu 1 C_INTERNET 1 A 0 NOERROR T F F F 1 www-cmu.andrew.cmu.edu,www-cmu-2.andrew.cmu.edu,128.2.10.163,www-cmu.andrew.cmu.edu 86400.000000,5.000000,21600.000000,86400.000000 F -1363716396.798374 UWkUyAuUGXf 55.247.223.174 27285 222.195.43.124 53 udp 21140 - - - - - 0 NOERROR T F F F 0 www-cmu-2.andrew.cmu.edu,128.2.10.163 5.000000,21600.000000 F -#close 2013-07-18-13-21-52 +1363716396.798072 CXWv6p3arKYeMETxOg 55.247.223.174 27285 222.195.43.124 53 udp 21140 www.cmu.edu 1 C_INTERNET 1 A 0 NOERROR T F F F 1 www-cmu.andrew.cmu.edu,www-cmu-2.andrew.cmu.edu,128.2.10.163,www-cmu.andrew.cmu.edu 86400.000000,5.000000,21600.000000,86400.000000 F +1363716396.798374 CXWv6p3arKYeMETxOg 55.247.223.174 27285 222.195.43.124 53 udp 21140 - - - - - 0 NOERROR T F F F 0 www-cmu-2.andrew.cmu.edu,128.2.10.163 5.000000,21600.000000 F +#close 2013-08-26-19-04-08 diff --git a/testing/btest/Baseline/scripts.base.protocols.dns.duplicate-reponses/weird.log b/testing/btest/Baseline/scripts.base.protocols.dns.duplicate-reponses/weird.log index c7de92f894..175a474425 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dns.duplicate-reponses/weird.log +++ b/testing/btest/Baseline/scripts.base.protocols.dns.duplicate-reponses/weird.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path weird -#open 2013-07-18-13-21-52 +#open 2013-08-26-19-36-33 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1363716396.798286 UWkUyAuUGXf 55.247.223.174 27285 222.195.43.124 53 DNS_RR_unknown_type - F bro -1363716396.798374 UWkUyAuUGXf 55.247.223.174 27285 222.195.43.124 53 dns_unmatched_reply - F bro -#close 2013-07-18-13-21-52 +1363716396.798286 CXWv6p3arKYeMETxOg 55.247.223.174 27285 222.195.43.124 53 DNS_RR_unknown_type - F bro +1363716396.798374 CXWv6p3arKYeMETxOg 55.247.223.174 27285 222.195.43.124 53 dns_unmatched_reply - F bro +#close 2013-08-26-19-36-33 diff --git a/testing/btest/Baseline/scripts.base.protocols.dns.zero-responses/dns.log b/testing/btest/Baseline/scripts.base.protocols.dns.zero-responses/dns.log index 14ad7b77bc..32f9cc872f 100644 --- a/testing/btest/Baseline/scripts.base.protocols.dns.zero-responses/dns.log +++ b/testing/btest/Baseline/scripts.base.protocols.dns.zero-responses/dns.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dns -#open 2012-10-05-15-59-39 +#open 2013-08-26-19-04-09 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected #types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] bool -1349445121.080922 UWkUyAuUGXf 10.0.0.64 49204 146.186.163.66 53 udp 17323 psu.edu 1 C_INTERNET 28 AAAA 0 NOERROR F F T F 0 - - F -#close 2012-10-05-15-59-39 +1349445121.080922 CXWv6p3arKYeMETxOg 10.0.0.64 49204 146.186.163.66 53 udp 17323 psu.edu 1 C_INTERNET 28 AAAA 0 NOERROR F F T F 0 - - F +#close 2013-08-26-19-04-09 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log index 3520980833..69cdb7bb93 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log @@ -3,12 +3,12 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-02-21-16-53-13 +#open 2013-08-26-19-04-09 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1329843175.736107 arKYeMETxOg 141.142.220.235 37604 199.233.217.249 56666 tcp ftp-data 0.112432 0 342 SF - 0 ShAdfFa 4 216 4 562 (empty) -1329843179.871641 k6kgXLOoSKl 141.142.220.235 59378 199.233.217.249 56667 tcp ftp-data 0.111218 0 77 SF - 0 ShAdfFa 4 216 4 297 (empty) -1329843194.151526 nQcgTWjvg4c 199.233.217.249 61920 141.142.220.235 33582 tcp ftp-data 0.056211 342 0 SF - 0 ShADaFf 5 614 3 164 (empty) -1329843197.783443 j4u32Pc5bif 199.233.217.249 61918 141.142.220.235 37835 tcp ftp-data 0.056005 77 0 SF - 0 ShADaFf 5 349 3 164 (empty) -1329843161.968492 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 tcp ftp 38.055625 180 3146 SF - 0 ShAdDfFa 38 2164 25 4458 (empty) -#close 2012-02-21-16-53-20 +1329843175.736107 CjhGID4nQcgTWjvg4c 141.142.220.235 37604 199.233.217.249 56666 tcp ftp-data 0.112432 0 342 SF - 0 ShAdfFa 4 216 4 562 (empty) +1329843179.871641 CCvvfg3TEfuqmmG4bh 141.142.220.235 59378 199.233.217.249 56667 tcp ftp-data 0.111218 0 77 SF - 0 ShAdfFa 4 216 4 297 (empty) +1329843194.151526 CsRx2w45OKnoww6xl4 199.233.217.249 61920 141.142.220.235 33582 tcp ftp-data 0.056211 342 0 SF - 0 ShADaFf 5 614 3 164 (empty) +1329843197.783443 CRJuHdVW0XPVINV8a 199.233.217.249 61918 141.142.220.235 37835 tcp ftp-data 0.056005 77 0 SF - 0 ShADaFf 5 349 3 164 (empty) +1329843161.968492 CXWv6p3arKYeMETxOg 141.142.220.235 50003 199.233.217.249 21 tcp ftp 38.055625 180 3146 SF - 0 ShAdDfFa 38 2164 25 4458 (empty) +#close 2013-08-26-19-04-09 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log index 4cc6d67761..cabefb73fc 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log @@ -3,13 +3,13 @@ #empty_field (empty) #unset_field - #path ftp -#open 2013-07-27-01-49-02 +#open 2013-08-26-18-40-14 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p fuid #types time string addr port addr port string string string string string count count string bool addr addr port string -1329843175.680248 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,90) T 141.142.220.235 199.233.217.249 56666 - -1329843179.815947 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,91) T 141.142.220.235 199.233.217.249 56667 - -1329843179.926563 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. - - - - 4VAnSiNGSQh -1329843194.040188 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,131,46 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 33582 4VAnSiNGSQh -1329843197.672179 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,147,203 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 37835 4VAnSiNGSQh -1329843197.727769 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. - - - - aJg8mtdsS86 -#close 2013-07-27-01-49-02 +1329843175.680248 CXWv6p3arKYeMETxOg 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,90) T 141.142.220.235 199.233.217.249 56666 - +1329843179.815947 CXWv6p3arKYeMETxOg 141.142.220.235 50003 199.233.217.249 21 anonymous test PASV - - - 227 Entering Passive Mode (199,233,217,249,221,91) T 141.142.220.235 199.233.217.249 56667 - +1329843179.926563 CXWv6p3arKYeMETxOg 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. - - - - FmGk6O3KEoCPd4zuQd +1329843194.040188 CXWv6p3arKYeMETxOg 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,131,46 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 33582 FmGk6O3KEoCPd4zuQd +1329843197.672179 CXWv6p3arKYeMETxOg 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,147,203 - - 200 PORT command successful. F 199.233.217.249 141.142.220.235 37835 FmGk6O3KEoCPd4zuQd +1329843197.727769 CXWv6p3arKYeMETxOg 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. - - - - Fuh3fj1cWjSe4spPPl +#close 2013-08-26-18-40-14 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log index 3d81f45670..c31b1a6328 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log @@ -3,13 +3,13 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-02-15-17-43-15 +#open 2013-08-26-19-04-09 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1329327783.316897 arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49186 2001:470:4867:99::21 57086 tcp ftp-data 0.219721 0 342 SF - 0 ShAdfFa 5 372 4 642 (empty) -1329327786.524332 k6kgXLOoSKl 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49187 2001:470:4867:99::21 57087 tcp ftp-data 0.217501 0 43 SF - 0 ShAdfFa 5 372 4 343 (empty) -1329327787.289095 nQcgTWjvg4c 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49188 2001:470:4867:99::21 57088 tcp ftp-data 0.217941 0 77 SF - 0 ShAdfFa 5 372 4 377 (empty) -1329327795.571921 j4u32Pc5bif 2001:470:4867:99::21 55785 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49189 tcp ftp-data 0.109813 77 0 SF - 0 ShADFaf 5 449 4 300 (empty) -1329327777.822004 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 tcp ftp 26.658219 310 3448 SF - 0 ShAdDfFa 57 4426 34 5908 (empty) -1329327800.017649 TEfuqmmG4bh 2001:470:4867:99::21 55647 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49190 tcp ftp-data 0.109181 342 0 SF - 0 ShADFaf 5 714 4 300 (empty) -#close 2012-02-15-17-43-24 +1329327783.316897 CjhGID4nQcgTWjvg4c 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49186 2001:470:4867:99::21 57086 tcp ftp-data 0.219721 0 342 SF - 0 ShAdfFa 5 372 4 642 (empty) +1329327786.524332 CCvvfg3TEfuqmmG4bh 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49187 2001:470:4867:99::21 57087 tcp ftp-data 0.217501 0 43 SF - 0 ShAdfFa 5 372 4 343 (empty) +1329327787.289095 CsRx2w45OKnoww6xl4 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49188 2001:470:4867:99::21 57088 tcp ftp-data 0.217941 0 77 SF - 0 ShAdfFa 5 372 4 377 (empty) +1329327795.571921 CRJuHdVW0XPVINV8a 2001:470:4867:99::21 55785 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49189 tcp ftp-data 0.109813 77 0 SF - 0 ShADFaf 5 449 4 300 (empty) +1329327777.822004 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 tcp ftp 26.658219 310 3448 SF - 0 ShAdDfFa 57 4426 34 5908 (empty) +1329327800.017649 CPbrpk1qSsw6ESzHV4 2001:470:4867:99::21 55647 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49190 tcp ftp-data 0.109181 342 0 SF - 0 ShADFaf 5 714 4 300 (empty) +#close 2013-08-26-19-04-09 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log index d6f57bcf45..36cf521ae4 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log @@ -3,14 +3,14 @@ #empty_field (empty) #unset_field - #path ftp -#open 2013-07-27-01-49-13 +#open 2013-08-26-18-40-14 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type file_size reply_code reply_msg data_channel.passive data_channel.orig_h data_channel.resp_h data_channel.resp_p fuid #types time string addr port addr port string string string string string count count string bool addr addr port string -1329327783.207785 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57086|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57086 - -1329327786.415755 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57087|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57087 - -1329327787.180814 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57088|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57088 - -1329327787.396984 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - 77 226 Transfer complete. - - - - - -1329327795.355248 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49189| - - 200 EPRT command successful. F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49189 4YhNtGvCehl -1329327795.463946 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - 77 226 Transfer complete. - - - - 4YhNtGvCehl -1329327799.799327 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49190| - - 200 EPRT command successful. F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49190 4YhNtGvCehl -#close 2013-07-27-01-49-13 +1329327783.207785 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57086|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57086 - +1329327786.415755 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57087|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57087 - +1329327787.180814 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPSV - - - 229 Entering Extended Passive Mode (|||57088|) T 2001:470:1f11:81f:c999:d94:aa7c:2e3e 2001:470:4867:99::21 57088 - +1329327787.396984 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - 77 226 Transfer complete. - - - - - +1329327795.355248 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49189| - - 200 EPRT command successful. F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49189 F3XFox4nrGoBVJlBGd +1329327795.463946 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - 77 226 Transfer complete. - - - - F3XFox4nrGoBVJlBGd +1329327799.799327 CXWv6p3arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test EPRT |2|2001:470:1f11:81f:c999:d94:aa7c:2e3e|49190| - - 200 EPRT command successful. F 2001:470:4867:99::21 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49190 F3XFox4nrGoBVJlBGd +#close 2013-08-26-18-40-14 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/conn.log index f3ac10b5b0..423ac86ac0 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/conn.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/conn.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-10-05-21-45-15 +#open 2013-08-26-19-36-34 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1348168976.274919 UWkUyAuUGXf 192.168.57.103 60108 192.168.57.101 2811 tcp ssl,ftp,gridftp 0.294743 4491 6659 SF - 0 ShAdDaFf 22 5643 21 7759 (empty) -1348168976.546371 arKYeMETxOg 192.168.57.103 35391 192.168.57.101 55968 tcp ssl,gridftp-data 0.011938 2135 3196 S1 - 0 ShADad 8 2559 6 3516 (empty) -#close 2012-10-05-21-45-15 +1348168976.274919 CXWv6p3arKYeMETxOg 192.168.57.103 60108 192.168.57.101 2811 tcp ssl,ftp,gridftp 0.294743 4491 6659 SF - 0 ShAdDaFf 22 5643 21 7759 (empty) +1348168976.546371 CjhGID4nQcgTWjvg4c 192.168.57.103 35391 192.168.57.101 55968 tcp ssl,gridftp-data 0.011938 2135 3196 S1 - 0 ShADad 8 2559 6 3516 (empty) +#close 2013-08-26-19-36-34 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/notice.log b/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/notice.log index 04c80407f6..336f78dc2f 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/notice.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/notice.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path notice -#open 2013-07-23-05-19-25 +#open 2013-08-26-19-04-09 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fuid file_mime_type file_desc proto note msg sub src dst p n peer_descr actions suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude #types time string addr port addr port string string string enum enum string string addr addr port count string table[enum] interval bool string string string double double -1348168976.558309 arKYeMETxOg 192.168.57.103 35391 192.168.57.101 55968 - - - tcp GridFTP::Data_Channel GridFTP data channel over threshold 2 bytes - 192.168.57.103 192.168.57.101 55968 - bro Notice::ACTION_LOG 3600.000000 F - - - - - -#close 2013-07-23-05-19-25 +1348168976.558309 CjhGID4nQcgTWjvg4c 192.168.57.103 35391 192.168.57.101 55968 - - - tcp GridFTP::Data_Channel GridFTP data channel over threshold 2 bytes - 192.168.57.103 192.168.57.101 55968 - bro Notice::ACTION_LOG 3600.000000 F - - - - - +#close 2013-08-26-19-04-09 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/ssl.log b/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/ssl.log index 512676bbb6..20296a715e 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/ssl.log +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.gridftp/ssl.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path ssl -#open 2012-10-05-21-45-15 +#open 2013-08-26-19-47-01 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher server_name session_id subject issuer_subject not_valid_before not_valid_after last_alert client_subject client_issuer_subject #types time string addr port addr port string string string string string string time time string string string -1348168976.508038 UWkUyAuUGXf 192.168.57.103 60108 192.168.57.101 2811 TLSv10 TLS_RSA_WITH_AES_256_CBC_SHA - - CN=host/alpha,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Globus Simple CA,OU=simpleCA-alpha,OU=GlobusTest,O=Grid 1348161979.000000 1379697979.000000 - CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid -1348168976.551422 arKYeMETxOg 192.168.57.103 35391 192.168.57.101 55968 TLSv10 TLS_RSA_WITH_NULL_SHA - - CN=932373381,CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid 1348168676.000000 1348206441.000000 - CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid -#close 2012-10-05-21-45-15 +1348168976.508038 CXWv6p3arKYeMETxOg 192.168.57.103 60108 192.168.57.101 2811 TLSv10 TLS_RSA_WITH_AES_256_CBC_SHA - - CN=host/alpha,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Globus Simple CA,OU=simpleCA-alpha,OU=GlobusTest,O=Grid 1348161979.000000 1379697979.000000 - CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid +1348168976.551422 CjhGID4nQcgTWjvg4c 192.168.57.103 35391 192.168.57.101 55968 TLSv10 TLS_RSA_WITH_NULL_SHA - - CN=932373381,CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid 1348168676.000000 1348206441.000000 - CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid +#close 2013-08-26-19-47-01 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log b/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log index a81c0d4a2d..5aec6dfed3 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-19-39-08 +#open 2013-08-26-18-40-15 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1237440095.634312 UWkUyAuUGXf 192.168.3.103 54102 128.146.216.51 80 1 POST www.osu.edu / - curl/7.17.1 (i386-apple-darwin8.11.1) libcurl/7.17.1 zlib/1.2.3 2001 60731 200 OK 100 Continue - (empty) - - - 8TXBHVmBGD7 text/plain ATGo7hdUXdi text/html -#close 2013-07-25-19-39-08 +1237440095.634312 CXWv6p3arKYeMETxOg 192.168.3.103 54102 128.146.216.51 80 1 POST www.osu.edu / - curl/7.17.1 (i386-apple-darwin8.11.1) libcurl/7.17.1 zlib/1.2.3 2001 60731 200 OK 100 Continue - (empty) - - - F7Wq2D1IW7Cp2nfZMa text/plain FFhC1T3ieHHQqVBLpc text/html +#close 2013-08-26-18-40-15 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log index 674e355631..dea803676b 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/http.log @@ -3,56 +3,56 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-19-41-27 +#open 2013-08-26-18-40-16 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1354328870.191989 UWkUyAuUGXf 128.2.6.136 46562 173.194.75.103 80 1 OPTIONS www.google.com * - - 0 962 405 Method Not Allowed - - - (empty) - - - - - VTrFjxi3V27 text/html -1354328874.237327 arKYeMETxOg 128.2.6.136 46563 173.194.75.103 80 1 OPTIONS www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - jeoiUX9q8v9 text/html -1354328874.299063 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - 6dL7NPgFhil text/html -1354328874.342591 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - cix6gzDRCob text/html -1354328874.364020 j4u32Pc5bif 128.2.6.136 46566 173.194.75.103 80 1 GET www.google.com / - - 0 43911 200 OK - - - (empty) - - - - - tCZHDKUkBdi text/html -1354328878.470424 TEfuqmmG4bh 128.2.6.136 46567 173.194.75.103 80 1 GET www.google.com / - - 0 43983 200 OK - - - (empty) - - - - - iVzFNTeQnnc text/html -1354328882.575456 FrJExwHcSal 128.2.6.136 46568 173.194.75.103 80 1 GET www.google.com /HTTP/1.1 - - 0 1207 403 Forbidden - - - (empty) - - - - - boBAqw2JcFi text/html -1354328882.928027 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - r3w183FJvW3 text/html -1354328882.968948 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - bncugeoItlf text/html -1354328882.990373 VW0XPVINV8a 128.2.6.136 46571 173.194.75.103 80 1 GET www.google.com / - - 0 43913 200 OK - - - (empty) - - - - - NkYD5vo8Gy text/html -1354328887.114613 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 0 - - - - - 0 961 405 Method Not Allowed - - - (empty) - - - - - S85THffBTLh text/html -1354328891.161077 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - 2m6kUZZS0wd text/html -1354328891.204740 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - UoqtpOgJZSk text/html -1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - mqs8p4wwsS7 text/html -1354328891.287655 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - S36eCQJUY5k text/html -1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - - - LeNRDWYrpS7 text/html -1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 1 CCM_POST www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - ZwKUASlWzYk text/html -1354328895.416133 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - uj62KNQhsG3 text/html -1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - taBxWzrYquk text/html -1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - - - bHBxZULKI0k text/html -1354328899.526682 EAr0uf4mhq 128.2.6.136 46582 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - - - t6k8zHaGZk5 text/html -1354328903.572533 GvmoxJFXdTa 128.2.6.136 46583 173.194.75.103 80 1 CONNECT www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - c11un7ZO6nc text/html -1354328903.634196 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - iWCHzW5XJWk text/html -1354328903.676395 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - dzvHktkjD9a text/html -1354328903.697693 UfGkYA2HI2g 128.2.6.136 46586 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - - - vEO9iYqh3Zc text/html -1354328907.743696 i2rO3KD1Syg 128.2.6.136 46587 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - - - 8seYaeRVuV2 text/html -1354328911.790590 2cx26uAvUPl 128.2.6.136 46588 173.194.75.103 80 1 TRACE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - 0kkHkmLHFl3 text/html -1354328911.853464 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - koHEYsvMVBa text/html -1354328911.897044 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - 50tlwxQjBCb text/html -1354328911.918511 zno26fFZkrh 128.2.6.136 46591 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - - - DdECXqOZjXh text/html -1354328915.964678 v5rgkJBig5l 128.2.6.136 46592 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - - - LIZQeBP0Coi text/html -1354328920.010458 eWZCH7OONC1 128.2.6.136 46593 173.194.75.103 80 1 DELETE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - hjPo0BdP973 text/html -1354328920.072101 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - d6K2onvteNa text/html -1354328920.114526 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - BY1g634OMv6 text/html -1354328920.136714 yC2d6kVg709 128.2.6.136 46596 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - - - 5aAa2m40fZd text/html -1354328924.183211 VcgagLjnO92 128.2.6.136 46597 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - y3Syn85ve8e text/html -1354328924.224567 bdRoHfaPBo3 128.2.6.136 46598 173.194.75.103 80 1 PUT www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - - - P92nMD5z6D4 text/html -1354328924.287402 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - qIPObDBIhSj text/html -1354328924.328257 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - su86MWxyjne text/html -1354328924.350343 xNYSS2hJkle 128.2.6.136 46601 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - r2aysGE6ve8 text/html -1354328924.391728 vMVjlplKKbd 128.2.6.136 46602 173.194.75.103 80 1 POST www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - Zosv3c0p2Zb text/html -1354328924.433150 3omNawSNrxj 128.2.6.136 46603 173.194.75.103 80 1 POST www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - - - L02QmCl2lX4 text/html -1354328924.496732 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - uh9TwTMdWI9 text/html -1354328924.537671 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - 4gLQ9WVkuYd text/html -1354328924.559704 E490YZTUozc 128.2.6.136 46606 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - - -1354328928.625437 YIeWJmXWNWj 128.2.6.136 46607 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - - -1354328932.692706 ydiZblvsYri 128.2.6.136 46608 173.194.75.103 80 1 HEAD www.google.com /HTTP/1.1 - - 0 0 400 Bad Request - - - (empty) - - - - - - - -1354328932.754657 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - NIV5LGdqSk2 text/html -1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - SlC7NZIgx1d text/html -#close 2013-07-25-19-41-27 +1354328870.191989 CXWv6p3arKYeMETxOg 128.2.6.136 46562 173.194.75.103 80 1 OPTIONS www.google.com * - - 0 962 405 Method Not Allowed - - - (empty) - - - - - FKgccv1sOsIPuN3b73 text/html +1354328874.237327 CjhGID4nQcgTWjvg4c 128.2.6.136 46563 173.194.75.103 80 1 OPTIONS www.google.com HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - FWUdF12OgqGLhf3NPl text/html +1354328874.299063 CCvvfg3TEfuqmmG4bh 128.2.6.136 46564 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FE9yCx4wFg8js0ey37 text/html +1354328874.342591 CsRx2w45OKnoww6xl4 128.2.6.136 46565 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FNt1Jq2h23tJ5Hwp2b text/html +1354328874.364020 CRJuHdVW0XPVINV8a 128.2.6.136 46566 173.194.75.103 80 1 GET www.google.com / - - 0 43911 200 OK - - - (empty) - - - - - FbONWS332vB7QP1sDi text/html +1354328878.470424 CPbrpk1qSsw6ESzHV4 128.2.6.136 46567 173.194.75.103 80 1 GET www.google.com / - - 0 43983 200 OK - - - (empty) - - - - - Fw8xGD2taqNAOVvI88 text/html +1354328882.575456 C6pKV8GSxOnSLghOa 128.2.6.136 46568 173.194.75.103 80 1 GET www.google.com /HTTP/1.1 - - 0 1207 403 Forbidden - - - (empty) - - - - - FdEQPY3H4Z608y5yq1 text/html +1354328882.928027 CIPOse170MGiRM1Qf4 128.2.6.136 46569 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - Fe1D9QLJph7d7eq5l text/html +1354328882.968948 C7XEbhP654jzLoe3a 128.2.6.136 46570 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FxJ9Xg33X67Nyx01C2 text/html +1354328882.990373 CJ3xTn1c4Zw9TmAE05 128.2.6.136 46571 173.194.75.103 80 1 GET www.google.com / - - 0 43913 200 OK - - - (empty) - - - - - FAbDo7c8yz5wducYb text/html +1354328887.114613 CMXxB5GvmoxJFXdTa 128.2.6.136 46572 173.194.75.103 80 0 - - - - - 0 961 405 Method Not Allowed - - - (empty) - - - - - Fz1p2N3K0efiD4l7kc text/html +1354328891.161077 Caby8b1slFea8xwSmb 128.2.6.136 46573 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FnhBKS2ssy1v8C41Jf text/html +1354328891.204740 Che1bq3i2rO3KD1Syg 128.2.6.136 46574 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FWs6es4rYFRUFyUzC1 text/html +1354328891.245592 C3SfNE4BWaU4aSuwkc 128.2.6.136 46575 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FNQNbG1yFFfHE0L8O7 text/html +1354328891.287655 CEle3f3zno26fFZkrh 128.2.6.136 46576 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FzDULh4an8RDf3xKpi text/html +1354328891.309065 CwSkQu4eWZCH7OONC1 128.2.6.136 46577 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - - - F1d9bG11AdUoYIAPna text/html +1354328895.355012 CfTOmO0HKorjr8Zp7 128.2.6.136 46578 173.194.75.103 80 1 CCM_POST www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - F73Xpt400aDAjp1tOj text/html +1354328895.416133 CzA03V1VcgagLjnO92 128.2.6.136 46579 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FlniJMJjcc7kx6rhj text/html +1354328895.459490 CyAhVIzHqb7t7kv28 128.2.6.136 46580 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FihiZm4nJV0LOus1F1 text/html +1354328895.480865 Cab0vO1xNYSS2hJkle 128.2.6.136 46581 173.194.75.103 80 1 CCM_POST www.google.com / - - 0 963 405 Method Not Allowed - - - (empty) - - - - - FodlEg40uUijFetJb9 text/html +1354328899.526682 Cx2FqO23omNawSNrxj 128.2.6.136 46582 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - - - FgQlB81dSyLHN5T8Q4 text/html +1354328903.572533 Cx3C534wEyF3OvvcQe 128.2.6.136 46583 173.194.75.103 80 1 CONNECT www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - FW2UCD2e0jxAndsTK3 text/html +1354328903.634196 CkDsfG2YIeWJmXWNWj 128.2.6.136 46584 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FNzD1t4XvaMaqIEamf text/html +1354328903.676395 CUKS0W3HFYOnBqSE5e 128.2.6.136 46585 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - Fq1Oia2lyBocfl9sX6 text/html +1354328903.697693 CRrfvP2lalMAYOCLhj 128.2.6.136 46586 173.194.75.103 80 1 CONNECT www.google.com / - - 0 925 400 Bad Request - - - (empty) - - - - - FAVGIL2N6x9nLyfGHh text/html +1354328907.743696 Cn78a440HlxuyZKs6f 128.2.6.136 46587 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - - - FKbiICMAvCsO6CFjk text/html +1354328911.790590 CUof3F2yAIid8QS3dk 128.2.6.136 46588 173.194.75.103 80 1 TRACE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - FD5riIpYe5BLR0aok text/html +1354328911.853464 CojBOU3CXcLHl1r6x1 128.2.6.136 46589 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FHB2lg2TvAjywhH0Yc text/html +1354328911.897044 CJzVQRGJrX6V15ik7 128.2.6.136 46590 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FIcQHt2xzPeH47BMdl text/html +1354328911.918511 ClAbxY1nmdjCuo0Le2 128.2.6.136 46591 173.194.75.103 80 1 TRACE www.google.com / - - 0 960 405 Method Not Allowed - - - (empty) - - - - - FQrvtP3qpKeKPxn5Gf text/html +1354328915.964678 CwG0BF1VXE0gWgs78 128.2.6.136 46592 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - - - Fs5qiV3XoBOExKLdi4 text/html +1354328920.010458 CisNaL1Cm73CiNOmcg 128.2.6.136 46593 173.194.75.103 80 1 DELETE www.google.com /HTTP/1.1 - - 0 925 400 Bad Request - - - (empty) - - - - - FpkucFbcGcM4CNkZf text/html +1354328920.072101 CBQnJn22qN8TOeeZil 128.2.6.136 46594 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FcavKi2ltkvguBtFh4 text/html +1354328920.114526 CbEsuD3dgDDngdlbKf 128.2.6.136 46595 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FWc18o1CNTndDqC3Sc text/html +1354328920.136714 Cktvtw2VqwbTG0OgWk 128.2.6.136 46596 173.194.75.103 80 1 DELETE www.google.com / - - 0 961 405 Method Not Allowed - - - (empty) - - - - - FNb8ZY2Zvw0MpF1qU4 text/html +1354328924.183211 CKfF8L3XSsgT2WYDN 128.2.6.136 46597 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - Fo23U03XCMamm7QQWe text/html +1354328924.224567 CHrnr1115j0JRSXjG6 128.2.6.136 46598 173.194.75.103 80 1 PUT www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - - - FqyVeZqSV8Tz7hfT1 text/html +1354328924.287402 Cnkr172qPtDAaK7Xd 128.2.6.136 46599 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FeaMQe4sztncIKuIdg text/html +1354328924.328257 CcxZj6188NwHGl3a16 128.2.6.136 46600 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FVZu7439jNbDyOjNDj text/html +1354328924.350343 CUqYZc2XzbfnZKbgT 128.2.6.136 46601 173.194.75.103 80 1 PUT www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - FuGiTK15gnR7f8Uti2 text/html +1354328924.391728 CVdnYXVEtNT1lQVL6 128.2.6.136 46602 173.194.75.103 80 1 POST www.google.com / - - 0 934 411 Length Required - - - (empty) - - - - - F93zuy2MGUDDPwg0xl text/html +1354328924.433150 CbNmy32YFt3gdIjV8 128.2.6.136 46603 173.194.75.103 80 1 POST www.google.com /HTTP/1.1 - - 0 934 411 Length Required - - - (empty) - - - - - FRJvy31aqXlFemaBfc text/html +1354328924.496732 COTmF91mGWcb4zV7W5 128.2.6.136 46604 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FMJLB42ry1sw3MMTq8 text/html +1354328924.537671 CuChlg202P8sUFuXrg 128.2.6.136 46605 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - Fx4bPY2OFFAByxhLAl text/html +1354328924.559704 CZTTFm2GrMAs8leAyl 128.2.6.136 46606 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - - +1354328928.625437 CV23rC3tBHfPhMUPtf 128.2.6.136 46607 173.194.75.103 80 1 HEAD www.google.com / - - 0 0 200 OK - - - (empty) - - - - - - - +1354328932.692706 CkaPGx2P0Y3W5aHVFk 128.2.6.136 46608 173.194.75.103 80 1 HEAD www.google.com /HTTP/1.1 - - 0 0 400 Bad Request - - - (empty) - - - - - - - +1354328932.754657 CY93mM3aViMiLKuSw3 128.2.6.136 46609 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - F04ZTu63dLSqJQpwa text/html +1354328932.796568 CXgISq6dA2DVPzqp9 128.2.6.136 46610 173.194.75.103 80 0 - - - - - 0 925 400 Bad Request - - - (empty) - - - - - FVoxfM2o0FqsBuQkDa text/html +#close 2013-08-26-18-40-16 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log index 8b963f00cf..9b9ba53885 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-methods/weird.log @@ -3,56 +3,56 @@ #empty_field (empty) #unset_field - #path weird -#open 2012-12-07-04-43-19 +#open 2013-08-26-19-04-10 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string -1354328874.278822 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 bad_HTTP_request - F bro -1354328874.299063 k6kgXLOoSKl 128.2.6.136 46564 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328874.321792 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 bad_HTTP_request - F bro -1354328874.342591 nQcgTWjvg4c 128.2.6.136 46565 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328882.908690 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 bad_HTTP_request - F bro -1354328882.928027 5OKnoww6xl4 128.2.6.136 46569 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328882.949510 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 bad_HTTP_request - F bro -1354328882.968948 3PKsZ2Uye21 128.2.6.136 46570 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328887.094494 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 bad_HTTP_request - F bro -1354328887.114613 fRFu0wcOle6 128.2.6.136 46572 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328891.141058 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 bad_HTTP_request - F bro -1354328891.161077 qSsw6ESzHV4 128.2.6.136 46573 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328891.183942 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 bad_HTTP_request - F bro -1354328891.204740 iE6yhOq3SF 128.2.6.136 46574 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328891.226199 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 bad_HTTP_request - F bro -1354328891.245592 GSxOnSLghOa 128.2.6.136 46575 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328891.267625 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 bad_HTTP_request - F bro -1354328891.287655 qCaWGmzFtM5 128.2.6.136 46576 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328891.309065 70MGiRM1Qf4 128.2.6.136 46577 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro -1354328895.355012 h5DsfNtYzi1 128.2.6.136 46578 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro -1354328895.396634 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 bad_HTTP_request - F bro -1354328895.416133 P654jzLoe3a 128.2.6.136 46579 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328895.438812 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 bad_HTTP_request - F bro -1354328895.459490 Tw8jXtpTGu6 128.2.6.136 46580 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328895.480865 c4Zw9TmAE05 128.2.6.136 46581 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro -1354328903.614145 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 bad_HTTP_request - F bro -1354328903.634196 0Q4FH8sESw5 128.2.6.136 46584 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328903.656369 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 bad_HTTP_request - F bro -1354328903.676395 slFea8xwSmb 128.2.6.136 46585 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328911.832856 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 bad_HTTP_request - F bro -1354328911.853464 BWaU4aSuwkc 128.2.6.136 46589 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328911.876341 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 bad_HTTP_request - F bro -1354328911.897044 10XodEwRycf 128.2.6.136 46590 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328920.052085 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 bad_HTTP_request - F bro -1354328920.072101 0Pwk3ntf8O3 128.2.6.136 46594 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328920.094072 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 bad_HTTP_request - F bro -1354328920.114526 0HKorjr8Zp7 128.2.6.136 46595 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328924.266693 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 bad_HTTP_request - F bro -1354328924.287402 zHqb7t7kv28 128.2.6.136 46599 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328924.308714 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 bad_HTTP_request - F bro -1354328924.328257 rrZWoMUQpv8 128.2.6.136 46600 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328924.476011 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 bad_HTTP_request - F bro -1354328924.496732 Rv8AJVfi9Zi 128.2.6.136 46604 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328924.518204 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 bad_HTTP_request - F bro -1354328924.537671 wEyF3OvvcQe 128.2.6.136 46605 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328932.734579 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 bad_HTTP_request - F bro -1354328932.754657 HFYOnBqSE5e 128.2.6.136 46609 173.194.75.103 80 unmatched_HTTP_reply - F bro -1354328932.776609 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 bad_HTTP_request - F bro -1354328932.796568 JcUvhfWUMgd 128.2.6.136 46610 173.194.75.103 80 unmatched_HTTP_reply - F bro -#close 2012-12-07-04-43-19 +1354328874.278822 CCvvfg3TEfuqmmG4bh 128.2.6.136 46564 173.194.75.103 80 bad_HTTP_request - F bro +1354328874.299063 CCvvfg3TEfuqmmG4bh 128.2.6.136 46564 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328874.321792 CsRx2w45OKnoww6xl4 128.2.6.136 46565 173.194.75.103 80 bad_HTTP_request - F bro +1354328874.342591 CsRx2w45OKnoww6xl4 128.2.6.136 46565 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328882.908690 CIPOse170MGiRM1Qf4 128.2.6.136 46569 173.194.75.103 80 bad_HTTP_request - F bro +1354328882.928027 CIPOse170MGiRM1Qf4 128.2.6.136 46569 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328882.949510 C7XEbhP654jzLoe3a 128.2.6.136 46570 173.194.75.103 80 bad_HTTP_request - F bro +1354328882.968948 C7XEbhP654jzLoe3a 128.2.6.136 46570 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328887.094494 CMXxB5GvmoxJFXdTa 128.2.6.136 46572 173.194.75.103 80 bad_HTTP_request - F bro +1354328887.114613 CMXxB5GvmoxJFXdTa 128.2.6.136 46572 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.141058 Caby8b1slFea8xwSmb 128.2.6.136 46573 173.194.75.103 80 bad_HTTP_request - F bro +1354328891.161077 Caby8b1slFea8xwSmb 128.2.6.136 46573 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.183942 Che1bq3i2rO3KD1Syg 128.2.6.136 46574 173.194.75.103 80 bad_HTTP_request - F bro +1354328891.204740 Che1bq3i2rO3KD1Syg 128.2.6.136 46574 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.226199 C3SfNE4BWaU4aSuwkc 128.2.6.136 46575 173.194.75.103 80 bad_HTTP_request - F bro +1354328891.245592 C3SfNE4BWaU4aSuwkc 128.2.6.136 46575 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.267625 CEle3f3zno26fFZkrh 128.2.6.136 46576 173.194.75.103 80 bad_HTTP_request - F bro +1354328891.287655 CEle3f3zno26fFZkrh 128.2.6.136 46576 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328891.309065 CwSkQu4eWZCH7OONC1 128.2.6.136 46577 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro +1354328895.355012 CfTOmO0HKorjr8Zp7 128.2.6.136 46578 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro +1354328895.396634 CzA03V1VcgagLjnO92 128.2.6.136 46579 173.194.75.103 80 bad_HTTP_request - F bro +1354328895.416133 CzA03V1VcgagLjnO92 128.2.6.136 46579 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328895.438812 CyAhVIzHqb7t7kv28 128.2.6.136 46580 173.194.75.103 80 bad_HTTP_request - F bro +1354328895.459490 CyAhVIzHqb7t7kv28 128.2.6.136 46580 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328895.480865 Cab0vO1xNYSS2hJkle 128.2.6.136 46581 173.194.75.103 80 unknown_HTTP_method CCM_POST F bro +1354328903.614145 CkDsfG2YIeWJmXWNWj 128.2.6.136 46584 173.194.75.103 80 bad_HTTP_request - F bro +1354328903.634196 CkDsfG2YIeWJmXWNWj 128.2.6.136 46584 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328903.656369 CUKS0W3HFYOnBqSE5e 128.2.6.136 46585 173.194.75.103 80 bad_HTTP_request - F bro +1354328903.676395 CUKS0W3HFYOnBqSE5e 128.2.6.136 46585 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328911.832856 CojBOU3CXcLHl1r6x1 128.2.6.136 46589 173.194.75.103 80 bad_HTTP_request - F bro +1354328911.853464 CojBOU3CXcLHl1r6x1 128.2.6.136 46589 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328911.876341 CJzVQRGJrX6V15ik7 128.2.6.136 46590 173.194.75.103 80 bad_HTTP_request - F bro +1354328911.897044 CJzVQRGJrX6V15ik7 128.2.6.136 46590 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328920.052085 CBQnJn22qN8TOeeZil 128.2.6.136 46594 173.194.75.103 80 bad_HTTP_request - F bro +1354328920.072101 CBQnJn22qN8TOeeZil 128.2.6.136 46594 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328920.094072 CbEsuD3dgDDngdlbKf 128.2.6.136 46595 173.194.75.103 80 bad_HTTP_request - F bro +1354328920.114526 CbEsuD3dgDDngdlbKf 128.2.6.136 46595 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328924.266693 Cnkr172qPtDAaK7Xd 128.2.6.136 46599 173.194.75.103 80 bad_HTTP_request - F bro +1354328924.287402 Cnkr172qPtDAaK7Xd 128.2.6.136 46599 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328924.308714 CcxZj6188NwHGl3a16 128.2.6.136 46600 173.194.75.103 80 bad_HTTP_request - F bro +1354328924.328257 CcxZj6188NwHGl3a16 128.2.6.136 46600 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328924.476011 COTmF91mGWcb4zV7W5 128.2.6.136 46604 173.194.75.103 80 bad_HTTP_request - F bro +1354328924.496732 COTmF91mGWcb4zV7W5 128.2.6.136 46604 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328924.518204 CuChlg202P8sUFuXrg 128.2.6.136 46605 173.194.75.103 80 bad_HTTP_request - F bro +1354328924.537671 CuChlg202P8sUFuXrg 128.2.6.136 46605 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328932.734579 CY93mM3aViMiLKuSw3 128.2.6.136 46609 173.194.75.103 80 bad_HTTP_request - F bro +1354328932.754657 CY93mM3aViMiLKuSw3 128.2.6.136 46609 173.194.75.103 80 unmatched_HTTP_reply - F bro +1354328932.776609 CXgISq6dA2DVPzqp9 128.2.6.136 46610 173.194.75.103 80 bad_HTTP_request - F bro +1354328932.796568 CXgISq6dA2DVPzqp9 128.2.6.136 46610 173.194.75.103 80 unmatched_HTTP_reply - F bro +#close 2013-08-26-19-04-10 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log index 6779485f91..a9fd14cf34 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log @@ -3,12 +3,12 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-19-43-06 +#open 2013-08-26-18-40-16 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1258577884.844956 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 1 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2675 200 OK - - - (empty) - - - - - XRu8VItOvLc text/plain -1258577884.960135 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 2 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 21421 200 OK - - - (empty) - - - - - m1D1wMxW9y8 text/plain -1258577885.317160 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 3 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 94 200 OK - - - (empty) - - - - - ZwnCaxWANNb image/gif -1258577885.349639 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 4 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2349 200 OK - - - (empty) - - - - - 3WVi9g0Caei image/png -1258577885.394612 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 5 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 27579 200 OK - - - (empty) - - - - - ta9bGBff1Wl image/png -#close 2013-07-25-19-43-06 +1258577884.844956 CXWv6p3arKYeMETxOg 192.168.1.104 1673 63.245.209.11 80 1 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2675 200 OK - - - (empty) - - - - - Fa7DPI2ItmEOoVqyYj text/plain +1258577884.960135 CXWv6p3arKYeMETxOg 192.168.1.104 1673 63.245.209.11 80 2 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 21421 200 OK - - - (empty) - - - - - FnBh5P1KP0SnMzl3Qj text/plain +1258577885.317160 CXWv6p3arKYeMETxOg 192.168.1.104 1673 63.245.209.11 80 3 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 94 200 OK - - - (empty) - - - - - F2TV5w2Kwn3G7doSk5 image/gif +1258577885.349639 CXWv6p3arKYeMETxOg 192.168.1.104 1673 63.245.209.11 80 4 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2349 200 OK - - - (empty) - - - - - F4kk4T3Unyqtkczzue image/png +1258577885.394612 CXWv6p3arKYeMETxOg 192.168.1.104 1673 63.245.209.11 80 5 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 27579 200 OK - - - (empty) - - - - - FcB26G4nL7jRheOyA8 image/png +#close 2013-08-26-18-40-16 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.multipart-extract/http.log b/testing/btest/Baseline/scripts.base.protocols.http.multipart-extract/http.log index ae71680dfa..a32d83d79c 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.multipart-extract/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.multipart-extract/http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-07-25-19-50-23 +#open 2013-08-26-18-40-16 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] vector[string] vector[string] vector[string] vector[string] -1369159408.455878 UWkUyAuUGXf 141.142.228.5 57262 54.243.88.146 80 1 POST httpbin.org /post - curl/7.30.0 370 465 200 OK - - - (empty) - - - UB09X6VFGTd,wFP689pOsIa,g5yDIGBH4i5 text/plain,text/plain,text/plain yv4qm3EsdOc text/plain -#close 2013-07-25-19-50-23 +1369159408.455878 CXWv6p3arKYeMETxOg 141.142.228.5 57262 54.243.88.146 80 1 POST httpbin.org /post - curl/7.30.0 370 465 200 OK - - - (empty) - - - F2yGNX2vGXLxfZeD12,Fq4rJh2kLHKa8YC1q1,F9sKY71Rb9megdy7sg text/plain,text/plain,text/plain FjeopJ2lRk9U1CNNb5 text/plain +#close 2013-08-26-18-40-16 diff --git a/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log b/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log index 8249c94938..7f6fa31d5a 100644 --- a/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log +++ b/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log @@ -3,11 +3,11 @@ #empty_field (empty) #unset_field - #path irc -#open 2013-07-25-19-51-43 +#open 2013-08-26-19-04-11 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user command value addl dcc_file_name dcc_file_size fuid #types time string addr port addr port string string string string string string count string -1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 - - NICK bloed - - - - -1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - -1311189174.474127 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje JOIN #easymovies (empty) - - - -1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje DCC #easymovies (empty) ladyvampress-default(2011-07-07)-OS.zip 42208 - -#close 2013-07-25-19-51-43 +1311189164.119437 CXWv6p3arKYeMETxOg 192.168.1.77 57640 66.198.80.67 6667 - - NICK bloed - - - - +1311189164.119437 CXWv6p3arKYeMETxOg 192.168.1.77 57640 66.198.80.67 6667 bloed - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - +1311189174.474127 CXWv6p3arKYeMETxOg 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje JOIN #easymovies (empty) - - - +1311189316.326025 CXWv6p3arKYeMETxOg 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje DCC #easymovies (empty) ladyvampress-default(2011-07-07)-OS.zip 42208 - +#close 2013-08-26-19-04-11 diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/modbus.log b/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/modbus.log index 315907f8c4..407487756d 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/modbus.log +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/modbus.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path modbus -#open 2012-11-12-17-40-34 +#open 2013-08-26-19-04-11 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p func exception #types time string addr port addr port string string -1153491909.414125 UWkUyAuUGXf 192.168.66.235 2582 166.161.16.230 502 unknown-156 - -1153491913.013726 UWkUyAuUGXf 192.168.66.235 2582 166.161.16.230 502 unknown-162 - -#close 2012-11-12-17-40-34 +1153491909.414125 CXWv6p3arKYeMETxOg 192.168.66.235 2582 166.161.16.230 502 unknown-156 - +1153491913.013726 CXWv6p3arKYeMETxOg 192.168.66.235 2582 166.161.16.230 502 unknown-162 - +#close 2013-08-26-19-04-11 diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/weird.log b/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/weird.log index 455b7602f6..57fa59a1ef 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/weird.log +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.exception_handling/weird.log @@ -3,9 +3,9 @@ #empty_field (empty) #unset_field - #path weird -#open 2012-11-12-17-40-34 +#open 2013-08-26-19-36-36 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer #types time string addr port addr port string string bool string 1153491909.414066 - - - - - truncated_IP - F bro -1153491912.529443 UWkUyAuUGXf 192.168.66.235 2582 166.161.16.230 502 binpac exception: out_of_bound: WriteSingleRegisterRequest: 4 > 0 - F bro -#close 2012-11-12-17-40-34 +1153491912.529443 CXWv6p3arKYeMETxOg 192.168.66.235 2582 166.161.16.230 502 binpac exception: out_of_bound: WriteSingleRegisterRequest: 4 > 0 - F bro +#close 2013-08-26-19-36-36 diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.policy/modbus.log b/testing/btest/Baseline/scripts.base.protocols.modbus.policy/modbus.log index b52fbb5a19..1752ed3c34 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.policy/modbus.log +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.policy/modbus.log @@ -3,19988 +3,19988 @@ #empty_field (empty) #unset_field - #path modbus -#open 2012-11-06-00-51-15 +#open 2013-08-26-19-04-12 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p func exception #types time string addr port addr port string string -1093521704.839184 arKYeMETxOg 10.0.0.57 2578 10.0.0.3 502 DIAGNOSTICS - -1093521710.268829 arKYeMETxOg 10.0.0.57 2578 10.0.0.3 502 DIAGNOSTICS - -1093521740.211122 arKYeMETxOg 10.0.0.57 2578 10.0.0.3 502 DIAGNOSTICS - -1093521743.213870 arKYeMETxOg 10.0.0.57 2578 10.0.0.3 502 DIAGNOSTICS - -1093521997.919380 arKYeMETxOg 10.0.0.57 2578 10.0.0.3 502 REPORT_SLAVE_ID - -1093522000.292566 arKYeMETxOg 10.0.0.57 2578 10.0.0.3 502 REPORT_SLAVE_ID - -1093522338.987616 nQcgTWjvg4c 10.0.0.9 3082 10.0.0.3 502 READ_COILS - -1093522368.744337 nQcgTWjvg4c 10.0.0.9 3082 10.0.0.3 502 READ_COILS - -1093522405.134171 nQcgTWjvg4c 10.0.0.9 3082 10.0.0.3 502 READ_HOLDING_REGISTERS - -1093522432.261317 nQcgTWjvg4c 10.0.0.9 3082 10.0.0.3 502 WRITE_SINGLE_COIL - -1093522442.074410 nQcgTWjvg4c 10.0.0.9 3082 10.0.0.3 502 WRITE_SINGLE_COIL - -1093522480.000230 nQcgTWjvg4c 10.0.0.9 3082 10.0.0.3 502 WRITE_SINGLE_REGISTER - -1153491892.783650 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-128 - -1153491893.492404 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491893.492404 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_VALUE -1153491893.990688 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_DISCRETE_INPUTS_EXCEPTION ILLEGAL_DATA_VALUE -1153491894.576738 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_HOLDING_REGISTERS_EXCEPTION ILLEGAL_DATA_VALUE -1153491895.256017 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_INPUT_REGISTERS_EXCEPTION ILLEGAL_DATA_VALUE -1153491895.832303 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 WRITE_SINGLE_COIL - -1153491896.426683 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 WRITE_SINGLE_REGISTER_EXCEPTION ILLEGAL_DATA_VALUE -1153491897.165539 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_EXCEPTION_STATUS - -1153491897.712499 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 DIAGNOSTICS - -1153491901.676648 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 WRITE_MULTIPLE_COILS_EXCEPTION ILLEGAL_DATA_VALUE -1153491902.236242 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 WRITE_MULTIPLE_REGISTERS_EXCEPTION ILLEGAL_DATA_VALUE -1153491904.958574 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_FILE_RECORD_EXCEPTION ILLEGAL_DATA_VALUE -1153491905.606024 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 WRITE_FILE_RECORD_EXCEPTION ILLEGAL_DATA_VALUE -1153491906.126922 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 MASK_WRITE_REGISTER_EXCEPTION ILLEGAL_DATA_VALUE -1153491906.665323 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_WRITE_MULTIPLE_REGISTERS_EXCEPTION ILLEGAL_DATA_VALUE -1153491907.202989 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_FIFO_QUEUE_EXCEPTION - -1153491907.202989 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_FIFO_QUEUE_EXCEPTION ILLEGAL_DATA_VALUE -1153491907.721092 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-153 - -1153491908.288044 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-154 - -1153491908.794212 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-155 - -1153491909.414125 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-156 - -1153491910.093490 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-157 - -1153491910.705044 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-158 - -1153491911.416719 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-159 - -1153491911.976794 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-160 - -1153491912.494612 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-161 - -1153491913.013726 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-162 - -1153491913.563241 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-163 - -1153491914.102765 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-164 - -1153491914.609591 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-165 - -1153491915.148323 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-166 - -1153491915.666317 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-167 - -1153491916.246101 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 PROGRAM_CONCEPT - -1153491916.839806 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-169 - -1153491917.510280 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-42 - -1153491918.097523 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-171 - -1153491918.886019 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-172 - -1153491919.637519 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-173 - -1153491920.132919 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-174 - -1153491920.661039 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-175 - -1153491921.200303 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-176 - -1153491921.780851 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-177 - -1153491922.516425 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-178 - -1153491923.075893 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-179 - -1153491923.568357 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-180 - -1153491924.126968 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-181 - -1153491924.737832 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-182 - -1153491925.426974 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-183 - -1153491925.969700 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-184 - -1153491926.501102 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-185 - -1153491927.019176 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-186 - -1153491927.553318 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-187 - -1153491928.090342 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-188 - -1153491928.626285 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-189 - -1153491929.144400 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-190 - -1153491929.663558 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-191 - -1153491930.380544 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-192 - -1153491930.955009 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-193 - -1153491931.508232 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-194 - -1153491932.064038 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-195 - -1153491932.617246 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-196 - -1153491933.217552 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-197 - -1153491933.898173 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-198 - -1153491934.493195 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-199 - -1153491935.212569 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-200 - -1153491935.750950 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-201 - -1153491936.289847 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-202 - -1153491936.820614 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-203 - -1153491937.326834 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-204 - -1153491937.875669 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-205 - -1153491938.393501 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-206 - -1153491938.983495 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-207 - -1153491939.720697 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-208 - -1153491940.242679 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-209 - -1153491940.778209 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-210 - -1153491941.311600 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-211 - -1153491941.851940 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-212 - -1153491942.402906 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-213 - -1153491942.948265 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-214 - -1153491943.639225 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-215 - -1153491944.200324 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-216 - -1153491944.731019 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-217 - -1153491945.309829 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-218 - -1153491945.801031 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-219 - -1153491946.326315 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-220 - -1153491946.881363 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-221 - -1153491947.379569 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-222 - -1153491947.917182 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-223 - -1153491948.522538 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-224 - -1153491949.242450 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-225 - -1153491949.786176 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-226 - -1153491950.318859 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-227 - -1153491950.839949 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-228 - -1153491951.355365 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-229 - -1153491951.927690 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-230 - -1153491952.439603 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-231 - -1153491952.967534 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-232 - -1153491953.481427 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-233 - -1153491954.018322 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-234 - -1153491954.733393 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-235 - -1153491955.355330 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-236 - -1153491955.910091 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-237 - -1153491956.642232 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-238 - -1153491957.266232 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-239 - -1153491958.032310 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-240 - -1153491958.726775 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-241 - -1153491959.440580 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-242 - -1153491960.040221 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-243 - -1153491960.610615 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-244 - -1153491961.149960 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-245 - -1153491961.618613 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-246 - -1153491962.181217 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-247 - -1153491962.688996 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-248 - -1153491963.226713 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-249 - -1153491963.781229 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-250 - -1153491964.324462 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-251 - -1153491964.870228 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-252 - -1153491965.346071 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 FIRMWARE_REPLACEMENT - -1153491965.897323 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-254 - -1153491966.425892 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 unknown-255 - -1153491967.462159 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS - -1153491968.001263 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS - -1153491968.505228 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491968.505228 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS -1153491969.106358 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491969.106358 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS -1153491969.807100 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491969.807100 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS -1153491970.362598 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491970.362598 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS -1153491970.940211 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491970.940211 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS -1153491971.734926 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491971.734926 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS -1153491972.448954 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS - -1153491973.009668 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS - -1153491973.499918 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491973.499918 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS -1153491974.078420 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - -1153491974.078420 5OKnoww6xl4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS -1342774499.602711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.618257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.633881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.649736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.665129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.680776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.696389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.712024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.727627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.743256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.758901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.774498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774499.790129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.805748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.821395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.837006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774499.852712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.868263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.883868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.899494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.915123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774499.930770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.946383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.962002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.977626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774499.993255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774501.008954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774501.024564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774501.040163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774501.055750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774501.071372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774501.087014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774501.102663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774501.118262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774501.133894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774501.149722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774501.165118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.180781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.196410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774502.212010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.227656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.243258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.258920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774502.274503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.290144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.305756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.321389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774502.337026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.352656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.368263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774503.383881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.399508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.415144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.430765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774503.446381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.462238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.477626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.493255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774503.508879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.524559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.540148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774504.555766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.571382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.586999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.602612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774504.618243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.633886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.649716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.665119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774504.680748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.696399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.712010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774505.727639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.743262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.758899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.774514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774505.790120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.805743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.821372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.837008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774505.852627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774506.868280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774506.883875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774506.899506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774506.915128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774506.930773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774506.946397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774506.962010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774506.977632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774506.993300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774507.008875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774507.024525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.040170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.055773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774508.071382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.087037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.102608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.118291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774508.133895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.149730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.165121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.180755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774508.196376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.212038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.227653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774509.243257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.258902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.274499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.290143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774509.305756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.321374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.337023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.352630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774509.368306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.383907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.399511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774510.415150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.430768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.446406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.462243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774510.477627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.493250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.508876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.524502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774510.540154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.555806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.571396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774511.587001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.602645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.618247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.633887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774511.649712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.665115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.680746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.696380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774511.711992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.727667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.743256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774512.758901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.774514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.790125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.805742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774512.821365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.837018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.852618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.868249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774512.883911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774513.899562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774513.915132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774513.930762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774513.946377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774513.962004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774513.977619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774513.993247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774514.008872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774514.024516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774514.040161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774514.055747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.071409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.087017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774515.102648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.118272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.133903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.149763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774515.165133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.180747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.196399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.212004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774515.227684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.243285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.258910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774516.274502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.290132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.305750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.321388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774516.337016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.352622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.368241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.383871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774516.399516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.415180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.430768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774517.446391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.462228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.477629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.493254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774517.508882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.524519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.540147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.555744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774517.571370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.587023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.602630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774518.618268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.633897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.649729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.665122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774518.680763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.696389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.711990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.727622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774518.743260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.758928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.774516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774519.790226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.805758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.821381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.837016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774519.852619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.868268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.883880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.899496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774519.915120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774520.931544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774520.946460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774520.962006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774520.977628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774520.993375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774521.008944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774521.024533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774521.040157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774521.055745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774521.071388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774521.086996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.102679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.118279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774522.133899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.149738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.165124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.180766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774522.196386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.212002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.227625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.243278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774522.258899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.274527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.290133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774523.305750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.321397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.337022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.352630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774523.368244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.383874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.399508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.415136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774523.430759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.446433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.462235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774524.477634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.493255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.508891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.524511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774524.540153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.555752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.571373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.586996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774524.602631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.618282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.633900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774525.649723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.665124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.680761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.696386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774525.712003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.727623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.743252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.758890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774525.774492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.790148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.805742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774526.821371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.837013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.852632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.868239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774526.883869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.899487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.915109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.930739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774526.946485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774527.962037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774527.977629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774527.993243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774528.008875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774528.024528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774528.040150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774528.063396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774528.071379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774528.087066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774528.102611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774528.118249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.133917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.149739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774529.165316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.180760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.196375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.212016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774529.227622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.243288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.258889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.274490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774529.290130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.305803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.321387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774530.337012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.352631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.368310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.383867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774530.399498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.415142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.430747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.446485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774530.462247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.477719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.493267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774531.508894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.524521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.540166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.563507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774531.571381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.586999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.602614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.618233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774531.633877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.649757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.665132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774532.680762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.696388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.711997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.727627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774532.743271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.758902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.774495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.790124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774532.805791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.821418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.837013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774533.852623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.868244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.883877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.899495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774533.915125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.930775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.946493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.961991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774533.977611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774534.993361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774535.008887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774535.024548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774535.040155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774535.063715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774535.071385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774535.087011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774535.102611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774535.118256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774535.133866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774535.149625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.165166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.180759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774536.196393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.212012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.227623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.243270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774536.258902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.274485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.290123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.305748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774536.321389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.337048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.352627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774537.368242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.383957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.399492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.415140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774537.430737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.446470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.462212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.477609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774537.493253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.508890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.524510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774538.540139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.563465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.571378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.587004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774538.602620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.618241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.633873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.649585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774538.665335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.680798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.696420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774539.712001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.727617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.743265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.758904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774539.774496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.790379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.805806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.821378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.837005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774539.852753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774539.868248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774539.883866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774539.899499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774539.915119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774540.930922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774540.946501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774540.962000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774540.977715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774540.993341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774541.008955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774541.024602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774541.040214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774541.063483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774541.071377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774541.087001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.102649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.118279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774542.133876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.149819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.165121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.180752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774542.196395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.211983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.227616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.243231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774542.258907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.274530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.290128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774543.305748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.321369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.337000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.352703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774543.368239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.383862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.399493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.415145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774543.430752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.446505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.462262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774544.477618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.493250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.508865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.524504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774544.540129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.555757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.571357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.586984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774544.602612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.618287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.633871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774545.649796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.665118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.680748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.696382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774545.711992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.727616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.743240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.758896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774545.774506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.790149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.805739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774546.821375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.837056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.852722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.868239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774546.883943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.899494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.915130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.930731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774546.946377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774547.962023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774547.977616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774547.993231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774548.008873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774548.024513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774548.040138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774548.055750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774548.071371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774548.087056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774548.102614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774548.118251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.133886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.149759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774549.165106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.180736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.196367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.211981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774549.227628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.243229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.258897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.274489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774549.290217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.305789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.321396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774550.337014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.352703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.368241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.383855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774550.399492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.415123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.430735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.446363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774550.462240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.477684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.493250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774551.508885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.524507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.540139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.555763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774551.571382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.586980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.602610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.618251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774551.633857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.649831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.665123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774552.680741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.696379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.712001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.727605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774552.743245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.758898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.774491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.790124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774552.805738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.821388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.836986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774553.852718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.868237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.883869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.899487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774553.915117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.930736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.946445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.962000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774553.977608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774554.993301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774555.008892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774555.024521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774555.040149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774555.055761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774555.071379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774555.087002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774555.102621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774555.118247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774555.133868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774555.149707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.165143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.180764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774556.196483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.212011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.227620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.243328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774556.258906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.274539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.290122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.305756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774556.321372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.337027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.352719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774557.368236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.383869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.399492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.415143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774557.430750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.446448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.462249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.477604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774557.493242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.508914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.524501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774558.540143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.555753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.571372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.586992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774558.602611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.618251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.633855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.649702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774558.665118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.680779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.696448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774559.712000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.727617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.743336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.758901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774559.774495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.790113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.805737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.821364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774559.846415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774560.852890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774560.868263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774560.883875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774560.899515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774560.915121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774560.930749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774560.946428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774560.962014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774560.977620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774560.993242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774561.008871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.024568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.040155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774562.055768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.071374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.087015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.102621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774562.118261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.133870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.149752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.165133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774562.180735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.196442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.212000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774563.227626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.243245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.258900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.274496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774563.290112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.305731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.321366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.336980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774563.352631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.368670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.384020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774564.399651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.415134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.430747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.446483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774564.462286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.477608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.493255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.508878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774564.524511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.540203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.555764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774565.571376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.586987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.602621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.618241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774565.633885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.649712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.665142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.680743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774565.696568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.712032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.727627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774566.743235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.758913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.774483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.790109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774566.805743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.821363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.836985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.852604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774566.868295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774567.883915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774567.899498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774567.915118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774567.930741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774567.946408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774567.962027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774567.977609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774567.993246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774568.008876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774568.024521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774568.040149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.055789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.071364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774569.087013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.102613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.118260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.133859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774569.149714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.165118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.180737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.196396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774569.211998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.227796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.243243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774570.258893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.274489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.290117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.305742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774570.321398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.336975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.352600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.368240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774570.383861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.399509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.415137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774571.430720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.446386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.462222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.477603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774571.493228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.508857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.524488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.540121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774571.555728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.571405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.586990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774572.602614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.618231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.633864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.649704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774572.665130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.680733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.696398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.711996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774572.727607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.743272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.758880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774573.774489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.790143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.805744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.821379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774573.836997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.852744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.868251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.883872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774573.899492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774574.915293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774574.930820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774574.946459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774574.962056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774574.977629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774574.993236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774575.008861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774575.024508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774575.040166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774575.055736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774575.071435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.087101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.102612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774576.118275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.133855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.149488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.165135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774576.180745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.196376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.211977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.227625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774576.243229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.258938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.274479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774577.290113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.305748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.321366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.337000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774577.352610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.368255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.383871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.399480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774577.415141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.430805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.446383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774578.462282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.477623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.493258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.508871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774578.524508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.540140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.555736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.571374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774578.587000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.602648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.618237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774579.633874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.649621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.665124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.680744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774579.696367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.711985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.727608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.743235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774579.758889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.774511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.790121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774580.805735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.821391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.836983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.852616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774580.868253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.883862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.899480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.915108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774580.930724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774581.946458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774581.962015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774581.978016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774581.993401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774582.008955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774582.024673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774582.040443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774582.056097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774582.071585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774582.087006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774582.102854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.118469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.133885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774583.149628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.165131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.180747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.196373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774583.211985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.227632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.243245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.258892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774583.274503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.290149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.305751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774584.321370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.336989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.352608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.368266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774584.383879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.399492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.415140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.431177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774584.446364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.462461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.477638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774585.493257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.509037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.524528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.540139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774585.555782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.573771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.587018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.602671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774585.618367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.633991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.649694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774586.665197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.680809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.696461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.712122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774586.727685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.743335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.758923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.774560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774586.790103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.805840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.821374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774587.837055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.852607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.868256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.883864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774587.899479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.915109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.930728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.946351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774587.961988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774588.977633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774588.993239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774589.008858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774589.024510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774589.040143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774589.055738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774589.071370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774589.086978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774589.102600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774589.118235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774589.133844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.149634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.165125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774590.180730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.196349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.211982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.227597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774590.243240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.258884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.274526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.290095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774590.305744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.321450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.336991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774591.352620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.368250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.383872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.399487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774591.415135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.430741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.446359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.462250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774591.477639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.493286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.508873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774592.524505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.540138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.555856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.571376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774592.586982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.602603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.618255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.633858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774592.649478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.665130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.680730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774593.696363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.711984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.727610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.743237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774593.758871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.774490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.790111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.805725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774593.821355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.837060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.852635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774594.868257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.883864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.899477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.915152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774594.930742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.946353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.961994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.977635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774594.993232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.008887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.024505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774596.040129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.055813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.071383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.087032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774596.102604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.118252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.133872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.149595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774596.165106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.180768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.196363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774597.211976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.227607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.243229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.258887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774597.274490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.290105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.305727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.321364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774597.336987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.352745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.368259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774598.383857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.399491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.415125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.430735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774598.446359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.462213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.477622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.493222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774598.508858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.524586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.540151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774599.555850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.571419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.587016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.602642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774599.618218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.633868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.649619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.665095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774599.680742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.696439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.711994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774600.727625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.743243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.758879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.774506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774600.790101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.805722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.821349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.836968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774600.852617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774601.868389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774601.883882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774601.899582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774601.915106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774601.930718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774601.946349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774601.962044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774601.977656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774601.993276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774602.008939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774602.024497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.040167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.055744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774603.071370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.086997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.102595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.118250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774603.133856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.149611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.165102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.180734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774603.196341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.212004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.227605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774604.243231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.258890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.274487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.290156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774604.305722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.321353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.336993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.352600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774604.368217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.383893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.399472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774605.415119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.430728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.446350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.462193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774605.477625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.493244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.508848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.524487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774605.540116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.555781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.571384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774606.586991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.602599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.618243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.633851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774606.649603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.665098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.680735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.696345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774606.711980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.727626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.743227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774607.758879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.774489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.790105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.805724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774607.821360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.836974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.852608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.868224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774607.883859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774608.899550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774608.915115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774608.930726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774608.946361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774608.961976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774608.977623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774608.993235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774609.008853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774609.024513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774609.040121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774609.062315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.071409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.087001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774610.102596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.118226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.133862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.149605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774610.165098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.180736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.196359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.211979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774610.227590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.243290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.258883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774611.274492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.290102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.305725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.321347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774611.336964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.352588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.368232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.383856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774611.399470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.415160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.435961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774612.446356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.462234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.477615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.493514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774612.508854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.524494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.540134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.563205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774612.571349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.587000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.602600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774613.618233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.633853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.649581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.665108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774613.680736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.696526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.711972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.727611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774613.743233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.758931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.774591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774614.790104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.805733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.821360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.836980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774614.852602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.868227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.883880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.899480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774614.915121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774615.930772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774615.946412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774615.961988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774615.977632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774615.993244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774616.008875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774616.024504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774616.040146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774616.063329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774616.071355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774616.087061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.102654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.118250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774617.133860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.149604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.165108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.180755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774617.196356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.211993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.227599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.243241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774617.258881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.274518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.290105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774618.305723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.321349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.336968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.352605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774618.368232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.383862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.399466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.415122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774618.430710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.446369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.462192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774619.477613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.493231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.508844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.524496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774619.540121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.563325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.571354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.586981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774619.602612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.618264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.633851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774620.649601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.665098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.680757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.696341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774620.711978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.727586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.743224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.758879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774620.774486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.790215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.805750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774621.821353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.836976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.852588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.868213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774621.883882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.899472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.915104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.930721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774621.946419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774622.962020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774622.977615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774622.993226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774623.008858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774623.024499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774623.040130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774623.063125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774623.071341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774623.086991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774623.102596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774623.118224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.133883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.149597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774624.165102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.180734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.196353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.211979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774624.227603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.243228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.258880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.274473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774624.290124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.305757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.321351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774625.336969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.352607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.368215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.383875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774625.399461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.415101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.430706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.446348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774625.462192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.477643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.493225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774626.508855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.524474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.540135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.563834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774626.571355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.586992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.602590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.618212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774626.633835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.649636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.665101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774627.680742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.696358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.711977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.727610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774627.743217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.758886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.774477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.790109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774627.805726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.821393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.836973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774628.852597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.868212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.883857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.899474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774628.915098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.930734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.946340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.961968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774628.977590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774629.993299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774630.008869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774630.024507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774630.040145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774630.055721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774630.071342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774630.087010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774630.102597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774630.118229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774630.133854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774630.149618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.165137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.180749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774631.196356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.211979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.227592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.243248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774631.258882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.274474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.290121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.305717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774631.321353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.337006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.352609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774632.368231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.383875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.399480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.415130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774632.430741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.446350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.462301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.477604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774632.493239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.508928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.524484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774633.540136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.555727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.571345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.586988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774633.602596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.618221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.633841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.649600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774633.665088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.680769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.696437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774634.712049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.727598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.743220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.758872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774634.774462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.790113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.805716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.821338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774634.836964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774635.852621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774635.868217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774635.883864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774635.899471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774635.915143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774635.930706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774635.946335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774635.962030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774635.977579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774635.993234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774636.008852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.024580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.040136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774637.055726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.071343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.086984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.102601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774637.118231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.133840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.149578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.165090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774637.180713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.196461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.211974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774638.227586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.243225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.258862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.274464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774638.290105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.305705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.321337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.336969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774638.352583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.368318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.383855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774639.399465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.415101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.430735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.446341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774639.462252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.477581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.493236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.508834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774639.524478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.540167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.555731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774640.571379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.586993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.602597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.618216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774640.633844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.649589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.665093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.680716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774640.696360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.712027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.727610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774641.743234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.764220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.774450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.790106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774641.805809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.821369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.836975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.852605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774641.868217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774642.883890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774642.899476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774642.915104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774642.930723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774642.946340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774642.961975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774642.977586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774642.993228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774643.008842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774643.024484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774643.040114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.055736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.071360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774644.087050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.102611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.118237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.133846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774644.149578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.165095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.180713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.196362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774644.211975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.227635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.243226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774645.258875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.274472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.290114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.305726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774645.321349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.336961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.352586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.368212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774645.383848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.399494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.415113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774646.430719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.446337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.462191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.477591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774646.493235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.508845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.524480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.540116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774646.555714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.571462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.587099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774647.602603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.618262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.634003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.649615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774647.665144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.680715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.696820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.711979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774647.727589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.743246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.758872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774648.774469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.790107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.805706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.821342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774648.836972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.852581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.868212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.883853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774648.899476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774649.915117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774649.930724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774649.946338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774649.961961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774649.977580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774649.993224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774650.008836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774650.024482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774650.040110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774650.055715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774650.071333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.087025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.102602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774651.118230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.133847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.149589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.165087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774651.180719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.196349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.211959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.227588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774651.243206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.258894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.274470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774652.290116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.305720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.321342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.336970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774652.352603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.368212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.383849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.399473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774652.415105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.431165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.446338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774653.462189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.477585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.493240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.508852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774653.524480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.540109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.555715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.571349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774653.586965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.602623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.618228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774654.633848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.649601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.665102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.680725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774654.696575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.711986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.727594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.743228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774654.758866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.774494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.790109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774655.805722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.821346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.836975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.852594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774655.868229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.883955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.899475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.915088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774655.930705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774656.946357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774656.961976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774656.977585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774656.993237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774657.008839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774657.024490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774657.040112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774657.055723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774657.071329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774657.086965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774657.102593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.118245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.133869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774658.149582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.165083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.180711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.196359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774658.211973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.227592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.243219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.258855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774658.274453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.290123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.305769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774659.321340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.336968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.352595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.368374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774659.383846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.399481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.415106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.430711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774659.446335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.462262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.477599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774660.493230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.508847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.524464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.540112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774660.555714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.571343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.586954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.602590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774660.618205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.633885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.649607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774661.665086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.680713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.696380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.711970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774661.727632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.743211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.758870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.774470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774661.790079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.805776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.821342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774662.836975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.852588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.868224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.883865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774662.899474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.915081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.930709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.946325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774662.961983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774663.977628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774663.993225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774664.008842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774664.024494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774664.040123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774664.055738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774664.071345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774664.087048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774664.102604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774664.118219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774664.133833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.149611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.165137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774665.180715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.196355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.211965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.227595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774665.243208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.258869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.274457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.290089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774665.305739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.321398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.336968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774666.352592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.368210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.383856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.399475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774666.415093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.431155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.446339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.462213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774666.477589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.493257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.508851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774667.524473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.540129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.555726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.571345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774667.586961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.602602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.618204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.633832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774667.649584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.665115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.680721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774668.696358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.711973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.727594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.743218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774668.758874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.774461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.790086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.805752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774668.821343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.837012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.852591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774669.868221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.883842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.899491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.915063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774669.930689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.946328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.961981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.977586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774669.993208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.008885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.024504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774671.040132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.055743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.071342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.086967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774671.102621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.118223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.133841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.149579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774671.165086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.180898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.196356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774672.211966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.227584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.243218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.258864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774672.274453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.290084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.305728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.321347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774672.336961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.352635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.368207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774673.383853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.399476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.415102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.431143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774673.446345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.462179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.477582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.493212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774673.508883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.524841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.540127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774674.555788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.571394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.587040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.602620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774674.618267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.633844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.649625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.665092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774674.680723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.696485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.712098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774675.727670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.743812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.758898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.774534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774675.790288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.805928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.821355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.837146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774675.852679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774676.868267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774676.883835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774676.899514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774676.915463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774676.930727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774676.946819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774676.962070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774676.977665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774676.993459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774677.008933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774677.024492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.040175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.055748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774678.071336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.086970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.102604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.118207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774678.133827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.149582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.165074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.180709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774678.196328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.212034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.227585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774679.243211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.258854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.274460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.290093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774679.305741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.321330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.337001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.352588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774679.368214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.384131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.399514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774680.415107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.431436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.446379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.462215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774680.477623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.493680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.508853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.524472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774680.540121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.555821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.571355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774681.586963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.602608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.618225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.633929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774681.649623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.665091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.680720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.696470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774681.711989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.727604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.743212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774682.758831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.774479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.790085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.805854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774682.821336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.836961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.852574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.868207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774682.883865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774683.899504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774683.915095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774683.930712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774683.946346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774683.961959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774683.977623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774683.993203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774684.008851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774684.024491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774684.040121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774684.055726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.071384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.086962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774685.102610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.118214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.133840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.149604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774685.165085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.180800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.196338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.212041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774685.227581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.243245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.258863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774686.274486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.290086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.305736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.321349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774686.336952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.352578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.368202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.383852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774686.399446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.415200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.430723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774687.446333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.462286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.477582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.493213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774687.508842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.524467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.540095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.555719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774687.571486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.586970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.602599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774688.618209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.633842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.649595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.665075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774688.680698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.696324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.711959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.727585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774688.743203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.758885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.774465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774689.790091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.805724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.821333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.836960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774689.852579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.868212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.883819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.899448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774689.915092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774690.930851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774690.946347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774690.961968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774690.977614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774690.993564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774691.008859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774691.024476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774691.040103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774691.055730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774691.071332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774691.086956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.102620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.118233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774692.133847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.149615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.165073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.180698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774692.196321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.211991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.227572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.243197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774692.258853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.274500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.290129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774693.305790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.321393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.337008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.352586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774693.368227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.383836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.399464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.415112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774693.431272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.446370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.462200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774694.477580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.493221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.508849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.524586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774694.542809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.555722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.571321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.586955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774694.602576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.618242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.633909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774695.649594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.665098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.680706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.696322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774695.711982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.727574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.743221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.758854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774695.774473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.790106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.805827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774696.821426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.836953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.852570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.868211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774696.883818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.899451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.915095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.930784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774696.946336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774697.962069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774697.977674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774697.993217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774698.008849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774698.024490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774698.040104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774698.063118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774698.071330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774698.086957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774698.102569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774698.118214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.133879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.149570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774699.165073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.180712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.196354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.211976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774699.227575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.243212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.258844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.274458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774699.290073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.305796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.321337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774700.336955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.352569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.368193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.383820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774700.399440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.415101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.430702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.446333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774700.462172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.477625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.493211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774701.508853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.524468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.540135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.563214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774701.571330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.586946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.602573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.618219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774701.633843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.649695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.665096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774702.680716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.696340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.711966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.727583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774702.743209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.758865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.774461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.790075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774702.805714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.821378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.836968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774703.852583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.868220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.883829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.899479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774703.915098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.930686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.946327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.961955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774703.977572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774704.993246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774705.008848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774705.024491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774705.040112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774705.063164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774705.071327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774705.086953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774705.102577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774705.118219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774705.133824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774705.149442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.165127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.180712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774706.196351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.211968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.227600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.243211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774706.258858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.274472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.290089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.305715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774706.321343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.336966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.352577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774707.368220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.383824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.399457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.415097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774707.430704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.446321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.462158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.477563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774707.493195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.508872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.524469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774708.540094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.563119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.571328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.586953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774708.602577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.618224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.633835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.649445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774708.665190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.680727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.696456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774709.711973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.727588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.743206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.758858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774709.774449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.790084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.805782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.821363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774709.836950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774710.852624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774710.868194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774710.883816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774710.899437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774710.915092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774710.930775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774710.946609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774710.962037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774710.977647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774710.993215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774711.008891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.024527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.040113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774712.063294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.071330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.087031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.102571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774712.118219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.133833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.149454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.165200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774712.180695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.196372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.211971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774713.227581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.243207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.258845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.274454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774713.290069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.305795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.321341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.336963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774713.352580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.368308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.383827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774714.399456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.415108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.430709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.446334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774714.462219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.477657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.493249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.508841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774714.524523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.540146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.555794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774715.571338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.586949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.602580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.618228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774715.633829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.649583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.665079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.680711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774715.696331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.712028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.727570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774716.743186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.758843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.774448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.790068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774716.805772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.821339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.836924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.852553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774716.868193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774717.883865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774717.899458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774717.915079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774717.930700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774717.946405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774717.962038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774717.977665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774717.993290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774718.008901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774718.024476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774718.040095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.055813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.071347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774719.086967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.102585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.118247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.133834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774719.149592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.165074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.180724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.196334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774719.211965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.227629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.243192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774720.258835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.274442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.290062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.305779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774720.321320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.336940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.352556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.368202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774720.383808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.399469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.415101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774721.431194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.446364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.462161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.477608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774721.493196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.508824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.524468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.540090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774721.555757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.571374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.586951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774722.602567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.618218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.633824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.649677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774722.665079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.680827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.696428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.711941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774722.727689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.743233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.758857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774723.774448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.790085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.805743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.821339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774723.836939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.852570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.868297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.883833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774723.899437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774724.915130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774724.930707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774724.946321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774724.961947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774724.977656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774724.993250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774725.008846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774725.024527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774725.040200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774725.055748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774725.071327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.086981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.102581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774726.118219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.133832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.149570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.165066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774726.180702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.196315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.211934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.227604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774726.243194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.258890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.274456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774727.290069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.305730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.321337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.336959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774727.352565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.368203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.383814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.399437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774727.415092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.430720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.446338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774728.462156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.477596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.493202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.508833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774728.524473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.540111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.555742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.571329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774728.586942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.602599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.618229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774729.633823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.649678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.665069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.680708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774729.696319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.711970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.727586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.743205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774729.758841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.774476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.790074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774730.805743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.821343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.836945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.852577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774730.868192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.883835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.899473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.915078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774730.930701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774731.946356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774731.961965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774731.977566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774731.993188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774732.008829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774732.024493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774732.040103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774732.055725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774732.071333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774732.087037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774732.102568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.118277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.133813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774733.149561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.165073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.180691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.196317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774733.211941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.227573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.243194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.258827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774733.274429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.290112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.305757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774734.321336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.337002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.352566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.368197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774734.383826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.399451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.415091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.430703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774734.446317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.462254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.477596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774735.493200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.508827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.524469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.540103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774735.555713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.571357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.586950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.602585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774735.618197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.633913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.649578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774736.665064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.680696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.696312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.711937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774736.727589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.743188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.758847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.774438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774736.790135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.805733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.821338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774737.836939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.852585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.868190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.883830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774737.899441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.915084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.930701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.946312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774737.961945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774738.977600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774738.993201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774739.008824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774739.024484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774739.040102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774739.055708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774739.071319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774739.086953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774739.102557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774739.118200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774739.133821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.149611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.165070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774740.180702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.196314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.211939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.227582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774740.243214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.258959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.274460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.290157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774740.305733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.321393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.336940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774741.352572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.368188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.383805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.399432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774741.415087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.430700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.446316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.462191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774741.477556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.493260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.508827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774742.524463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.540095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.555690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.571324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774742.586937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.602554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.618180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.633841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774742.649576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.665081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.680689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774743.696315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.711948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.727586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.743190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774743.758834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.774445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.790071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.805678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774743.821314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.836982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.852567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774744.868197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.883824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.899452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.915068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774744.930717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.946324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.961940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.977561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774744.993183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.008868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.024478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774746.040093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.055699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.071311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.086936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774746.102560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.118207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.133836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.149568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774746.165054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.180715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.196318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774747.211944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.227573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.243194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.258834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774747.274445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.290046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.305703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.321315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774747.336949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.352600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.368186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774748.383822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.399445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.415089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.430712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774748.446316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.462157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.477571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.493182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774748.508813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.524510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.540085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774749.555706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.571316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.586941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.602569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774749.618196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.633821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.649558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.665054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774749.680679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.696329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.711947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774750.727585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.743332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.758936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.774451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774750.790057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.805676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.821306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.836942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774750.852554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774751.868224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774751.883820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774751.899442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774751.915076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774751.930715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774751.946335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774751.961946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774751.977578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774751.993188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774752.008819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774752.024456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.040131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.055693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774753.071313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.086959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.102582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.118220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774753.133828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.149552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.165051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.180683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774753.196312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.212051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.227594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774754.243200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.258860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.274439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.290107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774754.305706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.321327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.336960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.352559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774754.368193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.383898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.399490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774755.415131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.430835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.446331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.462161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774755.477556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.493182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.508857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.524485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774755.540141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.555709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.571315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774756.586937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.602559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.618185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.633826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774756.649575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.665050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.680680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.696306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774756.711933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.727597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.743181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774757.758839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.774433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.790061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.805684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774757.821317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.836943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.852549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.868175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774757.883799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774758.899484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774758.915060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774758.930732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774758.946310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774758.961987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774758.977545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774758.993185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774759.008806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774759.024449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774759.040083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774759.055680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.071336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.087002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774760.102560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.118205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.133816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.149544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774760.165053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.180687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.196305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.211925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774760.227559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.243210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.258837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774761.274431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.290053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.305676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.321311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774761.337037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.352566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.368171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.383803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774761.399433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.415127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.430698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774762.446318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.462165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.477567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.493181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774762.508811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.524433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.540083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.555696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774762.571415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.586994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.602576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774763.618203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.633846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.649585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.665071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774763.680701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.696506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.711954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.727570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774763.743219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.758858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.774453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774764.790068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.805696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.821304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.836945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774764.852567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.868180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.883812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.899424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774764.915066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774765.930729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774765.946319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774765.962191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774765.977549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774765.993169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774766.008808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774766.024723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774766.040126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774766.055677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774766.072023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774766.086982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.102795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.118305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774767.133820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.149663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.165066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.180686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774767.196343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.211935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.227660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.243203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774767.258837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.274478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.290065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774768.305690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.321320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.336953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.352565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774768.368171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.383815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.399432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.415081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774768.430678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.446348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.462168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774769.477565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.493182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.508817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.524441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774769.540106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.555693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.571311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.586931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774769.602555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.618269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.633832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774770.649602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.665056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.680693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.696303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774770.711931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.727568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.743193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.758830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774770.774452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.790131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.805986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774771.821329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.836960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.852563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.868200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774771.883820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.899437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.915057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.930685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774771.946405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774772.961971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774772.977578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774772.993178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774773.008817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774773.024456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774773.040106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774773.055679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774773.071298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774773.086936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774773.102556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774773.118223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.133892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.149586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774774.165064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.180694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.196320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.211949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774774.227564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.243206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.258833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.274446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774774.290062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.305761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.321324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774775.336948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.352575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.368182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.383815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774775.399431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.415082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.430673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.446399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774775.462164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.477613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.493196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774776.508816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.524442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.540094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.555691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774776.571346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.586924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.602553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.618181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774776.633806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.649655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.665070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774777.680693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.696309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.711943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.727554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774777.743204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.758836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.774433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.790063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774777.805672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.821348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.836952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774778.852568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.868176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.883802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.899448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774778.915050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.930678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.946396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.961930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774778.977547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774779.993242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774780.008819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774780.024473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774780.040102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774780.055695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774780.071304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774780.086994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774780.102560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774780.118197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774780.133796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774780.149634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.165098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.180682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774781.196304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.211936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.227559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.243202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774781.258819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.274429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.290050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.305671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774781.321304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.336960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.352555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774782.368162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.383800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.399418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.415071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774782.430671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.446385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.462132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.477535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774782.493193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.508830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.524431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774783.540091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.555674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.571307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.586920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774783.602540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.618172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.633803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.649595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774783.665107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.680694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.696305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774784.711919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.727540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.743192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.758816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774784.774412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.790035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.805663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.821301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774784.836933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774785.852652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774785.868174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774785.883802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774785.899426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774785.915051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774785.930671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774785.946397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774785.961925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774785.977539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774785.993171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774786.008792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.024481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.040084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774787.055679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.071303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.086930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.102542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774787.118193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.133794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.149625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.165038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774787.180666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.196416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.211931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774788.227556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.243187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.258811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.274410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774788.290040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.305662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.321300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.336920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774788.352637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.368222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.383803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774789.399415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.415080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.430668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.446393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774789.462125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.477536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.493165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.508789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774789.524415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.540223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.555704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774790.571307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.586921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.602547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.618179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774790.633808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.649657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.665054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.680676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774790.696296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.711987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.727565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774791.743205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.758842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.774414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.790078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774791.806015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.821357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.836961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.852645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774791.868181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774792.883832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774792.899440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774792.915056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774792.930687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774792.946411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774792.961953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774792.977543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774792.993170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774793.008805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774793.024441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774793.040073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.055715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.071318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774794.086935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.102574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.118184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.133798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774794.149645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.165048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.180668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.196290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774794.211920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.227612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.243213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774795.258835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.274457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.290062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.305791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774795.321311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.337044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.352766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.368191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774795.383810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.399518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.415073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774796.430690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.446407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.462146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.477553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774796.493193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.508798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.524438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.540076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774796.563349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.571336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.586929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774797.602557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.618190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.633805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.649639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774797.665046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.680672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.696390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.711931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774797.727557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.743218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.758823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774798.774430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.790053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.805674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.821314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774798.836928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.852634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.868169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.883809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774798.899412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774799.915082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774799.931155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774799.946374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774799.961940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774799.977550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774799.993184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774800.008830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774800.024470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774800.040085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774800.055697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774800.071290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.087050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.102619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774801.118311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.133807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.149851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.165260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774801.180843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.196498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.211919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.227764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774801.243172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.258992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.274491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774802.290104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.305932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.321526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.337181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774802.352854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.368251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.383926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.399481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774802.415076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.431629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.446461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774803.462210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.477663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.493762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.508994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774803.524607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.540258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.555976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.571300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774803.587045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.602613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.618187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774804.633803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.649661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.665043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.680681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774804.696303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.711936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.727562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.743172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774804.758829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.774466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.790065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774805.805679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.821300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.836932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.852643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774805.868171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.883853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.899415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.915046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774805.930663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774806.946416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774806.961937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774806.977553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774806.993187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774807.008815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774807.024451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774807.040074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774807.055703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774807.071304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774807.086928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774807.102555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.118215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.133799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774808.149632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.165061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.180676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.196307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774808.211939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.227565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.243187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.258849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774808.274429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.290077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.305676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774809.321306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.336927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.352666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.368170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774809.383811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.399434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.415059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.430667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774809.446294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.462197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.477680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774810.493181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.508942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.524425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.540193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774810.555686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.571306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.586905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.605165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.618273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774810.633881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774810.649587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774810.665107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774810.680695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774810.696318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774811.711936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774811.727563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774811.743165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774811.758840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774811.774415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774811.790048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774811.805679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774811.821289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774811.836909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774811.852558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774811.868198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774812.883895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774812.899441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774812.915046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774812.930677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774812.946298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774812.961945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774812.977544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774812.993168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774813.008793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774813.024442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774813.040077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.055754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.071297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774814.086929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.102570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.118175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.133795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774814.149535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.165293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.180727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.196301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774814.211911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.227602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.243182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774815.258849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.274422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.290059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.305666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774815.321307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.336922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.352540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.368192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774815.383791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.399480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.415113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774816.430684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.446308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.462193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.477562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774816.493176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.508794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.524421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.540067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774816.555694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.571325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.586920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774817.602543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.618174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.633809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.649556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774817.665063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.680677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.696291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.711938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774817.727546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.743222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.758852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774818.774427 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.790053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.805683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.821333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774818.836941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.852538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.868193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.883793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774818.899423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774819.915098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774819.930832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774819.946301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774819.961962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774819.977556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774819.993180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774820.008806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774820.024456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774820.040078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774820.055678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774820.071318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.086965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.102543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774821.118167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.133795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.149537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.165075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774821.180670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.196286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.211914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.227546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774821.243187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.258853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.274417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774822.290054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.305667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.321291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.336917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774822.352539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.368188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.383799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.399414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774822.415072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.430729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.446321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774823.462222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.477568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.493205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.508828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774823.524444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.540079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.555671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.571320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774823.586918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.602568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.618181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774824.633810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.649546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.665091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.680685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774824.696304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.711913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.727555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.743176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774824.758819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.774435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.790061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774825.805675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.821307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.836928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.852546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774825.868198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.883789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.899448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.915074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774825.930670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774826.946341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774826.961947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774826.977541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774826.993168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774827.008800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774827.024440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774827.040077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774827.055672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774827.071318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774827.086935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774827.102552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.118202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.133801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774828.149522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.165071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.180663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.196302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774828.211933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.227542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.243156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.258828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774828.274427 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.290223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.305754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774829.321304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.336930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.352553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.368241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774829.383788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.399417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.415094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.430676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774829.446282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.462194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.477543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774830.493176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.508791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.524468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.540074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774830.555721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.571306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.586911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.602551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.618163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774830.633839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774830.649574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774830.665064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774830.680694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774830.696328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774831.711986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774831.727542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774831.743191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774831.758827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774831.774453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774831.790052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774831.805697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774831.821382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774831.836932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774831.852548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774831.868184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774832.883859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774832.899429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774832.915065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774832.930660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774832.946289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774832.961911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774832.977557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774832.993162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774833.008800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774833.024437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774833.040072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.055745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.071317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774834.086952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.102552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.118181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.133806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774834.149559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.165069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.180686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.196303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774834.211931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.227588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.243177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774835.258821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.274448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.290050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.305677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774835.321298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.336917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.352550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.368170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774835.383827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.399563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.415102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774836.430668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.446312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.462137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.477560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774836.493172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.508794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.524411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.540065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774836.555657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.571346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.586917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774837.602544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.618170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.633811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.649551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774837.665069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.680679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.696480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.711918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774837.727554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.743184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.758818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774838.774421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.790038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.805655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.821299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774838.836905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.852532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.868154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.883797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774838.899401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774839.915152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774839.930739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774839.946295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774839.961915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774839.977580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774839.993153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774840.008791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774840.024433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774840.040069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774840.055654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774840.071286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.087089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.102554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774841.118175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.133801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.149665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.165044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774841.180677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.196463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.211922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.227632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774841.243163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.258843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.274431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774842.290044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.305669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.321301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.336921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774842.352534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.368155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.383795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.399410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774842.415072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.430700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.446296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774843.462127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.477554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.493242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.508787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774843.524428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.540046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.555667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.571280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774843.586918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.602558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.618171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774844.633800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.649533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.665051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.680678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774844.696284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.711912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.727530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.743153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774844.758810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.774449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.790046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774845.805658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.821293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.836907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.852538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774845.868168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.883803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.899418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.915035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774845.930653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774846.946322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774846.961932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774846.977555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774846.993189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774847.008805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774847.024441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774847.040074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774847.055668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774847.071290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774847.086935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774847.102544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.118199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.133783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774848.149530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.165054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.180677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.196291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774848.211908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.227551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.243191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.258808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774848.274408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.290067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.305683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774849.321304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.336911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.352542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.368155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774849.383801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.399418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.415062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.430655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774849.446281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.462143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.477545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774850.493156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.508782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.524415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.540041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774850.555660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.571330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.586914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.602521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774850.618173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.633850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.649532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774851.665061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.680685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.696315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.711921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774851.727539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.743170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.758854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.774466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774851.790061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.811261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.821263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774852.836896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.852509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.868154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.883805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774852.899422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.915051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.930667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.946296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774852.961926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774853.977595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774853.993159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774854.008800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774854.024441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774854.040066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774854.055676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774854.071289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774854.086957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774854.102537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774854.118153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774854.133782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.149622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.165060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774855.180676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.196291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.211909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.227551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774855.243151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.258819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.274408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.290062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774855.305662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.321481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.336951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774856.352543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.368524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.383817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.399622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774856.415286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.431232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.446790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.462540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774856.477897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.493313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.508890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774857.524723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.540299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.555971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.571399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774857.587000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.602533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.618163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.633803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774857.649785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.665084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.680689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774858.696283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.711918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.727532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.743168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774858.758810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.774424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.790062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.805669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774858.821281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.836941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.852542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774859.868172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.883806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.899432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.915049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774859.930664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.946296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.961918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.977534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774859.993182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.008920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.024458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774861.040092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.055676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.071286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.086959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774861.102540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.118171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.133781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.149557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774861.165061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.180796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.196289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774862.211905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.227541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.243170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.258856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774862.274398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.290049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.305652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.321338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774862.336918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.352639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.368229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774863.383809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.399413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.415082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.430656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774863.446298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.462161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.477602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.493182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774863.508861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.524448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.540052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774864.555665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.571286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.586930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.602545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774864.618181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.633796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.649716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.665075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774864.680662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.696468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.711927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774865.727531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.743158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.758822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.774404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774865.790053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.805659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.821292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.836911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774865.852538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774866.868197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774866.883797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774866.899423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774866.915111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774866.930669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774866.946280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774866.961916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774866.977533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774866.993181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774867.008790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774867.024442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.040100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.055661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774868.071302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.086984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.102534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.118180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774868.133796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.149527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.165143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.180652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774868.196310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.212039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.227544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774869.243251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.258933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.274404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.290054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774869.305659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.321288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.336910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.352529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774869.368203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.383917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.399405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774870.415161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.430655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.446281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.462122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774870.477523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.493165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.508774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.524405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774870.540061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.555718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.571288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774871.586935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.602548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.618162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.633799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774871.649549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.665095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.680645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.696300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.711902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774871.727548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774871.743185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774871.758925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774871.774418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774871.790013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342774872.805776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774872.821282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774872.836996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774872.852537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774872.868164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774872.883817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774872.899431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774872.915420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774872.930654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774872.946282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774872.961906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774873.977695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774873.993193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774874.008802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774874.024435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774874.040073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774874.062739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774874.071288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774874.086916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774874.102548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774874.118150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774874.133775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.149584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.165085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774875.180664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.196343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.211941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.227532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774875.243169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.258801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.274410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.290041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774875.305664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.321311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.336964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774876.352578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.368174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.383789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.399422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774876.415112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.430665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.446284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.462123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774876.477520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.493200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.508782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774877.524425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.540051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.562722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.571291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774877.586912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.602561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.618156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.633780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774877.649414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.665097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.680669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774878.696294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.711910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.727541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.743180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774878.758811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.774405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.790027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.805658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774878.821271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.836915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.852527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774879.868150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.883789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.899425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.915091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774879.930667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.946282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.961910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.977532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774879.993144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.008925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.024428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774881.040059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.062738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.071275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.086908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774881.102546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.118191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.133776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.149416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774881.165201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.180713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.196298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774882.211915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.227548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.243174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.258803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774882.274433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.290036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.305689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.321290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774882.336897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.352672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.368412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774883.383812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.399444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.415096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.430657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774883.446290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.462201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.477531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.493174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774883.508839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.524452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.540063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774884.555667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.571295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.586916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.602541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774884.618170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.633778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.649561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.665067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774884.680662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.696335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.711910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774885.727524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.743162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.758805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.774404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774885.790035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.805782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.821282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.836912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774885.852524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774886.868172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774886.883775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774886.899439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774886.915042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774886.930746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774886.946364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774886.961988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774886.977617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774886.993157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774887.008796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774887.024433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.040108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.055668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774888.071285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.086985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.102544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.118169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774888.133780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.149535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.165054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.180641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774888.196272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.211946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.227539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774889.243198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.258812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.274398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.290029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774889.305671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.321284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.336915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.352547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774889.368162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.383850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.399433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774890.415065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.430645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.446270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.462132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774890.477530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.493141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.508785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.524410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774890.540039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.555716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.571297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774891.586916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.602549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.618169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.633780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774891.649551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.665030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.680642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.696275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774891.711912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.727583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.743154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774892.758799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.774404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.790027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.805839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774892.821276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.836932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.852526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.868161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774892.883791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774893.899477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774893.915040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774893.930650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774893.946282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774893.961902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774893.977525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774893.993154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774894.008789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774894.024424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774894.040043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774894.055651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.071326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.086916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774895.102537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.118169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.133776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.149522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774895.165021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.180639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.196264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.211896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774895.227514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.243212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.258816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774896.274402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.290033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.305671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.321286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774896.336900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.352522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.368154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.383780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774896.399386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.415242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.430666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774897.446295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.462129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.477539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.493150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774897.508802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.524412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.540047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.555655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774897.571275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.586943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.602541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774898.618157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.633780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.649522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.665028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774898.680656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.696282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.711918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.727524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774898.743164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.758831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.775740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774899.790028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.805849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.821290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.836907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774899.852526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.868140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.883789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.899392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774899.915042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774900.930673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774900.946279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774900.961900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774900.977517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774900.993145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774901.008784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774901.024420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774901.040043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774901.055639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774901.071266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774901.086894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.102609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.118171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774902.133790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.149550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.165037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.180655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774902.196409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.211928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.227541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.243150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774902.258821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.274430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.290026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774903.305660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.321274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.336904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.352535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774903.368252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.383788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.399418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.415074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774903.430650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.446325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.462131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774904.477535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.493151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.508798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.524413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774904.540057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.555655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.571283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.586892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774904.602509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.618178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.633812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774905.649520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.665018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.680661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.696265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774905.711924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.727517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.743143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.758792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774905.774399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.790068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.805670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774906.821282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.836888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.852530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.868145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774906.883775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.899403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.915052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.930647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774906.946290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774907.961944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774907.977522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774907.993147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774908.008794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774908.024420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774908.040054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774908.055655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774908.071284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774908.086974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774908.102523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774908.118187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.133791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.149533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774909.165017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.180657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.196270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.211914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774909.227523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.243148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.258792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.274397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774909.290019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.305701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.321273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774910.337019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.352518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.368148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.383882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774910.399499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.415139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.430750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.446382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774910.462090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.477658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.493176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774911.508803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.524417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.540090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.555654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774911.571331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.587004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.602537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.618153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774911.633763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.649559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.665020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774912.680646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.696278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.711935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.727531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774912.743143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.758803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.774412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.790017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774912.805640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.821308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.836897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774913.852521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.868147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.883776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.899403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774913.915036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.930637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.946288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.961889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774913.977508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774914.993227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774915.008808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774915.024530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774915.040074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774915.055803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774915.071329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774915.086973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774915.102577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774915.118174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774915.133883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774915.149526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.165045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.180655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774916.196432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.211934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.227541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.243159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774916.258850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.274403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.290021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.305808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774916.321297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.336928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.352525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774917.368143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.383782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.399393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.415045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774917.430625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.446269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.462129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.477520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774917.493134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.508819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.524404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774918.540053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.555645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.571291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.586893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774918.602512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.618160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.633769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.649504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774918.665004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.680703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.696271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774919.711923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.727515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.743148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.758788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774919.774393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.790012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.805638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.821330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774919.836939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774920.852651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774920.868156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774920.883791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774920.899426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774920.915049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774920.931195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774920.946285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774920.961914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774920.977527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774920.993160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774921.008778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.024499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.040090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774922.055654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.071281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.086931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.102536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774922.118181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.133777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.149631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.165016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774922.180662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.196327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.211998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774923.227579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.243236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.258795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.274390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774923.290019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.305637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.321297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.336890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774923.352526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.368183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.383769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774924.399384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.415071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.430651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.446266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774924.462113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.477515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.493149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.508754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774924.524412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.540077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.555643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774925.571273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.586889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.602523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.618153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774925.633754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.649508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.664998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.680646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774925.696251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.712011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.727525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774926.743135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.758788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.774393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.790010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774926.805633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.821285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.836893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.852504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774926.868146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774927.883793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774927.899387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774927.915028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774927.930673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774927.946253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774927.961897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774927.977504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774927.993125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774928.008766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774928.024424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774928.040084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.055648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.071260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774929.086895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.102502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.118165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.133753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774929.149488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.165004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.180641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.196255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774929.211881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.227635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.243205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774930.258787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.274386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.290014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.305642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774930.321273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.336892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.352519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.368130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774930.383759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.399452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.415080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774931.430640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.446273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.462112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.477511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774931.493134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.508772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.524407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.540038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774931.555633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.571285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.586889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774932.602522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.618167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.633751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.649500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774932.665000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.680633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.696254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.711883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774932.727546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.743180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.758792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774933.774536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.790017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.806024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.821426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774933.836938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.852517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.868181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.883802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774933.899429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774934.915082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774934.930651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774934.946276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774934.961903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774934.977524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774934.993153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774935.008773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774935.024428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774935.040058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774935.055639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774935.071274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.086947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.102520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774936.118181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.133763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.149523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.165018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774936.180647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.196264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.211903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.227534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774936.243153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.258821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.274420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774937.290024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.305659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.321284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.336909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774937.352513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.368140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.383760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.399392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774937.415024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.430661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.446275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774938.462109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.477512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.493147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.508763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774938.524409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.540026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.555648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.571254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774938.586879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.602535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.622575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774939.633762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.649512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.665013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.680642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774939.696254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.711892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.727531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.743144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774939.758794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.774410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.790038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774940.805681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.821284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.836895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.852531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774940.868142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.883752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.899383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.915003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774940.930647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774941.946304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774941.961912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774941.977522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774941.993149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774942.008790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774942.024447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774942.040054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774942.055644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774942.071265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774942.086891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774942.102519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.118183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.133751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774943.149502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.165011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.180889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.196279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774943.211919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.229458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.243163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.258794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774943.274541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.290256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.305651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774944.321291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.336896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.352513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.368134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774944.383758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.399380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.415015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.430662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774944.446258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.462142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.477521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774945.493271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.508782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.524408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.540026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774945.555630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.571266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.586876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.602494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774945.618127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.633882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.649523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774946.665029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.680635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.696469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.711903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774946.727556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.743132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.758825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.774457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774946.790008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.805952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.821458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774947.837080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.852593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.868147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.883991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774947.899500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.915012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.930644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.946258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774947.961893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774948.977587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774948.993142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774949.008783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774949.024432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774949.040054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774949.055637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774949.071282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774949.086892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774949.102507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774949.118142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774949.133772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.149605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.165011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774950.180636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.196255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.211879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.227524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774950.243158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.258785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.274391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.290009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774950.305630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.321394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.336902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774951.352531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.368132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.383749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.399378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774951.415036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.430647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.446253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.462145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774951.477695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.493173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.508895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774952.524410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.540036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.555633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.571254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774952.586881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.602497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.618131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.633765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774952.649497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.665035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.680641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774953.696273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.711886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.727639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.743142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774953.758778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.774376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.790112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.805641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774953.821278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.836964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.852525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774954.868151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.883767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.899395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.915009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774954.930650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.946264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.961890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.977511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774954.993148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.008799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.024429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774956.040046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.055647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.071265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.086930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774956.102525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.118143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.133773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.149517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774956.165012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.180647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.196256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774957.211889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.227522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.243142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.258779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774957.274378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.289996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.305624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.321259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774957.336893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.352527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.368140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774958.383767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.399381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.415027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.430656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774958.446259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.462074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.477506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.493131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774958.508755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.524425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.540038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774959.555709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.571292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.586885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.602512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774959.618128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.633770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.649500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.664997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774959.680627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.696289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.711888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774960.727521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.743138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.758784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.774384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774960.790005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.805635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.821259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.836893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774960.852509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774961.868150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774961.883781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774961.899403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774961.915005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774961.930647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774961.946270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774961.961884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774961.977514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774961.993124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774962.008753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774962.024411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.040080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.055741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774963.071379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.086899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.102512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.118154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774963.133874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.149615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.165015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.180629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774963.196258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.211919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.227529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774964.243131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.258786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.274389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.290001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774964.305638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.321253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.336919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.352503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774964.368146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.383776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.399384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774965.415027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.430662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.446260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.462101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774965.477538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.493146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.508756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.524389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774965.540041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.555671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.571266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774966.586884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.602520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.618136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.633767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774966.649517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.665003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.680675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.696248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774966.711894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.727536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.743149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774967.758777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.774394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.790002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.805635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774967.821262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.836900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.852505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.868135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774967.883755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774968.899402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774968.915008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774968.930645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774968.946260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774968.961890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774968.977507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774968.993130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774969.008757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774969.024411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774969.040037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774969.055641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.071285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.086895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774970.102505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.118162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.133768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.149500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774970.165012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.180658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.196245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.211885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774970.227500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.243143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.258785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774971.274381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.290011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.305628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.321259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774971.336894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.352507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.368128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.383755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774971.399380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.415073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.430658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774972.446261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.462111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.477610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.493134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774972.508755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.524377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.540026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.555624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774972.571249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.586932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.602556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774973.618139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.633772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.649518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.664998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774973.680681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.696273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.711925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.727511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774973.743186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.758814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.774411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774974.790006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.805651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.821254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.836918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774974.852504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.868121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.883753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.899371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774974.915026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774975.931316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774975.946337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774975.961957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774975.977582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774975.993195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774976.008759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774976.024415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774976.040053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774976.055637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774976.071248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774976.086908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.102543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.118147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774977.133774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.149496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.165041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.180628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774977.196257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.211871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.227507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.243133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774977.258771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.274414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.290005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774978.305630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.321252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.336889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.352508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774978.368125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.383745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.399369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.415027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774978.430624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.446288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.462083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774979.477505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.493127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.508800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.524418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774979.540039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.555630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.571256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.586877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774979.602493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.618166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.633774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774980.649503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.665007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.680624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.696243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774980.711881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.727495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.743162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.758768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774980.774383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.790080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.805664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774981.821257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.836911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.852501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.868130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774981.883756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.899370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.915017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.930618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774981.946360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774982.961912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774982.977509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774982.993125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774983.008765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774983.024411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774983.040039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774983.055621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774983.071245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774983.086892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774983.102494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774983.118150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.133823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.149515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774984.165006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.180640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.196316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.211879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774984.227555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.243147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.258846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.274382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774984.290050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.305663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.321271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774985.336891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.352513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.368124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.383753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774985.399385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.414997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.430617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.446342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774985.462153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.477584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.493146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774986.508749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.524398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.540042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.555680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774986.571291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.586979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.602502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.618126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774986.633758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.649525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.665009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774987.680635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.696242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.711878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.727496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774987.743142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.758773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.774389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.790003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774987.805625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.821319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.836901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774988.852503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.868133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.883743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.899369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774988.915007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.930618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.946362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.961898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774988.977499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774989.993145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774990.008762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774990.024415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774990.040031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774990.055627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774990.071249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774990.086898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774990.102499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774990.118145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774990.133740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774990.149573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.165024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.180632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774991.196257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.211871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.227506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.243139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774991.258769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.274385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.289985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.305632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774991.321236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.336942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.352507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774992.368141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.383758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.399379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.415087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774992.430633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.446355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.462110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.477495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774992.493192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.508813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.524740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774993.540058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.555628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.571259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.586874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774993.602494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.618120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.633743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.649586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774993.664988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.680730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.696259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774994.711891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.727515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.743149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.758791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774994.774394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.790003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.805626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.821257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774994.836878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774995.852551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774995.868128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774995.883753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774995.899376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774995.915010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774995.930623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774995.946348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774995.961880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774995.977498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774995.993140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774996.008792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.024452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.040045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774997.055634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.071258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.086886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.102588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774997.118134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.133747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.149577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.164987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774997.180617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.196280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.211890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774998.227498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.243148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.258794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.274391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774998.290002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.305630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.321251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.336868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774998.352589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.368147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.383759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774999.399391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.415038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.431113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.446321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342774999.462085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.477556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.493524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.508761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342774999.524400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.540041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.555632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775000.571265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.586871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.602486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.618109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775000.633740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.649567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.664990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.680613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775000.696231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.711970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.727511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775001.743153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.758796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.774405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.790009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775001.805619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.821247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.836873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.852611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775001.868136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775002.883822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775002.899376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775002.914993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775002.930616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775002.946409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775002.961931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775002.977535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775002.993167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775003.008748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775003.024381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775003.040037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.055714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.071278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775004.086954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.102513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.118135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.133753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775004.149612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.164987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.180623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.196251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775004.211873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.227540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.243145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775005.258775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.274398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.289996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.305631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775005.321242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.336871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.352590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.368110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775005.383740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.399472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.415099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775006.430696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.446340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.462082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.477496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775006.493123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.508746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.524379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.540019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775006.555645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.571268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.586874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775007.602492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.618126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.633745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.649577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775007.664987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.680615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.696239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.711872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775007.727483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.743209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.758790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775008.774382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.789983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.805613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.821263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775008.836865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.852588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.868114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.883750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775008.899356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775009.915033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775009.930632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775009.946358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775009.961875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775009.977502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775009.993112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775010.008753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775010.024402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775010.040020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775010.055635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775010.071236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.086949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.102514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775011.118121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.133752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.149586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.164993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775011.180614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.196242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.211862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.227488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775011.243125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.258797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.274394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775012.290003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.305622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.321240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.336873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775012.352587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.368109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.383748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.399356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775012.415007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.430735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.446349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775013.462081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.477495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.493129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.508749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775013.524383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.540026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.555640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.571252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775013.586862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.602640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.618125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775014.633756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.649542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.665004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.680623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775014.696269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.711910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.727493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.743141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775014.758779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.774411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.789996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775015.805690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.821250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.836906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.852574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775015.868121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.883742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.899361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.914983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775015.930700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775016.946382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775016.961877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775016.977501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775016.993124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775017.008755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775017.024414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775017.040031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775017.055646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775017.071245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775017.086881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775017.102491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.118155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.133783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775018.149619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.164992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.180621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.196240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775018.211872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.227494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.243132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.258873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775018.274389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.290016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.305618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775019.321244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.336861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.352582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.368112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775019.383743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.399368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.415023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.430606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775019.446240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.462094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.477493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775020.493123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.508738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.524394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.540017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775020.555645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.571239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.586859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.602484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775020.618106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.633779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.649563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775021.665000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.680691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.696303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.711865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775021.727492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.743104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.758775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.774366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775021.789987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.805724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.821259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775022.836859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.852565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.868106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.883757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775022.899366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.914983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.930696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.946314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775022.961889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775023.977701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775023.993139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775024.008753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775024.024517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775024.040053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775024.055648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775024.071250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775024.086953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775024.102514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775024.118122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775024.133737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.149616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.164995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775025.180621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.196244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.211863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.227495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775025.243118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.258765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.274449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.289980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775025.305613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.321304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.336876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775026.352605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.368122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.383753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.399375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775026.414995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.430606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.446254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.462156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775026.477488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.493153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.508749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775027.524456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.540008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.555634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.571250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775027.586859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.602487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.618112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.633727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775027.649507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.665010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.680624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775028.696247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.711872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.727489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.743116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775028.758767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.774432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.789983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.805608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775028.821239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.836901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.852601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775029.868110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.883747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.899364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.914992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775029.930606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.946260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.961874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.977480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775029.993103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.008768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.024463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775031.040013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.055643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.071235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.086875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775031.102498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.118127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.133733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.149469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775031.164997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.180655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.196235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775032.211858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.227490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.243105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.258784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775032.274420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.289999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.305619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.321232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775032.336862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.352602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.368113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775033.383744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.399363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.415008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.430614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775033.446242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.462089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.477494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.493113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775033.508774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.524477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.540012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775034.555654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.571246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.586853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.602491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775034.618129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.633726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.649479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.665004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775034.680609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.696252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.711906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775035.727475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.743103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.758766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.774358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775035.789973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.805617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.821226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.836858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775035.852476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775036.868143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775036.883743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775036.899370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775036.914991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775036.931162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775036.946250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775036.961886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775036.977496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775036.993120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775037.008762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775037.024441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.040173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.055649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775038.071253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.086882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.102491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.118138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775038.133736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.149499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.164993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.180610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775038.196225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.211897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.227497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775039.243116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.258784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.274401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.289990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775039.305610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.321241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.336915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.352496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775039.368140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.383817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.399374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775040.415024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.430612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.446229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.462148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775040.477504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.493112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.508739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.524401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775040.540009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.555692 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.571259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775041.586869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.602496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.618131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.633746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775041.649510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.665007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.680623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.696254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775041.711873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.727530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.743140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775042.758847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.774505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.790121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.805910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775042.821232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.836916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.852522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.868135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775042.883767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775043.899490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775043.915005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775043.930620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775043.946255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775043.962021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775043.977502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775043.993165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775044.008748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775044.024430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775044.040173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775044.063300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.071269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.086870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775045.102485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.118118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.133723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.149491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775045.164990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.180595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.196223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.211847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775045.227473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.243129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.258768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775046.274373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.289973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.305607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.321229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775046.336857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.352474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.368120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.383723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775046.399340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.415018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.430607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775047.446233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.462076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.477486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.493098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775047.508734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.524372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.540009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.563076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775047.571240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.586902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.602482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775048.618123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.633735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.649488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.664999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775048.680602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.696226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.711855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.727481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775048.743102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.758798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.774377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775049.789986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.805611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.821239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.836861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775049.852492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.868135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.883742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.899354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775049.914978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775050.930651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775050.946255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775050.961880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775050.977483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775050.993119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775051.008791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775051.024449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775051.040062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775051.063888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775051.071252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775051.086862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.102556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.118176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775052.133779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.149536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.165014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.180594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775052.196223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.211853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.227481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.243099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775052.258846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.274394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.289960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775053.305606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.321239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.336860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.352483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775053.368120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.383732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.399354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.415004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775053.430603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.446271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.462092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775054.477485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.493283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.508857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.524399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775054.540639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.555638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.571284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.586862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775054.602541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.618153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.633744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775055.649494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.665030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.680625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.696247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775055.711872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.727493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.743126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.758758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775055.774389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.790028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.805619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775056.821246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.836864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.852517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.868121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775056.883734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.899357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.914979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.930616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775056.946228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775057.961919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775057.977480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775057.993102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775058.008747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775058.024399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775058.040014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775058.055606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775058.071246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775058.086867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775058.102481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775058.118122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.133772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.149492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775059.165000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.180601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.196268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.211862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775059.227490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.243115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.258747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.274368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775059.289983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.305638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.321241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775060.336854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.352493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.368113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.383727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775060.399389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.414992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.430594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.446222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775060.462073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.477536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.493112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775061.508731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.524375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.540005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.555607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775061.571256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.586853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.602475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.618096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775061.633739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.649517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.665011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775062.680615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.696241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.711860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.727498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775062.743113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.758752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.774384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.789979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775062.805602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.821301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.836859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775063.852774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.868258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.883973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.899361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775063.915002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.930614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.946256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.961873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775063.977518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775064.993230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775065.008745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775065.024392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775065.040036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775065.055612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775065.071251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775065.086878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775065.102483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775065.118130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775065.133720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775065.149495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.165034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.180609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775066.196227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.211863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.227477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.243114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775066.258760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.274372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.289982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.305594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775066.321219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.336894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.352488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775067.368136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.383736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.399365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.415020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775067.430743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.446236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.462063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.477519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775067.493125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.508862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.524379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775068.540035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.555621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.571252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.586860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775068.602479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.618127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.633727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.649496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775068.664973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.680636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.696241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775069.711923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.727484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.743113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.758762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775069.774370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.789982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.805612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.821243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775069.836855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775070.852501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775070.868128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775070.883733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775070.899356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775070.914979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775070.930612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775070.946218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775070.961867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775070.977504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775070.993106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775071.008748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.024457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.040017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775072.055622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.071257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.086939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.102484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775072.118150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.133733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.149483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.164983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775072.180631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.196258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.211898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775073.227483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.243113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.258752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.274373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775073.289978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.305593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.321220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.336851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775073.352467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.368163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.383750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775074.399416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.414996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.430614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.446249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775074.462081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.477489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.493116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.508714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775074.524364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.540056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.555612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775075.571251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.586855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.602485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.618108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775075.633735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.649489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.664969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.680613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775075.696225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.711985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.727493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775076.743100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.758760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.774348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.789986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775076.805598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.821234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.836844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.852469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775076.868092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775077.883804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775077.899355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775077.914991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775077.930625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775077.946238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775077.961863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775077.977539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775077.993096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775078.008721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775078.024368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775078.040009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.055678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.071257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775079.086868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.102485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.118133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.133736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775079.149491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.164980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.180633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.196231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775079.211851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.227525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.243130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775080.258859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.274363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.290081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.305700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775080.321336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.336847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.352482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.368102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775080.383748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.399372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.415001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775081.431043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.446223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.462069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.477497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775081.493113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.508738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.524371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.540004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775081.555606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.571269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.586848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775082.602480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.618111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.633734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.649482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775082.664975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.680613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.696269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.711853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775082.727474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.743143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.758757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775083.774376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.789976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.805604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.821223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775083.836861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.852468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.868115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.883740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775083.899364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775084.915016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775084.930615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775084.946223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775084.961861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775084.977499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775084.993112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775085.008735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775085.024381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775085.040004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775085.055598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775085.071222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.086943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.102516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775086.118166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.133785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.149515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.165029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775086.180695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.196278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.211910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.227519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775086.243141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.258797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.274373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775087.289975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.305614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.321220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.336851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775087.352488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.368108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.383733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.399349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775087.414992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.430623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.446230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775088.462063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.477483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.493102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.508736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775088.524353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.539998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.555602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.571226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775088.586863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.602502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.618101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775089.633726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.649488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.664964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.680615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775089.696218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.711859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.727469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.743103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775089.758746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.774390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.789996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775090.805588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.821221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.836847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.852467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775090.868106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.883733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.899335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.914958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775090.930585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775091.946246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775091.961861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775091.977507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775092.003958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775092.009016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775092.024389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775092.040006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775092.055592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775092.071226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775092.086944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775092.102481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.118146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.133722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775093.149446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.164968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.180615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.196220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775093.211831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.227461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.243074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.258845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775093.274348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.290037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.305610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775094.321228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.336861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.352480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.368105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775094.383741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.399353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.415019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.430602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775094.446226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.462208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.477505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775095.493114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.508732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.524354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.540021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775095.555612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.571268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.586862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.602471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775095.618091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.633741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.649464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775096.664993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.680614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.696216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.711853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775096.727470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.743106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.758747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.774335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775096.789984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.805615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.821235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775097.836858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.852477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.868173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.883742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775097.899367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.914975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.930592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.946230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775097.961843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775098.977522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775098.993105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775099.008732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775099.024376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775099.040000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775099.055611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775099.071230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775099.086872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775099.102466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775099.118102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775099.133722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.149492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.164968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775100.180596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.196207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.211839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.227451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775100.243093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.258744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.274341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.289979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775100.305593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.321251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.336849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775101.352474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.368081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.383745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.399349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775101.415086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.430585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.446217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.462048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775101.477458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.493170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.508733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775102.524351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.540006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.555600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.571219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775102.586883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.602461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.618102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.633725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775102.649461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.664997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.680616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775103.696226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.711851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.727485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.743088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775103.758734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.774333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.789982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.805586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775103.821208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.836904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.852507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775104.868116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.883739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.899353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.914965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775104.930586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.946215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.961847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.977466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775104.993113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.008767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.024380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775106.040009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.055607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.071228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.086884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775106.102474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.118116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.133724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.149474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775106.164984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.180643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.196237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775107.211850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.227471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.243104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.258745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775107.274373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.289991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.305583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.321219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775107.336832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.352486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.368121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775108.383736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.399344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.414997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.430595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775108.446224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.462058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.477465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.493136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775108.508709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.524389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.540015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775109.555613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.571238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.586860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.602481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775109.618112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.633721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.649465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.664962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775109.680595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.696252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.711841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775110.727484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.743098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.758754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.774340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775110.789998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.805591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.821213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.836848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775110.852470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775111.868125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775111.883740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775111.899338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775111.914962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775111.930602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775111.946219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775111.961854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775111.977470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775111.993127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775112.008716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775112.024362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.040066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.055599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775113.071222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.086871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.102476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.118099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775113.133723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.149470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.165093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.180731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775113.196349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.211875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.227483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775114.243104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.258752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.274337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.289995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775114.305601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.321211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.336846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.352461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775114.368102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.383905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.399356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775115.414992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.430600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.446365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.462098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775115.477478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.493321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.508735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.524353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775115.540017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.555635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.571229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775116.586857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.602471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.618100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.633715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775116.649473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.664959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.680586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.696244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775116.711843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.727494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.743118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775117.758757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.774354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.789995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.805598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775117.821226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.836840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.852473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.868084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775117.883715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775118.899386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775118.914995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775118.930599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775118.946226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775118.961849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775118.977468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775118.993091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775119.008723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775119.024354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775119.039981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775119.063043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.071250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.086942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775120.102471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.118117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.133725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.149466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775120.164965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.180586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.196220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.211832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775120.227460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.243110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.258760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775121.274337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.289977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.305588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.321276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775121.336884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.352471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.368273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.383729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775121.399352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.415155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.431302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775122.446266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.462117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.477613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.493150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775122.508819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.524340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.539989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.563149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775122.571209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.586873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.602469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775123.618095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.633712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.649465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.664959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775123.680582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.696254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.711849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.727466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775123.743084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.758803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.774389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775124.790031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.805708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.821216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.836850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775124.852459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.868084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.883725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.899407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775124.915078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775125.931047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775125.946284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775125.961853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775125.977469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775125.993109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775126.008725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775126.024368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775126.040256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775126.063180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775126.071213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775126.086863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.102480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.118112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775127.133716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.149455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.164972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.180587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775127.196231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.211840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.227526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.243084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775127.258797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.274383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.289994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775128.305593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.321222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.336841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.352476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775128.368101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.383742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.399356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.414986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775128.430688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.446263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.462114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775129.477454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.493119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.508716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.524346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775129.539999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.563072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.571238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.586852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775129.602492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.618138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.633737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775130.649479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.664981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.680637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.696242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775130.711897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.727518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.743154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.758780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775130.774388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.790032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.805608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775131.821218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.836846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.852462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.868110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775131.883710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.899352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.914966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.930576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775131.946205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775132.961876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775132.977473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775132.993106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775133.008769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775133.024356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775133.040011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775133.063003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775133.071218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775133.086835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775133.102476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775133.118130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.133759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.149454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775134.164958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.180597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.196244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.211828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775134.227455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.243082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.258738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.274326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775134.289971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.305697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.321278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775135.336848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.352464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.368090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.383743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775135.399437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.414992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.430589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.446227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775135.462114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.477498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.493110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775136.508721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.524338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.539989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.563145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775136.571215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.586831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.602474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.618070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775136.633721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.649516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.664974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775137.680590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.696247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.711842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.727474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775137.743090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.758726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.774327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.789951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775137.805605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.821248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.836841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775138.852464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.868089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.883719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.899366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775138.914958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.930585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.946204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.961840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775138.977451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775139.993181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775140.008728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775140.024363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775140.040005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775140.055595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775140.071213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775140.086942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775140.102472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775140.118108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775140.133725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775140.149458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.164988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.180593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775141.196236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.211839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.227474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.243083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775141.258748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.274341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.289964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.305587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775141.321205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.336865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.352455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775142.368095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.383733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.399315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.415156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775142.431142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.446318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.462045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.477501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.493135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775142.508741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775142.524345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775142.539984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775142.555595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775142.571219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775143.586878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775143.602482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775143.618142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775143.633729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775143.649489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775143.664961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775143.680589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775143.696218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775143.711862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775143.727465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775143.743090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.758775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.774328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775144.789960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.805613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.821212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.836845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775144.852459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.868091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.883725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.899331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775144.914986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775145.930609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775145.946205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775145.961841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775145.977455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775145.993106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775146.008734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775146.024363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775146.039989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775146.055577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775146.071207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775146.086843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.102484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.118100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775147.133730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.149456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.164957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.180574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775147.196220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.211849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.227449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.243083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775147.258723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.274375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.289968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775148.305594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.321227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.336835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.352466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775148.368087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.383730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.399329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.414993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775148.430576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.446244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.462040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775149.477467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.493080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.508732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.524340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775149.539999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.555577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.571204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.586825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775149.602450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.618108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.633731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775150.649444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.664966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.680579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.696220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775150.711849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.727453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.743077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.758722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775150.774313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.789992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.805606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775151.821205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.836842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.852457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.868089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775151.883717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.899321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.914972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.930573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775151.946216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775152.961915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775152.978032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775152.993086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775153.008735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775153.024358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775153.040243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775153.055591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775153.071210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775153.086846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775153.102458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775153.118114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.133770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.149470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775154.164959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.180582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.196212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.211853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775154.227465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.243081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.258750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.274332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775154.289954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.305664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.321219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775155.336839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.352452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.368095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.383732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775155.399330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.414992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.430581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.446227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775155.462076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.477533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.493093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775156.508725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.524325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.539984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.555578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775156.571199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.586821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.602444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.618088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775156.633728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.649483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.664967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775157.680574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.696208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.711834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.727472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775157.743075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.758719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.774332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.789941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775157.805569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.821253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.836834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775158.852465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.868086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.883722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.899335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775158.914965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.930570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.946194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.961829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775158.977450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775159.993122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775160.008739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775160.024365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775160.039993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775160.055583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775160.071211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775160.086898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775160.102464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775160.118102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775160.133738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775160.149469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.165077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.180619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775161.196701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.211922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.227488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.243087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775161.258758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.274454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.289947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.305571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775161.321224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.336911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.352649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775162.368191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.383888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.399428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.415046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775162.430615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.446198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.462120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.477571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775162.493626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.508780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.524324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775163.539980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.555572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.571205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.586820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775163.602456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.618092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.633729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.649468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.664960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775163.680593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775163.696255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775163.711863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775163.727497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775163.743101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775164.758785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775164.774350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775164.789958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775164.805593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775164.821233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775164.836881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775164.852459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775164.868086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775164.883710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775164.899385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775164.914951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775165.930625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775165.946207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775165.961884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775165.977461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775165.993106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775166.008703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775166.024368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775166.040003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775166.055593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775166.071216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775166.086835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.102513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.118104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775167.133713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.149443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.164947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.180579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775167.196198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.211818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.227467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.243072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775167.258726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.274388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.289962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775168.305585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.321218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.336839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.352458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775168.368082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.383721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.399333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.414962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775168.430588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.446249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.462063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775169.477453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.493075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.508707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.524344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775169.539988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.555586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.571202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.586822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775169.602442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.618132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.633718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775170.649431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.664956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.680574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.696195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775170.711832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.727463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.743065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.758720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775170.774309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.789970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.805568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775171.821221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.836827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.852443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.868073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775171.883705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.899330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.914943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.930576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775171.946186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775172.961876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775172.978016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775172.993079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775173.008704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775173.024366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775173.039999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775173.055570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775173.071194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775173.086831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775173.102446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775173.118074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.133770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.149462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775174.165177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.180593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.196205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.211847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775174.227476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.243097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.258721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.274335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775174.289951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.305632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.321237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775175.336830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.352470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.368082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.383720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775175.399330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.415013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.430595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.446198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775175.462050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.477472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.493311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775176.508698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.524362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.539971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.555597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775176.571205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.586824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.602454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.618086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775176.633736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.649473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.664960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775177.680574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.696202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.711836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.727487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775177.743082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.758734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.774311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.789957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775177.805584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.821274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.836843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775178.852449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.868081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.883712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.899340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775178.914945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.930584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.946191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.961831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775178.977449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775179.993121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775180.008711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775180.024362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775180.039980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775180.055593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775180.071192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775180.086923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775180.102446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775180.118073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775180.133735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775180.149453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.164981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.180577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775181.196205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.211821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.227472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.243080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775181.258736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.274319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.289942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.305566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775181.321198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.336880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.352451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775182.368070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.383793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.399327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.414966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775182.430597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.446188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.462071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.477457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775182.493075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.508747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.524354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775183.539978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.555576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.571208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.586820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775183.602457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.618075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.633813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.649455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775183.664964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.680595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.696195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775184.711824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.727465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.743068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.758724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775184.774303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.789949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.805697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.821212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775184.836844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775185.852502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775185.868077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775185.883780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775185.899317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775185.914948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775185.930578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775185.946284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775185.961836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775185.977438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775185.993065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775186.008786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.024401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.039991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775187.055575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.071208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.086825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.102454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775187.118070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.133780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.149444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.164943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775187.180573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.196222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.211826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775188.227461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.243080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.258721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.274318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775188.289954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.305566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.321202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.336832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775188.352436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.368167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.383763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775189.399325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.415004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.430586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.446195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775189.462065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.477449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.493061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.508697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775189.524319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.540037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.555572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775190.571207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.586819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.602443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.618083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775190.633764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.649453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.664951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.680579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775190.696204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.711862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.727463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775191.743072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.758721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.774319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.789938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775191.805577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.821198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.836821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.852443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775191.868063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775192.883801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775192.899334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775192.914952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775192.931126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775192.946207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775192.961827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775192.978006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775192.993075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775193.008700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775193.024351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775193.039995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.055603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.071204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775194.086838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.102445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.118072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.133766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775194.149448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.164942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.180569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.196190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775194.211811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.227518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.243094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775195.258733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.274332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.289946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.305577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775195.321200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.336850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.352453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.368071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775195.383731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.399441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.414983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775196.430574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.446189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.462079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.477438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775196.493072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.508776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.524375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.539976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775196.562812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.571207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.586823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775197.602444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.618063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.633751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.649429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775197.664935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.680565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.696183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.711810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775197.727439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.743092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.758786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775198.774326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.789950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.805571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.821204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775198.836840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.852454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.868067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.883730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775198.899313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775199.914961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775199.930595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775199.946199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775199.961825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775199.977466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775199.993071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775200.008696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775200.024349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775200.039971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775200.062739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775200.071198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.086847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.102448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775201.118066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.133730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.149431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.164940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775201.180573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.196201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.211828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.227436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775201.243082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.258738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.274325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775202.289936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.305566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.321190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.336835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775202.352450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.368066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.383697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.399317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775202.414952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.430639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.446209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775203.462054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.477450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.493091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.508694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775203.524331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.539988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.562939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.571196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.586816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775203.602458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775203.618085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775203.633721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775203.649435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775203.665096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775204.680609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775204.696194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775204.711812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775204.727431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775204.743071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775204.758710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775204.774313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775204.789934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775204.805557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775204.821197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775204.836809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775205.852477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775205.868067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775205.883714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775205.899316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775205.914948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775205.930565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775205.946305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775205.961830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775205.977432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775205.993070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775206.008684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.024370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.039973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775207.055588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.071195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.086828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.102452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775207.118073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.133710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.149538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.164932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775207.180555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.196221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.211811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775208.227444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.243078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.258710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.274320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775208.289943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.305555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.321180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.336810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775208.352538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.368104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.383803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775209.399318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.414958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.430559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.446296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775209.462037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.477436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.493066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.508680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775209.524314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.540023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.555577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775210.571200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.586824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.602439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.618065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775210.633689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.649534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.664934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.680563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775210.696180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.711847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.727446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775211.743078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.758727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.774318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.789930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775211.805556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.821181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.836814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.852528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775211.868065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775212.883764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775212.899327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775212.914954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775212.930565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775212.946293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775212.961819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775212.977462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775212.993061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775213.008705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775213.024348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775213.039967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.055597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.071215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775214.086828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.102443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.118071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.133699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775214.149520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.164931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.180557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.196184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775214.211806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.227596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.243169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775215.258796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.274317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.289933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.305647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775215.321269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.336892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.352536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.368076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775215.383714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.399436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.414961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775216.430567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.446391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.462009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.477545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775216.493056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.508682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.524315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.540052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775216.562867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.571239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.586832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775217.602444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.618072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.633700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.649515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775217.664938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.680556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.696180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.711808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775217.727439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.743151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.758827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775218.774378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.790078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.805972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.821382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775218.836937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.852697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.868251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.883893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775218.899384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775219.915080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775219.930609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775219.946280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775219.961911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775219.977517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775219.993151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775220.008691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775220.024328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775220.039959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775220.062940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775220.071178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.087023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.102456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775221.118077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.133681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.149530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.164932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775221.180551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.196263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.211808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.227440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775221.243059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.258768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.274324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775222.289946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.305578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.321183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.336816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775222.352525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.368062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.383682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.399301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775222.414968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.430691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.446328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775223.462032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.477432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.493080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.508682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775223.524326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.539958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.555579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.571178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775223.586783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.602563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.618243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775224.633802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.649512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.664926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.680552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775224.696204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.711832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.727438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.743078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775224.758720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.774342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.789964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775225.805578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.821195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.836819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.852547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775225.868065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.883676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.899302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.914949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775225.930560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775226.946312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775226.961815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775226.977435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775226.993076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775227.008702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775227.024329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775227.039973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775227.055577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775227.071181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775227.086829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775227.102424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.118133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.133703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775228.149518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.164936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.180560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.196198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775228.211811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.227437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.243054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.258722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775228.274301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.289956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.305561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775229.321180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.336807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.352525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.368105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775229.383679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.399303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.414955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.430555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775229.446179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.462047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.477448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775230.493059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.508696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.524311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.539951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775230.555566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.571188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.586810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.602438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775230.618049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.633703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.649526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775231.664944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.680552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.696181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.711802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775231.727419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.743059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.758720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.774312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775231.789920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.805625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.821182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775232.836808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.852523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.868057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.883706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775232.899299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.914928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.930558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.946181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775232.961825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775233.977469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775233.993061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775234.008702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775234.024329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775234.039963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775234.055568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775234.071173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775234.086832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775234.102425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775234.118075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775234.133682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.149689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.164981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775235.180575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.196284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.211844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.227450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775235.243079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.258789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.274324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.289961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775235.305571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.321252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.336830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775236.352528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.368073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.383689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.399304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775236.414948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.430561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.446184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.462086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775236.477448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.493082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.508699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775237.524323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.539975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.555573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.571193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775237.586806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.602429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.618052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.633683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775237.649431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.665053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.680576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775238.696192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.711819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.727435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.743128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775238.758727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.774325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.789932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.805583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775238.821179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.836845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.852518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775239.868052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.883673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.899314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.914946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775239.930568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.946238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.961838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.977433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775239.993069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.008721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.024330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775241.039960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.055577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.071177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.086804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775241.102436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.118074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.133676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.149412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775241.164936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.180596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.196191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775242.211817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.227434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.243057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.258716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775242.274304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.289940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.305553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.321191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775242.336805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.352555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.368081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775243.383698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.399315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.414953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.430562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775243.446182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.462036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.477424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.493068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775243.508704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.524356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.539967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775244.555590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.571195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.586811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.602435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775244.618062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.633853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.649481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.664951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775244.680558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.696230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.711819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775245.727440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.743066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.758778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.774322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775245.789942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.805565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.821189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.836822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775245.852439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775246.868080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775246.883688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775246.899322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775246.914935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775246.930577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775246.946186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775246.961830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775246.977430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775246.994562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775247.008687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775247.024340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.040047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.055608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775248.071192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.086880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.102440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.118092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775248.133682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.149452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.164943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.180561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775248.196182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.211841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.227433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775249.243070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.258720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.274306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.289930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775249.305550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.321184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.336828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.352445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775249.368244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.383719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.399303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775250.415013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.430553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.446184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.462049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775250.477430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.493057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.508682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.524321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775250.539965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.555605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.571188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775251.586805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.602428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.618042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.633669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775251.649432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.664937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.680543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.696168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775251.711789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.727442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.743056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775252.758717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.774290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.789898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.805570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775252.821281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.836859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.852470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.868089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775252.883694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775253.899374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775253.914949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775253.930560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775253.946192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775253.961830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775253.977437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775253.993043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775254.008698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775254.024329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775254.039962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775254.055565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.071249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.086830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775255.102453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.118073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.133682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.149462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775255.164955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.180553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.196174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.211800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775255.227462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.243114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.258726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775256.274324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.289938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.305568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.321185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775256.336828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.352438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.368305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.383682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775256.399324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.414992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.430545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775257.446183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.462041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.477415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.493043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775257.508688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.524309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.539947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.555543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775257.571185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.586818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.602418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775258.618052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.633666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.649412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.664934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775258.680539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.696174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.711788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.727414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775258.743038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.758737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.774294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775259.789916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.805541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.821177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.836794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775259.852442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.868059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.883665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.899287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775259.914915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775260.930577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775260.946171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775260.961825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775260.977418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775260.993048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775261.008666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775261.024317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775261.039941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775261.055545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775261.071179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775261.086824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.102445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.118050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775262.133680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.149410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.164947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.180552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775262.196183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.211785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.227414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.243034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775262.258684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.274340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.289928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775263.305554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.321176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.336821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.352421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775263.368057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.383665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.399310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.414944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775263.430541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.446220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.462037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775264.477430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.493062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.508687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.524309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775264.539950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.555542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.571188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.586788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775264.602422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.618109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.633681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775265.649442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.664950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.680568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.696185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775265.711801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.727417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.743048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.758699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775265.774313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.789965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.805555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775266.821190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.836804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.852421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.868061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775266.883692 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.899307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.914930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.930551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775266.946175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775267.961878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775267.977426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775267.993053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775268.008677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775268.024329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775268.039952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775268.055552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775268.071192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775268.086866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775268.102422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775268.118075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.133752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.149465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775269.164947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.180553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.196174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.211787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775269.227418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.243051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.258709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.274309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775269.289910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.305610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.321196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775270.336812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.352446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.368048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.383686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775270.399313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.414946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.430548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.446189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775270.462045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.477470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.493052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775271.508696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.524311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.539945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.555560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775271.571188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.586803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.602424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.618050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775271.633662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.649484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.664941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775272.680566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.696186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.711814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.727415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775272.743049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.758710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.774293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.789922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775272.805547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.821203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.836811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775273.852426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.868066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.883678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.899301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775273.914931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.930551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.946168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.961791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775273.977443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775274.993120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775275.008678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775275.024319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775275.039947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775275.055551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775275.071186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775275.086816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775275.102425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775275.118043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775275.133666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775275.149428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.164965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.180550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775276.196170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.211802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.227412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.243040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775276.258691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.274305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.289913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.305538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775276.321167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.336850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.352433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775277.368228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.383688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.399291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.414959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775277.430563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.446168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.462067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.477441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775277.493044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.508718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.524306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775278.539958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.555550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.571187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.586805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775278.602424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.618063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.633674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.649411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775278.664931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.680575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.696183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775279.711802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.727424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.743041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.758715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775279.774308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.789930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.805550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.821183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775279.836794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775280.852468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775280.868063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775280.883663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775280.899307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775280.914925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775280.930542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775280.946157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775280.961798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775280.977429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775280.993058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775281.008664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.024376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.047534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775282.057642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.071279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.086793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.102472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775282.118143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.133662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.149293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.165072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775282.180561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.196309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.211822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775283.227438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.243223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.258805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.274412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775283.289923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.305548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.321273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.336793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775283.352519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.368171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.383699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775284.399289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.414942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.430544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.446225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775284.462010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.477433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.493043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.508669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775284.524299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.540028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.555563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775285.571202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.586796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.602422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.618070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775285.633668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.649309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.664916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.680576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775285.696168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.711839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.727423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775286.743047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.758681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.774300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.789922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775286.805542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.821176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.836785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.852422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775286.868034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775287.883702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775287.899297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775287.914917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775287.930540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775287.946166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775287.961792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775287.977442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775287.993044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775288.008661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775288.024352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775288.039951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.055610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.071192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775289.086812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.102427 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.118062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.133673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775289.149292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.164927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.180560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.196167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775289.211796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.227455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.243074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775290.258695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.274305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.289978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.305546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775290.321185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.336802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.352408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.368046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775290.383680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.399345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.414943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775291.430552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.446172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.462039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.477449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775291.493046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.508664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.524290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.539938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775291.563097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.571265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.586786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775292.602420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.618055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.633671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.649313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775292.664917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.680561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.696166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.711783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775292.727405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.743116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.758698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775293.774318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.789913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.805514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.821173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775293.836794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.852414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.868044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.883686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775293.899305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775294.915010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775294.930537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775294.946164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775294.961799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775294.977983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775294.993187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775295.008789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775295.024550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775295.039972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775295.063528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775295.071162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.086940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.102441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775296.118057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.133677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.149290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.164915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775296.180557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.196158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.211782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.227424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775296.243047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.258715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.274331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775297.289927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.305545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.321174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.336784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775297.352418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.368044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.383695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.399296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775297.414935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.430972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.446276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775298.462016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.477546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.493074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.508792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775298.524302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.539951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.563301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.571176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775298.586834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.602481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.618040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775299.633673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.649289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.664915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.680551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775299.696157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.711786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.727419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.743049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775299.758677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.774347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.789924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775300.805707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.821180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.836805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.852421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775300.868065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.883686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.899289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.914909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775300.930525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775301.946204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775301.961795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775301.977435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775301.993074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775302.008670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775302.024314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775302.040245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775302.063480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775302.071164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775302.086815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775302.102409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.118064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.133656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775303.149286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.164913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.180549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.196164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775303.211784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.227412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.243041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.258661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775303.274285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.289939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.305547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775304.321164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.336795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.352414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.368045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775304.383686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.399280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.414924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.430530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775304.446159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.462217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.477495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775305.493046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.509423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.524513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.539979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775305.563510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.571195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.586837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.602415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775305.618116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.633790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.649296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775306.664924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.680579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.696159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.711816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775306.727403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.743105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.758653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.774276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775306.789935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.805597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.821177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775307.836798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.852468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.868050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.883742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775307.899299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.914930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.931125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.946169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775307.961842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775308.977537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775308.993406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775309.008719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775309.024341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775309.039934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775309.055616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775309.071245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775309.086915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775309.102473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775309.118122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775309.133684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.149445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.164915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775310.180585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.196179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.211788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.227450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775310.243072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.258667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.274326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.289989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775310.305541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.321285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.336800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775311.352434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.368048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.383694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.399292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775311.414941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.430543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.446183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.462087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775311.477425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.493093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.508662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775312.524299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.539943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.555544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.571171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775312.586832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.602407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.618059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.633662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775312.649281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.664977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.680554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775313.696248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.711871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.727414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.743059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775313.758657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.774292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.790008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.805542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775313.821163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.836844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.852411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775314.868068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.883685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.899290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.914921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775314.931059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.946190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.961803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.977420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775314.993108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.008851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.024376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775316.039957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.055548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.071175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.086890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775316.102428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.118061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.133670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.149307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775316.164926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.180585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.196166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775317.211795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.227415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.243051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.258658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775317.274278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.289924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.305524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.321148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775317.336772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.352452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.368042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775318.383684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.399283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.414926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.430528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775318.446159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.462078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.477425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.493073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775318.508665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.524385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.539940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775319.555547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.571154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.586814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.602421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775319.618042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.633658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.649278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.664910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775319.680534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.696195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.711783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775320.727417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.743062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.758655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.774274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775320.789941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.805690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.821171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.836800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775320.852414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775321.868194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775321.883734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775321.899338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775321.914916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775321.930547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775321.946162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775321.961786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775321.977406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775321.993071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775322.008662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775322.024306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.040008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.055540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775323.071147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.086833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.102407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.118037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775323.133653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.149276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.165049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.180532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775323.196171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.211843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.227424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775324.243069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.258672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.274291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.289937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775324.305540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.321171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.336811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.352428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775324.368034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.383741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.399291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775325.414932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.430533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.446157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.462008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775325.477404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.493071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.508653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.524306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775325.539930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.555668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.571247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775326.586888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.602494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.618043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.633665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775326.649284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.664914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.680528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.696195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775326.711781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.727598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.743070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775327.758660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.774284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.789938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.805546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775327.821164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.836784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.852398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.868036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775327.883669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775328.899348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775328.914914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775328.930537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775328.946162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775328.961785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775328.977402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775328.993072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775329.008652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775329.024296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775329.039934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775329.055531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.071202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.086811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775330.102405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.118024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.133664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.149275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775330.164900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.180528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.196180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.211778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775330.227396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.243109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.258663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775331.274281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.289920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.305531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.321164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775331.336784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.352408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.368021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.383668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775331.399297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.415037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.430614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775332.446155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.461989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.477407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.493054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775332.508656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.524278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.539932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.555546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775332.571156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.586849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.602402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775333.618044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.633661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.649279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.664899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775333.680538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.696194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.711782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.727395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775333.743039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.758713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.774286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775334.789928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.805537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.821157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.836787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775334.852398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.868030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.883655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.899304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775334.914922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775335.930591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775335.946172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775335.961794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775335.977416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775335.993068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775336.008691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775336.024303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775336.040197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775336.055532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775336.071151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775336.086850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.102442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.118033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775337.133662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.149285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.164918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.180542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775337.196177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.211779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.227404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.243140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775337.258665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.274357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.289931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775338.305537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.321169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.336797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.352404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775338.368022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.383665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.399287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.414919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775338.430530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.446189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.462002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775339.477404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.493139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.508668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.524320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775339.539933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.555532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.571158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.586770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775339.602421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.618068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.633654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775340.649284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.664932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.680522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.696177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775340.711793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.727396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.743110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.758653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775340.774259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.789959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.805566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775341.821153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.836788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.852401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.868020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775341.883644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.899297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.914887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.930527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775341.946148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775342.961810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775342.977403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775342.993058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775343.008667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775343.024304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775343.039923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775343.055536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775343.071159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775343.086781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775343.102418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775343.118031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.133720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.149337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775344.164956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.180539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.196227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.211773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775344.227450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.243147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.258650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.274281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775344.289899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.305633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.321159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775345.336787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.352409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.368025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.383671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775345.399307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.414923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.430522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.446159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775345.462028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.477459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.493113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775346.508654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.524282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.539940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.555516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775346.571146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.586771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.602430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.618016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775346.633648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.649326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.664907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775347.680540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.696178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.711780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.727398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775347.743082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.758648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.774272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.789895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775347.805523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.821285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.836796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775348.852429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.868039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.883669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.899313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775348.915010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.930988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.946159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.961798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775348.977412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775349.993148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775350.008659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775350.024298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775350.039937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775350.055527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775350.071147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775350.086788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775350.102412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775350.118026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775350.133651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775350.149275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.165013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.180536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775351.196160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.211772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.227389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.243069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775351.258647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.274278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.289889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.305538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775351.321141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.336880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.352425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775352.368036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.383678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.399289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.414928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775352.430540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.446166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.462065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.477416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775352.493055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.508701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.524293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775353.539934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.555554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.571166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.586774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775353.602421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.618013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.633666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.649268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775353.664929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.680577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.696176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775354.711787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.727404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.743039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.758658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775354.774270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.789918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.805546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.821150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775354.836784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775355.852607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775355.868086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775355.883664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775355.899316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775355.914927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775355.930525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775355.946152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775355.961788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775355.977405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775355.993070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775356.008685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.024327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.039947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775357.055528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.071155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.086780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.102409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775357.118028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.133650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.149271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.164894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775357.180517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.196196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.211779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775358.227403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.243024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.258646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.274265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775358.289894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.305535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.321149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.336771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775358.352389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.368041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.383652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775359.399294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.414908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.430533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.446142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775359.461971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.477391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.493025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.508652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775359.524270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.539945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.555527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775360.571148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.586787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.602407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.618012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775360.633632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.649262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.664887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.680513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775360.696138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.711803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.727391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775361.743028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.758647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.774258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.789888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775361.805532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.821144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.836760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.852394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775361.868011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775362.883767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775362.899304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775362.915016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775362.930532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775362.946164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775362.961785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775362.977413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775362.993034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775363.008669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775363.024303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775363.039957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.055563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.071157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775364.086851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.102420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.118045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.133656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775364.149271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.164886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.180541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.196147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775364.211792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.227421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.243031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775365.258645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.274267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.289912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.305530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775365.321141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.336762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.352389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.368000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775365.383647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.399377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.414919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775366.430524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.446167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.462029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.477410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775366.493309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.508678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.524280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.539919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775366.563046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.571187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.586810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775367.602424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.618037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.633647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.649278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775367.664907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.680531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.696148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.711796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775367.727398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.743055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.758650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775368.774358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.789919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.805536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.821171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775368.836778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.852405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.868026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.883767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775368.899281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775369.914949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775369.930527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775369.946174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775369.961790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775369.977391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775369.993015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775370.008664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775370.024293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775370.039919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775370.063001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775370.071143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.086899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.102443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775371.118106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.133638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.149258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.164961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775371.180534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.196163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.211793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.227398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775371.243035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.258690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.274277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775372.289902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.305532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.321151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.336768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775372.352396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.368017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.383655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.399277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775372.414920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.430627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.446161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775373.462000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.477392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.493035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.508661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775373.524278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.539907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.563012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.571144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775373.586771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.602504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.618031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775374.633658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.649297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.665010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.680641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775374.696352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.711796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.727504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.743138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775374.758766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.774365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.789906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775375.805665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.821158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.836778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.852411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775375.868022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.883659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.899285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.914903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775375.930521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775376.946339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775376.961865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775376.977483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775376.993026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775377.008661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775377.024295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775377.039915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775377.063005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775377.071151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775377.086794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775377.102402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.118072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.133648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775378.149269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.164903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.180523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.196152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775378.211783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.227388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.243015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.258644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775378.274269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.289951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.305539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775379.321145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.336768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.352405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.368019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775379.383657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.399269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.414918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.430518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775379.446157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.462032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.477397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775380.493023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.508661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.524282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.539909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775380.563031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.571156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.586763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.602398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775380.618042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.633667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.649265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775381.664889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.680518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.696137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.711792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775381.727384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.743008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.758635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.774254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775381.789888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.805703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.821231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775382.836848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.852383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.868014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.883659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775382.899261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.914902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.930508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.946218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775382.961766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775383.977449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775383.993026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775384.008687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775384.024293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775384.039973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775384.062942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775384.071160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775384.086830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775384.102391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775384.118080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775384.133643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.149303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.164904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775385.180551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.196140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.211792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.227386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775385.243028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.258650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.274263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.289904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775385.305510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.321190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.336776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775386.352409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.368015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.383653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.399262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775386.414914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.430512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.446148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.461988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775386.477384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.493121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.508729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775387.524427 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.540031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.563208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.571146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775387.586759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.602386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.618022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.633637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775387.649263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.664960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.680514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775388.696146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.711792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.727384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.743007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775388.758633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.774274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.789879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.805507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775388.821157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.836792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.852398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775389.868011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.883647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.899262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.914917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775389.930511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.946131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.961761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.977379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775389.993006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.008756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.024301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775391.039930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.063116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.071150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.086768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775391.102396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.118037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.133638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.149258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775391.164887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.180620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.196141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775392.211788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.227390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.243017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.258646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775392.274266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.289885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.305522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.321143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775392.336756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.352409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.368017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775393.383646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.399265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.414978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.430511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775393.446157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.461987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.477386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.493011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775393.508633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.524388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.539947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775394.555560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.571150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.586767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.602395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775394.618036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.633646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.649269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.664887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775394.680530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.696191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.711789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775395.727384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.743023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.758629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.774258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775395.789880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.805513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.821165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.836765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775395.852385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775396.868043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775396.883639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775396.899273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775396.914946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775396.930523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775396.946143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775396.961786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775396.977393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775396.993005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775397.008633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775397.024293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.042340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.055602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775398.071226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.086794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.102384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.118041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775398.133633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.149265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.164883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.180514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775398.196130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.211848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.227408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775399.243059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.258648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.274262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.289886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775399.305511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.321209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.336887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.352422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775399.368234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.383946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.399381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775400.415032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.430695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.446249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.462250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775400.477498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.493124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.508899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.524452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775400.540131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.555641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.571224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775401.586887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.602450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.618046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.633667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775401.649257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.664907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.680507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.696172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775401.711840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.727625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.743072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775402.758648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.774491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.790029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.805901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775402.821399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.836846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.852457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.868089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775402.883733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775403.899352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775403.915113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775403.930527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775403.946223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775403.961779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775403.977569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775403.993201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775404.008713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775404.024405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775404.040354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775404.055585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.071219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.086835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775405.102395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.118044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.133637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.149273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775405.164886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.180529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.196143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.211782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775405.227411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.243112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.258751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775406.274274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.289898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.305509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.321150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775406.336767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.352376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.368006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.383727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775406.399265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.414972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.430512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775407.446151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.461982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.477387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.493019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775407.508642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.524303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.539917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.555519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775407.571134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.586796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.602399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775408.618052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.633646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.649265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.664882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775408.680517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.696143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.711757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.727406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775408.743006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.758708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.774269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775409.789898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.805530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.821181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.836753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775409.852381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.868005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.883632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.899256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775409.914893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775410.930522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775410.946138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775410.961769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775410.977388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775410.993006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775411.008634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775411.024294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775411.039907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775411.055510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775411.071127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775411.086761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.102401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.118045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775412.133640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.149271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.164884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.180521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775412.196130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.211754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.227396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.242999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775412.258636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.274277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.289898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775413.305524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.321174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.336761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.352380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775413.368004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.383645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.399253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.414898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775413.430522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.446195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.462006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775414.477413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.493030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.508653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.524346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775414.539917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.555511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.571149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.586761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775414.602391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.618172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.633637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775415.649265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.664901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.680510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.696133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775415.711763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.727406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.743007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.758632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775415.774257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.789943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.805526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775416.821159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.836768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.852396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.868004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775416.883630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.899255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.914892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.930517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775416.946127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775417.961812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775417.977393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775417.993002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775418.008641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775418.024310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775418.039916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775418.055520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775418.071149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775418.086801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775418.102391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775418.118022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.133669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.149264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775419.164893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.180525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.196170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.211761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775419.227414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.243002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.258634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.274251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775419.289880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.305565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.321157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775420.336769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.352390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.368024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.383625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775420.399250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.414902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.430533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.446124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775420.461980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.477413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.493011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775421.508652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.524280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.539921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.555517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775421.571136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.586772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.602386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.618008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775421.633667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.649295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.664885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775422.680512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.696134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.711765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.727400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775422.743011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.758640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.774265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.789885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775422.805514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.821243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.836772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775423.852386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.868007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.883627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.899250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775423.914873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.930517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.946130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.961763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775423.977377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775424.993038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775425.008635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775425.024294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775425.039920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775425.055502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775425.071131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775425.086769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775425.102379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775425.118007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775425.133644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775425.149249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.164979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.180562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775426.196146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.211804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.227401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.243024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775426.258797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.274327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.289888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.305499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775426.321124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.336839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.352384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775427.368006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.383651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.399252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.414931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775427.430522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.446136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.462005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.477392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775427.493149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.508752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.524287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775428.539920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.555529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.571136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.586759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775428.602377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.618001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.633664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.649252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775428.664876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.680567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.696131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775429.711760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.727398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.743016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.758648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775429.774255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.789875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.805510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.821126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775429.836771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775430.852422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775430.868049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775430.883631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775430.899257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775430.914888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775430.930991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775430.946146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775430.961764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775430.977386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775430.993006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775431.008627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.024332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.039915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775432.055582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.071128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.086820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.102373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775432.118008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.133639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.149250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.164871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775432.180519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.196185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.211753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775433.227390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.242998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.258616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.274242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775433.289867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.305495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.321124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.336771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775433.352373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.368181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.383636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775434.399256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.414903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.430526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.446126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775434.461969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.477373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.493006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.508635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775434.524421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.540057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.555684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775435.571266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.586776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.602383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.618003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775435.633782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.649256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.664886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.680515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775435.696134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.711875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.727421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775436.743025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.758756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.774262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.789878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775436.805507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.821127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.836769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.852392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775436.868003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775437.883674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775437.899258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775437.914887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775437.930620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775437.946144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775437.961840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775437.977377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775437.992998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775438.008628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775438.024272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775438.039912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.055594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.071203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775439.086845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.102391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.118078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.133723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775439.149324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.164941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.180567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.196207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775439.211816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.227510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.243007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775440.258684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.274261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.289885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.305509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775440.321129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.336777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.352368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.368012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775440.383618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.399355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.414952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775441.430536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.446139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.461977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.477428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775441.493046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.508668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.524306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.539908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775441.555576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.571147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.586763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775442.602373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.617993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.633656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.649247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775442.664924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.680520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.696123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.711739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775442.727365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.743050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.758661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775443.774230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.789889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.805484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.821121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775443.836776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.852369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.867992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.883638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775443.899245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775444.914960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775444.931160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775444.946142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775444.961810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775444.977372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775444.993004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775445.008643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775445.024267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775445.039907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775445.055496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775445.071119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.086829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.102390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775446.118012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.133655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.149261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.164871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775446.180506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.196123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.211757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.227371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775446.243018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.258676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.274248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775447.289887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.305500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.321120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.336763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775447.352386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.367992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.383631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.399244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775447.414890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.431026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.446154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775448.461964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.477379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.493017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.508629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775448.524265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.539904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.555507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.571131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775448.586757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.602441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.618024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775449.633651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.649252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.664874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.680506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775449.696127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.711763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.727382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.743022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775449.758632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.774284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.789865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775450.805507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.821121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.836766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.852382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775450.868006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.883738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.899243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.914862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775450.930496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775451.946181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775451.961787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775451.977390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775451.992997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775452.008650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775452.024269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775452.039913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775452.055496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775452.071119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775452.086824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775452.102383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.118051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.133643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775453.149246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.164894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.180492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.196117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775453.211743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.227368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.243009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.258630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775453.274241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.289893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.305509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775454.321122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.336758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.352374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.368001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775454.383627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.399248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.414889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.430493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775454.446217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.462117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.477384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775455.493001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.508633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.524255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.539900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775455.555501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.571181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.586756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.602387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775455.618007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.633694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.649253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775456.664882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.680508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.696117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.711759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775456.727472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.743015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.758629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.774355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775456.789984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.805542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.821131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775457.836768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.852406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.867995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.883634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775457.899251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.914883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.930494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.946216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775457.961763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775458.977413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775458.993015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775459.008633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775459.024270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775459.039903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775459.055494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775459.071116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775459.086748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775459.102400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775459.118007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775459.133616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.149286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.164873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775460.180507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.196134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.211748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.227374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775460.243018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.258629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.274260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.289876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775460.305504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.321194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.336777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775461.352389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.368004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.383616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.399239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775461.414908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.430499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.446207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.461985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775461.477373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.493116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.508626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775462.524255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.539898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.555518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.571126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775462.586751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.602390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.618002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.633621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775462.649337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.664908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.680498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775463.696116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.711756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.727362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.743010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775463.758616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.774237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.789868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.805491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775463.821118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.836825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.852421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775464.868007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.883619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.899266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.914884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775464.930496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.946218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.961757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.977370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775464.992995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.008745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.024275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775466.039937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.055499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.071119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.086755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775466.102387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.118014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.133616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.149324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775466.164863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.180690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.196164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775467.211752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.227371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.243014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.258629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775467.274251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.289871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.305497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.321122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775467.336759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.352430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.368036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775468.383630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.399298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.414905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.430500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775468.446250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.461966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.478280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.492986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775468.508625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.524318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.539911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775469.555607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.571160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.586740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.602373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775469.617990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.633725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.649461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.664875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775469.680591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.696331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.711740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775470.727374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.743017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.758622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.774244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775470.789873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.805502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.821126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.836740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775470.852490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775471.868063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775471.883623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775471.899242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775471.914878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775471.930485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775471.946221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775471.961751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775471.977364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775471.992998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775472.008622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775472.024288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.039941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.055502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775473.071128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.086754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.102376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.118007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775473.133616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.149322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.164864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.180490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775473.196114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.211779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.227377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775474.243007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.258616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.274225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.289864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775474.305499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.321111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.336730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.352469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.367989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775474.383638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775474.399277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775474.414905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775474.430516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775474.446132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775475.462102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775475.477365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775475.492998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775475.508636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775475.524238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775475.539882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775475.563029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775475.571111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775475.586731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775475.602389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775475.617981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.633664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.649354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775476.664877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.680497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.696123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.711736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775476.727365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.742987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.758635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.774233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775476.789874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.805525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.821125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775477.836755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.852479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.867979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.883608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775477.899239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.914872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.930484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.946111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775477.961753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775478.977412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775478.993002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775479.008655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775479.024259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775479.039902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775479.055532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775479.071109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775479.086744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775479.102376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775479.118005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775479.133607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.149495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.164970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775480.180494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.196224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.211739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.227363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775480.242987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.258628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.274239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.289862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775480.305492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.321166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.336759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775481.352490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.367988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.383643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.399235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775481.414890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.430491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.446111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.461957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775481.477356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.493081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.508627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775482.524249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.539897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.555499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.571118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775482.586733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.602370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.617996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.633613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775482.649244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.664908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.680496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775483.696153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.711740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.727362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.742990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775483.758640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.774237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.789861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.805494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775483.821115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.836791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.852472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775484.867996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.883613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.899237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.914850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775484.930490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.946102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.961761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.977355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775484.992976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.008693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.024268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775486.039906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.055633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.071116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.086899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775486.102497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.118127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.133790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.149311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775486.165004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.180576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.196127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775487.211743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.227364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.242990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.258625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775487.274247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.289860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.305483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.321114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775487.336734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.352512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.367988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775488.383615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.399253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.414879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.430504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775488.446121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.461985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.477373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.492987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775488.508758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.524392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.539939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775489.555710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.571129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.586818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.602407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775489.622621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.633696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.649324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.664951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775489.680718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.696410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.711836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775490.727450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.743069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.758710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.774406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775490.789860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.805493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.821287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.836898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775490.852586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775491.868055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775491.883615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775491.899249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775491.914852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775491.930488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775491.946106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775491.961752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775491.977357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775491.993077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775492.008618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775492.024263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.039931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.055507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775493.071116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.086766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.102462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.118018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775493.133614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.149225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.164867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.180479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775493.196118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.211797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.227373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775494.242997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.258668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.274227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.289861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775494.305490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.321103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.336777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.352465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.368015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775494.383624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775494.399260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775494.414902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775494.430502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775494.446133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775495.462089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775495.477389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775495.492996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775495.508639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775495.524261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775495.539887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775495.555496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775495.571168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775495.586733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775495.602456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775495.618005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.633677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.649252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775496.664888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.680484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.696153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.711748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775496.727363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.742988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.758615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.774338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775496.789864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.805569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.821131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775497.836742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.852448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.868012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.883613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775497.899233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.914865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.930482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.946140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775497.961738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775498.977418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775498.992998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775499.008613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775499.024263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775499.039891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775499.055482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775499.071121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775499.086744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775499.102444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775499.117992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775499.133629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.149305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.164884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775500.180507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.196110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.211752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.227364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775500.243004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.258628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.274265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.289861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775500.305489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.321194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.336742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775501.352441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.368007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.383608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.399240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775501.414886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.430483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.446146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.461964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775501.477388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.493033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.508615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775502.524251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.539902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.555493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.571134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775502.586732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.602426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.617980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.633622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775502.649255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.664918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.680488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775503.696120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.711740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.727358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.742977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775503.758620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.774260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.789853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.805474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775503.821099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.836811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.852425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775504.868008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.883612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.899231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.914858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775504.930509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.946109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.961741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.977405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775504.992980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.008641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.024263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775506.039879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.055496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.071125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.086747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775506.102407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.117992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.133606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.149226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775506.164850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.180554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.196130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775507.211736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.227375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.242964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.258610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775507.274263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.289851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.305476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.321106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775507.336730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.352450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.368004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775508.383626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.399243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.414890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.430498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775508.446111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.461962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.477374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.492985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775508.508615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.524296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.539915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775509.555495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.571137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.586747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.602407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775509.618297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.633614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.649248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.664873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775509.680506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.696144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.711734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775510.727367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.742997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.758607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.774250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775510.789864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.805480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.821107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.836793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775510.852405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775511.868185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775511.883698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775511.899289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775511.914925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775511.930485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775511.946109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775511.961732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775511.977370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775511.992987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775512.008614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775512.024263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.039955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.055560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775513.071129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.086746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.102381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.117985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775513.133602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.149227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.164859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.180496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775513.196108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.211769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.227370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775514.242973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.258615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.274247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.289847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775514.305496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.321122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.336728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.352357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775514.367957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.383753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.399292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775515.414888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.430489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.446110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.461974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775515.477377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.492974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.508597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.524228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775515.539889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.555552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.571136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775516.586733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.602369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.617991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.633603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775516.649244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.664861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.680502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.696100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775516.711738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.727392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.742990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775517.758612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.774259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.789854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.805481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775517.821105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.836727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.852357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.867975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775517.883629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775518.899270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775518.914865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775518.930477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775518.946100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775518.961729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775518.977371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775518.992973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775519.008609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775519.024255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775519.039874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775519.055492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.071170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.086796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775520.102369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.117983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.133617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.149231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775520.164854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.180493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.196101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.211724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775520.227370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.243022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.258618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775521.274243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.289848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.305475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.321111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775521.336729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.352348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.367969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.383619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775521.399232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.415055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.430531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775522.446118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.461952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.477380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.492977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775522.508772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.524250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.539872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.555480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775522.571103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.586780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.602499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775523.617986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.633639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.649253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.664974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775523.680514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.696121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.711723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.727374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775523.743002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.758670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.774261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775524.789865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.805482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.821106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.836730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775524.852352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.867976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.883631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.899231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775524.914853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775525.930660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775525.946172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775525.961738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775525.977376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775525.992997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775526.008616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775526.024307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775526.039890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775526.055474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775526.071097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775526.086804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.102407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.118019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775527.133605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.149240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.164857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.180495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775527.196194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.211730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.227349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.242985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775527.258602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.274287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.289870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775528.305481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.321111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.336733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.352359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775528.367973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.383620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.399232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.414887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775528.430479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.446138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.461943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775529.477368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.492972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.508605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.524231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775529.539901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.555506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.571124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.586744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775529.602361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.618028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.633620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775530.649257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.664853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.680494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.696103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775530.711730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.727355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.742995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.758595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775530.774205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.789889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.805478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775531.821115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.836725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.852431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.867970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775531.883626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.899218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.914859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.930473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775531.946113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775532.961864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775532.977370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775532.993057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775533.008612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775533.024253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775533.039887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775533.055472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775533.071106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775533.086753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775533.102343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775533.117976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.133690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.149233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775534.165085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.180516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.196111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.211739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775534.227504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.243005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.258671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.274234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.289893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775534.305518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775534.321145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775534.336747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775534.352369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775534.367992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775535.383684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775535.399236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775535.414894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775535.430483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775535.446112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775535.461968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775535.477355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775535.492994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775535.508611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775535.524339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775535.539892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.555561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.571106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775536.586744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.602357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.617971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.633611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775536.649220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.664849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.680477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.696124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775536.711724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.727393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.742974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775537.758601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.774231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.789861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.805481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775537.821099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.836734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.852356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.867968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775537.883610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775538.899314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775538.914847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775538.930467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775538.946096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775538.961723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775538.977345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775538.992978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775539.008602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775539.024245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775539.039878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775539.062650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.071121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.086803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775540.102337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.117979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.133586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.149214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775540.164842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.180462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.196114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.211716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775540.227343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.243003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.258608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775541.274233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.289856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.305465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.321088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775541.336711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.352336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.367956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.383607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775541.399227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.414973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.430489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775542.446107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.461953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.477346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.492987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775542.508598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.524224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.539876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.562475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775542.571098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.586758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.602346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775543.617978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.633592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.649235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.664844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775543.680464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.696132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.711793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.727343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775543.743037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.758636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.774244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775544.789871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.805472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.821137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.836719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775544.852345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.867971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.883609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.899237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775544.914837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775545.930491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775545.946175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775545.961733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775545.977357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775545.992997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775546.008611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775546.024230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775546.039864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775546.062586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775546.071094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775546.086725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.102480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.117985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775547.133605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.149222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.164855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.180480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775547.196123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.211741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.227371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.242977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775547.258609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.274275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.289870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775548.305487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.321096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.336734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.352341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775548.368180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.383609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.399239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.414867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775548.430464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.446164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.462021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775549.477352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.493000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.508598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.524214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775549.539874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.562743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.571098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.586712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775549.602355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.618030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.633610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775550.649230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.664846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.680481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.696115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775550.711735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.727354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.742980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.758591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775550.774236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.789974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.805513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775551.821100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.836724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.852355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.867972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775551.883614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.899242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.914846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.930469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775551.946091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775552.961813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775552.977357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775552.993009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775553.008614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775553.024253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775553.039902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775553.062786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775553.071115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775553.086746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775553.102368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775553.117977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.133654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.149227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775554.164846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.180484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.196113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.211723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775554.227338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.242963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.258604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.274224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775554.289838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.305564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.321113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775555.336882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.352510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.368362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.383714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775555.399255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.414876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.430468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.446097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775555.461960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.477529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.493367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775556.508620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.524336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.539977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.562854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775556.571094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.586753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.602362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.617975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775556.633594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.649410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.664936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775557.680564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.696122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.711751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.727345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775557.742973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.758684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.774305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.789853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775557.805486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.821224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.836752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775558.852339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.867975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.883596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.899229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775558.914846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.930460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.946081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.961713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775558.977333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775559.993123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775560.008672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775560.024332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775560.039881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775560.062839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775560.071090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775560.086771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775560.102360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775560.117998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775560.133597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775560.149214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.164877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.180469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775561.196105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.211714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.227341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.242965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775561.258582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.274205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.289829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.305482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775561.321087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.336822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.352346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775562.367958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.383605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.399220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.414857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775562.430461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.446088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.461932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.477329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775562.492951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.508701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.524328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775563.542225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.555560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.571139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.586724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775563.602435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.617963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.633586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.649228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775563.664844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.680514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.696127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775564.711721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.727307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.742972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.758603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775564.774210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.789839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.805490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.821108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775564.836714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775565.852405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775565.867976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775565.883592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775565.899285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775565.914886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775565.931065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775565.946110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775565.961738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775565.977354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775565.992972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775566.008621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.024292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.039864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775567.055474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.071092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.086714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.102359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775567.117968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.133586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.149211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.164829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775567.180557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.196158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.211729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775568.227347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.242982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.258611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.274222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775568.289851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.305486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.321096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.336711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775568.352342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.368011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.383615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775569.399239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.414873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.430474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.446102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775569.461965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.477350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.492963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.508606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775569.524228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.539920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.555489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775570.571098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.586711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.602568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.617984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775570.633583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.649206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.664855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.680457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775570.696098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.711776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.727347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775571.742972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.758617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.774203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.789837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775571.805549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.821090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.836713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.852332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775571.867968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775572.883643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775572.899234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775572.914855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775572.930473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775572.946098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775572.961714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775572.977357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775572.992966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775573.008616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775573.024229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775573.039869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.055516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.071100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775574.086730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.102366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.117986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.133594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775574.149221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.164853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.180466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.196104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775574.211738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.227413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.242957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775575.258688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.274223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.289830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.305477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775575.321093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.336711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.352335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.368050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775575.383673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.399330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.415006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775576.430476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.446088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.461998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.477358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775576.492972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.508613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.524222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.539862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775576.555462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.571132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.586723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775577.602360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.617959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.633593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.649224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775577.664859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.680473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.696093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.711742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775577.727352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.743010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.758609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775578.774231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.789843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.805638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.821100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775578.836713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.852337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.867963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.883593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775578.899222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775579.914973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775579.930963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775579.946115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775579.961731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775579.977352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775579.993459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775580.008621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775580.024402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775580.039899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775580.055512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775580.071139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.086987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.102435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775581.118000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.133604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.149223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.165032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775581.180465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.196254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.211928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.227527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775581.243087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.258643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.274231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775582.289842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.305496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.321163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.336724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775582.352344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.367964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.383596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.399219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775582.414871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.430499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.446093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775583.461930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.477336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.492966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.508605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775583.524226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.539856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.555478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.571083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775583.586696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.602404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.617962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775584.633607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.649213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.664839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.680472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775584.696103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.711732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.727356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.742972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775584.758591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.774288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.789847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775585.805488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.821102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.836714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.852340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775585.867978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.883593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.899232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.914855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775585.930901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775586.946260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775586.961729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775586.977345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775586.992963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775587.008635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775587.024243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775587.039885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775587.055460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775587.071080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775587.086719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775587.102336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.118031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.133593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775588.149215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.164848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.180465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.196105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775588.211739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.227341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.242970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.258620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775588.274213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.289880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.305501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775589.321103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.336716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.352335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.368034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775589.383582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.399212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.414863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.430458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775589.446097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.462050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.477349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775590.492953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.508608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.524209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.539859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775590.555475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.571084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.586711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.602334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775590.617990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.633638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.649217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775591.664836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.680465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.696092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.711721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775591.727351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.742966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.758597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.774226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775591.789829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.805525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.821098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775592.836709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.852328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.867961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.883598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775592.899209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.914871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.930462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.946093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775592.961713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775593.977387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775593.992966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775594.008610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775594.024255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775594.039862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775594.055460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775594.071082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775594.086711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775594.102346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775594.117987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775594.133582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.149254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.164835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775595.180459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.196085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.211762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.227357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775595.242965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.258593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.274235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.289833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775595.305471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.321151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.336722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775596.352351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.367966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.383589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.399226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775596.414852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.430452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.446089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.461937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775596.477314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.492993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.508604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775597.524229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.539855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.555476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.571081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775597.586704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.602322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.617972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.633585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775597.649209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.664892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.680467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775598.696085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.711757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.727344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.742964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775598.758575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.774262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.789828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.805463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775598.821120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.836862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.852352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775599.867954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.883597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.899211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.914856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775599.930452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.946093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.961711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.977321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775599.992964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.008640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.024240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775601.039860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.055455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.071085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.086709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775601.102338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.117979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.133591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.149202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775601.164827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.180498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.196084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775602.211740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.227338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.242959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.258583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775602.274208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.289825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.305452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.321095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775602.336716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.352558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.367964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775603.383584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.399200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.414858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.430460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775603.446075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.461951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.477327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.492966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775603.508572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.524257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.539851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775604.555453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.571151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.586864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.602434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775604.618067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.633604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.649203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.664866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775604.680458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.696128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.711744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775605.727342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.742959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.758587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.774216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775605.789833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.805467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.821104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.836708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775605.852340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775606.868080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775606.883594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775606.899227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775606.914852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775606.930473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775606.946102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775606.961748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775606.977347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775606.992965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775607.008605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775607.024262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.039899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.055477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775608.071094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.086801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.102336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.118005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775608.133582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.149203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.164837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.180453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775608.196078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.211768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.227344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775609.242961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.258590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.274201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.289851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775609.305451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.321088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.336716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.352331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775609.367949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.383609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.399211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775610.414863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.430450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.446079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.461917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775610.477326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.492949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.508580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.524220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775610.539844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.555478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.571091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775611.586723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.602338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.617984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.633590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775611.649209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.664847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.680460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.696081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775611.711706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.727360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.742962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775612.758592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.774189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.789845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.805455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775612.821097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.836715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.852334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.867958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775612.883574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775613.899262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775613.914849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775613.930461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775613.946087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775613.961734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775613.977340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775613.993107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775614.008579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775614.024248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775614.039867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775614.055472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.071141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.086723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775615.102339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.117994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.133590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.149205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775615.164835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.180453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.196075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.211709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775615.227346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.243024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.258594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775616.274214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.289839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.305449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.321095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775616.336698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.352324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.367951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.383586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775616.399200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.415086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.430547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775617.446091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.461963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.477322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.492946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775617.508591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.524232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.539850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.555457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775617.571073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.586733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.602329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775618.617975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.633575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.649202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.664830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775618.680451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.696175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.711736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.727343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775618.742954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.758625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.774302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775619.789998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.805554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.821189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.836807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775619.852382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.867950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.883579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.899196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775619.914969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775620.930529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775620.946103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775620.961718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775620.977326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775620.992976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775621.008583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775621.024235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775621.039879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775621.055445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775621.071067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775621.086703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.102366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.117982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775622.133576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.149208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.164822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.180454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775622.196073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.211719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.227349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.242963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775622.258576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.274280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.289877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775623.305465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.321108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.336706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.352329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775623.367953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.383626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.399211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.414850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775623.430477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.446126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.461944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775624.477328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.492950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.508582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.524222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775624.539859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.555457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.571073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.586693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775624.602319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.618011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.633591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775625.649200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.664833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.680463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.696062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775625.711719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.727342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.742956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.758575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775625.774200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.789869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.805467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775626.821114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.836716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.852325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.867945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775626.883568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.899192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.914811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.930466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775626.946070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775627.961771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775627.977328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775627.992952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775628.008582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775628.024233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775628.039853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775628.055465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775628.071083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775628.086769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775628.102321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775628.117977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.133605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.149206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775629.164828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.180452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.196081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.211708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775629.227333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.242953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.258567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.274192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775629.289807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.305477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.321101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775630.336699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.352337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.367954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.383572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775630.399195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.414840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.430454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.446081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775630.461926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.477365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.492953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775631.508576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.524233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.539843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.555462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775631.571069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.586715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.602317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.617946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775631.633594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.649317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.664834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775632.680460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.696077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.711712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.727350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775632.742945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.758569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.774180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.789803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775632.805443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.821114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.836699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775633.852326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.867958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.883569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.899193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775633.914818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.930457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.946069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.961719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775633.977318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775634.992999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775635.008573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775635.024240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775635.039852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775635.055451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775635.071081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775635.086708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775635.102330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775635.117953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775635.133584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775635.149197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.164979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.180462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775636.196085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.211721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.227358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.242962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775636.258579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.274203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.289850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.305459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775636.321090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.336752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.352335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775637.367949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.383597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.399203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.414833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775637.430460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.446073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.461933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.477331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775637.493327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.508623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.524229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775638.539844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.555478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.571094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.586689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775638.602324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.617945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.633588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.649208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775638.664813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.680489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.696094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775639.711703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.727343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.742937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.758573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775639.774223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.789833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.805575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.821083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775639.836731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775640.852402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775640.867956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775640.883585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775640.899208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775640.914833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775640.930462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775640.946092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775640.961729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775640.977333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775640.993172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775641.008577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.024366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.039859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775642.063872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.071074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.086756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.102372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775642.117981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.133596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.149402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.164842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775642.180619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.196205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.211730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775643.227353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.242968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.258582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.274206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775643.289835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.305441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.321080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.336713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775643.352324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.368436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.383581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775644.399201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.414843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.430457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.446065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775644.461934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.477327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.492943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.508570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775644.524206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.539905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.563022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775645.571080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.586723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.602338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.617949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775645.633595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.649207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.664829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.680451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775645.696083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.711747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.727302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775646.742925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.758574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.774200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.789875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775646.805450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.821074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.836712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.852319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775646.867956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775647.883620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775647.899252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775647.914833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775647.930483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775647.946076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775647.961715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775647.977329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775647.992980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775648.008616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775648.024213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775648.039869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.055546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.071076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775649.086707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.102331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.117954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.133604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775649.149196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.164817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.180446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.196070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775649.211729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.227384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.242956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775650.258593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.274195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.289820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.305456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775650.321086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.336718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.352330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.367950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775650.383574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.399260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.414871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775651.430463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.446081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.462021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.477312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775651.492952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.508573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.524205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.539834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775651.555444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.571133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.586699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775652.602321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.617951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.633587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.649189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775652.664820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.680444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.696068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.711787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775652.727313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.742989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.758568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775653.774193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.789831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.805439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.821062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775653.836699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.852307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.867940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.883563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775653.899188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775654.914899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775654.930469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775654.946081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775654.961800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775654.977309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775654.992949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775655.008580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775655.024226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775655.039878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775655.055484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775655.071089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.086767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.102329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775656.117983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.133602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.149200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.164831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775656.180472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.196079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.211798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.227329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775656.242985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.258624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.274197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775657.289826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.305442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.321064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.336703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775657.352310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.367934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.383567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.399182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775657.414844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.430865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.446090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775658.462021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.477337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.492953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.508572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775658.524214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.539857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.555462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.571074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775658.586705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.602367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.617949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775659.633595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.649189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.664818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.680444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775659.696074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.711776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.727320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.742968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775659.758564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.774231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.789822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775660.805555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.821090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.836716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.852335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775660.867952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.883562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.899193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.914825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775660.930447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775661.946117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775661.961764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775661.977318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775661.992950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775662.008596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775662.024206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775662.039848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775662.055439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775662.071069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775662.086696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775662.102310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.117981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.133590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775663.149197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.164822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.180445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.196077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775663.211737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.227319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.242965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.258571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775663.274184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.289860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.305442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775664.321067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.336718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.352316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.367942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775664.383558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.399186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.414842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.430437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775664.446148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.462111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.477398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775665.493029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.508649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.524200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.539860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775665.555452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.571077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.586702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.602318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775665.617955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.633615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.649208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775666.664824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.680461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.701465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.711771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775666.727390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.742953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.758594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.774359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775666.789915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.805548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.821081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775667.836922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.852328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.868371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.885712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775667.899219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.914838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.930710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.946310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775667.961824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775668.977422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775668.992963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775669.008590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775669.024228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775669.039889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775669.055455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775669.071081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775669.086709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775669.102330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775669.117958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775669.133584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.149361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.164818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775670.180439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.196084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.211724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.227317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775670.242982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.258572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.274204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.289828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775670.305458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.321155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.336723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775671.352333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.367944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.383580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.399184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775671.414835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.430445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.446145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.461949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775671.477325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.492977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.508577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775672.524204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.539848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.555430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.571074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775672.586700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.602308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.617940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.633557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775672.649283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.664849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.680448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775673.696070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.711712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.727312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.742967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775673.758573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.774186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.789806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.805438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775673.821056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.836778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.852322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775674.867960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.883570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.899186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.914823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775674.930531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.946146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.961705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.977310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775674.992938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.008639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.024219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775676.039863 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.055446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.071069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.086778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775676.102323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.117954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.133577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.149285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775676.164818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.180655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.196156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775677.211708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.227321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.242954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.258572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775677.274185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.289814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.305433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.321054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775677.336683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.352359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.367950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775678.383570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.399192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.414818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.430434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775678.446211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.461901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.477315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.492943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775678.508566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.524220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.539857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775679.555442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.571074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.586688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.602317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775679.617936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.633558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.649266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.664806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775679.680433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.696105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.711698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775680.727322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.742965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.758564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.774169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775680.789804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.805429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.821054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.836684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775680.852391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775681.867998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775681.883638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775681.899268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775681.914822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775681.930447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775681.946179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775681.961766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775681.977382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775681.993087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775682.008655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775682.024303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.042304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.055459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775683.071077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.086713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.102315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.117949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775683.133582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.149287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.164822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.180443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775683.196072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.211746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.227329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775684.242987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.258567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.274198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.289801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775684.305435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.321053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.336712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.352392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775684.367929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.383598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.399204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775685.414951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.430545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.446259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.461887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775685.477342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.492935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.508576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.524196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775685.539836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.555478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.571068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775686.586698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.602312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.617935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.633575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775686.649274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.664831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.680437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.696066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775686.711695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.727448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.742978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775687.758561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.774192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.789801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.805440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775687.821054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.836700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.852400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.867932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775687.883573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775688.899217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775688.914813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775688.930429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775688.946153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775688.961689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775688.977309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775688.992944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775689.008666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775689.024210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775689.039846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775689.055454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.071090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.086693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775690.102319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.117937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.133567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.149282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775690.164821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.180435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.196069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.211692 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775690.227309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.242981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.258571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775691.274212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.289815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.305454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.321070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775691.336730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.352419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.367988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.383578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775691.399201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.414885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.430439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775692.446158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.461904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.477318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.492935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775692.508579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.524309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.539842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.555553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775692.571167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.586716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.602324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775693.617940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.633569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.649286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.664822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775693.680437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.696214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.711691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.727324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775693.742941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.758652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.774204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775694.789828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.805448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.821072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.836672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775694.852392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.867938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.883571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.899188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775694.914802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775695.930578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775695.946193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775695.961708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775695.977340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775695.992945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775696.008585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775696.024210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775696.040136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775696.055454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775696.071064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775696.086753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.102387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.117958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775697.133562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.149291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.164817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.180428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775697.196056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.211705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.227304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.242920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775697.258579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.274244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.289801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775698.305439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.321050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.336687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.352767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775698.367940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.383572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.399200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.414836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775698.430447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.446203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.461900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775699.477312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.492942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.508551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.524213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775699.539842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.555447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.571056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.586686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775699.602296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.617987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.633564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775700.649277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.664830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.680454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.696057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775700.711690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.727298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.742932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.758579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775700.774181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.789920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.805461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775701.821068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.836683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.852399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.867928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775701.883568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.899177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.914816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.930424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775701.946057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775702.961714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775702.977322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775702.992930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775703.008572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775703.024208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775703.039851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775703.055442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775703.071058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775703.086685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775703.102315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775703.117960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.133583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.149291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775704.164813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.180439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.196064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.211673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775704.227300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.242937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.258569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.274176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775704.289804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.305471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.321062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775705.336680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.352386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.367938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.383553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775705.399190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.414827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.430440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.446053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775705.461901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.477383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.492944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775706.508560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.524184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.539836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.555453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775706.571064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.586682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.602306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.617935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775706.633565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.649351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.664813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775707.680434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.696054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.711679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.727309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775707.742943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.758576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.774177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.789801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775707.805431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.821102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.836686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775708.852399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.867932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.883558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.899166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775708.914796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.930432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.946058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.961707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775708.977309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775709.993003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775710.008566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775710.024212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775710.039850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775710.055447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775710.071071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775710.086698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775710.102308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775710.117948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775710.133563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775710.149182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.164844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.180428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775711.196084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.211679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.227310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.242925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775711.258564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.274176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.289808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.305420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775711.321050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.336706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.352410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775712.367948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.383570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.399175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.414832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775712.430438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.446053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.461918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.477303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775712.492920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.508598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.524190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775713.539823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.555449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.571051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.586677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775713.602300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.617930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.633577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.649181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775713.664811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.680480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.696049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775714.711670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.727302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.742922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.758557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775714.774163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.789792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.805428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.821053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775714.836678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775715.852471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775715.867944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775715.883742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775715.899188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775715.914904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775715.930431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775715.946178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775715.961815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775715.977311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775715.992943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775716.008566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.024224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.039834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775717.055458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.071042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.086662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.102302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775717.117939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.133566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.149187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.164815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775717.180425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.196101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.211680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775718.227306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.242932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.258572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.274178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775718.289815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.305411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.321045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.336671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775718.352295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.367968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.383561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775719.399185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.414826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.430452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.446053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775719.461884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.477293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.492920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.508556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775719.524173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.539914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.555449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775720.571062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.586684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.602297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.617923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775720.633549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.649186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.664824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.680418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775720.696050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.711718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.727301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775721.742931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.758572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.774173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.789796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775721.805423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.821045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.836669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.852292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775721.867933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775722.883598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775722.899183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775722.914821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775722.930434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775722.946047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775722.961695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775722.977304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775722.992915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775723.008550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775723.024199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775723.039820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.055488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.071065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775724.086747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.102318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.117930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.133543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775724.149180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.164826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.180418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.196037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775724.211669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.227393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.242935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775725.258588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.274186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.289808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.305424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775725.321057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.336683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.352298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.367937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775725.383550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.399223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.414807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775726.430433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.446051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.461928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.477298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775726.492923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.508539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.524192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.539812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775726.562959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.571094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.586683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775727.602298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.617928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.633549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.649179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775727.664826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.680413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.696048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.711662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775727.727296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.743027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.758582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775728.774255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.789880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.805496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.821147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775728.836683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.852312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.867956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.883713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775728.899190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775729.914913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775729.930434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775729.946061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775729.961717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775729.977306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775729.992938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775730.008548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775730.024201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775730.039826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775730.062912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775730.071070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.086841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.102372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775731.117943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.133577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.149209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.164836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775731.180451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.196101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.211699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.227342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775731.242972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.258649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.274191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775732.289804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.305433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.321060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.336678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775732.352304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.367945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.383537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.399182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775732.414837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.430656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.446203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775733.462048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.477441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.492975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.508578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775733.524184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.539813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.555420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.571063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775733.586662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.602342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.617936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775734.633557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.649180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.664910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.680420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775734.696049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.711668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.727295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.742918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775734.758550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.774236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.789812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775735.805616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.821060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.836681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.852308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775735.867944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.883545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.899180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.914802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775735.930420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775736.946268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775736.961711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775736.977309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775736.992931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775737.008571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775737.024220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775737.039842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775737.055425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775737.071081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775737.086687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775737.102295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.117987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.133562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775738.149183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.164820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.180432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.196064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775738.211685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.227299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.242919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.258563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775738.274187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.289824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.305424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775739.321056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.336671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.352297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.367937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775739.383541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.399173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.414812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.430424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775739.446051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.461916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.477307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775740.492914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.508598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.524168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.539825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775740.555436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.571056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.586670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.602305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775740.617915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.633590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.649175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775741.664818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.680454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.696045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.711674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775741.727292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.742916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.758557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.774186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775741.789820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.805456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.821044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775742.836671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.852291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.867929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.883563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775742.899161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.914785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.930410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.946041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775742.961662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775743.977401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775743.992931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775744.008540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775744.024184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775744.039813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775744.055412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775744.071056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775744.086721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775744.102290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775744.117910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775744.133529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.149207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.164817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775745.180412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.196052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.211666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.227289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775745.242917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.258526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.274208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.289771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775745.305417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.321063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.336676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775746.352286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.367940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.383532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.399163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775746.414806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.430423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.446038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.461875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775746.477312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.493032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.508579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775747.524190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.539855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.555550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.571073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775747.586679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.602298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.617924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.633570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775747.649182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.664873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.680427 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775748.696051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.711675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.727293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.742912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775748.758551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.774234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.789796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.805413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775748.821047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.836729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.852406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775749.867944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.883566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.899190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.914795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775749.930405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.946040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.961671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.977315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775749.992928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.008583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.024192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775751.039826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.055426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.071061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.086666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775751.102282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.117909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.133533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.149158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775751.164782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.180449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.196049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775752.211678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.227359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.242927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.258542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775752.274172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.289793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.305418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.321038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775752.336662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.352323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.367933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775753.383542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.399165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.414804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.430411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775753.446062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.461866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.477314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.492926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775753.508534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.524366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.539864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775754.555431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.571078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.586682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.602283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775754.617908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.633545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.649161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.664796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775754.680423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.696096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.711810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775755.727297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.742951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.758558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.774255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775755.789841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.805436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.821066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.836678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775755.852299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775756.868007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775756.883587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775756.899167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775756.914796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775756.930415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775756.946036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775756.961671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775756.977287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775756.992910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775757.008550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775757.024182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.039867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.055471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775758.071081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.086697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.102334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.117926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775758.133549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.149164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.164786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.180424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775758.196041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.211727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.227325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775759.242925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.258558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.274191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.289789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775759.305408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.321052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.336735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.352302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775759.367915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.383740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.399494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775760.414862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.430926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.446142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.461888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775760.477315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.493270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.508635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.524269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775760.541067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.555474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.571086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775761.586675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.602290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.617929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.633546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775761.649172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.664791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.680437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.696053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775761.711665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.727378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.742925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775762.758551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.774223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.789776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.805582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775762.821124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.836675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.852330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.867932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775762.883548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775763.899342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775763.914966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775763.930423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775763.946099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775763.961677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775763.977327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775763.993079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775764.008809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775764.024251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775764.039840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775764.055430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.071150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.086695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775765.102291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.117936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.133540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.149181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775765.164796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.180438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.196049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.211671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775765.227297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.242983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.258542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775766.274181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.289835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.305424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.321065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775766.336678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.352302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.368304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.383573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775766.399182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.414929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.430423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775767.446047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.461923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.477304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.492927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775767.508540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.524175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.539816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.555433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775767.571054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.586729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.602301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775768.617941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.633548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.649167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.664797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775768.680433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.696041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.711675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.727302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775768.742922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.758579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.774187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775769.789817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.805413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.821058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.836679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775769.852281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.867928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.883566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.899159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775769.914792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775770.930473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775770.946052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775770.961679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775770.977307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775770.992918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775771.008550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775771.024201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775771.039816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775771.055426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775771.071058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775771.086729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.102319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.117921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775772.133542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.149174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.164788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.180425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775772.196033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.211660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.227285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.242913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775772.258541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.274212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.289787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775773.305424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.321052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.336659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.352285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775773.367908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.383553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.399182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.414805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775773.430439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.446096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.461889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775774.477312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.492930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.508587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.524339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775774.539838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.555432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.571068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.586698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775774.602301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.617960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.633653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775775.649178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.664813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.680430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.696051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775775.711670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.727306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.742920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.758541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775775.774164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.789833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.805405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775776.821065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.836664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.852293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.867914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775776.883563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.899172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.914800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.930475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775776.946031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775777.961712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775777.977302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775777.992914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775778.008554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775778.024181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775778.039811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775778.055415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775778.071075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775778.086688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775778.102271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775778.117914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.133573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.149152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775779.164792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.180421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.196058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.211653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775779.227273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.242902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.258540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.274150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775779.289792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.305485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.321073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775780.336659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.352294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.367903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.383562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775780.399171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.414805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.430410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.446039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775780.461928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.477324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.492915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775781.508543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.524168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.539801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.555417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775781.571047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.586666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.602280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.617905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775781.633527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.649179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.664788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775782.680428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.696031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.711651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.727273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775782.742926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.758531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.774138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.789795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775782.805399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.821093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.836659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775783.852356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.867906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.883616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.899158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775783.914783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.930468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.946110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.961670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775783.977278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775784.992938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775785.008522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775785.024183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775785.039808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775785.055407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775785.071036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775785.086681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775785.102273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775785.117909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775785.133535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775785.149150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.164848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.180434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775786.196055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.211660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.227298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.242917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775786.258537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.274156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.289797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.305421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775786.321046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.336709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.352287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775787.367918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.383603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.404432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.414803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775787.430699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.446038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.461899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.477275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775787.493031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.508642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.524183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775788.539821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.555417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.571051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.586691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775788.602346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.617908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.633542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.649225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775788.664786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.680532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.696044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775789.711666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.727291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.742922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.758545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775789.774232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.789854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.805496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.821155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775789.836672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775790.852364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775790.867922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775790.883761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775790.899158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775790.914783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775790.930408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775790.946049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775790.961653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775790.977275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775790.992918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775791.008529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.024243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.039816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775792.055473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.071044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.086727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.102279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775792.117914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.133525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.149131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.164770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775792.180398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.196073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.211656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775793.227297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.242912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.258525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.274148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775793.289788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.305395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.321035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.336650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775793.352272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.367945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.383565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775794.399167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.414809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.430401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.446033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775794.461891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.477278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.492921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.508550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775794.524158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.539950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.555425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775795.571045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.586677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.602286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.617913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775795.633538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.649154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.664779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.680399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775795.696051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.711713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.727296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775796.742920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.758536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.774167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.789793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775796.805401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.821040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.836662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.852286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775796.867909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775797.883616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775797.899153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775797.914790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775797.930843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775797.946050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775797.961665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775797.977283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775797.992930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775798.008537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775798.024187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775798.039823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.055501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.071061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775799.086694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.102296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.117925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.133546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775799.149164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.164780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.180412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.196058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775799.211667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.227318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.242916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775800.258531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.274159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.289794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.305402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775800.321064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.336658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.352276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.367894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775800.383537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.399183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.414813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775801.430412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.446031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.461858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.477274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775801.492919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.508526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.524158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.539796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775801.562884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.571065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.586676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775802.602282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.617915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.633523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.649149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775802.664773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.680396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.696041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.711650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775802.727277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.742946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.758548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775803.774173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.789796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.805404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.821038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775803.836647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.852273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.867910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.883534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775803.899162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775804.914812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775804.930413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775804.946028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775804.961664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775804.977278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775804.992922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775805.008524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775805.024168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775805.039803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775805.062810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775805.071032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775805.086654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775805.102320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775805.117947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775805.133540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775805.149167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775806.164818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775806.180404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775806.196045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775806.211660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775806.227276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775806.242906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775806.258522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775806.274142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775806.289765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775806.305422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775806.321134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.336706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.352288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775807.367905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.383575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.399167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.414797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775807.430397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.446044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.461869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.477273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775807.492912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.508542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.524164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775808.539789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.555407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.571116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.586640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775808.602286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.617889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.633515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.649143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775808.664767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.680439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.696052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775809.711648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.727277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.742892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.758515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775809.774142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.789761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.805407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.821106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775809.836640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775810.852304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775810.867893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775810.883519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775810.899182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775810.914768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775810.930395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775810.946025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775810.961644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775810.977264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775810.992892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775811.008534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.024207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.039806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775812.062583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.071111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.086731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.102283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775812.117912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.133526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.149140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.164772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775812.180392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.196076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.211649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775813.227280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.242912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.258543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.274144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775813.289766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.305408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.321095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.336648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775813.352266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.367923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.383544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775814.399163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.414811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.430392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.446022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775814.461851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.477262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.492896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.508531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775814.524207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.539926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.563533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775815.571123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.586663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.602292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.617896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775815.633511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.649152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.664787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.680421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775815.696025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.711723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.727279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775816.742922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.758533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.774159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.789772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775816.805528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.821096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.836658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.852293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775816.867911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775817.883569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775817.899170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775817.914840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775817.930436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775817.946075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775817.961665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775817.977274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775817.992898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775818.008554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775818.024182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775818.040076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.055424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.071088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775819.086665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.102295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.117910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.133522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775819.149146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.164954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.180409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.196053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775819.211663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.227330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.242893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775820.258517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.274145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.289766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.305405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775820.321069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.336639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.352271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.367894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775820.383525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.399308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.414808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775821.430392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.446024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.461928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.477285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775821.492892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.508542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.524153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.539799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775821.555396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.571090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.586657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775822.602297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.617909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.633524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.649145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775822.664774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.680407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.696018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.711673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775822.727273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.743014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.758532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775823.774142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.789783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.805412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.821048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775823.836644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.852276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.867895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.883521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775823.899145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775824.914798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775824.930390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775824.946021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775824.961659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775824.977283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775824.992896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775825.008527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775825.024174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775825.039787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775825.055397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775825.071069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775825.086665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775825.102276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775825.117937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775825.133529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775825.149153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775826.164845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775826.180415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775826.196030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775826.211681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775826.227296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775826.242911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775826.258529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775826.274165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775826.289774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775826.305392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775826.321082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.336672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.352290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775827.367899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.383528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.399155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.414811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775827.430389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.446018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.461845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.477283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775827.492893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.508676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.524163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775828.539795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.555408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.571043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.586655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775828.602263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.617924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.633518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.649137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775828.664787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.680539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.696034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775829.711689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.727277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.743025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.758524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775829.774143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.789869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.805388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.821179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775829.836654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775830.852365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775830.867911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775830.883528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775830.899155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775830.914799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775830.930848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775830.946032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775830.961655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775830.977281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775830.992910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775831.008534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.024263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.039818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775832.055401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.071040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.086698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.102272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775832.117965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.133513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.149163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.164765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775832.180394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.196056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.211673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775833.227273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.242916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.258524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.274155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775833.289768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.305387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.321054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.336641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775833.352270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.367954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.383552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775834.399170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.414796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.430392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.445997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775834.461854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.477285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.492894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.508520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775834.524230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.539913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.555592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775835.571047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.586648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.602274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.617906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775835.633626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.649140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.664778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.680492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775835.696019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.711707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.727278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775836.742910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.758530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.774164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.789816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775836.805396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.821058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.836651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.852267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775836.867893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775837.883592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775837.899156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775837.914798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775837.930385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775837.946029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775837.961661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775837.977273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775837.992893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775838.008515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775838.024182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775838.039805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.055440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.071032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775839.086666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.102269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.117914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.133530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775839.149200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.164750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.180401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.196017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775839.211641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.227336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.242896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775840.258532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.274153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.289768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.305379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775840.321047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.336635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.352380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.367893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775840.383515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.399198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.414803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775841.430395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.446010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.461860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.477285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775841.493259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.508520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.524278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.539840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775841.555395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.571085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.586656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775842.602270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.617913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.633515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.649151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775842.664768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.680388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.696018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.711642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775842.727282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.742938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.758536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775843.774146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.789781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.805395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.821033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775843.836643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.852260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.867898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.883519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775843.899141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775844.914798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775844.930975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775844.946022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775844.961660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775844.977278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775844.992902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775845.008518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775845.024182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775845.039801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775845.055400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775845.071024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.086685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.102269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775846.117911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.133540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.149147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.164772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775846.180434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.196023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.211646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.227279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775846.242905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.258595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.274153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775847.289780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.305397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.321041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.336640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775847.352270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.367892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.383520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.399140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.414796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775847.789820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775847.805408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775847.821058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775847.836668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775847.852299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775848.430513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775848.446142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775848.462016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775848.477331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775848.493082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775848.508596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775848.524256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775848.539881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775848.555479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775848.571115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775848.586735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.602344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.617922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775849.633525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.649162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.664777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.680410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775849.696213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.711653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.727300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.742903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775849.758521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.774693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.789901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775850.805601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.821063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.836673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.852285 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775850.867943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.883717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.899379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.914939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775850.930514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775851.946104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775851.961673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775851.977272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775851.992906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775852.008524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775852.024188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775852.039799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775852.055473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775852.071030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775852.086709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775852.102262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.117936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.133538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775853.149141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.164772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.180399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.196015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775853.211637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.227280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.242897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.258512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775853.274158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.289813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.305397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775854.321036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.336655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.352258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.367883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775854.383512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.399151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.414786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.430413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775854.446021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.461890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.477263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775855.492884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.508514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.524166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.539787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775855.555378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.571059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.586656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.602254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775855.617895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.633581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.649145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775856.664810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.680399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.696020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.711654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775856.727282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.742889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.758513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.774123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775856.789775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.805466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.821044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775857.836647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.852278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.867881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.883510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775857.899129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.914764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.930395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.946006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775857.961644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775858.977410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775858.992969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775859.008517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775859.024183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775859.039811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775859.055385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775859.071022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775859.086642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775859.102267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775859.117887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775859.133552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.149209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.164775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775860.180402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.196015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.211650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.227289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775860.242889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.258526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.274137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.289760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775860.305389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.321116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.336698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775861.352315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.367899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.383539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.399141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775861.414790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.430417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.446008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.461911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775861.477260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.492916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.508532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775862.524173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.539811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.555422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.571011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775862.586635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.602271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.617882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.633526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775862.649141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.664907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.680401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775863.696013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.711634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.727297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.742888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775863.758537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.774143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.789760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.805476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775863.821020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.836779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.852270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775864.867885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.883510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.899137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.914756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775864.930481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.946018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.961637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.977328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775864.992886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.008604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.024190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775866.039797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.055382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.071019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.086660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775866.102263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.117896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.133537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.149131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775866.164756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.180485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.196031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775867.211640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.227290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.242898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.258524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775867.274153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.289775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.305392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.321015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775867.336649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.352370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.367907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775868.383533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.399136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.414812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.430401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775868.446016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.461902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.477266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.492899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775868.508509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.524230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.539817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775869.555408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.571009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.586659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.602262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775869.617891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.633520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.649133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.664757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775869.680385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.696065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.711635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775870.727291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.742897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.758531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.774149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775870.789757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.805373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.821014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.836650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.852257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775870.867907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775870.883530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775870.899156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775870.914768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775870.930409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342775871.946067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775871.961652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775871.977270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775871.992898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775872.008524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775872.024166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775872.039810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775872.055390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775872.071020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775872.086728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775872.102257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.117940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.133529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775873.149144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.164769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.180399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.196014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775873.211652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.227264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.242913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.258529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775873.274144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.289790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.305402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775874.321173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.336672 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.352254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.367881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775874.383533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.399129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.414766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.430398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775874.446107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.462000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.477266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775875.492893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.508512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.524143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.539787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775875.555384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.571003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.586642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.602257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775875.617874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.633599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.649143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775876.664784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.680387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.696027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.711643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775876.727270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.742917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.758522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.774148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775876.789782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.805421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.821025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775877.836666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.852236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.867897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.883497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775877.899143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.914759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.930379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.946098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775877.961636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775878.977306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775878.992888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775879.008524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775879.024162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775879.039807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775879.055394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775879.071017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775879.086650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775879.102275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775879.117894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775879.133513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.149223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.164763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775880.180387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.196007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.211634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.227255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775880.242902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.258508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.274128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.289757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775880.305366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.321059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.336663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775881.352257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.367881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.383488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.399109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775881.414789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.430378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.446104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.461864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775881.477249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.492989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.508532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775882.524185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.555693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.571013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.587024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775882.602255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.617911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.633517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.649238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775882.664805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.680582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.696020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775883.711747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.727317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.742894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.758522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775883.774141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.789778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.805389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.821196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775883.836753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775884.852332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775884.867900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775884.883510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775884.899148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775884.914760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775884.930383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775884.946088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775884.961681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775884.977263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775884.993118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775885.008519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.024208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.039783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775886.055392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.071002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.086666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.102260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775886.117899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.133503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.149198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.164749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775886.180402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.196050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.211644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775887.227269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.242901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.258527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.274132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775887.289764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.305402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.321007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.336634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775887.352339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.368060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.383568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775888.399185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.414867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.430528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.446101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775888.461901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.477260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.492894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.508643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775888.524201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.539860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.555406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775889.571017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.586625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.602258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.617866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775889.633537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.649204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.664765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.680370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775889.695998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.711679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.727272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775890.742888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.758528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.774125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.789751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775890.805391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.820997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.836626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.852331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775890.867889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775891.883538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775891.899130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775891.914754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775891.930387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775891.946076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775891.961651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775891.977248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775891.992875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775892.008508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775892.024145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775892.039764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.055415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.071015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775893.086643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.102259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.117885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.133497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775893.149202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.164772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.180381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.195998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775893.211630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.227279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.242909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775894.258521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.274126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.289748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.305369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775894.320995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.336621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.352317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.367885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775894.383506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.399181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.414774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775895.430382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.446063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.461877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.477246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775895.492873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.508496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.524123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.539747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775895.555384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.571092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.586644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775896.602261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.617887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.633519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.649222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775896.664801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.680393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.696003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.711633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775896.727262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.742931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.758529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775897.774127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.789772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.805380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.821010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775897.836636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.852346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.867904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.883527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775897.899144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775898.914826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775898.930943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775898.946081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775898.961679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775898.977269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775898.992873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775899.008512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775899.024156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775899.039827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775899.055388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775899.071026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.086750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.102263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775900.117997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.133506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.149224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.164786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775900.180374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.195997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.211633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.227270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775900.242887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.258561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.274137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775901.289762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.305383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.321003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.336623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775901.352319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.367885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.383497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.399138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775901.414782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.430845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.446102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775902.461858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.477258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.492887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.508511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775902.524132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.539756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.555393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.571029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775902.586629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.602287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.617887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775903.633511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.649202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.664775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.680373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775903.696019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.711629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.727261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.742877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775903.758504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.774149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.789762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775904.805388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.821001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.836614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.852334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775904.867888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.883499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.899127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.914760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775904.930379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775905.946110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775905.961658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775905.977256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775905.992888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775906.008511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775906.024152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775906.039756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775906.055364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775906.071056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775906.086646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775906.102245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.118034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.133608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775907.149213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.164790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.180373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.196012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775907.211619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.227258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.242879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.258515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775907.274149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.289826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.305393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775908.321012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.336725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.352444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.367887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775908.383614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.399223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.414905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.430376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775908.446114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.461950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.477265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775909.492875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.508543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.524133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.539778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775909.555376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.571034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.586612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.602242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775909.617876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.633576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.649197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775910.664783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.680386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.695994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.711617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775910.727239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.742871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.758500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.774132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775910.789753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.805419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.821008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775911.836623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.852339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.867881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.883494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775911.899118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.914787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.930510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.946005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775911.961628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775912.977291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775912.992892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775913.008524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775913.024150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775913.039772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775913.055405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775913.071010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775913.086625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775913.102246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775913.117887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775913.133496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.149243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.164784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775914.180389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.195998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.211619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.227244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775914.242879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.258495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.274131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.289740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775914.305392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.321053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.336620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775915.352337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.367882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.383498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.399120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775915.414798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.430367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.445996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.461878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775915.477284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.492935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.508511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775916.524153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.539759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.555388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.571031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775916.586631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.602255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.617885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.633518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775916.649138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.664799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.680393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775917.696015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.711630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.727251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.742879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775917.758500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.774147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.789736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.805367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775917.820989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.836698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.852338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775918.867943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.883510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.899142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.914764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775918.930398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.945997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.961645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.977271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775918.992869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.008533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.024154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775920.039771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.055373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.071011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.086656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775920.102240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.117894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.133501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.149206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775920.164763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.180440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.196001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775921.211625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.227249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.242876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.258502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775921.274133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.289754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.305367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.320988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775921.336632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.352435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.367897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775922.383508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.399118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.414786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.430386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775922.446008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.461851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.477261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.492896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775922.508512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.524191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.539761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775923.555387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.571014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.586619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.602244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775923.617879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.633496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.649141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.664777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775923.688083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.696132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.711636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775924.727248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.742888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.758506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.774142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775924.789734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.805365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.820995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.836620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775924.852246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775925.867978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775925.883521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775925.899137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775925.914782 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775925.930400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775925.946015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775925.961626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775925.977269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775925.992895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775926.008510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775926.024159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.039813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.055386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775927.071014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.086638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.102255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.117894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775927.133501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.149131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.164777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.187708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775927.196012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.211657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.227249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775928.242868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.258517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.274154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.289751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775928.305380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.320992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.336616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.352279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775928.367867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.383542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.399126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775929.414769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.430382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.445989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.461815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775929.477263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.492865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.508505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.524118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775929.539764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.555464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.571017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775930.586622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.602254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.617869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.633488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775930.649109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.664755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.687897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.695983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775930.711606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.727307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.742885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775931.758496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.774152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.789745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.805375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775931.821013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.836620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.852313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.867879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775931.883509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775932.899166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775932.914755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775932.930838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775932.946004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775932.961640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775932.977261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775932.992868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775933.008490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775933.024133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775933.039755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775933.055362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.071040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.086629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775934.102244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.117892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.133496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.149110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775934.164765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.180391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.195994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.211612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775934.227250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.242916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.258525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775935.274146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.289765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.305375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.321008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775935.336627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.352254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.367876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.383515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775935.399141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.414810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.430385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775936.445993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.461974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.477263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.492876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775936.508504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.524133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.539732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.555366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775936.570991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.586649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.602251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775937.617868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.633502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.649118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.664755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775937.680384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.695989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.711624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.727231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775937.742859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.758565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.774148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775938.789746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.805385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.820999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.836629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775938.852242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.867868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.883505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.899121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775938.914739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775939.930856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775939.946011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775939.961635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775939.977266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775939.992879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775940.008507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775940.024153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775940.039764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775940.055377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775940.070995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775940.086709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.102411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.118199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775941.133509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.149124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.164790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.180446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775941.196003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.211660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.227264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.242900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775941.258561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.274218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.289753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775942.305367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.321002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.336612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.352256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775942.367882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.383513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.399120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.414771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775942.430383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.446040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.461859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775943.477269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.492881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.508485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.524133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775943.539731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.555397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.570989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.586630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775943.602236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.617911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.633508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775944.649121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.664769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.680411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.696010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775944.711607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.727237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.742861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.758490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775944.774204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.789819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.805373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775945.820990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.836623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.852231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.867892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775945.883516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.899113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.914738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.930389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775945.945981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775946.961759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775946.977269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775946.992865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775947.008495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775947.024143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775947.039776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775947.055373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775947.070996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775947.086646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775947.102249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775947.117868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.133601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.149125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775948.164766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.180397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.195998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.211611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775948.227271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.242855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.258487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.274124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775948.289812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.305404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.321001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775949.336616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.352243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.367937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.383510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775949.399111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.414765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.430380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.445985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775949.461838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.477320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.492868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775950.508488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.524115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.539735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.555356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775950.570987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.586625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.602237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.617859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775950.633490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.649137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.664770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775951.680397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.696004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.711617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.727237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775951.742881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.758486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.774116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.789746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775951.805369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.821028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.836619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775952.852243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.867868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.883518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.899105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775952.914760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.930384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.945986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.961609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775952.977233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775953.992885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775954.008514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775954.024147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775954.039766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775954.055368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775954.070999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775954.086630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775954.102231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775954.117872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775954.133486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775954.149117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.164820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.180438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775955.196017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.211623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.227240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.242869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775955.258491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.274116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.289779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.305357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775955.320985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.336742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.352226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775956.367873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.383522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.399116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.414769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775956.430387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.445991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.461891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.477237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775956.492879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.508536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.524124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775957.539729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.555353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.570998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.586629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775957.602228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.617856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.633479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.649107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775957.664754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.680466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.696009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775958.711617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.727245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.742880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.758512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775958.774119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.789755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.805381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.820996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775958.836611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775959.852317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775959.867876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775959.883515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775959.899120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775959.914753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775959.930375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775959.946003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775959.961631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775959.977254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775959.992884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775960.008481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.024173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.039754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775961.055360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.070986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.086633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.102243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775961.117879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.133486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.149112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.164761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775961.180378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.196033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.211623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775962.227244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.242870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.258498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.274107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775962.289768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.305362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.320983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.336627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775962.352243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.367895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.383505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775963.399111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.414764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.430470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.445987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775963.461819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.477230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.492884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.508477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775963.524131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.539758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.555363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775964.570985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.586623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.602229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.617859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775964.633481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.649102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.664773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.680454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775964.695997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.711633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.727252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775965.742870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.758498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.774105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.789742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775965.805352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.820976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.836603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.852223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775965.867856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775966.883543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775966.899119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775966.914735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775966.930451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775966.945991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775966.961618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775966.977233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775966.992865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775967.008485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775967.024130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775967.039749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.055392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.071004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775968.086697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.102241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.117889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.133484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775968.149103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.164765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.180448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.196000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775968.211600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.227314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.242877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775969.258495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.274129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.289758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.305367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775969.320985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.336629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.352229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.367854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775969.383490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.399185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.414794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775970.430506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.445983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.461849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.477265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775970.492871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.508491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.524117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.539729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775970.555369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.571041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.586644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775971.602225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.617857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.633505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.649112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775971.664745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.680424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.695992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.711598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775971.727247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.742888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.758494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775972.774116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.789757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.805361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.820983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775972.836663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.852240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.867869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.883481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775972.899131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775973.914764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775973.930435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775973.945990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775973.961612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775973.977235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775973.993074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775974.008484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775974.024141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775974.039747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775974.055367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775974.070977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.086741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.102257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775975.117874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.133513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.149125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.164763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775975.180425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.196027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.211617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.227239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775975.242872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.258544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.274125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775976.289761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.305368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.320991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.336635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775976.352245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.367866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.383496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.399138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775976.414787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.430446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.445997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775977.461829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.477254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.492873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.508480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775977.524128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.539736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.555355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.570979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775977.586612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.602358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.617868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775978.633496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.649120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.664771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.680400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775978.696009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.711606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.727240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.742856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775978.758482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.774165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.789753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775979.805369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.820990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.836617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.852227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775979.867855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.883483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.899123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.914735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775979.930394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775980.946042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775980.961622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775980.977237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775980.992907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775981.008489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775981.024124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775981.039865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775981.055362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775981.071068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775981.086624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775981.102257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.117930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.133499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775982.149140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.164770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.180405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.196006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775982.211606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.227240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.242865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.258487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775982.274119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.289800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.305359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775983.320981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.336622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.352245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.367856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775983.383477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.399121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.414750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.430382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775983.445994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.461858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.477243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775984.492877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.508491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.524113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.539727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775984.555377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.570978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.586603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.602249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775984.617849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.633536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.649110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775985.664760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.680481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.696003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.711608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775985.727244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.742864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.758580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.774102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775985.789828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.805496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.820987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775986.836606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.852231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.867846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.883473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775986.899114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.914731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.930354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.945983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775986.961604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775987.977271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775987.992882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775988.008487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775988.024146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775988.039753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775988.055358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775988.070987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775988.086682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775988.102251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775988.117864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775988.133512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.149145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.164773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775989.180386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.196001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.211618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.227230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775989.242848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.258480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.274108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.289724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775989.305372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.321038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.336613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775990.352230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.367862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.383493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.399133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775990.414765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.430355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.445980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.461816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775990.477232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.492906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.508495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775991.524113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.539735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.555367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.570974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775991.586601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.602269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.617847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.633481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775991.649115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.664807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.680431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775992.696122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.711602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.727239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.742866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775992.758483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.774127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.789732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.805374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775992.820991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.836639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.852230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775993.867857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.883480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.899123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.914729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775993.930373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.945981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.961615 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.977220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775993.992848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.008623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.024146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775995.039781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.055367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.071011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.086628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775995.102237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.117874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.133498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.149111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775995.164779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.180434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.195998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775996.211607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.227245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.242888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.258477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775996.274120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.289737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.305367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.320978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775996.336612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.352311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.367876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775997.383506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.399132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.414768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.430360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775997.445970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.461827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.477222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.492870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775997.508492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.524193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.539750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775998.555355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.570977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.586604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.602243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775998.617853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.633468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.649100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.664743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775998.687808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.696335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.711669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775999.727229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.742866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.758476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.774194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342775999.789814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.805369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.820975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.836599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342775999.852230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776000.867958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776000.883481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776000.899117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776000.914722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776000.930527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776000.946056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776000.961614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776000.977209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776000.992856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776001.008490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776001.024118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.039793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.055461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776002.071015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.086605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.102235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.117876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776002.133464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.149104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.164734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.187817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776002.195974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.211845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.227434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776003.243080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.258537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.274120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.289755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776003.305601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.321150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.336668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.352316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776003.368367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.383547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.399132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776004.414948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.430908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.446197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.461920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776004.477325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.492883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.508757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.524130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776004.539964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.555458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.571044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776005.586611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.602249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.617866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.633464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776005.649098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.664737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.687965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.695974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776005.711620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.727272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.742864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776006.758487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.774106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.789719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.805354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776006.820968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.836574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.852217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.867846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776006.883471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776007.899195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776007.914747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776007.930357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776007.945991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776007.961607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776007.977230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776007.992866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776008.008503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776008.024130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776008.039747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776008.055355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.071071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.086632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776009.102256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.117867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.133485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.149100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776009.164755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.187955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.195980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.211638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776009.227254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.242883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.258492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776010.274110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.289734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.305371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.320978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776010.336599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.352232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.367857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.383498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776010.399117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.414768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.430383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776011.445980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.461802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.477229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.493052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776011.508497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.524110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.539746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.555357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776011.570992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.586617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.602247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776012.617872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.633490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.649102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.664751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776012.687665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.696112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.711626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.727232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776012.742859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.758509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.774104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776013.789716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.805365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.820972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.836598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776013.852216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.867852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.883478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.899109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776013.914745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776014.930468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776014.945988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776014.961695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776014.977233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776014.992919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776015.008565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776015.024144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776015.039814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776015.055358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776015.071067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776015.086622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.102351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.117961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776016.133479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.149102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.164746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.187772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776016.195970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.211605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.227213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.242836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776016.258468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.274135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.289727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776017.305360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.320976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.336601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.352212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776017.367845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.383488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.399092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.414748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776017.430348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.446015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.461824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776018.477231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.492855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.508481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.524107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776018.539707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.555366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.570969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.586598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776018.602219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.617940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.633528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776019.649109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.664755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.680482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.695978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776019.711739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.727236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.742905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.758479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776019.774111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.789786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.805564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776020.820980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.836604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.852224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.867859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776020.883471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.899107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.914751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.930340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776020.945996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776021.961664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776021.977232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776021.992848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776022.008499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776022.024118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776022.039749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776022.055367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776022.070968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776022.086603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776022.102222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776022.117880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.133520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.149095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776023.164748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.180353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.195983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.211608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776023.227231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.242854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.258472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.274104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776023.289726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.305413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.320977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776024.336603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.352227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.367852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.383498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776024.399107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.414751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.430343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.445974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776024.461821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.477263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.492845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776025.508501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.524115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.539723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.555346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776025.570976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.586594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.602223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.617865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776025.633481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.649134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.664851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776026.680387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.696004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.711674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.727227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776026.742853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.758484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.774097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.789724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776026.805351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.821005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.836609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776027.852220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.867856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.883478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.899096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776027.914725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.930341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.945956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.961608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776027.977212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776028.993123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776029.008495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776029.024161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776029.040776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776029.055417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776029.071025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776029.086698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776029.102220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776029.117883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776029.133478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776029.149106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.164821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.180349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776030.195982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.211607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.227218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.242853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776030.258471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.274188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.289720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.305342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776030.320990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.336754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.352340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776031.368049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.383690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.399113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.414759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776031.430339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.445969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.461860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.477479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776031.492934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.508819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.524178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776032.539783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.555404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.571011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.586617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776032.602212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.617854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.633521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.649134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776032.664753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.680698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.696225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776033.711682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.727262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.742916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.758529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776033.774175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.790032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.805796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.821264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776033.836940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776034.852316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776034.867870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776034.883483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776034.899101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776034.914738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776034.930345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776034.945964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776034.961614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776034.977228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776034.992843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776035.008487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.024288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.039761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776036.055354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.070967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.086655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.102217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776036.117880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.133469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.149105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.164740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776036.180344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.196075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.211625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776037.227232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.242855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.258489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.274109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776037.289726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.305346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.320983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.336601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776037.352215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.368050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.383549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776038.399100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.414753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.430350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.446013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776038.461818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.477232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.492851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.508466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776038.524142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.539800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.555358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776039.570988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.586593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.602227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.617867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776039.633523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.649140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.664745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.680337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776039.695965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.711689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.727264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776040.742906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.758473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.774156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.789729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776040.805366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.820985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.836587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.852217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776040.867833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776041.883548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776041.899107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776041.914733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776041.930337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776041.945973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776041.961606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776041.977217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776041.992872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776042.008474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776042.024121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776042.039746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.055369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.070971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776043.086598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.102220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.117851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.133464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776043.149086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.164728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.180336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.195958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776043.211600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.227353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.242851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776044.258465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.274097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.289707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.305344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776044.320971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.336596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.352221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.367828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776044.383456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.399205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.414829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776045.430418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.445970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.461806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.477214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776045.492918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.508466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.524105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.539710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776045.555381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.571098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.586610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776046.602208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.617855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.633463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.649093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776046.664732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.680345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.695969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.711586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776046.727241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.743058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.758479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776047.774102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.789730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.805348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.820997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776047.836590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.852212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.867836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.883470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776047.899097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776048.914864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776048.930359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776048.945970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776048.961601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776048.977216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776048.992840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776049.008461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776049.024129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776049.039730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776049.055332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776049.070959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.086631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.102224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776050.117857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.133467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.149081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.164727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776050.180334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.195976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.211582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.227217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776050.242837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.258498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.274096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776051.289711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.305350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.320995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.336581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776051.352207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.367832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.383465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.399083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776051.414730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.430372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.445973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776052.461802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.477217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.492843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.508473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776052.524117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.539717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.555352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.570974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776052.586591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.602241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.617861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776053.633457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.649089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.664733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.680332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776053.695990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.711586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.727216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.742832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776053.758483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.774263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.789891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776054.805363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.821154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.836598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.852220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776054.867856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.883480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.899103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.914718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776054.930363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776055.946024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776055.961599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776055.977225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776055.992844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776056.008467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776056.024134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776056.039731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776056.055338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776056.070959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776056.086639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776056.102212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.117930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.133470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776057.149092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.164743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.180347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.195967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776057.211599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.227233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.242841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.258456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776057.274084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.289753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.305356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776058.320982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.336597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.352216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.367837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776058.383477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.399097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.414747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.430363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776058.445984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.461854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.477227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776059.492829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.508495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.524136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.539741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776059.555342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.570972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.586578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.602218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776059.617842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.633531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.649103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776060.664743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.680342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.695972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.711589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776060.727229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.742839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.758458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.774090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776060.789721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.805414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.821045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776061.836596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.852255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.867873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.883471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776061.899093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.914713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.930989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.945978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776061.961651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776062.977242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776062.992895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776063.008467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776063.024186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776063.039783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776063.055359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776063.070960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776063.086596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776063.102209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776063.117844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776063.133488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.149156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.164739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776064.180351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.195976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.211588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.227230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776064.242834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.258470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.274085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.289719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776064.305335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.321050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.336629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776065.352238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.367884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.383507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.399068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776065.414773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.430355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.445985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.461794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776065.477224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.492884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.508479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776066.524119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.539709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.555351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.570961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776066.586594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.602217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.617831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.633493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776066.649599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.667167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.680416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776067.695997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.711590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.727229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.742835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776067.758470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.774090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.789713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.805332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776067.820956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.836785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.852210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776068.867840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.883453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.899224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.914718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776068.930353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.946070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.961694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.977302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776068.992836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.008530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.024139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776070.039778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.055345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.070957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.086614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776070.102205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.117850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.133482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.149073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776070.164723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.180366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.195975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776071.211588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.227226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.242829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.258460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776071.274089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.289721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.305337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.320969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776071.336610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.352241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.368008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776072.383470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.399084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.414730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.430370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776072.445969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.461818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.477227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.492846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776072.508468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.524156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.539729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776073.555374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.570972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.586639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.602221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776073.617851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.633488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.649088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.664733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776073.680332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.696035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.711593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776074.727225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.742842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.758465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.774073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776074.789737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.805670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.820972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.836606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776074.852230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776075.867869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776075.883472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776075.899087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776075.914722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776075.930354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776075.945945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776075.961592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776075.977203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776075.992915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776076.008449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776076.024104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.039874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.055342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776077.070964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.086588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.102208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.117833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776077.133471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.149076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.164725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.180327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776077.195957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.211666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.227253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776078.242849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.258462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.274092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.289726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776078.305332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.320961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.336596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.352206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776078.367837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.383484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.399100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776079.414756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.430360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.445987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.461787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776079.477219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.492823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.508456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.524084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776079.539770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.555386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.570972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776080.586583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.602205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.617824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.633484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776080.649085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.664722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.680329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.695967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776080.711578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.727245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.742845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776081.758464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.774093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.789710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.805343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776081.820966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.836602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.852198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.867827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776081.883456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776082.899117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776082.914716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776082.930354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776082.945967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776082.961585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776082.977194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776082.992820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776083.008462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776083.024127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776083.039751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776083.055325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.071002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.086667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776084.102216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.117859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.133477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.149076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776084.164721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.180329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.195959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.211574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776084.227210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.242849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.258458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776085.274079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.289730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.305335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.320958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776085.336604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.352205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.367834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.383454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776085.399083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.414771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.430359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776086.445963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.461810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.477207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.492841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776086.508447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.524079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.539739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.555331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776086.570957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.586600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.602204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776087.617822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.633460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.649088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.664722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776087.687640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.695952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.711570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.727199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776087.742837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.758495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.774069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776088.789753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.805332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.820946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.836604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776088.852206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.867828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.883437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.899067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776088.914721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776089.930786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776089.945970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776089.961601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776089.977210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776089.992829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776090.008471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776090.024107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776090.039767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776090.055330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776090.070951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776090.086603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.102368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.117874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776091.133472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.149190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.164725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.187680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776091.195964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.211578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.227194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.242835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776091.258450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.274115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.289736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776092.305328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.320956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.336596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.352219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776092.367814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.383450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.399091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.414703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776092.430331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.445984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.461786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776093.477204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.492835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.508464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.524077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776093.539727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.555318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.570949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.586590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776093.602193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.617921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.633485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776094.649092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.664839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.688001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.695967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776094.711594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.727206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.742841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.758452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776094.774152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.789804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.805326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776095.820987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.836600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.852212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.867822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776095.883449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.899097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.914712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.930331 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776095.945966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776096.961601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776096.977200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776096.992825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776097.008457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776097.024144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776097.039772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776097.055450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776097.070950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776097.086642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776097.102217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776097.117882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.133517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.149089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776098.164730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.187716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.195957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.211584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776098.227202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.242859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.258459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.274074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776098.289729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.305365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.320954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776099.336597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.352200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.367824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.383463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776099.399081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.414723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.430323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.445956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776099.461802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.477246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.492824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776100.508459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.524087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.539740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.555327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776100.570956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.586571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.602204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.617827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776100.633456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.649105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.664738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776101.687695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.695977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.711588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.727200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776101.742868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.758452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.774066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.789735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776101.805458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.820984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.836601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776102.852215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.867832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.883469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.899133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776102.914701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.930340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.945978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.961578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776102.977202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776103.992864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776104.008456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776104.024097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776104.039749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776104.055349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776104.070952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776104.086634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776104.102203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776104.117828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776104.133451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776104.149089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.164817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.180346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776105.195968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.211581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.227203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.242841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776105.258455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.274092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.289710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.305324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776105.320947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.336656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.352212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776106.367839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.383454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.399075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.414713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776106.430319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.445971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.461798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.477208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776106.492830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.508517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.524103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776107.539733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.555335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.570953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.586580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776107.602207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.617828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.633472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.649102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776107.664728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.680375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.695961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776108.711590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.727211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.742848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.758450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776108.774075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.789713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.805329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.820950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776108.836587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776109.852273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776109.867827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776109.883448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776109.899069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776109.914712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776109.930766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776109.945973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776109.961580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776109.977207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776109.992821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776110.008459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.024131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.039745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776111.055328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.070950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.086576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.102186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776111.117823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.133467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.149088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.164712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776111.180315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.196040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.211590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776112.227203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.242843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.258534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.274072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776112.289710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.305319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.320944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.336570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776112.352208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.367860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.383462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776113.399073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.414728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.430324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.445971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776113.461774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.477204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.492820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.508442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776113.524083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.539792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.555346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776114.570952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.586581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.602211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.617833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776114.633449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.649089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.664720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.680324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776114.695955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.711623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.727221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776115.742860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.758451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.774085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.789720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776115.805334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.820940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.836569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.852222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776115.867820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776116.883544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776116.899077 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776116.914715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776116.930340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776116.945974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776116.961575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776116.977190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776116.992816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776117.008471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776117.024116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776117.039732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.055403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.070960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776118.086598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.102190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.117836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.133449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776118.149082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.164723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.180317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.195950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776118.211567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.227257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.242859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776119.258451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.274071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.289975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.305335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776119.320948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.336640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.352230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.367820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776119.383447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.399142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.414773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776120.430325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.445964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.461789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.477179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776120.492819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.508443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.524075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.539791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776120.555338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.571069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.586654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776121.604839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.617896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.633690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.649223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776121.664737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.680345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.695972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.711736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776121.727191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.743173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.758686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776122.774833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.789918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.805766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.821200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776122.836655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.852273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.867974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.883605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776122.899211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776123.914909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776123.930417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776123.946045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776123.961671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776123.977442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776123.993289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776124.008589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776124.024290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776124.039904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776124.055361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776124.070965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.086896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.102280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776125.117911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.133520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.149087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.164795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776125.180313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.195940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.211564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.227189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776125.242815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.258473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.274068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776126.289780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.305317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.320942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.336647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776126.352204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.367811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.383439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.399071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776126.414708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.430399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.445965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776127.461797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.477195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.492820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.508493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776127.524069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.539756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.555330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.570941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776127.586559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.602272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.617830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776128.633447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.649101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.664727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.680313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776128.695936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.711560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.727188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.742837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776128.758459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.774112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.789772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776129.805318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.820949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.836564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.852209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776129.867819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.883446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.899056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.914675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776129.930312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776130.946128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776130.961659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776130.977195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776130.992832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776131.008450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776131.024084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776131.039770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776131.055323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776131.070933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776131.086566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776131.102189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.117934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.133455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776132.149086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.164713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.180327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.195941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776132.211568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.227190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.242902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.258465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776132.274079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.289862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.305411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776133.320960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.336579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.352206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.367825 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776133.383444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.399073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.414695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.430323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776133.446022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.461854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.477246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776134.492842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.508462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.524247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.539762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776134.555343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.570946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.586567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.602190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776134.617826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.633537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.649088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776135.664712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.680335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.695958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.711579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776135.727196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.742837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.758456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.774070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776135.789728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.805381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.820949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776136.836575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.852212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.867822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.883438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776136.899059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.914690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.930341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.946013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776136.961582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776137.977268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776137.992832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776138.008471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776138.024096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776138.039751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776138.055338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776138.070963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776138.086578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776138.102211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776138.117828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776138.133468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.149098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.164785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776139.180311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.195985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.211563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.227187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776139.242811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.258458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.274071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.289709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776139.305315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.321036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.336583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776140.352219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.367812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.383460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.399063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776140.414702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.430317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.446095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.461798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776140.477203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.492895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.508452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776141.524085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.539719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.555341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.570947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776141.586580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.602188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.617807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.633444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.649149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776141.664745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776141.680326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776141.695949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776141.711599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776141.727200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776142.742896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776142.758456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776142.774071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776142.789697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776142.805454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776142.821083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776142.836649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776142.852400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776142.867860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776142.883493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776142.899071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776143.914730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776143.930321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776143.946019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776143.961595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776143.977197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776143.993019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776144.008449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776144.024090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776144.039726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776144.055316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776144.070957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.086626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.102192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776145.117828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.133456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.149167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.164710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776145.180335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.195933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.211576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.227181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776145.242805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.258491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.274075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776146.289697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.305310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.320941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.336566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776146.352252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.367827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.383431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.399055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776146.414711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.430353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.446038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776147.461792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.477189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.492835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.508451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776147.524075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.539667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.555311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.570951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776147.586564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.602231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.617821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776148.633456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.649158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.664741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.680312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776148.695942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.711558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.727186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.742826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776148.758546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.774269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.789750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776149.805323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.820956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.836578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.852284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776149.867838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.883449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.899082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.914697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776149.930316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776150.946066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776150.961593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776150.977177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776150.992821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776151.008450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776151.024088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776151.039708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776151.055314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776151.070960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776151.086575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776151.102183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.117942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.133438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776152.149132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.164717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.180322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.195934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776152.211560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.227179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.242812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.258431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776152.274069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.289730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.305323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776153.320939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.336568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.352271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.367821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776153.383429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.399040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.414716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.430323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776153.445944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.461896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.477239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776154.492842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.508448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.524219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.539690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776154.555565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.570969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.586788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.602195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776154.617817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.633509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.649153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776155.664733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.680325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.695959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.711562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776155.727194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.742817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.758440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.774091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776155.789707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.805356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.820957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776156.836565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.852282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.867844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.883448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776156.899065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.914754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.930317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.945936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776156.961569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776157.977232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776157.992815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776158.008546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776158.024093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776158.039701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776158.055315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776158.070947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776158.086564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776158.102175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776158.117804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776158.133440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.149238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.164723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776159.180312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.195944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.211560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.227203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776159.242818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.258437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.274082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.289683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776159.305299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.320989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.336573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776160.352261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.367822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.383427 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.399060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776160.414703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.430312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.445983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.461791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776160.477189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.493025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.508570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776161.524113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.539745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.555382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.570948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776161.586557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.602178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.617805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.633425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776161.649056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.664785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.680315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776162.695938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.711553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.727180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.742813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776162.758429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.774074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.789671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.805302 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776162.820922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.836593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.852254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776163.867817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.883434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.899047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.914670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776163.930297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.945924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.961555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.977194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776163.992796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.008544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.024093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776165.039704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.055299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.070934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.086551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776165.102177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.117804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.133429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.149153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776165.164717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.180398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.195939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776166.211555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.227190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.242819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.258434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776166.274071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.289682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.305308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.320948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.336569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776166.352202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776166.367819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776166.383474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776166.399070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776166.414722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776167.430340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776167.445943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776167.461762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776167.477192 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776167.492800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776167.508444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776167.524060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776167.539680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776167.555298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776167.570929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776167.586566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.602217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.617804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776168.633435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.649055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.664712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.680316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776168.695939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.711551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.727172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.742800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776168.758426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.774126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.789699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776169.805323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.820963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.836574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.852191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776169.867811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.883454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.899058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.914691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776169.930317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776170.945968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776170.961613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776170.977193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776170.992823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776171.008452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776171.024088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776171.039708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776171.055306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776171.070934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776171.086567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776171.102175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.117869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.133440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776172.149059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.164713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.180374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.195923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776172.211568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.227170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.242805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.258426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776172.274049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.289708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.305308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776173.320934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.336567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.352184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.367801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776173.383447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.399063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.414708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.430311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776173.445949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.461779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.477210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776174.492822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.508463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.524238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.539689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776174.555317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.570952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.586598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.602196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776174.617821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.633522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.649062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776175.664713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.680353 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.695934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.711574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776175.727189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.742800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.758424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.774058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776175.789700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.805348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.820947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776176.836570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.852196 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.867810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.883456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776176.899054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.914671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.930326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.945936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776176.961569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776177.977240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776177.992806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776178.008444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776178.024091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776178.039696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776178.055308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776178.070931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776178.086608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776178.102168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776178.117803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776178.133434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.149100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.164918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776179.180341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.195968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.211562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.227182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776179.242806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.258434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.274064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.289688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776179.305305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.321006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.336570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776180.352182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.367810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.383450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.399048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776180.414675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.430301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.445934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.461817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776180.477180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.492903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.508442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776181.524059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.539691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.555321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.570932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776181.586574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.602173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.617812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.633424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776181.649052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.664748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.680340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776182.695935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.711540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.727187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.742826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776182.758433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.774038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.789702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.805303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776182.820930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.836580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.852181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776183.867813 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.883449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.899059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.914674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776183.930296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.945930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.961570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.977173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776183.992815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.008461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.024075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776185.039701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.055317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.070931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.086574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776185.102186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.117794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.133425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.149045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776185.164688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.180350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.195932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776186.211565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.227176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.242798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.258426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776186.274048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.289687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.305311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.320930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776186.336552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.352215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.367808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776187.383446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.399065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.414699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.430305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776187.445937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.461752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.477155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.492812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776187.508431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.570960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.586583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776188.602186 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.617809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.633420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.649052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776188.664693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.680316 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.695943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.711564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776188.727170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.742855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.758431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776189.774062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.789690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.805296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.820919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776189.836558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.852201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.867795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.883412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776189.899059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776190.914772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776190.930326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776190.945931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776190.961570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776190.977174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776190.992819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776191.008425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776191.024073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776191.039693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776191.055296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776191.070925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.086669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.102182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776192.117819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.133430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.149064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.164702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776192.180327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.195947 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.211553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.227191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776192.242809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.258462 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.274049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776193.289686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.305297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.320924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.336562 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776193.352176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.367794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.383438 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.399065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776193.414697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.430340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.445932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776194.461777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.477194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.492841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.508431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776194.524115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.539673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.555306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.570936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776194.586571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.602244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.617819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776195.633434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.649056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.664713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.680312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776195.695941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.711543 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.727173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.742795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776195.758417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.774081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.789694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776196.805299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.820930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.836554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.852171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776196.867789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.883421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.899065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.914686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776196.930293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776197.945999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776197.961564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776197.977181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776197.992839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776198.008435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776198.024069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776198.039702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776198.055298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776198.070920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776198.086554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776198.102209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.117924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.133442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776199.149067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.164702 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.180305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.195935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776199.211547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.227168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.242816 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.258426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776199.274058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.289780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.305312 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776200.320932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.336547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.352178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.367795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776200.383424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.399047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.414692 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.430297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776200.445922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.461896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.477200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776201.493030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.508436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.524058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.539682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776201.555313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.570930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.586558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.602191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776201.617807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.633468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.649056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776202.664696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.680309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.695940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.711617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776202.727172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.742818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.758431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.774050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776202.789675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.805343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.820931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776203.836559 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.852176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.867801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.883427 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776203.899059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.914680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.930317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.945923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776203.961552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776204.977217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776204.992808 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776205.008437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776205.024079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776205.039695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776205.055325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776205.070921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776205.086561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776205.102183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776205.117807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776205.133414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.149081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.164695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776206.180313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.195952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.211547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.227176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776206.242802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.258423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.274040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.289674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776206.305307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.321014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.336560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776207.352174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.367802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.383439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.399063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776207.414698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.430298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.445919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.461774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776207.477173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.492865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.508477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776208.524051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.539676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.555298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.570924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776208.586551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.602176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.617791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.633415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776208.649044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.664927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.680336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776209.695950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.711556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.727202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.742919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776209.758550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.774091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.790502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.805721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776209.820926 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.836613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.852189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776210.867832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.883431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.899205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.914676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776210.930409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.945939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.961652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.977178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776210.992812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.008593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.024333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776212.039820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.055364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.070937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.086630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776212.102207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.117991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.133439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.149048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.164709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776212.180314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776212.196062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776212.211656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776212.227205 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776212.242815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776213.258498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776213.274085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776213.289673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776213.305333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776213.320934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776213.336587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776213.352609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776213.367879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776213.383645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776213.399041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776213.414701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.430358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.446039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776214.461922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.477188 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.492834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.508529 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776214.524249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.539683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.555311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.570941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776214.586555 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.602317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.617802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776215.633420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.649055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.664717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.680342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776215.695920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.711574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.727168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.742791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776215.758433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.774049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.789678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776216.805493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.820944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.836561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.852179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776216.867867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.883427 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.899061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.914784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776216.930326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776217.945992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776217.961604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776217.977181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776217.992797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776218.008448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776218.024062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776218.039709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776218.055288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776218.070915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776218.086560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776218.102169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.117848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.133433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776219.149058 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.164691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.180299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.195956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776219.211566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.227164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.242799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.258414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776219.274050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.289744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.305324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776220.320920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.336550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.352160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.367787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776220.383425 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.399047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.414693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.430293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776220.445917 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.461849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.477173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776221.492809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.508442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.524057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.539665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776221.555292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.570918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.586571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.602177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776221.617809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.633454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.649052 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776222.664688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.680300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.695920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.711571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776222.727173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.742795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.758424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.774043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776222.789671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.805320 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.820922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776223.836551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.852165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.867792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.883430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776223.899043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.914679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.930296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.945920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776223.961554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776224.977262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776224.992793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776225.008446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776225.024071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776225.039683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776225.055274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776225.070912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776225.086558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776225.102164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776225.117802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776225.133411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.149060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.164688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776226.180310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.195923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.211585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.227183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776226.242801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.258419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.274049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.289670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776226.305294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.320954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.336568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776227.352200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.367801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.383483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.399061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776227.414685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.430294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.445920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.461749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776227.477167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.492851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.508443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776228.524054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.539691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.555297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.570933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776228.586546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.602185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.617809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.633417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776228.649071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.664736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.680324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776229.695952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.711565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.727164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.742783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776229.758434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.774054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.789687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.805290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776229.820932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.836604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.852172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776230.867805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.883433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.899066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.914694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776230.930721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.945933 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.961550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.977176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776230.992811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.008496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.024070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776232.039693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.055290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.070915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.086621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776232.102171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.117806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.133422 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.149049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776232.164679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.180321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.195932 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776233.211556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.227167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.242809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.258420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776233.274042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.289678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.305294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.320935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776233.336547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.352190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.367949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776234.383468 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.399061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.414688 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.430284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776234.445914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.461759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.477156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.492770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776234.508410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.524105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.539724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776235.555365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.570916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.586538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.602213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776235.617869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.633472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.649102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.664683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776235.680346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.695948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.711563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776236.727176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.742797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.758433 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.774026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776236.789661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.805281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.820922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.836536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776236.852157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776237.867821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776237.883417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776237.899059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776237.914732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776237.930287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776237.945971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776237.961590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776237.977204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776237.992840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776238.008423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776238.024087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.039821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.055304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776239.070952 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.086557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.102174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.117822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776239.133424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.149076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.164760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.180305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776239.195923 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.211604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.227176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776240.242788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.258410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.274041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.289655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776240.305284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.320919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.336533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.352156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776240.367805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.383548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.399146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776241.414774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.430370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.445922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.461777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776241.477167 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.492789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.508420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.524056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776241.539663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.555355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.570965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776242.586537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.602162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.617803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.633405 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776242.649038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.664678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.680289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.695901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776242.711527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.727431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.742791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776243.758479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.774044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.789669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.805424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776243.820943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.836600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.852237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.867849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776243.883499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776244.899144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776244.914689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776244.930305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776244.945916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776244.961552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776244.977163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776244.992784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776245.008426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776245.024082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776245.039681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776245.055292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.070959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.086552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776246.102178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.117814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.133413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.149050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776246.164682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.187540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.196049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.211552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776246.227178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.242811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.258426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776247.274040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.289667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.305293 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.320936 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776247.336537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.352164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.367784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.383408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776247.399046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.414762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.430290 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776248.445909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.461773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.477162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.493031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776248.508413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.524054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.539667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.555327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776248.570915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.586625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.602177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776249.617815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.633412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.649051 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.664681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776249.688356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.695919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.711554 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.727175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776249.742795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.758502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.774086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776250.789662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.805287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.820948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.836536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776250.852151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.867789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.883416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.899063 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776250.914670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776251.930328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776251.945914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776251.961539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776251.977162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776251.992787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776252.008419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776252.024080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776252.039680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776252.055286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776252.070911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776252.086585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.102210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.117805 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776253.133420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.149065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.164687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.187851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776253.195907 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.211545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.227175 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.242797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776253.258419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.274073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.289671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776254.305294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.320946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.336542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.352176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776254.367795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.383419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.399049 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.414684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776254.430381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.445980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.461771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776255.477168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.492795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.508429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.524066 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776255.539705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.555298 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.570934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.586538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776255.602160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.617913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.633424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776256.649071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.664735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.687581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.696062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776256.711541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.727173 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.742798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.758410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776256.774043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.789697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.805301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776257.821099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.836569 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.852145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.867774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776257.883407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.899039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.914647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.930371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776257.945911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776258.961659 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776258.977306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776258.993299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776259.008583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776259.024226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776259.039680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776259.055417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776259.071104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776259.086732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776259.102169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776259.117798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.133527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.149075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776260.164693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.187650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.195918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.211546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776260.227162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.242787 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.258421 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.274029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776260.289657 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.305364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.320939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776261.336535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.352162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.367776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.383429 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776261.399036 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.414692 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.430310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.445901 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776261.461756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.477185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.492792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776262.508430 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.524057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.539655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.555287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776262.570905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.586541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.602146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.617774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776262.633423 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.649088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.664697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776263.688010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.695946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.711541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.727180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776263.742778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.758418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.774024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.789652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776263.805281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.820956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.836530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776264.852160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.867785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.883412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.899056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776264.914662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.930727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.945906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.961547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776264.977152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776265.992834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776266.008419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776266.024070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776266.039678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776266.055276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776266.070900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776266.086530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776266.102162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776266.117809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776266.133415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776266.149053 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.164727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.180294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776267.195918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.211540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.227168 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.242781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776267.258399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.274025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.289647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.305274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776267.320927 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.336612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.352169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776268.367783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.383410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.399060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.414693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776268.430294 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.445920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.461755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.477156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776268.492789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.508495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.524055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776269.539691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.555306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.570909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.586536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776269.602151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.617769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.633431 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.649046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776269.664676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.680371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.695920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776270.711544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.727195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.742791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.758439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776270.774202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.789673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.805300 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.820906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776270.836558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776271.852347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776271.867793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776271.883404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776271.899050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776271.914648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776271.930296 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776271.945905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776271.961524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776271.977166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776271.992767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776272.008399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.024099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.039664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776273.055299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.070899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.086533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.102149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776273.117788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.133406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.149035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.164665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776273.180280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.195924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.211534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776274.227165 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.242770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.258407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.274023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776274.289655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.305295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.320902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.336532 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776274.352139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.367859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.383434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776275.399045 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.414689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.430303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.445918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776275.461790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.477157 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.492792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.508417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776275.524041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.539681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.555299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776276.570929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.586530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.602257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.617856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776276.633497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.649136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.664756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.680291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776276.695913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.711575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.727184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776277.742781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.758404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.774032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.789653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776277.805278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.820912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.836544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.852155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776277.867783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776278.883473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776278.899141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776278.914661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776278.930412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776278.945913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776278.961654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776278.977166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776278.992784 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776279.008401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776279.024044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776279.039666 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.055340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.071308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776280.086578 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.102150 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.117778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.133428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776280.149112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.164783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.180273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.195894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776280.211517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.227288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.242777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776281.258402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.274014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.289683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.305287 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776281.320919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.336545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.352159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.367777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776281.383410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.399149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.414679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776282.430297 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.445909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.461749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.477155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776282.492793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.508401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.524040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.539669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776282.555282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.570949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.586535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776283.602160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.617788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.633426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.649225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776283.664676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.680389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.696046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.711531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776283.727159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.742856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.758441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776284.774065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.789662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.805275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.820906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776284.836552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.852153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.867778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.883530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776284.899099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776285.914744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776285.930305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776285.945919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776285.961549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776285.977151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776285.992975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776286.008415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776286.024060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776286.039684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776286.055280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776286.070911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.086573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.102170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776287.117797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.133416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.149085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.164678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776287.180270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.195910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.211521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.227145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776287.242793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.258441 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.274026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776288.289653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.305281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.320912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.336541 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776288.352154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.367976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.383402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.399085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776288.414675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.430321 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.445913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776289.461737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.477156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.492992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.508406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776289.524037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.539679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.555303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.570903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776289.586521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.602242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.617786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776290.633420 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.649056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.664699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.680275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776290.695895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.711518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.727155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.742796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776290.758402 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.774121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.789747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776291.805286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.820972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.836549 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.852219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776291.867769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.883463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.899067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.914647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776291.930282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776292.945954 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776292.961548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776292.977160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776292.992771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776293.008401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776293.024050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776293.039682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776293.055270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776293.070898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776293.086526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776293.102141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.117836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.133416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776294.149059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.164687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.180278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.195900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776294.211528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.227145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.242785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.258399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776294.274038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.289768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.305291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776295.320898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.336533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.352142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.367772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776295.383384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.399048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.414777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.430362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776295.445938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.461995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.477383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776296.493260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.508544 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.524128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.539705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776296.555383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.570919 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.586691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.602239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776296.617768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.633475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.649046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776297.664680 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.680274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.695895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.711521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776297.727142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.742781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.758392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.774023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776297.789640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.805332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.820957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776298.836553 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.852151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.867779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.883478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776298.899030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.914640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.930280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.945915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776298.961619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776299.977203 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776299.992781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776300.008404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776300.024046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776300.039675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776300.055273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776300.070890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776300.086588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776300.102145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776300.117791 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776300.133551 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.149093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.164675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776301.180306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.195904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.211527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.227151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776301.242786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.258394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.274017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.289630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776301.305269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.321014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.336983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776302.352274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.367836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.383572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.399043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776302.414684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.430424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.445930 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.461929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776302.477159 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.492857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.508409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776303.524120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.539841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.555480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.570900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776303.586527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.602237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.617853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.633506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776303.649090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.664719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.680357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776304.696083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.711635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.727334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.742803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776304.758393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.773997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.789640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.805266 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776304.820903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.836595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.852145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776305.867769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.883398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.899029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.914643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776305.930276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.945910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.961523 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.977140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776305.992794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.008435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.024046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776307.039665 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.055271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.070929 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.086533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776307.102152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.117781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.133394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.149034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776307.164673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.180495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.195903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776308.211540 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.227160 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.242821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.258407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776308.274033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.289677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.305274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.320912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776308.336547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.352276 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.367991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776309.383412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.399025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.414686 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.430263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776309.445918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.461798 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.477143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.492777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776309.508412 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.524085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.539667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776310.555289 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.570897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.586521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.602158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776310.617768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.633401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.649031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.664670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776310.680269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.695955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.711535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776311.727151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.742790 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.758403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.774022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776311.789651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.805281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.820912 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.836527 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776311.852152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776312.867853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776312.883418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776312.899073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776312.914696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776312.930470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776312.946022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776312.961622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776312.977149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776312.992783 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776313.008472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776313.024148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.039713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.055281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776314.070899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.086534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.102204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.117792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776314.133397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.149029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.164841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.180273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776314.195910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.211568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.227152 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776315.242801 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.258409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.274041 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.289650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776315.305280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.320897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.336513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.352164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776315.367785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.383450 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.399043 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776316.414678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.430280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.445914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.461793 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776316.477156 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.493008 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.508391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.524038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776316.539643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.555327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.570900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776317.586528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.602138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.617774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.633406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776317.649050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.664679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.680270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.695899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776317.711528 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.727212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.742792 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776318.758408 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.774015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.789650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.805269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776318.820894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.836518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.852155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.867765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776318.883394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776319.899064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776319.914658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776319.930272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776319.945911 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776319.961534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776319.977142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776319.992762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776320.008388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776320.024023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776320.039799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776320.055388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.070951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.086538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776321.102140 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.117776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.133403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.149040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776321.164667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.180269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.195902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.211519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776321.227137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.242831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.258397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776322.274024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.289648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.305263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.320887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776322.336513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.352182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.367757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.383382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776322.399006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.414683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.430277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776323.445924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.461712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.477149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.492776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776323.508388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.524019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.539639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.555299 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776323.570987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.586545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.602147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776324.617859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.633385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.649033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.664652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776324.680271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.695879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.711502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.727143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776324.742763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.758404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.774012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776325.789642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.805246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.820899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.836516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776325.852146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.867769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.883382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.899003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776325.914647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776326.930288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776326.945900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776326.961517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776326.977134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776326.992753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776327.008397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776327.024040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776327.039660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776327.055279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776327.070885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776327.086514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.102180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.117774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776328.133409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.149032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.164639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.180280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776328.195875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.211503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.227131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.242757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776328.258396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.274055 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.289650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776329.305269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.320890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.336531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.352207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776329.367758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.383400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.399018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.414694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776329.430256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.446013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.461763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776330.477113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.492766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.508381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.524015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776330.539638 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.555273 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.570881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.586505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776330.602141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.617898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.633502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776331.649054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.664779 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.680272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.695904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776331.711519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.727153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.742773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.758416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776331.774015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.789802 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.805355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776332.820968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.836519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.852204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.867804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776332.883414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.899013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.914630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.930530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776332.946011 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776333.961545 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776333.977135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776333.992751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776334.008386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776334.024027 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776334.039645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776334.055269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776334.070888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776334.086520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776334.102142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776334.117762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.133498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.149047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776335.164670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.180281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.195895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.211517 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776335.227155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.242771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.258403 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.274031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776335.289634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.305306 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.320894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776336.336515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.352148 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.367760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.383395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776336.399013 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.414670 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.430256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.445956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776336.461736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.477176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.492772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776337.508397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.524025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.539653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.555280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776337.570891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.586515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.602130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.617763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776337.633401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.649130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.664676 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776338.680291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.695892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.711506 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.727132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776338.742770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.758409 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.774017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.789632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776338.805256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.820942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.836524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776339.852154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.867772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.883387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.899019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776339.914642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.930750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.945957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.961548 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776339.977172 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776340.992879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776341.008401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776341.024047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776341.039667 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776341.055274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776341.070898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776341.086520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776341.102151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776341.117770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776341.133389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776341.149102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.164735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.180282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776342.195889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.211522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.227138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.242757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776342.258395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.274032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.289637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.305323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776342.320883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.336550 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.352162 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776343.367768 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.383389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.399012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.414645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776343.430253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.445972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.461760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.477134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776343.492769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.508471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.524035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776344.539640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.555280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.570896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.586552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776344.602142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.617778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.633385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.649080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776344.664673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.680291 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.695884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776345.711509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.727129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.742755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.758397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776345.774025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.789637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.805281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.820883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776345.836522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776346.852177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776346.867772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776346.883383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776346.899010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776346.914632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776346.930253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776346.945953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776346.961524 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776346.977144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776346.992751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776347.008382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.024074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.039654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776348.055271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.070896 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.086581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.102133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776348.117771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.133415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.149081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.164658 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776348.187750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.195920 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.211522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776349.227153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.242774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.258417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.274110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776349.289628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.305281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.320887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.336514 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776349.352217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.367796 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.383388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776350.399004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.414649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.430270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.445963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776350.461742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.477142 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.492853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.508390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776350.524015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.539819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.555309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776351.570895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.586516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.602147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.617758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776351.633384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.649080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.664664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.680260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776351.695883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.711547 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.727149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776352.742822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.758410 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.773995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.789631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776352.805258 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.820879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.836505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.852202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776352.867767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776353.883418 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776353.899023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776353.914641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776353.930270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776353.945961 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776353.961536 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776353.977126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776353.992753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776354.008396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776354.024025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776354.039654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.055333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.070885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776355.086526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.102132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.117757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.133391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776355.149073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.164652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.180263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.195895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776355.211500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.227183 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.242776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776356.258415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.274019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.289626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.305250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776356.320883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.336518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.352197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.367780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776356.383375 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.399048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.414643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776357.430740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.445974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.461737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.477136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776357.492757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.508395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.524018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.539635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776357.555257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.570934 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.586556 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776358.602166 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.617763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.633502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.649083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776358.664660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.680260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.695879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.711502 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776358.727123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.742837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.758426 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776359.775187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.789633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.805275 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.820890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776359.836520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.852232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.867775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.883400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776359.899009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776360.914678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776360.930278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776360.945967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776360.961537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776360.977130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776360.992777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776361.008394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776361.024030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776361.039648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776361.055259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776361.070898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.086567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.102138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776362.117774 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.133391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.149074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.164651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776362.180252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.195876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.211496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.227121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776362.242742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.258434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.274017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776363.289633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.305252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.320893 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.336504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776363.352191 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.367766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.383377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.399000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776363.414634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.430406 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.446065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776364.462056 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.477374 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.493399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.508488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776364.524239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.539850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.555563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.571135 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776364.586788 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.602154 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.617757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776365.633384 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.649080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.664689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.680251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776365.695876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.711501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.727129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.742745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776365.758373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.774131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.789642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776366.805373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.820889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.836512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.852199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776366.867766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.883373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.898993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.914619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776366.930248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776367.946113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776367.961537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776367.977158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776367.992770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776368.008386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776368.024050 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776368.039656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776368.055260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776368.070914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776368.086590 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776368.102127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.117862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.133400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776369.149101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.164678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.180263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.195888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776369.211498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.227123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.242755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.258387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776369.274026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.289789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.305256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776370.320873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.336505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.352303 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.367778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776370.383376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.399006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.414643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.430254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776370.445887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.461777 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.477145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776371.492759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.508385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.524018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.539619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776371.555256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.570892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.586496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.602120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776371.617757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.633444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.649092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776372.664668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.680272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.695880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.711499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776372.727130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.742751 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.758380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.774003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776372.789629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.805397 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.820892 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776373.836509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.852200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.867764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.883371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776373.899001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.914627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.930822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.945877 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776373.961505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776374.977234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776374.992769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776375.008391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776375.024028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776375.039664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776375.055262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776375.070895 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776375.086504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776375.102126 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776375.117750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776375.133381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.149229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.164690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776376.180264 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.195885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.211512 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.227181 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776376.242767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.258387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.274021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.289641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776376.305255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.320945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.336510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776377.352208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.367771 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.383378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.399012 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776377.414651 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.430244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.445867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.461714 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776377.477145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.492858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.508381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776378.524003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.539618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.555248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.570887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776378.586490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.602180 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.617797 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.633381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776378.649006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.664855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.680251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776379.695900 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.711516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.727136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.742754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776379.758373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.774006 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.789637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.805249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776379.820876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.836558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.852233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776380.867772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.883391 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.899001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.914635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776380.930269 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.945887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.961509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.977147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776380.992772 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.008432 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.024035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776382.039644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.055260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.070894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.086510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776382.102128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.117759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.133367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.148991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776382.164645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.180288 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.195878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776383.211515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.227128 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.242764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.258368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776383.274023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.289616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.305246 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.320888 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776383.336497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.352238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.367770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776384.383372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.399003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.414653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.430256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776384.445866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.461719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.477134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.492765 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776384.508373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.524031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.539623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776385.555260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.570889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.586500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.602115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776385.617742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.633365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.648991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.664646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776385.680260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.695897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.711501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776386.727132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.742755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.758355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.774131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776386.789611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.805243 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.820956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.836546 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776386.852131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776387.867935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776387.883385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776387.899018 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776387.914628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776387.930254 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776387.945878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776387.961505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776387.977132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776387.992756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776388.008389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776388.024025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.039698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.055286 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776389.070898 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.086509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.102121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.117754 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776389.133378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.149037 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.164695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.180280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776389.195873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.211574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.227163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776390.242789 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.258444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.274076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.289661 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776390.305252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.320865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.336486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.352117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776390.367748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.383537 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.399024 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776391.414886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.430259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.445953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.461767 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776391.477268 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.492881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.508396 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.525681 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776391.539650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.555280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.570904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776392.586564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.602125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.617776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.633378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776392.649028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.664711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.680279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.695894 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776392.711621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.727301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.742827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776393.758471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.774143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.789701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.805277 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776393.820909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.836611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.852199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.867820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776393.883472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776394.899060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776394.914785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776394.930253 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776394.945925 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776394.961694 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776394.977139 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776394.992746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776395.008385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776395.024015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776395.039632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776395.055239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.071047 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.086653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776396.102133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.117749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.133379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.148993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776396.164684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.180281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.195865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.211496 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776396.227114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.242800 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.258389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776397.274062 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.289621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.305248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.320881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776397.336490 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.352119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.367743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.383417 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776397.398991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.414677 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.430267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776398.445885 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.461722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.477158 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.492755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776398.508389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.524176 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.539693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.555279 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776398.570905 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.586627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.602146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776399.617758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.633381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.649016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.664656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776399.680284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.696009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.711492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.727123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776399.742755 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.758445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.774034 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776400.789639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.805367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.820884 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.836497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776400.852132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.867753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.883392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.899005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776400.914625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776401.930301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776401.945887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776401.961511 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776401.977153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776401.992746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776402.008389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776402.024022 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776402.039647 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776402.055278 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776402.070879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776402.086530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.102263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.117759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776403.133472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.149003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.164646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.180261 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776403.195864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.211486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.227107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.242734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776403.258382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.274044 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.289622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776404.305249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.320875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.336520 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.352115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776404.367749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.383389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.398994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.414636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776404.430251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.445910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.461699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776405.477134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.492748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.508383 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.523997 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776405.539620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.555244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.570873 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.586505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776405.602120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.617812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.633371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776406.649014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.664646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.680272 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.696015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776406.711510 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.727121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.742756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.758385 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776406.774000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.789645 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.805242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776407.820878 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.836494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.852130 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.867739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776407.883381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.898992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.914609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.930242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776407.945870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776408.961535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776408.977144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776408.992742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776409.008386 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776409.024010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776409.039628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776409.055234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776409.070866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776409.086522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776409.102116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776409.117742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.133445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.149002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776410.164640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.180251 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.195867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.211479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776410.227117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.242737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.258376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.273985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776410.289646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.305362 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.320874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776411.336497 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.352123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.367757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.383398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776411.398994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.414643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.430238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.445866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776411.461725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.477178 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.492748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776412.508428 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.524057 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.539622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.555233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776412.570866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.586501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.602107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.617733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776412.633373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.649119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.664673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776413.680280 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.695904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.711488 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.727116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776413.742812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.758379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.773998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.789625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776413.805238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.820942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.836501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776414.852134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.867747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.883393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.898985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776414.914608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.930240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.945862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.961489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776414.977111 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776415.992776 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776416.008389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776416.024017 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776416.039633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776416.055244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776416.070872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776416.086574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776416.102122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776416.117749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776416.133378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776416.148992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.164669 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.180271 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776417.195870 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.211498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.227121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.242748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776417.258377 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.273985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.289639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.305231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776417.320876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.336513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.352115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776418.367750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.383381 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.398991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.414631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776418.430248 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.445861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.461678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.477110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776418.492760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.508503 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.524032 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776419.539655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.555238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.570865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.586494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776419.602122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.617760 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.633358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.648976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776419.664631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.680486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.695872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776420.711655 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.727112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.742922 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.758380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776420.773989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.789639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.805257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.820874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776420.836498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776421.852169 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776421.867752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776421.883388 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776421.898982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776421.914613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776421.930237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776421.945861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776421.961489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776421.977104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776421.992745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776422.008370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.024033 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.039630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776423.055270 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.070876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.086505 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.102119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776423.117732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.133352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.148980 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.164630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776423.187614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.195890 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.211500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776424.227115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.242758 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.258379 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.273992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776424.289632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.305245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.320871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.336499 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776424.352107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.367778 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.383392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776425.399000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.414641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.430234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.445865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776425.461689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.477137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.492741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.508371 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776425.523998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.539697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.555260 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776426.570856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.586495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.602113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.617744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776426.633354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.648993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.664635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.687909 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776426.695889 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.711566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.727122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776427.742748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.758387 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.773993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.789631 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776427.805235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.820871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.836484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.852122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776427.867738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776428.883400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776428.898987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776428.914614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776428.930233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776428.945868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776428.961492 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776428.977108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776428.992745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776429.008372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776429.024002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776429.039621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.055334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.070882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776430.086533 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.102575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.117744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.133363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776430.149007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.164654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.187838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.195891 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776430.211494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.227170 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.242750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776431.258370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.273987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.289642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.305231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776431.320867 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.336479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.352110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.367730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776431.383359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.399028 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.414646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776432.430245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.445872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.461697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.477127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776432.492745 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.508454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.523990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.539606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776432.555239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.570906 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.586504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776433.602122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.617731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.633359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.648985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776433.664632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.687625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.695903 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.711495 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776433.727112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.742799 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.758465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776434.773988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.789640 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.805242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.820887 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776434.836561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.852137 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.867756 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.883370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776434.899007 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776435.914683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776435.930250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776435.945956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776435.961557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776435.977221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776435.992766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776436.008531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776436.024123 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776436.039639 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776436.055235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776436.070869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.086567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.102129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776437.117744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.133359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.148992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.164636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776437.180247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.195879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.211489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.227121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776437.242740 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.258483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.273996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776438.289634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.305239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.320864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.336486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776438.352114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.367730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.383368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.399010 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776438.414641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.430282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.446004 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776439.461747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.477122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.492752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.508435 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776439.523987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.539620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.555230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.570855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776439.586535 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.602262 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.617803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776440.633538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.648978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.664663 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.680240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776440.695876 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.711486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.727110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.742744 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776440.758442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.774214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.789641 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776441.805226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.820862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.836474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.852114 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776441.867733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.883365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.898989 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.914600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776441.930235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776442.945924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776442.961493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776442.977106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776442.992763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776443.008414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776443.024003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776443.039617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776443.055229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776443.070856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776443.086483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776443.102121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.117770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.133360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776444.148976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.164643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.180232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.195865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776444.211471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.227102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.242731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.258414 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776444.273981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.289653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.305242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776445.320859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.336473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.352103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.367728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776445.383349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.398995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.414621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.430227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776445.445854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.461696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.477112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776446.492743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.508411 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.523994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.539605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776446.555225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.570858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.586471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.602112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776446.617713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.633378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.648978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776447.664622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.680234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.695868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.711476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776447.727098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.742724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.758399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.773973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776447.789599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.805398 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.820859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776448.836476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.852106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.867736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.883358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776448.899016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.914605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.930223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.945862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776448.961487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776449.977179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776449.992757 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776450.008401 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776450.024003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776450.039621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776450.055230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776450.070849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776450.086483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776450.102125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776450.117731 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776450.133347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.149061 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.164652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776451.180240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.195875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.211504 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.227104 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776451.242743 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.258395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.273983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.289606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776451.305240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.320918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.336500 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776452.352113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.367749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.383360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.399014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776452.414634 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.430235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.445859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.461866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776452.477107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.492769 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.508399 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776453.524003 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.539620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.555241 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.570858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776453.586479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.602121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.617736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.633357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776453.648981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.664826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.680256 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776454.695914 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.711531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.727122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.742773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776454.758390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.774080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.789679 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.805475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776454.820937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.836501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.852119 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776455.867736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.883446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.899001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.914610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776455.930259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.945864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.961487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.977098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776455.992742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.008395 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.024015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776457.039632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.055240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.070853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.086485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776457.102122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.117746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.133359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.148979 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776457.164644 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.180323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.195910 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776458.211491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.227113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.242735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.258367 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776458.273972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.289603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.305240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.320855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776458.336479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.352144 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.367742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776459.383363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.398999 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.414633 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.430222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776459.445849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.461699 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.477103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.492727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776459.508372 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.524085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.539616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776460.555240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.570854 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.586475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.602134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776460.617719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.633346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.648968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.664622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776460.680225 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.695967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.711584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776461.727122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.742742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.758357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.773969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776461.789597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.805255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.820881 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.836481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776461.852118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776462.867780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776462.883392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776462.899138 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776462.914609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776462.930232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776462.945960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776462.961489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776462.977120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776462.992737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776463.008392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776463.024014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.039668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.055242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776464.070866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.086552 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.102132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.117737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776464.133354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.148985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.164811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.180250 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776464.195861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.211516 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.227110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776465.242759 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.258363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.273982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.289613 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776465.305257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.320848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.336577 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.352097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776465.367737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.383400 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.399001 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776466.414636 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.430238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.445862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.461807 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776466.477124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.492747 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.508509 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.523995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776466.539614 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.555295 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.570858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776467.586491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.602141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.617735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.633366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776467.648978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.664626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.680234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.695853 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776467.711485 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.727129 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.742742 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776468.758360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.773964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.789612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.805255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776468.820872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.836480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.852103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.867726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776468.883361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776469.899046 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776469.914617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776469.930337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776469.945857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776469.961478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776469.977118 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776469.992724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776470.008376 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776470.024005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776470.039623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776470.055223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.070918 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.086491 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776471.102122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.117748 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.133354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.148991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776471.164628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.180242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.195845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.211482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776471.227092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.242780 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.258357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776472.273981 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.289607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.305240 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.320848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776472.336471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.352091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.367724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.383368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776472.398977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.414671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.430227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776473.445868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.461691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.477105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.492730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776473.508366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.523986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.539593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.555222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776473.570852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.586581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.602143 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776474.617762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.633360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.648988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.664627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776474.680221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.695852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.711487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.727101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776474.742726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.758464 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.773991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776475.789606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.805445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.821029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.837099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776475.852101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.867727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.883357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.898976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776475.914635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776476.930283 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776476.945869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776476.961480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776476.977095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776476.992723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776477.008373 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776477.023992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776477.039637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776477.055200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776477.070849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776477.086483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.102151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.117746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776478.133352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.148971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.164648 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.180219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776478.195847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.211483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.227092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.242734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776478.258348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.274014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.289603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776479.305249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.320852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.336538 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.352093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776479.367717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.383356 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.398978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.414617 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776479.430292 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.445908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.461705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776480.477100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.492723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.508393 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.523984 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776480.539591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.555244 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.570842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.586465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776480.602092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.617935 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.633448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776481.648990 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.664643 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.680236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.695874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776481.711487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.727108 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.742734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.758352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776481.773992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.789642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.805249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776482.820858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.836481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.852093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.867717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776482.883355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.898971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.914609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.930214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.945957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776482.961526 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776482.977127 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776482.992764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776483.008481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776483.024179 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776484.040101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776484.055366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776484.071031 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776484.086722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776484.102242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776484.117773 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776484.133461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776484.149021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776484.164728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776484.181601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776484.196029 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.211573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.227110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776485.242726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.258363 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.273972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.289598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776485.305221 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.320862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.336481 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.352100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776485.367733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.383392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.398987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776486.414660 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.430921 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.445859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.461682 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776486.477122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.492986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.508354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.524064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776486.539591 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.555284 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.570857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776487.586473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.602117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.617739 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.633345 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776487.648964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.664635 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.680231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.695858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776487.711467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.727134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.742723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776488.758352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.773971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.789601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.805234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776488.820880 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.836482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.852122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.867729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776488.883347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776489.899026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776489.914626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776489.930228 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776489.945849 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776489.961477 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776489.977125 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776489.992713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776490.008358 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776490.024019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776490.039618 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776490.055233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.070931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.086493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776491.102102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.117750 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.133352 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.148975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776491.164609 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.180213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.195839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.211461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776491.227103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.242763 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.258359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776492.273983 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.289630 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.305233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.320897 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776492.336474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.352093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.367730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.383350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776492.398978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.414646 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.430236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776493.445856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.461692 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.477112 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.492724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776493.508341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.523986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.539594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.555226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776493.570847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.586612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.602116 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776494.617770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.633368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.648988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.664653 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776494.680242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.696021 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.711482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.727121 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776494.742726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.758407 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.773993 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776495.789606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.805382 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.820874 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.836484 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776495.852101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.867734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.883355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.898966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776495.914752 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776496.930259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776496.945857 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776496.961494 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776496.977102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776496.992722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776497.008360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776497.023996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776497.039604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776497.055218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776497.070840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776497.086498 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.102151 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.117766 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776498.133354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.148971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.164626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.180236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776498.195842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.211466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.227102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.242736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776498.258347 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.274038 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.289606 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776499.305231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.320931 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.336479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.352096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776499.367720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.383361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.398976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.414611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776499.430249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.445871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.461684 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776500.477106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.492720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.508342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.523988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776500.539603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.555222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.570845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.586479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776500.602109 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.617828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.633361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776501.648978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.664629 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.680224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.695864 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776501.711476 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.727115 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.742709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.758342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776501.773959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.789652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.805224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776502.820872 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.836475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.852089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.867726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776502.883339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.898964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.914607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.930233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776502.945838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776503.961557 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776503.977097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776503.992746 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776504.008361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776504.024000 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776504.039623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776504.055220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776504.070837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776504.086539 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776504.102088 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776504.117729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.133380 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.148982 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776505.164624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.180238 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.195846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.211460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776505.227098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.242700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.258334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.273957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776505.289584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.305249 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.320869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776506.336478 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.352098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.367736 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.383357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776506.398962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.414621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.430236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.445842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.461690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776506.477131 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776506.492749 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776506.508355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776506.524002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776506.539623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776507.555263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776507.570851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776507.586472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776507.602147 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776507.617721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776507.633355 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776507.648977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776507.664628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776507.687305 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776507.696026 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776507.711467 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.727133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.742724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776508.758350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.773966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.789602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.805214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776508.820843 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.836471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.852097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.867724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776508.883338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776509.899020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776509.914596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776509.930231 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776509.945838 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776509.961465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776509.977095 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776509.992704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776510.008332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776510.023991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776510.039601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776510.055229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.070913 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.086472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776511.102100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.117721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.133342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.148949 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776511.164607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.187370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.195828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.211453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776511.227079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.242814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.258361 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776512.273974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.289607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.305237 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.320858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776512.336501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.352110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.367734 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.383354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776512.398995 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.414662 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.430242 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776513.445846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.461687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.477081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.492712 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776513.508338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.523972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.539603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.555218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776513.570845 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.586585 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.602107 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776514.617725 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.633370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.648963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.664723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776514.687571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.695842 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.711460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.727093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776514.742728 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.758413 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.773978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776515.789593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.805255 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.820846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.836486 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776515.852099 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.867733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.883357 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.898973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776515.914622 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776516.930360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776516.945871 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776516.961473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776516.977087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776516.992713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776517.008440 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776517.024014 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776517.039624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776517.055211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776517.070832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776517.086466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.102120 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.117718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776518.133351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.148960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.164600 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.187649 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776518.195835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.211530 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.227084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.242722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776518.258333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.273994 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.289604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776519.305224 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.320861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.336519 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.352084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776519.367737 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.383340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.398996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.414608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776519.430234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.445915 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.461785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776520.477100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.492969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.508350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.523986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776520.539619 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.555274 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.570852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.586474 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776520.602110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.617815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.633359 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776521.648975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.664627 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.680215 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.695846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776521.711457 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.727103 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.742741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.758344 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776521.773975 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.789654 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.805229 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776522.820839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.836493 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.852086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.867716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776522.883364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.898958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.914604 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.930213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776522.945883 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776523.961522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776523.977101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776523.992718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776524.008354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776524.023996 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776524.039621 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776524.055206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776524.070837 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776524.086515 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776524.102084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776524.117716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.133419 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.148976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776525.164625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.180220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.195955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.211565 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776525.227190 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.242875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.258470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.274102 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776525.289583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.305281 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.320847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776526.336482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.352097 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.367706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.383346 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776526.398967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.414610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.430216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.445865 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776526.461693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.477105 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.492948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776527.508342 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.523970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.539605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.555214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776527.570846 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.586466 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.602080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.617717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776527.633337 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.648998 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.664607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776528.680213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.695834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.711453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.727076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776528.742717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.758327 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.773958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.789611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776528.805212 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.820886 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.836479 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776529.852087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.867720 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.883339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.898969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776529.914588 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.930206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.945860 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.961483 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776529.977081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776530.992822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776531.008351 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776531.023985 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776531.039620 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776531.055204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776531.071002 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776531.086525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776531.102282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776531.117713 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776531.133360 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776531.148991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.164671 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.180226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776532.195847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.211461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.227101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.242722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776532.258339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.273955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.289584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.305218 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776532.320836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.336508 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.352091 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776533.367711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.383335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.398962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.414602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776533.430207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.445868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.461673 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.477082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776533.492708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.508370 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.523977 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776534.539597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.555211 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.570834 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.586445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776534.602075 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.617697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.633334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.648963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776534.664610 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.680257 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.696005 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776535.711473 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.727092 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.742732 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.758334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776535.773969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.789593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.805230 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.820839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776535.836458 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776536.852122 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776536.867716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776536.883335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776536.898964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776536.914594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776536.930217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776536.945859 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776536.961470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776536.977086 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776536.992706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776537.008336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.024019 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.039607 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776538.055219 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.070840 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.086480 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.102083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776538.117715 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.133338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.148970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.164616 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776538.180210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.195902 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.211469 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776539.227065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.242690 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.258350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.273953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776539.289586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.305208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.320835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.336475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776539.352106 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.367786 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.383339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776540.398963 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.414595 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.430214 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.445856 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776540.461710 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.477076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.492717 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.508333 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776540.523958 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.539668 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.555213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776541.570836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.586461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.602082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.617709 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776541.633335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.648964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.664612 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.680247 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776541.695822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.711487 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.727096 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776542.742719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.758339 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.773973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.789572 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776542.805198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.820830 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.836451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.852098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776542.867704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776543.883366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776543.898965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776543.914586 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776543.930210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776543.945844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776543.961459 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776543.977080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776543.992700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776544.008335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776544.023972 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776544.039603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.055235 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.070848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776545.086475 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.102093 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.117719 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.133323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776545.148965 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.164594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.180199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.195831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776545.211449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.227132 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.242730 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776546.258329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.273986 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.289573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.305206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776546.320836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.336465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.352087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.367704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776546.383330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.399015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.414624 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776547.430210 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.445924 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.461704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.477074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776547.492711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.508324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.523970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.539584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776547.555226 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.570866 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.586456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776548.602090 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.617718 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.633336 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.648970 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776548.664605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.680222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.695822 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.711453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776548.727078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.742770 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.758332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776549.773966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.789576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.805197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.820823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776549.836453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.852085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.867721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.883330 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776549.899039 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776550.914704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776550.930209 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776550.945847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776550.961454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776550.977076 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776550.992703 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776551.008341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776551.023969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776551.039593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776551.055217 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776551.070817 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.086806 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.102110 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776552.117729 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.133335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.148987 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.164605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776552.180220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.195832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.211453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.227083 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.242723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776552.258369 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776552.273991 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776552.289603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776552.305234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776552.320852 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -1342776553.336525 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776553.352098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776553.367726 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776553.383366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776553.398957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776553.414623 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776553.430206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776553.445928 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776553.461687 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776553.477081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776553.492721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.508392 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.523992 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776554.539584 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.555227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.570829 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.586471 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776554.602071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.617723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.633334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.649025 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776554.664603 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.680343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.696035 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776555.711461 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.727245 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.742839 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.758452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776555.773968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.789580 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.805206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.820835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776555.836452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776556.852222 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776556.867814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776556.883335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776556.898971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776556.914689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776556.930267 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776556.945916 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776556.961482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776556.977073 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776556.992697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776557.008416 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.024100 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.039611 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776558.055216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.070826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.086451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.102068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776558.117738 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.133322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.149009 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.164598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776558.180197 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.195869 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.211454 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776559.227078 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.242704 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.258348 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.273956 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776559.289567 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.305206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.320811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.336463 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776559.352136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.367781 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.383338 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776560.398966 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.414706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.430202 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.446015 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776560.461685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.477080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.492695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.508329 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776560.523960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.539625 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.555234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776561.570836 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.586453 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.602071 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.617733 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776561.633335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.649040 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.664598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.680208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776561.695823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.711571 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.727164 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776562.742899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.758522 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.774149 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.789855 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776562.805265 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.820826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.836534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.852174 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776562.867899 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776563.883364 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776563.898964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776563.914583 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776563.930206 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776563.945957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776563.961489 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776563.977087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776563.992697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776564.008326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776564.023976 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776564.039598 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.055259 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.070833 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776565.086465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.102087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.117722 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.133390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776565.149020 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.164594 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.180216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.195826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776565.211455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.227161 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.242705 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776566.258349 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.273951 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.289575 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.305201 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776566.320821 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.336442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.352134 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.367741 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776566.383394 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.398974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.414608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776567.430674 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.445904 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.461678 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.477080 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776567.492706 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.508332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.523971 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.539568 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776567.555194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.570875 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.586691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776568.602094 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.617753 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.633343 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.649030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776568.664642 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.680263 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.695847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.711444 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776568.727069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.742785 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.758354 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776569.773953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.789605 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.805200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.820828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776569.836445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.852155 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.867735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.883335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776569.898950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776570.914650 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776570.930207 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776570.945908 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776570.961465 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776570.977070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776570.992698 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776571.008326 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776571.023974 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776571.039602 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776571.055204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776571.070858 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.086697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.102182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776572.117803 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.133424 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.149048 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.164632 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776572.180213 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.195861 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.211456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.227082 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776572.242708 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.258434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.273967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776573.289597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.305208 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.320944 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.336521 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776573.352136 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.367879 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.383531 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.398988 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776573.414637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.430324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.446200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776574.461868 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.477233 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.492711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.508507 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776574.524124 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.539693 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.555223 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.570978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776574.586460 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.602171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.617716 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776575.633378 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.649023 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.664592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.680220 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776575.695827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.711439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.727068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.742689 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776575.758319 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.774171 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.789576 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776576.805332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.820823 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.836442 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.852145 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776576.867735 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.883318 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.898948 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.914573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776576.930882 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776577.945959 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776577.961472 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776577.977079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776577.992695 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776578.008341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776578.023964 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776578.039601 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776578.055193 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776578.070847 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776578.086448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776578.102068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.117810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.133332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776579.149042 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.164599 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.180216 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.195862 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776579.211439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.227087 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.242707 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.258334 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776579.273973 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.289652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.305239 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776580.320826 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.336455 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.352153 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.367723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776580.383335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.398957 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.414596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.430198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776580.445820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.461761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.477074 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776581.492685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.508323 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.523953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.539574 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776581.555185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.570844 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.586439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.602067 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776581.617724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.633390 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.649030 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776582.664592 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.680195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.695814 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.711443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776582.727234 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.742691 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.758315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.773942 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776582.789561 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.805232 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.820818 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776583.836443 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.852141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.867723 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.883308 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776583.898937 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.914560 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.930184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.945819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776583.961447 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776584.977113 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776584.992700 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776585.008325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776585.023968 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776585.039587 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776585.055200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776585.070835 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776585.086452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776585.102065 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776585.117721 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776585.133328 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.149101 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.164608 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776586.180204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.195832 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.211449 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.227081 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776586.242685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.258340 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.273950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.289581 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776586.305194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.320850 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.336456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776587.352146 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.367727 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.383317 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.398962 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776587.414573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.430200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.445811 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.461656 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776587.477079 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.492761 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.508341 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776588.523955 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.539582 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.555200 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.570828 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776588.586436 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.602084 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.617701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.633307 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776588.648950 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.664637 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.680252 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776589.695824 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.711446 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.727060 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.742685 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776589.758315 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.773946 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.789564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.805182 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776589.820815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.836470 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.852141 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776590.867724 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.883310 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.898940 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.914566 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776590.930177 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.945820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.961437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.977069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776590.992697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.008368 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.023969 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776592.039579 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.055199 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.070827 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.086518 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776592.102054 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.117804 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.133311 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.148945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776592.164597 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.180227 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.195820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776593.211451 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.227069 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.242697 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.258314 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776593.273967 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.289558 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.305185 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.320810 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776593.336434 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.352163 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.367795 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776594.383324 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.398941 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.414589 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.430195 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776594.445815 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.461664 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.477068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.492675 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776594.508301 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.524133 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.539628 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776595.555198 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.570841 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.586513 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.602070 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776595.617775 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.633325 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.648945 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.664593 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776595.687534 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.695848 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.711448 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776596.727064 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.742701 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.758313 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.773953 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776596.789564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.805184 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.820812 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.836439 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776596.852072 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776597.867809 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776597.883335 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776597.898939 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776597.914570 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776597.930204 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776597.945820 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776597.961452 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776597.977089 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776597.992683 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776598.008309 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776598.023978 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.039711 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.055189 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776599.070831 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.086445 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.102068 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.117762 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776599.133304 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.148938 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.164794 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.196626 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776599.211437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.227117 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.242696 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776600.258322 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.273960 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.289573 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.305187 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - -1342776600.320819 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.336437 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.352059 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.367764 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.383332 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - -1342776600.399016 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - -#close 2012-11-06-00-51-23 +1093521704.839184 CjhGID4nQcgTWjvg4c 10.0.0.57 2578 10.0.0.3 502 DIAGNOSTICS - +1093521710.268829 CjhGID4nQcgTWjvg4c 10.0.0.57 2578 10.0.0.3 502 DIAGNOSTICS - +1093521740.211122 CjhGID4nQcgTWjvg4c 10.0.0.57 2578 10.0.0.3 502 DIAGNOSTICS - +1093521743.213870 CjhGID4nQcgTWjvg4c 10.0.0.57 2578 10.0.0.3 502 DIAGNOSTICS - +1093521997.919380 CjhGID4nQcgTWjvg4c 10.0.0.57 2578 10.0.0.3 502 REPORT_SLAVE_ID - +1093522000.292566 CjhGID4nQcgTWjvg4c 10.0.0.57 2578 10.0.0.3 502 REPORT_SLAVE_ID - +1093522338.987616 CsRx2w45OKnoww6xl4 10.0.0.9 3082 10.0.0.3 502 READ_COILS - +1093522368.744337 CsRx2w45OKnoww6xl4 10.0.0.9 3082 10.0.0.3 502 READ_COILS - +1093522405.134171 CsRx2w45OKnoww6xl4 10.0.0.9 3082 10.0.0.3 502 READ_HOLDING_REGISTERS - +1093522432.261317 CsRx2w45OKnoww6xl4 10.0.0.9 3082 10.0.0.3 502 WRITE_SINGLE_COIL - +1093522442.074410 CsRx2w45OKnoww6xl4 10.0.0.9 3082 10.0.0.3 502 WRITE_SINGLE_COIL - +1093522480.000230 CsRx2w45OKnoww6xl4 10.0.0.9 3082 10.0.0.3 502 WRITE_SINGLE_REGISTER - +1153491892.783650 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-128 - +1153491893.492404 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491893.492404 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_VALUE +1153491893.990688 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_DISCRETE_INPUTS_EXCEPTION ILLEGAL_DATA_VALUE +1153491894.576738 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_HOLDING_REGISTERS_EXCEPTION ILLEGAL_DATA_VALUE +1153491895.256017 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_INPUT_REGISTERS_EXCEPTION ILLEGAL_DATA_VALUE +1153491895.832303 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 WRITE_SINGLE_COIL - +1153491896.426683 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 WRITE_SINGLE_REGISTER_EXCEPTION ILLEGAL_DATA_VALUE +1153491897.165539 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_EXCEPTION_STATUS - +1153491897.712499 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 DIAGNOSTICS - +1153491901.676648 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 WRITE_MULTIPLE_COILS_EXCEPTION ILLEGAL_DATA_VALUE +1153491902.236242 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 WRITE_MULTIPLE_REGISTERS_EXCEPTION ILLEGAL_DATA_VALUE +1153491904.958574 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_FILE_RECORD_EXCEPTION ILLEGAL_DATA_VALUE +1153491905.606024 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 WRITE_FILE_RECORD_EXCEPTION ILLEGAL_DATA_VALUE +1153491906.126922 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 MASK_WRITE_REGISTER_EXCEPTION ILLEGAL_DATA_VALUE +1153491906.665323 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_WRITE_MULTIPLE_REGISTERS_EXCEPTION ILLEGAL_DATA_VALUE +1153491907.202989 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_FIFO_QUEUE_EXCEPTION - +1153491907.202989 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_FIFO_QUEUE_EXCEPTION ILLEGAL_DATA_VALUE +1153491907.721092 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-153 - +1153491908.288044 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-154 - +1153491908.794212 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-155 - +1153491909.414125 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-156 - +1153491910.093490 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-157 - +1153491910.705044 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-158 - +1153491911.416719 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-159 - +1153491911.976794 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-160 - +1153491912.494612 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-161 - +1153491913.013726 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-162 - +1153491913.563241 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-163 - +1153491914.102765 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-164 - +1153491914.609591 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-165 - +1153491915.148323 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-166 - +1153491915.666317 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-167 - +1153491916.246101 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 PROGRAM_CONCEPT - +1153491916.839806 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-169 - +1153491917.510280 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-42 - +1153491918.097523 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-171 - +1153491918.886019 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-172 - +1153491919.637519 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-173 - +1153491920.132919 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-174 - +1153491920.661039 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-175 - +1153491921.200303 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-176 - +1153491921.780851 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-177 - +1153491922.516425 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-178 - +1153491923.075893 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-179 - +1153491923.568357 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-180 - +1153491924.126968 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-181 - +1153491924.737832 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-182 - +1153491925.426974 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-183 - +1153491925.969700 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-184 - +1153491926.501102 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-185 - +1153491927.019176 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-186 - +1153491927.553318 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-187 - +1153491928.090342 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-188 - +1153491928.626285 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-189 - +1153491929.144400 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-190 - +1153491929.663558 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-191 - +1153491930.380544 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-192 - +1153491930.955009 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-193 - +1153491931.508232 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-194 - +1153491932.064038 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-195 - +1153491932.617246 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-196 - +1153491933.217552 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-197 - +1153491933.898173 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-198 - +1153491934.493195 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-199 - +1153491935.212569 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-200 - +1153491935.750950 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-201 - +1153491936.289847 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-202 - +1153491936.820614 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-203 - +1153491937.326834 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-204 - +1153491937.875669 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-205 - +1153491938.393501 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-206 - +1153491938.983495 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-207 - +1153491939.720697 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-208 - +1153491940.242679 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-209 - +1153491940.778209 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-210 - +1153491941.311600 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-211 - +1153491941.851940 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-212 - +1153491942.402906 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-213 - +1153491942.948265 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-214 - +1153491943.639225 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-215 - +1153491944.200324 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-216 - +1153491944.731019 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-217 - +1153491945.309829 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-218 - +1153491945.801031 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-219 - +1153491946.326315 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-220 - +1153491946.881363 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-221 - +1153491947.379569 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-222 - +1153491947.917182 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-223 - +1153491948.522538 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-224 - +1153491949.242450 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-225 - +1153491949.786176 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-226 - +1153491950.318859 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-227 - +1153491950.839949 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-228 - +1153491951.355365 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-229 - +1153491951.927690 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-230 - +1153491952.439603 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-231 - +1153491952.967534 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-232 - +1153491953.481427 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-233 - +1153491954.018322 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-234 - +1153491954.733393 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-235 - +1153491955.355330 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-236 - +1153491955.910091 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-237 - +1153491956.642232 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-238 - +1153491957.266232 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-239 - +1153491958.032310 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-240 - +1153491958.726775 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-241 - +1153491959.440580 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-242 - +1153491960.040221 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-243 - +1153491960.610615 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-244 - +1153491961.149960 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-245 - +1153491961.618613 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-246 - +1153491962.181217 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-247 - +1153491962.688996 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-248 - +1153491963.226713 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-249 - +1153491963.781229 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-250 - +1153491964.324462 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-251 - +1153491964.870228 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-252 - +1153491965.346071 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 FIRMWARE_REPLACEMENT - +1153491965.897323 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-254 - +1153491966.425892 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 unknown-255 - +1153491967.462159 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS - +1153491968.001263 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS - +1153491968.505228 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491968.505228 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS +1153491969.106358 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491969.106358 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS +1153491969.807100 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491969.807100 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS +1153491970.362598 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491970.362598 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS +1153491970.940211 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491970.940211 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS +1153491971.734926 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491971.734926 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS +1153491972.448954 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS - +1153491973.009668 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS - +1153491973.499918 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491973.499918 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS +1153491974.078420 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION - +1153491974.078420 CIPOse170MGiRM1Qf4 192.168.66.235 2582 166.161.16.230 502 READ_COILS_EXCEPTION ILLEGAL_DATA_ADDRESS +1342774499.602711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.618257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.633881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.649736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.665129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.680776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.696389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.712024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.727627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.743256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.758901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.774498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774499.790129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.805748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.821395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.837006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774499.852712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.868263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.883868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.899494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.915123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774499.930770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.946383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.962002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.977626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774499.993255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774501.008954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774501.024564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774501.040163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774501.055750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774501.071372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774501.087014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774501.102663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774501.118262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774501.133894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774501.149722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774501.165118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.180781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.196410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774502.212010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.227656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.243258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.258920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774502.274503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.290144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.305756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.321389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774502.337026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.352656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.368263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774503.383881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.399508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.415144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.430765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774503.446381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.462238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.477626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.493255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774503.508879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.524559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.540148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774504.555766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.571382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.586999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.602612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774504.618243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.633886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.649716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.665119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774504.680748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.696399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.712010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774505.727639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.743262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.758899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.774514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774505.790120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.805743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.821372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.837008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774505.852627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774506.868280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774506.883875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774506.899506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774506.915128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774506.930773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774506.946397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774506.962010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774506.977632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774506.993300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774507.008875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774507.024525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.040170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.055773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774508.071382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.087037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.102608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.118291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774508.133895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.149730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.165121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.180755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774508.196376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.212038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.227653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774509.243257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.258902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.274499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.290143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774509.305756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.321374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.337023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.352630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774509.368306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.383907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.399511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774510.415150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.430768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.446406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.462243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774510.477627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.493250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.508876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.524502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774510.540154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.555806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.571396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774511.587001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.602645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.618247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.633887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774511.649712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.665115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.680746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.696380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774511.711992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.727667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.743256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774512.758901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.774514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.790125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.805742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774512.821365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.837018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.852618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.868249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774512.883911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774513.899562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774513.915132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774513.930762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774513.946377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774513.962004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774513.977619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774513.993247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774514.008872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774514.024516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774514.040161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774514.055747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.071409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.087017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774515.102648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.118272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.133903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.149763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774515.165133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.180747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.196399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.212004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774515.227684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.243285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.258910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774516.274502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.290132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.305750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.321388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774516.337016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.352622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.368241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.383871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774516.399516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.415180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.430768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774517.446391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.462228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.477629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.493254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774517.508882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.524519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.540147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.555744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774517.571370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.587023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.602630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774518.618268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.633897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.649729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.665122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774518.680763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.696389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.711990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.727622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774518.743260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.758928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.774516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774519.790226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.805758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.821381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.837016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774519.852619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.868268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.883880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.899496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774519.915120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774520.931544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774520.946460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774520.962006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774520.977628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774520.993375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774521.008944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774521.024533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774521.040157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774521.055745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774521.071388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774521.086996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.102679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.118279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774522.133899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.149738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.165124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.180766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774522.196386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.212002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.227625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.243278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774522.258899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.274527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.290133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774523.305750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.321397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.337022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.352630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774523.368244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.383874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.399508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.415136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774523.430759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.446433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.462235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774524.477634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.493255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.508891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.524511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774524.540153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.555752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.571373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.586996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774524.602631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.618282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.633900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774525.649723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.665124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.680761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.696386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774525.712003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.727623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.743252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.758890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774525.774492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.790148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.805742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774526.821371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.837013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.852632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.868239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774526.883869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.899487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.915109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.930739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774526.946485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774527.962037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774527.977629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774527.993243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774528.008875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774528.024528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774528.040150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774528.063396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774528.071379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774528.087066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774528.102611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774528.118249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.133917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.149739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774529.165316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.180760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.196375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.212016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774529.227622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.243288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.258889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.274490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774529.290130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.305803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.321387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774530.337012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.352631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.368310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.383867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774530.399498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.415142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.430747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.446485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774530.462247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.477719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.493267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774531.508894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.524521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.540166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.563507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774531.571381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.586999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.602614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.618233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774531.633877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.649757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.665132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774532.680762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.696388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.711997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.727627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774532.743271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.758902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.774495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.790124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774532.805791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.821418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.837013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774533.852623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.868244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.883877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.899495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774533.915125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.930775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.946493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.961991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774533.977611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774534.993361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774535.008887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774535.024548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774535.040155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774535.063715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774535.071385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774535.087011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774535.102611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774535.118256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774535.133866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774535.149625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.165166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.180759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774536.196393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.212012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.227623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.243270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774536.258902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.274485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.290123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.305748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774536.321389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.337048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.352627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774537.368242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.383957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.399492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.415140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774537.430737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.446470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.462212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.477609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774537.493253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.508890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.524510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774538.540139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.563465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.571378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.587004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774538.602620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.618241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.633873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.649585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774538.665335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.680798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.696420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774539.712001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.727617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.743265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.758904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774539.774496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.790379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.805806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.821378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.837005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774539.852753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774539.868248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774539.883866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774539.899499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774539.915119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774540.930922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774540.946501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774540.962000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774540.977715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774540.993341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774541.008955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774541.024602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774541.040214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774541.063483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774541.071377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774541.087001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.102649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.118279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774542.133876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.149819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.165121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.180752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774542.196395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.211983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.227616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.243231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774542.258907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.274530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.290128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774543.305748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.321369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.337000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.352703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774543.368239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.383862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.399493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.415145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774543.430752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.446505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.462262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774544.477618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.493250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.508865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.524504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774544.540129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.555757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.571357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.586984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774544.602612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.618287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.633871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774545.649796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.665118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.680748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.696382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774545.711992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.727616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.743240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.758896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774545.774506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.790149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.805739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774546.821375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.837056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.852722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.868239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774546.883943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.899494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.915130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.930731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774546.946377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774547.962023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774547.977616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774547.993231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774548.008873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774548.024513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774548.040138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774548.055750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774548.071371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774548.087056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774548.102614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774548.118251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.133886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.149759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774549.165106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.180736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.196367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.211981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774549.227628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.243229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.258897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.274489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774549.290217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.305789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.321396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774550.337014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.352703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.368241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.383855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774550.399492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.415123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.430735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.446363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774550.462240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.477684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.493250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774551.508885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.524507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.540139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.555763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774551.571382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.586980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.602610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.618251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774551.633857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.649831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.665123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774552.680741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.696379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.712001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.727605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774552.743245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.758898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.774491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.790124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774552.805738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.821388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.836986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774553.852718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.868237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.883869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.899487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774553.915117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.930736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.946445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.962000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774553.977608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774554.993301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774555.008892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774555.024521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774555.040149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774555.055761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774555.071379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774555.087002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774555.102621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774555.118247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774555.133868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774555.149707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.165143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.180764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774556.196483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.212011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.227620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.243328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774556.258906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.274539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.290122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.305756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774556.321372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.337027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.352719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774557.368236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.383869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.399492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.415143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774557.430750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.446448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.462249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.477604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774557.493242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.508914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.524501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774558.540143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.555753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.571372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.586992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774558.602611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.618251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.633855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.649702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774558.665118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.680779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.696448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774559.712000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.727617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.743336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.758901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774559.774495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.790113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.805737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.821364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774559.846415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774560.852890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774560.868263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774560.883875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774560.899515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774560.915121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774560.930749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774560.946428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774560.962014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774560.977620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774560.993242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774561.008871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.024568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.040155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774562.055768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.071374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.087015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.102621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774562.118261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.133870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.149752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.165133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774562.180735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.196442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.212000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774563.227626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.243245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.258900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.274496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774563.290112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.305731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.321366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.336980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774563.352631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.368670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.384020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774564.399651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.415134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.430747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.446483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774564.462286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.477608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.493255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.508878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774564.524511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.540203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.555764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774565.571376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.586987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.602621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.618241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774565.633885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.649712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.665142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.680743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774565.696568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.712032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.727627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774566.743235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.758913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.774483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.790109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774566.805743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.821363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.836985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.852604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774566.868295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774567.883915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774567.899498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774567.915118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774567.930741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774567.946408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774567.962027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774567.977609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774567.993246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774568.008876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774568.024521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774568.040149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.055789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.071364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774569.087013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.102613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.118260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.133859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774569.149714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.165118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.180737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.196396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774569.211998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.227796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.243243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774570.258893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.274489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.290117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.305742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774570.321398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.336975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.352600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.368240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774570.383861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.399509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.415137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774571.430720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.446386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.462222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.477603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774571.493228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.508857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.524488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.540121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774571.555728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.571405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.586990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774572.602614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.618231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.633864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.649704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774572.665130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.680733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.696398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.711996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774572.727607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.743272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.758880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774573.774489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.790143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.805744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.821379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774573.836997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.852744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.868251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.883872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774573.899492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774574.915293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774574.930820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774574.946459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774574.962056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774574.977629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774574.993236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774575.008861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774575.024508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774575.040166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774575.055736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774575.071435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.087101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.102612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774576.118275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.133855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.149488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.165135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774576.180745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.196376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.211977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.227625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774576.243229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.258938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.274479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774577.290113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.305748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.321366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.337000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774577.352610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.368255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.383871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.399480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774577.415141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.430805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.446383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774578.462282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.477623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.493258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.508871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774578.524508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.540140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.555736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.571374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774578.587000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.602648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.618237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774579.633874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.649621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.665124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.680744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774579.696367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.711985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.727608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.743235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774579.758889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.774511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.790121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774580.805735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.821391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.836983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.852616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774580.868253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.883862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.899480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.915108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774580.930724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774581.946458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774581.962015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774581.978016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774581.993401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774582.008955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774582.024673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774582.040443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774582.056097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774582.071585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774582.087006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774582.102854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.118469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.133885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774583.149628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.165131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.180747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.196373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774583.211985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.227632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.243245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.258892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774583.274503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.290149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.305751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774584.321370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.336989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.352608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.368266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774584.383879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.399492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.415140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.431177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774584.446364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.462461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.477638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774585.493257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.509037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.524528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.540139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774585.555782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.573771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.587018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.602671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774585.618367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.633991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.649694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774586.665197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.680809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.696461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.712122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774586.727685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.743335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.758923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.774560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774586.790103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.805840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.821374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774587.837055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.852607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.868256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.883864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774587.899479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.915109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.930728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.946351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774587.961988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774588.977633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774588.993239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774589.008858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774589.024510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774589.040143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774589.055738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774589.071370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774589.086978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774589.102600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774589.118235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774589.133844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.149634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.165125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774590.180730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.196349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.211982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.227597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774590.243240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.258884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.274526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.290095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774590.305744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.321450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.336991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774591.352620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.368250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.383872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.399487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774591.415135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.430741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.446359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.462250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774591.477639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.493286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.508873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774592.524505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.540138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.555856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.571376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774592.586982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.602603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.618255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.633858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774592.649478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.665130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.680730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774593.696363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.711984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.727610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.743237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774593.758871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.774490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.790111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.805725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774593.821355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.837060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.852635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774594.868257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.883864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.899477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.915152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774594.930742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.946353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.961994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.977635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774594.993232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.008887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.024505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774596.040129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.055813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.071383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.087032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774596.102604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.118252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.133872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.149595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774596.165106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.180768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.196363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774597.211976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.227607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.243229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.258887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774597.274490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.290105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.305727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.321364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774597.336987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.352745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.368259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774598.383857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.399491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.415125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.430735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774598.446359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.462213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.477622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.493222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774598.508858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.524586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.540151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774599.555850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.571419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.587016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.602642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774599.618218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.633868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.649619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.665095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774599.680742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.696439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.711994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774600.727625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.743243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.758879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.774506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774600.790101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.805722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.821349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.836968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774600.852617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774601.868389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774601.883882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774601.899582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774601.915106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774601.930718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774601.946349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774601.962044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774601.977656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774601.993276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774602.008939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774602.024497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.040167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.055744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774603.071370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.086997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.102595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.118250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774603.133856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.149611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.165102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.180734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774603.196341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.212004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.227605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774604.243231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.258890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.274487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.290156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774604.305722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.321353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.336993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.352600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774604.368217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.383893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.399472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774605.415119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.430728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.446350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.462193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774605.477625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.493244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.508848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.524487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774605.540116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.555781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.571384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774606.586991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.602599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.618243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.633851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774606.649603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.665098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.680735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.696345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774606.711980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.727626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.743227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774607.758879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.774489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.790105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.805724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774607.821360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.836974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.852608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.868224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774607.883859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774608.899550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774608.915115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774608.930726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774608.946361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774608.961976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774608.977623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774608.993235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774609.008853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774609.024513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774609.040121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774609.062315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.071409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.087001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774610.102596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.118226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.133862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.149605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774610.165098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.180736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.196359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.211979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774610.227590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.243290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.258883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774611.274492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.290102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.305725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.321347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774611.336964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.352588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.368232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.383856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774611.399470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.415160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.435961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774612.446356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.462234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.477615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.493514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774612.508854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.524494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.540134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.563205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774612.571349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.587000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.602600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774613.618233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.633853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.649581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.665108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774613.680736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.696526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.711972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.727611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774613.743233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.758931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.774591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774614.790104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.805733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.821360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.836980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774614.852602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.868227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.883880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.899480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774614.915121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774615.930772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774615.946412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774615.961988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774615.977632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774615.993244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774616.008875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774616.024504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774616.040146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774616.063329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774616.071355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774616.087061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.102654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.118250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774617.133860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.149604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.165108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.180755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774617.196356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.211993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.227599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.243241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774617.258881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.274518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.290105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774618.305723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.321349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.336968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.352605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774618.368232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.383862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.399466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.415122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774618.430710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.446369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.462192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774619.477613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.493231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.508844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.524496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774619.540121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.563325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.571354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.586981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774619.602612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.618264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.633851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774620.649601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.665098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.680757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.696341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774620.711978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.727586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.743224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.758879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774620.774486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.790215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.805750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774621.821353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.836976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.852588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.868213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774621.883882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.899472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.915104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.930721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774621.946419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774622.962020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774622.977615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774622.993226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774623.008858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774623.024499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774623.040130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774623.063125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774623.071341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774623.086991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774623.102596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774623.118224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.133883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.149597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774624.165102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.180734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.196353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.211979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774624.227603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.243228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.258880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.274473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774624.290124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.305757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.321351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774625.336969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.352607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.368215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.383875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774625.399461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.415101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.430706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.446348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774625.462192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.477643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.493225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774626.508855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.524474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.540135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.563834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774626.571355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.586992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.602590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.618212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774626.633835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.649636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.665101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774627.680742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.696358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.711977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.727610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774627.743217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.758886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.774477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.790109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774627.805726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.821393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.836973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774628.852597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.868212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.883857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.899474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774628.915098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.930734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.946340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.961968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774628.977590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774629.993299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774630.008869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774630.024507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774630.040145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774630.055721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774630.071342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774630.087010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774630.102597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774630.118229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774630.133854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774630.149618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.165137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.180749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774631.196356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.211979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.227592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.243248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774631.258882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.274474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.290121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.305717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774631.321353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.337006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.352609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774632.368231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.383875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.399480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.415130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774632.430741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.446350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.462301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.477604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774632.493239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.508928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.524484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774633.540136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.555727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.571345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.586988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774633.602596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.618221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.633841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.649600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774633.665088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.680769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.696437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774634.712049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.727598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.743220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.758872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774634.774462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.790113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.805716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.821338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774634.836964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774635.852621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774635.868217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774635.883864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774635.899471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774635.915143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774635.930706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774635.946335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774635.962030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774635.977579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774635.993234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774636.008852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.024580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.040136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774637.055726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.071343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.086984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.102601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774637.118231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.133840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.149578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.165090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774637.180713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.196461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.211974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774638.227586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.243225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.258862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.274464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774638.290105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.305705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.321337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.336969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774638.352583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.368318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.383855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774639.399465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.415101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.430735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.446341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774639.462252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.477581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.493236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.508834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774639.524478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.540167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.555731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774640.571379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.586993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.602597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.618216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774640.633844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.649589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.665093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.680716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774640.696360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.712027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.727610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774641.743234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.764220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.774450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.790106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774641.805809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.821369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.836975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.852605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774641.868217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774642.883890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774642.899476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774642.915104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774642.930723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774642.946340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774642.961975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774642.977586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774642.993228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774643.008842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774643.024484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774643.040114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.055736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.071360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774644.087050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.102611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.118237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.133846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774644.149578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.165095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.180713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.196362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774644.211975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.227635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.243226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774645.258875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.274472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.290114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.305726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774645.321349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.336961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.352586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.368212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774645.383848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.399494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.415113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774646.430719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.446337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.462191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.477591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774646.493235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.508845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.524480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.540116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774646.555714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.571462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.587099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774647.602603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.618262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.634003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.649615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774647.665144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.680715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.696820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.711979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774647.727589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.743246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.758872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774648.774469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.790107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.805706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.821342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774648.836972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.852581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.868212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.883853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774648.899476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774649.915117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774649.930724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774649.946338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774649.961961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774649.977580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774649.993224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774650.008836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774650.024482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774650.040110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774650.055715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774650.071333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.087025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.102602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774651.118230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.133847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.149589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.165087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774651.180719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.196349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.211959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.227588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774651.243206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.258894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.274470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774652.290116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.305720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.321342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.336970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774652.352603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.368212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.383849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.399473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774652.415105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.431165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.446338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774653.462189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.477585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.493240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.508852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774653.524480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.540109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.555715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.571349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774653.586965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.602623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.618228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774654.633848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.649601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.665102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.680725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774654.696575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.711986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.727594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.743228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774654.758866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.774494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.790109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774655.805722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.821346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.836975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.852594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774655.868229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.883955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.899475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.915088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774655.930705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774656.946357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774656.961976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774656.977585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774656.993237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774657.008839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774657.024490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774657.040112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774657.055723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774657.071329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774657.086965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774657.102593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.118245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.133869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774658.149582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.165083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.180711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.196359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774658.211973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.227592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.243219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.258855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774658.274453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.290123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.305769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774659.321340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.336968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.352595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.368374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774659.383846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.399481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.415106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.430711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774659.446335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.462262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.477599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774660.493230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.508847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.524464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.540112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774660.555714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.571343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.586954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.602590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774660.618205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.633885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.649607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774661.665086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.680713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.696380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.711970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774661.727632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.743211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.758870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.774470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774661.790079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.805776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.821342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774662.836975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.852588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.868224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.883865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774662.899474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.915081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.930709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.946325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774662.961983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774663.977628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774663.993225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774664.008842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774664.024494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774664.040123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774664.055738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774664.071345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774664.087048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774664.102604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774664.118219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774664.133833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.149611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.165137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774665.180715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.196355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.211965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.227595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774665.243208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.258869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.274457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.290089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774665.305739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.321398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.336968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774666.352592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.368210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.383856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.399475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774666.415093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.431155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.446339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.462213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774666.477589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.493257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.508851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774667.524473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.540129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.555726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.571345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774667.586961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.602602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.618204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.633832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774667.649584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.665115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.680721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774668.696358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.711973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.727594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.743218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774668.758874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.774461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.790086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.805752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774668.821343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.837012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.852591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774669.868221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.883842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.899491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.915063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774669.930689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.946328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.961981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.977586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774669.993208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.008885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.024504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774671.040132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.055743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.071342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.086967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774671.102621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.118223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.133841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.149579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774671.165086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.180898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.196356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774672.211966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.227584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.243218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.258864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774672.274453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.290084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.305728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.321347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774672.336961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.352635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.368207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774673.383853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.399476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.415102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.431143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774673.446345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.462179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.477582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.493212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774673.508883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.524841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.540127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774674.555788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.571394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.587040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.602620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774674.618267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.633844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.649625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.665092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774674.680723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.696485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.712098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774675.727670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.743812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.758898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.774534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774675.790288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.805928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.821355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.837146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774675.852679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774676.868267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774676.883835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774676.899514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774676.915463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774676.930727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774676.946819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774676.962070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774676.977665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774676.993459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774677.008933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774677.024492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.040175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.055748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774678.071336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.086970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.102604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.118207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774678.133827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.149582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.165074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.180709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774678.196328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.212034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.227585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774679.243211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.258854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.274460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.290093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774679.305741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.321330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.337001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.352588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774679.368214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.384131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.399514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774680.415107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.431436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.446379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.462215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774680.477623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.493680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.508853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.524472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774680.540121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.555821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.571355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774681.586963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.602608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.618225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.633929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774681.649623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.665091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.680720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.696470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774681.711989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.727604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.743212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774682.758831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.774479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.790085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.805854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774682.821336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.836961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.852574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.868207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774682.883865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774683.899504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774683.915095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774683.930712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774683.946346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774683.961959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774683.977623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774683.993203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774684.008851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774684.024491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774684.040121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774684.055726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.071384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.086962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774685.102610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.118214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.133840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.149604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774685.165085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.180800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.196338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.212041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774685.227581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.243245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.258863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774686.274486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.290086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.305736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.321349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774686.336952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.352578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.368202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.383852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774686.399446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.415200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.430723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774687.446333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.462286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.477582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.493213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774687.508842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.524467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.540095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.555719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774687.571486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.586970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.602599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774688.618209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.633842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.649595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.665075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774688.680698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.696324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.711959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.727585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774688.743203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.758885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.774465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774689.790091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.805724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.821333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.836960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774689.852579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.868212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.883819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.899448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774689.915092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774690.930851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774690.946347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774690.961968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774690.977614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774690.993564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774691.008859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774691.024476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774691.040103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774691.055730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774691.071332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774691.086956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.102620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.118233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774692.133847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.149615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.165073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.180698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774692.196321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.211991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.227572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.243197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774692.258853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.274500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.290129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774693.305790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.321393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.337008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.352586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774693.368227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.383836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.399464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.415112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774693.431272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.446370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.462200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774694.477580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.493221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.508849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.524586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774694.542809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.555722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.571321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.586955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774694.602576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.618242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.633909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774695.649594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.665098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.680706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.696322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774695.711982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.727574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.743221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.758854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774695.774473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.790106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.805827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774696.821426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.836953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.852570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.868211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774696.883818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.899451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.915095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.930784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774696.946336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774697.962069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774697.977674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774697.993217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774698.008849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774698.024490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774698.040104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774698.063118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774698.071330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774698.086957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774698.102569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774698.118214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.133879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.149570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774699.165073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.180712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.196354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.211976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774699.227575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.243212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.258844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.274458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774699.290073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.305796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.321337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774700.336955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.352569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.368193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.383820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774700.399440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.415101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.430702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.446333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774700.462172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.477625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.493211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774701.508853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.524468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.540135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.563214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774701.571330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.586946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.602573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.618219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774701.633843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.649695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.665096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774702.680716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.696340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.711966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.727583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774702.743209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.758865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.774461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.790075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774702.805714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.821378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.836968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774703.852583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.868220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.883829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.899479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774703.915098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.930686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.946327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.961955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774703.977572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774704.993246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774705.008848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774705.024491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774705.040112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774705.063164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774705.071327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774705.086953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774705.102577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774705.118219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774705.133824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774705.149442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.165127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.180712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774706.196351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.211968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.227600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.243211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774706.258858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.274472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.290089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.305715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774706.321343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.336966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.352577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774707.368220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.383824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.399457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.415097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774707.430704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.446321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.462158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.477563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774707.493195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.508872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.524469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774708.540094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.563119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.571328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.586953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774708.602577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.618224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.633835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.649445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774708.665190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.680727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.696456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774709.711973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.727588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.743206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.758858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774709.774449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.790084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.805782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.821363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774709.836950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774710.852624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774710.868194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774710.883816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774710.899437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774710.915092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774710.930775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774710.946609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774710.962037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774710.977647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774710.993215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774711.008891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.024527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.040113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774712.063294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.071330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.087031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.102571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774712.118219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.133833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.149454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.165200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774712.180695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.196372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.211971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774713.227581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.243207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.258845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.274454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774713.290069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.305795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.321341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.336963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774713.352580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.368308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.383827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774714.399456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.415108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.430709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.446334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774714.462219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.477657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.493249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.508841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774714.524523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.540146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.555794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774715.571338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.586949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.602580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.618228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774715.633829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.649583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.665079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.680711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774715.696331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.712028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.727570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774716.743186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.758843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.774448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.790068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774716.805772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.821339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.836924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.852553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774716.868193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774717.883865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774717.899458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774717.915079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774717.930700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774717.946405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774717.962038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774717.977665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774717.993290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774718.008901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774718.024476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774718.040095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.055813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.071347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774719.086967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.102585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.118247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.133834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774719.149592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.165074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.180724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.196334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774719.211965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.227629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.243192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774720.258835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.274442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.290062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.305779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774720.321320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.336940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.352556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.368202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774720.383808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.399469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.415101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774721.431194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.446364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.462161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.477608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774721.493196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.508824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.524468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.540090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774721.555757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.571374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.586951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774722.602567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.618218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.633824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.649677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774722.665079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.680827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.696428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.711941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774722.727689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.743233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.758857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774723.774448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.790085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.805743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.821339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774723.836939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.852570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.868297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.883833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774723.899437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774724.915130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774724.930707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774724.946321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774724.961947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774724.977656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774724.993250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774725.008846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774725.024527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774725.040200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774725.055748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774725.071327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.086981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.102581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774726.118219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.133832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.149570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.165066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774726.180702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.196315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.211934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.227604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774726.243194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.258890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.274456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774727.290069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.305730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.321337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.336959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774727.352565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.368203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.383814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.399437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774727.415092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.430720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.446338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774728.462156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.477596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.493202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.508833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774728.524473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.540111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.555742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.571329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774728.586942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.602599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.618229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774729.633823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.649678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.665069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.680708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774729.696319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.711970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.727586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.743205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774729.758841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.774476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.790074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774730.805743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.821343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.836945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.852577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774730.868192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.883835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.899473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.915078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774730.930701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774731.946356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774731.961965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774731.977566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774731.993188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774732.008829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774732.024493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774732.040103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774732.055725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774732.071333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774732.087037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774732.102568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.118277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.133813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774733.149561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.165073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.180691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.196317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774733.211941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.227573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.243194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.258827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774733.274429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.290112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.305757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774734.321336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.337002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.352566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.368197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774734.383826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.399451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.415091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.430703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774734.446317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.462254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.477596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774735.493200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.508827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.524469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.540103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774735.555713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.571357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.586950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.602585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774735.618197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.633913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.649578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774736.665064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.680696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.696312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.711937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774736.727589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.743188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.758847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.774438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774736.790135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.805733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.821338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774737.836939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.852585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.868190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.883830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774737.899441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.915084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.930701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.946312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774737.961945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774738.977600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774738.993201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774739.008824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774739.024484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774739.040102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774739.055708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774739.071319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774739.086953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774739.102557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774739.118200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774739.133821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.149611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.165070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774740.180702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.196314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.211939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.227582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774740.243214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.258959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.274460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.290157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774740.305733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.321393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.336940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774741.352572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.368188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.383805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.399432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774741.415087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.430700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.446316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.462191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774741.477556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.493260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.508827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774742.524463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.540095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.555690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.571324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774742.586937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.602554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.618180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.633841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774742.649576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.665081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.680689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774743.696315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.711948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.727586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.743190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774743.758834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.774445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.790071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.805678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774743.821314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.836982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.852567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774744.868197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.883824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.899452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.915068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774744.930717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.946324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.961940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.977561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774744.993183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.008868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.024478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774746.040093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.055699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.071311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.086936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774746.102560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.118207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.133836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.149568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774746.165054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.180715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.196318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774747.211944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.227573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.243194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.258834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774747.274445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.290046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.305703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.321315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774747.336949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.352600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.368186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774748.383822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.399445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.415089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.430712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774748.446316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.462157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.477571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.493182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774748.508813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.524510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.540085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774749.555706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.571316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.586941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.602569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774749.618196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.633821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.649558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.665054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774749.680679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.696329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.711947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774750.727585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.743332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.758936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.774451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774750.790057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.805676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.821306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.836942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774750.852554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774751.868224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774751.883820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774751.899442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774751.915076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774751.930715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774751.946335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774751.961946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774751.977578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774751.993188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774752.008819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774752.024456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.040131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.055693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774753.071313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.086959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.102582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.118220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774753.133828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.149552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.165051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.180683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774753.196312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.212051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.227594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774754.243200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.258860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.274439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.290107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774754.305706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.321327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.336960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.352559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774754.368193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.383898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.399490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774755.415131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.430835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.446331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.462161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774755.477556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.493182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.508857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.524485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774755.540141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.555709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.571315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774756.586937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.602559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.618185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.633826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774756.649575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.665050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.680680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.696306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774756.711933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.727597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.743181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774757.758839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.774433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.790061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.805684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774757.821317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.836943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.852549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.868175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774757.883799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774758.899484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774758.915060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774758.930732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774758.946310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774758.961987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774758.977545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774758.993185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774759.008806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774759.024449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774759.040083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774759.055680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.071336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.087002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774760.102560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.118205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.133816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.149544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774760.165053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.180687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.196305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.211925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774760.227559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.243210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.258837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774761.274431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.290053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.305676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.321311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774761.337037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.352566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.368171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.383803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774761.399433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.415127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.430698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774762.446318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.462165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.477567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.493181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774762.508811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.524433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.540083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.555696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774762.571415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.586994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.602576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774763.618203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.633846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.649585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.665071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774763.680701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.696506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.711954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.727570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774763.743219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.758858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.774453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774764.790068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.805696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.821304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.836945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774764.852567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.868180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.883812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.899424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774764.915066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774765.930729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774765.946319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774765.962191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774765.977549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774765.993169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774766.008808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774766.024723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774766.040126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774766.055677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774766.072023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774766.086982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.102795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.118305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774767.133820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.149663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.165066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.180686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774767.196343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.211935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.227660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.243203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774767.258837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.274478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.290065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774768.305690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.321320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.336953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.352565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774768.368171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.383815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.399432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.415081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774768.430678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.446348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.462168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774769.477565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.493182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.508817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.524441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774769.540106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.555693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.571311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.586931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774769.602555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.618269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.633832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774770.649602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.665056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.680693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.696303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774770.711931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.727568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.743193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.758830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774770.774452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.790131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.805986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774771.821329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.836960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.852563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.868200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774771.883820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.899437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.915057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.930685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774771.946405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774772.961971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774772.977578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774772.993178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774773.008817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774773.024456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774773.040106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774773.055679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774773.071298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774773.086936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774773.102556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774773.118223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.133892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.149586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774774.165064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.180694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.196320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.211949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774774.227564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.243206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.258833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.274446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774774.290062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.305761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.321324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774775.336948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.352575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.368182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.383815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774775.399431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.415082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.430673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.446399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774775.462164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.477613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.493196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774776.508816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.524442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.540094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.555691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774776.571346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.586924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.602553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.618181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774776.633806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.649655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.665070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774777.680693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.696309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.711943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.727554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774777.743204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.758836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.774433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.790063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774777.805672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.821348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.836952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774778.852568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.868176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.883802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.899448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774778.915050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.930678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.946396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.961930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774778.977547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774779.993242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774780.008819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774780.024473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774780.040102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774780.055695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774780.071304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774780.086994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774780.102560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774780.118197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774780.133796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774780.149634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.165098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.180682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774781.196304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.211936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.227559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.243202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774781.258819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.274429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.290050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.305671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774781.321304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.336960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.352555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774782.368162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.383800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.399418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.415071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774782.430671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.446385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.462132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.477535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774782.493193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.508830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.524431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774783.540091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.555674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.571307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.586920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774783.602540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.618172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.633803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.649595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774783.665107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.680694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.696305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774784.711919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.727540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.743192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.758816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774784.774412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.790035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.805663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.821301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774784.836933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774785.852652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774785.868174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774785.883802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774785.899426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774785.915051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774785.930671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774785.946397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774785.961925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774785.977539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774785.993171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774786.008792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.024481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.040084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774787.055679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.071303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.086930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.102542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774787.118193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.133794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.149625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.165038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774787.180666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.196416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.211931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774788.227556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.243187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.258811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.274410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774788.290040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.305662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.321300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.336920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774788.352637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.368222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.383803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774789.399415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.415080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.430668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.446393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774789.462125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.477536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.493165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.508789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774789.524415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.540223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.555704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774790.571307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.586921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.602547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.618179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774790.633808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.649657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.665054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.680676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774790.696296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.711987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.727565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774791.743205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.758842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.774414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.790078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774791.806015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.821357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.836961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.852645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774791.868181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774792.883832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774792.899440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774792.915056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774792.930687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774792.946411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774792.961953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774792.977543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774792.993170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774793.008805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774793.024441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774793.040073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.055715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.071318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774794.086935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.102574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.118184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.133798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774794.149645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.165048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.180668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.196290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774794.211920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.227612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.243213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774795.258835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.274457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.290062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.305791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774795.321311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.337044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.352766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.368191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774795.383810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.399518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.415073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774796.430690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.446407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.462146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.477553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774796.493193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.508798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.524438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.540076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774796.563349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.571336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.586929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774797.602557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.618190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.633805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.649639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774797.665046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.680672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.696390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.711931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774797.727557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.743218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.758823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774798.774430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.790053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.805674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.821314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774798.836928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.852634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.868169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.883809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774798.899412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774799.915082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774799.931155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774799.946374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774799.961940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774799.977550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774799.993184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774800.008830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774800.024470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774800.040085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774800.055697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774800.071290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.087050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.102619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774801.118311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.133807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.149851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.165260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774801.180843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.196498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.211919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.227764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774801.243172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.258992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.274491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774802.290104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.305932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.321526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.337181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774802.352854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.368251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.383926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.399481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774802.415076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.431629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.446461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774803.462210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.477663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.493762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.508994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774803.524607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.540258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.555976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.571300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774803.587045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.602613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.618187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774804.633803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.649661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.665043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.680681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774804.696303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.711936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.727562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.743172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774804.758829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.774466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.790065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774805.805679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.821300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.836932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.852643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774805.868171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.883853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.899415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.915046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774805.930663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774806.946416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774806.961937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774806.977553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774806.993187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774807.008815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774807.024451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774807.040074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774807.055703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774807.071304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774807.086928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774807.102555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.118215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.133799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774808.149632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.165061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.180676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.196307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774808.211939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.227565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.243187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.258849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774808.274429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.290077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.305676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774809.321306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.336927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.352666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.368170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774809.383811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.399434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.415059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.430667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774809.446294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.462197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.477680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774810.493181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.508942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.524425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.540193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774810.555686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.571306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.586905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.605165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.618273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774810.633881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774810.649587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774810.665107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774810.680695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774810.696318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774811.711936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774811.727563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774811.743165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774811.758840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774811.774415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774811.790048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774811.805679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774811.821289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774811.836909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774811.852558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774811.868198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774812.883895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774812.899441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774812.915046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774812.930677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774812.946298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774812.961945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774812.977544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774812.993168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774813.008793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774813.024442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774813.040077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.055754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.071297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774814.086929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.102570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.118175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.133795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774814.149535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.165293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.180727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.196301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774814.211911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.227602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.243182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774815.258849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.274422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.290059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.305666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774815.321307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.336922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.352540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.368192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774815.383791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.399480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.415113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774816.430684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.446308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.462193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.477562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774816.493176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.508794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.524421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.540067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774816.555694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.571325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.586920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774817.602543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.618174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.633809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.649556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774817.665063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.680677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.696291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.711938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774817.727546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.743222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.758852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774818.774427 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.790053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.805683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.821333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774818.836941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.852538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.868193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.883793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774818.899423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774819.915098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774819.930832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774819.946301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774819.961962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774819.977556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774819.993180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774820.008806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774820.024456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774820.040078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774820.055678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774820.071318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.086965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.102543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774821.118167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.133795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.149537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.165075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774821.180670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.196286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.211914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.227546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774821.243187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.258853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.274417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774822.290054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.305667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.321291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.336917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774822.352539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.368188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.383799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.399414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774822.415072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.430729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.446321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774823.462222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.477568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.493205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.508828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774823.524444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.540079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.555671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.571320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774823.586918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.602568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.618181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774824.633810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.649546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.665091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.680685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774824.696304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.711913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.727555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.743176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774824.758819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.774435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.790061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774825.805675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.821307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.836928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.852546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774825.868198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.883789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.899448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.915074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774825.930670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774826.946341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774826.961947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774826.977541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774826.993168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774827.008800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774827.024440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774827.040077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774827.055672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774827.071318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774827.086935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774827.102552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.118202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.133801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774828.149522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.165071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.180663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.196302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774828.211933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.227542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.243156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.258828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774828.274427 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.290223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.305754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774829.321304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.336930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.352553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.368241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774829.383788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.399417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.415094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.430676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774829.446282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.462194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.477543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774830.493176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.508791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.524468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.540074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774830.555721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.571306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.586911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.602551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.618163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774830.633839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774830.649574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774830.665064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774830.680694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774830.696328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774831.711986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774831.727542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774831.743191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774831.758827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774831.774453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774831.790052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774831.805697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774831.821382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774831.836932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774831.852548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774831.868184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774832.883859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774832.899429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774832.915065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774832.930660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774832.946289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774832.961911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774832.977557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774832.993162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774833.008800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774833.024437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774833.040072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.055745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.071317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774834.086952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.102552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.118181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.133806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774834.149559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.165069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.180686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.196303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774834.211931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.227588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.243177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774835.258821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.274448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.290050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.305677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774835.321298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.336917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.352550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.368170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774835.383827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.399563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.415102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774836.430668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.446312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.462137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.477560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774836.493172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.508794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.524411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.540065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774836.555657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.571346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.586917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774837.602544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.618170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.633811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.649551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774837.665069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.680679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.696480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.711918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774837.727554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.743184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.758818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774838.774421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.790038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.805655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.821299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774838.836905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.852532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.868154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.883797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774838.899401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774839.915152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774839.930739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774839.946295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774839.961915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774839.977580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774839.993153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774840.008791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774840.024433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774840.040069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774840.055654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774840.071286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.087089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.102554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774841.118175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.133801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.149665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.165044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774841.180677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.196463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.211922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.227632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774841.243163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.258843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.274431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774842.290044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.305669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.321301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.336921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774842.352534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.368155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.383795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.399410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774842.415072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.430700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.446296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774843.462127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.477554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.493242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.508787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774843.524428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.540046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.555667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.571280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774843.586918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.602558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.618171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774844.633800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.649533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.665051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.680678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774844.696284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.711912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.727530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.743153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774844.758810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.774449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.790046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774845.805658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.821293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.836907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.852538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774845.868168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.883803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.899418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.915035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774845.930653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774846.946322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774846.961932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774846.977555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774846.993189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774847.008805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774847.024441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774847.040074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774847.055668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774847.071290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774847.086935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774847.102544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.118199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.133783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774848.149530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.165054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.180677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.196291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774848.211908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.227551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.243191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.258808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774848.274408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.290067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.305683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774849.321304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.336911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.352542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.368155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774849.383801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.399418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.415062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.430655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774849.446281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.462143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.477545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774850.493156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.508782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.524415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.540041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774850.555660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.571330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.586914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.602521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774850.618173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.633850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.649532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774851.665061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.680685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.696315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.711921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774851.727539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.743170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.758854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.774466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774851.790061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.811261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.821263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774852.836896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.852509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.868154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.883805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774852.899422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.915051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.930667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.946296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774852.961926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774853.977595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774853.993159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774854.008800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774854.024441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774854.040066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774854.055676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774854.071289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774854.086957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774854.102537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774854.118153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774854.133782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.149622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.165060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774855.180676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.196291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.211909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.227551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774855.243151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.258819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.274408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.290062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774855.305662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.321481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.336951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774856.352543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.368524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.383817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.399622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774856.415286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.431232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.446790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.462540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774856.477897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.493313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.508890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774857.524723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.540299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.555971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.571399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774857.587000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.602533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.618163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.633803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774857.649785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.665084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.680689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774858.696283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.711918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.727532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.743168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774858.758810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.774424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.790062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.805669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774858.821281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.836941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.852542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774859.868172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.883806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.899432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.915049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774859.930664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.946296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.961918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.977534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774859.993182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.008920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.024458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774861.040092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.055676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.071286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.086959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774861.102540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.118171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.133781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.149557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774861.165061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.180796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.196289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774862.211905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.227541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.243170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.258856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774862.274398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.290049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.305652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.321338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774862.336918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.352639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.368229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774863.383809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.399413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.415082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.430656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774863.446298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.462161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.477602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.493182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774863.508861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.524448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.540052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774864.555665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.571286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.586930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.602545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774864.618181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.633796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.649716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.665075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774864.680662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.696468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.711927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774865.727531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.743158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.758822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.774404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774865.790053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.805659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.821292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.836911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774865.852538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774866.868197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774866.883797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774866.899423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774866.915111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774866.930669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774866.946280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774866.961916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774866.977533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774866.993181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774867.008790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774867.024442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.040100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.055661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774868.071302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.086984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.102534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.118180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774868.133796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.149527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.165143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.180652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774868.196310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.212039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.227544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774869.243251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.258933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.274404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.290054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774869.305659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.321288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.336910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.352529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774869.368203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.383917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.399405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774870.415161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.430655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.446281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.462122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774870.477523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.493165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.508774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.524405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774870.540061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.555718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.571288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774871.586935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.602548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.618162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.633799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774871.649549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.665095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.680645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.696300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.711902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774871.727548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774871.743185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774871.758925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774871.774418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774871.790013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342774872.805776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774872.821282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774872.836996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774872.852537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774872.868164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774872.883817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774872.899431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774872.915420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774872.930654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774872.946282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774872.961906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774873.977695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774873.993193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774874.008802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774874.024435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774874.040073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774874.062739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774874.071288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774874.086916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774874.102548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774874.118150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774874.133775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.149584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.165085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774875.180664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.196343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.211941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.227532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774875.243169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.258801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.274410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.290041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774875.305664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.321311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.336964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774876.352578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.368174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.383789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.399422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774876.415112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.430665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.446284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.462123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774876.477520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.493200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.508782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774877.524425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.540051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.562722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.571291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774877.586912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.602561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.618156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.633780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774877.649414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.665097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.680669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774878.696294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.711910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.727541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.743180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774878.758811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.774405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.790027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.805658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774878.821271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.836915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.852527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774879.868150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.883789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.899425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.915091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774879.930667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.946282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.961910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.977532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774879.993144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.008925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.024428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774881.040059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.062738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.071275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.086908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774881.102546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.118191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.133776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.149416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774881.165201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.180713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.196298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774882.211915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.227548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.243174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.258803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774882.274433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.290036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.305689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.321290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774882.336897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.352672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.368412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774883.383812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.399444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.415096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.430657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774883.446290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.462201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.477531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.493174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774883.508839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.524452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.540063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774884.555667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.571295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.586916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.602541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774884.618170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.633778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.649561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.665067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774884.680662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.696335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.711910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774885.727524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.743162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.758805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.774404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774885.790035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.805782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.821282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.836912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774885.852524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774886.868172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774886.883775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774886.899439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774886.915042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774886.930746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774886.946364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774886.961988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774886.977617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774886.993157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774887.008796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774887.024433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.040108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.055668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774888.071285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.086985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.102544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.118169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774888.133780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.149535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.165054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.180641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774888.196272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.211946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.227539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774889.243198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.258812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.274398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.290029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774889.305671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.321284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.336915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.352547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774889.368162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.383850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.399433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774890.415065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.430645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.446270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.462132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774890.477530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.493141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.508785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.524410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774890.540039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.555716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.571297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774891.586916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.602549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.618169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.633780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774891.649551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.665030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.680642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.696275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774891.711912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.727583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.743154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774892.758799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.774404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.790027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.805839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774892.821276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.836932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.852526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.868161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774892.883791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774893.899477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774893.915040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774893.930650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774893.946282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774893.961902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774893.977525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774893.993154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774894.008789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774894.024424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774894.040043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774894.055651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.071326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.086916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774895.102537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.118169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.133776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.149522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774895.165021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.180639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.196264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.211896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774895.227514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.243212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.258816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774896.274402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.290033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.305671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.321286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774896.336900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.352522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.368154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.383780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774896.399386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.415242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.430666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774897.446295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.462129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.477539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.493150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774897.508802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.524412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.540047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.555655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774897.571275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.586943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.602541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774898.618157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.633780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.649522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.665028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774898.680656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.696282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.711918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.727524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774898.743164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.758831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.775740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774899.790028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.805849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.821290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.836907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774899.852526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.868140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.883789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.899392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774899.915042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774900.930673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774900.946279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774900.961900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774900.977517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774900.993145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774901.008784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774901.024420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774901.040043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774901.055639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774901.071266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774901.086894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.102609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.118171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774902.133790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.149550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.165037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.180655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774902.196409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.211928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.227541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.243150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774902.258821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.274430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.290026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774903.305660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.321274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.336904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.352535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774903.368252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.383788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.399418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.415074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774903.430650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.446325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.462131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774904.477535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.493151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.508798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.524413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774904.540057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.555655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.571283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.586892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774904.602509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.618178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.633812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774905.649520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.665018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.680661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.696265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774905.711924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.727517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.743143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.758792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774905.774399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.790068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.805670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774906.821282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.836888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.852530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.868145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774906.883775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.899403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.915052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.930647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774906.946290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774907.961944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774907.977522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774907.993147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774908.008794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774908.024420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774908.040054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774908.055655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774908.071284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774908.086974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774908.102523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774908.118187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.133791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.149533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774909.165017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.180657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.196270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.211914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774909.227523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.243148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.258792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.274397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774909.290019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.305701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.321273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774910.337019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.352518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.368148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.383882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774910.399499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.415139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.430750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.446382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774910.462090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.477658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.493176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774911.508803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.524417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.540090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.555654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774911.571331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.587004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.602537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.618153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774911.633763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.649559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.665020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774912.680646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.696278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.711935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.727531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774912.743143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.758803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.774412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.790017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774912.805640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.821308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.836897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774913.852521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.868147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.883776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.899403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774913.915036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.930637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.946288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.961889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774913.977508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774914.993227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774915.008808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774915.024530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774915.040074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774915.055803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774915.071329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774915.086973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774915.102577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774915.118174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774915.133883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774915.149526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.165045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.180655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774916.196432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.211934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.227541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.243159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774916.258850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.274403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.290021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.305808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774916.321297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.336928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.352525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774917.368143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.383782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.399393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.415045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774917.430625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.446269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.462129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.477520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774917.493134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.508819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.524404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774918.540053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.555645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.571291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.586893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774918.602512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.618160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.633769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.649504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774918.665004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.680703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.696271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774919.711923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.727515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.743148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.758788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774919.774393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.790012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.805638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.821330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774919.836939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774920.852651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774920.868156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774920.883791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774920.899426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774920.915049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774920.931195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774920.946285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774920.961914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774920.977527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774920.993160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774921.008778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.024499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.040090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774922.055654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.071281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.086931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.102536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774922.118181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.133777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.149631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.165016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774922.180662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.196327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.211998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774923.227579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.243236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.258795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.274390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774923.290019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.305637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.321297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.336890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774923.352526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.368183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.383769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774924.399384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.415071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.430651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.446266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774924.462113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.477515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.493149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.508754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774924.524412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.540077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.555643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774925.571273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.586889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.602523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.618153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774925.633754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.649508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.664998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.680646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774925.696251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.712011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.727525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774926.743135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.758788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.774393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.790010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774926.805633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.821285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.836893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.852504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774926.868146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774927.883793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774927.899387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774927.915028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774927.930673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774927.946253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774927.961897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774927.977504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774927.993125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774928.008766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774928.024424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774928.040084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.055648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.071260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774929.086895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.102502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.118165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.133753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774929.149488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.165004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.180641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.196255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774929.211881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.227635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.243205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774930.258787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.274386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.290014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.305642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774930.321273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.336892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.352519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.368130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774930.383759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.399452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.415080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774931.430640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.446273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.462112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.477511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774931.493134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.508772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.524407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.540038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774931.555633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.571285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.586889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774932.602522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.618167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.633751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.649500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774932.665000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.680633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.696254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.711883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774932.727546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.743180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.758792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774933.774536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.790017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.806024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.821426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774933.836938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.852517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.868181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.883802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774933.899429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774934.915082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774934.930651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774934.946276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774934.961903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774934.977524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774934.993153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774935.008773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774935.024428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774935.040058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774935.055639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774935.071274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.086947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.102520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774936.118181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.133763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.149523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.165018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774936.180647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.196264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.211903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.227534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774936.243153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.258821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.274420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774937.290024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.305659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.321284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.336909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774937.352513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.368140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.383760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.399392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774937.415024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.430661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.446275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774938.462109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.477512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.493147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.508763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774938.524409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.540026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.555648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.571254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774938.586879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.602535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.622575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774939.633762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.649512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.665013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.680642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774939.696254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.711892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.727531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.743144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774939.758794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.774410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.790038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774940.805681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.821284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.836895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.852531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774940.868142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.883752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.899383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.915003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774940.930647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774941.946304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774941.961912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774941.977522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774941.993149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774942.008790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774942.024447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774942.040054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774942.055644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774942.071265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774942.086891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774942.102519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.118183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.133751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774943.149502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.165011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.180889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.196279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774943.211919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.229458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.243163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.258794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774943.274541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.290256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.305651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774944.321291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.336896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.352513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.368134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774944.383758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.399380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.415015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.430662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774944.446258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.462142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.477521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774945.493271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.508782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.524408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.540026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774945.555630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.571266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.586876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.602494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774945.618127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.633882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.649523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774946.665029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.680635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.696469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.711903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774946.727556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.743132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.758825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.774457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774946.790008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.805952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.821458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774947.837080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.852593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.868147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.883991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774947.899500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.915012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.930644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.946258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774947.961893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774948.977587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774948.993142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774949.008783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774949.024432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774949.040054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774949.055637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774949.071282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774949.086892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774949.102507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774949.118142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774949.133772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.149605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.165011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774950.180636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.196255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.211879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.227524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774950.243158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.258785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.274391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.290009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774950.305630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.321394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.336902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774951.352531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.368132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.383749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.399378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774951.415036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.430647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.446253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.462145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774951.477695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.493173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.508895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774952.524410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.540036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.555633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.571254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774952.586881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.602497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.618131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.633765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774952.649497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.665035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.680641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774953.696273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.711886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.727639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.743142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774953.758778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.774376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.790112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.805641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774953.821278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.836964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.852525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774954.868151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.883767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.899395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.915009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774954.930650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.946264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.961890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.977511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774954.993148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.008799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.024429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774956.040046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.055647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.071265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.086930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774956.102525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.118143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.133773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.149517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774956.165012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.180647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.196256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774957.211889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.227522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.243142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.258779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774957.274378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.289996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.305624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.321259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774957.336893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.352527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.368140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774958.383767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.399381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.415027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.430656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774958.446259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.462074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.477506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.493131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774958.508755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.524425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.540038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774959.555709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.571292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.586885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.602512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774959.618128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.633770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.649500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.664997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774959.680627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.696289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.711888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774960.727521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.743138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.758784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.774384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774960.790005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.805635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.821259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.836893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774960.852509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774961.868150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774961.883781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774961.899403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774961.915005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774961.930647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774961.946270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774961.961884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774961.977514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774961.993124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774962.008753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774962.024411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.040080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.055741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774963.071379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.086899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.102512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.118154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774963.133874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.149615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.165015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.180629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774963.196258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.211919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.227529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774964.243131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.258786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.274389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.290001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774964.305638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.321253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.336919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.352503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774964.368146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.383776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.399384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774965.415027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.430662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.446260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.462101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774965.477538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.493146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.508756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.524389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774965.540041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.555671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.571266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774966.586884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.602520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.618136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.633767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774966.649517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.665003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.680675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.696248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774966.711894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.727536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.743149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774967.758777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.774394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.790002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.805635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774967.821262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.836900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.852505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.868135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774967.883755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774968.899402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774968.915008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774968.930645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774968.946260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774968.961890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774968.977507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774968.993130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774969.008757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774969.024411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774969.040037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774969.055641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.071285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.086895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774970.102505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.118162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.133768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.149500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774970.165012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.180658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.196245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.211885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774970.227500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.243143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.258785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774971.274381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.290011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.305628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.321259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774971.336894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.352507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.368128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.383755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774971.399380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.415073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.430658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774972.446261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.462111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.477610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.493134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774972.508755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.524377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.540026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.555624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774972.571249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.586932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.602556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774973.618139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.633772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.649518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.664998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774973.680681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.696273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.711925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.727511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774973.743186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.758814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.774411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774974.790006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.805651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.821254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.836918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774974.852504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.868121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.883753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.899371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774974.915026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774975.931316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774975.946337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774975.961957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774975.977582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774975.993195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774976.008759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774976.024415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774976.040053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774976.055637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774976.071248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774976.086908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.102543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.118147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774977.133774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.149496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.165041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.180628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774977.196257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.211871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.227507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.243133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774977.258771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.274414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.290005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774978.305630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.321252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.336889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.352508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774978.368125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.383745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.399369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.415027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774978.430624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.446288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.462083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774979.477505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.493127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.508800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.524418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774979.540039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.555630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.571256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.586877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774979.602493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.618166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.633774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774980.649503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.665007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.680624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.696243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774980.711881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.727495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.743162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.758768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774980.774383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.790080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.805664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774981.821257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.836911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.852501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.868130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774981.883756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.899370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.915017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.930618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774981.946360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774982.961912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774982.977509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774982.993125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774983.008765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774983.024411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774983.040039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774983.055621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774983.071245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774983.086892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774983.102494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774983.118150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.133823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.149515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774984.165006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.180640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.196316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.211879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774984.227555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.243147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.258846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.274382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774984.290050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.305663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.321271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774985.336891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.352513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.368124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.383753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774985.399385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.414997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.430617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.446342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774985.462153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.477584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.493146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774986.508749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.524398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.540042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.555680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774986.571291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.586979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.602502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.618126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774986.633758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.649525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.665009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774987.680635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.696242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.711878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.727496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774987.743142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.758773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.774389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.790003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774987.805625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.821319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.836901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774988.852503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.868133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.883743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.899369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774988.915007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.930618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.946362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.961898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774988.977499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774989.993145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774990.008762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774990.024415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774990.040031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774990.055627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774990.071249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774990.086898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774990.102499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774990.118145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774990.133740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774990.149573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.165024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.180632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774991.196257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.211871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.227506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.243139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774991.258769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.274385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.289985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.305632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774991.321236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.336942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.352507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774992.368141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.383758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.399379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.415087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774992.430633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.446355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.462110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.477495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774992.493192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.508813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.524740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774993.540058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.555628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.571259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.586874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774993.602494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.618120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.633743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.649586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774993.664988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.680730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.696259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774994.711891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.727515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.743149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.758791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774994.774394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.790003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.805626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.821257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774994.836878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774995.852551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774995.868128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774995.883753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774995.899376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774995.915010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774995.930623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774995.946348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774995.961880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774995.977498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774995.993140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774996.008792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.024452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.040045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774997.055634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.071258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.086886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.102588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774997.118134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.133747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.149577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.164987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774997.180617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.196280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.211890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774998.227498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.243148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.258794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.274391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774998.290002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.305630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.321251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.336868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774998.352589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.368147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.383759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774999.399391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.415038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.431113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.446321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342774999.462085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.477556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.493524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.508761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342774999.524400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.540041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.555632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775000.571265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.586871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.602486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.618109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775000.633740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.649567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.664990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.680613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775000.696231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.711970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.727511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775001.743153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.758796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.774405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.790009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775001.805619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.821247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.836873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.852611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775001.868136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775002.883822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775002.899376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775002.914993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775002.930616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775002.946409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775002.961931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775002.977535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775002.993167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775003.008748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775003.024381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775003.040037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.055714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.071278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775004.086954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.102513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.118135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.133753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775004.149612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.164987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.180623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.196251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775004.211873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.227540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.243145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775005.258775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.274398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.289996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.305631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775005.321242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.336871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.352590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.368110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775005.383740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.399472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.415099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775006.430696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.446340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.462082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.477496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775006.493123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.508746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.524379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.540019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775006.555645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.571268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.586874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775007.602492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.618126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.633745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.649577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775007.664987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.680615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.696239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.711872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775007.727483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.743209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.758790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775008.774382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.789983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.805613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.821263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775008.836865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.852588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.868114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.883750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775008.899356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775009.915033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775009.930632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775009.946358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775009.961875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775009.977502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775009.993112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775010.008753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775010.024402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775010.040020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775010.055635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775010.071236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.086949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.102514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775011.118121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.133752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.149586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.164993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775011.180614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.196242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.211862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.227488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775011.243125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.258797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.274394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775012.290003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.305622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.321240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.336873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775012.352587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.368109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.383748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.399356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775012.415007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.430735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.446349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775013.462081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.477495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.493129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.508749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775013.524383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.540026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.555640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.571252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775013.586862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.602640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.618125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775014.633756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.649542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.665004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.680623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775014.696269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.711910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.727493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.743141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775014.758779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.774411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.789996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775015.805690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.821250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.836906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.852574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775015.868121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.883742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.899361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.914983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775015.930700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775016.946382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775016.961877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775016.977501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775016.993124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775017.008755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775017.024414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775017.040031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775017.055646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775017.071245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775017.086881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775017.102491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.118155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.133783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775018.149619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.164992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.180621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.196240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775018.211872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.227494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.243132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.258873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775018.274389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.290016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.305618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775019.321244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.336861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.352582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.368112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775019.383743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.399368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.415023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.430606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775019.446240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.462094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.477493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775020.493123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.508738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.524394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.540017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775020.555645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.571239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.586859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.602484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775020.618106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.633779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.649563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775021.665000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.680691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.696303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.711865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775021.727492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.743104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.758775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.774366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775021.789987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.805724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.821259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775022.836859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.852565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.868106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.883757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775022.899366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.914983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.930696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.946314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775022.961889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775023.977701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775023.993139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775024.008753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775024.024517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775024.040053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775024.055648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775024.071250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775024.086953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775024.102514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775024.118122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775024.133737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.149616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.164995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775025.180621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.196244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.211863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.227495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775025.243118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.258765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.274449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.289980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775025.305613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.321304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.336876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775026.352605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.368122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.383753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.399375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775026.414995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.430606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.446254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.462156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775026.477488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.493153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.508749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775027.524456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.540008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.555634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.571250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775027.586859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.602487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.618112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.633727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775027.649507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.665010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.680624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775028.696247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.711872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.727489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.743116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775028.758767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.774432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.789983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.805608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775028.821239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.836901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.852601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775029.868110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.883747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.899364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.914992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775029.930606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.946260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.961874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.977480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775029.993103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.008768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.024463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775031.040013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.055643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.071235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.086875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775031.102498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.118127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.133733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.149469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775031.164997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.180655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.196235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775032.211858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.227490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.243105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.258784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775032.274420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.289999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.305619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.321232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775032.336862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.352602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.368113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775033.383744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.399363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.415008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.430614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775033.446242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.462089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.477494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.493113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775033.508774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.524477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.540012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775034.555654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.571246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.586853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.602491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775034.618129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.633726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.649479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.665004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775034.680609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.696252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.711906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775035.727475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.743103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.758766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.774358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775035.789973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.805617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.821226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.836858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775035.852476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775036.868143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775036.883743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775036.899370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775036.914991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775036.931162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775036.946250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775036.961886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775036.977496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775036.993120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775037.008762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775037.024441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.040173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.055649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775038.071253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.086882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.102491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.118138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775038.133736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.149499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.164993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.180610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775038.196225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.211897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.227497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775039.243116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.258784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.274401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.289990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775039.305610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.321241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.336915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.352496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775039.368140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.383817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.399374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775040.415024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.430612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.446229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.462148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775040.477504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.493112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.508739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.524401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775040.540009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.555692 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.571259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775041.586869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.602496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.618131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.633746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775041.649510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.665007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.680623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.696254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775041.711873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.727530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.743140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775042.758847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.774505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.790121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.805910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775042.821232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.836916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.852522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.868135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775042.883767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775043.899490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775043.915005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775043.930620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775043.946255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775043.962021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775043.977502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775043.993165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775044.008748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775044.024430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775044.040173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775044.063300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.071269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.086870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775045.102485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.118118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.133723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.149491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775045.164990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.180595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.196223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.211847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775045.227473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.243129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.258768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775046.274373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.289973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.305607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.321229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775046.336857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.352474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.368120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.383723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775046.399340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.415018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.430607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775047.446233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.462076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.477486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.493098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775047.508734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.524372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.540009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.563076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775047.571240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.586902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.602482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775048.618123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.633735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.649488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.664999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775048.680602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.696226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.711855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.727481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775048.743102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.758798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.774377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775049.789986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.805611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.821239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.836861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775049.852492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.868135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.883742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.899354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775049.914978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775050.930651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775050.946255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775050.961880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775050.977483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775050.993119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775051.008791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775051.024449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775051.040062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775051.063888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775051.071252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775051.086862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.102556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.118176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775052.133779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.149536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.165014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.180594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775052.196223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.211853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.227481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.243099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775052.258846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.274394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.289960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775053.305606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.321239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.336860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.352483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775053.368120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.383732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.399354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.415004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775053.430603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.446271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.462092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775054.477485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.493283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.508857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.524399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775054.540639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.555638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.571284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.586862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775054.602541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.618153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.633744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775055.649494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.665030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.680625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.696247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775055.711872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.727493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.743126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.758758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775055.774389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.790028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.805619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775056.821246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.836864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.852517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.868121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775056.883734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.899357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.914979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.930616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775056.946228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775057.961919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775057.977480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775057.993102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775058.008747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775058.024399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775058.040014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775058.055606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775058.071246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775058.086867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775058.102481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775058.118122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.133772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.149492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775059.165000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.180601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.196268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.211862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775059.227490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.243115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.258747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.274368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775059.289983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.305638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.321241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775060.336854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.352493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.368113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.383727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775060.399389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.414992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.430594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.446222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775060.462073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.477536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.493112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775061.508731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.524375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.540005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.555607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775061.571256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.586853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.602475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.618096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775061.633739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.649517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.665011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775062.680615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.696241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.711860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.727498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775062.743113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.758752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.774384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.789979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775062.805602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.821301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.836859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775063.852774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.868258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.883973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.899361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775063.915002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.930614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.946256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.961873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775063.977518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775064.993230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775065.008745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775065.024392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775065.040036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775065.055612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775065.071251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775065.086878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775065.102483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775065.118130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775065.133720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775065.149495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.165034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.180609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775066.196227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.211863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.227477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.243114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775066.258760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.274372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.289982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.305594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775066.321219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.336894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.352488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775067.368136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.383736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.399365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.415020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775067.430743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.446236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.462063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.477519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775067.493125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.508862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.524379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775068.540035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.555621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.571252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.586860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775068.602479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.618127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.633727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.649496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775068.664973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.680636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.696241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775069.711923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.727484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.743113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.758762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775069.774370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.789982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.805612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.821243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775069.836855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775070.852501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775070.868128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775070.883733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775070.899356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775070.914979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775070.930612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775070.946218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775070.961867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775070.977504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775070.993106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775071.008748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.024457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.040017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775072.055622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.071257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.086939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.102484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775072.118150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.133733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.149483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.164983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775072.180631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.196258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.211898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775073.227483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.243113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.258752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.274373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775073.289978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.305593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.321220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.336851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775073.352467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.368163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.383750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775074.399416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.414996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.430614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.446249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775074.462081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.477489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.493116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.508714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775074.524364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.540056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.555612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775075.571251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.586855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.602485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.618108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775075.633735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.649489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.664969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.680613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775075.696225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.711985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.727493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775076.743100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.758760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.774348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.789986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775076.805598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.821234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.836844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.852469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775076.868092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775077.883804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775077.899355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775077.914991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775077.930625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775077.946238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775077.961863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775077.977539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775077.993096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775078.008721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775078.024368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775078.040009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.055678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.071257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775079.086868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.102485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.118133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.133736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775079.149491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.164980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.180633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.196231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775079.211851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.227525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.243130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775080.258859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.274363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.290081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.305700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775080.321336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.336847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.352482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.368102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775080.383748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.399372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.415001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775081.431043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.446223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.462069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.477497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775081.493113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.508738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.524371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.540004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775081.555606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.571269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.586848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775082.602480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.618111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.633734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.649482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775082.664975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.680613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.696269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.711853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775082.727474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.743143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.758757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775083.774376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.789976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.805604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.821223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775083.836861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.852468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.868115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.883740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775083.899364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775084.915016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775084.930615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775084.946223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775084.961861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775084.977499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775084.993112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775085.008735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775085.024381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775085.040004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775085.055598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775085.071222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.086943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.102516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775086.118166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.133785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.149515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.165029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775086.180695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.196278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.211910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.227519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775086.243141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.258797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.274373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775087.289975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.305614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.321220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.336851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775087.352488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.368108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.383733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.399349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775087.414992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.430623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.446230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775088.462063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.477483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.493102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.508736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775088.524353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.539998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.555602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.571226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775088.586863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.602502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.618101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775089.633726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.649488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.664964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.680615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775089.696218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.711859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.727469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.743103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775089.758746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.774390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.789996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775090.805588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.821221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.836847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.852467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775090.868106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.883733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.899335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.914958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775090.930585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775091.946246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775091.961861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775091.977507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775092.003958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775092.009016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775092.024389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775092.040006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775092.055592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775092.071226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775092.086944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775092.102481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.118146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.133722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775093.149446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.164968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.180615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.196220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775093.211831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.227461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.243074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.258845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775093.274348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.290037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.305610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775094.321228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.336861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.352480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.368105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775094.383741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.399353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.415019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.430602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775094.446226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.462208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.477505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775095.493114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.508732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.524354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.540021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775095.555612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.571268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.586862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.602471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775095.618091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.633741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.649464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775096.664993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.680614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.696216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.711853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775096.727470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.743106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.758747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.774335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775096.789984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.805615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.821235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775097.836858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.852477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.868173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.883742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775097.899367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.914975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.930592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.946230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775097.961843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775098.977522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775098.993105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775099.008732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775099.024376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775099.040000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775099.055611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775099.071230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775099.086872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775099.102466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775099.118102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775099.133722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.149492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.164968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775100.180596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.196207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.211839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.227451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775100.243093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.258744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.274341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.289979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775100.305593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.321251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.336849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775101.352474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.368081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.383745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.399349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775101.415086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.430585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.446217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.462048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775101.477458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.493170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.508733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775102.524351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.540006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.555600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.571219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775102.586883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.602461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.618102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.633725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775102.649461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.664997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.680616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775103.696226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.711851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.727485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.743088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775103.758734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.774333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.789982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.805586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775103.821208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.836904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.852507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775104.868116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.883739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.899353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.914965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775104.930586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.946215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.961847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.977466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775104.993113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.008767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.024380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775106.040009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.055607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.071228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.086884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775106.102474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.118116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.133724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.149474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775106.164984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.180643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.196237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775107.211850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.227471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.243104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.258745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775107.274373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.289991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.305583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.321219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775107.336832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.352486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.368121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775108.383736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.399344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.414997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.430595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775108.446224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.462058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.477465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.493136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775108.508709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.524389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.540015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775109.555613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.571238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.586860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.602481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775109.618112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.633721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.649465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.664962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775109.680595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.696252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.711841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775110.727484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.743098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.758754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.774340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775110.789998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.805591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.821213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.836848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775110.852470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775111.868125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775111.883740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775111.899338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775111.914962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775111.930602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775111.946219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775111.961854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775111.977470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775111.993127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775112.008716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775112.024362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.040066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.055599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775113.071222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.086871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.102476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.118099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775113.133723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.149470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.165093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.180731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775113.196349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.211875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.227483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775114.243104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.258752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.274337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.289995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775114.305601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.321211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.336846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.352461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775114.368102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.383905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.399356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775115.414992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.430600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.446365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.462098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775115.477478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.493321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.508735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.524353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775115.540017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.555635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.571229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775116.586857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.602471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.618100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.633715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775116.649473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.664959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.680586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.696244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775116.711843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.727494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.743118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775117.758757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.774354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.789995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.805598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775117.821226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.836840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.852473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.868084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775117.883715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775118.899386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775118.914995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775118.930599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775118.946226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775118.961849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775118.977468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775118.993091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775119.008723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775119.024354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775119.039981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775119.063043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.071250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.086942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775120.102471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.118117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.133725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.149466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775120.164965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.180586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.196220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.211832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775120.227460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.243110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.258760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775121.274337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.289977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.305588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.321276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775121.336884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.352471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.368273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.383729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775121.399352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.415155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.431302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775122.446266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.462117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.477613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.493150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775122.508819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.524340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.539989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.563149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775122.571209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.586873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.602469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775123.618095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.633712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.649465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.664959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775123.680582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.696254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.711849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.727466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775123.743084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.758803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.774389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775124.790031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.805708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.821216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.836850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775124.852459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.868084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.883725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.899407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775124.915078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775125.931047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775125.946284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775125.961853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775125.977469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775125.993109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775126.008725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775126.024368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775126.040256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775126.063180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775126.071213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775126.086863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.102480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.118112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775127.133716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.149455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.164972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.180587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775127.196231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.211840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.227526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.243084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775127.258797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.274383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.289994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775128.305593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.321222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.336841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.352476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775128.368101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.383742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.399356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.414986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775128.430688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.446263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.462114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775129.477454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.493119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.508716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.524346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775129.539999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.563072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.571238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.586852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775129.602492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.618138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.633737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775130.649479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.664981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.680637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.696242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775130.711897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.727518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.743154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.758780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775130.774388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.790032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.805608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775131.821218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.836846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.852462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.868110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775131.883710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.899352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.914966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.930576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775131.946205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775132.961876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775132.977473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775132.993106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775133.008769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775133.024356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775133.040011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775133.063003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775133.071218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775133.086835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775133.102476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775133.118130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.133759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.149454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775134.164958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.180597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.196244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.211828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775134.227455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.243082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.258738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.274326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775134.289971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.305697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.321278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775135.336848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.352464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.368090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.383743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775135.399437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.414992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.430589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.446227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775135.462114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.477498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.493110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775136.508721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.524338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.539989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.563145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775136.571215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.586831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.602474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.618070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775136.633721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.649516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.664974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775137.680590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.696247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.711842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.727474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775137.743090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.758726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.774327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.789951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775137.805605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.821248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.836841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775138.852464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.868089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.883719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.899366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775138.914958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.930585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.946204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.961840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775138.977451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775139.993181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775140.008728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775140.024363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775140.040005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775140.055595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775140.071213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775140.086942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775140.102472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775140.118108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775140.133725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775140.149458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.164988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.180593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775141.196236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.211839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.227474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.243083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775141.258748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.274341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.289964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.305587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775141.321205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.336865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.352455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775142.368095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.383733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.399315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.415156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775142.431142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.446318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.462045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.477501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.493135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775142.508741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775142.524345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775142.539984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775142.555595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775142.571219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775143.586878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775143.602482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775143.618142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775143.633729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775143.649489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775143.664961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775143.680589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775143.696218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775143.711862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775143.727465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775143.743090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.758775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.774328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775144.789960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.805613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.821212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.836845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775144.852459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.868091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.883725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.899331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775144.914986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775145.930609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775145.946205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775145.961841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775145.977455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775145.993106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775146.008734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775146.024363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775146.039989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775146.055577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775146.071207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775146.086843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.102484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.118100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775147.133730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.149456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.164957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.180574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775147.196220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.211849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.227449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.243083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775147.258723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.274375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.289968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775148.305594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.321227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.336835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.352466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775148.368087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.383730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.399329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.414993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775148.430576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.446244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.462040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775149.477467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.493080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.508732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.524340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775149.539999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.555577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.571204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.586825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775149.602450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.618108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.633731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775150.649444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.664966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.680579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.696220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775150.711849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.727453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.743077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.758722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775150.774313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.789992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.805606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775151.821205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.836842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.852457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.868089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775151.883717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.899321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.914972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.930573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775151.946216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775152.961915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775152.978032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775152.993086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775153.008735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775153.024358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775153.040243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775153.055591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775153.071210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775153.086846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775153.102458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775153.118114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.133770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.149470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775154.164959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.180582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.196212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.211853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775154.227465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.243081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.258750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.274332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775154.289954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.305664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.321219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775155.336839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.352452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.368095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.383732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775155.399330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.414992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.430581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.446227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775155.462076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.477533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.493093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775156.508725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.524325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.539984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.555578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775156.571199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.586821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.602444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.618088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775156.633728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.649483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.664967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775157.680574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.696208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.711834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.727472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775157.743075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.758719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.774332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.789941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775157.805569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.821253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.836834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775158.852465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.868086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.883722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.899335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775158.914965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.930570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.946194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.961829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775158.977450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775159.993122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775160.008739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775160.024365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775160.039993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775160.055583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775160.071211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775160.086898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775160.102464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775160.118102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775160.133738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775160.149469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.165077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.180619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775161.196701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.211922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.227488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.243087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775161.258758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.274454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.289947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.305571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775161.321224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.336911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.352649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775162.368191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.383888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.399428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.415046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775162.430615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.446198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.462120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.477571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775162.493626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.508780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.524324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775163.539980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.555572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.571205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.586820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775163.602456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.618092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.633729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.649468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.664960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775163.680593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775163.696255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775163.711863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775163.727497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775163.743101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775164.758785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775164.774350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775164.789958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775164.805593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775164.821233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775164.836881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775164.852459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775164.868086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775164.883710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775164.899385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775164.914951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775165.930625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775165.946207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775165.961884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775165.977461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775165.993106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775166.008703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775166.024368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775166.040003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775166.055593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775166.071216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775166.086835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.102513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.118104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775167.133713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.149443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.164947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.180579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775167.196198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.211818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.227467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.243072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775167.258726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.274388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.289962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775168.305585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.321218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.336839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.352458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775168.368082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.383721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.399333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.414962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775168.430588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.446249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.462063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775169.477453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.493075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.508707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.524344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775169.539988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.555586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.571202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.586822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775169.602442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.618132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.633718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775170.649431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.664956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.680574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.696195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775170.711832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.727463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.743065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.758720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775170.774309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.789970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.805568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775171.821221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.836827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.852443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.868073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775171.883705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.899330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.914943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.930576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775171.946186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775172.961876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775172.978016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775172.993079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775173.008704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775173.024366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775173.039999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775173.055570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775173.071194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775173.086831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775173.102446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775173.118074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.133770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.149462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775174.165177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.180593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.196205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.211847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775174.227476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.243097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.258721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.274335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775174.289951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.305632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.321237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775175.336830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.352470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.368082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.383720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775175.399330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.415013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.430595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.446198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775175.462050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.477472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.493311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775176.508698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.524362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.539971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.555597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775176.571205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.586824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.602454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.618086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775176.633736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.649473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.664960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775177.680574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.696202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.711836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.727487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775177.743082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.758734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.774311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.789957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775177.805584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.821274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.836843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775178.852449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.868081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.883712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.899340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775178.914945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.930584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.946191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.961831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775178.977449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775179.993121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775180.008711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775180.024362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775180.039980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775180.055593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775180.071192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775180.086923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775180.102446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775180.118073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775180.133735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775180.149453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.164981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.180577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775181.196205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.211821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.227472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.243080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775181.258736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.274319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.289942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.305566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775181.321198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.336880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.352451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775182.368070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.383793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.399327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.414966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775182.430597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.446188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.462071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.477457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775182.493075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.508747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.524354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775183.539978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.555576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.571208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.586820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775183.602457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.618075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.633813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.649455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775183.664964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.680595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.696195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775184.711824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.727465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.743068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.758724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775184.774303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.789949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.805697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.821212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775184.836844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775185.852502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775185.868077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775185.883780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775185.899317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775185.914948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775185.930578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775185.946284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775185.961836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775185.977438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775185.993065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775186.008786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.024401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.039991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775187.055575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.071208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.086825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.102454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775187.118070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.133780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.149444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.164943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775187.180573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.196222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.211826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775188.227461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.243080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.258721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.274318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775188.289954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.305566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.321202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.336832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775188.352436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.368167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.383763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775189.399325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.415004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.430586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.446195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775189.462065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.477449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.493061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.508697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775189.524319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.540037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.555572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775190.571207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.586819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.602443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.618083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775190.633764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.649453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.664951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.680579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775190.696204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.711862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.727463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775191.743072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.758721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.774319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.789938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775191.805577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.821198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.836821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.852443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775191.868063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775192.883801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775192.899334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775192.914952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775192.931126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775192.946207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775192.961827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775192.978006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775192.993075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775193.008700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775193.024351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775193.039995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.055603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.071204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775194.086838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.102445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.118072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.133766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775194.149448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.164942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.180569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.196190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775194.211811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.227518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.243094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775195.258733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.274332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.289946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.305577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775195.321200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.336850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.352453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.368071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775195.383731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.399441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.414983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775196.430574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.446189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.462079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.477438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775196.493072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.508776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.524375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.539976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775196.562812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.571207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.586823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775197.602444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.618063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.633751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.649429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775197.664935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.680565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.696183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.711810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775197.727439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.743092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.758786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775198.774326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.789950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.805571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.821204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775198.836840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.852454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.868067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.883730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775198.899313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775199.914961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775199.930595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775199.946199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775199.961825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775199.977466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775199.993071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775200.008696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775200.024349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775200.039971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775200.062739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775200.071198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.086847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.102448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775201.118066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.133730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.149431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.164940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775201.180573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.196201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.211828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.227436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775201.243082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.258738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.274325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775202.289936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.305566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.321190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.336835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775202.352450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.368066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.383697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.399317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775202.414952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.430639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.446209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775203.462054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.477450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.493091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.508694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775203.524331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.539988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.562939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.571196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.586816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775203.602458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775203.618085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775203.633721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775203.649435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775203.665096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775204.680609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775204.696194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775204.711812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775204.727431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775204.743071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775204.758710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775204.774313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775204.789934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775204.805557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775204.821197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775204.836809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775205.852477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775205.868067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775205.883714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775205.899316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775205.914948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775205.930565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775205.946305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775205.961830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775205.977432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775205.993070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775206.008684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.024370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.039973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775207.055588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.071195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.086828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.102452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775207.118073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.133710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.149538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.164932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775207.180555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.196221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.211811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775208.227444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.243078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.258710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.274320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775208.289943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.305555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.321180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.336810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775208.352538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.368104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.383803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775209.399318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.414958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.430559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.446296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775209.462037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.477436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.493066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.508680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775209.524314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.540023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.555577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775210.571200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.586824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.602439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.618065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775210.633689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.649534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.664934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.680563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775210.696180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.711847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.727446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775211.743078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.758727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.774318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.789930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775211.805556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.821181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.836814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.852528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775211.868065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775212.883764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775212.899327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775212.914954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775212.930565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775212.946293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775212.961819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775212.977462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775212.993061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775213.008705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775213.024348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775213.039967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.055597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.071215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775214.086828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.102443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.118071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.133699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775214.149520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.164931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.180557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.196184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775214.211806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.227596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.243169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775215.258796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.274317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.289933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.305647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775215.321269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.336892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.352536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.368076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775215.383714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.399436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.414961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775216.430567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.446391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.462009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.477545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775216.493056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.508682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.524315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.540052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775216.562867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.571239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.586832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775217.602444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.618072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.633700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.649515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775217.664938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.680556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.696180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.711808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775217.727439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.743151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.758827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775218.774378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.790078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.805972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.821382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775218.836937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.852697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.868251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.883893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775218.899384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775219.915080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775219.930609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775219.946280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775219.961911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775219.977517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775219.993151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775220.008691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775220.024328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775220.039959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775220.062940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775220.071178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.087023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.102456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775221.118077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.133681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.149530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.164932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775221.180551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.196263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.211808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.227440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775221.243059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.258768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.274324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775222.289946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.305578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.321183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.336816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775222.352525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.368062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.383682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.399301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775222.414968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.430691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.446328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775223.462032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.477432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.493080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.508682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775223.524326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.539958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.555579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.571178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775223.586783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.602563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.618243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775224.633802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.649512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.664926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.680552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775224.696204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.711832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.727438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.743078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775224.758720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.774342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.789964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775225.805578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.821195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.836819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.852547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775225.868065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.883676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.899302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.914949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775225.930560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775226.946312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775226.961815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775226.977435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775226.993076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775227.008702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775227.024329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775227.039973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775227.055577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775227.071181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775227.086829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775227.102424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.118133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.133703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775228.149518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.164936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.180560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.196198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775228.211811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.227437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.243054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.258722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775228.274301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.289956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.305561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775229.321180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.336807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.352525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.368105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775229.383679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.399303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.414955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.430555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775229.446179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.462047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.477448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775230.493059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.508696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.524311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.539951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775230.555566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.571188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.586810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.602438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775230.618049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.633703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.649526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775231.664944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.680552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.696181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.711802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775231.727419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.743059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.758720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.774312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775231.789920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.805625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.821182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775232.836808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.852523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.868057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.883706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775232.899299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.914928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.930558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.946181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775232.961825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775233.977469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775233.993061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775234.008702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775234.024329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775234.039963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775234.055568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775234.071173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775234.086832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775234.102425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775234.118075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775234.133682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.149689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.164981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775235.180575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.196284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.211844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.227450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775235.243079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.258789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.274324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.289961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775235.305571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.321252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.336830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775236.352528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.368073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.383689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.399304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775236.414948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.430561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.446184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.462086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775236.477448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.493082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.508699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775237.524323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.539975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.555573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.571193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775237.586806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.602429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.618052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.633683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775237.649431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.665053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.680576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775238.696192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.711819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.727435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.743128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775238.758727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.774325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.789932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.805583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775238.821179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.836845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.852518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775239.868052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.883673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.899314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.914946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775239.930568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.946238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.961838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.977433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775239.993069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.008721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.024330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775241.039960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.055577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.071177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.086804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775241.102436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.118074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.133676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.149412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775241.164936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.180596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.196191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775242.211817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.227434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.243057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.258716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775242.274304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.289940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.305553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.321191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775242.336805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.352555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.368081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775243.383698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.399315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.414953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.430562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775243.446182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.462036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.477424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.493068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775243.508704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.524356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.539967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775244.555590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.571195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.586811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.602435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775244.618062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.633853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.649481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.664951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775244.680558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.696230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.711819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775245.727440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.743066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.758778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.774322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775245.789942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.805565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.821189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.836822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775245.852439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775246.868080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775246.883688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775246.899322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775246.914935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775246.930577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775246.946186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775246.961830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775246.977430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775246.994562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775247.008687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775247.024340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.040047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.055608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775248.071192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.086880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.102440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.118092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775248.133682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.149452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.164943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.180561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775248.196182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.211841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.227433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775249.243070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.258720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.274306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.289930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775249.305550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.321184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.336828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.352445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775249.368244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.383719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.399303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775250.415013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.430553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.446184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.462049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775250.477430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.493057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.508682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.524321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775250.539965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.555605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.571188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775251.586805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.602428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.618042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.633669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775251.649432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.664937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.680543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.696168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775251.711789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.727442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.743056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775252.758717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.774290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.789898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.805570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775252.821281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.836859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.852470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.868089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775252.883694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775253.899374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775253.914949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775253.930560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775253.946192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775253.961830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775253.977437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775253.993043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775254.008698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775254.024329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775254.039962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775254.055565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.071249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.086830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775255.102453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.118073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.133682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.149462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775255.164955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.180553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.196174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.211800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775255.227462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.243114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.258726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775256.274324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.289938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.305568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.321185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775256.336828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.352438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.368305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.383682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775256.399324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.414992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.430545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775257.446183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.462041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.477415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.493043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775257.508688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.524309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.539947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.555543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775257.571185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.586818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.602418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775258.618052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.633666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.649412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.664934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775258.680539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.696174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.711788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.727414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775258.743038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.758737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.774294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775259.789916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.805541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.821177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.836794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775259.852442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.868059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.883665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.899287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775259.914915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775260.930577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775260.946171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775260.961825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775260.977418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775260.993048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775261.008666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775261.024317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775261.039941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775261.055545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775261.071179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775261.086824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.102445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.118050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775262.133680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.149410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.164947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.180552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775262.196183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.211785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.227414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.243034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775262.258684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.274340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.289928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775263.305554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.321176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.336821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.352421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775263.368057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.383665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.399310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.414944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775263.430541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.446220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.462037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775264.477430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.493062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.508687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.524309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775264.539950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.555542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.571188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.586788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775264.602422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.618109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.633681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775265.649442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.664950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.680568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.696185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775265.711801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.727417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.743048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.758699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775265.774313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.789965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.805555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775266.821190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.836804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.852421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.868061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775266.883692 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.899307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.914930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.930551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775266.946175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775267.961878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775267.977426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775267.993053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775268.008677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775268.024329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775268.039952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775268.055552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775268.071192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775268.086866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775268.102422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775268.118075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.133752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.149465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775269.164947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.180553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.196174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.211787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775269.227418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.243051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.258709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.274309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775269.289910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.305610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.321196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775270.336812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.352446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.368048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.383686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775270.399313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.414946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.430548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.446189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775270.462045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.477470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.493052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775271.508696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.524311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.539945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.555560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775271.571188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.586803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.602424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.618050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775271.633662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.649484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.664941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775272.680566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.696186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.711814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.727415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775272.743049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.758710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.774293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.789922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775272.805547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.821203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.836811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775273.852426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.868066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.883678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.899301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775273.914931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.930551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.946168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.961791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775273.977443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775274.993120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775275.008678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775275.024319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775275.039947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775275.055551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775275.071186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775275.086816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775275.102425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775275.118043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775275.133666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775275.149428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.164965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.180550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775276.196170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.211802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.227412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.243040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775276.258691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.274305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.289913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.305538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775276.321167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.336850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.352433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775277.368228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.383688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.399291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.414959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775277.430563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.446168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.462067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.477441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775277.493044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.508718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.524306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775278.539958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.555550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.571187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.586805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775278.602424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.618063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.633674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.649411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775278.664931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.680575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.696183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775279.711802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.727424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.743041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.758715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775279.774308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.789930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.805550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.821183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775279.836794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775280.852468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775280.868063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775280.883663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775280.899307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775280.914925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775280.930542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775280.946157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775280.961798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775280.977429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775280.993058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775281.008664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.024376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.047534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775282.057642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.071279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.086793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.102472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775282.118143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.133662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.149293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.165072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775282.180561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.196309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.211822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775283.227438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.243223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.258805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.274412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775283.289923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.305548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.321273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.336793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775283.352519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.368171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.383699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775284.399289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.414942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.430544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.446225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775284.462010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.477433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.493043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.508669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775284.524299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.540028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.555563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775285.571202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.586796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.602422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.618070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775285.633668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.649309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.664916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.680576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775285.696168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.711839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.727423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775286.743047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.758681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.774300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.789922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775286.805542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.821176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.836785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.852422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775286.868034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775287.883702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775287.899297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775287.914917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775287.930540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775287.946166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775287.961792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775287.977442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775287.993044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775288.008661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775288.024352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775288.039951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.055610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.071192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775289.086812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.102427 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.118062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.133673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775289.149292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.164927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.180560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.196167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775289.211796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.227455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.243074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775290.258695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.274305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.289978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.305546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775290.321185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.336802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.352408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.368046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775290.383680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.399345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.414943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775291.430552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.446172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.462039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.477449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775291.493046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.508664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.524290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.539938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775291.563097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.571265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.586786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775292.602420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.618055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.633671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.649313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775292.664917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.680561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.696166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.711783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775292.727405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.743116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.758698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775293.774318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.789913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.805514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.821173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775293.836794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.852414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.868044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.883686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775293.899305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775294.915010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775294.930537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775294.946164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775294.961799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775294.977983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775294.993187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775295.008789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775295.024550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775295.039972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775295.063528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775295.071162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.086940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.102441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775296.118057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.133677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.149290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.164915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775296.180557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.196158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.211782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.227424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775296.243047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.258715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.274331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775297.289927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.305545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.321174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.336784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775297.352418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.368044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.383695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.399296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775297.414935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.430972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.446276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775298.462016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.477546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.493074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.508792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775298.524302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.539951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.563301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.571176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775298.586834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.602481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.618040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775299.633673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.649289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.664915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.680551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775299.696157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.711786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.727419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.743049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775299.758677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.774347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.789924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775300.805707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.821180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.836805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.852421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775300.868065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.883686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.899289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.914909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775300.930525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775301.946204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775301.961795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775301.977435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775301.993074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775302.008670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775302.024314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775302.040245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775302.063480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775302.071164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775302.086815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775302.102409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.118064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.133656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775303.149286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.164913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.180549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.196164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775303.211784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.227412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.243041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.258661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775303.274285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.289939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.305547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775304.321164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.336795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.352414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.368045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775304.383686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.399280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.414924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.430530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775304.446159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.462217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.477495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775305.493046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.509423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.524513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.539979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775305.563510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.571195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.586837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.602415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775305.618116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.633790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.649296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775306.664924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.680579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.696159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.711816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775306.727403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.743105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.758653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.774276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775306.789935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.805597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.821177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775307.836798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.852468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.868050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.883742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775307.899299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.914930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.931125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.946169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775307.961842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775308.977537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775308.993406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775309.008719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775309.024341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775309.039934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775309.055616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775309.071245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775309.086915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775309.102473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775309.118122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775309.133684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.149445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.164915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775310.180585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.196179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.211788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.227450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775310.243072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.258667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.274326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.289989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775310.305541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.321285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.336800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775311.352434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.368048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.383694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.399292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775311.414941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.430543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.446183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.462087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775311.477425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.493093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.508662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775312.524299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.539943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.555544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.571171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775312.586832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.602407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.618059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.633662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775312.649281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.664977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.680554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775313.696248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.711871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.727414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.743059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775313.758657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.774292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.790008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.805542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775313.821163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.836844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.852411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775314.868068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.883685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.899290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.914921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775314.931059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.946190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.961803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.977420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775314.993108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.008851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.024376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775316.039957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.055548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.071175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.086890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775316.102428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.118061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.133670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.149307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775316.164926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.180585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.196166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775317.211795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.227415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.243051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.258658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775317.274278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.289924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.305524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.321148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775317.336772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.352452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.368042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775318.383684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.399283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.414926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.430528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775318.446159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.462078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.477425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.493073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775318.508665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.524385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.539940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775319.555547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.571154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.586814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.602421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775319.618042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.633658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.649278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.664910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775319.680534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.696195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.711783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775320.727417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.743062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.758655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.774274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775320.789941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.805690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.821171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.836800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775320.852414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775321.868194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775321.883734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775321.899338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775321.914916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775321.930547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775321.946162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775321.961786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775321.977406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775321.993071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775322.008662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775322.024306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.040008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.055540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775323.071147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.086833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.102407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.118037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775323.133653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.149276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.165049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.180532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775323.196171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.211843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.227424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775324.243069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.258672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.274291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.289937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775324.305540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.321171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.336811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.352428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775324.368034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.383741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.399291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775325.414932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.430533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.446157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.462008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775325.477404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.493071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.508653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.524306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775325.539930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.555668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.571247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775326.586888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.602494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.618043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.633665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775326.649284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.664914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.680528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.696195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775326.711781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.727598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.743070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775327.758660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.774284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.789938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.805546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775327.821164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.836784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.852398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.868036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775327.883669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775328.899348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775328.914914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775328.930537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775328.946162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775328.961785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775328.977402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775328.993072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775329.008652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775329.024296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775329.039934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775329.055531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.071202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.086811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775330.102405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.118024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.133664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.149275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775330.164900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.180528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.196180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.211778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775330.227396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.243109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.258663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775331.274281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.289920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.305531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.321164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775331.336784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.352408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.368021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.383668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775331.399297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.415037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.430614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775332.446155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.461989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.477407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.493054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775332.508656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.524278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.539932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.555546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775332.571156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.586849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.602402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775333.618044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.633661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.649279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.664899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775333.680538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.696194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.711782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.727395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775333.743039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.758713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.774286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775334.789928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.805537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.821157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.836787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775334.852398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.868030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.883655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.899304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775334.914922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775335.930591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775335.946172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775335.961794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775335.977416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775335.993068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775336.008691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775336.024303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775336.040197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775336.055532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775336.071151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775336.086850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.102442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.118033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775337.133662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.149285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.164918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.180542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775337.196177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.211779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.227404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.243140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775337.258665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.274357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.289931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775338.305537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.321169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.336797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.352404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775338.368022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.383665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.399287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.414919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775338.430530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.446189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.462002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775339.477404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.493139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.508668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.524320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775339.539933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.555532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.571158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.586770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775339.602421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.618068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.633654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775340.649284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.664932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.680522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.696177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775340.711793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.727396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.743110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.758653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775340.774259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.789959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.805566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775341.821153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.836788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.852401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.868020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775341.883644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.899297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.914887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.930527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775341.946148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775342.961810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775342.977403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775342.993058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775343.008667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775343.024304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775343.039923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775343.055536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775343.071159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775343.086781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775343.102418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775343.118031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.133720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.149337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775344.164956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.180539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.196227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.211773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775344.227450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.243147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.258650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.274281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775344.289899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.305633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.321159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775345.336787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.352409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.368025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.383671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775345.399307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.414923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.430522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.446159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775345.462028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.477459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.493113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775346.508654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.524282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.539940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.555516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775346.571146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.586771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.602430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.618016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775346.633648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.649326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.664907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775347.680540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.696178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.711780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.727398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775347.743082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.758648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.774272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.789895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775347.805523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.821285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.836796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775348.852429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.868039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.883669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.899313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775348.915010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.930988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.946159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.961798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775348.977412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775349.993148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775350.008659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775350.024298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775350.039937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775350.055527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775350.071147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775350.086788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775350.102412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775350.118026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775350.133651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775350.149275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.165013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.180536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775351.196160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.211772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.227389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.243069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775351.258647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.274278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.289889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.305538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775351.321141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.336880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.352425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775352.368036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.383678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.399289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.414928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775352.430540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.446166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.462065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.477416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775352.493055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.508701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.524293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775353.539934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.555554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.571166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.586774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775353.602421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.618013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.633666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.649268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775353.664929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.680577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.696176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775354.711787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.727404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.743039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.758658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775354.774270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.789918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.805546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.821150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775354.836784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775355.852607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775355.868086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775355.883664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775355.899316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775355.914927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775355.930525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775355.946152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775355.961788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775355.977405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775355.993070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775356.008685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.024327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.039947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775357.055528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.071155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.086780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.102409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775357.118028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.133650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.149271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.164894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775357.180517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.196196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.211779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775358.227403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.243024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.258646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.274265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775358.289894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.305535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.321149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.336771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775358.352389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.368041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.383652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775359.399294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.414908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.430533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.446142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775359.461971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.477391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.493025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.508652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775359.524270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.539945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.555527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775360.571148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.586787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.602407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.618012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775360.633632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.649262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.664887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.680513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775360.696138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.711803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.727391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775361.743028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.758647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.774258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.789888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775361.805532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.821144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.836760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.852394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775361.868011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775362.883767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775362.899304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775362.915016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775362.930532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775362.946164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775362.961785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775362.977413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775362.993034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775363.008669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775363.024303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775363.039957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.055563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.071157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775364.086851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.102420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.118045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.133656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775364.149271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.164886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.180541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.196147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775364.211792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.227421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.243031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775365.258645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.274267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.289912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.305530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775365.321141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.336762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.352389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.368000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775365.383647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.399377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.414919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775366.430524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.446167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.462029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.477410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775366.493309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.508678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.524280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.539919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775366.563046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.571187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.586810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775367.602424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.618037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.633647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.649278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775367.664907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.680531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.696148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.711796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775367.727398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.743055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.758650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775368.774358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.789919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.805536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.821171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775368.836778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.852405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.868026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.883767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775368.899281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775369.914949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775369.930527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775369.946174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775369.961790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775369.977391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775369.993015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775370.008664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775370.024293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775370.039919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775370.063001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775370.071143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.086899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.102443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775371.118106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.133638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.149258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.164961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775371.180534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.196163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.211793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.227398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775371.243035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.258690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.274277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775372.289902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.305532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.321151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.336768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775372.352396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.368017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.383655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.399277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775372.414920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.430627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.446161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775373.462000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.477392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.493035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.508661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775373.524278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.539907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.563012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.571144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775373.586771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.602504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.618031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775374.633658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.649297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.665010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.680641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775374.696352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.711796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.727504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.743138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775374.758766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.774365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.789906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775375.805665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.821158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.836778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.852411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775375.868022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.883659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.899285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.914903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775375.930521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775376.946339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775376.961865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775376.977483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775376.993026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775377.008661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775377.024295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775377.039915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775377.063005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775377.071151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775377.086794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775377.102402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.118072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.133648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775378.149269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.164903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.180523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.196152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775378.211783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.227388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.243015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.258644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775378.274269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.289951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.305539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775379.321145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.336768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.352405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.368019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775379.383657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.399269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.414918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.430518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775379.446157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.462032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.477397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775380.493023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.508661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.524282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.539909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775380.563031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.571156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.586763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.602398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775380.618042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.633667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.649265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775381.664889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.680518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.696137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.711792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775381.727384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.743008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.758635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.774254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775381.789888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.805703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.821231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775382.836848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.852383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.868014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.883659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775382.899261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.914902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.930508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.946218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775382.961766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775383.977449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775383.993026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775384.008687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775384.024293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775384.039973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775384.062942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775384.071160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775384.086830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775384.102391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775384.118080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775384.133643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.149303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.164904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775385.180551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.196140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.211792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.227386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775385.243028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.258650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.274263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.289904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775385.305510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.321190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.336776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775386.352409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.368015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.383653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.399262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775386.414914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.430512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.446148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.461988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775386.477384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.493121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.508729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775387.524427 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.540031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.563208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.571146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775387.586759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.602386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.618022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.633637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775387.649263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.664960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.680514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775388.696146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.711792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.727384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.743007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775388.758633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.774274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.789879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.805507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775388.821157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.836792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.852398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775389.868011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.883647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.899262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.914917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775389.930511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.946131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.961761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.977379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775389.993006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.008756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.024301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775391.039930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.063116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.071150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.086768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775391.102396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.118037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.133638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.149258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775391.164887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.180620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.196141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775392.211788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.227390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.243017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.258646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775392.274266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.289885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.305522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.321143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775392.336756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.352409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.368017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775393.383646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.399265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.414978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.430511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775393.446157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.461987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.477386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.493011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775393.508633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.524388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.539947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775394.555560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.571150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.586767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.602395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775394.618036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.633646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.649269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.664887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775394.680530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.696191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.711789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775395.727384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.743023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.758629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.774258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775395.789880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.805513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.821165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.836765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775395.852385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775396.868043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775396.883639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775396.899273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775396.914946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775396.930523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775396.946143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775396.961786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775396.977393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775396.993005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775397.008633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775397.024293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.042340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.055602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775398.071226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.086794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.102384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.118041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775398.133633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.149265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.164883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.180514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775398.196130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.211848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.227408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775399.243059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.258648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.274262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.289886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775399.305511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.321209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.336887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.352422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775399.368234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.383946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.399381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775400.415032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.430695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.446249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.462250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775400.477498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.493124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.508899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.524452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775400.540131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.555641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.571224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775401.586887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.602450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.618046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.633667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775401.649257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.664907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.680507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.696172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775401.711840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.727625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.743072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775402.758648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.774491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.790029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.805901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775402.821399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.836846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.852457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.868089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775402.883733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775403.899352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775403.915113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775403.930527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775403.946223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775403.961779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775403.977569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775403.993201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775404.008713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775404.024405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775404.040354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775404.055585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.071219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.086835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775405.102395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.118044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.133637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.149273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775405.164886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.180529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.196143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.211782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775405.227411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.243112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.258751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775406.274274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.289898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.305509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.321150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775406.336767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.352376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.368006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.383727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775406.399265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.414972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.430512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775407.446151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.461982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.477387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.493019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775407.508642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.524303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.539917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.555519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775407.571134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.586796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.602399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775408.618052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.633646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.649265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.664882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775408.680517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.696143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.711757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.727406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775408.743006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.758708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.774269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775409.789898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.805530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.821181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.836753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775409.852381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.868005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.883632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.899256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775409.914893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775410.930522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775410.946138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775410.961769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775410.977388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775410.993006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775411.008634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775411.024294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775411.039907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775411.055510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775411.071127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775411.086761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.102401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.118045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775412.133640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.149271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.164884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.180521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775412.196130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.211754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.227396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.242999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775412.258636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.274277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.289898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775413.305524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.321174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.336761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.352380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775413.368004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.383645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.399253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.414898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775413.430522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.446195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.462006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775414.477413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.493030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.508653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.524346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775414.539917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.555511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.571149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.586761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775414.602391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.618172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.633637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775415.649265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.664901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.680510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.696133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775415.711763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.727406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.743007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.758632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775415.774257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.789943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.805526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775416.821159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.836768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.852396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.868004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775416.883630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.899255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.914892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.930517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775416.946127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775417.961812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775417.977393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775417.993002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775418.008641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775418.024310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775418.039916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775418.055520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775418.071149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775418.086801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775418.102391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775418.118022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.133669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.149264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775419.164893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.180525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.196170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.211761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775419.227414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.243002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.258634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.274251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775419.289880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.305565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.321157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775420.336769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.352390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.368024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.383625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775420.399250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.414902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.430533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.446124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775420.461980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.477413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.493011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775421.508652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.524280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.539921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.555517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775421.571136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.586772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.602386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.618008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775421.633667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.649295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.664885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775422.680512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.696134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.711765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.727400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775422.743011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.758640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.774265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.789885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775422.805514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.821243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.836772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775423.852386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.868007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.883627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.899250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775423.914873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.930517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.946130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.961763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775423.977377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775424.993038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775425.008635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775425.024294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775425.039920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775425.055502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775425.071131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775425.086769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775425.102379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775425.118007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775425.133644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775425.149249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.164979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.180562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775426.196146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.211804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.227401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.243024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775426.258797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.274327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.289888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.305499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775426.321124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.336839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.352384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775427.368006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.383651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.399252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.414931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775427.430522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.446136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.462005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.477392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775427.493149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.508752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.524287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775428.539920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.555529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.571136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.586759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775428.602377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.618001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.633664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.649252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775428.664876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.680567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.696131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775429.711760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.727398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.743016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.758648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775429.774255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.789875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.805510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.821126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775429.836771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775430.852422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775430.868049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775430.883631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775430.899257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775430.914888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775430.930991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775430.946146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775430.961764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775430.977386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775430.993006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775431.008627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.024332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.039915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775432.055582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.071128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.086820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.102373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775432.118008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.133639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.149250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.164871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775432.180519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.196185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.211753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775433.227390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.242998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.258616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.274242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775433.289867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.305495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.321124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.336771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775433.352373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.368181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.383636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775434.399256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.414903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.430526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.446126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775434.461969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.477373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.493006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.508635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775434.524421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.540057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.555684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775435.571266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.586776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.602383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.618003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775435.633782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.649256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.664886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.680515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775435.696134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.711875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.727421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775436.743025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.758756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.774262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.789878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775436.805507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.821127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.836769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.852392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775436.868003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775437.883674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775437.899258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775437.914887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775437.930620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775437.946144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775437.961840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775437.977377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775437.992998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775438.008628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775438.024272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775438.039912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.055594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.071203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775439.086845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.102391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.118078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.133723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775439.149324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.164941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.180567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.196207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775439.211816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.227510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.243007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775440.258684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.274261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.289885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.305509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775440.321129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.336777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.352368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.368012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775440.383618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.399355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.414952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775441.430536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.446139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.461977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.477428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775441.493046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.508668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.524306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.539908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775441.555576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.571147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.586763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775442.602373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.617993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.633656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.649247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775442.664924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.680520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.696123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.711739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775442.727365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.743050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.758661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775443.774230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.789889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.805484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.821121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775443.836776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.852369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.867992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.883638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775443.899245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775444.914960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775444.931160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775444.946142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775444.961810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775444.977372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775444.993004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775445.008643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775445.024267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775445.039907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775445.055496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775445.071119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.086829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.102390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775446.118012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.133655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.149261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.164871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775446.180506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.196123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.211757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.227371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775446.243018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.258676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.274248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775447.289887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.305500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.321120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.336763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775447.352386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.367992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.383631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.399244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775447.414890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.431026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.446154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775448.461964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.477379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.493017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.508629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775448.524265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.539904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.555507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.571131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775448.586757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.602441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.618024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775449.633651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.649252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.664874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.680506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775449.696127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.711763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.727382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.743022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775449.758632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.774284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.789865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775450.805507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.821121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.836766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.852382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775450.868006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.883738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.899243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.914862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775450.930496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775451.946181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775451.961787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775451.977390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775451.992997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775452.008650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775452.024269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775452.039913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775452.055496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775452.071119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775452.086824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775452.102383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.118051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.133643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775453.149246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.164894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.180492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.196117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775453.211743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.227368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.243009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.258630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775453.274241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.289893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.305509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775454.321122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.336758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.352374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.368001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775454.383627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.399248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.414889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.430493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775454.446217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.462117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.477384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775455.493001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.508633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.524255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.539900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775455.555501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.571181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.586756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.602387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775455.618007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.633694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.649253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775456.664882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.680508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.696117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.711759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775456.727472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.743015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.758629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.774355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775456.789984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.805542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.821131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775457.836768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.852406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.867995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.883634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775457.899251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.914883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.930494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.946216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775457.961763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775458.977413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775458.993015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775459.008633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775459.024270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775459.039903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775459.055494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775459.071116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775459.086748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775459.102400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775459.118007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775459.133616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.149286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.164873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775460.180507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.196134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.211748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.227374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775460.243018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.258629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.274260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.289876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775460.305504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.321194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.336777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775461.352389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.368004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.383616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.399239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775461.414908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.430499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.446207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.461985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775461.477373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.493116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.508626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775462.524255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.539898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.555518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.571126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775462.586751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.602390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.618002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.633621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775462.649337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.664908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.680498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775463.696116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.711756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.727362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.743010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775463.758616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.774237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.789868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.805491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775463.821118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.836825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.852421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775464.868007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.883619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.899266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.914884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775464.930496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.946218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.961757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.977370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775464.992995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.008745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.024275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775466.039937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.055499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.071119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.086755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775466.102387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.118014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.133616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.149324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775466.164863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.180690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.196164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775467.211752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.227371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.243014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.258629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775467.274251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.289871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.305497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.321122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775467.336759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.352430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.368036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775468.383630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.399298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.414905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.430500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775468.446250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.461966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.478280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.492986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775468.508625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.524318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.539911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775469.555607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.571160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.586740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.602373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775469.617990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.633725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.649461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.664875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775469.680591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.696331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.711740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775470.727374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.743017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.758622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.774244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775470.789873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.805502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.821126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.836740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775470.852490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775471.868063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775471.883623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775471.899242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775471.914878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775471.930485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775471.946221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775471.961751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775471.977364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775471.992998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775472.008622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775472.024288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.039941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.055502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775473.071128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.086754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.102376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.118007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775473.133616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.149322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.164864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.180490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775473.196114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.211779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.227377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775474.243007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.258616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.274225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.289864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775474.305499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.321111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.336730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.352469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.367989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775474.383638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775474.399277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775474.414905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775474.430516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775474.446132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775475.462102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775475.477365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775475.492998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775475.508636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775475.524238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775475.539882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775475.563029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775475.571111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775475.586731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775475.602389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775475.617981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.633664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.649354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775476.664877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.680497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.696123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.711736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775476.727365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.742987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.758635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.774233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775476.789874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.805525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.821125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775477.836755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.852479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.867979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.883608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775477.899239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.914872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.930484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.946111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775477.961753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775478.977412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775478.993002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775479.008655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775479.024259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775479.039902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775479.055532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775479.071109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775479.086744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775479.102376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775479.118005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775479.133607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.149495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.164970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775480.180494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.196224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.211739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.227363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775480.242987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.258628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.274239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.289862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775480.305492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.321166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.336759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775481.352490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.367988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.383643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.399235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775481.414890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.430491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.446111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.461957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775481.477356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.493081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.508627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775482.524249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.539897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.555499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.571118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775482.586733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.602370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.617996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.633613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775482.649244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.664908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.680496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775483.696153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.711740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.727362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.742990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775483.758640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.774237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.789861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.805494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775483.821115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.836791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.852472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775484.867996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.883613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.899237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.914850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775484.930490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.946102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.961761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.977355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775484.992976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.008693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.024268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775486.039906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.055633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.071116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.086899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775486.102497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.118127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.133790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.149311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775486.165004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.180576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.196127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775487.211743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.227364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.242990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.258625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775487.274247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.289860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.305483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.321114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775487.336734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.352512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.367988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775488.383615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.399253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.414879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.430504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775488.446121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.461985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.477373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.492987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775488.508758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.524392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.539939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775489.555710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.571129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.586818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.602407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775489.622621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.633696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.649324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.664951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775489.680718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.696410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.711836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775490.727450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.743069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.758710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.774406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775490.789860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.805493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.821287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.836898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775490.852586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775491.868055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775491.883615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775491.899249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775491.914852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775491.930488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775491.946106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775491.961752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775491.977357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775491.993077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775492.008618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775492.024263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.039931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.055507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775493.071116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.086766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.102462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.118018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775493.133614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.149225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.164867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.180479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775493.196118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.211797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.227373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775494.242997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.258668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.274227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.289861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775494.305490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.321103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.336777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.352465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.368015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775494.383624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775494.399260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775494.414902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775494.430502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775494.446133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775495.462089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775495.477389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775495.492996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775495.508639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775495.524261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775495.539887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775495.555496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775495.571168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775495.586733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775495.602456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775495.618005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.633677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.649252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775496.664888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.680484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.696153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.711748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775496.727363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.742988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.758615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.774338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775496.789864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.805569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.821131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775497.836742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.852448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.868012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.883613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775497.899233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.914865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.930482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.946140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775497.961738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775498.977418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775498.992998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775499.008613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775499.024263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775499.039891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775499.055482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775499.071121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775499.086744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775499.102444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775499.117992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775499.133629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.149305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.164884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775500.180507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.196110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.211752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.227364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775500.243004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.258628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.274265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.289861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775500.305489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.321194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.336742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775501.352441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.368007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.383608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.399240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775501.414886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.430483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.446146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.461964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775501.477388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.493033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.508615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775502.524251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.539902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.555493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.571134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775502.586732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.602426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.617980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.633622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775502.649255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.664918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.680488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775503.696120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.711740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.727358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.742977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775503.758620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.774260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.789853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.805474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775503.821099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.836811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.852425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775504.868008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.883612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.899231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.914858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775504.930509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.946109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.961741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.977405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775504.992980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.008641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.024263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775506.039879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.055496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.071125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.086747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775506.102407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.117992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.133606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.149226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775506.164850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.180554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.196130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775507.211736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.227375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.242964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.258610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775507.274263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.289851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.305476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.321106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775507.336730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.352450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.368004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775508.383626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.399243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.414890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.430498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775508.446111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.461962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.477374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.492985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775508.508615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.524296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.539915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775509.555495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.571137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.586747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.602407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775509.618297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.633614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.649248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.664873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775509.680506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.696144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.711734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775510.727367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.742997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.758607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.774250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775510.789864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.805480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.821107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.836793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775510.852405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775511.868185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775511.883698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775511.899289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775511.914925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775511.930485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775511.946109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775511.961732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775511.977370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775511.992987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775512.008614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775512.024263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.039955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.055560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775513.071129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.086746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.102381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.117985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775513.133602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.149227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.164859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.180496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775513.196108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.211769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.227370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775514.242973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.258615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.274247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.289847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775514.305496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.321122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.336728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.352357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775514.367957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.383753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.399292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775515.414888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.430489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.446110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.461974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775515.477377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.492974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.508597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.524228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775515.539889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.555552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.571136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775516.586733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.602369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.617991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.633603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775516.649244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.664861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.680502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.696100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775516.711738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.727392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.742990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775517.758612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.774259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.789854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.805481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775517.821105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.836727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.852357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.867975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775517.883629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775518.899270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775518.914865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775518.930477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775518.946100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775518.961729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775518.977371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775518.992973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775519.008609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775519.024255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775519.039874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775519.055492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.071170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.086796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775520.102369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.117983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.133617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.149231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775520.164854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.180493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.196101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.211724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775520.227370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.243022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.258618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775521.274243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.289848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.305475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.321111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775521.336729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.352348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.367969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.383619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775521.399232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.415055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.430531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775522.446118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.461952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.477380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.492977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775522.508772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.524250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.539872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.555480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775522.571103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.586780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.602499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775523.617986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.633639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.649253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.664974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775523.680514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.696121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.711723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.727374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775523.743002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.758670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.774261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775524.789865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.805482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.821106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.836730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775524.852352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.867976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.883631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.899231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775524.914853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775525.930660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775525.946172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775525.961738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775525.977376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775525.992997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775526.008616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775526.024307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775526.039890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775526.055474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775526.071097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775526.086804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.102407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.118019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775527.133605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.149240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.164857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.180495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775527.196194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.211730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.227349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.242985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775527.258602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.274287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.289870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775528.305481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.321111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.336733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.352359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775528.367973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.383620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.399232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.414887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775528.430479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.446138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.461943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775529.477368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.492972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.508605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.524231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775529.539901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.555506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.571124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.586744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775529.602361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.618028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.633620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775530.649257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.664853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.680494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.696103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775530.711730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.727355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.742995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.758595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775530.774205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.789889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.805478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775531.821115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.836725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.852431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.867970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775531.883626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.899218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.914859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.930473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775531.946113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775532.961864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775532.977370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775532.993057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775533.008612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775533.024253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775533.039887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775533.055472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775533.071106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775533.086753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775533.102343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775533.117976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.133690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.149233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775534.165085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.180516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.196111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.211739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775534.227504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.243005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.258671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.274234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.289893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775534.305518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775534.321145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775534.336747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775534.352369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775534.367992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775535.383684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775535.399236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775535.414894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775535.430483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775535.446112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775535.461968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775535.477355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775535.492994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775535.508611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775535.524339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775535.539892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.555561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.571106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775536.586744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.602357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.617971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.633611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775536.649220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.664849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.680477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.696124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775536.711724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.727393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.742974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775537.758601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.774231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.789861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.805481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775537.821099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.836734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.852356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.867968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775537.883610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775538.899314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775538.914847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775538.930467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775538.946096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775538.961723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775538.977345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775538.992978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775539.008602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775539.024245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775539.039878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775539.062650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.071121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.086803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775540.102337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.117979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.133586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.149214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775540.164842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.180462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.196114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.211716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775540.227343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.243003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.258608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775541.274233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.289856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.305465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.321088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775541.336711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.352336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.367956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.383607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775541.399227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.414973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.430489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775542.446107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.461953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.477346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.492987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775542.508598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.524224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.539876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.562475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775542.571098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.586758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.602346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775543.617978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.633592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.649235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.664844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775543.680464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.696132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.711793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.727343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775543.743037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.758636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.774244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775544.789871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.805472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.821137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.836719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775544.852345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.867971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.883609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.899237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775544.914837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775545.930491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775545.946175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775545.961733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775545.977357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775545.992997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775546.008611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775546.024230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775546.039864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775546.062586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775546.071094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775546.086725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.102480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.117985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775547.133605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.149222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.164855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.180480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775547.196123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.211741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.227371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.242977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775547.258609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.274275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.289870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775548.305487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.321096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.336734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.352341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775548.368180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.383609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.399239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.414867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775548.430464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.446164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.462021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775549.477352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.493000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.508598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.524214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775549.539874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.562743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.571098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.586712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775549.602355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.618030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.633610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775550.649230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.664846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.680481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.696115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775550.711735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.727354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.742980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.758591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775550.774236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.789974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.805513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775551.821100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.836724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.852355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.867972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775551.883614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.899242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.914846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.930469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775551.946091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775552.961813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775552.977357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775552.993009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775553.008614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775553.024253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775553.039902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775553.062786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775553.071115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775553.086746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775553.102368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775553.117977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.133654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.149227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775554.164846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.180484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.196113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.211723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775554.227338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.242963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.258604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.274224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775554.289838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.305564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.321113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775555.336882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.352510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.368362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.383714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775555.399255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.414876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.430468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.446097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775555.461960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.477529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.493367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775556.508620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.524336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.539977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.562854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775556.571094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.586753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.602362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.617975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775556.633594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.649410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.664936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775557.680564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.696122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.711751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.727345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775557.742973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.758684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.774305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.789853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775557.805486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.821224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.836752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775558.852339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.867975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.883596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.899229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775558.914846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.930460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.946081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.961713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775558.977333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775559.993123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775560.008672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775560.024332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775560.039881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775560.062839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775560.071090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775560.086771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775560.102360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775560.117998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775560.133597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775560.149214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.164877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.180469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775561.196105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.211714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.227341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.242965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775561.258582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.274205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.289829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.305482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775561.321087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.336822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.352346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775562.367958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.383605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.399220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.414857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775562.430461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.446088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.461932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.477329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775562.492951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.508701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.524328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775563.542225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.555560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.571139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.586724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775563.602435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.617963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.633586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.649228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775563.664844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.680514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.696127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775564.711721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.727307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.742972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.758603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775564.774210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.789839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.805490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.821108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775564.836714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775565.852405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775565.867976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775565.883592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775565.899285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775565.914886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775565.931065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775565.946110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775565.961738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775565.977354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775565.992972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775566.008621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.024292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.039864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775567.055474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.071092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.086714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.102359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775567.117968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.133586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.149211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.164829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775567.180557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.196158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.211729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775568.227347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.242982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.258611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.274222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775568.289851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.305486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.321096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.336711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775568.352342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.368011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.383615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775569.399239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.414873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.430474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.446102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775569.461965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.477350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.492963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.508606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775569.524228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.539920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.555489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775570.571098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.586711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.602568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.617984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775570.633583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.649206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.664855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.680457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775570.696098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.711776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.727347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775571.742972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.758617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.774203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.789837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775571.805549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.821090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.836713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.852332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775571.867968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775572.883643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775572.899234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775572.914855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775572.930473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775572.946098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775572.961714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775572.977357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775572.992966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775573.008616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775573.024229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775573.039869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.055516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.071100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775574.086730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.102366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.117986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.133594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775574.149221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.164853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.180466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.196104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775574.211738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.227413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.242957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775575.258688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.274223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.289830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.305477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775575.321093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.336711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.352335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.368050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775575.383673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.399330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.415006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775576.430476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.446088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.461998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.477358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775576.492972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.508613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.524222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.539862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775576.555462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.571132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.586723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775577.602360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.617959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.633593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.649224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775577.664859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.680473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.696093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.711742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775577.727352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.743010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.758609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775578.774231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.789843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.805638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.821100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775578.836713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.852337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.867963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.883593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775578.899222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775579.914973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775579.930963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775579.946115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775579.961731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775579.977352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775579.993459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775580.008621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775580.024402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775580.039899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775580.055512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775580.071139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.086987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.102435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775581.118000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.133604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.149223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.165032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775581.180465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.196254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.211928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.227527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775581.243087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.258643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.274231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775582.289842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.305496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.321163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.336724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775582.352344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.367964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.383596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.399219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775582.414871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.430499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.446093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775583.461930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.477336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.492966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.508605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775583.524226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.539856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.555478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.571083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775583.586696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.602404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.617962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775584.633607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.649213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.664839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.680472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775584.696103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.711732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.727356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.742972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775584.758591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.774288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.789847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775585.805488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.821102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.836714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.852340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775585.867978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.883593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.899232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.914855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775585.930901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775586.946260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775586.961729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775586.977345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775586.992963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775587.008635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775587.024243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775587.039885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775587.055460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775587.071080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775587.086719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775587.102336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.118031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.133593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775588.149215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.164848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.180465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.196105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775588.211739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.227341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.242970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.258620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775588.274213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.289880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.305501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775589.321103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.336716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.352335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.368034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775589.383582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.399212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.414863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.430458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775589.446097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.462050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.477349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775590.492953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.508608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.524209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.539859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775590.555475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.571084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.586711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.602334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775590.617990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.633638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.649217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775591.664836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.680465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.696092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.711721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775591.727351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.742966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.758597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.774226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775591.789829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.805525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.821098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775592.836709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.852328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.867961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.883598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775592.899209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.914871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.930462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.946093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775592.961713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775593.977387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775593.992966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775594.008610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775594.024255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775594.039862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775594.055460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775594.071082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775594.086711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775594.102346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775594.117987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775594.133582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.149254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.164835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775595.180459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.196085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.211762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.227357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775595.242965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.258593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.274235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.289833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775595.305471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.321151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.336722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775596.352351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.367966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.383589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.399226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775596.414852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.430452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.446089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.461937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775596.477314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.492993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.508604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775597.524229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.539855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.555476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.571081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775597.586704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.602322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.617972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.633585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775597.649209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.664892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.680467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775598.696085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.711757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.727344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.742964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775598.758575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.774262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.789828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.805463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775598.821120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.836862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.852352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775599.867954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.883597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.899211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.914856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775599.930452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.946093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.961711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.977321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775599.992964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.008640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.024240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775601.039860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.055455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.071085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.086709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775601.102338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.117979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.133591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.149202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775601.164827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.180498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.196084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775602.211740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.227338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.242959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.258583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775602.274208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.289825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.305452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.321095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775602.336716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.352558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.367964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775603.383584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.399200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.414858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.430460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775603.446075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.461951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.477327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.492966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775603.508572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.524257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.539851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775604.555453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.571151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.586864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.602434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775604.618067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.633604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.649203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.664866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775604.680458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.696128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.711744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775605.727342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.742959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.758587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.774216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775605.789833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.805467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.821104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.836708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775605.852340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775606.868080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775606.883594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775606.899227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775606.914852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775606.930473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775606.946102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775606.961748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775606.977347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775606.992965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775607.008605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775607.024262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.039899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.055477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775608.071094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.086801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.102336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.118005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775608.133582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.149203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.164837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.180453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775608.196078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.211768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.227344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775609.242961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.258590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.274201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.289851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775609.305451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.321088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.336716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.352331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775609.367949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.383609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.399211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775610.414863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.430450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.446079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.461917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775610.477326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.492949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.508580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.524220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775610.539844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.555478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.571091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775611.586723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.602338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.617984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.633590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775611.649209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.664847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.680460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.696081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775611.711706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.727360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.742962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775612.758592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.774189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.789845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.805455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775612.821097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.836715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.852334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.867958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775612.883574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775613.899262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775613.914849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775613.930461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775613.946087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775613.961734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775613.977340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775613.993107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775614.008579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775614.024248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775614.039867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775614.055472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.071141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.086723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775615.102339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.117994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.133590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.149205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775615.164835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.180453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.196075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.211709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775615.227346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.243024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.258594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775616.274214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.289839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.305449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.321095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775616.336698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.352324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.367951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.383586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775616.399200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.415086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.430547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775617.446091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.461963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.477322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.492946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775617.508591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.524232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.539850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.555457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775617.571073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.586733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.602329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775618.617975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.633575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.649202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.664830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775618.680451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.696175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.711736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.727343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775618.742954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.758625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.774302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775619.789998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.805554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.821189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.836807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775619.852382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.867950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.883579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.899196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775619.914969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775620.930529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775620.946103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775620.961718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775620.977326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775620.992976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775621.008583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775621.024235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775621.039879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775621.055445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775621.071067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775621.086703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.102366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.117982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775622.133576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.149208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.164822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.180454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775622.196073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.211719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.227349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.242963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775622.258576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.274280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.289877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775623.305465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.321108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.336706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.352329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775623.367953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.383626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.399211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.414850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775623.430477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.446126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.461944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775624.477328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.492950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.508582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.524222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775624.539859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.555457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.571073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.586693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775624.602319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.618011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.633591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775625.649200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.664833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.680463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.696062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775625.711719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.727342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.742956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.758575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775625.774200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.789869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.805467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775626.821114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.836716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.852325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.867945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775626.883568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.899192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.914811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.930466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775626.946070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775627.961771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775627.977328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775627.992952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775628.008582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775628.024233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775628.039853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775628.055465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775628.071083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775628.086769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775628.102321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775628.117977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.133605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.149206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775629.164828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.180452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.196081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.211708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775629.227333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.242953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.258567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.274192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775629.289807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.305477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.321101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775630.336699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.352337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.367954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.383572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775630.399195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.414840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.430454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.446081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775630.461926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.477365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.492953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775631.508576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.524233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.539843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.555462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775631.571069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.586715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.602317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.617946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775631.633594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.649317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.664834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775632.680460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.696077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.711712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.727350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775632.742945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.758569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.774180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.789803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775632.805443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.821114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.836699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775633.852326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.867958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.883569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.899193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775633.914818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.930457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.946069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.961719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775633.977318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775634.992999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775635.008573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775635.024240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775635.039852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775635.055451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775635.071081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775635.086708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775635.102330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775635.117953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775635.133584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775635.149197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.164979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.180462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775636.196085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.211721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.227358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.242962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775636.258579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.274203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.289850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.305459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775636.321090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.336752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.352335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775637.367949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.383597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.399203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.414833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775637.430460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.446073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.461933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.477331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775637.493327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.508623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.524229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775638.539844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.555478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.571094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.586689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775638.602324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.617945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.633588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.649208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775638.664813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.680489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.696094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775639.711703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.727343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.742937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.758573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775639.774223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.789833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.805575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.821083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775639.836731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775640.852402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775640.867956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775640.883585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775640.899208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775640.914833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775640.930462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775640.946092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775640.961729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775640.977333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775640.993172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775641.008577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.024366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.039859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775642.063872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.071074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.086756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.102372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775642.117981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.133596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.149402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.164842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775642.180619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.196205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.211730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775643.227353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.242968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.258582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.274206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775643.289835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.305441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.321080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.336713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775643.352324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.368436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.383581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775644.399201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.414843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.430457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.446065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775644.461934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.477327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.492943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.508570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775644.524206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.539905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.563022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775645.571080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.586723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.602338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.617949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775645.633595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.649207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.664829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.680451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775645.696083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.711747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.727302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775646.742925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.758574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.774200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.789875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775646.805450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.821074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.836712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.852319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775646.867956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775647.883620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775647.899252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775647.914833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775647.930483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775647.946076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775647.961715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775647.977329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775647.992980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775648.008616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775648.024213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775648.039869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.055546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.071076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775649.086707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.102331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.117954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.133604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775649.149196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.164817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.180446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.196070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775649.211729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.227384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.242956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775650.258593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.274195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.289820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.305456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775650.321086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.336718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.352330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.367950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775650.383574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.399260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.414871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775651.430463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.446081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.462021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.477312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775651.492952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.508573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.524205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.539834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775651.555444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.571133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.586699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775652.602321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.617951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.633587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.649189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775652.664820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.680444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.696068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.711787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775652.727313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.742989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.758568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775653.774193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.789831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.805439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.821062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775653.836699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.852307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.867940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.883563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775653.899188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775654.914899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775654.930469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775654.946081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775654.961800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775654.977309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775654.992949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775655.008580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775655.024226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775655.039878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775655.055484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775655.071089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.086767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.102329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775656.117983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.133602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.149200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.164831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775656.180472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.196079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.211798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.227329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775656.242985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.258624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.274197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775657.289826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.305442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.321064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.336703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775657.352310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.367934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.383567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.399182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775657.414844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.430865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.446090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775658.462021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.477337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.492953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.508572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775658.524214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.539857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.555462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.571074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775658.586705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.602367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.617949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775659.633595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.649189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.664818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.680444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775659.696074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.711776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.727320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.742968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775659.758564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.774231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.789822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775660.805555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.821090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.836716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.852335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775660.867952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.883562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.899193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.914825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775660.930447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775661.946117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775661.961764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775661.977318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775661.992950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775662.008596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775662.024206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775662.039848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775662.055439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775662.071069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775662.086696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775662.102310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.117981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.133590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775663.149197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.164822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.180445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.196077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775663.211737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.227319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.242965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.258571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775663.274184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.289860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.305442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775664.321067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.336718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.352316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.367942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775664.383558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.399186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.414842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.430437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775664.446148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.462111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.477398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775665.493029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.508649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.524200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.539860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775665.555452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.571077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.586702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.602318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775665.617955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.633615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.649208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775666.664824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.680461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.701465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.711771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775666.727390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.742953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.758594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.774359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775666.789915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.805548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.821081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775667.836922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.852328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.868371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.885712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775667.899219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.914838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.930710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.946310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775667.961824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775668.977422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775668.992963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775669.008590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775669.024228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775669.039889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775669.055455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775669.071081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775669.086709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775669.102330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775669.117958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775669.133584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.149361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.164818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775670.180439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.196084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.211724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.227317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775670.242982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.258572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.274204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.289828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775670.305458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.321155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.336723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775671.352333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.367944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.383580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.399184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775671.414835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.430445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.446145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.461949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775671.477325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.492977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.508577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775672.524204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.539848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.555430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.571074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775672.586700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.602308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.617940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.633557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775672.649283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.664849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.680448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775673.696070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.711712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.727312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.742967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775673.758573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.774186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.789806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.805438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775673.821056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.836778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.852322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775674.867960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.883570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.899186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.914823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775674.930531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.946146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.961705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.977310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775674.992938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.008639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.024219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775676.039863 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.055446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.071069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.086778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775676.102323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.117954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.133577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.149285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775676.164818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.180655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.196156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775677.211708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.227321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.242954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.258572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775677.274185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.289814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.305433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.321054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775677.336683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.352359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.367950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775678.383570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.399192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.414818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.430434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775678.446211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.461901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.477315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.492943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775678.508566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.524220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.539857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775679.555442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.571074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.586688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.602317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775679.617936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.633558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.649266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.664806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775679.680433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.696105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.711698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775680.727322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.742965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.758564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.774169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775680.789804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.805429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.821054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.836684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775680.852391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775681.867998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775681.883638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775681.899268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775681.914822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775681.930447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775681.946179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775681.961766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775681.977382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775681.993087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775682.008655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775682.024303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.042304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.055459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775683.071077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.086713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.102315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.117949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775683.133582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.149287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.164822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.180443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775683.196072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.211746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.227329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775684.242987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.258567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.274198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.289801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775684.305435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.321053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.336712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.352392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775684.367929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.383598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.399204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775685.414951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.430545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.446259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.461887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775685.477342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.492935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.508576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.524196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775685.539836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.555478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.571068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775686.586698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.602312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.617935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.633575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775686.649274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.664831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.680437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.696066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775686.711695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.727448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.742978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775687.758561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.774192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.789801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.805440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775687.821054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.836700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.852400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.867932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775687.883573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775688.899217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775688.914813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775688.930429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775688.946153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775688.961689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775688.977309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775688.992944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775689.008666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775689.024210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775689.039846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775689.055454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.071090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.086693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775690.102319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.117937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.133567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.149282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775690.164821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.180435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.196069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.211692 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775690.227309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.242981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.258571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775691.274212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.289815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.305454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.321070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775691.336730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.352419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.367988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.383578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775691.399201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.414885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.430439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775692.446158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.461904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.477318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.492935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775692.508579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.524309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.539842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.555553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775692.571167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.586716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.602324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775693.617940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.633569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.649286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.664822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775693.680437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.696214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.711691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.727324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775693.742941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.758652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.774204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775694.789828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.805448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.821072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.836672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775694.852392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.867938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.883571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.899188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775694.914802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775695.930578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775695.946193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775695.961708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775695.977340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775695.992945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775696.008585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775696.024210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775696.040136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775696.055454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775696.071064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775696.086753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.102387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.117958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775697.133562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.149291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.164817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.180428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775697.196056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.211705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.227304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.242920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775697.258579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.274244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.289801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775698.305439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.321050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.336687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.352767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775698.367940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.383572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.399200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.414836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775698.430447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.446203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.461900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775699.477312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.492942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.508551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.524213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775699.539842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.555447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.571056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.586686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775699.602296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.617987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.633564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775700.649277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.664830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.680454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.696057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775700.711690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.727298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.742932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.758579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775700.774181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.789920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.805461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775701.821068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.836683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.852399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.867928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775701.883568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.899177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.914816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.930424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775701.946057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775702.961714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775702.977322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775702.992930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775703.008572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775703.024208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775703.039851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775703.055442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775703.071058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775703.086685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775703.102315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775703.117960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.133583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.149291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775704.164813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.180439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.196064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.211673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775704.227300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.242937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.258569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.274176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775704.289804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.305471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.321062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775705.336680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.352386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.367938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.383553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775705.399190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.414827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.430440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.446053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775705.461901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.477383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.492944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775706.508560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.524184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.539836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.555453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775706.571064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.586682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.602306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.617935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775706.633565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.649351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.664813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775707.680434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.696054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.711679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.727309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775707.742943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.758576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.774177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.789801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775707.805431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.821102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.836686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775708.852399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.867932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.883558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.899166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775708.914796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.930432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.946058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.961707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775708.977309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775709.993003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775710.008566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775710.024212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775710.039850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775710.055447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775710.071071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775710.086698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775710.102308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775710.117948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775710.133563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775710.149182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.164844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.180428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775711.196084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.211679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.227310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.242925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775711.258564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.274176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.289808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.305420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775711.321050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.336706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.352410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775712.367948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.383570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.399175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.414832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775712.430438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.446053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.461918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.477303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775712.492920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.508598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.524190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775713.539823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.555449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.571051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.586677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775713.602300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.617930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.633577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.649181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775713.664811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.680480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.696049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775714.711670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.727302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.742922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.758557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775714.774163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.789792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.805428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.821053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775714.836678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775715.852471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775715.867944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775715.883742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775715.899188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775715.914904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775715.930431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775715.946178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775715.961815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775715.977311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775715.992943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775716.008566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.024224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.039834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775717.055458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.071042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.086662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.102302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775717.117939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.133566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.149187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.164815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775717.180425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.196101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.211680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775718.227306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.242932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.258572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.274178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775718.289815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.305411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.321045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.336671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775718.352295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.367968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.383561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775719.399185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.414826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.430452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.446053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775719.461884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.477293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.492920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.508556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775719.524173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.539914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.555449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775720.571062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.586684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.602297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.617923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775720.633549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.649186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.664824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.680418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775720.696050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.711718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.727301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775721.742931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.758572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.774173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.789796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775721.805423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.821045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.836669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.852292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775721.867933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775722.883598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775722.899183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775722.914821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775722.930434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775722.946047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775722.961695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775722.977304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775722.992915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775723.008550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775723.024199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775723.039820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.055488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.071065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775724.086747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.102318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.117930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.133543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775724.149180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.164826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.180418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.196037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775724.211669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.227393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.242935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775725.258588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.274186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.289808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.305424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775725.321057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.336683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.352298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.367937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775725.383550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.399223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.414807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775726.430433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.446051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.461928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.477298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775726.492923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.508539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.524192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.539812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775726.562959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.571094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.586683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775727.602298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.617928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.633549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.649179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775727.664826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.680413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.696048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.711662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775727.727296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.743027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.758582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775728.774255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.789880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.805496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.821147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775728.836683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.852312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.867956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.883713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775728.899190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775729.914913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775729.930434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775729.946061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775729.961717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775729.977306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775729.992938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775730.008548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775730.024201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775730.039826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775730.062912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775730.071070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.086841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.102372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775731.117943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.133577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.149209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.164836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775731.180451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.196101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.211699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.227342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775731.242972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.258649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.274191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775732.289804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.305433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.321060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.336678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775732.352304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.367945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.383537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.399182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775732.414837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.430656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.446203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775733.462048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.477441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.492975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.508578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775733.524184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.539813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.555420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.571063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775733.586662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.602342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.617936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775734.633557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.649180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.664910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.680420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775734.696049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.711668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.727295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.742918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775734.758550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.774236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.789812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775735.805616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.821060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.836681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.852308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775735.867944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.883545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.899180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.914802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775735.930420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775736.946268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775736.961711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775736.977309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775736.992931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775737.008571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775737.024220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775737.039842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775737.055425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775737.071081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775737.086687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775737.102295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.117987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.133562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775738.149183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.164820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.180432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.196064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775738.211685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.227299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.242919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.258563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775738.274187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.289824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.305424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775739.321056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.336671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.352297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.367937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775739.383541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.399173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.414812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.430424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775739.446051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.461916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.477307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775740.492914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.508598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.524168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.539825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775740.555436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.571056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.586670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.602305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775740.617915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.633590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.649175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775741.664818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.680454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.696045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.711674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775741.727292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.742916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.758557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.774186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775741.789820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.805456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.821044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775742.836671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.852291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.867929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.883563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775742.899161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.914785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.930410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.946041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775742.961662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775743.977401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775743.992931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775744.008540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775744.024184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775744.039813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775744.055412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775744.071056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775744.086721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775744.102290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775744.117910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775744.133529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.149207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.164817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775745.180412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.196052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.211666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.227289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775745.242917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.258526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.274208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.289771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775745.305417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.321063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.336676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775746.352286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.367940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.383532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.399163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775746.414806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.430423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.446038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.461875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775746.477312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.493032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.508579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775747.524190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.539855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.555550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.571073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775747.586679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.602298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.617924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.633570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775747.649182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.664873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.680427 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775748.696051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.711675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.727293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.742912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775748.758551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.774234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.789796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.805413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775748.821047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.836729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.852406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775749.867944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.883566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.899190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.914795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775749.930405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.946040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.961671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.977315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775749.992928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.008583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.024192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775751.039826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.055426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.071061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.086666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775751.102282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.117909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.133533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.149158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775751.164782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.180449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.196049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775752.211678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.227359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.242927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.258542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775752.274172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.289793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.305418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.321038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775752.336662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.352323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.367933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775753.383542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.399165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.414804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.430411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775753.446062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.461866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.477314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.492926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775753.508534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.524366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.539864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775754.555431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.571078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.586682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.602283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775754.617908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.633545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.649161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.664796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775754.680423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.696096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.711810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775755.727297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.742951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.758558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.774255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775755.789841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.805436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.821066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.836678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775755.852299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775756.868007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775756.883587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775756.899167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775756.914796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775756.930415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775756.946036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775756.961671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775756.977287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775756.992910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775757.008550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775757.024182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.039867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.055471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775758.071081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.086697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.102334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.117926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775758.133549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.149164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.164786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.180424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775758.196041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.211727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.227325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775759.242925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.258558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.274191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.289789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775759.305408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.321052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.336735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.352302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775759.367915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.383740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.399494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775760.414862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.430926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.446142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.461888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775760.477315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.493270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.508635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.524269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775760.541067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.555474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.571086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775761.586675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.602290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.617929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.633546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775761.649172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.664791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.680437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.696053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775761.711665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.727378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.742925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775762.758551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.774223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.789776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.805582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775762.821124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.836675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.852330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.867932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775762.883548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775763.899342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775763.914966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775763.930423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775763.946099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775763.961677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775763.977327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775763.993079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775764.008809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775764.024251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775764.039840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775764.055430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.071150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.086695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775765.102291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.117936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.133540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.149181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775765.164796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.180438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.196049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.211671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775765.227297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.242983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.258542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775766.274181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.289835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.305424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.321065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775766.336678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.352302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.368304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.383573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775766.399182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.414929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.430423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775767.446047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.461923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.477304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.492927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775767.508540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.524175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.539816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.555433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775767.571054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.586729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.602301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775768.617941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.633548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.649167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.664797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775768.680433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.696041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.711675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.727302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775768.742922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.758579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.774187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775769.789817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.805413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.821058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.836679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775769.852281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.867928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.883566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.899159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775769.914792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775770.930473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775770.946052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775770.961679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775770.977307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775770.992918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775771.008550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775771.024201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775771.039816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775771.055426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775771.071058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775771.086729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.102319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.117921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775772.133542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.149174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.164788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.180425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775772.196033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.211660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.227285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.242913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775772.258541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.274212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.289787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775773.305424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.321052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.336659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.352285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775773.367908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.383553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.399182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.414805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775773.430439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.446096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.461889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775774.477312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.492930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.508587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.524339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775774.539838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.555432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.571068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.586698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775774.602301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.617960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.633653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775775.649178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.664813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.680430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.696051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775775.711670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.727306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.742920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.758541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775775.774164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.789833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.805405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775776.821065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.836664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.852293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.867914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775776.883563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.899172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.914800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.930475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775776.946031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775777.961712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775777.977302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775777.992914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775778.008554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775778.024181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775778.039811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775778.055415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775778.071075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775778.086688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775778.102271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775778.117914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.133573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.149152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775779.164792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.180421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.196058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.211653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775779.227273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.242902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.258540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.274150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775779.289792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.305485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.321073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775780.336659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.352294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.367903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.383562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775780.399171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.414805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.430410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.446039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775780.461928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.477324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.492915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775781.508543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.524168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.539801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.555417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775781.571047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.586666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.602280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.617905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775781.633527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.649179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.664788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775782.680428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.696031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.711651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.727273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775782.742926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.758531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.774138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.789795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775782.805399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.821093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.836659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775783.852356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.867906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.883616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.899158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775783.914783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.930468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.946110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.961670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775783.977278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775784.992938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775785.008522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775785.024183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775785.039808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775785.055407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775785.071036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775785.086681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775785.102273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775785.117909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775785.133535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775785.149150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.164848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.180434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775786.196055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.211660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.227298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.242917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775786.258537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.274156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.289797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.305421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775786.321046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.336709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.352287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775787.367918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.383603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.404432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.414803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775787.430699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.446038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.461899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.477275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775787.493031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.508642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.524183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775788.539821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.555417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.571051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.586691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775788.602346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.617908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.633542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.649225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775788.664786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.680532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.696044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775789.711666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.727291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.742922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.758545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775789.774232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.789854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.805496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.821155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775789.836672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775790.852364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775790.867922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775790.883761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775790.899158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775790.914783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775790.930408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775790.946049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775790.961653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775790.977275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775790.992918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775791.008529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.024243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.039816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775792.055473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.071044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.086727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.102279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775792.117914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.133525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.149131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.164770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775792.180398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.196073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.211656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775793.227297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.242912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.258525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.274148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775793.289788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.305395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.321035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.336650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775793.352272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.367945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.383565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775794.399167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.414809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.430401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.446033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775794.461891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.477278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.492921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.508550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775794.524158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.539950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.555425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775795.571045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.586677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.602286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.617913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775795.633538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.649154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.664779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.680399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775795.696051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.711713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.727296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775796.742920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.758536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.774167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.789793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775796.805401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.821040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.836662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.852286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775796.867909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775797.883616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775797.899153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775797.914790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775797.930843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775797.946050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775797.961665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775797.977283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775797.992930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775798.008537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775798.024187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775798.039823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.055501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.071061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775799.086694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.102296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.117925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.133546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775799.149164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.164780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.180412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.196058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775799.211667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.227318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.242916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775800.258531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.274159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.289794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.305402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775800.321064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.336658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.352276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.367894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775800.383537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.399183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.414813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775801.430412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.446031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.461858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.477274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775801.492919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.508526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.524158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.539796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775801.562884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.571065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.586676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775802.602282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.617915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.633523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.649149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775802.664773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.680396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.696041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.711650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775802.727277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.742946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.758548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775803.774173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.789796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.805404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.821038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775803.836647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.852273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.867910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.883534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775803.899162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775804.914812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775804.930413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775804.946028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775804.961664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775804.977278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775804.992922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775805.008524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775805.024168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775805.039803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775805.062810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775805.071032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775805.086654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775805.102320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775805.117947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775805.133540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775805.149167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775806.164818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775806.180404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775806.196045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775806.211660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775806.227276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775806.242906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775806.258522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775806.274142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775806.289765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775806.305422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775806.321134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.336706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.352288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775807.367905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.383575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.399167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.414797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775807.430397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.446044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.461869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.477273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775807.492912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.508542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.524164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775808.539789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.555407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.571116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.586640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775808.602286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.617889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.633515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.649143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775808.664767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.680439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.696052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775809.711648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.727277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.742892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.758515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775809.774142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.789761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.805407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.821106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775809.836640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775810.852304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775810.867893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775810.883519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775810.899182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775810.914768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775810.930395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775810.946025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775810.961644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775810.977264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775810.992892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775811.008534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.024207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.039806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775812.062583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.071111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.086731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.102283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775812.117912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.133526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.149140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.164772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775812.180392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.196076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.211649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775813.227280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.242912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.258543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.274144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775813.289766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.305408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.321095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.336648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775813.352266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.367923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.383544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775814.399163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.414811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.430392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.446022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775814.461851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.477262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.492896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.508531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775814.524207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.539926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.563533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775815.571123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.586663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.602292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.617896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775815.633511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.649152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.664787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.680421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775815.696025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.711723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.727279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775816.742922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.758533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.774159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.789772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775816.805528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.821096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.836658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.852293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775816.867911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775817.883569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775817.899170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775817.914840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775817.930436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775817.946075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775817.961665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775817.977274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775817.992898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775818.008554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775818.024182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775818.040076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.055424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.071088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775819.086665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.102295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.117910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.133522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775819.149146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.164954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.180409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.196053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775819.211663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.227330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.242893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775820.258517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.274145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.289766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.305405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775820.321069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.336639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.352271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.367894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775820.383525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.399308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.414808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775821.430392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.446024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.461928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.477285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775821.492892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.508542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.524153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.539799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775821.555396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.571090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.586657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775822.602297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.617909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.633524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.649145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775822.664774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.680407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.696018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.711673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775822.727273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.743014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.758532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775823.774142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.789783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.805412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.821048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775823.836644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.852276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.867895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.883521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775823.899145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775824.914798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775824.930390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775824.946021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775824.961659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775824.977283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775824.992896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775825.008527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775825.024174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775825.039787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775825.055397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775825.071069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775825.086665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775825.102276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775825.117937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775825.133529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775825.149153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775826.164845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775826.180415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775826.196030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775826.211681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775826.227296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775826.242911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775826.258529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775826.274165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775826.289774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775826.305392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775826.321082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.336672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.352290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775827.367899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.383528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.399155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.414811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775827.430389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.446018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.461845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.477283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775827.492893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.508676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.524163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775828.539795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.555408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.571043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.586655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775828.602263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.617924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.633518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.649137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775828.664787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.680539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.696034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775829.711689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.727277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.743025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.758524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775829.774143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.789869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.805388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.821179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775829.836654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775830.852365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775830.867911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775830.883528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775830.899155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775830.914799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775830.930848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775830.946032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775830.961655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775830.977281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775830.992910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775831.008534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.024263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.039818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775832.055401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.071040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.086698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.102272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775832.117965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.133513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.149163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.164765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775832.180394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.196056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.211673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775833.227273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.242916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.258524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.274155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775833.289768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.305387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.321054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.336641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775833.352270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.367954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.383552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775834.399170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.414796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.430392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.445997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775834.461854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.477285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.492894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.508520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775834.524230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.539913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.555592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775835.571047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.586648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.602274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.617906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775835.633626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.649140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.664778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.680492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775835.696019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.711707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.727278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775836.742910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.758530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.774164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.789816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775836.805396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.821058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.836651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.852267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775836.867893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775837.883592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775837.899156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775837.914798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775837.930385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775837.946029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775837.961661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775837.977273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775837.992893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775838.008515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775838.024182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775838.039805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.055440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.071032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775839.086666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.102269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.117914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.133530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775839.149200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.164750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.180401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.196017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775839.211641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.227336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.242896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775840.258532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.274153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.289768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.305379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775840.321047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.336635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.352380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.367893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775840.383515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.399198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.414803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775841.430395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.446010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.461860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.477285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775841.493259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.508520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.524278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.539840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775841.555395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.571085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.586656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775842.602270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.617913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.633515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.649151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775842.664768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.680388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.696018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.711642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775842.727282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.742938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.758536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775843.774146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.789781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.805395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.821033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775843.836643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.852260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.867898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.883519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775843.899141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775844.914798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775844.930975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775844.946022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775844.961660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775844.977278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775844.992902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775845.008518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775845.024182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775845.039801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775845.055400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775845.071024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.086685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.102269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775846.117911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.133540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.149147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.164772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775846.180434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.196023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.211646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.227279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775846.242905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.258595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.274153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775847.289780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.305397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.321041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.336640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775847.352270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.367892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.383520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.399140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.414796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775847.789820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775847.805408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775847.821058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775847.836668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775847.852299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775848.430513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775848.446142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775848.462016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775848.477331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775848.493082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775848.508596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775848.524256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775848.539881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775848.555479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775848.571115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775848.586735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.602344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.617922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775849.633525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.649162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.664777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.680410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775849.696213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.711653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.727300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.742903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775849.758521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.774693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.789901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775850.805601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.821063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.836673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.852285 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775850.867943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.883717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.899379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.914939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775850.930514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775851.946104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775851.961673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775851.977272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775851.992906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775852.008524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775852.024188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775852.039799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775852.055473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775852.071030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775852.086709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775852.102262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.117936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.133538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775853.149141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.164772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.180399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.196015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775853.211637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.227280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.242897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.258512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775853.274158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.289813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.305397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775854.321036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.336655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.352258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.367883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775854.383512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.399151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.414786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.430413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775854.446021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.461890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.477263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775855.492884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.508514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.524166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.539787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775855.555378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.571059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.586656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.602254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775855.617895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.633581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.649145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775856.664810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.680399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.696020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.711654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775856.727282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.742889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.758513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.774123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775856.789775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.805466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.821044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775857.836647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.852278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.867881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.883510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775857.899129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.914764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.930395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.946006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775857.961644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775858.977410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775858.992969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775859.008517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775859.024183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775859.039811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775859.055385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775859.071022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775859.086642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775859.102267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775859.117887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775859.133552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.149209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.164775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775860.180402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.196015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.211650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.227289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775860.242889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.258526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.274137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.289760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775860.305389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.321116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.336698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775861.352315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.367899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.383539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.399141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775861.414790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.430417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.446008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.461911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775861.477260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.492916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.508532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775862.524173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.539811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.555422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.571011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775862.586635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.602271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.617882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.633526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775862.649141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.664907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.680401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775863.696013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.711634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.727297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.742888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775863.758537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.774143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.789760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.805476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775863.821020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.836779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.852270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775864.867885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.883510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.899137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.914756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775864.930481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.946018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.961637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.977328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775864.992886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.008604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.024190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775866.039797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.055382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.071019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.086660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775866.102263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.117896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.133537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.149131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775866.164756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.180485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.196031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775867.211640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.227290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.242898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.258524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775867.274153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.289775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.305392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.321015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775867.336649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.352370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.367907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775868.383533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.399136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.414812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.430401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775868.446016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.461902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.477266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.492899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775868.508509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.524230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.539817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775869.555408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.571009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.586659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.602262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775869.617891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.633520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.649133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.664757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775869.680385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.696065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.711635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775870.727291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.742897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.758531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.774149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775870.789757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.805373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.821014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.836650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.852257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775870.867907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775870.883530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775870.899156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775870.914768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775870.930409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342775871.946067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775871.961652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775871.977270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775871.992898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775872.008524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775872.024166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775872.039810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775872.055390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775872.071020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775872.086728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775872.102257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.117940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.133529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775873.149144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.164769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.180399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.196014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775873.211652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.227264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.242913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.258529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775873.274144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.289790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.305402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775874.321173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.336672 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.352254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.367881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775874.383533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.399129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.414766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.430398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775874.446107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.462000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.477266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775875.492893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.508512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.524143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.539787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775875.555384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.571003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.586642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.602257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775875.617874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.633599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.649143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775876.664784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.680387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.696027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.711643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775876.727270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.742917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.758522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.774148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775876.789782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.805421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.821025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775877.836666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.852236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.867897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.883497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775877.899143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.914759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.930379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.946098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775877.961636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775878.977306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775878.992888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775879.008524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775879.024162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775879.039807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775879.055394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775879.071017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775879.086650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775879.102275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775879.117894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775879.133513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.149223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.164763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775880.180387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.196007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.211634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.227255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775880.242902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.258508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.274128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.289757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775880.305366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.321059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.336663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775881.352257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.367881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.383488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.399109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775881.414789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.430378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.446104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.461864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775881.477249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.492989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.508532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775882.524185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.555693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.571013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.587024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775882.602255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.617911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.633517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.649238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775882.664805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.680582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.696020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775883.711747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.727317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.742894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.758522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775883.774141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.789778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.805389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.821196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775883.836753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775884.852332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775884.867900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775884.883510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775884.899148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775884.914760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775884.930383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775884.946088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775884.961681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775884.977263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775884.993118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775885.008519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.024208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.039783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775886.055392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.071002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.086666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.102260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775886.117899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.133503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.149198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.164749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775886.180402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.196050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.211644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775887.227269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.242901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.258527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.274132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775887.289764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.305402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.321007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.336634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775887.352339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.368060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.383568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775888.399185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.414867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.430528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.446101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775888.461901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.477260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.492894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.508643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775888.524201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.539860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.555406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775889.571017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.586625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.602258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.617866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775889.633537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.649204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.664765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.680370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775889.695998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.711679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.727272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775890.742888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.758528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.774125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.789751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775890.805391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.820997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.836626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.852331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775890.867889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775891.883538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775891.899130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775891.914754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775891.930387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775891.946076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775891.961651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775891.977248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775891.992875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775892.008508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775892.024145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775892.039764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.055415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.071015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775893.086643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.102259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.117885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.133497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775893.149202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.164772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.180381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.195998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775893.211630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.227279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.242909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775894.258521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.274126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.289748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.305369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775894.320995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.336621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.352317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.367885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775894.383506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.399181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.414774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775895.430382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.446063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.461877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.477246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775895.492873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.508496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.524123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.539747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775895.555384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.571092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.586644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775896.602261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.617887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.633519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.649222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775896.664801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.680393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.696003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.711633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775896.727262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.742931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.758529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775897.774127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.789772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.805380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.821010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775897.836636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.852346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.867904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.883527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775897.899144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775898.914826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775898.930943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775898.946081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775898.961679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775898.977269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775898.992873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775899.008512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775899.024156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775899.039827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775899.055388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775899.071026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.086750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.102263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775900.117997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.133506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.149224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.164786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775900.180374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.195997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.211633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.227270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775900.242887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.258561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.274137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775901.289762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.305383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.321003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.336623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775901.352319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.367885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.383497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.399138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775901.414782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.430845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.446102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775902.461858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.477258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.492887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.508511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775902.524132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.539756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.555393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.571029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775902.586629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.602287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.617887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775903.633511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.649202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.664775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.680373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775903.696019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.711629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.727261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.742877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775903.758504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.774149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.789762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775904.805388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.821001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.836614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.852334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775904.867888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.883499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.899127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.914760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775904.930379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775905.946110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775905.961658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775905.977256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775905.992888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775906.008511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775906.024152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775906.039756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775906.055364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775906.071056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775906.086646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775906.102245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.118034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.133608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775907.149213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.164790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.180373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.196012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775907.211619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.227258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.242879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.258515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775907.274149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.289826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.305393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775908.321012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.336725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.352444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.367887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775908.383614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.399223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.414905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.430376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775908.446114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.461950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.477265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775909.492875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.508543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.524133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.539778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775909.555376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.571034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.586612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.602242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775909.617876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.633576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.649197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775910.664783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.680386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.695994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.711617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775910.727239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.742871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.758500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.774132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775910.789753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.805419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.821008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775911.836623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.852339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.867881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.883494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775911.899118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.914787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.930510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.946005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775911.961628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775912.977291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775912.992892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775913.008524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775913.024150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775913.039772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775913.055405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775913.071010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775913.086625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775913.102246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775913.117887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775913.133496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.149243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.164784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775914.180389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.195998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.211619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.227244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775914.242879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.258495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.274131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.289740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775914.305392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.321053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.336620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775915.352337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.367882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.383498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.399120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775915.414798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.430367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.445996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.461878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775915.477284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.492935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.508511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775916.524153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.539759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.555388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.571031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775916.586631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.602255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.617885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.633518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775916.649138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.664799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.680393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775917.696015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.711630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.727251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.742879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775917.758500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.774147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.789736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.805367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775917.820989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.836698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.852338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775918.867943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.883510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.899142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.914764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775918.930398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.945997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.961645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.977271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775918.992869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.008533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.024154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775920.039771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.055373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.071011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.086656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775920.102240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.117894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.133501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.149206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775920.164763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.180440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.196001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775921.211625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.227249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.242876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.258502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775921.274133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.289754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.305367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.320988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775921.336632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.352435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.367897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775922.383508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.399118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.414786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.430386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775922.446008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.461851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.477261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.492896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775922.508512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.524191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.539761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775923.555387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.571014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.586619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.602244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775923.617879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.633496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.649141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.664777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775923.688083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.696132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.711636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775924.727248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.742888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.758506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.774142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775924.789734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.805365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.820995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.836620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775924.852246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775925.867978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775925.883521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775925.899137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775925.914782 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775925.930400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775925.946015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775925.961626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775925.977269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775925.992895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775926.008510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775926.024159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.039813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.055386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775927.071014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.086638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.102255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.117894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775927.133501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.149131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.164777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.187708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775927.196012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.211657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.227249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775928.242868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.258517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.274154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.289751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775928.305380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.320992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.336616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.352279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775928.367867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.383542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.399126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775929.414769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.430382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.445989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.461815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775929.477263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.492865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.508505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.524118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775929.539764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.555464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.571017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775930.586622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.602254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.617869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.633488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775930.649109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.664755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.687897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.695983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775930.711606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.727307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.742885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775931.758496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.774152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.789745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.805375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775931.821013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.836620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.852313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.867879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775931.883509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775932.899166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775932.914755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775932.930838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775932.946004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775932.961640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775932.977261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775932.992868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775933.008490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775933.024133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775933.039755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775933.055362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.071040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.086629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775934.102244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.117892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.133496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.149110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775934.164765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.180391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.195994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.211612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775934.227250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.242916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.258525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775935.274146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.289765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.305375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.321008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775935.336627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.352254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.367876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.383515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775935.399141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.414810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.430385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775936.445993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.461974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.477263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.492876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775936.508504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.524133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.539732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.555366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775936.570991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.586649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.602251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775937.617868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.633502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.649118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.664755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775937.680384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.695989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.711624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.727231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775937.742859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.758565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.774148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775938.789746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.805385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.820999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.836629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775938.852242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.867868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.883505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.899121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775938.914739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775939.930856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775939.946011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775939.961635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775939.977266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775939.992879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775940.008507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775940.024153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775940.039764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775940.055377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775940.070995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775940.086709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.102411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.118199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775941.133509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.149124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.164790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.180446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775941.196003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.211660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.227264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.242900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775941.258561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.274218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.289753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775942.305367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.321002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.336612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.352256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775942.367882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.383513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.399120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.414771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775942.430383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.446040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.461859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775943.477269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.492881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.508485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.524133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775943.539731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.555397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.570989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.586630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775943.602236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.617911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.633508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775944.649121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.664769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.680411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.696010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775944.711607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.727237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.742861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.758490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775944.774204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.789819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.805373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775945.820990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.836623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.852231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.867892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775945.883516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.899113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.914738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.930389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775945.945981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775946.961759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775946.977269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775946.992865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775947.008495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775947.024143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775947.039776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775947.055373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775947.070996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775947.086646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775947.102249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775947.117868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.133601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.149125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775948.164766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.180397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.195998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.211611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775948.227271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.242855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.258487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.274124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775948.289812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.305404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.321001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775949.336616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.352243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.367937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.383510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775949.399111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.414765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.430380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.445985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775949.461838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.477320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.492868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775950.508488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.524115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.539735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.555356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775950.570987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.586625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.602237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.617859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775950.633490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.649137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.664770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775951.680397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.696004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.711617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.727237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775951.742881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.758486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.774116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.789746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775951.805369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.821028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.836619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775952.852243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.867868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.883518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.899105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775952.914760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.930384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.945986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.961609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775952.977233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775953.992885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775954.008514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775954.024147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775954.039766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775954.055368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775954.070999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775954.086630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775954.102231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775954.117872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775954.133486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775954.149117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.164820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.180438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775955.196017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.211623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.227240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.242869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775955.258491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.274116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.289779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.305357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775955.320985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.336742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.352226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775956.367873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.383522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.399116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.414769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775956.430387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.445991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.461891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.477237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775956.492879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.508536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.524124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775957.539729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.555353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.570998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.586629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775957.602228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.617856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.633479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.649107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775957.664754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.680466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.696009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775958.711617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.727245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.742880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.758512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775958.774119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.789755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.805381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.820996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775958.836611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775959.852317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775959.867876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775959.883515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775959.899120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775959.914753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775959.930375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775959.946003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775959.961631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775959.977254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775959.992884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775960.008481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.024173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.039754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775961.055360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.070986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.086633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.102243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775961.117879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.133486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.149112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.164761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775961.180378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.196033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.211623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775962.227244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.242870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.258498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.274107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775962.289768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.305362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.320983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.336627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775962.352243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.367895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.383505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775963.399111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.414764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.430470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.445987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775963.461819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.477230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.492884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.508477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775963.524131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.539758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.555363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775964.570985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.586623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.602229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.617859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775964.633481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.649102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.664773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.680454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775964.695997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.711633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.727252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775965.742870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.758498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.774105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.789742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775965.805352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.820976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.836603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.852223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775965.867856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775966.883543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775966.899119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775966.914735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775966.930451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775966.945991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775966.961618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775966.977233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775966.992865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775967.008485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775967.024130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775967.039749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.055392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.071004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775968.086697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.102241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.117889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.133484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775968.149103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.164765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.180448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.196000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775968.211600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.227314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.242877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775969.258495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.274129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.289758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.305367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775969.320985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.336629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.352229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.367854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775969.383490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.399185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.414794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775970.430506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.445983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.461849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.477265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775970.492871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.508491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.524117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.539729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775970.555369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.571041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.586644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775971.602225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.617857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.633505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.649112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775971.664745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.680424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.695992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.711598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775971.727247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.742888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.758494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775972.774116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.789757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.805361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.820983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775972.836663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.852240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.867869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.883481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775972.899131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775973.914764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775973.930435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775973.945990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775973.961612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775973.977235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775973.993074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775974.008484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775974.024141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775974.039747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775974.055367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775974.070977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.086741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.102257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775975.117874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.133513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.149125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.164763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775975.180425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.196027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.211617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.227239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775975.242872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.258544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.274125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775976.289761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.305368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.320991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.336635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775976.352245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.367866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.383496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.399138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775976.414787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.430446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.445997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775977.461829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.477254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.492873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.508480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775977.524128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.539736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.555355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.570979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775977.586612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.602358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.617868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775978.633496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.649120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.664771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.680400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775978.696009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.711606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.727240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.742856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775978.758482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.774165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.789753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775979.805369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.820990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.836617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.852227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775979.867855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.883483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.899123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.914735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775979.930394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775980.946042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775980.961622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775980.977237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775980.992907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775981.008489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775981.024124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775981.039865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775981.055362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775981.071068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775981.086624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775981.102257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.117930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.133499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775982.149140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.164770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.180405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.196006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775982.211606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.227240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.242865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.258487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775982.274119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.289800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.305359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775983.320981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.336622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.352245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.367856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775983.383477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.399121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.414750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.430382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775983.445994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.461858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.477243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775984.492877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.508491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.524113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.539727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775984.555377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.570978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.586603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.602249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775984.617849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.633536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.649110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775985.664760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.680481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.696003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.711608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775985.727244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.742864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.758580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.774102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775985.789828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.805496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.820987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775986.836606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.852231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.867846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.883473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775986.899114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.914731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.930354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.945983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775986.961604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775987.977271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775987.992882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775988.008487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775988.024146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775988.039753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775988.055358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775988.070987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775988.086682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775988.102251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775988.117864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775988.133512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.149145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.164773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775989.180386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.196001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.211618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.227230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775989.242848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.258480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.274108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.289724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775989.305372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.321038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.336613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775990.352230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.367862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.383493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.399133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775990.414765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.430355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.445980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.461816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775990.477232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.492906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.508495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775991.524113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.539735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.555367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.570974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775991.586601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.602269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.617847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.633481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775991.649115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.664807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.680431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775992.696122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.711602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.727239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.742866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775992.758483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.774127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.789732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.805374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775992.820991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.836639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.852230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775993.867857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.883480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.899123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.914729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775993.930373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.945981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.961615 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.977220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775993.992848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.008623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.024146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775995.039781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.055367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.071011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.086628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775995.102237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.117874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.133498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.149111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775995.164779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.180434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.195998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775996.211607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.227245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.242888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.258477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775996.274120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.289737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.305367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.320978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775996.336612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.352311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.367876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775997.383506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.399132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.414768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.430360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775997.445970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.461827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.477222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.492870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775997.508492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.524193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.539750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775998.555355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.570977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.586604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.602243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775998.617853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.633468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.649100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.664743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775998.687808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.696335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.711669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775999.727229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.742866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.758476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.774194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342775999.789814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.805369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.820975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.836599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342775999.852230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776000.867958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776000.883481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776000.899117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776000.914722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776000.930527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776000.946056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776000.961614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776000.977209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776000.992856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776001.008490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776001.024118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.039793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.055461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776002.071015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.086605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.102235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.117876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776002.133464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.149104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.164734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.187817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776002.195974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.211845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.227434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776003.243080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.258537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.274120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.289755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776003.305601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.321150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.336668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.352316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776003.368367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.383547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.399132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776004.414948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.430908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.446197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.461920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776004.477325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.492883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.508757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.524130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776004.539964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.555458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.571044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776005.586611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.602249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.617866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.633464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776005.649098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.664737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.687965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.695974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776005.711620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.727272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.742864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776006.758487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.774106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.789719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.805354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776006.820968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.836574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.852217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.867846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776006.883471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776007.899195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776007.914747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776007.930357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776007.945991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776007.961607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776007.977230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776007.992866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776008.008503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776008.024130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776008.039747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776008.055355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.071071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.086632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776009.102256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.117867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.133485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.149100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776009.164755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.187955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.195980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.211638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776009.227254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.242883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.258492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776010.274110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.289734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.305371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.320978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776010.336599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.352232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.367857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.383498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776010.399117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.414768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.430383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776011.445980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.461802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.477229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.493052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776011.508497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.524110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.539746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.555357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776011.570992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.586617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.602247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776012.617872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.633490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.649102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.664751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776012.687665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.696112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.711626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.727232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776012.742859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.758509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.774104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776013.789716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.805365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.820972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.836598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776013.852216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.867852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.883478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.899109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776013.914745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776014.930468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776014.945988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776014.961695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776014.977233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776014.992919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776015.008565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776015.024144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776015.039814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776015.055358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776015.071067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776015.086622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.102351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.117961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776016.133479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.149102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.164746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.187772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776016.195970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.211605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.227213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.242836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776016.258468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.274135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.289727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776017.305360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.320976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.336601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.352212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776017.367845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.383488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.399092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.414748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776017.430348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.446015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.461824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776018.477231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.492855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.508481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.524107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776018.539707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.555366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.570969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.586598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776018.602219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.617940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.633528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776019.649109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.664755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.680482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.695978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776019.711739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.727236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.742905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.758479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776019.774111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.789786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.805564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776020.820980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.836604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.852224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.867859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776020.883471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.899107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.914751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.930340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776020.945996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776021.961664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776021.977232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776021.992848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776022.008499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776022.024118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776022.039749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776022.055367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776022.070968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776022.086603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776022.102222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776022.117880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.133520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.149095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776023.164748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.180353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.195983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.211608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776023.227231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.242854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.258472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.274104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776023.289726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.305413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.320977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776024.336603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.352227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.367852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.383498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776024.399107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.414751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.430343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.445974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776024.461821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.477263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.492845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776025.508501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.524115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.539723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.555346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776025.570976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.586594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.602223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.617865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776025.633481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.649134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.664851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776026.680387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.696004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.711674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.727227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776026.742853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.758484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.774097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.789724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776026.805351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.821005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.836609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776027.852220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.867856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.883478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.899096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776027.914725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.930341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.945956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.961608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776027.977212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776028.993123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776029.008495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776029.024161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776029.040776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776029.055417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776029.071025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776029.086698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776029.102220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776029.117883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776029.133478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776029.149106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.164821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.180349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776030.195982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.211607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.227218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.242853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776030.258471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.274188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.289720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.305342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776030.320990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.336754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.352340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776031.368049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.383690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.399113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.414759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776031.430339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.445969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.461860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.477479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776031.492934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.508819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.524178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776032.539783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.555404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.571011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.586617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776032.602212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.617854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.633521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.649134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776032.664753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.680698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.696225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776033.711682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.727262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.742916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.758529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776033.774175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.790032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.805796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.821264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776033.836940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776034.852316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776034.867870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776034.883483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776034.899101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776034.914738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776034.930345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776034.945964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776034.961614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776034.977228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776034.992843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776035.008487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.024288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.039761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776036.055354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.070967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.086655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.102217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776036.117880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.133469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.149105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.164740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776036.180344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.196075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.211625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776037.227232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.242855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.258489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.274109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776037.289726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.305346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.320983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.336601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776037.352215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.368050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.383549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776038.399100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.414753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.430350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.446013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776038.461818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.477232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.492851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.508466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776038.524142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.539800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.555358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776039.570988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.586593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.602227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.617867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776039.633523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.649140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.664745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.680337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776039.695965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.711689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.727264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776040.742906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.758473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.774156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.789729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776040.805366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.820985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.836587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.852217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776040.867833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776041.883548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776041.899107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776041.914733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776041.930337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776041.945973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776041.961606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776041.977217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776041.992872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776042.008474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776042.024121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776042.039746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.055369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.070971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776043.086598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.102220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.117851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.133464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776043.149086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.164728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.180336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.195958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776043.211600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.227353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.242851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776044.258465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.274097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.289707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.305344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776044.320971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.336596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.352221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.367828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776044.383456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.399205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.414829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776045.430418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.445970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.461806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.477214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776045.492918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.508466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.524105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.539710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776045.555381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.571098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.586610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776046.602208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.617855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.633463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.649093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776046.664732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.680345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.695969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.711586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776046.727241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.743058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.758479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776047.774102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.789730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.805348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.820997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776047.836590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.852212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.867836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.883470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776047.899097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776048.914864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776048.930359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776048.945970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776048.961601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776048.977216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776048.992840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776049.008461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776049.024129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776049.039730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776049.055332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776049.070959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.086631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.102224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776050.117857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.133467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.149081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.164727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776050.180334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.195976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.211582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.227217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776050.242837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.258498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.274096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776051.289711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.305350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.320995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.336581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776051.352207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.367832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.383465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.399083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776051.414730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.430372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.445973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776052.461802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.477217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.492843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.508473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776052.524117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.539717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.555352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.570974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776052.586591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.602241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.617861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776053.633457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.649089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.664733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.680332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776053.695990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.711586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.727216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.742832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776053.758483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.774263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.789891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776054.805363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.821154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.836598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.852220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776054.867856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.883480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.899103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.914718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776054.930363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776055.946024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776055.961599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776055.977225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776055.992844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776056.008467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776056.024134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776056.039731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776056.055338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776056.070959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776056.086639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776056.102212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.117930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.133470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776057.149092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.164743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.180347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.195967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776057.211599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.227233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.242841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.258456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776057.274084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.289753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.305356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776058.320982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.336597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.352216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.367837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776058.383477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.399097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.414747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.430363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776058.445984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.461854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.477227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776059.492829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.508495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.524136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.539741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776059.555342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.570972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.586578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.602218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776059.617842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.633531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.649103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776060.664743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.680342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.695972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.711589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776060.727229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.742839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.758458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.774090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776060.789721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.805414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.821045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776061.836596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.852255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.867873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.883471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776061.899093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.914713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.930989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.945978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776061.961651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776062.977242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776062.992895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776063.008467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776063.024186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776063.039783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776063.055359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776063.070960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776063.086596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776063.102209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776063.117844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776063.133488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.149156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.164739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776064.180351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.195976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.211588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.227230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776064.242834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.258470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.274085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.289719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776064.305335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.321050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.336629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776065.352238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.367884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.383507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.399068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776065.414773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.430355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.445985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.461794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776065.477224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.492884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.508479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776066.524119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.539709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.555351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.570961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776066.586594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.602217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.617831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.633493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776066.649599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.667167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.680416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776067.695997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.711590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.727229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.742835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776067.758470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.774090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.789713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.805332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776067.820956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.836785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.852210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776068.867840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.883453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.899224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.914718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776068.930353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.946070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.961694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.977302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776068.992836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.008530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.024139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776070.039778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.055345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.070957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.086614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776070.102205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.117850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.133482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.149073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776070.164723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.180366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.195975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776071.211588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.227226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.242829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.258460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776071.274089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.289721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.305337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.320969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776071.336610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.352241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.368008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776072.383470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.399084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.414730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.430370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776072.445969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.461818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.477227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.492846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776072.508468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.524156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.539729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776073.555374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.570972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.586639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.602221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776073.617851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.633488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.649088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.664733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776073.680332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.696035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.711593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776074.727225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.742842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.758465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.774073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776074.789737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.805670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.820972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.836606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776074.852230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776075.867869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776075.883472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776075.899087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776075.914722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776075.930354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776075.945945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776075.961592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776075.977203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776075.992915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776076.008449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776076.024104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.039874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.055342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776077.070964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.086588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.102208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.117833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776077.133471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.149076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.164725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.180327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776077.195957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.211666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.227253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776078.242849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.258462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.274092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.289726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776078.305332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.320961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.336596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.352206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776078.367837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.383484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.399100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776079.414756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.430360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.445987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.461787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776079.477219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.492823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.508456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.524084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776079.539770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.555386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.570972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776080.586583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.602205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.617824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.633484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776080.649085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.664722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.680329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.695967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776080.711578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.727245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.742845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776081.758464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.774093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.789710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.805343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776081.820966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.836602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.852198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.867827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776081.883456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776082.899117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776082.914716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776082.930354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776082.945967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776082.961585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776082.977194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776082.992820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776083.008462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776083.024127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776083.039751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776083.055325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.071002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.086667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776084.102216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.117859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.133477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.149076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776084.164721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.180329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.195959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.211574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776084.227210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.242849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.258458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776085.274079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.289730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.305335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.320958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776085.336604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.352205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.367834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.383454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776085.399083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.414771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.430359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776086.445963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.461810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.477207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.492841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776086.508447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.524079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.539739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.555331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776086.570957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.586600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.602204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776087.617822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.633460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.649088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.664722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776087.687640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.695952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.711570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.727199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776087.742837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.758495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.774069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776088.789753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.805332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.820946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.836604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776088.852206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.867828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.883437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.899067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776088.914721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776089.930786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776089.945970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776089.961601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776089.977210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776089.992829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776090.008471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776090.024107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776090.039767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776090.055330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776090.070951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776090.086603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.102368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.117874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776091.133472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.149190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.164725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.187680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776091.195964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.211578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.227194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.242835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776091.258450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.274115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.289736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776092.305328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.320956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.336596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.352219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776092.367814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.383450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.399091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.414703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776092.430331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.445984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.461786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776093.477204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.492835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.508464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.524077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776093.539727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.555318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.570949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.586590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776093.602193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.617921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.633485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776094.649092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.664839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.688001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.695967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776094.711594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.727206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.742841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.758452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776094.774152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.789804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.805326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776095.820987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.836600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.852212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.867822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776095.883449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.899097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.914712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.930331 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776095.945966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776096.961601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776096.977200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776096.992825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776097.008457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776097.024144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776097.039772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776097.055450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776097.070950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776097.086642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776097.102217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776097.117882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.133517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.149089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776098.164730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.187716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.195957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.211584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776098.227202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.242859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.258459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.274074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776098.289729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.305365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.320954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776099.336597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.352200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.367824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.383463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776099.399081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.414723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.430323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.445956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776099.461802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.477246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.492824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776100.508459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.524087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.539740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.555327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776100.570956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.586571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.602204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.617827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776100.633456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.649105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.664738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776101.687695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.695977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.711588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.727200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776101.742868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.758452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.774066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.789735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776101.805458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.820984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.836601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776102.852215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.867832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.883469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.899133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776102.914701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.930340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.945978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.961578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776102.977202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776103.992864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776104.008456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776104.024097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776104.039749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776104.055349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776104.070952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776104.086634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776104.102203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776104.117828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776104.133451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776104.149089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.164817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.180346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776105.195968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.211581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.227203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.242841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776105.258455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.274092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.289710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.305324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776105.320947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.336656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.352212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776106.367839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.383454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.399075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.414713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776106.430319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.445971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.461798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.477208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776106.492830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.508517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.524103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776107.539733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.555335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.570953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.586580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776107.602207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.617828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.633472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.649102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776107.664728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.680375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.695961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776108.711590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.727211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.742848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.758450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776108.774075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.789713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.805329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.820950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776108.836587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776109.852273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776109.867827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776109.883448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776109.899069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776109.914712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776109.930766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776109.945973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776109.961580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776109.977207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776109.992821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776110.008459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.024131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.039745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776111.055328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.070950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.086576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.102186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776111.117823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.133467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.149088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.164712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776111.180315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.196040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.211590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776112.227203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.242843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.258534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.274072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776112.289710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.305319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.320944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.336570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776112.352208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.367860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.383462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776113.399073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.414728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.430324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.445971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776113.461774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.477204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.492820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.508442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776113.524083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.539792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.555346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776114.570952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.586581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.602211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.617833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776114.633449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.649089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.664720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.680324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776114.695955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.711623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.727221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776115.742860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.758451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.774085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.789720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776115.805334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.820940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.836569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.852222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776115.867820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776116.883544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776116.899077 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776116.914715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776116.930340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776116.945974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776116.961575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776116.977190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776116.992816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776117.008471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776117.024116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776117.039732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.055403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.070960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776118.086598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.102190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.117836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.133449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776118.149082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.164723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.180317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.195950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776118.211567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.227257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.242859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776119.258451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.274071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.289975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.305335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776119.320948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.336640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.352230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.367820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776119.383447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.399142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.414773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776120.430325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.445964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.461789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.477179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776120.492819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.508443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.524075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.539791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776120.555338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.571069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.586654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776121.604839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.617896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.633690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.649223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776121.664737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.680345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.695972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.711736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776121.727191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.743173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.758686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776122.774833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.789918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.805766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.821200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776122.836655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.852273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.867974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.883605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776122.899211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776123.914909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776123.930417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776123.946045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776123.961671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776123.977442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776123.993289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776124.008589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776124.024290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776124.039904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776124.055361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776124.070965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.086896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.102280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776125.117911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.133520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.149087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.164795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776125.180313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.195940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.211564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.227189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776125.242815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.258473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.274068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776126.289780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.305317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.320942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.336647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776126.352204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.367811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.383439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.399071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776126.414708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.430399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.445965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776127.461797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.477195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.492820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.508493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776127.524069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.539756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.555330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.570941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776127.586559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.602272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.617830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776128.633447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.649101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.664727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.680313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776128.695936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.711560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.727188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.742837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776128.758459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.774112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.789772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776129.805318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.820949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.836564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.852209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776129.867819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.883446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.899056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.914675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776129.930312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776130.946128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776130.961659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776130.977195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776130.992832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776131.008450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776131.024084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776131.039770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776131.055323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776131.070933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776131.086566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776131.102189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.117934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.133455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776132.149086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.164713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.180327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.195941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776132.211568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.227190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.242902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.258465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776132.274079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.289862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.305411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776133.320960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.336579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.352206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.367825 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776133.383444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.399073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.414695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.430323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776133.446022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.461854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.477246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776134.492842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.508462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.524247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.539762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776134.555343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.570946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.586567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.602190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776134.617826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.633537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.649088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776135.664712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.680335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.695958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.711579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776135.727196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.742837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.758456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.774070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776135.789728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.805381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.820949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776136.836575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.852212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.867822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.883438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776136.899059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.914690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.930341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.946013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776136.961582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776137.977268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776137.992832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776138.008471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776138.024096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776138.039751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776138.055338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776138.070963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776138.086578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776138.102211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776138.117828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776138.133468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.149098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.164785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776139.180311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.195985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.211563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.227187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776139.242811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.258458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.274071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.289709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776139.305315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.321036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.336583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776140.352219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.367812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.383460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.399063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776140.414702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.430317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.446095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.461798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776140.477203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.492895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.508452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776141.524085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.539719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.555341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.570947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776141.586580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.602188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.617807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.633444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.649149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776141.664745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776141.680326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776141.695949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776141.711599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776141.727200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776142.742896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776142.758456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776142.774071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776142.789697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776142.805454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776142.821083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776142.836649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776142.852400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776142.867860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776142.883493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776142.899071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776143.914730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776143.930321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776143.946019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776143.961595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776143.977197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776143.993019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776144.008449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776144.024090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776144.039726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776144.055316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776144.070957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.086626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.102192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776145.117828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.133456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.149167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.164710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776145.180335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.195933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.211576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.227181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776145.242805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.258491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.274075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776146.289697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.305310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.320941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.336566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776146.352252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.367827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.383431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.399055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776146.414711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.430353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.446038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776147.461792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.477189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.492835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.508451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776147.524075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.539667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.555311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.570951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776147.586564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.602231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.617821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776148.633456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.649158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.664741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.680312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776148.695942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.711558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.727186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.742826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776148.758546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.774269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.789750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776149.805323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.820956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.836578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.852284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776149.867838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.883449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.899082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.914697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776149.930316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776150.946066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776150.961593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776150.977177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776150.992821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776151.008450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776151.024088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776151.039708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776151.055314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776151.070960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776151.086575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776151.102183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.117942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.133438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776152.149132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.164717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.180322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.195934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776152.211560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.227179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.242812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.258431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776152.274069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.289730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.305323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776153.320939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.336568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.352271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.367821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776153.383429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.399040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.414716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.430323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776153.445944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.461896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.477239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776154.492842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.508448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.524219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.539690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776154.555565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.570969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.586788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.602195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776154.617817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.633509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.649153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776155.664733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.680325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.695959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.711562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776155.727194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.742817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.758440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.774091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776155.789707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.805356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.820957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776156.836565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.852282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.867844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.883448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776156.899065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.914754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.930317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.945936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776156.961569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776157.977232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776157.992815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776158.008546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776158.024093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776158.039701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776158.055315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776158.070947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776158.086564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776158.102175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776158.117804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776158.133440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.149238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.164723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776159.180312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.195944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.211560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.227203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776159.242818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.258437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.274082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.289683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776159.305299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.320989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.336573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776160.352261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.367822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.383427 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.399060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776160.414703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.430312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.445983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.461791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776160.477189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.493025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.508570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776161.524113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.539745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.555382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.570948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776161.586557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.602178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.617805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.633425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776161.649056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.664785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.680315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776162.695938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.711553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.727180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.742813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776162.758429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.774074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.789671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.805302 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776162.820922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.836593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.852254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776163.867817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.883434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.899047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.914670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776163.930297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.945924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.961555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.977194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776163.992796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.008544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.024093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776165.039704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.055299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.070934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.086551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776165.102177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.117804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.133429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.149153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776165.164717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.180398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.195939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776166.211555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.227190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.242819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.258434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776166.274071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.289682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.305308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.320948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.336569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776166.352202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776166.367819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776166.383474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776166.399070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776166.414722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776167.430340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776167.445943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776167.461762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776167.477192 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776167.492800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776167.508444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776167.524060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776167.539680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776167.555298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776167.570929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776167.586566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.602217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.617804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776168.633435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.649055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.664712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.680316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776168.695939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.711551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.727172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.742800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776168.758426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.774126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.789699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776169.805323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.820963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.836574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.852191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776169.867811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.883454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.899058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.914691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776169.930317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776170.945968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776170.961613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776170.977193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776170.992823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776171.008452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776171.024088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776171.039708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776171.055306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776171.070934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776171.086567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776171.102175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.117869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.133440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776172.149059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.164713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.180374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.195923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776172.211568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.227170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.242805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.258426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776172.274049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.289708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.305308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776173.320934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.336567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.352184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.367801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776173.383447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.399063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.414708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.430311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776173.445949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.461779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.477210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776174.492822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.508463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.524238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.539689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776174.555317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.570952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.586598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.602196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776174.617821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.633522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.649062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776175.664713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.680353 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.695934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.711574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776175.727189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.742800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.758424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.774058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776175.789700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.805348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.820947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776176.836570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.852196 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.867810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.883456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776176.899054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.914671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.930326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.945936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776176.961569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776177.977240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776177.992806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776178.008444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776178.024091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776178.039696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776178.055308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776178.070931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776178.086608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776178.102168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776178.117803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776178.133434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.149100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.164918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776179.180341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.195968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.211562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.227182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776179.242806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.258434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.274064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.289688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776179.305305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.321006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.336570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776180.352182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.367810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.383450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.399048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776180.414675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.430301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.445934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.461817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776180.477180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.492903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.508442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776181.524059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.539691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.555321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.570932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776181.586574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.602173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.617812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.633424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776181.649052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.664748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.680340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776182.695935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.711540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.727187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.742826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776182.758433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.774038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.789702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.805303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776182.820930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.836580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.852181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776183.867813 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.883449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.899059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.914674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776183.930296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.945930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.961570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.977173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776183.992815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.008461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.024075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776185.039701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.055317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.070931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.086574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776185.102186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.117794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.133425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.149045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776185.164688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.180350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.195932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776186.211565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.227176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.242798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.258426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776186.274048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.289687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.305311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.320930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776186.336552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.352215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.367808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776187.383446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.399065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.414699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.430305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776187.445937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.461752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.477155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.492812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776187.508431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.570960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.586583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776188.602186 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.617809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.633420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.649052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776188.664693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.680316 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.695943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.711564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776188.727170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.742855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.758431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776189.774062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.789690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.805296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.820919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776189.836558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.852201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.867795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.883412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776189.899059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776190.914772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776190.930326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776190.945931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776190.961570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776190.977174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776190.992819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776191.008425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776191.024073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776191.039693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776191.055296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776191.070925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.086669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.102182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776192.117819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.133430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.149064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.164702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776192.180327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.195947 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.211553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.227191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776192.242809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.258462 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.274049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776193.289686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.305297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.320924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.336562 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776193.352176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.367794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.383438 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.399065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776193.414697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.430340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.445932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776194.461777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.477194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.492841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.508431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776194.524115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.539673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.555306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.570936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776194.586571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.602244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.617819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776195.633434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.649056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.664713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.680312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776195.695941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.711543 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.727173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.742795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776195.758417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.774081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.789694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776196.805299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.820930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.836554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.852171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776196.867789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.883421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.899065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.914686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776196.930293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776197.945999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776197.961564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776197.977181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776197.992839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776198.008435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776198.024069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776198.039702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776198.055298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776198.070920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776198.086554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776198.102209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.117924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.133442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776199.149067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.164702 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.180305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.195935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776199.211547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.227168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.242816 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.258426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776199.274058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.289780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.305312 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776200.320932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.336547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.352178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.367795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776200.383424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.399047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.414692 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.430297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776200.445922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.461896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.477200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776201.493030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.508436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.524058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.539682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776201.555313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.570930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.586558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.602191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776201.617807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.633468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.649056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776202.664696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.680309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.695940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.711617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776202.727172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.742818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.758431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.774050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776202.789675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.805343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.820931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776203.836559 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.852176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.867801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.883427 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776203.899059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.914680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.930317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.945923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776203.961552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776204.977217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776204.992808 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776205.008437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776205.024079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776205.039695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776205.055325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776205.070921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776205.086561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776205.102183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776205.117807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776205.133414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.149081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.164695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776206.180313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.195952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.211547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.227176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776206.242802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.258423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.274040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.289674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776206.305307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.321014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.336560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776207.352174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.367802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.383439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.399063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776207.414698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.430298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.445919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.461774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776207.477173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.492865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.508477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776208.524051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.539676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.555298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.570924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776208.586551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.602176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.617791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.633415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776208.649044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.664927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.680336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776209.695950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.711556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.727202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.742919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776209.758550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.774091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.790502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.805721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776209.820926 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.836613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.852189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776210.867832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.883431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.899205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.914676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776210.930409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.945939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.961652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.977178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776210.992812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.008593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.024333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776212.039820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.055364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.070937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.086630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776212.102207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.117991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.133439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.149048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.164709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776212.180314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776212.196062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776212.211656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776212.227205 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776212.242815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776213.258498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776213.274085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776213.289673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776213.305333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776213.320934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776213.336587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776213.352609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776213.367879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776213.383645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776213.399041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776213.414701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.430358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.446039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776214.461922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.477188 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.492834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.508529 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776214.524249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.539683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.555311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.570941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776214.586555 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.602317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.617802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776215.633420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.649055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.664717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.680342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776215.695920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.711574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.727168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.742791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776215.758433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.774049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.789678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776216.805493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.820944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.836561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.852179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776216.867867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.883427 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.899061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.914784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776216.930326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776217.945992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776217.961604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776217.977181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776217.992797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776218.008448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776218.024062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776218.039709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776218.055288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776218.070915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776218.086560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776218.102169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.117848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.133433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776219.149058 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.164691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.180299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.195956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776219.211566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.227164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.242799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.258414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776219.274050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.289744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.305324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776220.320920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.336550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.352160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.367787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776220.383425 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.399047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.414693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.430293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776220.445917 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.461849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.477173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776221.492809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.508442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.524057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.539665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776221.555292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.570918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.586571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.602177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776221.617809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.633454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.649052 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776222.664688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.680300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.695920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.711571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776222.727173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.742795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.758424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.774043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776222.789671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.805320 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.820922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776223.836551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.852165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.867792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.883430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776223.899043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.914679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.930296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.945920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776223.961554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776224.977262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776224.992793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776225.008446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776225.024071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776225.039683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776225.055274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776225.070912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776225.086558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776225.102164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776225.117802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776225.133411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.149060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.164688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776226.180310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.195923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.211585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.227183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776226.242801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.258419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.274049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.289670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776226.305294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.320954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.336568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776227.352200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.367801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.383483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.399061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776227.414685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.430294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.445920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.461749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776227.477167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.492851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.508443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776228.524054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.539691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.555297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.570933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776228.586546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.602185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.617809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.633417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776228.649071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.664736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.680324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776229.695952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.711565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.727164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.742783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776229.758434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.774054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.789687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.805290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776229.820932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.836604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.852172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776230.867805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.883433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.899066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.914694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776230.930721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.945933 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.961550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.977176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776230.992811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.008496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.024070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776232.039693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.055290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.070915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.086621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776232.102171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.117806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.133422 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.149049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776232.164679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.180321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.195932 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776233.211556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.227167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.242809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.258420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776233.274042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.289678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.305294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.320935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776233.336547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.352190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.367949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776234.383468 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.399061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.414688 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.430284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776234.445914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.461759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.477156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.492770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776234.508410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.524105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.539724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776235.555365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.570916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.586538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.602213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776235.617869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.633472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.649102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.664683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776235.680346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.695948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.711563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776236.727176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.742797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.758433 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.774026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776236.789661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.805281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.820922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.836536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776236.852157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776237.867821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776237.883417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776237.899059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776237.914732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776237.930287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776237.945971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776237.961590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776237.977204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776237.992840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776238.008423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776238.024087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.039821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.055304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776239.070952 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.086557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.102174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.117822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776239.133424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.149076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.164760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.180305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776239.195923 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.211604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.227176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776240.242788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.258410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.274041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.289655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776240.305284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.320919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.336533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.352156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776240.367805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.383548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.399146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776241.414774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.430370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.445922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.461777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776241.477167 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.492789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.508420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.524056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776241.539663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.555355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.570965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776242.586537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.602162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.617803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.633405 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776242.649038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.664678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.680289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.695901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776242.711527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.727431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.742791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776243.758479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.774044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.789669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.805424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776243.820943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.836600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.852237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.867849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776243.883499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776244.899144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776244.914689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776244.930305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776244.945916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776244.961552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776244.977163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776244.992784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776245.008426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776245.024082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776245.039681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776245.055292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.070959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.086552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776246.102178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.117814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.133413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.149050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776246.164682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.187540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.196049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.211552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776246.227178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.242811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.258426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776247.274040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.289667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.305293 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.320936 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776247.336537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.352164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.367784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.383408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776247.399046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.414762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.430290 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776248.445909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.461773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.477162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.493031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776248.508413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.524054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.539667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.555327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776248.570915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.586625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.602177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776249.617815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.633412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.649051 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.664681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776249.688356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.695919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.711554 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.727175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776249.742795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.758502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.774086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776250.789662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.805287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.820948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.836536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776250.852151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.867789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.883416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.899063 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776250.914670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776251.930328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776251.945914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776251.961539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776251.977162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776251.992787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776252.008419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776252.024080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776252.039680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776252.055286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776252.070911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776252.086585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.102210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.117805 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776253.133420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.149065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.164687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.187851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776253.195907 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.211545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.227175 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.242797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776253.258419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.274073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.289671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776254.305294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.320946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.336542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.352176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776254.367795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.383419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.399049 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.414684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776254.430381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.445980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.461771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776255.477168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.492795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.508429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.524066 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776255.539705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.555298 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.570934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.586538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776255.602160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.617913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.633424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776256.649071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.664735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.687581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.696062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776256.711541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.727173 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.742798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.758410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776256.774043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.789697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.805301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776257.821099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.836569 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.852145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.867774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776257.883407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.899039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.914647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.930371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776257.945911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776258.961659 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776258.977306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776258.993299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776259.008583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776259.024226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776259.039680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776259.055417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776259.071104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776259.086732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776259.102169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776259.117798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.133527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.149075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776260.164693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.187650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.195918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.211546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776260.227162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.242787 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.258421 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.274029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776260.289657 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.305364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.320939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776261.336535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.352162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.367776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.383429 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776261.399036 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.414692 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.430310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.445901 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776261.461756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.477185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.492792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776262.508430 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.524057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.539655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.555287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776262.570905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.586541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.602146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.617774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776262.633423 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.649088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.664697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776263.688010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.695946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.711541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.727180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776263.742778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.758418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.774024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.789652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776263.805281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.820956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.836530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776264.852160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.867785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.883412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.899056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776264.914662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.930727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.945906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.961547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776264.977152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776265.992834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776266.008419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776266.024070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776266.039678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776266.055276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776266.070900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776266.086530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776266.102162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776266.117809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776266.133415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776266.149053 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.164727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.180294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776267.195918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.211540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.227168 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.242781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776267.258399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.274025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.289647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.305274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776267.320927 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.336612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.352169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776268.367783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.383410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.399060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.414693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776268.430294 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.445920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.461755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.477156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776268.492789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.508495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.524055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776269.539691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.555306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.570909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.586536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776269.602151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.617769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.633431 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.649046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776269.664676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.680371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.695920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776270.711544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.727195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.742791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.758439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776270.774202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.789673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.805300 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.820906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776270.836558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776271.852347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776271.867793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776271.883404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776271.899050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776271.914648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776271.930296 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776271.945905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776271.961524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776271.977166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776271.992767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776272.008399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.024099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.039664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776273.055299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.070899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.086533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.102149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776273.117788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.133406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.149035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.164665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776273.180280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.195924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.211534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776274.227165 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.242770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.258407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.274023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776274.289655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.305295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.320902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.336532 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776274.352139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.367859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.383434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776275.399045 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.414689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.430303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.445918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776275.461790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.477157 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.492792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.508417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776275.524041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.539681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.555299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776276.570929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.586530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.602257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.617856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776276.633497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.649136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.664756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.680291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776276.695913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.711575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.727184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776277.742781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.758404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.774032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.789653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776277.805278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.820912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.836544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.852155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776277.867783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776278.883473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776278.899141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776278.914661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776278.930412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776278.945913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776278.961654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776278.977166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776278.992784 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776279.008401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776279.024044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776279.039666 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.055340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.071308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776280.086578 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.102150 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.117778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.133428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776280.149112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.164783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.180273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.195894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776280.211517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.227288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.242777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776281.258402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.274014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.289683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.305287 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776281.320919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.336545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.352159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.367777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776281.383410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.399149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.414679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776282.430297 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.445909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.461749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.477155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776282.492793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.508401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.524040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.539669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776282.555282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.570949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.586535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776283.602160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.617788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.633426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.649225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776283.664676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.680389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.696046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.711531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776283.727159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.742856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.758441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776284.774065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.789662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.805275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.820906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776284.836552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.852153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.867778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.883530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776284.899099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776285.914744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776285.930305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776285.945919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776285.961549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776285.977151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776285.992975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776286.008415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776286.024060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776286.039684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776286.055280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776286.070911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.086573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.102170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776287.117797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.133416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.149085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.164678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776287.180270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.195910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.211521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.227145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776287.242793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.258441 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.274026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776288.289653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.305281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.320912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.336541 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776288.352154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.367976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.383402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.399085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776288.414675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.430321 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.445913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776289.461737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.477156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.492992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.508406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776289.524037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.539679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.555303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.570903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776289.586521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.602242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.617786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776290.633420 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.649056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.664699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.680275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776290.695895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.711518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.727155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.742796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776290.758402 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.774121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.789747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776291.805286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.820972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.836549 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.852219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776291.867769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.883463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.899067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.914647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776291.930282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776292.945954 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776292.961548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776292.977160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776292.992771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776293.008401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776293.024050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776293.039682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776293.055270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776293.070898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776293.086526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776293.102141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.117836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.133416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776294.149059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.164687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.180278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.195900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776294.211528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.227145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.242785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.258399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776294.274038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.289768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.305291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776295.320898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.336533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.352142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.367772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776295.383384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.399048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.414777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.430362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776295.445938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.461995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.477383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776296.493260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.508544 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.524128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.539705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776296.555383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.570919 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.586691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.602239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776296.617768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.633475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.649046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776297.664680 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.680274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.695895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.711521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776297.727142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.742781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.758392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.774023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776297.789640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.805332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.820957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776298.836553 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.852151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.867779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.883478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776298.899030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.914640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.930280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.945915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776298.961619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776299.977203 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776299.992781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776300.008404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776300.024046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776300.039675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776300.055273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776300.070890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776300.086588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776300.102145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776300.117791 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776300.133551 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.149093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.164675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776301.180306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.195904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.211527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.227151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776301.242786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.258394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.274017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.289630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776301.305269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.321014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.336983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776302.352274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.367836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.383572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.399043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776302.414684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.430424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.445930 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.461929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776302.477159 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.492857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.508409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776303.524120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.539841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.555480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.570900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776303.586527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.602237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.617853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.633506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776303.649090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.664719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.680357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776304.696083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.711635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.727334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.742803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776304.758393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.773997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.789640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.805266 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776304.820903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.836595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.852145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776305.867769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.883398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.899029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.914643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776305.930276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.945910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.961523 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.977140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776305.992794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.008435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.024046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776307.039665 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.055271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.070929 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.086533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776307.102152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.117781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.133394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.149034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776307.164673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.180495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.195903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776308.211540 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.227160 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.242821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.258407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776308.274033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.289677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.305274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.320912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776308.336547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.352276 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.367991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776309.383412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.399025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.414686 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.430263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776309.445918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.461798 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.477143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.492777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776309.508412 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.524085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.539667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776310.555289 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.570897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.586521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.602158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776310.617768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.633401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.649031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.664670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776310.680269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.695955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.711535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776311.727151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.742790 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.758403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.774022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776311.789651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.805281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.820912 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.836527 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776311.852152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776312.867853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776312.883418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776312.899073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776312.914696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776312.930470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776312.946022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776312.961622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776312.977149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776312.992783 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776313.008472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776313.024148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.039713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.055281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776314.070899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.086534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.102204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.117792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776314.133397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.149029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.164841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.180273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776314.195910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.211568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.227152 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776315.242801 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.258409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.274041 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.289650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776315.305280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.320897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.336513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.352164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776315.367785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.383450 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.399043 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776316.414678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.430280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.445914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.461793 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776316.477156 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.493008 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.508391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.524038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776316.539643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.555327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.570900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776317.586528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.602138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.617774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.633406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776317.649050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.664679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.680270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.695899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776317.711528 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.727212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.742792 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776318.758408 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.774015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.789650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.805269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776318.820894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.836518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.852155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.867765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776318.883394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776319.899064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776319.914658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776319.930272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776319.945911 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776319.961534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776319.977142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776319.992762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776320.008388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776320.024023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776320.039799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776320.055388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.070951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.086538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776321.102140 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.117776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.133403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.149040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776321.164667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.180269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.195902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.211519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776321.227137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.242831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.258397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776322.274024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.289648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.305263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.320887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776322.336513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.352182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.367757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.383382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776322.399006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.414683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.430277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776323.445924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.461712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.477149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.492776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776323.508388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.524019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.539639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.555299 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776323.570987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.586545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.602147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776324.617859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.633385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.649033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.664652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776324.680271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.695879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.711502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.727143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776324.742763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.758404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.774012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776325.789642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.805246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.820899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.836516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776325.852146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.867769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.883382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.899003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776325.914647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776326.930288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776326.945900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776326.961517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776326.977134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776326.992753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776327.008397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776327.024040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776327.039660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776327.055279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776327.070885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776327.086514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.102180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.117774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776328.133409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.149032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.164639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.180280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776328.195875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.211503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.227131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.242757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776328.258396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.274055 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.289650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776329.305269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.320890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.336531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.352207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776329.367758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.383400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.399018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.414694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776329.430256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.446013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.461763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776330.477113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.492766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.508381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.524015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776330.539638 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.555273 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.570881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.586505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776330.602141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.617898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.633502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776331.649054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.664779 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.680272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.695904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776331.711519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.727153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.742773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.758416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776331.774015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.789802 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.805355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776332.820968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.836519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.852204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.867804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776332.883414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.899013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.914630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.930530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776332.946011 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776333.961545 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776333.977135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776333.992751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776334.008386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776334.024027 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776334.039645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776334.055269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776334.070888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776334.086520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776334.102142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776334.117762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.133498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.149047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776335.164670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.180281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.195895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.211517 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776335.227155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.242771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.258403 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.274031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776335.289634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.305306 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.320894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776336.336515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.352148 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.367760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.383395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776336.399013 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.414670 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.430256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.445956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776336.461736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.477176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.492772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776337.508397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.524025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.539653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.555280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776337.570891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.586515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.602130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.617763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776337.633401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.649130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.664676 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776338.680291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.695892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.711506 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.727132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776338.742770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.758409 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.774017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.789632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776338.805256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.820942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.836524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776339.852154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.867772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.883387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.899019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776339.914642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.930750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.945957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.961548 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776339.977172 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776340.992879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776341.008401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776341.024047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776341.039667 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776341.055274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776341.070898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776341.086520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776341.102151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776341.117770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776341.133389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776341.149102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.164735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.180282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776342.195889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.211522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.227138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.242757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776342.258395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.274032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.289637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.305323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776342.320883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.336550 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.352162 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776343.367768 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.383389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.399012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.414645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776343.430253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.445972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.461760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.477134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776343.492769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.508471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.524035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776344.539640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.555280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.570896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.586552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776344.602142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.617778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.633385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.649080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776344.664673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.680291 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.695884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776345.711509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.727129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.742755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.758397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776345.774025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.789637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.805281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.820883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776345.836522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776346.852177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776346.867772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776346.883383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776346.899010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776346.914632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776346.930253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776346.945953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776346.961524 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776346.977144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776346.992751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776347.008382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.024074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.039654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776348.055271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.070896 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.086581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.102133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776348.117771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.133415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.149081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.164658 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776348.187750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.195920 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.211522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776349.227153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.242774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.258417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.274110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776349.289628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.305281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.320887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.336514 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776349.352217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.367796 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.383388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776350.399004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.414649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.430270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.445963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776350.461742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.477142 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.492853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.508390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776350.524015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.539819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.555309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776351.570895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.586516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.602147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.617758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776351.633384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.649080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.664664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.680260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776351.695883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.711547 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.727149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776352.742822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.758410 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.773995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.789631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776352.805258 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.820879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.836505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.852202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776352.867767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776353.883418 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776353.899023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776353.914641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776353.930270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776353.945961 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776353.961536 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776353.977126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776353.992753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776354.008396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776354.024025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776354.039654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.055333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.070885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776355.086526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.102132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.117757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.133391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776355.149073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.164652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.180263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.195895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776355.211500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.227183 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.242776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776356.258415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.274019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.289626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.305250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776356.320883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.336518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.352197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.367780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776356.383375 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.399048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.414643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776357.430740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.445974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.461737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.477136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776357.492757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.508395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.524018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.539635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776357.555257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.570934 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.586556 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776358.602166 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.617763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.633502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.649083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776358.664660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.680260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.695879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.711502 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776358.727123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.742837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.758426 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776359.775187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.789633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.805275 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.820890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776359.836520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.852232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.867775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.883400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776359.899009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776360.914678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776360.930278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776360.945967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776360.961537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776360.977130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776360.992777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776361.008394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776361.024030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776361.039648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776361.055259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776361.070898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.086567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.102138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776362.117774 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.133391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.149074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.164651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776362.180252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.195876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.211496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.227121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776362.242742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.258434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.274017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776363.289633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.305252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.320893 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.336504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776363.352191 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.367766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.383377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.399000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776363.414634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.430406 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.446065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776364.462056 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.477374 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.493399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.508488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776364.524239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.539850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.555563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.571135 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776364.586788 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.602154 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.617757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776365.633384 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.649080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.664689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.680251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776365.695876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.711501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.727129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.742745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776365.758373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.774131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.789642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776366.805373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.820889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.836512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.852199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776366.867766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.883373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.898993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.914619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776366.930248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776367.946113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776367.961537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776367.977158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776367.992770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776368.008386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776368.024050 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776368.039656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776368.055260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776368.070914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776368.086590 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776368.102127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.117862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.133400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776369.149101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.164678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.180263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.195888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776369.211498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.227123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.242755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.258387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776369.274026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.289789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.305256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776370.320873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.336505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.352303 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.367778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776370.383376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.399006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.414643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.430254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776370.445887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.461777 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.477145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776371.492759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.508385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.524018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.539619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776371.555256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.570892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.586496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.602120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776371.617757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.633444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.649092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776372.664668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.680272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.695880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.711499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776372.727130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.742751 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.758380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.774003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776372.789629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.805397 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.820892 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776373.836509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.852200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.867764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.883371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776373.899001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.914627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.930822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.945877 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776373.961505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776374.977234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776374.992769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776375.008391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776375.024028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776375.039664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776375.055262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776375.070895 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776375.086504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776375.102126 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776375.117750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776375.133381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.149229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.164690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776376.180264 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.195885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.211512 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.227181 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776376.242767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.258387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.274021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.289641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776376.305255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.320945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.336510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776377.352208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.367771 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.383378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.399012 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776377.414651 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.430244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.445867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.461714 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776377.477145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.492858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.508381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776378.524003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.539618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.555248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.570887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776378.586490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.602180 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.617797 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.633381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776378.649006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.664855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.680251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776379.695900 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.711516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.727136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.742754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776379.758373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.774006 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.789637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.805249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776379.820876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.836558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.852233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776380.867772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.883391 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.899001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.914635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776380.930269 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.945887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.961509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.977147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776380.992772 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.008432 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.024035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776382.039644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.055260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.070894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.086510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776382.102128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.117759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.133367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.148991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776382.164645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.180288 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.195878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776383.211515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.227128 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.242764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.258368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776383.274023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.289616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.305246 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.320888 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776383.336497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.352238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.367770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776384.383372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.399003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.414653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.430256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776384.445866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.461719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.477134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.492765 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776384.508373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.524031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.539623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776385.555260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.570889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.586500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.602115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776385.617742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.633365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.648991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.664646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776385.680260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.695897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.711501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776386.727132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.742755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.758355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.774131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776386.789611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.805243 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.820956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.836546 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776386.852131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776387.867935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776387.883385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776387.899018 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776387.914628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776387.930254 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776387.945878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776387.961505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776387.977132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776387.992756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776388.008389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776388.024025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.039698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.055286 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776389.070898 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.086509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.102121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.117754 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776389.133378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.149037 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.164695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.180280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776389.195873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.211574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.227163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776390.242789 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.258444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.274076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.289661 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776390.305252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.320865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.336486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.352117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776390.367748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.383537 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.399024 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776391.414886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.430259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.445953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.461767 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776391.477268 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.492881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.508396 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.525681 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776391.539650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.555280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.570904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776392.586564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.602125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.617776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.633378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776392.649028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.664711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.680279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.695894 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776392.711621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.727301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.742827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776393.758471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.774143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.789701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.805277 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776393.820909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.836611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.852199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.867820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776393.883472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776394.899060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776394.914785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776394.930253 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776394.945925 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776394.961694 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776394.977139 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776394.992746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776395.008385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776395.024015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776395.039632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776395.055239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.071047 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.086653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776396.102133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.117749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.133379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.148993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776396.164684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.180281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.195865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.211496 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776396.227114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.242800 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.258389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776397.274062 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.289621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.305248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.320881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776397.336490 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.352119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.367743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.383417 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776397.398991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.414677 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.430267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776398.445885 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.461722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.477158 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.492755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776398.508389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.524176 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.539693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.555279 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776398.570905 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.586627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.602146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776399.617758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.633381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.649016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.664656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776399.680284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.696009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.711492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.727123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776399.742755 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.758445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.774034 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776400.789639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.805367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.820884 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.836497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776400.852132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.867753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.883392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.899005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776400.914625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776401.930301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776401.945887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776401.961511 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776401.977153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776401.992746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776402.008389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776402.024022 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776402.039647 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776402.055278 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776402.070879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776402.086530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.102263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.117759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776403.133472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.149003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.164646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.180261 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776403.195864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.211486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.227107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.242734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776403.258382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.274044 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.289622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776404.305249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.320875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.336520 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.352115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776404.367749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.383389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.398994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.414636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776404.430251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.445910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.461699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776405.477134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.492748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.508383 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.523997 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776405.539620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.555244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.570873 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.586505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776405.602120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.617812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.633371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776406.649014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.664646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.680272 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.696015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776406.711510 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.727121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.742756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.758385 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776406.774000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.789645 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.805242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776407.820878 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.836494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.852130 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.867739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776407.883381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.898992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.914609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.930242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776407.945870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776408.961535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776408.977144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776408.992742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776409.008386 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776409.024010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776409.039628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776409.055234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776409.070866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776409.086522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776409.102116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776409.117742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.133445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.149002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776410.164640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.180251 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.195867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.211479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776410.227117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.242737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.258376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.273985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776410.289646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.305362 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.320874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776411.336497 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.352123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.367757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.383398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776411.398994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.414643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.430238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.445866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776411.461725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.477178 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.492748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776412.508428 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.524057 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.539622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.555233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776412.570866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.586501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.602107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.617733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776412.633373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.649119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.664673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776413.680280 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.695904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.711488 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.727116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776413.742812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.758379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.773998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.789625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776413.805238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.820942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.836501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776414.852134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.867747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.883393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.898985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776414.914608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.930240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.945862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.961489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776414.977111 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776415.992776 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776416.008389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776416.024017 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776416.039633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776416.055244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776416.070872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776416.086574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776416.102122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776416.117749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776416.133378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776416.148992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.164669 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.180271 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776417.195870 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.211498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.227121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.242748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776417.258377 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.273985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.289639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.305231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776417.320876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.336513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.352115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776418.367750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.383381 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.398991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.414631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776418.430248 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.445861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.461678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.477110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776418.492760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.508503 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.524032 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776419.539655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.555238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.570865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.586494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776419.602122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.617760 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.633358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.648976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776419.664631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.680486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.695872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776420.711655 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.727112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.742922 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.758380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776420.773989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.789639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.805257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.820874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776420.836498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776421.852169 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776421.867752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776421.883388 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776421.898982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776421.914613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776421.930237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776421.945861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776421.961489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776421.977104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776421.992745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776422.008370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.024033 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.039630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776423.055270 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.070876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.086505 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.102119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776423.117732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.133352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.148980 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.164630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776423.187614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.195890 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.211500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776424.227115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.242758 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.258379 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.273992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776424.289632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.305245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.320871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.336499 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776424.352107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.367778 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.383392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776425.399000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.414641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.430234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.445865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776425.461689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.477137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.492741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.508371 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776425.523998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.539697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.555260 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776426.570856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.586495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.602113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.617744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776426.633354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.648993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.664635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.687909 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776426.695889 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.711566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.727122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776427.742748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.758387 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.773993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.789631 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776427.805235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.820871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.836484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.852122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776427.867738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776428.883400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776428.898987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776428.914614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776428.930233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776428.945868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776428.961492 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776428.977108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776428.992745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776429.008372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776429.024002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776429.039621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.055334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.070882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776430.086533 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.102575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.117744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.133363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776430.149007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.164654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.187838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.195891 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776430.211494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.227170 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.242750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776431.258370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.273987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.289642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.305231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776431.320867 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.336479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.352110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.367730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776431.383359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.399028 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.414646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776432.430245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.445872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.461697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.477127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776432.492745 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.508454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.523990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.539606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776432.555239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.570906 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.586504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776433.602122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.617731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.633359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.648985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776433.664632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.687625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.695903 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.711495 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776433.727112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.742799 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.758465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776434.773988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.789640 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.805242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.820887 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776434.836561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.852137 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.867756 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.883370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776434.899007 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776435.914683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776435.930250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776435.945956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776435.961557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776435.977221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776435.992766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776436.008531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776436.024123 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776436.039639 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776436.055235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776436.070869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.086567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.102129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776437.117744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.133359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.148992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.164636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776437.180247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.195879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.211489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.227121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776437.242740 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.258483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.273996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776438.289634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.305239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.320864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.336486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776438.352114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.367730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.383368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.399010 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776438.414641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.430282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.446004 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776439.461747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.477122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.492752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.508435 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776439.523987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.539620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.555230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.570855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776439.586535 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.602262 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.617803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776440.633538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.648978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.664663 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.680240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776440.695876 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.711486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.727110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.742744 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776440.758442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.774214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.789641 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776441.805226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.820862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.836474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.852114 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776441.867733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.883365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.898989 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.914600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776441.930235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776442.945924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776442.961493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776442.977106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776442.992763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776443.008414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776443.024003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776443.039617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776443.055229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776443.070856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776443.086483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776443.102121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.117770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.133360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776444.148976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.164643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.180232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.195865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776444.211471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.227102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.242731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.258414 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776444.273981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.289653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.305242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776445.320859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.336473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.352103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.367728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776445.383349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.398995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.414621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.430227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776445.445854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.461696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.477112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776446.492743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.508411 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.523994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.539605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776446.555225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.570858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.586471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.602112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776446.617713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.633378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.648978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776447.664622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.680234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.695868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.711476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776447.727098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.742724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.758399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.773973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776447.789599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.805398 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.820859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776448.836476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.852106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.867736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.883358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776448.899016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.914605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.930223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.945862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776448.961487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776449.977179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776449.992757 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776450.008401 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776450.024003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776450.039621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776450.055230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776450.070849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776450.086483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776450.102125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776450.117731 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776450.133347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.149061 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.164652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776451.180240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.195875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.211504 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.227104 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776451.242743 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.258395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.273983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.289606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776451.305240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.320918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.336500 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776452.352113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.367749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.383360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.399014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776452.414634 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.430235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.445859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.461866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776452.477107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.492769 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.508399 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776453.524003 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.539620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.555241 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.570858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776453.586479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.602121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.617736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.633357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776453.648981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.664826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.680256 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776454.695914 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.711531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.727122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.742773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776454.758390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.774080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.789679 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.805475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776454.820937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.836501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.852119 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776455.867736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.883446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.899001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.914610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776455.930259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.945864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.961487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.977098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776455.992742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.008395 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.024015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776457.039632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.055240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.070853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.086485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776457.102122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.117746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.133359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.148979 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776457.164644 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.180323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.195910 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776458.211491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.227113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.242735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.258367 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776458.273972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.289603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.305240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.320855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776458.336479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.352144 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.367742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776459.383363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.398999 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.414633 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.430222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776459.445849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.461699 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.477103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.492727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776459.508372 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.524085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.539616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776460.555240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.570854 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.586475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.602134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776460.617719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.633346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.648968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.664622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776460.680225 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.695967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.711584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776461.727122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.742742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.758357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.773969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776461.789597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.805255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.820881 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.836481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776461.852118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776462.867780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776462.883392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776462.899138 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776462.914609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776462.930232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776462.945960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776462.961489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776462.977120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776462.992737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776463.008392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776463.024014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.039668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.055242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776464.070866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.086552 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.102132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.117737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776464.133354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.148985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.164811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.180250 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776464.195861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.211516 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.227110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776465.242759 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.258363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.273982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.289613 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776465.305257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.320848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.336577 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.352097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776465.367737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.383400 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.399001 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776466.414636 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.430238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.445862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.461807 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776466.477124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.492747 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.508509 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.523995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776466.539614 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.555295 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.570858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776467.586491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.602141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.617735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.633366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776467.648978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.664626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.680234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.695853 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776467.711485 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.727129 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.742742 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776468.758360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.773964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.789612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.805255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776468.820872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.836480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.852103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.867726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776468.883361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776469.899046 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776469.914617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776469.930337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776469.945857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776469.961478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776469.977118 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776469.992724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776470.008376 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776470.024005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776470.039623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776470.055223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.070918 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.086491 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776471.102122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.117748 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.133354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.148991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776471.164628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.180242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.195845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.211482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776471.227092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.242780 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.258357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776472.273981 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.289607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.305240 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.320848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776472.336471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.352091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.367724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.383368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776472.398977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.414671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.430227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776473.445868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.461691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.477105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.492730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776473.508366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.523986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.539593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.555222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776473.570852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.586581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.602143 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776474.617762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.633360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.648988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.664627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776474.680221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.695852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.711487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.727101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776474.742726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.758464 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.773991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776475.789606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.805445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.821029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.837099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776475.852101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.867727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.883357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.898976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776475.914635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776476.930283 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776476.945869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776476.961480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776476.977095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776476.992723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776477.008373 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776477.023992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776477.039637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776477.055200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776477.070849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776477.086483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.102151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.117746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776478.133352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.148971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.164648 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.180219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776478.195847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.211483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.227092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.242734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776478.258348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.274014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.289603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776479.305249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.320852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.336538 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.352093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776479.367717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.383356 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.398978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.414617 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776479.430292 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.445908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.461705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776480.477100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.492723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.508393 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.523984 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776480.539591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.555244 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.570842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.586465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776480.602092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.617935 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.633448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776481.648990 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.664643 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.680236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.695874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776481.711487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.727108 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.742734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.758352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776481.773992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.789642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.805249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776482.820858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.836481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.852093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.867717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776482.883355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.898971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.914609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.930214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.945957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776482.961526 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776482.977127 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776482.992764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776483.008481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776483.024179 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776484.040101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776484.055366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776484.071031 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776484.086722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776484.102242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776484.117773 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776484.133461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776484.149021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776484.164728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776484.181601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776484.196029 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.211573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.227110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776485.242726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.258363 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.273972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.289598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776485.305221 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.320862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.336481 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.352100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776485.367733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.383392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.398987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776486.414660 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.430921 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.445859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.461682 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776486.477122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.492986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.508354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.524064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776486.539591 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.555284 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.570857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776487.586473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.602117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.617739 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.633345 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776487.648964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.664635 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.680231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.695858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776487.711467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.727134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.742723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776488.758352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.773971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.789601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.805234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776488.820880 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.836482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.852122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.867729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776488.883347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776489.899026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776489.914626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776489.930228 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776489.945849 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776489.961477 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776489.977125 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776489.992713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776490.008358 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776490.024019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776490.039618 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776490.055233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.070931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.086493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776491.102102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.117750 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.133352 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.148975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776491.164609 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.180213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.195839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.211461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776491.227103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.242763 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.258359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776492.273983 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.289630 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.305233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.320897 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776492.336474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.352093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.367730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.383350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776492.398978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.414646 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.430236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776493.445856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.461692 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.477112 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.492724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776493.508341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.523986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.539594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.555226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776493.570847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.586612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.602116 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776494.617770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.633368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.648988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.664653 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776494.680242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.696021 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.711482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.727121 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776494.742726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.758407 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.773993 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776495.789606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.805382 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.820874 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.836484 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776495.852101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.867734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.883355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.898966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776495.914752 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776496.930259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776496.945857 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776496.961494 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776496.977102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776496.992722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776497.008360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776497.023996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776497.039604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776497.055218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776497.070840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776497.086498 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.102151 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.117766 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776498.133354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.148971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.164626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.180236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776498.195842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.211466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.227102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.242736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776498.258347 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.274038 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.289606 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776499.305231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.320931 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.336479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.352096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776499.367720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.383361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.398976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.414611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776499.430249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.445871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.461684 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776500.477106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.492720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.508342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.523988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776500.539603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.555222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.570845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.586479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776500.602109 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.617828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.633361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776501.648978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.664629 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.680224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.695864 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776501.711476 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.727115 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.742709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.758342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776501.773959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.789652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.805224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776502.820872 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.836475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.852089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.867726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776502.883339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.898964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.914607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.930233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776502.945838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776503.961557 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776503.977097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776503.992746 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776504.008361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776504.024000 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776504.039623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776504.055220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776504.070837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776504.086539 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776504.102088 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776504.117729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.133380 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.148982 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776505.164624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.180238 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.195846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.211460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776505.227098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.242700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.258334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.273957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776505.289584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.305249 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.320869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776506.336478 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.352098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.367736 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.383357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776506.398962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.414621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.430236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.445842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.461690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776506.477131 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776506.492749 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776506.508355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776506.524002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776506.539623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776507.555263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776507.570851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776507.586472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776507.602147 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776507.617721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776507.633355 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776507.648977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776507.664628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776507.687305 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776507.696026 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776507.711467 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.727133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.742724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776508.758350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.773966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.789602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.805214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776508.820843 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.836471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.852097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.867724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776508.883338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776509.899020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776509.914596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776509.930231 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776509.945838 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776509.961465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776509.977095 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776509.992704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776510.008332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776510.023991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776510.039601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776510.055229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.070913 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.086472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776511.102100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.117721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.133342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.148949 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776511.164607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.187370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.195828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.211453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776511.227079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.242814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.258361 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776512.273974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.289607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.305237 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.320858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776512.336501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.352110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.367734 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.383354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776512.398995 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.414662 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.430242 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776513.445846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.461687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.477081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.492712 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776513.508338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.523972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.539603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.555218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776513.570845 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.586585 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.602107 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776514.617725 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.633370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.648963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.664723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776514.687571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.695842 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.711460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.727093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776514.742728 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.758413 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.773978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776515.789593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.805255 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.820846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.836486 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776515.852099 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.867733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.883357 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.898973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776515.914622 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776516.930360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776516.945871 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776516.961473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776516.977087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776516.992713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776517.008440 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776517.024014 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776517.039624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776517.055211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776517.070832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776517.086466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.102120 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.117718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776518.133351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.148960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.164600 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.187649 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776518.195835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.211530 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.227084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.242722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776518.258333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.273994 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.289604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776519.305224 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.320861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.336519 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.352084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776519.367737 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.383340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.398996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.414608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776519.430234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.445915 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.461785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776520.477100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.492969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.508350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.523986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776520.539619 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.555274 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.570852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.586474 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776520.602110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.617815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.633359 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776521.648975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.664627 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.680215 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.695846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776521.711457 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.727103 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.742741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.758344 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776521.773975 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.789654 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.805229 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776522.820839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.836493 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.852086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.867716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776522.883364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.898958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.914604 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.930213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776522.945883 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776523.961522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776523.977101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776523.992718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776524.008354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776524.023996 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776524.039621 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776524.055206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776524.070837 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776524.086515 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776524.102084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776524.117716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.133419 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.148976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776525.164625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.180220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.195955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.211565 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776525.227190 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.242875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.258470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.274102 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776525.289583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.305281 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.320847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776526.336482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.352097 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.367706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.383346 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776526.398967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.414610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.430216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.445865 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776526.461693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.477105 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.492948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776527.508342 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.523970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.539605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.555214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776527.570846 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.586466 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.602080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.617717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776527.633337 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.648998 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.664607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776528.680213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.695834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.711453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.727076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776528.742717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.758327 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.773958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.789611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776528.805212 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.820886 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.836479 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776529.852087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.867720 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.883339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.898969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776529.914588 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.930206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.945860 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.961483 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776529.977081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776530.992822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776531.008351 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776531.023985 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776531.039620 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776531.055204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776531.071002 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776531.086525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776531.102282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776531.117713 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776531.133360 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776531.148991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.164671 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.180226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776532.195847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.211461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.227101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.242722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776532.258339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.273955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.289584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.305218 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776532.320836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.336508 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.352091 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776533.367711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.383335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.398962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.414602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776533.430207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.445868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.461673 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.477082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776533.492708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.508370 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.523977 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776534.539597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.555211 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.570834 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.586445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776534.602075 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.617697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.633334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.648963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776534.664610 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.680257 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.696005 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776535.711473 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.727092 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.742732 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.758334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776535.773969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.789593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.805230 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.820839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776535.836458 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776536.852122 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776536.867716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776536.883335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776536.898964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776536.914594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776536.930217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776536.945859 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776536.961470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776536.977086 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776536.992706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776537.008336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.024019 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.039607 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776538.055219 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.070840 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.086480 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.102083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776538.117715 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.133338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.148970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.164616 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776538.180210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.195902 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.211469 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776539.227065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.242690 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.258350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.273953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776539.289586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.305208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.320835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.336475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776539.352106 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.367786 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.383339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776540.398963 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.414595 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.430214 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.445856 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776540.461710 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.477076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.492717 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.508333 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776540.523958 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.539668 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.555213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776541.570836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.586461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.602082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.617709 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776541.633335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.648964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.664612 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.680247 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776541.695822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.711487 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.727096 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776542.742719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.758339 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.773973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.789572 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776542.805198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.820830 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.836451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.852098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776542.867704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776543.883366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776543.898965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776543.914586 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776543.930210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776543.945844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776543.961459 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776543.977080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776543.992700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776544.008335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776544.023972 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776544.039603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.055235 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.070848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776545.086475 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.102093 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.117719 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.133323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776545.148965 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.164594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.180199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.195831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776545.211449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.227132 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.242730 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776546.258329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.273986 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.289573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.305206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776546.320836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.336465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.352087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.367704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776546.383330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.399015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.414624 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776547.430210 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.445924 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.461704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.477074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776547.492711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.508324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.523970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.539584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776547.555226 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.570866 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.586456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776548.602090 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.617718 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.633336 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.648970 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776548.664605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.680222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.695822 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.711453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776548.727078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.742770 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.758332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776549.773966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.789576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.805197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.820823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776549.836453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.852085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.867721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.883330 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776549.899039 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776550.914704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776550.930209 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776550.945847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776550.961454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776550.977076 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776550.992703 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776551.008341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776551.023969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776551.039593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776551.055217 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776551.070817 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.086806 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.102110 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776552.117729 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.133335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.148987 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.164605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776552.180220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.195832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.211453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.227083 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.242723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776552.258369 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776552.273991 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776552.289603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776552.305234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776552.320852 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +1342776553.336525 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776553.352098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776553.367726 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776553.383366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776553.398957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776553.414623 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776553.430206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776553.445928 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776553.461687 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776553.477081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776553.492721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.508392 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.523992 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776554.539584 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.555227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.570829 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.586471 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776554.602071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.617723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.633334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.649025 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776554.664603 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.680343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.696035 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776555.711461 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.727245 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.742839 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.758452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776555.773968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.789580 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.805206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.820835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776555.836452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776556.852222 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776556.867814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776556.883335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776556.898971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776556.914689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776556.930267 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776556.945916 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776556.961482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776556.977073 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776556.992697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776557.008416 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.024100 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.039611 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776558.055216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.070826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.086451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.102068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776558.117738 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.133322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.149009 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.164598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776558.180197 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.195869 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.211454 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776559.227078 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.242704 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.258348 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.273956 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776559.289567 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.305206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.320811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.336463 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776559.352136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.367781 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.383338 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776560.398966 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.414706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.430202 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.446015 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776560.461685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.477080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.492695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.508329 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776560.523960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.539625 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.555234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776561.570836 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.586453 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.602071 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.617733 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776561.633335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.649040 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.664598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.680208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776561.695823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.711571 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.727164 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776562.742899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.758522 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.774149 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.789855 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776562.805265 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.820826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.836534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.852174 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776562.867899 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776563.883364 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776563.898964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776563.914583 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776563.930206 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776563.945957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776563.961489 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776563.977087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776563.992697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776564.008326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776564.023976 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776564.039598 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.055259 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.070833 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776565.086465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.102087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.117722 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.133390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776565.149020 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.164594 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.180216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.195826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776565.211455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.227161 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.242705 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776566.258349 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.273951 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.289575 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.305201 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776566.320821 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.336442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.352134 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.367741 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776566.383394 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.398974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.414608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776567.430674 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.445904 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.461678 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.477080 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776567.492706 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.508332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.523971 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.539568 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776567.555194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.570875 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.586691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776568.602094 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.617753 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.633343 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.649030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776568.664642 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.680263 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.695847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.711444 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776568.727069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.742785 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.758354 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776569.773953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.789605 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.805200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.820828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776569.836445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.852155 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.867735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.883335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776569.898950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776570.914650 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776570.930207 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776570.945908 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776570.961465 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776570.977070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776570.992698 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776571.008326 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776571.023974 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776571.039602 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776571.055204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776571.070858 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.086697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.102182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776572.117803 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.133424 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.149048 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.164632 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776572.180213 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.195861 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.211456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.227082 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776572.242708 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.258434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.273967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776573.289597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.305208 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.320944 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.336521 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776573.352136 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.367879 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.383531 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.398988 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776573.414637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.430324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.446200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776574.461868 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.477233 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.492711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.508507 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776574.524124 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.539693 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.555223 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.570978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776574.586460 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.602171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.617716 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776575.633378 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.649023 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.664592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.680220 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776575.695827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.711439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.727068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.742689 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776575.758319 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.774171 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.789576 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776576.805332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.820823 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.836442 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.852145 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776576.867735 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.883318 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.898948 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.914573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776576.930882 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776577.945959 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776577.961472 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776577.977079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776577.992695 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776578.008341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776578.023964 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776578.039601 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776578.055193 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776578.070847 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776578.086448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776578.102068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.117810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.133332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776579.149042 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.164599 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.180216 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.195862 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776579.211439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.227087 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.242707 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.258334 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776579.273973 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.289652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.305239 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776580.320826 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.336455 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.352153 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.367723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776580.383335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.398957 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.414596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.430198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776580.445820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.461761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.477074 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776581.492685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.508323 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.523953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.539574 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776581.555185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.570844 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.586439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.602067 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776581.617724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.633390 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.649030 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776582.664592 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.680195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.695814 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.711443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776582.727234 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.742691 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.758315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.773942 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776582.789561 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.805232 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.820818 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776583.836443 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.852141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.867723 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.883308 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776583.898937 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.914560 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.930184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.945819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776583.961447 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776584.977113 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776584.992700 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776585.008325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776585.023968 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776585.039587 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776585.055200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776585.070835 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776585.086452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776585.102065 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776585.117721 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776585.133328 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.149101 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.164608 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776586.180204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.195832 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.211449 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.227081 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776586.242685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.258340 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.273950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.289581 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776586.305194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.320850 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.336456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776587.352146 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.367727 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.383317 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.398962 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776587.414573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.430200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.445811 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.461656 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776587.477079 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.492761 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.508341 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776588.523955 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.539582 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.555200 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.570828 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776588.586436 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.602084 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.617701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.633307 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776588.648950 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.664637 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.680252 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776589.695824 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.711446 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.727060 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.742685 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776589.758315 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.773946 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.789564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.805182 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776589.820815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.836470 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.852141 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776590.867724 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.883310 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.898940 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.914566 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776590.930177 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.945820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.961437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.977069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776590.992697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.008368 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.023969 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776592.039579 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.055199 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.070827 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.086518 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776592.102054 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.117804 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.133311 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.148945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776592.164597 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.180227 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.195820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776593.211451 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.227069 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.242697 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.258314 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776593.273967 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.289558 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.305185 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.320810 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776593.336434 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.352163 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.367795 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776594.383324 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.398941 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.414589 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.430195 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776594.445815 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.461664 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.477068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.492675 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776594.508301 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.524133 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.539628 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776595.555198 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.570841 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.586513 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.602070 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776595.617775 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.633325 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.648945 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.664593 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776595.687534 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.695848 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.711448 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776596.727064 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.742701 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.758313 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.773953 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776596.789564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.805184 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.820812 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.836439 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776596.852072 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776597.867809 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776597.883335 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776597.898939 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776597.914570 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776597.930204 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776597.945820 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776597.961452 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776597.977089 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776597.992683 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776598.008309 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776598.023978 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.039711 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.055189 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776599.070831 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.086445 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.102068 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.117762 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776599.133304 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.148938 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.164794 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.196626 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776599.211437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.227117 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.242696 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776600.258322 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.273960 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.289573 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.305187 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_HOLDING_REGISTERS - +1342776600.320819 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.336437 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.352059 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.367764 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.383332 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 READ_INPUT_REGISTERS - +1342776600.399016 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 WRITE_SINGLE_REGISTER - +#close 2013-08-26-19-04-17 diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.policy/modbus_register_change.log b/testing/btest/Baseline/scripts.base.protocols.modbus.policy/modbus_register_change.log index c44072aa42..8925b8ce7d 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.policy/modbus_register_change.log +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.policy/modbus_register_change.log @@ -3,47 +3,47 @@ #empty_field (empty) #unset_field - #path modbus_register_change -#open 2012-11-06-00-51-15 +#open 2013-08-26-19-36-36 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p register old_val new_val delta #types time string addr port addr port count count count interval -1342774501.024564 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 0 1 1.250066 -1342774540.946501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 1 0 39.921937 -1342774540.946501 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 0 1 41.172003 -1342774811.727563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 0 1 311.953065 -1342774811.727563 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781062 -1342774831.727542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 0 1 290.781041 -1342774831.727542 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 1 0 19.999979 -1342774872.821282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 1 0 41.093740 -1342774872.821282 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 0 1 61.093719 -1342775143.602482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 0 1 311.874940 -1342775143.602482 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781200 -1342775164.774350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 0 1 291.953068 -1342775164.774350 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 1 0 21.171868 -1342775204.696194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 1 0 39.921844 -1342775204.696194 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 0 1 61.093712 -1342775475.477365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 0 1 310.703015 -1342775475.477365 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781171 -1342775495.477389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 0 1 290.781195 -1342775495.477389 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 1 0 20.000024 -1342775535.399236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 1 0 39.921847 -1342775535.399236 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 0 1 59.921871 -1342775806.180404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 0 1 310.703015 -1342775806.180404 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781168 -1342775826.180415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 0 1 290.781179 -1342775826.180415 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 1 0 20.000011 -1342775848.508596 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 501 80 90 1348.671590 -1342775871.961652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 1 0 45.781237 -1342775871.961652 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 0 1 65.781248 -1342776142.758456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 0 1 316.578041 -1342776142.758456 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.796804 -1342776167.445943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 0 1 295.484291 -1342776167.445943 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 1 0 24.687487 -1342776213.274085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 1 0 45.828142 -1342776213.274085 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 0 1 70.515629 -1342776484.055366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 0 1 316.609423 -1342776484.055366 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781281 -1342776507.570851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 0 1 294.296766 -1342776507.570851 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 102 1 0 23.515485 -1342776553.352098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 101 1 0 45.781247 -1342776553.352098 3PKsZ2Uye21 10.1.1.234 51411 10.10.5.85 502 103 0 1 69.296732 -#close 2012-11-06-00-51-23 +1342774501.024564 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 0 1 1.250066 +1342774540.946501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 1 0 39.921937 +1342774540.946501 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 0 1 41.172003 +1342774811.727563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 0 1 311.953065 +1342774811.727563 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781062 +1342774831.727542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 0 1 290.781041 +1342774831.727542 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 1 0 19.999979 +1342774872.821282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 1 0 41.093740 +1342774872.821282 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 0 1 61.093719 +1342775143.602482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 0 1 311.874940 +1342775143.602482 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781200 +1342775164.774350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 0 1 291.953068 +1342775164.774350 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 1 0 21.171868 +1342775204.696194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 1 0 39.921844 +1342775204.696194 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 0 1 61.093712 +1342775475.477365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 0 1 310.703015 +1342775475.477365 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781171 +1342775495.477389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 0 1 290.781195 +1342775495.477389 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 1 0 20.000024 +1342775535.399236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 1 0 39.921847 +1342775535.399236 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 0 1 59.921871 +1342775806.180404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 0 1 310.703015 +1342775806.180404 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781168 +1342775826.180415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 0 1 290.781179 +1342775826.180415 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 1 0 20.000011 +1342775848.508596 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 501 80 90 1348.671590 +1342775871.961652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 1 0 45.781237 +1342775871.961652 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 0 1 65.781248 +1342776142.758456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 0 1 316.578041 +1342776142.758456 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.796804 +1342776167.445943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 0 1 295.484291 +1342776167.445943 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 1 0 24.687487 +1342776213.274085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 1 0 45.828142 +1342776213.274085 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 0 1 70.515629 +1342776484.055366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 0 1 316.609423 +1342776484.055366 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 1 0 270.781281 +1342776507.570851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 0 1 294.296766 +1342776507.570851 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 102 1 0 23.515485 +1342776553.352098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 101 1 0 45.781247 +1342776553.352098 C7XEbhP654jzLoe3a 10.1.1.234 51411 10.10.5.85 502 103 0 1 69.296732 +#close 2013-08-26-19-36-40 diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.register_parsing/modbus.log b/testing/btest/Baseline/scripts.base.protocols.modbus.register_parsing/modbus.log index 85a3a6117c..fabf920ca8 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.register_parsing/modbus.log +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.register_parsing/modbus.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path modbus -#open 2012-11-12-21-51-15 +#open 2013-08-26-19-04-19 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p func exception #types time string addr port addr port string string -1342774775.305761 UWkUyAuUGXf 10.1.1.234 51411 10.10.5.104 502 READ_INPUT_REGISTERS - -1342775209.493066 arKYeMETxOg 10.1.1.234 51411 10.10.5.104 502 READ_INPUT_REGISTERS - -1342776371.617757 nQcgTWjvg4c 10.1.1.234 51411 10.10.5.104 502 READ_INPUT_REGISTERS - -#close 2012-11-12-21-51-15 +1342774775.305761 CXWv6p3arKYeMETxOg 10.1.1.234 51411 10.10.5.104 502 READ_INPUT_REGISTERS - +1342775209.493066 CjhGID4nQcgTWjvg4c 10.1.1.234 51411 10.10.5.104 502 READ_INPUT_REGISTERS - +1342776371.617757 CsRx2w45OKnoww6xl4 10.1.1.234 51411 10.10.5.104 502 READ_INPUT_REGISTERS - +#close 2013-08-26-19-04-19 diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log b/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log index b56b8afab6..540ff8c0ae 100644 --- a/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log +++ b/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path smtp -#open 2013-07-25-19-52-35 +#open 2013-08-26-18-40-24 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth helo mailfrom rcptto date from to reply_to msg_id in_reply_to subject x_originating_ip first_received second_received last_reply path user_agent fuids #types time string addr port addr port count string string table[string] string string table[string] string string string string addr string string string vector[addr] string vector[string] -1254722768.219663 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 GP Mon, 5 Oct 2009 11:36:07 +0530 "Gurpartap Singh" - <000301ca4581$ef9e57f0$cedb07d0$@in> - SMTP - - - 250 OK id=1Mugho-0003Dg-Un 74.53.140.153,10.10.1.4 Microsoft Office Outlook 12.0 A1IqG95k9Tk,VUcocHqaWva,JJPHrvZaGJj -#close 2013-07-25-19-52-35 +1254722768.219663 CjhGID4nQcgTWjvg4c 10.10.1.4 1470 74.53.140.153 25 1 GP Mon, 5 Oct 2009 11:36:07 +0530 "Gurpartap Singh" - <000301ca4581$ef9e57f0$cedb07d0$@in> - SMTP - - - 250 OK id=1Mugho-0003Dg-Un 74.53.140.153,10.10.1.4 Microsoft Office Outlook 12.0 Fel9gs4OtNEV6gUJZ5,Ft4M3f2yMvLlmwtbq9,FL9Y0d45OI4LpS6fmh +#close 2013-08-26-18-40-24 diff --git a/testing/btest/Baseline/scripts.base.protocols.socks.trace1/socks.log b/testing/btest/Baseline/scripts.base.protocols.socks.trace1/socks.log index 8529e18186..148e4adf02 100644 --- a/testing/btest/Baseline/scripts.base.protocols.socks.trace1/socks.log +++ b/testing/btest/Baseline/scripts.base.protocols.socks.trace1/socks.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path socks -#open 2013-05-02-01-02-50 +#open 2013-08-26-19-04-20 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user status request.host request.name request_p bound.host bound.name bound_p #types time string addr port addr port count string string addr string port addr string port -1340213015.276495 arKYeMETxOg 10.0.0.55 53994 60.190.189.214 8124 5 - succeeded - www.osnews.com 80 192.168.0.31 - 2688 -#close 2013-05-02-01-02-50 +1340213015.276495 CjhGID4nQcgTWjvg4c 10.0.0.55 53994 60.190.189.214 8124 5 - succeeded - www.osnews.com 80 192.168.0.31 - 2688 +#close 2013-08-26-19-04-20 diff --git a/testing/btest/Baseline/scripts.base.protocols.socks.trace2/socks.log b/testing/btest/Baseline/scripts.base.protocols.socks.trace2/socks.log index 4053bd7359..d706a11da3 100644 --- a/testing/btest/Baseline/scripts.base.protocols.socks.trace2/socks.log +++ b/testing/btest/Baseline/scripts.base.protocols.socks.trace2/socks.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path socks -#open 2012-06-19-13-41-02 +#open 2013-08-26-19-04-20 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version user status request.host request.name request_p bound.host bound.name bound_p #types time string addr port addr port count string string addr string port addr string port -1340113261.914619 UWkUyAuUGXf 10.0.0.50 59580 85.194.84.197 1080 5 - succeeded - www.google.com 443 0.0.0.0 - 443 -#close 2012-06-19-13-41-05 +1340113261.914619 CXWv6p3arKYeMETxOg 10.0.0.50 59580 85.194.84.197 1080 5 - succeeded - www.google.com 443 0.0.0.0 - 443 +#close 2013-08-26-19-04-20 diff --git a/testing/btest/Baseline/scripts.base.protocols.ssl.basic/ssl.log b/testing/btest/Baseline/scripts.base.protocols.ssl.basic/ssl.log index 872da052ea..a0dad9ea67 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ssl.basic/ssl.log +++ b/testing/btest/Baseline/scripts.base.protocols.ssl.basic/ssl.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path ssl -#open 2012-10-08-16-18-56 +#open 2013-08-26-19-04-21 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher server_name session_id subject issuer_subject not_valid_before not_valid_after last_alert client_subject client_issuer_subject #types time string addr port addr port string string string string string string time time string string string -1335538392.319381 UWkUyAuUGXf 192.168.1.105 62045 74.125.224.79 443 TLSv10 TLS_ECDHE_RSA_WITH_RC4_128_SHA ssl.gstatic.com - CN=*.gstatic.com,O=Google Inc,L=Mountain View,ST=California,C=US CN=Google Internet Authority,O=Google Inc,C=US 1334102677.000000 1365639277.000000 - - - -#close 2012-10-08-16-18-56 +1335538392.319381 CXWv6p3arKYeMETxOg 192.168.1.105 62045 74.125.224.79 443 TLSv10 TLS_ECDHE_RSA_WITH_RC4_128_SHA ssl.gstatic.com - CN=*.gstatic.com,O=Google Inc,L=Mountain View,ST=California,C=US CN=Google Internet Authority,O=Google Inc,C=US 1334102677.000000 1365639277.000000 - - - +#close 2013-08-26-19-04-21 diff --git a/testing/btest/Baseline/scripts.base.protocols.ssl.tls-1.2/ssl.log b/testing/btest/Baseline/scripts.base.protocols.ssl.tls-1.2/ssl.log index 375c033c38..dc9a9ff752 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ssl.tls-1.2/ssl.log +++ b/testing/btest/Baseline/scripts.base.protocols.ssl.tls-1.2/ssl.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path ssl -#open 2013-07-02-18-46-17 +#open 2013-08-26-19-04-22 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher server_name session_id subject issuer_subject not_valid_before not_valid_after last_alert client_subject client_issuer_subject #types time string addr port addr port string string string string string string time time string string string -1357328848.549370 UWkUyAuUGXf 10.0.0.80 56637 68.233.76.12 443 TLSv12 TLS_RSA_WITH_RC4_128_MD5 - - CN=*.taleo.net,OU=Comodo PremiumSSL Wildcard,OU=Web,O=Taleo Inc.,street=4140 Dublin Boulevard,street=Suite 400,L=Dublin,ST=CA,postalCode=94568,C=US CN=COMODO High-Assurance Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB 1304467200.000000 1467676799.000000 - - - -#close 2013-07-02-18-46-17 +1357328848.549370 CXWv6p3arKYeMETxOg 10.0.0.80 56637 68.233.76.12 443 TLSv12 TLS_RSA_WITH_RC4_128_MD5 - - CN=*.taleo.net,OU=Comodo PremiumSSL Wildcard,OU=Web,O=Taleo Inc.,street=4140 Dublin Boulevard,street=Suite 400,L=Dublin,ST=CA,postalCode=94568,C=US CN=COMODO High-Assurance Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB 1304467200.000000 1467676799.000000 - - - +#close 2013-08-26-19-04-22 diff --git a/testing/btest/Baseline/scripts.base.protocols.syslog.trace/syslog.log b/testing/btest/Baseline/scripts.base.protocols.syslog.trace/syslog.log index df53ef42f6..449166242c 100644 --- a/testing/btest/Baseline/scripts.base.protocols.syslog.trace/syslog.log +++ b/testing/btest/Baseline/scripts.base.protocols.syslog.trace/syslog.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path syslog -#open 2013-04-05-20-06-27 +#open 2013-08-26-19-04-22 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto facility severity message #types time string addr port addr port enum string string string -1365191811.424495 UWkUyAuUGXf 127.0.0.1 57067 127.0.0.1 514 udp LOCAL0 NOTICE Apr 5 12:56:51 robin: Hello, syslog!\x00 -#close 2013-04-05-20-06-27 +1365191811.424495 CXWv6p3arKYeMETxOg 127.0.0.1 57067 127.0.0.1 514 udp LOCAL0 NOTICE Apr 5 12:56:51 robin: Hello, syslog!\x00 +#close 2013-08-26-19-04-22 diff --git a/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log b/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log index 74de757007..18d5769abf 100644 --- a/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log +++ b/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path dns -#open 2012-10-05-17-47-40 +#open 2013-08-26-19-04-37 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected auth addl #types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] bool table[string] table[string] -930613226.518174 UWkUyAuUGXf 212.180.42.100 25000 131.243.64.3 53 tcp 34798 - - - - - 0 NOERROR F F F T 0 4.3.2.1 31337.000000 F - - -#close 2012-10-05-17-47-40 +930613226.518174 CXWv6p3arKYeMETxOg 212.180.42.100 25000 131.243.64.3 53 tcp 34798 - - - - - 0 NOERROR F F F T 0 4.3.2.1 31337.000000 F - - +#close 2013-08-26-19-04-37 diff --git a/testing/btest/Baseline/signatures.eval-condition/conn.log b/testing/btest/Baseline/signatures.eval-condition/conn.log index a803f74320..ded15438b7 100644 --- a/testing/btest/Baseline/signatures.eval-condition/conn.log +++ b/testing/btest/Baseline/signatures.eval-condition/conn.log @@ -3,12 +3,12 @@ #empty_field (empty) #unset_field - #path conn -#open 2012-08-23-16-41-23 +#open 2013-08-26-19-04-43 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] -1329843175.736107 arKYeMETxOg 141.142.220.235 37604 199.233.217.249 56666 tcp ftp-data 0.112432 0 342 SF - 0 ShAdfFa 4 216 4 562 (empty) -1329843179.871641 k6kgXLOoSKl 141.142.220.235 59378 199.233.217.249 56667 tcp ftp-data 0.111218 0 77 SF - 0 ShAdfFa 4 216 4 297 (empty) -1329843194.151526 nQcgTWjvg4c 199.233.217.249 61920 141.142.220.235 33582 tcp ftp-data 0.056211 342 0 SF - 0 ShADaFf 5 614 3 164 (empty) -1329843197.783443 j4u32Pc5bif 199.233.217.249 61918 141.142.220.235 37835 tcp ftp-data 0.056005 77 0 SF - 0 ShADaFf 5 349 3 164 (empty) -1329843161.968492 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 tcp ftp,blah 38.055625 180 3146 SF - 0 ShAdDfFa 38 2164 25 4458 (empty) -#close 2012-08-23-16-41-23 +1329843175.736107 CjhGID4nQcgTWjvg4c 141.142.220.235 37604 199.233.217.249 56666 tcp ftp-data 0.112432 0 342 SF - 0 ShAdfFa 4 216 4 562 (empty) +1329843179.871641 CCvvfg3TEfuqmmG4bh 141.142.220.235 59378 199.233.217.249 56667 tcp ftp-data 0.111218 0 77 SF - 0 ShAdfFa 4 216 4 297 (empty) +1329843194.151526 CsRx2w45OKnoww6xl4 199.233.217.249 61920 141.142.220.235 33582 tcp ftp-data 0.056211 342 0 SF - 0 ShADaFf 5 614 3 164 (empty) +1329843197.783443 CRJuHdVW0XPVINV8a 199.233.217.249 61918 141.142.220.235 37835 tcp ftp-data 0.056005 77 0 SF - 0 ShADaFf 5 349 3 164 (empty) +1329843161.968492 CXWv6p3arKYeMETxOg 141.142.220.235 50003 199.233.217.249 21 tcp ftp,blah 38.055625 180 3146 SF - 0 ShAdDfFa 38 2164 25 4458 (empty) +#close 2013-08-26-19-04-43 diff --git a/testing/btest/scripts/base/frameworks/file-analysis/input/basic.bro b/testing/btest/scripts/base/frameworks/file-analysis/input/basic.bro index f9ca9fb325..053341c840 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/input/basic.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/input/basic.bro @@ -1,7 +1,7 @@ # @TEST-EXEC: btest-bg-run bro bro -b $SCRIPTS/file-analysis-test.bro %INPUT # @TEST-EXEC: btest-bg-wait 8 # @TEST-EXEC: btest-diff bro/.stdout -# @TEST-EXEC: diff -q bro/nYgPNGLrZf9-file input.log +# @TEST-EXEC: diff -q bro/FK8WqY1Q9U1rVxnDge-file input.log redef exit_only_after_terminate = T; diff --git a/testing/scripts/diff-remove-file-ids b/testing/scripts/diff-remove-file-ids index f54177d8ba..965a74442e 100755 --- a/testing/scripts/diff-remove-file-ids +++ b/testing/scripts/diff-remove-file-ids @@ -1,6 +1,6 @@ #! /usr/bin/awk -f # -# A diff canonifier that removes all file IDs from file_analysis.log +# A diff canonifier that removes all file IDs from files.log BEGIN { FS="\t"; @@ -8,7 +8,7 @@ BEGIN { process = 0; } -$1 == "#path" && $2 == "file_analysis" { +$1 == "#path" && $2 == "files" { process = 1; } @@ -19,10 +19,10 @@ process && column1 > 0 && column2 > 0 { /^#/ { for ( i = 0; i < NF; ++i ) { - if ( $i == "id" ) + if ( $i == "fuid" ) column1 = i - 1; - if ( $i == "parent_id" ) + if ( $i == "parent_fuid" ) column2 = i - 1; } } From 50dbbab52c6e84f677c38f763ec8001d30ed282f Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 26 Aug 2013 16:11:20 -0500 Subject: [PATCH 262/881] Fix UID compiler warning/error & missed baselines. --- src/UID.cc | 4 +- src/UID.h | 2 + .../conn.ds.txt | 68 +++++++++---------- .../conn.ds.txt | 68 +++++++++---------- .../http.ds.txt | 28 ++++---- 5 files changed, 86 insertions(+), 84 deletions(-) diff --git a/src/UID.cc b/src/UID.cc index e71bf9fafc..48c341b11e 100644 --- a/src/UID.cc +++ b/src/UID.cc @@ -10,9 +10,9 @@ void UID::Set(bro_uint_t bits, const std::vector& v) uid.clear(); div_t res = div(bits, 64); - int size = res.rem ? res.quot + 1 : res.quot; + size_t size = res.rem ? res.quot + 1 : res.quot; - for ( int i = 0; i < size; ++i ) + for ( size_t i = 0; i < size; ++i ) uid.push_back(i < v.size() ? v[i] : calculate_unique_id()); if ( res.rem ) diff --git a/src/UID.h b/src/UID.h index 6fcad4e989..f18d85ca63 100644 --- a/src/UID.h +++ b/src/UID.h @@ -80,6 +80,8 @@ private: std::vector uid; }; +bool operator==(const UID& u1, const UID& u2); + } // namespace Bro #endif diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.time-as-int/conn.ds.txt b/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.time-as-int/conn.ds.txt index bd3d367632..5a48439a9f 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.time-as-int/conn.ds.txt +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.time-as-int/conn.ds.txt @@ -53,37 +53,37 @@ # Extent, type='conn' ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents -1300475167096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns 0 0 0 S0 F 0 D 1 73 0 0 -1300475167097012 arKYeMETxOg fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0 0 0 S0 F 0 D 1 199 0 0 -1300475167099816 k6kgXLOoSKl 141.142.220.50 5353 224.0.0.251 5353 udp 0 0 0 S0 F 0 D 1 179 0 0 -1300475168853899 TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 435 38 89 SF F 0 Dd 1 66 1 117 -1300475168854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 420 52 99 SF F 0 Dd 1 80 1 127 -1300475168854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 391 38 183 SF F 0 Dd 1 66 1 211 -1300475168857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 317 38 89 SF F 0 Dd 1 66 1 117 -1300475168858306 qSsw6ESzHV4 141.142.220.118 59816 141.142.2.2 53 udp dns 343 52 99 SF F 0 Dd 1 80 1 127 -1300475168858713 iE6yhOq3SF 141.142.220.118 59714 141.142.2.2 53 udp dns 375 38 183 SF F 0 Dd 1 66 1 211 -1300475168891644 qCaWGmzFtM5 141.142.220.118 58206 141.142.2.2 53 udp dns 339 38 89 SF F 0 Dd 1 66 1 117 -1300475168892037 70MGiRM1Qf4 141.142.220.118 38911 141.142.2.2 53 udp dns 334 52 99 SF F 0 Dd 1 80 1 127 -1300475168892414 h5DsfNtYzi1 141.142.220.118 59746 141.142.2.2 53 udp dns 420 38 183 SF F 0 Dd 1 66 1 211 -1300475168893988 c4Zw9TmAE05 141.142.220.118 45000 141.142.2.2 53 udp dns 384 38 89 SF F 0 Dd 1 66 1 117 -1300475168894422 EAr0uf4mhq 141.142.220.118 48479 141.142.2.2 53 udp dns 316 52 99 SF F 0 Dd 1 80 1 127 -1300475168894787 GvmoxJFXdTa 141.142.220.118 48128 141.142.2.2 53 udp dns 422 38 183 SF F 0 Dd 1 66 1 211 -1300475168901749 slFea8xwSmb 141.142.220.118 56056 141.142.2.2 53 udp dns 402 36 131 SF F 0 Dd 1 64 1 159 -1300475168902195 UfGkYA2HI2g 141.142.220.118 55092 141.142.2.2 53 udp dns 374 36 198 SF F 0 Dd 1 64 1 226 -1300475169899438 BWaU4aSuwkc 141.142.220.44 5353 224.0.0.251 5353 udp dns 0 0 0 S0 F 0 D 1 85 0 0 -1300475170862384 10XodEwRycf 141.142.220.226 137 141.142.220.255 137 udp dns 2613016 350 0 S0 F 0 D 7 546 0 0 -1300475171675372 zno26fFZkrh fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 100096 66 0 S0 F 0 D 2 162 0 0 -1300475171677081 v5rgkJBig5l 141.142.220.226 55131 224.0.0.252 5355 udp dns 100020 66 0 S0 F 0 D 2 122 0 0 -1300475173116749 eWZCH7OONC1 fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 99801 66 0 S0 F 0 D 2 162 0 0 -1300475173117362 0Pwk3ntf8O3 141.142.220.226 55671 224.0.0.252 5355 udp dns 99848 66 0 S0 F 0 D 2 122 0 0 -1300475173153679 0HKorjr8Zp7 141.142.220.238 56641 141.142.220.255 137 udp dns 0 0 0 S0 F 0 D 1 78 0 0 -1300475168859163 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 tcp http 215893 1130 734 S1 F 0 ShADad 6 1450 4 950 -1300475168652003 nQcgTWjvg4c 141.142.220.118 35634 208.80.152.2 80 tcp 61328 463 350 OTH F 0 DdA 2 567 1 402 -1300475168895267 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 tcp http 227283 1178 734 S1 F 0 ShADad 6 1498 4 950 -1300475168902635 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 tcp http 120040 534 412 S1 F 0 ShADad 4 750 3 576 -1300475168892936 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 tcp http 229603 1148 734 S1 F 0 ShADad 6 1468 4 950 -1300475168855305 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 tcp http 218501 1171 733 S1 F 0 ShADad 6 1491 4 949 -1300475168892913 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 tcp http 220960 1137 733 S1 F 0 ShADad 6 1457 4 949 -1300475169780331 2cx26uAvUPl 141.142.220.235 6705 173.192.163.128 80 tcp 0 0 0 OTH F 0 h 0 0 1 48 -1300475168724007 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 tcp http 119904 525 232 S1 F 0 ShADad 4 741 3 396 -1300475168855330 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 tcp http 219720 1125 734 S1 F 0 ShADad 6 1445 4 950 +1300475167096535 CXWv6p3arKYeMETxOg 141.142.220.202 5353 224.0.0.251 5353 udp dns 0 0 0 S0 F 0 D 1 73 0 0 +1300475167097012 CjhGID4nQcgTWjvg4c fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0 0 0 S0 F 0 D 1 199 0 0 +1300475167099816 CCvvfg3TEfuqmmG4bh 141.142.220.50 5353 224.0.0.251 5353 udp 0 0 0 S0 F 0 D 1 179 0 0 +1300475168853899 CPbrpk1qSsw6ESzHV4 141.142.220.118 43927 141.142.2.2 53 udp dns 435 38 89 SF F 0 Dd 1 66 1 117 +1300475168854378 C6pKV8GSxOnSLghOa 141.142.220.118 37676 141.142.2.2 53 udp dns 420 52 99 SF F 0 Dd 1 80 1 127 +1300475168854837 CIPOse170MGiRM1Qf4 141.142.220.118 40526 141.142.2.2 53 udp dns 391 38 183 SF F 0 Dd 1 66 1 211 +1300475168857956 CMXxB5GvmoxJFXdTa 141.142.220.118 32902 141.142.2.2 53 udp dns 317 38 89 SF F 0 Dd 1 66 1 117 +1300475168858306 Caby8b1slFea8xwSmb 141.142.220.118 59816 141.142.2.2 53 udp dns 343 52 99 SF F 0 Dd 1 80 1 127 +1300475168858713 Che1bq3i2rO3KD1Syg 141.142.220.118 59714 141.142.2.2 53 udp dns 375 38 183 SF F 0 Dd 1 66 1 211 +1300475168891644 CEle3f3zno26fFZkrh 141.142.220.118 58206 141.142.2.2 53 udp dns 339 38 89 SF F 0 Dd 1 66 1 117 +1300475168892037 CwSkQu4eWZCH7OONC1 141.142.220.118 38911 141.142.2.2 53 udp dns 334 52 99 SF F 0 Dd 1 80 1 127 +1300475168892414 CfTOmO0HKorjr8Zp7 141.142.220.118 59746 141.142.2.2 53 udp dns 420 38 183 SF F 0 Dd 1 66 1 211 +1300475168893988 Cab0vO1xNYSS2hJkle 141.142.220.118 45000 141.142.2.2 53 udp dns 384 38 89 SF F 0 Dd 1 66 1 117 +1300475168894422 Cx2FqO23omNawSNrxj 141.142.220.118 48479 141.142.2.2 53 udp dns 316 52 99 SF F 0 Dd 1 80 1 127 +1300475168894787 Cx3C534wEyF3OvvcQe 141.142.220.118 48128 141.142.2.2 53 udp dns 422 38 183 SF F 0 Dd 1 66 1 211 +1300475168901749 CUKS0W3HFYOnBqSE5e 141.142.220.118 56056 141.142.2.2 53 udp dns 402 36 131 SF F 0 Dd 1 64 1 159 +1300475168902195 CRrfvP2lalMAYOCLhj 141.142.220.118 55092 141.142.2.2 53 udp dns 374 36 198 SF F 0 Dd 1 64 1 226 +1300475169899438 CojBOU3CXcLHl1r6x1 141.142.220.44 5353 224.0.0.251 5353 udp dns 0 0 0 S0 F 0 D 1 85 0 0 +1300475170862384 CJzVQRGJrX6V15ik7 141.142.220.226 137 141.142.220.255 137 udp dns 2613016 350 0 S0 F 0 D 7 546 0 0 +1300475171675372 ClAbxY1nmdjCuo0Le2 fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 100096 66 0 S0 F 0 D 2 162 0 0 +1300475171677081 CwG0BF1VXE0gWgs78 141.142.220.226 55131 224.0.0.252 5355 udp dns 100020 66 0 S0 F 0 D 2 122 0 0 +1300475173116749 CisNaL1Cm73CiNOmcg fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 99801 66 0 S0 F 0 D 2 162 0 0 +1300475173117362 CBQnJn22qN8TOeeZil 141.142.220.226 55671 224.0.0.252 5355 udp dns 99848 66 0 S0 F 0 D 2 122 0 0 +1300475173153679 CbEsuD3dgDDngdlbKf 141.142.220.238 56641 141.142.220.255 137 udp dns 0 0 0 S0 F 0 D 1 78 0 0 +1300475168859163 C3SfNE4BWaU4aSuwkc 141.142.220.118 49998 208.80.152.3 80 tcp http 215893 1130 734 S1 F 0 ShADad 6 1450 4 950 +1300475168652003 CsRx2w45OKnoww6xl4 141.142.220.118 35634 208.80.152.2 80 tcp 61328 463 350 OTH F 0 DdA 2 567 1 402 +1300475168895267 CkDsfG2YIeWJmXWNWj 141.142.220.118 50001 208.80.152.3 80 tcp http 227283 1178 734 S1 F 0 ShADad 6 1498 4 950 +1300475168902635 Cn78a440HlxuyZKs6f 141.142.220.118 35642 208.80.152.2 80 tcp http 120040 534 412 S1 F 0 ShADad 4 750 3 576 +1300475168892936 CyAhVIzHqb7t7kv28 141.142.220.118 50000 208.80.152.3 80 tcp http 229603 1148 734 S1 F 0 ShADad 6 1468 4 950 +1300475168855305 C7XEbhP654jzLoe3a 141.142.220.118 49996 208.80.152.3 80 tcp http 218501 1171 733 S1 F 0 ShADad 6 1491 4 949 +1300475168892913 CzA03V1VcgagLjnO92 141.142.220.118 49999 208.80.152.3 80 tcp http 220960 1137 733 S1 F 0 ShADad 6 1457 4 949 +1300475169780331 CUof3F2yAIid8QS3dk 141.142.220.235 6705 173.192.163.128 80 tcp 0 0 0 OTH F 0 h 0 0 1 48 +1300475168724007 CRJuHdVW0XPVINV8a 141.142.220.118 48649 208.80.152.118 80 tcp http 119904 525 232 S1 F 0 ShADad 4 741 3 396 +1300475168855330 CJ3xTn1c4Zw9TmAE05 141.142.220.118 49997 208.80.152.3 80 tcp http 219720 1125 734 S1 F 0 ShADad 6 1445 4 950 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/conn.ds.txt b/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/conn.ds.txt index a85ae29346..8f486c30e0 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/conn.ds.txt +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/conn.ds.txt @@ -53,37 +53,37 @@ # Extent, type='conn' ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents -1300475167.096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 73 0 0 -1300475167.097012 arKYeMETxOg fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0.000000 0 0 S0 F 0 D 1 199 0 0 -1300475167.099816 k6kgXLOoSKl 141.142.220.50 5353 224.0.0.251 5353 udp 0.000000 0 0 S0 F 0 D 1 179 0 0 -1300475168.853899 TEfuqmmG4bh 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF F 0 Dd 1 66 1 117 -1300475168.854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF F 0 Dd 1 80 1 127 -1300475168.854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF F 0 Dd 1 66 1 211 -1300475168.857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF F 0 Dd 1 66 1 117 -1300475168.858306 qSsw6ESzHV4 141.142.220.118 59816 141.142.2.2 53 udp dns 0.000343 52 99 SF F 0 Dd 1 80 1 127 -1300475168.858713 iE6yhOq3SF 141.142.220.118 59714 141.142.2.2 53 udp dns 0.000375 38 183 SF F 0 Dd 1 66 1 211 -1300475168.891644 qCaWGmzFtM5 141.142.220.118 58206 141.142.2.2 53 udp dns 0.000339 38 89 SF F 0 Dd 1 66 1 117 -1300475168.892037 70MGiRM1Qf4 141.142.220.118 38911 141.142.2.2 53 udp dns 0.000335 52 99 SF F 0 Dd 1 80 1 127 -1300475168.892414 h5DsfNtYzi1 141.142.220.118 59746 141.142.2.2 53 udp dns 0.000421 38 183 SF F 0 Dd 1 66 1 211 -1300475168.893988 c4Zw9TmAE05 141.142.220.118 45000 141.142.2.2 53 udp dns 0.000384 38 89 SF F 0 Dd 1 66 1 117 -1300475168.894422 EAr0uf4mhq 141.142.220.118 48479 141.142.2.2 53 udp dns 0.000317 52 99 SF F 0 Dd 1 80 1 127 -1300475168.894787 GvmoxJFXdTa 141.142.220.118 48128 141.142.2.2 53 udp dns 0.000423 38 183 SF F 0 Dd 1 66 1 211 -1300475168.901749 slFea8xwSmb 141.142.220.118 56056 141.142.2.2 53 udp dns 0.000402 36 131 SF F 0 Dd 1 64 1 159 -1300475168.902195 UfGkYA2HI2g 141.142.220.118 55092 141.142.2.2 53 udp dns 0.000374 36 198 SF F 0 Dd 1 64 1 226 -1300475169.899438 BWaU4aSuwkc 141.142.220.44 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 85 0 0 -1300475170.862384 10XodEwRycf 141.142.220.226 137 141.142.220.255 137 udp dns 2.613017 350 0 S0 F 0 D 7 546 0 0 -1300475171.675372 zno26fFZkrh fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 0.100096 66 0 S0 F 0 D 2 162 0 0 -1300475171.677081 v5rgkJBig5l 141.142.220.226 55131 224.0.0.252 5355 udp dns 0.100021 66 0 S0 F 0 D 2 122 0 0 -1300475173.116749 eWZCH7OONC1 fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 0.099801 66 0 S0 F 0 D 2 162 0 0 -1300475173.117362 0Pwk3ntf8O3 141.142.220.226 55671 224.0.0.252 5355 udp dns 0.099849 66 0 S0 F 0 D 2 122 0 0 -1300475173.153679 0HKorjr8Zp7 141.142.220.238 56641 141.142.220.255 137 udp dns 0.000000 0 0 S0 F 0 D 1 78 0 0 -1300475168.859163 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 tcp http 0.215893 1130 734 S1 F 0 ShADad 6 1450 4 950 -1300475168.652003 nQcgTWjvg4c 141.142.220.118 35634 208.80.152.2 80 tcp 0.061329 463 350 OTH F 0 DdA 2 567 1 402 -1300475168.895267 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 tcp http 0.227284 1178 734 S1 F 0 ShADad 6 1498 4 950 -1300475168.902635 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 tcp http 0.120041 534 412 S1 F 0 ShADad 4 750 3 576 -1300475168.892936 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 tcp http 0.229603 1148 734 S1 F 0 ShADad 6 1468 4 950 -1300475168.855305 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 tcp http 0.218501 1171 733 S1 F 0 ShADad 6 1491 4 949 -1300475168.892913 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 tcp http 0.220961 1137 733 S1 F 0 ShADad 6 1457 4 949 -1300475169.780331 2cx26uAvUPl 141.142.220.235 6705 173.192.163.128 80 tcp 0.000000 0 0 OTH F 0 h 0 0 1 48 -1300475168.724007 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 tcp http 0.119905 525 232 S1 F 0 ShADad 4 741 3 396 -1300475168.855330 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 tcp http 0.219720 1125 734 S1 F 0 ShADad 6 1445 4 950 +1300475167.096535 CXWv6p3arKYeMETxOg 141.142.220.202 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 73 0 0 +1300475167.097012 CjhGID4nQcgTWjvg4c fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp 0.000000 0 0 S0 F 0 D 1 199 0 0 +1300475167.099816 CCvvfg3TEfuqmmG4bh 141.142.220.50 5353 224.0.0.251 5353 udp 0.000000 0 0 S0 F 0 D 1 179 0 0 +1300475168.853899 CPbrpk1qSsw6ESzHV4 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF F 0 Dd 1 66 1 117 +1300475168.854378 C6pKV8GSxOnSLghOa 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF F 0 Dd 1 80 1 127 +1300475168.854837 CIPOse170MGiRM1Qf4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF F 0 Dd 1 66 1 211 +1300475168.857956 CMXxB5GvmoxJFXdTa 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF F 0 Dd 1 66 1 117 +1300475168.858306 Caby8b1slFea8xwSmb 141.142.220.118 59816 141.142.2.2 53 udp dns 0.000343 52 99 SF F 0 Dd 1 80 1 127 +1300475168.858713 Che1bq3i2rO3KD1Syg 141.142.220.118 59714 141.142.2.2 53 udp dns 0.000375 38 183 SF F 0 Dd 1 66 1 211 +1300475168.891644 CEle3f3zno26fFZkrh 141.142.220.118 58206 141.142.2.2 53 udp dns 0.000339 38 89 SF F 0 Dd 1 66 1 117 +1300475168.892037 CwSkQu4eWZCH7OONC1 141.142.220.118 38911 141.142.2.2 53 udp dns 0.000335 52 99 SF F 0 Dd 1 80 1 127 +1300475168.892414 CfTOmO0HKorjr8Zp7 141.142.220.118 59746 141.142.2.2 53 udp dns 0.000421 38 183 SF F 0 Dd 1 66 1 211 +1300475168.893988 Cab0vO1xNYSS2hJkle 141.142.220.118 45000 141.142.2.2 53 udp dns 0.000384 38 89 SF F 0 Dd 1 66 1 117 +1300475168.894422 Cx2FqO23omNawSNrxj 141.142.220.118 48479 141.142.2.2 53 udp dns 0.000317 52 99 SF F 0 Dd 1 80 1 127 +1300475168.894787 Cx3C534wEyF3OvvcQe 141.142.220.118 48128 141.142.2.2 53 udp dns 0.000423 38 183 SF F 0 Dd 1 66 1 211 +1300475168.901749 CUKS0W3HFYOnBqSE5e 141.142.220.118 56056 141.142.2.2 53 udp dns 0.000402 36 131 SF F 0 Dd 1 64 1 159 +1300475168.902195 CRrfvP2lalMAYOCLhj 141.142.220.118 55092 141.142.2.2 53 udp dns 0.000374 36 198 SF F 0 Dd 1 64 1 226 +1300475169.899438 CojBOU3CXcLHl1r6x1 141.142.220.44 5353 224.0.0.251 5353 udp dns 0.000000 0 0 S0 F 0 D 1 85 0 0 +1300475170.862384 CJzVQRGJrX6V15ik7 141.142.220.226 137 141.142.220.255 137 udp dns 2.613017 350 0 S0 F 0 D 7 546 0 0 +1300475171.675372 ClAbxY1nmdjCuo0Le2 fe80::3074:17d5:2052:c324 65373 ff02::1:3 5355 udp dns 0.100096 66 0 S0 F 0 D 2 162 0 0 +1300475171.677081 CwG0BF1VXE0gWgs78 141.142.220.226 55131 224.0.0.252 5355 udp dns 0.100021 66 0 S0 F 0 D 2 122 0 0 +1300475173.116749 CisNaL1Cm73CiNOmcg fe80::3074:17d5:2052:c324 54213 ff02::1:3 5355 udp dns 0.099801 66 0 S0 F 0 D 2 162 0 0 +1300475173.117362 CBQnJn22qN8TOeeZil 141.142.220.226 55671 224.0.0.252 5355 udp dns 0.099849 66 0 S0 F 0 D 2 122 0 0 +1300475173.153679 CbEsuD3dgDDngdlbKf 141.142.220.238 56641 141.142.220.255 137 udp dns 0.000000 0 0 S0 F 0 D 1 78 0 0 +1300475168.859163 C3SfNE4BWaU4aSuwkc 141.142.220.118 49998 208.80.152.3 80 tcp http 0.215893 1130 734 S1 F 0 ShADad 6 1450 4 950 +1300475168.652003 CsRx2w45OKnoww6xl4 141.142.220.118 35634 208.80.152.2 80 tcp 0.061329 463 350 OTH F 0 DdA 2 567 1 402 +1300475168.895267 CkDsfG2YIeWJmXWNWj 141.142.220.118 50001 208.80.152.3 80 tcp http 0.227284 1178 734 S1 F 0 ShADad 6 1498 4 950 +1300475168.902635 Cn78a440HlxuyZKs6f 141.142.220.118 35642 208.80.152.2 80 tcp http 0.120041 534 412 S1 F 0 ShADad 4 750 3 576 +1300475168.892936 CyAhVIzHqb7t7kv28 141.142.220.118 50000 208.80.152.3 80 tcp http 0.229603 1148 734 S1 F 0 ShADad 6 1468 4 950 +1300475168.855305 C7XEbhP654jzLoe3a 141.142.220.118 49996 208.80.152.3 80 tcp http 0.218501 1171 733 S1 F 0 ShADad 6 1491 4 949 +1300475168.892913 CzA03V1VcgagLjnO92 141.142.220.118 49999 208.80.152.3 80 tcp http 0.220961 1137 733 S1 F 0 ShADad 6 1457 4 949 +1300475169.780331 CUof3F2yAIid8QS3dk 141.142.220.235 6705 173.192.163.128 80 tcp 0.000000 0 0 OTH F 0 h 0 0 1 48 +1300475168.724007 CRJuHdVW0XPVINV8a 141.142.220.118 48649 208.80.152.118 80 tcp http 0.119905 525 232 S1 F 0 ShADad 4 741 3 396 +1300475168.855330 CJ3xTn1c4Zw9TmAE05 141.142.220.118 49997 208.80.152.3 80 tcp http 0.219720 1125 734 S1 F 0 ShADad 6 1445 4 950 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/http.ds.txt b/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/http.ds.txt index fd998057f3..e030dfee42 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/http.ds.txt +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.dataseries.wikipedia/http.ds.txt @@ -67,17 +67,17 @@ # Extent, type='http' ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied orig_fuids orig_mime_types resp_fuids resp_mime_types -1300475168.784020 j4u32Pc5bif 141.142.220.118 48649 208.80.152.118 80 1 GET bits.wikimedia.org /skins-1.5/monobook/main.css http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.916018 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.916183 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.918358 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.952307 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.952296 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/4/4a/Wiktionary-logo-en-35px.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.954820 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikiquote-logo.svg/35px-Wikiquote-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.962687 i2rO3KD1Syg 141.142.220.118 35642 208.80.152.2 80 1 GET meta.wikimedia.org /images/wikimedia-button.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.975934 VW0XPVINV8a 141.142.220.118 49997 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.976436 3PKsZ2Uye21 141.142.220.118 49996 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/d/df/Wikispecies-logo.svg/35px-Wikispecies-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475168.979264 GSxOnSLghOa 141.142.220.118 49998 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4c/Wikisource-logo.svg/35px-Wikisource-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475169.014619 Tw8jXtpTGu6 141.142.220.118 50000 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475169.014593 P654jzLoe3a 141.142.220.118 49999 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 -1300475169.014927 0Q4FH8sESw5 141.142.220.118 50001 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.784020 CRJuHdVW0XPVINV8a 141.142.220.118 48649 208.80.152.118 80 1 GET bits.wikimedia.org /skins-1.5/monobook/main.css http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.916018 CJ3xTn1c4Zw9TmAE05 141.142.220.118 49997 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.916183 C7XEbhP654jzLoe3a 141.142.220.118 49996 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.918358 C3SfNE4BWaU4aSuwkc 141.142.220.118 49998 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.952307 CyAhVIzHqb7t7kv28 141.142.220.118 50000 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.952296 CzA03V1VcgagLjnO92 141.142.220.118 49999 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/4/4a/Wiktionary-logo-en-35px.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.954820 CkDsfG2YIeWJmXWNWj 141.142.220.118 50001 208.80.152.3 80 1 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikiquote-logo.svg/35px-Wikiquote-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.962687 Cn78a440HlxuyZKs6f 141.142.220.118 35642 208.80.152.2 80 1 GET meta.wikimedia.org /images/wikimedia-button.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.975934 CJ3xTn1c4Zw9TmAE05 141.142.220.118 49997 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/f/fa/Wikibooks-logo.svg/35px-Wikibooks-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.976436 C7XEbhP654jzLoe3a 141.142.220.118 49996 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/d/df/Wikispecies-logo.svg/35px-Wikispecies-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475168.979264 C3SfNE4BWaU4aSuwkc 141.142.220.118 49998 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4c/Wikisource-logo.svg/35px-Wikisource-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475169.014619 CyAhVIzHqb7t7kv28 141.142.220.118 50000 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/4/4a/Commons-logo.svg/35px-Commons-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475169.014593 CzA03V1VcgagLjnO92 141.142.220.118 49999 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/9/91/Wikiversity-logo.svg/35px-Wikiversity-logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 +1300475169.014927 CkDsfG2YIeWJmXWNWj 141.142.220.118 50001 208.80.152.3 80 2 GET upload.wikimedia.org /wikipedia/commons/thumb/7/75/Wikimedia_Community_Logo.svg/35px-Wikimedia_Community_Logo.svg.png http://www.wikipedia.org/ Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110303 Ubuntu/10.04 (lucid) Firefox/3.6.15 0 0 304 Not Modified 0 From 8a5a2b5b39e49ac3a79e8396f6f97d44278aee4a Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 27 Aug 2013 12:20:03 -0700 Subject: [PATCH 263/881] add hexstr_to_bytestring bif that does exactly the opposite of bytestring_to_hexstr. --- src/bro.bif | 46 ++++++++++++++++++- .../bifs.hexstr_to_bytestring/.stderr | 1 + .../Baseline/bifs.hexstr_to_bytestring/out | 4 ++ testing/btest/bifs/hexstr_to_bytestring.bro | 12 +++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 testing/btest/Baseline/bifs.hexstr_to_bytestring/.stderr create mode 100644 testing/btest/Baseline/bifs.hexstr_to_bytestring/out create mode 100644 testing/btest/bifs/hexstr_to_bytestring.bro diff --git a/src/bro.bif b/src/bro.bif index e2a4ba62a9..6149c42482 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -2615,7 +2615,7 @@ function addr_to_ptr_name%(a: addr%): string ## ## Returns: The hexadecimal representation of *bytestring*. ## -## .. bro:see:: hexdump +## .. bro:see:: hexdump hexstr_to_bytestring function bytestring_to_hexstr%(bytestring: string%): string %{ bro_uint_t len = bytestring->AsString()->Len(); @@ -2629,6 +2629,50 @@ function bytestring_to_hexstr%(bytestring: string%): string return new StringVal(hexstr); %} +## Converts a hex-string into its binary representation. +## For example, ``"3034"`` would be converted to ``"04"``. +## +## The input string is assumed to only contain 0-9 and a-f, +## otherwhise behavior is undefines. +## +## hexstring: The hexadecimal string representation. +## +## Returns: The binary representation of *hexstring*. +## +## .. bro:see:: hexdump bytestring_to_hexstr +function hexstr_to_bytestring%(hexstr: string%): string + %{ + bro_uint_t len = hexstr->AsString()->Len(); + if ( len % 2 != 0 ) + { + reporter->Error("Hex string '%s' has invalid length (not divisble by 2)", hexstr->CheckString()); + return new StringVal(""); + } + + const char* bytes = hexstr->AsString()->CheckString(); + int outlen = (len/2); + char bytestring[outlen]; + memset(bytestring, 0, outlen); + + for ( bro_uint_t i = 0; i < len/2; ++i ) + { + int res = sscanf(bytes + (2*i), "%2hhx", &bytestring[i]); + if ( res == EOF ) + { + reporter->Error("Hex string %s contains invalid input: %s", hexstr->CheckString(), strerror(errno)); + return new StringVal(""); + } + else if ( res != 1 ) + { + reporter->Error("Could not read hex element from input %s", hexstr->CheckString()); + return new StringVal(""); + } + + } + + return new StringVal(outlen, bytestring); + %} + ## Encodes a Base64-encoded string. ## ## s: The string to encode diff --git a/testing/btest/Baseline/bifs.hexstr_to_bytestring/.stderr b/testing/btest/Baseline/bifs.hexstr_to_bytestring/.stderr new file mode 100644 index 0000000000..71691b5761 --- /dev/null +++ b/testing/btest/Baseline/bifs.hexstr_to_bytestring/.stderr @@ -0,0 +1 @@ +error: Hex string 'a' has invalid length (not divisble by 2) diff --git a/testing/btest/Baseline/bifs.hexstr_to_bytestring/out b/testing/btest/Baseline/bifs.hexstr_to_bytestring/out new file mode 100644 index 0000000000..ccb9c51e7c --- /dev/null +++ b/testing/btest/Baseline/bifs.hexstr_to_bytestring/out @@ -0,0 +1,4 @@ +04 + +\0 + diff --git a/testing/btest/bifs/hexstr_to_bytestring.bro b/testing/btest/bifs/hexstr_to_bytestring.bro new file mode 100644 index 0000000000..f0815a6269 --- /dev/null +++ b/testing/btest/bifs/hexstr_to_bytestring.bro @@ -0,0 +1,12 @@ +# +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out +# @TEST-EXEC: btest-diff .stderr + +event bro_init() + { + print hexstr_to_bytestring("3034"); + print hexstr_to_bytestring(""); + print hexstr_to_bytestring("00"); + print hexstr_to_bytestring("a"); + } From 0cdc8684461fb79f9ce134ab00f0121b4bca6f97 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 27 Aug 2013 14:10:38 -0700 Subject: [PATCH 264/881] Updating submodule(s). [nomail] --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index e94b0d7f83..97b064624a 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit e94b0d7f831fc58abf84dcddafa143cb95e068f2 +Subproject commit 97b064624a93bd0eb9ea258aa441f71054d4438e From ea9cfc749d5e362ed20553111ec1b9fc1291c2d8 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 27 Aug 2013 14:12:20 -0700 Subject: [PATCH 265/881] Updating submodule(s). [nomail] --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index 97b064624a..f66eea64d1 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 97b064624a93bd0eb9ea258aa441f71054d4438e +Subproject commit f66eea64d1bbcbee0e41621e553260cece2a1e48 From 2b78922af8c948797acfe20516bbfe03d154e25f Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 28 Aug 2013 00:57:44 -0400 Subject: [PATCH 266/881] Added a $unique_max field to Reducers for the SumStats::UNIQUE calculation - Using the new option in scan.bro and the FTP bruteforce detection. --- .../frameworks/sumstats/plugins/unique.bro | 33 ++++++++++++++++++- scripts/policy/misc/scan.bro | 4 +-- .../protocols/ftp/detect-bruteforcing.bro | 2 +- .../.stdout | 4 +-- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/scripts/base/frameworks/sumstats/plugins/unique.bro b/scripts/base/frameworks/sumstats/plugins/unique.bro index 011949ce2f..60dec66ae4 100644 --- a/scripts/base/frameworks/sumstats/plugins/unique.bro +++ b/scripts/base/frameworks/sumstats/plugins/unique.bro @@ -3,6 +3,11 @@ module SumStats; export { + redef record Reducer += { + ## Maximum number of unique elements to store. + unique_max: count &optional; + }; + redef enum Calculation += { ## Calculate the number of unique values. UNIQUE @@ -16,6 +21,11 @@ export { } redef record ResultVal += { + # Internal use only. This is used when multiple ResultVals + # are being merged and they need to abide the unique limit + # set in the reducer. + unique_max: count &optional; + # Internal use only. This is not meant to be publically available # because we don't want to trust that we can inspect the values # since we will like move to a probalistic data structure in the future. @@ -29,7 +39,12 @@ hook register_observe_plugins() { if ( ! rv?$unique_vals ) rv$unique_vals=set(); - add rv$unique_vals[obs]; + if ( r?$unique_max ) + rv$unique_max=r$unique_max; + + if ( ! r?$unique_max || |rv$unique_vals| <= r$unique_max ) + add rv$unique_vals[obs]; + rv$unique = |rv$unique_vals|; }); } @@ -38,15 +53,31 @@ hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { if ( rv1?$unique_vals || rv2?$unique_vals ) { + if ( rv1?$unique_max ) + result$unique_max = rv1$unique_max; + else if ( rv2?$unique_max ) + result$unique_max = rv2$unique_max; + if ( rv1?$unique_vals ) result$unique_vals = copy(rv1$unique_vals); if ( rv2?$unique_vals ) + { if ( ! result?$unique_vals ) + { result$unique_vals = copy(rv2$unique_vals); + } else + { for ( val2 in rv2$unique_vals ) + { + if ( result?$unique_max && |result$unique_vals| >= result$unique_max ) + break; + add result$unique_vals[copy(val2)]; + } + } + } result$unique = |result$unique_vals|; } diff --git a/scripts/policy/misc/scan.bro b/scripts/policy/misc/scan.bro index 909ccac02b..b1b63b74da 100644 --- a/scripts/policy/misc/scan.bro +++ b/scripts/policy/misc/scan.bro @@ -52,7 +52,7 @@ export { event bro_init() &priority=5 { - local r1: SumStats::Reducer = [$stream="scan.addr.fail", $apply=set(SumStats::UNIQUE)]; + local r1: SumStats::Reducer = [$stream="scan.addr.fail", $apply=set(SumStats::UNIQUE), $unique_max=double_to_count(addr_scan_threshold+2)]; SumStats::create([$name="addr-scan", $epoch=addr_scan_interval, $reducers=set(r1), @@ -77,7 +77,7 @@ event bro_init() &priority=5 }]); # Note: port scans are tracked similar to: table[src_ip, dst_ip] of set(port); - local r2: SumStats::Reducer = [$stream="scan.port.fail", $apply=set(SumStats::UNIQUE)]; + local r2: SumStats::Reducer = [$stream="scan.port.fail", $apply=set(SumStats::UNIQUE), $unique_max=double_to_count(port_scan_threshold+2)]; SumStats::create([$name="port-scan", $epoch=port_scan_interval, $reducers=set(r2), diff --git a/scripts/policy/protocols/ftp/detect-bruteforcing.bro b/scripts/policy/protocols/ftp/detect-bruteforcing.bro index 36dfafb53a..1af9bb081e 100644 --- a/scripts/policy/protocols/ftp/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ftp/detect-bruteforcing.bro @@ -27,7 +27,7 @@ export { event bro_init() { - local r1: SumStats::Reducer = [$stream="ftp.failed_auth", $apply=set(SumStats::UNIQUE)]; + local r1: SumStats::Reducer = [$stream="ftp.failed_auth", $apply=set(SumStats::UNIQUE), $unique_max=double_to_count(bruteforce_threshold+2)]; SumStats::create([$name="ftp-detect-bruteforcing", $epoch=bruteforce_measurement_interval, $reducers=set(r1), diff --git a/testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/.stdout b/testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/.stdout index 132a1114fc..3afedd785d 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/.stdout +++ b/testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/.stdout @@ -1,6 +1,6 @@ THRESHOLD_SERIES: hit a threshold series value at 3 for sumstats_key(host=1.2.3.4) -THRESHOLD_SERIES: hit a threshold series value at 6 for sumstats_key(host=1.2.3.4) THRESHOLD: hit a threshold value at 6 for sumstats_key(host=1.2.3.4) -THRESHOLD_SERIES: hit a threshold series value at 1001 for sumstats_key(host=7.2.1.5) +THRESHOLD_SERIES: hit a threshold series value at 6 for sumstats_key(host=1.2.3.4) THRESHOLD: hit a threshold value at 1001 for sumstats_key(host=7.2.1.5) +THRESHOLD_SERIES: hit a threshold series value at 1001 for sumstats_key(host=7.2.1.5) THRESHOLD WITH RATIO BETWEEN REDUCERS: hit a threshold value at 55x for sumstats_key(host=7.2.1.5) From 5c119561ad649d303dba82c1cb1ee513a5e22d35 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 28 Aug 2013 15:35:18 -0500 Subject: [PATCH 267/881] UID optimizations addressing BIT-1016. Max UID bit-length is now 128, but can be increased w/ trivial source code change of BRO_UID_LEN. --- scripts/base/init-bare.bro | 1 + src/Conn.cc | 2 +- src/TunnelEncapsulation.cc | 2 +- src/UID.cc | 29 ++++++----------- src/UID.h | 63 ++++++++++++++++++++++++++---------- src/file_analysis/Manager.cc | 5 +-- 6 files changed, 60 insertions(+), 42 deletions(-) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index d22aa067d8..59f13bf2eb 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -3082,6 +3082,7 @@ const global_hash_seed: string = "" &redef; ## Number of bits in UIDs that are generated to identify connections and ## files. The larger the value, the more confidence in UID uniqueness. +## The maximum is currently 128 bits. const bits_per_uid: count = 96 &redef; # Load BiFs defined by plugins. diff --git a/src/Conn.cc b/src/Conn.cc index e653211583..77c854c126 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -378,7 +378,7 @@ RecordVal* Connection::BuildConnVal() conn_val->Assign(8, new StringVal("")); // history if ( ! uid ) - uid = Bro::UID(bits_per_uid); + uid.Set(bits_per_uid); conn_val->Assign(9, new StringVal(uid.Base62("C").c_str())); diff --git a/src/TunnelEncapsulation.cc b/src/TunnelEncapsulation.cc index 6330236dc2..cb4b1eaabe 100644 --- a/src/TunnelEncapsulation.cc +++ b/src/TunnelEncapsulation.cc @@ -11,7 +11,7 @@ EncapsulatingConn::EncapsulatingConn(Connection* c, BifEnum::Tunnel::Type t) { if ( ! uid ) { - uid = Bro::UID(bits_per_uid); + uid.Set(bits_per_uid); c->SetUID(uid); } } diff --git a/src/UID.cc b/src/UID.cc index b7e5d0617c..28675c0376 100644 --- a/src/UID.cc +++ b/src/UID.cc @@ -7,39 +7,30 @@ using namespace Bro; using namespace std; -void UID::Set(bro_uint_t bits, const std::vector& v) +void UID::Set(bro_uint_t bits, const uint64* v, size_t n) { - uid.clear(); + initialized = true; + + for ( size_t i = 0; i < BRO_UID_LEN; ++i ) + uid[i] = 0; + + if ( bits > BRO_UID_LEN * 64 ) + bits = BRO_UID_LEN * 64; div_t res = div(bits, 64); size_t size = res.rem ? res.quot + 1 : res.quot; for ( size_t i = 0; i < size; ++i ) - uid.push_back(i < v.size() ? v[i] : calculate_unique_id()); + uid[i] = v && i < n ? v[i] : calculate_unique_id(); if ( res.rem ) uid[0] >>= 64 - res.rem; } -string UID::Base62(const std::string& prefix) const - { - char tmp[64]; // technically, this should dynamically scale based on size - string rval(prefix); - - for ( size_t i = 0; i < uid.size(); ++i ) - rval.append(uitoa_n(uid[i], tmp, sizeof(tmp), 62)); - - return rval; - } - bool Bro::operator==(const UID& u1, const UID& u2) { - if ( u1.uid.size() != u2.uid.size() ) - return false; - - for ( size_t i = 0; i < u1.uid.size(); ++i ) + for ( size_t i = 0; i < BRO_UID_LEN; ++i ) if ( u1.uid[i] != u2.uid[i] ) return false; - return true; } diff --git a/src/UID.h b/src/UID.h index a9a77dcc90..f7ddec8308 100644 --- a/src/UID.h +++ b/src/UID.h @@ -4,10 +4,12 @@ #define BRO_UID_H #include -#include +#include "Reporter.h" #include "util.h" +#define BRO_UID_LEN 2 + namespace Bro { /** @@ -18,53 +20,54 @@ class UID { public: /** - * Default ctor. The UID is uninitialized and in string format is - * represented by an empty string. + * Default ctor. The UID is uninitialized. */ - UID() {} + UID() : initialized(false) {} /** * Construct a UID of a given bit-length, optionally from given values. * @see UID::Set */ - UID(bro_uint_t bits, const std::vector& v = std::vector()) - { Set(bits, v); } + UID(bro_uint_t bits, const uint64* v = 0, size_t n = 0) + { Set(bits, v, n); } /** * Copy constructor. */ - UID(const UID& other) { uid = other.uid; } + UID(const UID& other); /** * Inititialize a UID of a given bit-length, optionally from given values. - * @param bits The desired length in bits of the UID. - * @param v A vector of values with which to initialize the UID. - * If empty or doesn't contain enough values to satisfy \a bits, - * then values are automatically generated using + * @param bits The desired length in bits of the UID, up to a max of + * BRO_UID_LEN * 64. + * @param v A pointer to an array of values with which to initialize the + * UID. If empty or doesn't contain enough values to satisfy + * \a bits, then values are automatically generated using * calculate_unique_id(). If \a bits isn't evenly divisible by * 64, then a value is truncated to bit in desired bit-length. + * @param n number of 64-bit elements in array pointed to by \a v. */ - void Set(bro_uint_t bits, - const std::vector& v = std::vector()); + void Set(bro_uint_t bits, const uint64* v = 0, size_t n = 0); /** * Returns a base62 (characters 0-9, A-Z, a-z) representation of the UID. * @param prefix An optional string prefix. * @return a base62 string representing the UID. */ - std::string Base62(const std::string& prefix = "") const; + std::string Base62(std::string prefix = "") const; /** * @return false if the UID instance was created via the default ctor * and not yet initialized w/ Set(). * TODO: this would be better as an "explicit" conversion operator (C++11) */ - operator bool() const { return ( ! uid.empty() ); } + operator bool() const + { return initialized; } /** * Assignment operator. */ - UID& operator=(const UID& other) { uid = other.uid; return *this; } + UID& operator=(const UID& other); /** * UID equality operator. @@ -78,11 +81,37 @@ public: { return ! ( u1 == u2 ); } private: - std::vector uid; + uint64 uid[BRO_UID_LEN]; + bool initialized; // Since technically uid == 0 is a legit UID }; bool operator==(const UID& u1, const UID& u2); +inline UID::UID(const UID& other) + { + for ( size_t i = 0; i < BRO_UID_LEN; ++i ) + uid[i] = other.uid[i]; + initialized = other.initialized; + } + +inline UID& UID::operator=(const UID& other) + { + for ( size_t i = 0; i < BRO_UID_LEN; ++i ) + uid[i] = other.uid[i]; + initialized = other.initialized; + return *this; + } + +inline std::string UID::Base62(std::string prefix) const + { + if ( ! initialized ) + reporter->InternalError("use of uninitialized UID"); + char tmp[64]; // technically, this should dynamically scale w/ BRO_UID_LEN + for ( size_t i = 0; i < BRO_UID_LEN; ++i ) + prefix.append(uitoa_n(uid[i], tmp, sizeof(tmp), 62)); + return prefix; + } + } // namespace Bro #endif diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index 77441f8264..8dfb220381 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -64,10 +64,7 @@ string Manager::HashHandle(const string& handle) const MD5(reinterpret_cast(msg.data()), msg.size(), reinterpret_cast(hash)); - vector v; - v.push_back(hash[0]); - v.push_back(hash[1]); - return Bro::UID(bits_per_uid, v).Base62("F"); + return Bro::UID(bits_per_uid, hash, 2).Base62("F"); } void Manager::SetHandle(const string& handle) From 7a2972d0e45ffbd8b536543fdb6d316186175a90 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 28 Aug 2013 16:12:11 -0500 Subject: [PATCH 268/881] Add bits_per_uid unit test, addressing BIT0-1016. --- testing/btest/Baseline/core.bits_per_uid/128 | 9 +++++++++ testing/btest/Baseline/core.bits_per_uid/32 | 9 +++++++++ testing/btest/Baseline/core.bits_per_uid/64 | 9 +++++++++ testing/btest/Baseline/core.bits_per_uid/96 | 9 +++++++++ testing/btest/core/bits_per_uid.bro | 21 ++++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 testing/btest/Baseline/core.bits_per_uid/128 create mode 100644 testing/btest/Baseline/core.bits_per_uid/32 create mode 100644 testing/btest/Baseline/core.bits_per_uid/64 create mode 100644 testing/btest/Baseline/core.bits_per_uid/96 create mode 100644 testing/btest/core/bits_per_uid.bro diff --git a/testing/btest/Baseline/core.bits_per_uid/128 b/testing/btest/Baseline/core.bits_per_uid/128 new file mode 100644 index 0000000000..95ef343262 --- /dev/null +++ b/testing/btest/Baseline/core.bits_per_uid/128 @@ -0,0 +1,9 @@ +CUWkUyAuUGXfarKYeMETxOg +Ck6kgXLOoSKlnQcgTWjvg4c +Cj4u32Pc5bifTEfuqmmG4bh +Fj3nTWNjezo6G6xBmyo58Tf +F4VAnSiNGSQhKEoCPd4zuQd +CFrJExwHcSal5OKnoww6xl4 +C3PKsZ2Uye21VW0XPVINV8a +FaJg8mtdsS86cWjSe4spPPl +FvBr89nD30GgGAp3wgtm6qf diff --git a/testing/btest/Baseline/core.bits_per_uid/32 b/testing/btest/Baseline/core.bits_per_uid/32 new file mode 100644 index 0000000000..a20d05dbd5 --- /dev/null +++ b/testing/btest/Baseline/core.bits_per_uid/32 @@ -0,0 +1,9 @@ +CXWv6p30 +CCyvnA30 +CjhGID40 +F75yAm10 +FmGk6O30 +CdfHBz20 +CCvvfg30 +Fuh3fj10 +Ftwuyy30 diff --git a/testing/btest/Baseline/core.bits_per_uid/64 b/testing/btest/Baseline/core.bits_per_uid/64 new file mode 100644 index 0000000000..b34eb4879d --- /dev/null +++ b/testing/btest/Baseline/core.bits_per_uid/64 @@ -0,0 +1,9 @@ +CUWkUyAuUGXf0 +CarKYeMETxOg0 +Ck6kgXLOoSKl0 +Fj3nTWNjezo60 +F4VAnSiNGSQh0 +CnQcgTWjvg4c0 +Cj4u32Pc5bif0 +FaJg8mtdsS860 +FvBr89nD30Gg0 diff --git a/testing/btest/Baseline/core.bits_per_uid/96 b/testing/btest/Baseline/core.bits_per_uid/96 new file mode 100644 index 0000000000..3ba0f50e04 --- /dev/null +++ b/testing/btest/Baseline/core.bits_per_uid/96 @@ -0,0 +1,9 @@ +CXWv6p3arKYeMETxOg +CjhGID4nQcgTWjvg4c +CCvvfg3TEfuqmmG4bh +F75yAm1G6xBmyo58Tf +FmGk6O3KEoCPd4zuQd +CsRx2w45OKnoww6xl4 +CRJuHdVW0XPVINV8a +Fuh3fj1cWjSe4spPPl +Ftwuyy3GAp3wgtm6qf diff --git a/testing/btest/core/bits_per_uid.bro b/testing/btest/core/bits_per_uid.bro new file mode 100644 index 0000000000..6e997907de --- /dev/null +++ b/testing/btest/core/bits_per_uid.bro @@ -0,0 +1,21 @@ +# @TEST-EXEC: bro -r $TRACES/ftp/ipv4.trace %INPUT bits_per_uid=32 >32 +# @TEST-EXEC: btest-diff 32 +# @TEST-EXEC: bro -r $TRACES/ftp/ipv4.trace %INPUT bits_per_uid=64 >64 +# @TEST-EXEC: btest-diff 64 +# @TEST-EXEC: bro -r $TRACES/ftp/ipv4.trace %INPUT bits_per_uid=96 >96 +# @TEST-EXEC: btest-diff 96 +# @TEST-EXEC: bro -r $TRACES/ftp/ipv4.trace %INPUT bits_per_uid=128 >128 +# @TEST-EXEC: btest-diff 128 +# @TEST-EXEC: bro -r $TRACES/ftp/ipv4.trace %INPUT bits_per_uid=256 >256 +# @TEST-EXEC: btest-diff 256 +# @TEST-EXEC: cmp 128 256 + +event new_connection(c: connection) + { + print c$uid; + } + +event file_new(f: fa_file) + { + print f$id; + } From f8c9d5e3d30cb7f87535fb9edd5b9ed5a2c079a6 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 28 Aug 2013 14:36:59 -0700 Subject: [PATCH 269/881] Adding lines in scripting/index.txt. No other change. --- doc/scripting/index.rst | 930 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 845 insertions(+), 85 deletions(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index a91a716189..0610589004 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -8,90 +8,249 @@ Writing Bro Scripts Understanding Bro Scripts ========================= -Bro includes an event queue driven scripting language that provides the primary means for an organization to extend and customize Bro's functionality. An overwhelming amount of the output generated by Bro is, in fact, generated by Bro scripts. It's almost easier to consider Bro to be an entity behind-the-scenes processing connections and generating events while Bro's scripting language is the medium through which we mere mortals can achieve communication. Bro scripts effectively notify Bro that should there be an event of a type we define, then let us have the information about the connection so we can perform some function on it. For example, the ssl.log file is generated by a Bro script that walks the entire certificate chain and issues notifications if any of the steps along the certificate chain are invalid. This entire process is setup by telling Bro that should it see a server or client issue an SSL HELLO message, we want to know about the information about that connection. +Bro includes an event queue driven scripting language that provides +the primary means for an organization to extend and customize Bro's +functionality. An overwhelming amount of the output generated by Bro +is, in fact, generated by Bro scripts. It's almost easier to consider +Bro to be an entity behind-the-scenes processing connections and +generating events while Bro's scripting language is the medium through +which we mere mortals can achieve communication. Bro scripts +effectively notify Bro that should there be an event of a type we +define, then let us have the information about the connection so we +can perform some function on it. For example, the ssl.log file is +generated by a Bro script that walks the entire certificate chain and +issues notifications if any of the steps along the certificate chain +are invalid. This entire process is setup by telling Bro that should +it see a server or client issue an SSL HELLO message, we want to know +about the information about that connection. -It's often easier to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the Team Cymru Malware hash registry for detected downloads via HTTP. Part of the Team Cymru Malware Hash registry includes the ability to do a host lookup on a domain with the format MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or sha1 hash of a file. Team Cymru also populates the TXT record of their DNS responses with both a "last seen" timestamp and a numerical "detection rate". The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script ``detect-MHR.bro`` is responsible for generating the appropriate DNS lookup and parsing the response. +It's often easier to understand Bro's scripting language by looking at +a complete script and breaking it down into its identifiable +components. In this example, we'll take a look at how Bro queries the +Team Cymru Malware hash registry for detected downloads via HTTP. Part +of the Team Cymru Malware Hash registry includes the ability to do a +host lookup on a domain with the format +MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or +sha1 hash of a file. Team Cymru also populates the TXT record of +their DNS responses with both a "last seen" timestamp and a numerical +"detection rate". The important aspect to understand is Bro already +generates hashes for files it can parse from HTTP streams, but the +script ``detect-MHR.bro`` is responsible for generating the +appropriate DNS lookup and parsing the response. .. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: -Visually, there are three distinct sections of the script. A base level with no indentation followed by an indented and formatted section explaining the custom variables being set (export) and another indented and formatted section describing the instructions for a specific event (event log_http). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. +Visually, there are three distinct sections of the script. A base +level with no indentation followed by an indented and formatted +section explaining the custom variables being set (export) and another +indented and formatted section describing the instructions for a +specific event (event log_http). Don't get discouraged if you don't +understand every section of the script; we'll cover the basics of the +script and much more in following sections. .. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: :lines: 7-11 -Lines 7 and 8 of the script process the ``__load__.bro`` script in the respective directories being loaded. The ``@load`` directives are often considered good practice or even just good manners when writing Bro scripts that might be distributed. While it's unlikely that in a full production deployment of Bro these additional resources wouldn't already be loaded, it's not a bad habit to try to get into as you get more experienced with Bro scripting. If you're just starting out, this level of granularity might not be entirely necessary though. +Lines 7 and 8 of the script process the ``__load__.bro`` script in the +respective directories being loaded. The ``@load`` directives are +often considered good practice or even just good manners when writing +Bro scripts that might be distributed. While it's unlikely that in a +full production deployment of Bro these additional resources wouldn't +already be loaded, it's not a bad habit to try to get into as you get +more experienced with Bro scripting. If you're just starting out, +this level of granularity might not be entirely necessary though. .. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: :lines: 12-24 -The export section redefines an enumerable constant that describes the type of notice we will generate with the logging framework. Bro allows for redefinable constants, which at first, might seem counter-intuitive. We'll get more indepth with constants in a later chapter, for now, think of them as variables that can only be altered before Bro starts running. The notice type listed allows for the use of the NOTICE() function to generate notices of type Malware_Hash_Registry_Match as done in the next section. Notices allow Bro to generate some kind of extra notification beyond its default log types. Often times, this extra notification comes in the form of an email generated and sent to a pre-configured address. +The export section redefines an enumerable constant that describes the +type of notice we will generate with the logging framework. Bro +allows for redefinable constants, which at first, might seem +counter-intuitive. We'll get more indepth with constants in a later +chapter, for now, think of them as variables that can only be altered +before Bro starts running. The notice type listed allows for the use +of the NOTICE() function to generate notices of type +Malware_Hash_Registry_Match as done in the next section. Notices +allow Bro to generate some kind of extra notification beyond its +default log types. Often times, this extra notification comes in the +form of an email generated and sent to a pre-configured address. .. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro :language: bro :linenos: :lines: 26-44 -The workhorse of the script is contained in the event handler for ``log_http``. The ``log_http`` event is defined as an event-hook in the base/protocols/http/main.bro script and allows scripts to handle a connection as it is being passed to the logging framework. The event handler is passed an HTTP::Info data structure which will be referred to as "rec" in body of the event handler. +The workhorse of the script is contained in the event handler for +``log_http``. The ``log_http`` event is defined as an event-hook in +the base/protocols/http/main.bro script and allows scripts to handle a +connection as it is being passed to the logging framework. The event +handler is passed an HTTP::Info data structure which will be referred +to as "rec" in body of the event handler. -An if statement is used to check for the existence of a data structure named "md5" nested within the rec data structure. Bro uses the "$" as a deference operator and as such, and it is employed in this script to check if rec$md5 is present by including the "?" operator within the path. If the rec data structure includes a nested data structure named "md5", the statement is processed as true and a local variable named "hash_domain" is provisioned and given a format string based on the contents of rec$md5 to produce a valid DNS lookup. +An if statement is used to check for the existence of a data structure +named "md5" nested within the rec data structure. Bro uses the "$" as +a deference operator and as such, and it is employed in this script to +check if rec$md5 is present by including the "?" operator within the +path. If the rec data structure includes a nested data structure +named "md5", the statement is processed as true and a local variable +named "hash_domain" is provisioned and given a format string based on +the contents of rec$md5 to produce a valid DNS lookup. -The rest of the script is contained within a when() block. In short, a when block is used when Bro needs to perform asynchronous actions, such a DNS lookup, to ensure that performance isn't effected. The when() block performs a DNS TXT lookup and stores the result in the local variable MHR_result. Effectively, processing for this event continues and upon receipt of the values returned by lookup_hostname_txt(), the when block is executed. The when block splits the string returned into two seperate values and checks to ensure an expected format. If the format is invalid, the script assumes that the hash wasn't found in the respository and processing is concluded. If the format is as expected and the detection rate is above the threshold set by MHR_threshold, two new local variables are created and used in the notice issued by NOTICE(). +The rest of the script is contained within a when() block. In short, +a when block is used when Bro needs to perform asynchronous actions, +such a DNS lookup, to ensure that performance isn't effected. The +when() block performs a DNS TXT lookup and stores the result in the +local variable MHR_result. Effectively, processing for this event +continues and upon receipt of the values returned by +lookup_hostname_txt(), the when block is executed. The when block +splits the string returned into two seperate values and checks to +ensure an expected format. If the format is invalid, the script +assumes that the hash wasn't found in the respository and processing +is concluded. If the format is as expected and the detection rate is +above the threshold set by MHR_threshold, two new local variables are +created and used in the notice issued by NOTICE(). -In approximately 15 lines of actual code, Bro provides an amazing utility that would be incredibly difficult to implement and deploy with other products. In truth, claiming that Bro does this in 15 lines is a misdirection; There is a truly massive number of things going on behind-the-scenes in Bro, but it is the inclusion of the scripting language that gives analysts access to those underlying layers in a succinct and well defined manner. +In approximately 15 lines of actual code, Bro provides an amazing +utility that would be incredibly difficult to implement and deploy +with other products. In truth, claiming that Bro does this in 15 +lines is a misdirection; There is a truly massive number of things +going on behind-the-scenes in Bro, but it is the inclusion of the +scripting language that gives analysts access to those underlying +layers in a succinct and well defined manner. The Event Queue and Event Handlers ================================== -Bro's scripting language is event driven which is a gear change from the majority of scripting languages with which most users will have previous experience. Scripting in Bro depends on handling the events generated by Bro as it processes network traffic, altering the state of data structures through those events, and making decisions on the information provided. This approach to scripting can often cause confusion to users who come to Bro from a procedural or functional language, but once the initial shock wears off it becomes more clear with each exposure. +Bro's scripting language is event driven which is a gear change from +the majority of scripting languages with which most users will have +previous experience. Scripting in Bro depends on handling the events +generated by Bro as it processes network traffic, altering the state +of data structures through those events, and making decisions on the +information provided. This approach to scripting can often cause +confusion to users who come to Bro from a procedural or functional +language, but once the initial shock wears off it becomes more clear +with each exposure. -Bro's core acts to place events into an ordered "event queue", allowing event handlers to process them on a first-come-first-serve basis. In effect, this is Bro's core functionality as without the scripts written to perform discrete actions on events, there would be little to no usable output. As such, a basic understanding of the event queue, the events being generated, and the way in which event handlers process those events is a basis for not only learning to write scripts for Bro but for understanding Bro itself. +Bro's core acts to place events into an ordered "event queue", +allowing event handlers to process them on a first-come-first-serve +basis. In effect, this is Bro's core functionality as without the +scripts written to perform discrete actions on events, there would be +little to no usable output. As such, a basic understanding of the +event queue, the events being generated, and the way in which event +handlers process those events is a basis for not only learning to +write scripts for Bro but for understanding Bro itself. -Gaining familiarity with the specific events generated by Bro is a big step towards building a mind set for working with Bro scripts. The majority of events generated by Bro are defined in the built-in-function files or .bif files which also act as the basis for online event documentation. These in-line comments are compiled into an online documentation system using Broxygen. Whether starting a script from scratch or reading and maintaining someone else's script, having the built-in event definitions available is an excellent resource to have on hand. For the 2.0 release the Bro developers put significant effort into organization and documentation of every event. This effort resulted in built-in-function files organized such that each entry contains a descriptive event name, the arguments passed to the event, and a concise explanation of the functions use. +Gaining familiarity with the specific events generated by Bro is a big +step towards building a mind set for working with Bro scripts. The +majority of events generated by Bro are defined in the +built-in-function files or .bif files which also act as the basis for +online event documentation. These in-line comments are compiled into +an online documentation system using Broxygen. Whether starting a +script from scratch or reading and maintaining someone else's script, +having the built-in event definitions available is an excellent +resource to have on hand. For the 2.0 release the Bro developers put +significant effort into organization and documentation of every event. +This effort resulted in built-in-function files organized such that +each entry contains a descriptive event name, the arguments passed to +the event, and a concise explanation of the functions use. .. literalinclude:: ../../../../build/src/base/event.bif.bro :language: bro :linenos: :lines: 4124-4149 -Above is a segment of the documentation for the event dns_request(). It's organized such that the documentation, commentary, and list of arguments precede the actual event definition used by Bro. As Bro detects DNS requests being issued by an originator, it issues this event and any number of scripts then have access to the data Bro passes along with the event. In this example, Bro passes not only the message, the query, query type and query class for the DNS request, but also a then record used for the connection itself. +Above is a segment of the documentation for the event dns_request(). +It's organized such that the documentation, commentary, and list of +arguments precede the actual event definition used by Bro. As Bro +detects DNS requests being issued by an originator, it issues this +event and any number of scripts then have access to the data Bro +passes along with the event. In this example, Bro passes not only the +message, the query, query type and query class for the DNS request, +but also a then record used for the connection itself. The Connection Record Data Type =============================== -Of all the events defined by Bro, an overwhelmingly large number of them are passed the connection record data type, in effect, making it the backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. Let's walk through the process of selecting an appropriate event, generating some output to standard out and dissecting the connection record so as to get an overview of it. We will cover data types in more detail later. +Of all the events defined by Bro, an overwhelmingly large number of +them are passed the connection record data type, in effect, making it +the backbone of many scripting solutions. The connection record +itself, as we will see in a moment, is a mass of nested data types +used to track state on a connection through its lifetime. Let's walk +through the process of selecting an appropriate event, generating some +output to standard out and dissecting the connection record so as to +get an overview of it. We will cover data types in more detail later. -While Bro is capable of packet level processing, its strengths lay in the context of a connection between an originator and a responder. As such, there are events defined for the primary parts of the connection life-cycle as you'll see from the small selection of connection-related events below. +While Bro is capable of packet level processing, its strengths lay in +the context of a connection between an originator and a responder. As +such, there are events defined for the primary parts of the connection +life-cycle as you'll see from the small selection of +connection-related events below. .. literalinclude:: ../../../../build/src/base/event.bif.bro :language: bro :linenos: :lines: 135-138,154,204-208,218,255-256,266,335-340,351 -Of the events listed, the event that will give us the best insight into the connection record data type will be connection_state_remove(). As detailed in the in-line documentation, Bro generates this event just before it decides to remove this event from memory, effectively forgetting about it. Let's take a look at a simple script that will output the connection record for a single connection. +Of the events listed, the event that will give us the best insight +into the connection record data type will be +connection_state_remove(). As detailed in the in-line documentation, +Bro generates this event just before it decides to remove this event +from memory, effectively forgetting about it. Let's take a look at a +simple script that will output the connection record for a single +connection. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_01.bro :language: bro :linenos: :lines: 4-9 -Again, we start with @load, this time importing the base/protocols/conn scripts which supply the tracking and logging of general information and state of connections. We handle the connection_state_remove() event and simply print the contents of the argument passed to it. For this example we're going to run Bro in "bare mode" which loads only the minimum number of scripts to retain operability and leaves the burden of loading required scripts to the script being run. While bare mode is a low level functionality incorporated into Bro, in this case, we're going to use it to demonstrate how different features of Bro add more and more layers of information about a connection. This will give us a chance to see the contents of the connection record without it being overly populated. +Again, we start with @load, this time importing the +base/protocols/conn scripts which supply the tracking and logging of +general information and state of connections. We handle the +connection_state_remove() event and simply print the contents of the +argument passed to it. For this example we're going to run Bro in +"bare mode" which loads only the minimum number of scripts to retain +operability and leaves the burden of loading required scripts to the +script being run. While bare mode is a low level functionality +incorporated into Bro, in this case, we're going to use it to +demonstrate how different features of Bro add more and more layers of +information about a connection. This will give us a chance to see the +contents of the connection record without it being overly populated. .. btest:: connection-record-01 @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_01.bro -As you can see from the output, the connection record is something of a jumble when printed on its own. Regularly taking a peek at a populated connection record helps to understand the relationship between its fields as well as allowing an opportunity to build a frame of reference for accessing data in a script. +As you can see from the output, the connection record is something of +a jumble when printed on its own. Regularly taking a peek at a +populated connection record helps to understand the relationship +between its fields as well as allowing an opportunity to build a frame +of reference for accessing data in a script. -Bro makes extensive use of nested data structures to store state and information gleaned from the analysis of a connection as a complete unit. To break down this collection of information, you will have to make use of use Bro's field delimiter the "$". For example, the originating host is referenced by c$id$orig_h which if given a narritive relates to "``orig_h`` which is a member of ``id`` which is a member of the data structure referred to as ``c`` that was passed into the event handler." Given that the responder port (``c$id$resp_p``) is 53/tcp, it's likely that Bro's base DNS scripts can further populate the connection record. Let's load the ``base/protocols/dns`` scripts and check the output of our script. +Bro makes extensive use of nested data structures to store state and +information gleaned from the analysis of a connection as a complete +unit. To break down this collection of information, you will have to +make use of use Bro's field delimiter the "$". For example, the +originating host is referenced by c$id$orig_h which if given a +narritive relates to "``orig_h`` which is a member of ``id`` which is +a member of the data structure referred to as ``c`` that was passed +into the event handler." Given that the responder port +(``c$id$resp_p``) is 53/tcp, it's likely that Bro's base DNS scripts +can further populate the connection record. Let's load the +``base/protocols/dns`` scripts and check the output of our script. -Bro uses the dollar sign as its field delimiter and a direct correlation exists between the output of the connection record and the proper format of a dereferenced variable in scripts. In the output of the script above, groups of information are collected between brackets, which would correspond to the $-delimiter in a Bro script. +Bro uses the dollar sign as its field delimiter and a direct +correlation exists between the output of the connection record and the +proper format of a dereferenced variable in scripts. In the output of +the script above, groups of information are collected between +brackets, which would correspond to the $-delimiter in a Bro script. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_02.bro :language: bro @@ -102,7 +261,19 @@ Bro uses the dollar sign as its field delimiter and a direct correlation exists @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_02.bro -The addition of the ``base/protocols/dns`` scripts populates the dns=[] member of the connection record. While Bro is doing a massive amount of work in the background, it is in what is commonly called "script land" that details are being refined and decisions being made. Were we to continue running in "bare mode" we could slowly keep adding infrastructure through ``@load`` statements. For example, were we to ``@load base/frameworks/logging``, Bro would generate a conn.log and dns.log for us in the current working directory. As mentioned above, including the appropriate ``@load`` statements is not only good practice, but can also help to indicate which functionalities are being used in a script. Take a second to run the script with the ``-b`` flag and check the output when all of Bro's functionality is applied to the tracefile. +The addition of the ``base/protocols/dns`` scripts populates the +dns=[] member of the connection record. While Bro is doing a massive +amount of work in the background, it is in what is commonly called +"script land" that details are being refined and decisions being made. +Were we to continue running in "bare mode" we could slowly keep adding +infrastructure through ``@load`` statements. For example, were we to +``@load base/frameworks/logging``, Bro would generate a conn.log and +dns.log for us in the current working directory. As mentioned above, +including the appropriate ``@load`` statements is not only good +practice, but can also help to indicate which functionalities are +being used in a script. Take a second to run the script with the +``-b`` flag and check the output when all of Bro's functionality is +applied to the tracefile. Data Types and Data Structures ============================== @@ -110,7 +281,15 @@ Data Types and Data Structures Scope ----- -Before embarking on a exploration of Bro's native Data Types and Data Structures, it's important to have a good grasp of the different levels of scope available in Bro and the appropriate times to use them within a script. The declarations of variables in Bro come in two forms. Variables can be declared with or without a definition in the form "SCOPE name: TYPE" or "SCOPE name = EXPRESSION" respectively; each of which produce the same result if EXPRESSION evaluates to the same type as TYPE. The decision as to which type of declaration to use is likely to be dictated by personal preference and readability. +Before embarking on a exploration of Bro's native Data Types and Data +Structures, it's important to have a good grasp of the different +levels of scope available in Bro and the appropriate times to use them +within a script. The declarations of variables in Bro come in two +forms. Variables can be declared with or without a definition in the +form "SCOPE name: TYPE" or "SCOPE name = EXPRESSION" respectively; +each of which produce the same result if EXPRESSION evaluates to the +same type as TYPE. The decision as to which type of declaration to +use is likely to be dictated by personal preference and readability. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_declaration.bro :language: bro @@ -120,35 +299,80 @@ Before embarking on a exploration of Bro's native Data Types and Data Structures Global Variables ~~~~~~~~~~~~~~~~ -A global variable is used when the state of variable needs to be tracked, not surprisingly, globally. While there are some caveats, when a script declares a variable using the global scope, that script is granting access to that variable from other scripts. However, when a script uses the ``module`` keyword to give the script a namespace, more care must be given to the declaration of globals to ensure the intended result. When a global is declared in a script with a namespace there are two possible outcomes. First, the variable is available only within the context of the namespace. In this scenario, other scripts within the same namespace will have access to the varaible declared while scripts using a different namespace or no namespace altogether will not have access to the variable. Alternatively, if a global variable is declared within an ``export{}`` block that variable is available to any other script through the naming convention of ``MODULE::variable_name``. +A global variable is used when the state of variable needs to be +tracked, not surprisingly, globally. While there are some caveats, +when a script declares a variable using the global scope, that script +is granting access to that variable from other scripts. However, when +a script uses the ``module`` keyword to give the script a namespace, +more care must be given to the declaration of globals to ensure the +intended result. When a global is declared in a script with a +namespace there are two possible outcomes. First, the variable is +available only within the context of the namespace. In this scenario, +other scripts within the same namespace will have access to the +varaible declared while scripts using a different namespace or no +namespace altogether will not have access to the variable. +Alternatively, if a global variable is declared within an ``export{}`` +block that variable is available to any other script through the +naming convention of ``MODULE::variable_name``. -The declaration below, is a taken from the ``known-hosts.bro`` script and declares a variable called "known_hosts"" as a global set of unique ip addresses(line 32) within the "Known" namespace (line 8) and exports it (line 10) for use outside of the "Known" namespace. Were we to want to use the "known_hosts" variable we'd be able to access it through ``Known::known_hosts``. +The declaration below, is a taken from the ``known-hosts.bro`` script +and declares a variable called "known_hosts"" as a global set of +unique ip addresses(line 32) within the "Known" namespace (line 8) and +exports it (line 10) for use outside of the "Known" namespace. Were +we to want to use the "known_hosts" variable we'd be able to access it +through ``Known::known_hosts``. .. literalinclude:: ../scripts/policy/protocols/conn/known-hosts.bro :language: bro :linenos: :lines: 8-10, 32, 37 -The sample above also makes use of an export{} block. When the module keyword is used in a script, the variables declared are said to be in that module's "namespace". Where as a global variable can be accessed by its name alone when it is not declared within a module, a global variable declared within a module must be exported and then accessed via MODULE_NAME::VARIABLE_NAME. As in the example above, we would be able to access the "known_hosts" in a separate script variable via "Known::known_hosts" due to the fact that known_hosts was declared as a global variable within an export block under the "Known" namespace. +The sample above also makes use of an export{} block. When the module +keyword is used in a script, the variables declared are said to be in +that module's "namespace". Where as a global variable can be accessed +by its name alone when it is not declared within a module, a global +variable declared within a module must be exported and then accessed +via MODULE_NAME::VARIABLE_NAME. As in the example above, we would be +able to access the "known_hosts" in a separate script variable via +"Known::known_hosts" due to the fact that known_hosts was declared as +a global variable within an export block under the "Known" namespace. + Constants ~~~~~~~~~ -Bro also makes use of constants which are denoted by the "const" keyword. Unlike globals, constants can only be set or altered at parse time if the &redef attribute has been used. Afterwards (in runtime) the constants are unalterable. In most cases, redefinable constants are used in Bro scripts as containers for configuration options. For example, the configuration option to log password decrypted from HTTP streams is stored in ``HTTP::default_capture_password`` as shown in the stripped down excerpt from ``http/main.bro`` below. +Bro also makes use of constants which are denoted by the "const" +keyword. Unlike globals, constants can only be set or altered at +parse time if the &redef attribute has been used. Afterwards (in +runtime) the constants are unalterable. In most cases, redefinable +constants are used in Bro scripts as containers for configuration +options. For example, the configuration option to log password +decrypted from HTTP streams is stored in +``HTTP::default_capture_password`` as shown in the stripped down +excerpt from ``http/main.bro`` below. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro :language: bro :linenos: :lines: 8-10,19,20,74 -Because the constant was declared with the ``&redef`` attribute, if we needed to turn this option on globally, we could do so by adding the following line to our ``site/local.bro`` file before firing up Bro. +Because the constant was declared with the ``&redef`` attribute, if we +needed to turn this option on globally, we could do so by adding the +following line to our ``site/local.bro`` file before firing up Bro. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const_simple.bro :language: bro :lines: 6 -While the idea of a redefinable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the "&redef" attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added to the table through redef statements. The table is then printed in a bro_init() event. Were we to try to alter the table in an event handler, Bro would notify the user of an error and the script would fail. +While the idea of a redefinable constant might be odd, the constraint +that constants can only be altered at parse-time remains even with the +"&redef" attribute. In the code snippet below, a table of strings +indexed by ports is declared as a constant before two values are added +to the table through redef statements. The table is then printed in a +bro_init() event. Were we to try to alter the table in an event +handler, Bro would notify the user of an error and the script would +fail. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const.bro :language: bro @@ -162,7 +386,27 @@ While the idea of a redefinable constant might be odd, the constraint that const Local Variables ~~~~~~~~~~~~~~~ -Whereas globals and constants are widely available in scriptland through various means, when a variable is defined with a local scope, its availability is restricted to the body of the event or function in which it was declared. Local variables tend to be used for values that are only needed within a specific scope and once the processing of a script passes beyond that scope and no longer used, the variable is deleted. While it is possible for a function to return a locally scoped variable, in doing so it retuns the value instead of the variable. Bro maintains a difference between variables an example of which is illustrated below. The script executes the event handler "bro_init()" which in turn calls the function "add_two(i: count)" with an argument of 10. Once Bro enters the add_two function, it provisions a locally scoped variable called "added_two" to hold the value of i+2, in this case, 12. The add_two function then prints the value of the added_two variable and returns its value to the bro_init() event handler. At this point, the variable "added_two" has fallen out of scope and no longer exists while the value 12 is still in use and stored in the locally scoped variable "test". When Bro finishes processing the bro_init function, the variable called "test" is no longer in scope and, since there exist no other references to the value "12", the value is also deleted. +Whereas globals and constants are widely available in scriptland +through various means, when a variable is defined with a local scope, +its availability is restricted to the body of the event or function in +which it was declared. Local variables tend to be used for values +that are only needed within a specific scope and once the processing +of a script passes beyond that scope and no longer used, the variable +is deleted. While it is possible for a function to return a locally +scoped variable, in doing so it retuns the value instead of the +variable. Bro maintains a difference between variables an example of +which is illustrated below. The script executes the event handler +"bro_init()" which in turn calls the function "add_two(i: count)" with +an argument of 10. Once Bro enters the add_two function, it +provisions a locally scoped variable called "added_two" to hold the +value of i+2, in this case, 12. The add_two function then prints the +value of the added_two variable and returns its value to the +bro_init() event handler. At this point, the variable "added_two" has +fallen out of scope and no longer exists while the value 12 is still +in use and stored in the locally scoped variable "test". When Bro +finishes processing the bro_init function, the variable called "test" +is no longer in scope and, since there exist no other references to +the value "12", the value is also deleted. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_local.bro :language: bro @@ -173,9 +417,22 @@ Whereas globals and constants are widely available in scriptland through various Data Structures --------------- -It's difficult to talk about Bro's data types in a practical manner without first covering the data structures available in Bro. Some of the more interesting characteristics of data types are revealed when used inside of a data structure, but given that data structures are made up of data types, it devolved rather quickly into a "chicken-and-egg"" problem. As such, we'll introduce data types from bird's eye view before diving into data structures and from there a more complete exploration of data types. +It's difficult to talk about Bro's data types in a practical manner +without first covering the data structures available in Bro. Some of +the more interesting characteristics of data types are revealed when +used inside of a data structure, but given that data structures are +made up of data types, it devolved rather quickly into a +"chicken-and-egg"" problem. As such, we'll introduce data types from +bird's eye view before diving into data structures and from there a +more complete exploration of data types. -The table below shows the atomic types used in Bro, of which, the first four should seem familiar if you have some scripting experience, while the remaining six are less common in other languages. It should come as no surprise that a scripting language for a Network Security Monitoring platform has a fairly robust set of network centric data types and taking note of them here may well save you a late night of reinventing the wheel. +The table below shows the atomic types used in Bro, of which, the +first four should seem familiar if you have some scripting experience, +while the remaining six are less common in other languages. It should +come as no surprise that a scripting language for a Network Security +Monitoring platform has a fairly robust set of network centric data +types and taking note of them here may well save you a late night of +reinventing the wheel. +-----------+-------------------------------------+ | Data Type | Description | @@ -204,23 +461,51 @@ The table below shows the atomic types used in Bro, of which, the first four sho Sets ~~~~ -Sets in Bro are used to stored a unique elements of the same data type. In essence, you can think of them as "a unique set of integers" or "a unique set of ip addresses". While the declaration of a set may differ based on the data type being collected, the set will always contain unique elements and the elements in the set will always be of the same data type. Such requirements make the set data type perfect for information that is already naturally unique such as ports or ip addresses. The code snippet below shows both an explicit and implicit declaration of a locally scoped set. +Sets in Bro are used to stored a unique elements of the same data +type. In essence, you can think of them as "a unique set of integers" +or "a unique set of ip addresses". While the declaration of a set may +differ based on the data type being collected, the set will always +contain unique elements and the elements in the set will always be of +the same data type. Such requirements make the set data type perfect +for information that is already naturally unique such as ports or ip +addresses. The code snippet below shows both an explicit and implicit +declaration of a locally scoped set. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro :language: bro :linenos: :lines: 6,7 -As you can see, sets are declared using the format "SCOPE var_name: set[TYPE]". Adding and removing elements in a set is achieved using the add and delete statements. Once you have elements inserted into the set, it's likely that you'll need to either iterate over that set or test for membership within the set, both of which are covered by the in operator. In the case of iterating over a set, combining the for statement and the in operator will allow you to sequentially process each element of the set as seen below. +As you can see, sets are declared using the format "SCOPE var_name: +set[TYPE]". Adding and removing elements in a set is achieved using +the add and delete statements. Once you have elements inserted into +the set, it's likely that you'll need to either iterate over that set +or test for membership within the set, both of which are covered by +the in operator. In the case of iterating over a set, combining the +for statement and the in operator will allow you to sequentially +process each element of the set as seen below. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro :language: bro :linenos: :lines: 21-29 -Here, the for statement loops over the contents of the set storing each element in the temporary variable "i". With each iteration of the for loop, the next element is chosen. Since sets are not an ordered data type, you cannot guarantee the order of the elements as the for loop processes. +Here, the for statement loops over the contents of the set storing +each element in the temporary variable "i". With each iteration of +the for loop, the next element is chosen. Since sets are not an +ordered data type, you cannot guarantee the order of the elements as +the for loop processes. -To test for membership in a set the in statment can be combined with an if statement to return a true or false value. If the exact element in the condition is already in the set, the condition returns true and the body executes. The in statement can also be negated by the ! operator to create the inverse of the condition. While line 16 of the code snippet below could be rewrite as "if (!( 587/tcp in ssl_ports ))" try to avoid using this construct; instead, negate the in operator itself. While the functionality is the same, using the "!in" is more efficient as well as a more natural construct which will aid in the readability of your script. +To test for membership in a set the in statment can be combined with +an if statement to return a true or false value. If the exact element +in the condition is already in the set, the condition returns true and +the body executes. The in statement can also be negated by the ! +operator to create the inverse of the condition. While line 16 of the +code snippet below could be rewrite as "if (!( 587/tcp in ssl_ports +))" try to avoid using this construct; instead, negate the in operator +itself. While the functionality is the same, using the "!in" is more +efficient as well as a more natural construct which will aid in the +readability of your script. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro :language: bro @@ -241,7 +526,22 @@ You can see the full script and its output below. Tables ~~~~~~ -A table in Bro is a mapping of a key to a value or yield. While the values don't have to be unique, each key in the table must be unique to preserve a one-to-one mapping of keys to values. In the example below, we've compiled a table of SSL enable services and their common ports. The explicit declaration and constructor for the table on lines 3 and 4 lay out the data types of the keys (strings) and the data types of the yields (ports) and then fill in some sample key and yeild pairs. Line 5 shows how to use a table accessor to insert one key-yield pair into the table. When using the in operator on a table, you are effectively working with the keys of the table. In the case of an inf statement, the in operator will check for membership among the set of keys and return a true or false value. As seen on line 7, we are checking if "SMTPS" is not in the set of keys for the ssl_services table and if the condition holds true, we add the key-yield pair to the table. Line 12 shows the use of a for statement to iterate over each key currently in the table. +A table in Bro is a mapping of a key to a value or yield. While the +values don't have to be unique, each key in the table must be unique +to preserve a one-to-one mapping of keys to values. In the example +below, we've compiled a table of SSL enable services and their common +ports. The explicit declaration and constructor for the table on +lines 3 and 4 lay out the data types of the keys (strings) and the +data types of the yields (ports) and then fill in some sample key and +yeild pairs. Line 5 shows how to use a table accessor to insert one +key-yield pair into the table. When using the in operator on a table, +you are effectively working with the keys of the table. In the case +of an inf statement, the in operator will check for membership among +the set of keys and return a true or false value. As seen on line 7, +we are checking if "SMTPS" is not in the set of keys for the +ssl_services table and if the condition holds true, we add the +key-yield pair to the table. Line 12 shows the use of a for statement +to iterate over each key currently in the table. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_declaration.bro :language: bro @@ -252,9 +552,27 @@ A table in Bro is a mapping of a key to a value or yield. While the values don' @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_declaration.bro -Simple examples aside, tables can become extremely complex as the keys and values for the table become more intricate. Tables can have keys comprised of multiple data types and even a series of elements called a 'tuple'. The flexibility gained with the use of complex tables in Bro implies a cost in complexity for the person writing the scripts but pays off in effectiveness given the power of Bro as a network security platform. +Simple examples aside, tables can become extremely complex as the keys +and values for the table become more intricate. Tables can have keys +comprised of multiple data types and even a series of elements called +a 'tuple'. The flexibility gained with the use of complex tables in +Bro implies a cost in complexity for the person writing the scripts +but pays off in effectiveness given the power of Bro as a network +security platform. -The script below shows a sample table of strings indexed by two strings, a count, and a final string. With a tuple acting as an aggregate key, the order is the important as a change in order would result in a new key. Here, we're using the table to track the Director, Studio, year or release, and lead actor in a series of samurai flicks. It's important to note that in the case of the for statement, it's an all or nothing kind of iteration. We cannot iterate over, say, the directors; We have to iterate with the exact format as the keys themselves. In this case, we need squared brackets surrounding four temporary variables to act as a collection for our iteration. While this is a contrived example, we could easily have had keys containin ip addresses(addr), ports(port) and even a string calculated as the result of a reverse hostname lookup. +The script below shows a sample table of strings indexed by two +strings, a count, and a final string. With a tuple acting as an +aggregate key, the order is the important as a change in order would +result in a new key. Here, we're using the table to track the +Director, Studio, year or release, and lead actor in a series of +samurai flicks. It's important to note that in the case of the for +statement, it's an all or nothing kind of iteration. We cannot +iterate over, say, the directors; We have to iterate with the exact +format as the keys themselves. In this case, we need squared brackets +surrounding four temporary variables to act as a collection for our +iteration. While this is a contrived example, we could easily have +had keys containin ip addresses(addr), ports(port) and even a string +calculated as the result of a reverse hostname lookup. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_complex.bro :language: bro @@ -268,9 +586,26 @@ The script below shows a sample table of strings indexed by two strings, a count Vectors ~~~~~~~ -If you're coming to Bro with a programming background, you may or may not be familiar with the Vector data type depending on your language of choice. On the surface, vectors perform much of the same functionality as arrays, but in truth they are more like associative arrays with zero indexed unsigned integers as the indecies. As such any time you need to sequentially store data of the same type, in Bro you'll have to reach for a vector. Vectors are a collection of objects, all of which are of the same data type, to which elements can be dynamically added or removed. Since Vectors use contiguous storage for their elements, the contents of a vector can be accessed through a zero indexed numerical offset. +If you're coming to Bro with a programming background, you may or may +not be familiar with the Vector data type depending on your language +of choice. On the surface, vectors perform much of the same +functionality as arrays, but in truth they are more like associative +arrays with zero indexed unsigned integers as the indecies. As such +any time you need to sequentially store data of the same type, in Bro +you'll have to reach for a vector. Vectors are a collection of +objects, all of which are of the same data type, to which elements can +be dynamically added or removed. Since Vectors use contiguous storage +for their elements, the contents of a vector can be accessed through a +zero indexed numerical offset. -The format for the declaration of a Vector follows the pattern of other declarations, namely, "SCOPE v: vector of T" where v is the name of your vector of T is the data type of its members. For example, the following snippet shows an explicit and implicit declaration of two locally scoped vectors. The script populates the first vector by inserting values at the end by placing the vector name between two vertical pipes to get the Vector's current length before printing the contents of both Vectors and their current lengths. +The format for the declaration of a Vector follows the pattern of +other declarations, namely, "SCOPE v: vector of T" where v is the name +of your vector of T is the data type of its members. For example, the +following snippet shows an explicit and implicit declaration of two +locally scoped vectors. The script populates the first vector by +inserting values at the end by placing the vector name between two +vertical pipes to get the Vector's current length before printing the +contents of both Vectors and their current lengths. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_vector_declaration.bro :language: bro @@ -281,7 +616,14 @@ The format for the declaration of a Vector follows the pattern of other declarat @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_declaration.bro -In a lot of cases, storing elements in a vector is simply a precursor to then iterating over them. Iterating over a vector is easy with the for keyword. The sample below iterates over a vector of IP addresses and for each IP address, masks that address with 18 bits. The for keyword is used to generate a locally scoped variable called "i" which will hold the index of the current element in the vector. Using i as an index to addr_vector we can access the current item in the vector with addr_vector[i]. +In a lot of cases, storing elements in a vector is simply a precursor +to then iterating over them. Iterating over a vector is easy with the +for keyword. The sample below iterates over a vector of IP addresses +and for each IP address, masks that address with 18 bits. The for +keyword is used to generate a locally scoped variable called "i" which +will hold the index of the current element in the vector. Using i as +an index to addr_vector we can access the current item in the vector +with addr_vector[i]. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_vector_iter.bro :language: bro @@ -299,26 +641,68 @@ Data Types Revisited addr ~~~~ -The addr, or address, data type manages to cover a surprisingly large amount of ground while remaining succinct. IPv4, IPv6 and even hostname constants are included in the addr data type. While IPv4 addresses use the default dotted quad formatting, IPv6 addresses use RFC 2373 defined notation with the addition of squared brackets wrapping the entire address. When you venture into hostname constants, Bro performs a little slight of hand for the benefit of the user; a hostname constant is, in fact, a set of addresses. Bro will issue a DNS request when it sees a hostname constant in use and return a set whose elements are the answers to the DNS request. For example, if you were to use ``local google = www.google.com;`` you would end up with a locally scoped set of addr elements that represent the current set of round robin DNS entries for google. At first blush, this seems trivial, but it is yet another example of Bro making the life of the common Bro scripter a little easier through abstraction applied in a practical manner. +The addr, or address, data type manages to cover a surprisingly large +amount of ground while remaining succinct. IPv4, IPv6 and even +hostname constants are included in the addr data type. While IPv4 +addresses use the default dotted quad formatting, IPv6 addresses use +RFC 2373 defined notation with the addition of squared brackets +wrapping the entire address. When you venture into hostname +constants, Bro performs a little slight of hand for the benefit of the +user; a hostname constant is, in fact, a set of addresses. Bro will +issue a DNS request when it sees a hostname constant in use and return +a set whose elements are the answers to the DNS request. For example, +if you were to use ``local google = www.google.com;`` you would end up +with a locally scoped set of addr elements that represent the current +set of round robin DNS entries for google. At first blush, this seems +trivial, but it is yet another example of Bro making the life of the +common Bro scripter a little easier through abstraction applied in a +practical manner. port ~~~~ -Transport layer port numbers in Bro are represented in the format of ``unsigned integer/protocol name`` e.g. ``22/tcp`` or ``53/udp``. Bro supports TCP( /tcp ), UDP( /udp ) , ICMP( /icmp ) and UNKNOWN( /unknown ) as protocol designations. While ICMP doesn't have an actual port, Bro supports the concept of ICMP "ports" by using the ICMP message type and ICMP message code as the source and destination port respectively. Ports can be compared for equality using the == or != operators and can even be compared for ordering. Bro gives the protocol designations the following "order": unknown < tcp < udp < icmp. +Transport layer port numbers in Bro are represented in the format of +``unsigned integer/protocol name`` e.g. ``22/tcp`` or ``53/udp``. Bro +supports TCP( /tcp ), UDP( /udp ) , ICMP( /icmp ) and UNKNOWN( +/unknown ) as protocol designations. While ICMP doesn't have an +actual port, Bro supports the concept of ICMP "ports" by using the +ICMP message type and ICMP message code as the source and destination +port respectively. Ports can be compared for equality using the == or +!= operators and can even be compared for ordering. Bro gives the +protocol designations the following "order": unknown < tcp < udp < +icmp. -Ports can be compared for equality and also for ordering. When comparing order across transport-level protocols, unknown < tcp < udp < icmp, for example 65535/tcp is smaller than 0/udp. +Ports can be compared for equality and also for ordering. When +comparing order across transport-level protocols, unknown < tcp < udp +< icmp, for example 65535/tcp is smaller than 0/udp. subnet ~~~~~~ -Bro has full support for CIDR notation subnets as a base data type. There is no need to manage the IP and the subnet mask as two seperate entities when you can provide the same information in CIDR notation in your scripts. The following example below uses a Bro script to determine if a series of IP addresses are within a set of subnets using a 20 bit subnet mask. +Bro has full support for CIDR notation subnets as a base data type. +There is no need to manage the IP and the subnet mask as two seperate +entities when you can provide the same information in CIDR notation in +your scripts. The following example below uses a Bro script to +determine if a series of IP addresses are within a set of subnets +using a 20 bit subnet mask. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_subnets.bro :language: bro :linenos: :lines: 4-19 -Because this is a script that doesn't use any kind of network analysis, we can handle the event bro_init() which is always generated by Bro's core upon startup. On lines six and seven, two locally scoped vectors are created to hold our lists of subnets and IP addresses respectively. Then, using a set of nested for loops, we iterate over every subnet and every IP address and use an if statement to compare an IP address against a subnet using the in operator. The in operator returns true if the IP address falls within a given subnet based on the longest prefix match calculation. For example, 10.0.0.1 in 10.0.0.0/8 would return true while 192.168.2.1 in 192.168.1.0/24 would return false. When we run the script, we get the output listing the IP address and the subnet in which it belongs. +Because this is a script that doesn't use any kind of network +analysis, we can handle the event bro_init() which is always generated +by Bro's core upon startup. On lines six and seven, two locally +scoped vectors are created to hold our lists of subnets and IP +addresses respectively. Then, using a set of nested for loops, we +iterate over every subnet and every IP address and use an if statement +to compare an IP address against a subnet using the in operator. The +in operator returns true if the IP address falls within a given subnet +based on the longest prefix match calculation. For example, 10.0.0.1 +in 10.0.0.0/8 would return true while 192.168.2.1 in 192.168.1.0/24 +would return false. When we run the script, we get the output listing +the IP address and the subnet in which it belongs. .. btest:: data_type_subnets @@ -327,14 +711,30 @@ Because this is a script that doesn't use any kind of network analysis, we can h time ~~~~ -While there is currently no supported way to add a time constant in Bro, two built-in functions exist to make use of the ``time`` data type. Both ``network_time()`` and ``current_time()`` return a ``time`` data type but they each return a time based on different criteria. The ``current_time()`` function returns what is called the wall-clock time as defined by the operating system. However, ``network_time()`` returns the timestamp of the last packet processed be it from a live data stream or saved packet capture. Both functions return the time in epoch seconds, meaning ``strftime`` must be used to turn the output into human readable output. The script below makes use of the ``connection_established`` event handler to generate text every time a SYN/ACK packet is seen responding to a SYN packet as part of a TCP handshake. The text generated, is in the format of a timestamp and an indication of who the originator and responder were. We use the ``strftime`` format string of ``%Y%M%d %H:%m:%S`` to produce a common date time formatted time stamp. +While there is currently no supported way to add a time constant in +Bro, two built-in functions exist to make use of the ``time`` data +type. Both ``network_time()`` and ``current_time()`` return a +``time`` data type but they each return a time based on different +criteria. The ``current_time()`` function returns what is called the +wall-clock time as defined by the operating system. However, +``network_time()`` returns the timestamp of the last packet processed +be it from a live data stream or saved packet capture. Both functions +return the time in epoch seconds, meaning ``strftime`` must be used to +turn the output into human readable output. The script below makes +use of the ``connection_established`` event handler to generate text +every time a SYN/ACK packet is seen responding to a SYN packet as part +of a TCP handshake. The text generated, is in the format of a +timestamp and an indication of who the originator and responder were. +We use the ``strftime`` format string of ``%Y%M%d %H:%m:%S`` to +produce a common date time formatted time stamp. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_time.bro :language: bro :linenos: :lines: 4-7 -When the script is executed we get an output showing the details of established connections. +When the script is executed we get an output showing the details of +established connections. .. btest:: data_type_time @@ -343,16 +743,39 @@ When the script is executed we get an output showing the details of established interval ~~~~~~~~ -The interval data type is another area in Bro where rational application of abstraction made perfect sense. As a data type, the interval represents a relative time as denoted by a numeric constant followed by a unit of time. For example, 2.2 seconds would be ``2.2sec`` and thirty-one days would be represented by ``31days``. Bro supports usec, msec, sec, min, hr, or day which represent microseconds, milliseconds, seconds, minutes, hours, and days respectively. In fact, the interval data type allows for a surprising amount of variation in its definitions. There can be a space between the numeric constant or they can crammed together like a temporal portmanteau. The time unit can be either singular or plural. All of this adds up to to the fact that both ``42hrs`` and ``42 hr`` are perfectly valid and logically equivalent in Bro. The point, however, is to increase the readability and thus maintainability of a script. Intervals can even be negated, allowing for ``- 10mins`` to represent "ten minutes ago". +The interval data type is another area in Bro where rational +application of abstraction made perfect sense. As a data type, the +interval represents a relative time as denoted by a numeric constant +followed by a unit of time. For example, 2.2 seconds would be +``2.2sec`` and thirty-one days would be represented by ``31days``. +Bro supports usec, msec, sec, min, hr, or day which represent +microseconds, milliseconds, seconds, minutes, hours, and days +respectively. In fact, the interval data type allows for a surprising +amount of variation in its definitions. There can be a space between +the numeric constant or they can crammed together like a temporal +portmanteau. The time unit can be either singular or plural. All of +this adds up to to the fact that both ``42hrs`` and ``42 hr`` are +perfectly valid and logically equivalent in Bro. The point, however, +is to increase the readability and thus maintainability of a script. +Intervals can even be negated, allowing for ``- 10mins`` to represent +"ten minutes ago". -Intervals in Bro can have mathematical operations performed against them allowing the user to perform addition, subtraction, multiplication, division, and comparison operations. As well, Bro returns an interval when comparing two ``time`` values using the ``-`` operator. The script below amends the script started in the section above to include a time delta value printed along with the connection establishment report. +Intervals in Bro can have mathematical operations performed against +them allowing the user to perform addition, subtraction, +multiplication, division, and comparison operations. As well, Bro +returns an interval when comparing two ``time`` values using the ``-`` +operator. The script below amends the script started in the section +above to include a time delta value printed along with the connection +establishment report. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_interval.bro :language: bro :linenos: :lines: 4-20 -This time, when we execute the script we see an additional line in the output to display the time delta since the last fully established connection. +This time, when we execute the script we see an additional line in the +output to display the time delta since the last fully established +connection. .. btest:: data_type_interval @@ -362,20 +785,47 @@ This time, when we execute the script we see an additional line in the output to Pattern ~~~~~~~ -Bro has support for fast text searching operations using regular expressions and even goes so far as to declare a native data type for the patterns used in regular expressions. A pattern constant is created by enclosing text within the forward slash characters. Bro supports syntax very similar to the flex lexical analyzer syntax. The most common use of patterns in Bro you are likely to come across is embedded matching using the ``in`` operator. Embedded matching adheres to a strict format, requiring the regular expression or pattern constant to be on the left side of the ``in`` operator and the string against which it will be tested to be on the right. +Bro has support for fast text searching operations using regular +expressions and even goes so far as to declare a native data type for +the patterns used in regular expressions. A pattern constant is +created by enclosing text within the forward slash characters. Bro +supports syntax very similar to the flex lexical analyzer syntax. The +most common use of patterns in Bro you are likely to come across is +embedded matching using the ``in`` operator. Embedded matching +adheres to a strict format, requiring the regular expression or +pattern constant to be on the left side of the ``in`` operator and the +string against which it will be tested to be on the right. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_pattern_01.bro :language: bro :linenos: :lines: 4-13 -In the sample above, two local variables are declared to hold our sample sentence and regular expression. Our regular expression in this case will return true if the string contains either the word "quick" or the word "fox." The ``if`` statement on line six uses embedded matching and the ``in`` operator to check for the existence of the pattern within the string. If the statement resolves to true, split is called to break the string into separate pieces. Split takes a string and a pattern as its arguments and returns a table of strings indexed by a count. Each element of the table will be the segments before and after any matches against the pattern but excluding the actual matches. In this case, our pattern matches twice, and results in a table with three entries. Lines 11 through 13 print the contents of the table in order. +In the sample above, two local variables are declared to hold our +sample sentence and regular expression. Our regular expression in +this case will return true if the string contains either the word +"quick" or the word "fox." The ``if`` statement on line six uses +embedded matching and the ``in`` operator to check for the existence +of the pattern within the string. If the statement resolves to true, +split is called to break the string into separate pieces. Split takes +a string and a pattern as its arguments and returns a table of strings +indexed by a count. Each element of the table will be the segments +before and after any matches against the pattern but excluding the +actual matches. In this case, our pattern matches twice, and results +in a table with three entries. Lines 11 through 13 print the contents +of the table in order. .. btest:: data_type_pattern @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_01.bro -Patterns can also be used to compare strings using equality and inequality operators through the ``==`` and ``!=`` operators respectively. When used in this manner however, the string must match entirely to resolve to true. For example, the script below uses two ternary conditional statements to illustrate the use of the ``==`` operators with patterns. On lines 5 and 8 the output is altered based on the result of the comparison between the pattern and the string. +Patterns can also be used to compare strings using equality and +inequality operators through the ``==`` and ``!=`` operators +respectively. When used in this manner however, the string must match +entirely to resolve to true. For example, the script below uses two +ternary conditional statements to illustrate the use of the ``==`` +operators with patterns. On lines 5 and 8 the output is altered based +on the result of the comparison between the pattern and the string. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_pattern_02.bro :language: bro @@ -391,18 +841,39 @@ Patterns can also be used to compare strings using equality and inequality opera Record Data Type ================ -With Bro's support for a wide array of data types and data structures an obvious extension of is to include the ability to create custom data types consisting of the atomic types and ddata structures. To accomplish this, Bro introduces the ``record`` type and the ``type`` keyword. Similar to how you would define a new data structure in C with the ``typedef`` and ``struct`` keywords, Bro allows you to cobble together new data types to suit the needs of your situation. +With Bro's support for a wide array of data types and data structures +an obvious extension of is to include the ability to create custom +data types consisting of the atomic types and ddata structures. To +accomplish this, Bro introduces the ``record`` type and the ``type`` +keyword. Similar to how you would define a new data structure in C +with the ``typedef`` and ``struct`` keywords, Bro allows you to cobble +together new data types to suit the needs of your situation. -When combined with the ``type`` keyword, ``record`` can generate a composite type. We have, in fact, already encountered a a complex example of the ``record`` data type in the earlier sections. The excerpt below shows the definition of the connection record data type as defined in the ``Conn`` module. +When combined with the ``type`` keyword, ``record`` can generate a +composite type. We have, in fact, already encountered a a complex +example of the ``record`` data type in the earlier sections. The +excerpt below shows the definition of the connection record data type +as defined in the ``Conn`` module. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro :language: bro :linenos: :lines: 10-12,16,17,19,21,23,25,28,31,35,37,56,62,68,90,93,97,100,104,108,109,114 -While it might be surprising that Bro is tracking and passing around this much data for each connection, it shouldn't be too surprising, given our exploration of it earlier, that the connection record consists of a collection of atomic data types, simple data types and even another ``record``. Looking at the structure of the definition, a new collection of data types is being defined as a type called ``Info``. Since this type definition is within the confines of an export block, what is defined is, in fact, ``Conn::Info``. +While it might be surprising that Bro is tracking and passing around +this much data for each connection, it shouldn't be too surprising, +given our exploration of it earlier, that the connection record +consists of a collection of atomic data types, simple data types and +even another ``record``. Looking at the structure of the definition, +a new collection of data types is being defined as a type called +``Info``. Since this type definition is within the confines of an +export block, what is defined is, in fact, ``Conn::Info``. -The formatting for a declaration of a record type in Bro includes the descriptive name of the type being defined and the seperate fields that make up the record. The individual fields that make up the new record are not limited in type or number as long as the name for each field is unique. +The formatting for a declaration of a record type in Bro includes the +descriptive name of the type being defined and the seperate fields +that make up the record. The individual fields that make up the new +record are not limited in type or number as long as the name for each +field is unique. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_01.bro :language: bro @@ -413,9 +884,20 @@ The formatting for a declaration of a record type in Bro includes the descriptiv @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_01.bro -The sample above shows a simple type definition that includes a string, a set of ports, and a count to define a service type. Also included is a function to print each field of a record in a formatted fashion and a bro_init event handler to show some functionality of working with records. The defintions of the dns and http services are both done inline using squared brackets before being passed to the ``print_service`` function. The ``print_service`` function makes use of the ``$`` dereference operator to access the fields within the newly defined Service record type. +The sample above shows a simple type definition that includes a +string, a set of ports, and a count to define a service type. Also +included is a function to print each field of a record in a formatted +fashion and a bro_init event handler to show some functionality of +working with records. The defintions of the dns and http services are +both done inline using squared brackets before being passed to the +``print_service`` function. The ``print_service`` function makes use +of the ``$`` dereference operator to access the fields within the +newly defined Service record type. -As you saw in the definition for the connection record, other records are even valid as fields within another record. We can extend the example above to include another record that contains a Service record. +As you saw in the definition for the connection record, other records +are even valid as fields within another record. We can extend the +example above to include another record that contains a Service +record. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_02.bro :language: bro @@ -426,26 +908,77 @@ As you saw in the definition for the connection record, other records are even v @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_02.bro -The example above includes a second record type in which a field is used as the data type for a set. Records can be reapeatedly nested within other records, their fields reachable through repeated chains of the ``$`` dereference operator. +The example above includes a second record type in which a field is +used as the data type for a set. Records can be reapeatedly nested +within other records, their fields reachable through repeated chains +of the ``$`` dereference operator. -It's also common to see a ``type`` used to simply alias a data structure to a more descriptive name. The example below shows an example of this from Bro's own type definitions file. +It's also common to see a ``type`` used to simply alias a data +structure to a more descriptive name. The example below shows an +example of this from Bro's own type definitions file. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/init-bare.bro :language: bro :linenos: :lines: 12,19,26 -The three lines above alias a type of data structure to a descriptive name. Functionally, the operations are the same, however, each of the types above are named such that their function is instantly identifiable. This is another place in Bro scripting where consideration can lead to better readability of your code and thus easier maintainability in the future. +The three lines above alias a type of data structure to a descriptive +name. Functionally, the operations are the same, however, each of the +types above are named such that their function is instantly +identifiable. This is another place in Bro scripting where +consideration can lead to better readability of your code and thus +easier maintainability in the future. Logging Framework ================= -Armed with a decent understanding of the data types and data structures in Bro, exploring the various frameworks available is a much more rewarding effort. The framework with which most users are likely to have the most interaction is the Logging Framework. Designed in such a way to so as to abstract much of the process of creating a file and appending ordered and organized data into it, the Logging Framework makes use of some potentially unfamiliar nomenclature. Specifically, Log streams, Filters and Writers are simply abstractions of the processes required to manage a high rate of incoming logs while maintaining full operability. If you've seen Bro employed in an environment with a large connection, you know that logs are produced incredibly quickly; the ability to process a large set of data and write it to disk is due to the design of the Logging Framework. +Armed with a decent understanding of the data types and data +structures in Bro, exploring the various frameworks available is a +much more rewarding effort. The framework with which most users are +likely to have the most interaction is the Logging Framework. +Designed in such a way to so as to abstract much of the process of +creating a file and appending ordered and organized data into it, the +Logging Framework makes use of some potentially unfamiliar +nomenclature. Specifically, Log streams, Filters and Writers are +simply abstractions of the processes required to manage a high rate of +incoming logs while maintaining full operability. If you've seen Bro +employed in an environment with a large connection, you know that logs +are produced incredibly quickly; the ability to process a large set of +data and write it to disk is due to the design of the Logging +Framework. -Data is written to a Log stream based on decision making processes in Bro's scriptland. Log streams correspond to a single log as defined by the set of name value pairs that make up its fields. That data can then be filtered, modified, or redirected with Logging Filters which, by default, are set to log everything. Filters can be used to break log files into subsets or duplicate that information to another output. The final output of the data is defined by the writer. Bro's default writer is simple tab separated ASCII files but Bro also includes support for DataSeries and Elasticsearch outputs as well as additional writers currently in development. While these new terms and ideas may give the impression that the Logging Framework is difficult to work with, the actual learning curve is, in actuality, not very steep at all. The abstraction built into the Logging Framework makes it such that a vast majority of scripts needs not go past the basics. In effect, writing to a log file is as simple as defining the format of your data, letting Bro know that you wish to create a new log, and then calling the ``Log::write()`` method to output log records. +Data is written to a Log stream based on decision making processes in +Bro's scriptland. Log streams correspond to a single log as defined +by the set of name value pairs that make up its fields. That data can +then be filtered, modified, or redirected with Logging Filters which, +by default, are set to log everything. Filters can be used to break +log files into subsets or duplicate that information to another +output. The final output of the data is defined by the writer. Bro's +default writer is simple tab separated ASCII files but Bro also +includes support for DataSeries and Elasticsearch outputs as well as +additional writers currently in development. While these new terms +and ideas may give the impression that the Logging Framework is +difficult to work with, the actual learning curve is, in actuality, +not very steep at all. The abstraction built into the Logging +Framework makes it such that a vast majority of scripts needs not go +past the basics. In effect, writing to a log file is as simple as +defining the format of your data, letting Bro know that you wish to +create a new log, and then calling the ``Log::write()`` method to +output log records. -The Logging Framework is an are in Bro where, the more you see it used and the more you use it yourself, the more second nature the boilerplate parts of the code will become. As such, let's work through a contrived example of simply logging the digits 1 through 10 and their corresponding factorial to the default ASCII log writer. It's always best to work through the problem once, simulating the desired output with ``print`` and ``fmt`` before attempting to dive into the Logging Framework. Below is a script that defines a factorial function to recursively calculate the factorial of a unsigned integer passed as an argument to the function. Using ``print`` and ``fmt`` we can ensure that Bro can perform these calculations correctly as well get an idea of the answers ourselves. +The Logging Framework is an are in Bro where, the more you see it used +and the more you use it yourself, the more second nature the +boilerplate parts of the code will become. As such, let's work +through a contrived example of simply logging the digits 1 through 10 +and their corresponding factorial to the default ASCII log writer. +It's always best to work through the problem once, simulating the +desired output with ``print`` and ``fmt`` before attempting to dive +into the Logging Framework. Below is a script that defines a +factorial function to recursively calculate the factorial of a +unsigned integer passed as an argument to the function. Using +``print`` and ``fmt`` we can ensure that Bro can perform these +calculations correctly as well get an idea of the answers ourselves. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_01.bro :language: bro @@ -456,38 +989,128 @@ The Logging Framework is an are in Bro where, the more you see it used and the m @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_01.bro -The output of the script aligns with what we expect so now it's time to integrate the Logging Framework. As mentioned above we have to perform a few steps before we can issue the ``Log::write()`` method and produce a logfile. As we are working within a namespace and informing an outside entity of workings and data internal to the namespace, we use an ``export{}`` block. First we need to inform Bro that we are going to be adding another Log stream by adding a value to the ``Log::ID`` enumerable. In line 3 of the script, we append the value ``LOG`` to the Log::ID enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs that make up the data of our logs and dictate its format. Lines 5 through 9 define a new datatype called an Info record (actually, ``Factor::Info``) with two fields, both unsigned integers. Each of the fields in the ``Factor::Log`` record type include the ``&log`` attribute, indicating that these fields should be passed to the Logging Framework when ``Log::write()`` is called. Were there to be any name value pairs without the ``&log`` attribute, those fields would simply be ignored during logging but remain available for the lifespan of the variable. The next step is to create the logging stream with ``Log::create_stream()`` which takes a Log::ID and a record as its arguments. In this example, on line 28, we call the ``Log::create_stream()`` method and pass ``Factor::LOG`` and the ``Factor::Info`` record as arguments. From here on out, if we issue the ``Log::write()`` command with the correct Log::ID and a properly formatted ``Factor::Info`` record, a log entry will be generated. +The output of the script aligns with what we expect so now it's time +to integrate the Logging Framework. As mentioned above we have to +perform a few steps before we can issue the ``Log::write()`` method +and produce a logfile. As we are working within a namespace and +informing an outside entity of workings and data internal to the +namespace, we use an ``export{}`` block. First we need to inform Bro +that we are going to be adding another Log stream by adding a value to +the ``Log::ID`` enumerable. In line 3 of the script, we append the +value ``LOG`` to the Log::ID enumerable, however due to this being in +an export block the value appended to ``Log::ID`` is actually +``Factor::Log``. Next, we need to define the name and value pairs +that make up the data of our logs and dictate its format. Lines 5 +through 9 define a new datatype called an Info record (actually, +``Factor::Info``) with two fields, both unsigned integers. Each of the +fields in the ``Factor::Log`` record type include the ``&log`` +attribute, indicating that these fields should be passed to the +Logging Framework when ``Log::write()`` is called. Were there to be +any name value pairs without the ``&log`` attribute, those fields +would simply be ignored during logging but remain available for the +lifespan of the variable. The next step is to create the logging +stream with ``Log::create_stream()`` which takes a Log::ID and a +record as its arguments. In this example, on line 28, we call the +``Log::create_stream()`` method and pass ``Factor::LOG`` and the +``Factor::Info`` record as arguments. From here on out, if we issue +the ``Log::write()`` command with the correct Log::ID and a properly +formatted ``Factor::Info`` record, a log entry will be generated. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_02.bro :language: bro :linenos: :lines: 4-40 -Now, if we run the new version of the script, instead of generating logging information to stdout, no output is created. Instead the output is all in factor.log, properly formatted and organized. +Now, if we run the new version of the script, instead of generating +logging information to stdout, no output is created. Instead the +output is all in factor.log, properly formatted and organized. .. btest:: framework_logging_factorial_02 @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_02/factor.log -While the previous example is a simplistic one, it serves to demonstrate the small pieces of script that need to be in place in order to generate logs. For example, it's common to call ``Log::create_stream()`` in ``bro_init()`` and while in a live example, determining when to call ``Log::write()`` would likely be done in an event handler, in this case we use ``bro_done()``. +While the previous example is a simplistic one, it serves to +demonstrate the small pieces of script that need to be in place in +order to generate logs. For example, it's common to call +``Log::create_stream()`` in ``bro_init()`` and while in a live +example, determining when to call ``Log::write()`` would likely be +done in an event handler, in this case we use ``bro_done()``. -If you've already spent time with a deployment of Bro, you've likely had the opportunity to view, search through, or manipulate the logs produced by the Logging Framework. The log output from a default installation of Bro is substantial to say the least, however, there are times in which the way the Logging Framework by default isn't ideal for the situation. This can range from needing to log more or less data with each call to ``Log::write()`` or even the need to split log files based on arbitrary logic. In the later case, Filters come into play along with the Logging Framework. Filters grant a level of customization to Bro's scriptland, allowing the script writer to include or exclude fields in the log and even make alterations to the path of the file in which the logs are being placed. Each stream, when created, is given a default filter called, not surprisingly, ``default``. When using the ``default`` filter, every key value pair with the ``&log`` attribute is written to a single file. For the example we've been using, let's extend it so as to write any factorial which is a factor of 5 to an alternate file, while writing the remaining logs to factor.log. +If you've already spent time with a deployment of Bro, you've likely +had the opportunity to view, search through, or manipulate the logs +produced by the Logging Framework. The log output from a default +installation of Bro is substantial to say the least, however, there +are times in which the way the Logging Framework by default isn't +ideal for the situation. This can range from needing to log more or +less data with each call to ``Log::write()`` or even the need to split +log files based on arbitrary logic. In the later case, Filters come +into play along with the Logging Framework. Filters grant a level of +customization to Bro's scriptland, allowing the script writer to +include or exclude fields in the log and even make alterations to the +path of the file in which the logs are being placed. Each stream, +when created, is given a default filter called, not surprisingly, +``default``. When using the ``default`` filter, every key value pair +with the ``&log`` attribute is written to a single file. For the +example we've been using, let's extend it so as to write any factorial +which is a factor of 5 to an alternate file, while writing the +remaining logs to factor.log. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_03.bro :language: bro :linenos: :lines: 43-60 -To dynamically alter the file in which a stream writes its logs a filter can specify function returns a string to be used as the filename for the current call to ``Log::write()``. The definition for this function has to take as its parameters a Log::ID called id, a string called path and the appropriate record type for the logs called "rec". You can see the definition of ``mod5`` used in this example on line one conforms to that requirement. The function simply returns "factor-mod5" if the factorial is divisible evenly by 5, otherwise, it returns "factor-non5". In the additional ``bro_init()`` event handler, we define a locally scoped ``Log::Filter`` and assign it a record that defines the ``name`` and ``path_func`` fields. We then call ``Log::add_filter()`` to add the filter to the ``Factor::LOG`` Log::ID and call ``Log::remove_filter()`` to remove the ``default`` filter for Factor::LOG. Had we not removed the ``default`` filter, we'd have ended up with three log files: factor-mod5.log with all the factorials that are a factors of 5, factor-non5.log with the factorials that are not factors of 5, and factor.log which would have included all factorials. +To dynamically alter the file in which a stream writes its logs a +filter can specify function returns a string to be used as the +filename for the current call to ``Log::write()``. The definition for +this function has to take as its parameters a Log::ID called id, a +string called path and the appropriate record type for the logs called +"rec". You can see the definition of ``mod5`` used in this example on +line one conforms to that requirement. The function simply returns +"factor-mod5" if the factorial is divisible evenly by 5, otherwise, it +returns "factor-non5". In the additional ``bro_init()`` event +handler, we define a locally scoped ``Log::Filter`` and assign it a +record that defines the ``name`` and ``path_func`` fields. We then +call ``Log::add_filter()`` to add the filter to the ``Factor::LOG`` +Log::ID and call ``Log::remove_filter()`` to remove the ``default`` +filter for Factor::LOG. Had we not removed the ``default`` filter, +we'd have ended up with three log files: factor-mod5.log with all the +factorials that are a factors of 5, factor-non5.log with the +factorials that are not factors of 5, and factor.log which would have +included all factorials. .. btest:: framework_logging_factorial_02 @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_03/factor-mod5.log @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_03/factor-non5.log -The ability of Bro to generate easily customizable and extensible logs which remain easily parsable is a big part of the reason Bro has gained a large measure of respect. In fact, it's difficult at times to think of something that Bro doesn't log and as such, it is often advantageous for analysts and systems architects to instead hook into the logging framework to be able to perform custom actions based upon the data being sent to the Logging Frame. To that end, every default log stream in Bro generates a custom event that can be handled by anyone wishing to act upon the data being sent to the stream. By convention these events are usually in the format ``log_x`` where x is the name of the logging stream; as such the event raised for every log sent to the Logging Framework by the HTTP parser would be ``log_http``. In fact, we've already seen a script handle the ``log_http`` event when we broke down how the ``detect-MHR.bro`` script worked. In that example, as each log entry was sent to the logging framework, post-processing was taking place in the ``log_http`` event. Instead of using an external script to parse the ``http.log`` file and do post-processing for the entry, post-processing can be done in real time in Bro. +The ability of Bro to generate easily customizable and extensible logs +which remain easily parsable is a big part of the reason Bro has +gained a large measure of respect. In fact, it's difficult at times +to think of something that Bro doesn't log and as such, it is often +advantageous for analysts and systems architects to instead hook into +the logging framework to be able to perform custom actions based upon +the data being sent to the Logging Frame. To that end, every default +log stream in Bro generates a custom event that can be handled by +anyone wishing to act upon the data being sent to the stream. By +convention these events are usually in the format ``log_x`` where x is +the name of the logging stream; as such the event raised for every log +sent to the Logging Framework by the HTTP parser would be +``log_http``. In fact, we've already seen a script handle the +``log_http`` event when we broke down how the ``detect-MHR.bro`` +script worked. In that example, as each log entry was sent to the +logging framework, post-processing was taking place in the +``log_http`` event. Instead of using an external script to parse the +``http.log`` file and do post-processing for the entry, +post-processing can be done in real time in Bro. -Telling Bro to raise an event in your own Logging stream is as simple as exporting that event name and then adding that event in the call to ``Log::create_stream``. Going back to our simple example of logging the factorial of an integer, we add ``log_factor`` to the ``export`` block and define the value to be passed to it, in this case the ``Factor::Info`` record. We then list the ``log_factor`` function as the ``$ev`` field in the call to ``Log::create_stream`` +Telling Bro to raise an event in your own Logging stream is as simple +as exporting that event name and then adding that event in the call to +``Log::create_stream``. Going back to our simple example of logging +the factorial of an integer, we add ``log_factor`` to the ``export`` +block and define the value to be passed to it, in this case the +``Factor::Info`` record. We then list the ``log_factor`` function as +the ``$ev`` field in the call to ``Log::create_stream`` .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_04.bro :language: bro @@ -498,9 +1121,38 @@ Telling Bro to raise an event in your own Logging stream is as simple as exporti Notice Framework ================ -While Bro's Logging Framework provides an easy and systematic way to generate logs, there still exists a need to indicate when a specific behavior has been detected and a method to allow that detection to come to someone's attention. To that end, the Notice Framework is in place to allow script writers a codified means through which they can raise a notice and a system through which an operator can opt-in to receive the notice. Bro holds to the philosophy that it is up to the individual operator to indicate the behaviors in which they are interested and as such Bro ships with a large number of policy scripts which detect behavior that may be of interest but it does not presume to guess as to which behaviors are "action-able". In effect, Bro works to separate the act of detection and the responsibility of reporting. With the Notice Framework it's simple to raise a notice for any behavior that is detected. +While Bro's Logging Framework provides an easy and systematic way to +generate logs, there still exists a need to indicate when a specific +behavior has been detected and a method to allow that detection to +come to someone's attention. To that end, the Notice Framework is in +place to allow script writers a codified means through which they can +raise a notice and a system through which an operator can opt-in to +receive the notice. Bro holds to the philosophy that it is up to the +individual operator to indicate the behaviors in which they are +interested and as such Bro ships with a large number of policy scripts +which detect behavior that may be of interest but it does not presume +to guess as to which behaviors are "action-able". In effect, Bro +works to separate the act of detection and the responsibility of +reporting. With the Notice Framework it's simple to raise a notice +for any behavior that is detected. -To raise a notice in Bro, you only need to indicate to Bro that you are provide a specific ``Notice::Type`` by exporting it and then make a call to ``NOTICE()`` supplying it with an appropriate ``Notice::Info`` record. Often times the call to ``NOTICE()`` includes just the ``Notice::Type``, and a concise message. There are however, significantly more options available when raising notices as seen in the table below. The only field in the table below whose attributes make it a required field is the ``note`` field. Still, good manners are always important and including a concise message in ``$msg`` and, where necessary, the contents of the connection record in ``$conn`` along with the ``Notice::Type`` tend to comprise the minimum of information required for an notice to be considered useful. If the ``$conn`` variable is supplied the Notice Framework will auto-populate the ``$id`` and ``$src`` fields as well. Other fields that are commonly included, ``$identifier`` and ``$suppress_for`` are built around the automated suppression feature of the Notice Framework which we will cover shortly. +To raise a notice in Bro, you only need to indicate to Bro that you +are provide a specific ``Notice::Type`` by exporting it and then make +a call to ``NOTICE()`` supplying it with an appropriate +``Notice::Info`` record. Often times the call to ``NOTICE()`` +includes just the ``Notice::Type``, and a concise message. There are +however, significantly more options available when raising notices as +seen in the table below. The only field in the table below whose +attributes make it a required field is the ``note`` field. Still, +good manners are always important and including a concise message in +``$msg`` and, where necessary, the contents of the connection record +in ``$conn`` along with the ``Notice::Type`` tend to comprise the +minimum of information required for an notice to be considered useful. +If the ``$conn`` variable is supplied the Notice Framework will +auto-populate the ``$id`` and ``$src`` fields as well. Other fields +that are commonly included, ``$identifier`` and ``$suppress_for`` are +built around the automated suppression feature of the Notice Framework +which we will cover shortly. +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | Field | Type | Attributes | Use | @@ -548,23 +1200,72 @@ To raise a notice in Bro, you only need to indicate to Bro that you are provide | suppress_for | interval | &log &optional | Length of time to suppress a notice. | +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ -One of the default policy scripts raises a notice when an SSH login has been heuristically detected and the originating hostname is one that would raise suspicion. Effectively, the script attempts to define a list of hosts from which you would never want to see SSH traffic originating, dns servers, mail servers, etc. To accomplish this, the script adhere's to the seperation of detection and reporting by detecting a behavior and raising a notice. Whether or not that notice is acted upon is decided by the local Notice Policy, but the script attempts to supply as much information as possible while staying concise. +One of the default policy scripts raises a notice when an SSH login +has been heuristically detected and the originating hostname is one +that would raise suspicion. Effectively, the script attempts to +define a list of hosts from which you would never want to see SSH +traffic originating, dns servers, mail servers, etc. To accomplish +this, the script adhere's to the seperation of detection and reporting +by detecting a behavior and raising a notice. Whether or not that +notice is acted upon is decided by the local Notice Policy, but the +script attempts to supply as much information as possible while +staying concise. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssh/interesting-hostnames.bro :language: bro :linenos: :lines: 1-46 -While much of the script relates to the actual detection, the parts specific to the Notice Framework are actually quite interesting in themselves. On line 12 the script's ``export`` block adds the value ``SSH::Interesting_Hostname_Login`` to the enumerable constant ``Notice::Type`` to indicate to the Bro core that a new type of notice is being defined. The script then calls ``NOTICE()`` and defines the ``$note``, ``$msg``, ``$sub`` and ``$conn`` fields. Line 39 also includes a ternary if statement that modifies the ``$msg`` text depending on whether the host is a local address and whether it is the client or the server. This use of ``fmt()`` and a ternary operators is a concise way to lend readability to the notices that are generated without the need for branching ``if`` statements that each raise a specific notice. +While much of the script relates to the actual detection, the parts +specific to the Notice Framework are actually quite interesting in +themselves. On line 12 the script's ``export`` block adds the value +``SSH::Interesting_Hostname_Login`` to the enumerable constant +``Notice::Type`` to indicate to the Bro core that a new type of notice +is being defined. The script then calls ``NOTICE()`` and defines the +``$note``, ``$msg``, ``$sub`` and ``$conn`` fields. Line 39 also +includes a ternary if statement that modifies the ``$msg`` text +depending on whether the host is a local address and whether it is the +client or the server. This use of ``fmt()`` and a ternary operators +is a concise way to lend readability to the notices that are generated +without the need for branching ``if`` statements that each raise a +specific notice. -The opt-in system for notices is managed through writing ``Notice::policy`` hooks. A ``Notice::policy`` hook takes as its argument a ``Notice::Info`` record which will hold the same information your script provided in its call to ``NOTICE()``. With access to the ``Notice::Info`` record for a specific notice you can include logic such as in statements in the body of your hook to alter the Policy for handling notices on your system. Notice hooks are akin to functions and event handlers and share the same structure; You can even think of hooks as multi-bodied functions. You define the hook and Bro will take care of passing in the ``Notice::Info`` record. The simplest kind of ``Notice::policy`` hooks simply check the value of ``$note`` in the ``Notice::Info`` record being passed into the hook and performing an action based on the answer. The hook below adds the ``Notice::ACTION_EMAIL`` action for the SSH::Interesting_Hostname_Login notice raised in the interesting-hostnames.bro script. +The opt-in system for notices is managed through writing +``Notice::policy`` hooks. A ``Notice::policy`` hook takes as its +argument a ``Notice::Info`` record which will hold the same +information your script provided in its call to ``NOTICE()``. With +access to the ``Notice::Info`` record for a specific notice you can +include logic such as in statements in the body of your hook to alter +the Policy for handling notices on your system. Notice hooks are akin +to functions and event handlers and share the same structure; You can +even think of hooks as multi-bodied functions. You define the hook +and Bro will take care of passing in the ``Notice::Info`` record. The +simplest kind of ``Notice::policy`` hooks simply check the value of +``$note`` in the ``Notice::Info`` record being passed into the hook +and performing an action based on the answer. The hook below adds the +``Notice::ACTION_EMAIL`` action for the +SSH::Interesting_Hostname_Login notice raised in the +interesting-hostnames.bro script. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_hook_01.bro :language: bro :linenos: :lines: 6-12 -In the example above we've added ``Notice::ACTION_EMAIL`` to the ``n$actions`` set. This set, defined in the Notice Framework scripts, can only have entries from the Notice::Action type which is itself an enumerable that defines the values shown in the table below along with their corresponding meanings. The ``Notice::ACTION_LOG`` action writes the notice to the ``Notice::LOG`` logging stream which, in the default configuration, will write each notice to the notice.log file and take no further action. The ``Notice::ACTION_EMAIL`` action will send an email to the address or addresses defined in the ``Notice::mail_dest`` variable with the particulars of the notice as the body of the email. The last action, ``Notice::ACTION_ALARM`` sends the notice to the ``Notice::ALARM_LOG`` logging stream which is then rotated hourly and its contents emailed in readable ASCII to the addresses in ``Notice::mail_dest``. +In the example above we've added ``Notice::ACTION_EMAIL`` to the +``n$actions`` set. This set, defined in the Notice Framework scripts, +can only have entries from the Notice::Action type which is itself an +enumerable that defines the values shown in the table below along with +their corresponding meanings. The ``Notice::ACTION_LOG`` action +writes the notice to the ``Notice::LOG`` logging stream which, in the +default configuration, will write each notice to the notice.log file +and take no further action. The ``Notice::ACTION_EMAIL`` action will +send an email to the address or addresses defined in the +``Notice::mail_dest`` variable with the particulars of the notice as +the body of the email. The last action, ``Notice::ACTION_ALARM`` +sends the notice to the ``Notice::ALARM_LOG`` logging stream which is +then rotated hourly and its contents emailed in readable ASCII to the +addresses in ``Notice::mail_dest``. +--------------+-----------------------------------------------------+ | ACTION_NONE | Take no action | @@ -576,23 +1277,68 @@ In the example above we've added ``Notice::ACTION_EMAIL`` to the ``n$actions`` s | ACTION_ALARM | Send the notice to the Notice::Alarm_LOG stream. | +--------------+-----------------------------------------------------+ -While actions like the ``Notice::ACTION_EMAIL`` action have appeal for quick alerts and response, a caveat of its use is to make sure the notices configured with this action also have a suppression. A suppression is a means through which notices can be ignored after they are initially raised if the author of the script has set an identifier. An identifier is a unique string of information collected from the connection relative to the behavior that has been observed by Bro. +While actions like the ``Notice::ACTION_EMAIL`` action have appeal for +quick alerts and response, a caveat of its use is to make sure the +notices configured with this action also have a suppression. A +suppression is a means through which notices can be ignored after they +are initially raised if the author of the script has set an +identifier. An identifier is a unique string of information collected +from the connection relative to the behavior that has been observed by +Bro. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssl/expiring-certs.bro :language: bro :linenos: :lines: 59-62 -In the ``expiring-certs.bro`` script which identifies when SSL certificates are set to expire and raises notices when it crosses a pre-defined threshold, the call to ``NOTICE()`` above also sets the ``$identifier`` entry by concatenating the responder ip, port, and the hash of the certificate. The selection of responder ip, port and certificate hash fits perfectly into an appropriate identifier as it creates a unique identifier with which the suppression can be matched. Were we to take out any of the entities used for the identifier, for example the certificate hash, we could be setting our suppression too broadly, causing an analyst to miss a notice that should have been raised. Depending on the available data for the identifier, it can be useful to set the ``$suppress_for`` variable as well. The ``expiring-certs.bro`` script sets ``$suppress_for`` to ``1day``, telling the Notice Framework to suppress the notice for 24 hours after the first notice is raised. Once that time limit has passed, another notice can be raised which will again set the ``1day`` suppression time. Suppressing for a specific amount of time has benefits beyond simply not filling up an analyst's email inbox; keeping the notice alerts timely and succinct helps avoid a case where an analyst might see the notice and, due to over exposure, ignore it. +In the ``expiring-certs.bro`` script which identifies when SSL +certificates are set to expire and raises notices when it crosses a +pre-defined threshold, the call to ``NOTICE()`` above also sets the +``$identifier`` entry by concatenating the responder ip, port, and the +hash of the certificate. The selection of responder ip, port and +certificate hash fits perfectly into an appropriate identifier as it +creates a unique identifier with which the suppression can be matched. +Were we to take out any of the entities used for the identifier, for +example the certificate hash, we could be setting our suppression too +broadly, causing an analyst to miss a notice that should have been +raised. Depending on the available data for the identifier, it can be +useful to set the ``$suppress_for`` variable as well. The +``expiring-certs.bro`` script sets ``$suppress_for`` to ``1day``, +telling the Notice Framework to suppress the notice for 24 hours after +the first notice is raised. Once that time limit has passed, another +notice can be raised which will again set the ``1day`` suppression +time. Suppressing for a specific amount of time has benefits beyond +simply not filling up an analyst's email inbox; keeping the notice +alerts timely and succinct helps avoid a case where an analyst might +see the notice and, due to over exposure, ignore it. -The ``$suppress_for`` variable can also be altered in a ``Notice::policy`` hook, allowing a deployment to better suit the environment in which it is be run. Using the example of ``expiring-certs.bro``, we can write a ``Notice::policy`` hook for ``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for`` variable to a shorter time. +The ``$suppress_for`` variable can also be altered in a +``Notice::policy`` hook, allowing a deployment to better suit the +environment in which it is be run. Using the example of +``expiring-certs.bro``, we can write a ``Notice::policy`` hook for +``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for`` +variable to a shorter time. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro :language: bro :linenos: :lines: 6-12 -While ``Notice::policy`` hooks allow you to build custom predicate-based policies for a deployment, there are bound to be times where you don't require the full expressiveness that a hook allows. In short, there will be notice policy considerations where a broad decision can be made based on the ``Notice::Type`` alone. To facilitate these types of decisions, the Notice Framework supports Notice Policy shortcuts. These shortcuts are implemented through the means of a group of data structures that map specific, pre-defined details and actions to the effective name of a notice. Primarily implemented as a set or table of enumerables of ``Notice::Type``, Notice Policy shortcuts can be placed as a single directive in your ``local.bro`` file as a concise readable configuration. As these variables are all constants, it bears mentioning that these variables are all set at parsetime before Bro is fully up and running and not set dynamically. +While ``Notice::policy`` hooks allow you to build custom +predicate-based policies for a deployment, there are bound to be times +where you don't require the full expressiveness that a hook allows. +In short, there will be notice policy considerations where a broad +decision can be made based on the ``Notice::Type`` alone. To +facilitate these types of decisions, the Notice Framework supports +Notice Policy shortcuts. These shortcuts are implemented through the +means of a group of data structures that map specific, pre-defined +details and actions to the effective name of a notice. Primarily +implemented as a set or table of enumerables of ``Notice::Type``, +Notice Policy shortcuts can be placed as a single directive in your +``local.bro`` file as a concise readable configuration. As these +variables are all constants, it bears mentioning that these variables +are all set at parsetime before Bro is fully up and running and not +set dynamically. +------------------------------------+-----------------------------------------------------+-------------------------------------+ | Name | Description | Data Type | @@ -610,14 +1356,28 @@ While ``Notice::policy`` hooks allow you to build custom predicate-based policie -The table above details the five Notice Policy shortcuts, their meaning and the data type used to implement them. With the exception of ``Notice::type_suppression_intervals`` a ``set`` data type is employed to hold the ``Notice::Type`` of the notice upon which a shortcut should applied. The first three shortcuts are fairly self explanatory, applying an action to the ``Notice::Type`` elements in the set, while the latter two shortcuts alter details of the suppression being applied to the Notice. The shortcut ``Notice::not_suppressed_types`` can be used to remove the configured suppression from a notice while ``Notice::type_suppression_intervals`` can be used to alter the suppression interval defined by $suppress_for in the call to ``NOTICE()``. +The table above details the five Notice Policy shortcuts, their +meaning and the data type used to implement them. With the exception +of ``Notice::type_suppression_intervals`` a ``set`` data type is +employed to hold the ``Notice::Type`` of the notice upon which a +shortcut should applied. The first three shortcuts are fairly self +explanatory, applying an action to the ``Notice::Type`` elements in +the set, while the latter two shortcuts alter details of the +suppression being applied to the Notice. The shortcut +``Notice::not_suppressed_types`` can be used to remove the configured +suppression from a notice while ``Notice::type_suppression_intervals`` +can be used to alter the suppression interval defined by $suppress_for +in the call to ``NOTICE()``. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_shortcuts_01.bro :language: bro :linenos: :lines: 7-10 -The Notice Policy shortcut above adds the ``Notice::Types`` of SSH::Interesting_Hostname_Login and SSH::Login to the Notice::emailed_types set while the shortcut below alters the length of time for which those notices will be suppressed. +The Notice Policy shortcut above adds the ``Notice::Types`` of +SSH::Interesting_Hostname_Login and SSH::Login to the +Notice::emailed_types set while the shortcut below alters the length +of time for which those notices will be suppressed. .. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_shortcuts_02.bro :language: bro From 39a848d76b30e7c897c1f7b63ad9befd1cad8da7 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 28 Aug 2013 18:57:23 -0700 Subject: [PATCH 270/881] Updating submodule(s). [nomail] --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 35bb074c1c..26be534261 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 35bb074c1c5173e44689df680a24ba13fea39a11 +Subproject commit 26be534261d3059e381933b362985ba85482ac91 From 13842f2fd514eb62e7da177406a47d5ca94615f0 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 28 Aug 2013 21:12:15 -0700 Subject: [PATCH 271/881] Updating submodule(s). [nomail] --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 26be534261..738bcc72de 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 26be534261d3059e381933b362985ba85482ac91 +Subproject commit 738bcc72de0b0a9a4c3359de8328e9c48f3526ef From fb8b78840b825fef55ebf9520ad0dfef18726dba Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Aug 2013 11:24:24 -0500 Subject: [PATCH 272/881] Fix bloom filter memory leaks. --- src/probabilistic/BloomFilter.cc | 10 +++ src/probabilistic/BloomFilter.h | 10 +++ testing/btest/core/leaks/bloomfilter.bro | 101 +++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 testing/btest/core/leaks/bloomfilter.bro diff --git a/src/probabilistic/BloomFilter.cc b/src/probabilistic/BloomFilter.cc index 4d5c5171ec..f6e4017626 100644 --- a/src/probabilistic/BloomFilter.cc +++ b/src/probabilistic/BloomFilter.cc @@ -125,6 +125,11 @@ BasicBloomFilter::BasicBloomFilter(const Hasher* hasher, size_t cells) bits = new BitVector(cells); } +BasicBloomFilter::~BasicBloomFilter() + { + delete bits; + } + IMPLEMENT_SERIAL(BasicBloomFilter, SER_BASICBLOOMFILTER) bool BasicBloomFilter::DoSerialize(SerialInfo* info) const @@ -173,6 +178,11 @@ CountingBloomFilter::CountingBloomFilter(const Hasher* hasher, cells = new CounterVector(width, arg_cells); } +CountingBloomFilter::~CountingBloomFilter() + { + delete cells; + } + bool CountingBloomFilter::Empty() const { return cells->AllZero(); diff --git a/src/probabilistic/BloomFilter.h b/src/probabilistic/BloomFilter.h index 65dda2396d..53b66c377e 100644 --- a/src/probabilistic/BloomFilter.h +++ b/src/probabilistic/BloomFilter.h @@ -124,6 +124,11 @@ public: */ BasicBloomFilter(const Hasher* hasher, size_t cells); + /** + * Destructor. + */ + ~BasicBloomFilter(); + /** * Computes the number of cells based on a given false positive rate * and capacity. In the literature, this parameter often has the name @@ -192,6 +197,11 @@ public: */ CountingBloomFilter(const Hasher* hasher, size_t cells, size_t width); + /** + * Destructor. + */ + ~CountingBloomFilter(); + // Overridden from BloomFilter. virtual bool Empty() const; virtual void Clear(); diff --git a/testing/btest/core/leaks/bloomfilter.bro b/testing/btest/core/leaks/bloomfilter.bro new file mode 100644 index 0000000000..6d9b74114e --- /dev/null +++ b/testing/btest/core/leaks/bloomfilter.bro @@ -0,0 +1,101 @@ +# Needs perftools support. +# +# @TEST-GROUP: leaks +# +# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks +# +# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local btest-bg-run bro bro -m -b -r $TRACES/wikipedia.trace %INPUT +# @TEST-EXEC: btest-bg-wait 15 + +function test_basic_bloom_filter() + { + # Basic usage with counts. + local bf_cnt = bloomfilter_basic_init(0.1, 1000); + bloomfilter_add(bf_cnt, 42); + bloomfilter_add(bf_cnt, 84); + bloomfilter_add(bf_cnt, 168); + print bloomfilter_lookup(bf_cnt, 0); + print bloomfilter_lookup(bf_cnt, 42); + print bloomfilter_lookup(bf_cnt, 168); + print bloomfilter_lookup(bf_cnt, 336); + bloomfilter_add(bf_cnt, 0.5); # Type mismatch + bloomfilter_add(bf_cnt, "foo"); # Type mismatch + + # Alternative constructor. + local bf_dbl = bloomfilter_basic_init2(4, 10); + bloomfilter_add(bf_dbl, 4.2); + bloomfilter_add(bf_dbl, 3.14); + print bloomfilter_lookup(bf_dbl, 4.2); + print bloomfilter_lookup(bf_dbl, 3.14); + + # Basic usage with strings. + local bf_str = bloomfilter_basic_init(0.9, 10); + bloomfilter_add(bf_str, "foo"); + bloomfilter_add(bf_str, "bar"); + print bloomfilter_lookup(bf_str, "foo"); + print bloomfilter_lookup(bf_str, "bar"); + print bloomfilter_lookup(bf_str, "bazzz"), "fp"; # FP + print bloomfilter_lookup(bf_str, "quuux"), "fp"; # FP + bloomfilter_add(bf_str, 0.5); # Type mismatch + bloomfilter_add(bf_str, 100); # Type mismatch + + # Edge cases. + local bf_edge0 = bloomfilter_basic_init(0.000000000001, 1); + local bf_edge1 = bloomfilter_basic_init(0.00000001, 100000000); + local bf_edge2 = bloomfilter_basic_init(0.9999999, 1); + local bf_edge3 = bloomfilter_basic_init(0.9999999, 100000000000); + + # Invalid parameters. + local bf_bug0 = bloomfilter_basic_init(-0.5, 42); + local bf_bug1 = bloomfilter_basic_init(1.1, 42); + + # Merging + local bf_cnt2 = bloomfilter_basic_init(0.1, 1000); + bloomfilter_add(bf_cnt2, 42); + bloomfilter_add(bf_cnt, 100); + local bf_merged = bloomfilter_merge(bf_cnt, bf_cnt2); + print bloomfilter_lookup(bf_merged, 42); + print bloomfilter_lookup(bf_merged, 84); + print bloomfilter_lookup(bf_merged, 100); + print bloomfilter_lookup(bf_merged, 168); + + #empty filter tests + local bf_empty = bloomfilter_basic_init(0.1, 1000); + local bf_empty_merged = bloomfilter_merge(bf_merged, bf_empty); + print bloomfilter_lookup(bf_empty_merged, 42); + } + +function test_counting_bloom_filter() + { + local bf = bloomfilter_counting_init(3, 32, 3); + bloomfilter_add(bf, "foo"); + print bloomfilter_lookup(bf, "foo"); # 1 + bloomfilter_add(bf, "foo"); + print bloomfilter_lookup(bf, "foo"); # 2 + bloomfilter_add(bf, "foo"); + print bloomfilter_lookup(bf, "foo"); # 3 + bloomfilter_add(bf, "foo"); + print bloomfilter_lookup(bf, "foo"); # still 3 + + + bloomfilter_add(bf, "bar"); + bloomfilter_add(bf, "bar"); + print bloomfilter_lookup(bf, "bar"); # 2 + print bloomfilter_lookup(bf, "foo"); # still 3 + + # Merging + local bf2 = bloomfilter_counting_init(3, 32, 3); + bloomfilter_add(bf2, "baz"); + bloomfilter_add(bf2, "baz"); + bloomfilter_add(bf2, "bar"); + local bf_merged = bloomfilter_merge(bf, bf2); + print bloomfilter_lookup(bf_merged, "foo"); + print bloomfilter_lookup(bf_merged, "bar"); + print bloomfilter_lookup(bf_merged, "baz"); + } + +event new_connection(c: connection) + { + test_basic_bloom_filter(); + test_counting_bloom_filter(); + } From e54ea6d7e911097ca2e61202eadc346ffa30ace2 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Aug 2013 14:09:56 -0500 Subject: [PATCH 273/881] Fix mem leak in socks analyzer for bad addr types. --- src/analyzer/protocol/socks/socks-analyzer.pac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyzer/protocol/socks/socks-analyzer.pac b/src/analyzer/protocol/socks/socks-analyzer.pac index 80051f0b27..311ca852ee 100644 --- a/src/analyzer/protocol/socks/socks-analyzer.pac +++ b/src/analyzer/protocol/socks/socks-analyzer.pac @@ -85,8 +85,8 @@ refine connection SOCKS_Conn += { default: bro_analyzer()->ProtocolViolation(fmt("invalid SOCKSv5 addr type: %d", ${request.remote_name.addr_type})); + delete sa; return false; - break; } BifEvent::generate_socks_request(bro_analyzer(), @@ -124,8 +124,8 @@ refine connection SOCKS_Conn += { default: bro_analyzer()->ProtocolViolation(fmt("invalid SOCKSv5 addr type: %d", ${reply.bound.addr_type})); + delete sa; return false; - break; } BifEvent::generate_socks_reply(bro_analyzer(), From b6e2505202c0213f226f3e7c83bc6b346311b366 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Aug 2013 14:13:16 -0500 Subject: [PATCH 274/881] Fix input framework memory leaks. Couldn't figure out a test case: gperftools didn't report them (maybe due to threading?), but valgrind did. --- src/input/Manager.cc | 21 ++++++++++----------- src/input/ReaderBackend.h | 1 + 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/input/Manager.cc b/src/input/Manager.cc index d467e32005..9e8e406346 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -74,7 +74,6 @@ declare(PDict, InputHash); class Manager::Stream { public: string name; - ReaderBackend::ReaderInfo* info; bool removed; StreamType stream_type; // to distinguish between event and table streams @@ -318,23 +317,23 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) string source((const char*) bsource->Bytes(), bsource->Len()); Unref(sourceval); - ReaderBackend::ReaderInfo* rinfo = new ReaderBackend::ReaderInfo(); - rinfo->source = copy_string(source.c_str()); - rinfo->name = copy_string(name.c_str()); + ReaderBackend::ReaderInfo rinfo; + rinfo.source = copy_string(source.c_str()); + rinfo.name = copy_string(name.c_str()); EnumVal* mode = description->LookupWithDefault(rtype->FieldOffset("mode"))->AsEnumVal(); switch ( mode->InternalInt() ) { case 0: - rinfo->mode = MODE_MANUAL; + rinfo.mode = MODE_MANUAL; break; case 1: - rinfo->mode = MODE_REREAD; + rinfo.mode = MODE_REREAD; break; case 2: - rinfo->mode = MODE_STREAM; + rinfo.mode = MODE_STREAM; break; default: @@ -357,7 +356,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) ListVal* index = info->config->RecoverIndex(k); string key = index->Index(0)->AsString()->CheckString(); string value = v->Value()->AsString()->CheckString(); - rinfo->config.insert(std::make_pair(copy_string(key.c_str()), copy_string(value.c_str()))); + rinfo.config.insert(std::make_pair(copy_string(key.c_str()), copy_string(value.c_str()))); Unref(index); delete k; } @@ -365,13 +364,12 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) } - ReaderFrontend* reader_obj = new ReaderFrontend(*rinfo, reader); + ReaderFrontend* reader_obj = new ReaderFrontend(rinfo, reader); assert(reader_obj); info->reader = reader_obj; info->type = reader->AsEnumVal(); // ref'd by lookupwithdefault info->name = name; - info->info = rinfo; Ref(description); info->description = description; @@ -1356,7 +1354,8 @@ void Manager::SendEndOfData(const Stream *i) DBG_LOG(DBG_INPUT, "SendEndOfData for stream %s", i->name.c_str()); #endif - SendEvent(end_of_data, 2, new StringVal(i->name.c_str()), new StringVal(i->info->source)); + SendEvent(end_of_data, 2, new StringVal(i->name.c_str()), + new StringVal(i->reader->Info().source)); if ( i->stream_type == ANALYSIS_STREAM ) file_mgr->EndOfFile(static_cast(i)->file_id); diff --git a/src/input/ReaderBackend.h b/src/input/ReaderBackend.h index 5419879e13..84984a3ce5 100644 --- a/src/input/ReaderBackend.h +++ b/src/input/ReaderBackend.h @@ -121,6 +121,7 @@ public: ~ReaderInfo() { delete [] source; + delete [] name; for ( config_map::iterator i = config.begin(); i != config.end(); i++ ) { From c4e8908c8e267c1e93fd7fa0c9df22f474ec47f3 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Aug 2013 15:50:46 -0500 Subject: [PATCH 275/881] Fix invalid pointer dereference in AsciiFormatter. Using a temporary object with strtol() makes the end pointer that it sets invalid after the call. --- src/threading/AsciiFormatter.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/threading/AsciiFormatter.cc b/src/threading/AsciiFormatter.cc index cb1c57f6f1..616abbe2b6 100644 --- a/src/threading/AsciiFormatter.cc +++ b/src/threading/AsciiFormatter.cc @@ -247,7 +247,8 @@ threading::Value* AsciiFormatter::ParseValue(string s, string name, TypeTag type goto parse_error; } - uint8_t width = (uint8_t) strtol(s.substr(pos+1).c_str(), &end, 10); + string width_str = s.substr(pos + 1); + uint8_t width = (uint8_t) strtol(width_str.c_str(), &end, 10); if ( CheckNumberError(s, end) ) goto parse_error; From 4cd20c6375bcf8d417cfaa6f7eb3285a12f102c4 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 29 Aug 2013 14:01:22 -0700 Subject: [PATCH 276/881] add clustered leak test for hll. No issues. --- .../core.leaks.hll_cluster/manager-1..stdout | 2 + .../core.leaks.hll_cluster/worker-1..stdout | 2 + .../core.leaks.hll_cluster/worker-2..stdout | 2 + testing/btest/core/leaks/hll_cluster.bro | 111 ++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 testing/btest/Baseline/core.leaks.hll_cluster/manager-1..stdout create mode 100644 testing/btest/Baseline/core.leaks.hll_cluster/worker-1..stdout create mode 100644 testing/btest/Baseline/core.leaks.hll_cluster/worker-2..stdout create mode 100644 testing/btest/core/leaks/hll_cluster.bro diff --git a/testing/btest/Baseline/core.leaks.hll_cluster/manager-1..stdout b/testing/btest/Baseline/core.leaks.hll_cluster/manager-1..stdout new file mode 100644 index 0000000000..910a87642c --- /dev/null +++ b/testing/btest/Baseline/core.leaks.hll_cluster/manager-1..stdout @@ -0,0 +1,2 @@ +This value should be about 21: +21.003365 diff --git a/testing/btest/Baseline/core.leaks.hll_cluster/worker-1..stdout b/testing/btest/Baseline/core.leaks.hll_cluster/worker-1..stdout new file mode 100644 index 0000000000..e64c2b30aa --- /dev/null +++ b/testing/btest/Baseline/core.leaks.hll_cluster/worker-1..stdout @@ -0,0 +1,2 @@ +This value should be around 13: +13.00129 diff --git a/testing/btest/Baseline/core.leaks.hll_cluster/worker-2..stdout b/testing/btest/Baseline/core.leaks.hll_cluster/worker-2..stdout new file mode 100644 index 0000000000..d2b4f08b8d --- /dev/null +++ b/testing/btest/Baseline/core.leaks.hll_cluster/worker-2..stdout @@ -0,0 +1,2 @@ +This value should be about 12: +12.001099 diff --git a/testing/btest/core/leaks/hll_cluster.bro b/testing/btest/core/leaks/hll_cluster.bro new file mode 100644 index 0000000000..01653a895f --- /dev/null +++ b/testing/btest/core/leaks/hll_cluster.bro @@ -0,0 +1,111 @@ +# Needs perftools support. +# +# @TEST-SERIALIZE: comm +# @TEST-GROUP: leaks +# +# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks +# +# @TEST-EXEC: bro %INPUT>out +# @TEST-EXEC: btest-bg-run manager-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro %INPUT +# @TEST-EXEC: sleep 2 +# @TEST-EXEC: btest-bg-run worker-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro runnumber=1 %INPUT +# @TEST-EXEC: btest-bg-run worker-2 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro runnumber=2 %INPUT +# @TEST-EXEC: btest-bg-wait -k 10 +# +# @TEST-EXEC: btest-diff manager-1/.stdout +# @TEST-EXEC: btest-diff worker-1/.stdout +# @TEST-EXEC: btest-diff worker-2/.stdout + +@TEST-START-FILE cluster-layout.bro +redef Cluster::nodes = { + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1", "worker-2")], + ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37760/tcp, $manager="manager-1"], + ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37761/tcp, $manager="manager-1"], +}; +@TEST-END-FILE + +redef Log::default_rotation_interval = 0secs; + +global hll_data: event(data: opaque of cardinality); + +redef Cluster::worker2manager_events += /hll_data/; + +@if ( Cluster::local_node_type() == Cluster::WORKER ) + +global runnumber: count &redef; # differentiate runs + +event remote_connection_handshake_done(p: event_peer) + { + local c = hll_cardinality_init(0.01); + + local add1 = 2001; + local add2 = 2002; + local add3 = 2003; + + if ( runnumber == 1 ) + { + hll_cardinality_add(c, add1); + hll_cardinality_add(c, add2); + hll_cardinality_add(c, add3); + hll_cardinality_add(c, 1000); + hll_cardinality_add(c, 1001); + hll_cardinality_add(c, 101); + hll_cardinality_add(c, 1003); + hll_cardinality_add(c, 1004); + hll_cardinality_add(c, 1005); + hll_cardinality_add(c, 1006); + hll_cardinality_add(c, 1007); + hll_cardinality_add(c, 1008); + hll_cardinality_add(c, 1009); + print "This value should be around 13:"; + print hll_cardinality_estimate(c); + } + else if ( runnumber == 2 ) + { + hll_cardinality_add(c, add1); + hll_cardinality_add(c, add2); + hll_cardinality_add(c, add3); + hll_cardinality_add(c, 1); + hll_cardinality_add(c, 101); + hll_cardinality_add(c, 2); + hll_cardinality_add(c, 3); + hll_cardinality_add(c, 4); + hll_cardinality_add(c, 5); + hll_cardinality_add(c, 6); + hll_cardinality_add(c, 7); + hll_cardinality_add(c, 8); + print "This value should be about 12:"; + print hll_cardinality_estimate(c); + } + + event hll_data(c); + + terminate(); + } + +@endif + +@if ( Cluster::local_node_type() == Cluster::MANAGER ) + +global result_count = 0; +global hll: opaque of cardinality; + +event bro_init() + { + hll = hll_cardinality_init(0.01); + } + +event hll_data(data: opaque of cardinality) + { + hll_cardinality_merge_into(hll, data); + ++result_count; + + if ( result_count == 2 ) + { + print "This value should be about 21:"; + print hll_cardinality_estimate(hll); + terminate(); + } + } + +@endif From 742a047a40e6eeb32aea9ededf6bd294d5263ff8 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Aug 2013 16:22:59 -0500 Subject: [PATCH 277/881] Fix malloc/delete mismatch. --- src/input/Manager.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/input/Manager.cc b/src/input/Manager.cc index 9e8e406346..2534ed1b69 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -2090,9 +2090,7 @@ HashKey* Manager::HashValues(const int num_elements, const Value* const *vals) return NULL; int position = 0; - char *data = (char*) malloc(length); - if ( data == 0 ) - reporter->InternalError("Could not malloc?"); + char *data = new char[length]; for ( int i = 0; i < num_elements; i++ ) { @@ -2108,7 +2106,7 @@ HashKey* Manager::HashValues(const int num_elements, const Value* const *vals) } HashKey *key = new HashKey(data, length); - delete data; + delete [] data; assert(position == length); return key; From dc2e3d6e04ad7504989b0b377f3c2f6cb9e1a2ef Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 29 Aug 2013 17:17:40 -0500 Subject: [PATCH 278/881] Fix global opaque val segfault, addresses BIT-1071 The opaque types need to be created before scripts are parsed. --- src/NetVar.cc | 14 -------------- src/NetVar.h | 8 -------- src/Type.h | 7 +++++++ src/main.cc | 14 ++++++++++++++ .../btest/Baseline/core.global_opaque_val/output | 1 + testing/btest/core/global_opaque_val.bro | 12 ++++++++++++ 6 files changed, 34 insertions(+), 22 deletions(-) create mode 100644 testing/btest/Baseline/core.global_opaque_val/output create mode 100644 testing/btest/core/global_opaque_val.bro diff --git a/src/NetVar.cc b/src/NetVar.cc index dad0547059..7a11c3f2d1 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -242,13 +242,6 @@ StringVal* global_hash_seed; bro_uint_t bits_per_uid; -OpaqueType* md5_type; -OpaqueType* sha1_type; -OpaqueType* sha256_type; -OpaqueType* entropy_type; -OpaqueType* topk_type; -OpaqueType* bloomfilter_type; - #include "const.bif.netvar_def" #include "types.bif.netvar_def" #include "event.bif.netvar_def" @@ -312,13 +305,6 @@ void init_general_global_var() global_hash_seed = opt_internal_string("global_hash_seed"); bits_per_uid = opt_internal_unsigned("bits_per_uid"); - - md5_type = new OpaqueType("md5"); - sha1_type = new OpaqueType("sha1"); - sha256_type = new OpaqueType("sha256"); - entropy_type = new OpaqueType("entropy"); - topk_type = new OpaqueType("topk"); - bloomfilter_type = new OpaqueType("bloomfilter"); } void init_net_var() diff --git a/src/NetVar.h b/src/NetVar.h index aa808abb59..c30895d5d4 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -246,14 +246,6 @@ extern StringVal* global_hash_seed; extern bro_uint_t bits_per_uid; -class OpaqueType; -extern OpaqueType* md5_type; -extern OpaqueType* sha1_type; -extern OpaqueType* sha256_type; -extern OpaqueType* entropy_type; -extern OpaqueType* topk_type; -extern OpaqueType* bloomfilter_type; - // Initializes globals that don't pertain to network/event analysis. extern void init_general_global_var(); diff --git a/src/Type.h b/src/Type.h index b10e249745..52fdfe5043 100644 --- a/src/Type.h +++ b/src/Type.h @@ -609,6 +609,13 @@ protected: BroType* yield_type; }; +extern OpaqueType* md5_type; +extern OpaqueType* sha1_type; +extern OpaqueType* sha256_type; +extern OpaqueType* entropy_type; +extern OpaqueType* topk_type; +extern OpaqueType* bloomfilter_type; + // Returns the BRO basic (non-parameterized) type with the given type. extern BroType* base_type(TypeTag tag); diff --git a/src/main.cc b/src/main.cc index 9868f62be9..bc47e21fc5 100644 --- a/src/main.cc +++ b/src/main.cc @@ -124,6 +124,13 @@ vector params; char* proc_status_file = 0; int snaplen = 0; // this gets set from the scripting-layer's value +OpaqueType* md5_type = 0; +OpaqueType* sha1_type = 0; +OpaqueType* sha256_type = 0; +OpaqueType* entropy_type = 0; +OpaqueType* topk_type = 0; +OpaqueType* bloomfilter_type = 0; + extern std::list docs_generated; // Keep copy of command line @@ -845,6 +852,13 @@ int main(int argc, char** argv) input::reader::Raw::ClassInit(); + md5_type = new OpaqueType("md5"); + sha1_type = new OpaqueType("sha1"); + sha256_type = new OpaqueType("sha256"); + entropy_type = new OpaqueType("entropy"); + topk_type = new OpaqueType("topk"); + bloomfilter_type = new OpaqueType("bloomfilter"); + // The leak-checker tends to produce some false // positives (memory which had already been // allocated before we start the checking is diff --git a/testing/btest/Baseline/core.global_opaque_val/output b/testing/btest/Baseline/core.global_opaque_val/output new file mode 100644 index 0000000000..db604ebbf4 --- /dev/null +++ b/testing/btest/Baseline/core.global_opaque_val/output @@ -0,0 +1 @@ +7b0391feb2e0cd271f1cf39aafb4376f diff --git a/testing/btest/core/global_opaque_val.bro b/testing/btest/core/global_opaque_val.bro new file mode 100644 index 0000000000..84087d8295 --- /dev/null +++ b/testing/btest/core/global_opaque_val.bro @@ -0,0 +1,12 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +global test = md5_hash_init(); + +event bro_init() + { + md5_hash_update(test, "one"); + md5_hash_update(test, "two"); + md5_hash_update(test, "three"); + print md5_hash_finish(test); + } From b74bf10565cdb6415132771db6048f86d33ddd2e Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 28 Aug 2013 18:05:01 -0700 Subject: [PATCH 279/881] Going over initial parts of the scripting overview. I made a light pass over the text. Switched the includes over to the new btest-include and adapted the other TEXT-EXECs a bit. Also includes more tweaking all over the Sphinx setup. --- aux/btest | 2 +- doc/conf.py.in | 6 +- doc/ext/rootedliteralinclude.py | 25 - doc/index.rst | 2 +- doc/install/changes.rst | 6 +- doc/quickstart/index.rst | 3 - doc/scripting/connection_record_01.bro | 6 + doc/scripting/connection_record_02.bro | 7 + doc/scripting/data_struct_record_01.bro | 22 + .../scripting}/data_struct_record_02.bro | 14 +- .../data_struct_set_declaration.bro | 12 +- .../scripting}/data_struct_table_complex.bro | 6 +- .../data_struct_table_declaration.bro | 10 +- .../scripting}/data_struct_vector.bro | 5 +- .../data_struct_vector_declaration.bro | 7 +- doc/scripting/data_struct_vector_iter.bro | 7 + doc/scripting/data_type_const.bro | 9 + .../scripting}/data_type_const_simple.bro | 3 - doc/scripting/data_type_declaration.bro | 9 + .../scripting}/data_type_interval.bro | 14 +- doc/scripting/data_type_local.bro | 11 + .../scripting}/data_type_pattern_01.bro | 9 +- .../scripting}/data_type_pattern_02.bro | 4 - doc/scripting/data_type_subnets.bro | 15 + doc/scripting/data_type_time.bro | 4 + .../framework_logging_factorial_01.bro | 19 + .../framework_logging_factorial_02.bro | 10 +- .../framework_logging_factorial_03.bro | 27 +- .../framework_logging_factorial_04.bro | 20 +- doc/scripting/framework_notice_hook_01.bro | 7 + .../framework_notice_hook_suppression_01.bro | 7 + .../framework_notice_shortcuts_01.bro | 3 - .../framework_notice_shortcuts_02.bro | 3 - doc/scripting/index.rst | 1050 ++++++++--------- .../scripting}/using_bro_sandbox_01 | 0 .../scripting}/using_bro_sandbox_02 | 0 doc/using/index.rst | 3 +- .../btest-doc.sphinx.connection-record-01#1 | 11 + .../btest-doc.sphinx.connection-record-02#1 | 17 + .../btest-doc.sphinx.data_struct_record_01#1 | 12 + .../btest-doc.sphinx.data_struct_record_02#1 | 13 + ...t-doc.sphinx.data_struct_set_declaration#1 | 14 + ...est-doc.sphinx.data_struct_table_complex#1 | 10 + ...doc.sphinx.data_struct_table_declaration#1 | 10 + ...oc.sphinx.data_struct_vector_declaration#1 | 10 + ...btest-doc.sphinx.data_struct_vector_iter#1 | 9 + .../btest-doc.sphinx.data_type_const.bro#1 | 10 + .../btest-doc.sphinx.data_type_interval#1 | 23 + .../btest-doc.sphinx.data_type_pattern#1 | 9 + .../btest-doc.sphinx.data_type_pattern_02#1 | 8 + .../btest-doc.sphinx.data_type_subnets#1 | 10 + .../btest-doc.sphinx.data_type_time#1 | 15 + ...doc.sphinx.framework_logging_factorial-2#1 | 29 + ...doc.sphinx.framework_logging_factorial-3#1 | 25 + ...t-doc.sphinx.framework_logging_factorial#1 | 16 + ..._scripting_connection_record_02_bro.btest} | 9 +- ...scripting_connection_record_02_bro@2.btest | 11 + ...scripting_data_struct_record_01_bro.btest} | 15 +- ..._scripting_data_struct_record_02_bro.btest | 45 + ...ting_data_struct_set_declaration_bro.btest | 9 + ...ng_data_struct_set_declaration_bro@2.btest | 9 + ...ng_data_struct_set_declaration_bro@3.btest | 7 + ...ng_data_struct_set_declaration_bro@4.btest | 26 + ...ipting_data_struct_table_complex_bro.btest | 17 + ...ng_data_struct_table_declaration_bro.btest | 17 + ...g_data_struct_vector_declaration_bro.btest | 19 + ...cripting_data_struct_vector_iter_bro.btest | 11 + ...e-doc_scripting_data_type_const_bro.btest} | 7 +- ...scripting_data_type_const_simple_bro.btest | 8 + ...scripting_data_type_declaration_bro.btest} | 11 +- ...doc_scripting_data_type_interval_bro.btest | 22 + ...e-doc_scripting_data_type_local_bro.btest} | 7 +- ...c_scripting_data_type_pattern_01_bro.btest | 17 + ...c_scripting_data_type_pattern_02_bro.btest | 14 + ...doc_scripting_data_type_subnets_bro.btest} | 17 +- ...de-doc_scripting_data_type_time_bro.btest} | 9 +- ..._framework_logging_factorial_01_bro.btest} | 12 +- ...g_framework_logging_factorial_02_bro.btest | 36 + ...g_framework_logging_factorial_03_bro.btest | 12 + ...g_framework_logging_factorial_04_bro.btest | 54 + ...ipting_framework_notice_hook_01_bro.btest} | 9 +- ...work_notice_hook_suppression_01_bro.btest} | 7 +- ...ng_framework_notice_shortcuts_01_bro.btest | 12 + ...ng_framework_notice_shortcuts_02_bro.btest | 11 + ...clude-scripts_base_bif_event_bif_bro.btest | 25 + ...e_bif_plugins_Bro_DNS_events_bif_bro.btest | 30 + ...o.include-scripts_base_init-bare_bro.btest | 7 + ...scripts_base_protocols_conn_main_bro.btest | 28 + ...scripts_base_protocols_http_main_bro.btest | 10 + ...licy_frameworks_files_detect-MHR_bro.btest | 61 + ...cy_frameworks_files_detect-MHR_bro@2.btest | 9 + ...cy_frameworks_files_detect-MHR_bro@3.btest | 17 + ...cy_frameworks_files_detect-MHR_bro@4.btest | 23 + ...olicy_protocols_conn_known-hosts_bro.btest | 9 + ...tocols_ssh_interesting-hostnames_bro.btest | 50 + ...icy_protocols_ssl_expiring-certs_bro.btest | 8 + .../doc.sphinx.test/btest-doc.sphinx.test.rst | 13 - .../btest-doc.sphinx.using_bro#1 | 11 +- .../btest-doc.sphinx.using_bro#2 | 2 + .../btest-doc.sphinx.using_bro#3 | 2 + .../btest-doc.sphinx.using_bro#4 | 2 + .../btest-doc.sphinx.using_bro#5 | 2 + .../btest-doc.sphinx.using_bro#6 | 2 + .../btest-doc.sphinx.using_bro#7 | 2 + .../btest-doc.sphinx.using_bro#8 | 2 + testing/btest/btest.cfg | 1 + .../btest/doc/manual/connection_record_01.bro | 9 - .../doc/manual/data_struct_vector_iter.bro | 12 - .../doc/sphinx/connection-record-01.btest | 1 + .../doc/sphinx/connection-record-02.btest | 1 + .../doc/sphinx/data_struct_record_01.btest | 1 + .../doc/sphinx/data_struct_record_02.btest | 1 + .../sphinx/data_struct_set_declaration.btest | 1 + .../sphinx/data_struct_table_complex.btest | 1 + .../data_struct_table_declaration.btest | 1 + .../data_struct_vector_declaration.btest | 1 + .../doc/sphinx/data_struct_vector_iter.btest | 1 + .../doc/sphinx/data_type_const.bro.btest | 1 + .../btest/doc/sphinx/data_type_interval.btest | 1 + .../btest/doc/sphinx/data_type_pattern.btest | 1 + .../doc/sphinx/data_type_pattern_02.btest | 1 + .../btest/doc/sphinx/data_type_subnets.btest | 1 + testing/btest/doc/sphinx/data_type_time.btest | 1 + .../framework_logging_factorial-2.btest | 2 + .../framework_logging_factorial-3.btest | 2 + .../sphinx/framework_logging_factorial.btest | 1 + ...c_scripting_connection_record_02_bro.btest | 11 + ...scripting_connection_record_02_bro@2.btest | 11 + ..._scripting_data_struct_record_01_bro.btest | 26 + ..._scripting_data_struct_record_02_bro.btest | 45 + ...ting_data_struct_set_declaration_bro.btest | 9 + ...ng_data_struct_set_declaration_bro@2.btest | 9 + ...ng_data_struct_set_declaration_bro@3.btest | 7 + ...ng_data_struct_set_declaration_bro@4.btest | 26 + ...ipting_data_struct_table_complex_bro.btest | 17 + ...ng_data_struct_table_declaration_bro.btest | 17 + ...g_data_struct_vector_declaration_bro.btest | 19 + ...cripting_data_struct_vector_iter_bro.btest | 11 + ...de-doc_scripting_data_type_const_bro.btest | 13 + ...scripting_data_type_const_simple_bro.btest | 8 + ..._scripting_data_type_declaration_bro.btest | 13 + ...doc_scripting_data_type_interval_bro.btest | 22 + ...de-doc_scripting_data_type_local_bro.btest | 15 + ...c_scripting_data_type_pattern_01_bro.btest | 17 + ...c_scripting_data_type_pattern_02_bro.btest | 14 + ...-doc_scripting_data_type_subnets_bro.btest | 19 + ...ude-doc_scripting_data_type_time_bro.btest | 8 + ...g_framework_logging_factorial_01_bro.btest | 23 + ...g_framework_logging_factorial_02_bro.btest | 36 + ...g_framework_logging_factorial_03_bro.btest | 12 + ...g_framework_logging_factorial_04_bro.btest | 54 + ...ripting_framework_notice_hook_01_bro.btest | 11 + ...ework_notice_hook_suppression_01_bro.btest | 11 + ...ng_framework_notice_shortcuts_01_bro.btest | 12 + ...ng_framework_notice_shortcuts_02_bro.btest | 11 + ...clude-scripts_base_bif_event_bif_bro.btest | 25 + ...e_bif_plugins_Bro_DNS_events_bif_bro.btest | 30 + .../include-scripts_base_init-bare_bro.btest | 7 + ...scripts_base_protocols_conn_main_bro.btest | 28 + ...scripts_base_protocols_http_main_bro.btest | 10 + ...licy_frameworks_files_detect-MHR_bro.btest | 61 + ...cy_frameworks_files_detect-MHR_bro@2.btest | 9 + ...cy_frameworks_files_detect-MHR_bro@3.btest | 17 + ...cy_frameworks_files_detect-MHR_bro@4.btest | 23 + ...olicy_protocols_conn_known-hosts_bro.btest | 9 + ...tocols_ssh_interesting-hostnames_bro.btest | 50 + ...icy_protocols_ssl_expiring-certs_bro.btest | 8 + testing/btest/doc/sphinx/using_bro.btest | 3 +- testing/scripts/rst-filter | 3 +- 169 files changed, 2421 insertions(+), 804 deletions(-) delete mode 100644 doc/ext/rootedliteralinclude.py create mode 100644 doc/scripting/connection_record_01.bro create mode 100644 doc/scripting/connection_record_02.bro create mode 100644 doc/scripting/data_struct_record_01.bro rename {testing/btest/doc/manual => doc/scripting}/data_struct_record_02.bro (86%) rename {testing/btest/doc/manual => doc/scripting}/data_struct_set_declaration.bro (79%) rename {testing/btest/doc/manual => doc/scripting}/data_struct_table_complex.bro (88%) rename {testing/btest/doc/manual => doc/scripting}/data_struct_table_declaration.bro (77%) rename {testing/btest/doc/manual => doc/scripting}/data_struct_vector.bro (67%) rename {testing/btest/doc/manual => doc/scripting}/data_struct_vector_declaration.bro (83%) create mode 100644 doc/scripting/data_struct_vector_iter.bro create mode 100644 doc/scripting/data_type_const.bro rename {testing/btest/doc/manual => doc/scripting}/data_type_const_simple.bro (53%) create mode 100644 doc/scripting/data_type_declaration.bro rename {testing/btest/doc/manual => doc/scripting}/data_type_interval.bro (80%) create mode 100644 doc/scripting/data_type_local.bro rename {testing/btest/doc/manual => doc/scripting}/data_type_pattern_01.bro (73%) rename {testing/btest/doc/manual => doc/scripting}/data_type_pattern_02.bro (85%) create mode 100644 doc/scripting/data_type_subnets.bro create mode 100644 doc/scripting/data_type_time.bro create mode 100644 doc/scripting/framework_logging_factorial_01.bro rename {testing/btest/doc/manual => doc/scripting}/framework_logging_factorial_02.bro (84%) rename {testing/btest/doc/manual => doc/scripting}/framework_logging_factorial_03.bro (77%) rename {testing/btest/doc/manual => doc/scripting}/framework_logging_factorial_04.bro (80%) create mode 100644 doc/scripting/framework_notice_hook_01.bro create mode 100644 doc/scripting/framework_notice_hook_suppression_01.bro rename {testing/btest/doc/manual => doc/scripting}/framework_notice_shortcuts_01.bro (74%) rename {testing/btest/doc/manual => doc/scripting}/framework_notice_shortcuts_02.bro (77%) rename {testing/btest/doc/manual => doc/scripting}/using_bro_sandbox_01 (100%) rename {testing/btest/doc/manual => doc/scripting}/using_bro_sandbox_02 (100%) create mode 100644 testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 create mode 100644 testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 create mode 100644 testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 create mode 100644 testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 create mode 100644 testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 create mode 100644 testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 rename testing/btest/{doc/manual/connection_record_02.bro => Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest} (53%) create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest rename testing/btest/{doc/manual/data_struct_record_01.bro => Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest} (53%) create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest rename testing/btest/{doc/manual/data_type_const.bro => Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest} (72%) create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest rename testing/btest/{doc/manual/data_type_declaration.bro => Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest} (53%) create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest rename testing/btest/{doc/manual/data_type_local.bro => Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest} (75%) create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest rename testing/btest/{doc/manual/data_type_subnets.bro => Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest} (63%) rename testing/btest/{doc/manual/data_type_time.bro => Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest} (66%) rename testing/btest/{doc/manual/framework_logging_factorial_01.bro => Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest} (73%) create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest rename testing/btest/{doc/manual/framework_notice_hook_01.bro => Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest} (71%) rename testing/btest/{doc/manual/framework_notice_hook_suppression_01.bro => Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest} (69%) create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest create mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest delete mode 100644 testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst delete mode 100644 testing/btest/doc/manual/connection_record_01.bro delete mode 100644 testing/btest/doc/manual/data_struct_vector_iter.bro create mode 100644 testing/btest/doc/sphinx/connection-record-01.btest create mode 100644 testing/btest/doc/sphinx/connection-record-02.btest create mode 100644 testing/btest/doc/sphinx/data_struct_record_01.btest create mode 100644 testing/btest/doc/sphinx/data_struct_record_02.btest create mode 100644 testing/btest/doc/sphinx/data_struct_set_declaration.btest create mode 100644 testing/btest/doc/sphinx/data_struct_table_complex.btest create mode 100644 testing/btest/doc/sphinx/data_struct_table_declaration.btest create mode 100644 testing/btest/doc/sphinx/data_struct_vector_declaration.btest create mode 100644 testing/btest/doc/sphinx/data_struct_vector_iter.btest create mode 100644 testing/btest/doc/sphinx/data_type_const.bro.btest create mode 100644 testing/btest/doc/sphinx/data_type_interval.btest create mode 100644 testing/btest/doc/sphinx/data_type_pattern.btest create mode 100644 testing/btest/doc/sphinx/data_type_pattern_02.btest create mode 100644 testing/btest/doc/sphinx/data_type_subnets.btest create mode 100644 testing/btest/doc/sphinx/data_type_time.btest create mode 100644 testing/btest/doc/sphinx/framework_logging_factorial-2.btest create mode 100644 testing/btest/doc/sphinx/framework_logging_factorial-3.btest create mode 100644 testing/btest/doc/sphinx/framework_logging_factorial.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest create mode 100644 testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest create mode 100644 testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest diff --git a/aux/btest b/aux/btest index 35bb074c1c..9726c5b982 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 35bb074c1c5173e44689df680a24ba13fea39a11 +Subproject commit 9726c5b982ee0e3e730a15dcd65f49bdee3fe458 diff --git a/doc/conf.py.in b/doc/conf.py.in index 8ca8d70a7a..e5e093d498 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -41,10 +41,10 @@ btest_tests="doc/sphinx" # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions += ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc', - 'rootedliteralinclude'] +extensions += ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc'] os.environ["BRO_SRC_ROOT"] = "@CMAKE_SOURCE_DIR@" +os.environ["DOC_ROOT"] = "@CMAKE_SOURCE_DIR@/doc" # Add any paths that contain templates here, relative to this directory. templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static'] @@ -83,7 +83,7 @@ today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = [] +exclude_patterns = [".#*"] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None diff --git a/doc/ext/rootedliteralinclude.py b/doc/ext/rootedliteralinclude.py deleted file mode 100644 index 7b4aea5547..0000000000 --- a/doc/ext/rootedliteralinclude.py +++ /dev/null @@ -1,25 +0,0 @@ -import os -from sphinx.directives.code import LiteralInclude - -def setup(app): - app.add_directive('rootedliteralinclude', RootedLiteralInclude) - -class RootedLiteralInclude(LiteralInclude): - """ - Like ``.. literalinclude::``, but the argument is an absolute path - which may contain environment variables which will be expanded when - generating documents. - """ - - def run(self): - document = self.state.document - if not document.settings.file_insertion_enabled: - return [document.reporter.warning('File insertion disabled', - line=self.lineno)] - env = document.settings.env - - expanded_arg = os.path.expandvars(self.arguments[0]) - sphinx_src_relation = os.path.relpath(expanded_arg, env.srcdir) - self.arguments[0] = os.path.join(os.sep, sphinx_src_relation) - - return super(RootedLiteralInclude, self).run() diff --git a/doc/index.rst b/doc/index.rst index 5afbb022a1..2dee7a4fb2 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,8 +9,8 @@ Bro Documentation :maxdepth: 2 intro/index.rst - quickstart/index.rst install/index.rst + quickstart/index.rst using/index.rst scripting/index.rst frameworks/index.rst diff --git a/doc/install/changes.rst b/doc/install/changes.rst index 5a1bd97220..32cd6ad33e 100644 --- a/doc/install/changes.rst +++ b/doc/install/changes.rst @@ -1,7 +1,7 @@ -=========================================== -Comprehensive Version History (aka CHANGES) -=========================================== +======================== +Detailed Version History +======================== .. contents:: diff --git a/doc/quickstart/index.rst b/doc/quickstart/index.rst index 89de40e948..e07e729a02 100644 --- a/doc/quickstart/index.rst +++ b/doc/quickstart/index.rst @@ -7,9 +7,6 @@ Quick Start Guide .. contents:: -Installation -============ - Bro works on most modern, Unix-based systems and requires no custom hardware. It can be downloaded in either pre-built binary package or source code forms. See :ref:`installing-bro` for instructions on how to diff --git a/doc/scripting/connection_record_01.bro b/doc/scripting/connection_record_01.bro new file mode 100644 index 0000000000..9800fb0520 --- /dev/null +++ b/doc/scripting/connection_record_01.bro @@ -0,0 +1,6 @@ +@load base/protocols/conn + +event connection_state_remove(c: connection) + { + print c; + } diff --git a/doc/scripting/connection_record_02.bro b/doc/scripting/connection_record_02.bro new file mode 100644 index 0000000000..4459e47ef6 --- /dev/null +++ b/doc/scripting/connection_record_02.bro @@ -0,0 +1,7 @@ +@load base/protocols/conn +@load base/protocols/dns + +event connection_state_remove(c: connection) + { + print c; + } diff --git a/doc/scripting/data_struct_record_01.bro b/doc/scripting/data_struct_record_01.bro new file mode 100644 index 0000000000..a80d30faae --- /dev/null +++ b/doc/scripting/data_struct_record_01.bro @@ -0,0 +1,22 @@ +type Service: record { + name: string; + ports: set[port]; + rfc: count; +}; + +function print_service(serv: Service): string + { + print fmt("Service: %s(RFC%d)",serv$name, serv$rfc); + + for ( p in serv$ports ) + print fmt(" port: %s", p); + } + +event bro_init() + { + local dns: Service = [$name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; + local http: Service = [$name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; + + print_service(dns); + print_service(http); + } diff --git a/testing/btest/doc/manual/data_struct_record_02.bro b/doc/scripting/data_struct_record_02.bro similarity index 86% rename from testing/btest/doc/manual/data_struct_record_02.bro rename to doc/scripting/data_struct_record_02.bro index e340bc5744..b10b3feac0 100644 --- a/testing/btest/doc/manual/data_struct_record_02.bro +++ b/doc/scripting/data_struct_record_02.bro @@ -1,6 +1,3 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - type Service: record { name: string; ports: set[port]; @@ -12,23 +9,20 @@ type System: record { services: set[Service]; }; - function print_service(serv: Service): string { print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc); - for (p in serv$ports) - { + + for ( p in serv$ports ) print fmt(" port: %s", p); - } } function print_system(sys: System): string { print fmt("System: %s", sys$name); - for (s in sys$services) - { + + for ( s in sys$services ) print_service(s); - } } event bro_init() diff --git a/testing/btest/doc/manual/data_struct_set_declaration.bro b/doc/scripting/data_struct_set_declaration.bro similarity index 79% rename from testing/btest/doc/manual/data_struct_set_declaration.bro rename to doc/scripting/data_struct_set_declaration.bro index 269cb3d328..94d53c7b66 100644 --- a/testing/btest/doc/manual/data_struct_set_declaration.bro +++ b/doc/scripting/data_struct_set_declaration.bro @@ -1,10 +1,8 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - event bro_init() { local ssl_ports: set[port]; local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp ); + # SSH add ssl_ports[22/tcp]; # HTTPS @@ -14,17 +12,11 @@ event bro_init() # Check for SMTPS if ( 587/tcp !in ssl_ports ) - { add ssl_ports[587/tcp]; - } for ( i in ssl_ports ) - { print fmt("SSL Port: %s", i); - } for ( i in non_ssl_ports ) - { print fmt("Non-SSL Port: %s", i); - } - } \ No newline at end of file + } diff --git a/testing/btest/doc/manual/data_struct_table_complex.bro b/doc/scripting/data_struct_table_complex.bro similarity index 88% rename from testing/btest/doc/manual/data_struct_table_complex.bro rename to doc/scripting/data_struct_table_complex.bro index 4ecd51aace..d04cee5a16 100644 --- a/testing/btest/doc/manual/data_struct_table_complex.bro +++ b/doc/scripting/data_struct_table_complex.bro @@ -1,17 +1,13 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - event bro_init() { local samurai_flicks: table[string, string, count, string] of string; + samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru"; samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin"; samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri"; samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei"; for ( [d, s, y, a] in samurai_flicks ) - { print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a); - } } diff --git a/testing/btest/doc/manual/data_struct_table_declaration.bro b/doc/scripting/data_struct_table_declaration.bro similarity index 77% rename from testing/btest/doc/manual/data_struct_table_declaration.bro rename to doc/scripting/data_struct_table_declaration.bro index 36abd0db1b..ab637f4c25 100644 --- a/testing/btest/doc/manual/data_struct_table_declaration.bro +++ b/doc/scripting/data_struct_table_declaration.bro @@ -1,19 +1,13 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - event bro_init() { local ssl_services: table[string] of port; + ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp); ssl_services["IMAPS"] = 993/tcp; if ( "SMTPS" !in ssl_services ) - { ssl_services["SMTPS"] = 587/tcp; - } for ( k in ssl_services ) - { print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]); - } - } \ No newline at end of file + } diff --git a/testing/btest/doc/manual/data_struct_vector.bro b/doc/scripting/data_struct_vector.bro similarity index 67% rename from testing/btest/doc/manual/data_struct_vector.bro rename to doc/scripting/data_struct_vector.bro index 99d0b4dc6d..0c93f6cd41 100644 --- a/testing/btest/doc/manual/data_struct_vector.bro +++ b/doc/scripting/data_struct_vector.bro @@ -1,10 +1,7 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - event bro_init() { local v: vector of count = vector(1, 2, 3, 4); local w = vector(1, 2, 3, 4); print v; print w; - } \ No newline at end of file + } diff --git a/testing/btest/doc/manual/data_struct_vector_declaration.bro b/doc/scripting/data_struct_vector_declaration.bro similarity index 83% rename from testing/btest/doc/manual/data_struct_vector_declaration.bro rename to doc/scripting/data_struct_vector_declaration.bro index 06fe48aeec..d64754b97b 100644 --- a/testing/btest/doc/manual/data_struct_vector_declaration.bro +++ b/doc/scripting/data_struct_vector_declaration.bro @@ -1,16 +1,15 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - event bro_init() { local v1: vector of count; local v2 = vector(1, 2, 3, 4); + v1[|v1|] = 1; v1[|v1|] = 2; v1[|v1|] = 3; v1[|v1|] = 4; + print fmt("contents of v1: %s", v1); print fmt("length of v1: %d", |v1|); print fmt("contents of v1: %s", v2); print fmt("length of v2: %d", |v2|); - } \ No newline at end of file + } diff --git a/doc/scripting/data_struct_vector_iter.bro b/doc/scripting/data_struct_vector_iter.bro new file mode 100644 index 0000000000..01a5ff4cd2 --- /dev/null +++ b/doc/scripting/data_struct_vector_iter.bro @@ -0,0 +1,7 @@ +event bro_init() + { + local addr_vector: vector of addr = vector(1.2.3.4, 2.3.4.5, 3.4.5.6); + + for (i in addr_vector) + print mask_addr(addr_vector[i], 18); + } diff --git a/doc/scripting/data_type_const.bro b/doc/scripting/data_type_const.bro new file mode 100644 index 0000000000..fbfd79a21e --- /dev/null +++ b/doc/scripting/data_type_const.bro @@ -0,0 +1,9 @@ +const port_list: table[port] of string &redef; + +redef port_list += { [6666/tcp] = "IRC"}; +redef port_list += { [80/tcp] = "WWW" }; + +event bro_init() + { + print port_list; + } diff --git a/testing/btest/doc/manual/data_type_const_simple.bro b/doc/scripting/data_type_const_simple.bro similarity index 53% rename from testing/btest/doc/manual/data_type_const_simple.bro rename to doc/scripting/data_type_const_simple.bro index e32f740614..4e843fc2ac 100644 --- a/testing/btest/doc/manual/data_type_const_simple.bro +++ b/doc/scripting/data_type_const_simple.bro @@ -1,6 +1,3 @@ -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff .stdout - @load base/protocols/http redef HTTP::default_capture_password = T; diff --git a/doc/scripting/data_type_declaration.bro b/doc/scripting/data_type_declaration.bro new file mode 100644 index 0000000000..55b9d1cd1c --- /dev/null +++ b/doc/scripting/data_type_declaration.bro @@ -0,0 +1,9 @@ +event bro_init() + { + local a: int; + a = 10; + local b = 10; + + if ( a == b ) + print fmt("A: %d, B: %d", a, b); + } diff --git a/testing/btest/doc/manual/data_type_interval.bro b/doc/scripting/data_type_interval.bro similarity index 80% rename from testing/btest/doc/manual/data_type_interval.bro rename to doc/scripting/data_type_interval.bro index 869715b76c..491c0d129c 100644 --- a/testing/btest/doc/manual/data_type_interval.bro +++ b/doc/scripting/data_type_interval.bro @@ -1,6 +1,3 @@ -# @TEST-EXEC: bro -b -r $TRACES/wikipedia.trace %INPUT -# @TEST-EXEC: btest-diff .stdout - # Store the time the previous connection was established. global last_connection_time: time; @@ -8,13 +5,14 @@ global last_connection_time: time; global connection_seen: bool = F; event connection_established(c: connection) - { + { local net_time: time = network_time(); + print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h); - if (connection_seen) - { + + if ( connection_seen ) print fmt(" Time since last connection: %s", net_time - last_connection_time); - } + last_connection_time = net_time; connection_seen = T; - } \ No newline at end of file + } diff --git a/doc/scripting/data_type_local.bro b/doc/scripting/data_type_local.bro new file mode 100644 index 0000000000..dfd4eb0a2a --- /dev/null +++ b/doc/scripting/data_type_local.bro @@ -0,0 +1,11 @@ +function add_two(i: count): count + { + local added_two = i+2; + print fmt("i + 2 = %d", added_two); + return added_two; + } + +event bro_init() + { + local test = add_two(10); + } diff --git a/testing/btest/doc/manual/data_type_pattern_01.bro b/doc/scripting/data_type_pattern_01.bro similarity index 73% rename from testing/btest/doc/manual/data_type_pattern_01.bro rename to doc/scripting/data_type_pattern_01.bro index 09b92773a3..08378dd124 100644 --- a/testing/btest/doc/manual/data_type_pattern_01.bro +++ b/doc/scripting/data_type_pattern_01.bro @@ -1,14 +1,13 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - event bro_init() { local test_string = "The quick brown fox jumped over the lazy dog."; local test_pattern = /quick|lazy/; - if (test_pattern in test_string) + if ( test_pattern in test_string ) + { local results = split(test_string, test_pattern); print results[1]; print results[2]; print results[3]; - } \ No newline at end of file + } + } diff --git a/testing/btest/doc/manual/data_type_pattern_02.bro b/doc/scripting/data_type_pattern_02.bro similarity index 85% rename from testing/btest/doc/manual/data_type_pattern_02.bro rename to doc/scripting/data_type_pattern_02.bro index f4621cfb90..071ed2b6c1 100644 --- a/testing/btest/doc/manual/data_type_pattern_02.bro +++ b/doc/scripting/data_type_pattern_02.bro @@ -1,6 +1,3 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - event bro_init() { local test_string = "equality"; @@ -11,4 +8,3 @@ event bro_init() test_pattern = /equality/; print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); } - diff --git a/doc/scripting/data_type_subnets.bro b/doc/scripting/data_type_subnets.bro new file mode 100644 index 0000000000..1676033003 --- /dev/null +++ b/doc/scripting/data_type_subnets.bro @@ -0,0 +1,15 @@ +event bro_init() + { + local subnets = vector(172.16.0.0/20, 172.16.16.0/20, 172.16.32.0/20, 172.16.48.0/20); + local addresses = vector(172.16.4.56, 172.16.47.254, 172.16.22.45, 172.16.1.1); + + for ( a in addresses ) + { + for ( s in subnets ) + { + if ( addresses[a] in subnets[s] ) + print fmt("%s belongs to subnet %s", addresses[a], subnets[s]); + } + } + + } diff --git a/doc/scripting/data_type_time.bro b/doc/scripting/data_type_time.bro new file mode 100644 index 0000000000..6d09878205 --- /dev/null +++ b/doc/scripting/data_type_time.bro @@ -0,0 +1,4 @@ +event connection_established(c: connection) + { + print fmt("%s: New connection established from %s to %s\n", strftime("%Y/%M/%d %H:%m:%S", network_time()), c$id$orig_h, c$id$resp_h); + } diff --git a/doc/scripting/framework_logging_factorial_01.bro b/doc/scripting/framework_logging_factorial_01.bro new file mode 100644 index 0000000000..e4a171ebb6 --- /dev/null +++ b/doc/scripting/framework_logging_factorial_01.bro @@ -0,0 +1,19 @@ +module Factor; + +function factorial(n: count): count + { + if ( n == 0 ) + return 1; + else + return ( n * factorial(n - 1) ); + } + +event bro_init() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + for ( n in numbers ) + print fmt("%d", factorial(numbers[n])); + } + + diff --git a/testing/btest/doc/manual/framework_logging_factorial_02.bro b/doc/scripting/framework_logging_factorial_02.bro similarity index 84% rename from testing/btest/doc/manual/framework_logging_factorial_02.bro rename to doc/scripting/framework_logging_factorial_02.bro index 2a6fb10d1a..abdbea605b 100644 --- a/testing/btest/doc/manual/framework_logging_factorial_02.bro +++ b/doc/scripting/framework_logging_factorial_02.bro @@ -1,6 +1,3 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff factor.log - module Factor; export { @@ -15,13 +12,10 @@ export { function factorial(n: count): count { if ( n == 0 ) - { return 1; - } + else - { return ( n * factorial(n - 1) ); - } } event bro_init() @@ -33,8 +27,6 @@ event bro_done() { local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); for ( n in numbers ) - { Log::write( Factor::LOG, [$num=numbers[n], $factorial_num=factorial(numbers[n])]); - } } diff --git a/testing/btest/doc/manual/framework_logging_factorial_03.bro b/doc/scripting/framework_logging_factorial_03.bro similarity index 77% rename from testing/btest/doc/manual/framework_logging_factorial_03.bro rename to doc/scripting/framework_logging_factorial_03.bro index 967229bd94..c99cca2c1d 100644 --- a/testing/btest/doc/manual/framework_logging_factorial_03.bro +++ b/doc/scripting/framework_logging_factorial_03.bro @@ -1,7 +1,3 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff factor-mod5.log -# @TEST-EXEC: btest-diff factor-non5.log - module Factor; export { @@ -16,45 +12,34 @@ export { function factorial(n: count): count { if ( n == 0 ) - { return 1; - } + else - { - return ( n * factorial(n - 1) ); - } - } - -event bro_init() - { - Log::create_stream(LOG, [$columns=Info]); + return (n * factorial(n - 1)); } event bro_done() { local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); for ( n in numbers ) - { Log::write( Factor::LOG, [$num=numbers[n], $factorial_num=factorial(numbers[n])]); - } } function mod5(id: Log::ID, path: string, rec: Factor::Info) : string { if ( rec$factorial_num % 5 == 0 ) - { return "factor-mod5"; - } + else - { return "factor-non5"; - } } event bro_init() { + Log::create_stream(LOG, [$columns=Info]); + local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; Log::add_filter(Factor::LOG, filter); Log::remove_filter(Factor::LOG, "default"); - } \ No newline at end of file + } diff --git a/testing/btest/doc/manual/framework_logging_factorial_04.bro b/doc/scripting/framework_logging_factorial_04.bro similarity index 80% rename from testing/btest/doc/manual/framework_logging_factorial_04.bro rename to doc/scripting/framework_logging_factorial_04.bro index 49aef83ffc..a563069c46 100644 --- a/testing/btest/doc/manual/framework_logging_factorial_04.bro +++ b/doc/scripting/framework_logging_factorial_04.bro @@ -1,7 +1,3 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff factor-mod5.log -# @TEST-EXEC: btest-diff factor-non5.log - module Factor; export { @@ -18,13 +14,10 @@ export { function factorial(n: count): count { if ( n == 0 ) - { return 1; - } + else - { - return ( n * factorial(n - 1) ); - } + return (n * factorial(n - 1)); } event bro_init() @@ -36,22 +29,17 @@ event bro_done() { local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); for ( n in numbers ) - { Log::write( Factor::LOG, [$num=numbers[n], $factorial_num=factorial(numbers[n])]); - } } function mod5(id: Log::ID, path: string, rec: Factor::Info) : string { if ( rec$factorial_num % 5 == 0 ) - { return "factor-mod5"; - } + else - { return "factor-non5"; - } } event bro_init() @@ -59,4 +47,4 @@ event bro_init() local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; Log::add_filter(Factor::LOG, filter); Log::remove_filter(Factor::LOG, "default"); - } \ No newline at end of file + } diff --git a/doc/scripting/framework_notice_hook_01.bro b/doc/scripting/framework_notice_hook_01.bro new file mode 100644 index 0000000000..7c4980a896 --- /dev/null +++ b/doc/scripting/framework_notice_hook_01.bro @@ -0,0 +1,7 @@ +@load policy/protocols/ssh/interesting-hostnames.bro + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSH::Interesting_Hostname_Login ) + add n$actions[Notice::ACTION_EMAIL]; + } diff --git a/doc/scripting/framework_notice_hook_suppression_01.bro b/doc/scripting/framework_notice_hook_suppression_01.bro new file mode 100644 index 0000000000..93bb988e25 --- /dev/null +++ b/doc/scripting/framework_notice_hook_suppression_01.bro @@ -0,0 +1,7 @@ +@load policy/protocols/ssl/expiring-certs.bro + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSL::Certificate_Expires_Soon ) + n$suppress_for = 12hrs; + } diff --git a/testing/btest/doc/manual/framework_notice_shortcuts_01.bro b/doc/scripting/framework_notice_shortcuts_01.bro similarity index 74% rename from testing/btest/doc/manual/framework_notice_shortcuts_01.bro rename to doc/scripting/framework_notice_shortcuts_01.bro index d1d2f19312..cd51abd5b5 100644 --- a/testing/btest/doc/manual/framework_notice_shortcuts_01.bro +++ b/doc/scripting/framework_notice_shortcuts_01.bro @@ -1,6 +1,3 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - @load policy/protocols/ssh/interesting-hostnames.bro @load base/protocols/ssh/ diff --git a/testing/btest/doc/manual/framework_notice_shortcuts_02.bro b/doc/scripting/framework_notice_shortcuts_02.bro similarity index 77% rename from testing/btest/doc/manual/framework_notice_shortcuts_02.bro rename to doc/scripting/framework_notice_shortcuts_02.bro index 5d05fdc775..ac427ac8b7 100644 --- a/testing/btest/doc/manual/framework_notice_shortcuts_02.bro +++ b/doc/scripting/framework_notice_shortcuts_02.bro @@ -1,6 +1,3 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - @load policy/protocols/ssh/interesting-hostnames.bro @load base/protocols/ssh/ diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 0610589004..a9826d9b3f 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -1,6 +1,8 @@ .. _writing-scripts: +.. contents:: + =================== Writing Bro Scripts =================== @@ -8,119 +10,120 @@ Writing Bro Scripts Understanding Bro Scripts ========================= -Bro includes an event queue driven scripting language that provides +.. todo:: + + The MHR integration has changed significantly since the text was + written. We need to update it, however I'm actually not sure this + script is a good introductory example anymore unfortunately. + -Robin + +Bro includes an event-driven scripting language that provides the primary means for an organization to extend and customize Bro's -functionality. An overwhelming amount of the output generated by Bro +functionality. Virtually all of the output generated by Bro is, in fact, generated by Bro scripts. It's almost easier to consider Bro to be an entity behind-the-scenes processing connections and generating events while Bro's scripting language is the medium through which we mere mortals can achieve communication. Bro scripts effectively notify Bro that should there be an event of a type we define, then let us have the information about the connection so we -can perform some function on it. For example, the ssl.log file is +can perform some function on it. For example, the ``ssl.log`` file is generated by a Bro script that walks the entire certificate chain and issues notifications if any of the steps along the certificate chain are invalid. This entire process is setup by telling Bro that should -it see a server or client issue an SSL HELLO message, we want to know +it see a server or client issue an SSL ``HELLO`` message, we want to know about the information about that connection. -It's often easier to understand Bro's scripting language by looking at -a complete script and breaking it down into its identifiable -components. In this example, we'll take a look at how Bro queries the -Team Cymru Malware hash registry for detected downloads via HTTP. Part -of the Team Cymru Malware Hash registry includes the ability to do a -host lookup on a domain with the format -MALWARE_HASH.malware.hash.cymru.com where MALWARE_HASH is the md5 or -sha1 hash of a file. Team Cymru also populates the TXT record of +It's often the easiest to understand Bro's scripting language by +looking at a complete script and breaking it down into its +identifiable components. In this example, we'll take a look at how +Bro queries the `Team Cymru Malware hash registry +`_ for downloads via +HTTP. Part of the Team Cymru Malware Hash registry includes the +ability to do a host lookup on a domain with the format +``MALWARE_HASH.malware.hash.cymru.com`` where ``MALWARE_HASH`` is the MD5 or +SHA1 hash of a file. Team Cymru also populates the TXT record of their DNS responses with both a "last seen" timestamp and a numerical "detection rate". The important aspect to understand is Bro already generates hashes for files it can parse from HTTP streams, but the script ``detect-MHR.bro`` is responsible for generating the appropriate DNS lookup and parsing the response. - -.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro Visually, there are three distinct sections of the script. A base level with no indentation followed by an indented and formatted -section explaining the custom variables being set (export) and another +section explaining the custom variables being provided (``export``) and another indented and formatted section describing the instructions for a -specific event (event log_http). Don't get discouraged if you don't +specific event (``event log_http``). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. -.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro :lines: 7-11 Lines 7 and 8 of the script process the ``__load__.bro`` script in the respective directories being loaded. The ``@load`` directives are often considered good practice or even just good manners when writing -Bro scripts that might be distributed. While it's unlikely that in a +Bro scripts to make sure they can be +used on their own. While it's unlikely that in a full production deployment of Bro these additional resources wouldn't already be loaded, it's not a bad habit to try to get into as you get more experienced with Bro scripting. If you're just starting out, this level of granularity might not be entirely necessary though. -.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro :lines: 12-24 The export section redefines an enumerable constant that describes the type of notice we will generate with the logging framework. Bro allows for redefinable constants, which at first, might seem -counter-intuitive. We'll get more indepth with constants in a later +counter-intuitive. We'll get more in-depth with constants in a later chapter, for now, think of them as variables that can only be altered before Bro starts running. The notice type listed allows for the use -of the NOTICE() function to generate notices of type -Malware_Hash_Registry_Match as done in the next section. Notices +of the :bro:id:`NOTICE` function to generate notices of type +``Malware_Hash_Registry_Match`` as done in the next section. Notices allow Bro to generate some kind of extra notification beyond its default log types. Often times, this extra notification comes in the form of an email generated and sent to a pre-configured address. -.. literalinclude:: ../scripts/policy/protocols/http/detect-MHR.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro :lines: 26-44 The workhorse of the script is contained in the event handler for ``log_http``. The ``log_http`` event is defined as an event-hook in -the base/protocols/http/main.bro script and allows scripts to handle a -connection as it is being passed to the logging framework. The event -handler is passed an HTTP::Info data structure which will be referred -to as "rec" in body of the event handler. +the :doc:`scripts/base/protocols/http/main.bro` script and allows scripts +to handle a connection as it is being passed to the logging framework. +The event handler is passed an :bro:id:`HTTP::Info` data structure +which will be referred to as ``rec`` in body of the event handler. -An if statement is used to check for the existence of a data structure -named "md5" nested within the rec data structure. Bro uses the "$" as +An ``if`` statement is used to check for the existence of a data structure +named ``md5`` nested within the ``rec`` data structure. Bro uses the ``$`` as a deference operator and as such, and it is employed in this script to -check if rec$md5 is present by including the "?" operator within the -path. If the rec data structure includes a nested data structure -named "md5", the statement is processed as true and a local variable -named "hash_domain" is provisioned and given a format string based on -the contents of rec$md5 to produce a valid DNS lookup. +check if ``rec$md5`` is present by including the ``?`` operator within the +path. If the ``rec`` data structure includes a nested data structure +named ``md5``, the statement is processed as true and a local variable +named ``hash_domain`` is provisioned and given a format string based on +the contents of ``rec$md5`` to produce a valid DNS lookup. -The rest of the script is contained within a when() block. In short, -a when block is used when Bro needs to perform asynchronous actions, -such a DNS lookup, to ensure that performance isn't effected. The -when() block performs a DNS TXT lookup and stores the result in the -local variable MHR_result. Effectively, processing for this event -continues and upon receipt of the values returned by -lookup_hostname_txt(), the when block is executed. The when block -splits the string returned into two seperate values and checks to -ensure an expected format. If the format is invalid, the script -assumes that the hash wasn't found in the respository and processing -is concluded. If the format is as expected and the detection rate is -above the threshold set by MHR_threshold, two new local variables are -created and used in the notice issued by NOTICE(). +The rest of the script is contained within a ``when`` block. In +short, a ``when`` block is used when Bro needs to perform asynchronous +actions, such a DNS lookup, to ensure that performance isn't effected. +The ``when`` block performs a DNS TXT lookup and stores the result +in the local variable ``MHR_result``. Effectively, processing for +this event continues and upon receipt of the values returned by +:bro:id:`lookup_hostname_txt`, the ``when`` block is executed. The +``when`` block splits the string returned into two seperate values and +checks to ensure an expected format. If the format is invalid, the +script assumes that the hash wasn't found in the respository and +processing is concluded. If the format is as expected and the +detection rate is above the threshold set by ``MHR_threshold``, two +new local variables are created and used in the notice issued by +:bro:id:`NOTICE`. In approximately 15 lines of actual code, Bro provides an amazing utility that would be incredibly difficult to implement and deploy with other products. In truth, claiming that Bro does this in 15 -lines is a misdirection; There is a truly massive number of things +lines is a misdirection; there is a truly massive number of things going on behind-the-scenes in Bro, but it is the inclusion of the scripting language that gives analysts access to those underlying layers in a succinct and well defined manner. @@ -150,7 +153,7 @@ write scripts for Bro but for understanding Bro itself. Gaining familiarity with the specific events generated by Bro is a big step towards building a mind set for working with Bro scripts. The majority of events generated by Bro are defined in the -built-in-function files or .bif files which also act as the basis for +built-in-function files or ``.bif`` files which also act as the basis for online event documentation. These in-line comments are compiled into an online documentation system using Broxygen. Whether starting a script from scratch or reading and maintaining someone else's script, @@ -161,31 +164,32 @@ This effort resulted in built-in-function files organized such that each entry contains a descriptive event name, the arguments passed to the event, and a concise explanation of the functions use. -.. literalinclude:: ../../../../build/src/base/event.bif.bro - :language: bro - :linenos: - :lines: 4124-4149 +.. btest-include:: ${BRO_SRC_ROOT}/build/scripts/base/bif/plugins/Bro_DNS.events.bif.bro + :lines: 29-54 -Above is a segment of the documentation for the event dns_request(). -It's organized such that the documentation, commentary, and list of -arguments precede the actual event definition used by Bro. As Bro -detects DNS requests being issued by an originator, it issues this -event and any number of scripts then have access to the data Bro -passes along with the event. In this example, Bro passes not only the -message, the query, query type and query class for the DNS request, -but also a then record used for the connection itself. +Above is a segment of the documentation for the event +:bro:id:`dns_request` (and the preceeding link points to the +documentation generated out of that). It's organized such that the +documentation, commentary, and list of arguments precede the actual +event definition used by Bro. As Bro detects DNS requests being +issued by an originator, it issues this event and any number of +scripts then have access to the data Bro passes along with the event. +In this example, Bro passes not only the message, the query, query +type and query class for the DNS request, but also a then record used +for the connection itself. The Connection Record Data Type =============================== Of all the events defined by Bro, an overwhelmingly large number of -them are passed the connection record data type, in effect, making it -the backbone of many scripting solutions. The connection record -itself, as we will see in a moment, is a mass of nested data types -used to track state on a connection through its lifetime. Let's walk -through the process of selecting an appropriate event, generating some -output to standard out and dissecting the connection record so as to -get an overview of it. We will cover data types in more detail later. +them are passed the :bro:id:`connection` record data type, in effect, +making it the backbone of many scripting solutions. The connection +record itself, as we will see in a moment, is a mass of nested data +types used to track state on a connection through its lifetime. Let's +walk through the process of selecting an appropriate event, generating +some output to standard out and dissecting the connection record so as +to get an overview of it. We will cover data types in more detail +later. While Bro is capable of packet level processing, its strengths lay in the context of a connection between an originator and a responder. As @@ -193,40 +197,42 @@ such, there are events defined for the primary parts of the connection life-cycle as you'll see from the small selection of connection-related events below. -.. literalinclude:: ../../../../build/src/base/event.bif.bro - :language: bro - :linenos: +.. todo:: + + Update the line numbers, this isn't pulling in the right events + anymore but I don't know which ones it were. + +.. btest-include:: ${BRO_SRC_ROOT}/build/scripts/base/bif/event.bif.bro :lines: 135-138,154,204-208,218,255-256,266,335-340,351 Of the events listed, the event that will give us the best insight into the connection record data type will be -connection_state_remove(). As detailed in the in-line documentation, -Bro generates this event just before it decides to remove this event -from memory, effectively forgetting about it. Let's take a look at a -simple script that will output the connection record for a single -connection. +:bro:id:`connection_state_remove` . As detailed in the in-line +documentation, Bro generates this event just before it decides to +remove this event from memory, effectively forgetting about it. Let's +take a look at a simple script, stored as +``connection_record_01.bro``, that will output the connection record +for a single connection. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_01.bro - :language: bro - :linenos: - :lines: 4-9 +.. btest-include:: ${DOC_ROOT}/scripting/connection_record_02.bro -Again, we start with @load, this time importing the -base/protocols/conn scripts which supply the tracking and logging of -general information and state of connections. We handle the -connection_state_remove() event and simply print the contents of the -argument passed to it. For this example we're going to run Bro in -"bare mode" which loads only the minimum number of scripts to retain -operability and leaves the burden of loading required scripts to the -script being run. While bare mode is a low level functionality -incorporated into Bro, in this case, we're going to use it to -demonstrate how different features of Bro add more and more layers of -information about a connection. This will give us a chance to see the -contents of the connection record without it being overly populated. +Again, we start with ``@load``, this time importing the +:doc:`scripts/base/protocols/conn` scripts which supply the tracking +and logging of general information and state of connections. We +handle the :bro:id:`connection_state_remove` event and simply print +the contents of the argument passed to it. For this example we're +going to run Bro in "bare mode" which loads only the minimum number of +scripts to retain operability and leaves the burden of loading +required scripts to the script being run. While bare mode is a low +level functionality incorporated into Bro, in this case, we're going +to use it to demonstrate how different features of Bro add more and +more layers of information about a connection. This will give us a +chance to see the contents of the connection record without it being +overly populated. .. btest:: connection-record-01 - @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_01.bro + @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${DOC_ROOT}/scripting/connection_record_01.bro As you can see from the output, the connection record is something of a jumble when printed on its own. Regularly taking a peek at a @@ -237,12 +243,12 @@ of reference for accessing data in a script. Bro makes extensive use of nested data structures to store state and information gleaned from the analysis of a connection as a complete unit. To break down this collection of information, you will have to -make use of use Bro's field delimiter the "$". For example, the -originating host is referenced by c$id$orig_h which if given a -narritive relates to "``orig_h`` which is a member of ``id`` which is +make use of use Bro's field delimiter ``$``. For example, the +originating host is referenced by ``c$id$orig_h`` which if given a +narritive relates to ``orig_h`` which is a member of ``id`` which is a member of the data structure referred to as ``c`` that was passed into the event handler." Given that the responder port -(``c$id$resp_p``) is 53/tcp, it's likely that Bro's base DNS scripts +(``c$id$resp_p``) is ``53/tcp``, it's likely that Bro's base DNS scripts can further populate the connection record. Let's load the ``base/protocols/dns`` scripts and check the output of our script. @@ -250,30 +256,27 @@ Bro uses the dollar sign as its field delimiter and a direct correlation exists between the output of the connection record and the proper format of a dereferenced variable in scripts. In the output of the script above, groups of information are collected between -brackets, which would correspond to the $-delimiter in a Bro script. +brackets, which would correspond to the ``$``-delimiter in a Bro script. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/connection_record_02.bro - :language: bro - :linenos: - :lines: 4-10 +.. btest-include:: ${DOC_ROOT}/scripting/connection_record_02.bro .. btest:: connection-record-02 - @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${TESTBASE}/doc/manual/connection_record_02.bro + @TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${DOC_ROOT}/scripting/connection_record_02.bro The addition of the ``base/protocols/dns`` scripts populates the -dns=[] member of the connection record. While Bro is doing a massive -amount of work in the background, it is in what is commonly called -"script land" that details are being refined and decisions being made. -Were we to continue running in "bare mode" we could slowly keep adding -infrastructure through ``@load`` statements. For example, were we to -``@load base/frameworks/logging``, Bro would generate a conn.log and -dns.log for us in the current working directory. As mentioned above, -including the appropriate ``@load`` statements is not only good -practice, but can also help to indicate which functionalities are -being used in a script. Take a second to run the script with the -``-b`` flag and check the output when all of Bro's functionality is -applied to the tracefile. +``dns=[]`` member of the connection record. While Bro is doing a +massive amount of work in the background, it is in what is commonly +called "scriptland" that details are being refined and decisions +being made. Were we to continue running in "bare mode" we could slowly +keep adding infrastructure through ``@load`` statements. For example, +were we to ``@load base/frameworks/logging``, Bro would generate a +``conn.log`` and ``dns.log`` for us in the current working directory. +As mentioned above, including the appropriate ``@load`` statements is +not only good practice, but can also help to indicate which +functionalities are being used in a script. Take a second to run the +script without the ``-b`` flag and check the output when all of Bro's +functionality is applied to the tracefile. Data Types and Data Structures ============================== @@ -281,20 +284,17 @@ Data Types and Data Structures Scope ----- -Before embarking on a exploration of Bro's native Data Types and Data -Structures, it's important to have a good grasp of the different +Before embarking on a exploration of Bro's native data types and data +structures, it's important to have a good grasp of the different levels of scope available in Bro and the appropriate times to use them within a script. The declarations of variables in Bro come in two forms. Variables can be declared with or without a definition in the -form "SCOPE name: TYPE" or "SCOPE name = EXPRESSION" respectively; -each of which produce the same result if EXPRESSION evaluates to the -same type as TYPE. The decision as to which type of declaration to +form ``SCOPE name: TYPE`` or ``SCOPE name = EXPRESSION`` respectively; +each of which produce the same result if ``EXPRESSION`` evaluates to the +same type as ``TYPE``. The decision as to which type of declaration to use is likely to be dictated by personal preference and readability. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_declaration.bro - :language: bro - :linenos: - :lines: 4-14 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_declaration.bro Global Variables ~~~~~~~~~~~~~~~~ @@ -309,79 +309,71 @@ intended result. When a global is declared in a script with a namespace there are two possible outcomes. First, the variable is available only within the context of the namespace. In this scenario, other scripts within the same namespace will have access to the -varaible declared while scripts using a different namespace or no +variable declared while scripts using a different namespace or no namespace altogether will not have access to the variable. -Alternatively, if a global variable is declared within an ``export{}`` +Alternatively, if a global variable is declared within an ``export { ... }`` block that variable is available to any other script through the naming convention of ``MODULE::variable_name``. -The declaration below, is a taken from the ``known-hosts.bro`` script -and declares a variable called "known_hosts"" as a global set of -unique ip addresses(line 32) within the "Known" namespace (line 8) and -exports it (line 10) for use outside of the "Known" namespace. Were -we to want to use the "known_hosts" variable we'd be able to access it -through ``Known::known_hosts``. +The declaration below is taken from the +:doc:`scripts/policy/protocols/conn/known-hosts.bro` script and +declares a variable called ``known_hosts`` as a global set of unique +IP addresses within the ``Known`` namespace and exports it for use +outside of the ``Known`` namespace. Were we to want to use the +``known_hosts`` variable we'd be able to access it through +``Known::known_hosts``. -.. literalinclude:: ../scripts/policy/protocols/conn/known-hosts.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/conn/known-hosts.bro :lines: 8-10, 32, 37 -The sample above also makes use of an export{} block. When the module +The sample above also makes use of an ``export { ... }`` block. When the module keyword is used in a script, the variables declared are said to be in that module's "namespace". Where as a global variable can be accessed by its name alone when it is not declared within a module, a global variable declared within a module must be exported and then accessed -via MODULE_NAME::VARIABLE_NAME. As in the example above, we would be -able to access the "known_hosts" in a separate script variable via -"Known::known_hosts" due to the fact that known_hosts was declared as -a global variable within an export block under the "Known" namespace. +via ``MODULE_NAME::VARIABLE_NAME``. As in the example above, we would be +able to access the ``known_hosts`` in a separate script variable via +``Known::known_hosts`` due to the fact that ``known_hosts`` was declared as +a global variable within an export block under the ``Known`` namespace. Constants ~~~~~~~~~ -Bro also makes use of constants which are denoted by the "const" +Bro also makes use of constants, which are denoted by the ``const`` keyword. Unlike globals, constants can only be set or altered at -parse time if the &redef attribute has been used. Afterwards (in +parse time if the ``&redef`` attribute has been used. Afterwards (in runtime) the constants are unalterable. In most cases, redefinable constants are used in Bro scripts as containers for configuration options. For example, the configuration option to log password decrypted from HTTP streams is stored in ``HTTP::default_capture_password`` as shown in the stripped down -excerpt from ``http/main.bro`` below. +excerpt from :doc:`scripts/scripts/base/protocols/http/main.bro` +below. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro - :language: bro - :linenos: - :lines: 8-10,19,20,74 +.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro + :lines: 8-10,19,20,118 Because the constant was declared with the ``&redef`` attribute, if we needed to turn this option on globally, we could do so by adding the following line to our ``site/local.bro`` file before firing up Bro. - -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const_simple.bro - :language: bro - :lines: 6 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_const_simple.bro While the idea of a redefinable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the -"&redef" attribute. In the code snippet below, a table of strings +``&redef`` attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added -to the table through redef statements. The table is then printed in a -bro_init() event. Were we to try to alter the table in an event -handler, Bro would notify the user of an error and the script would -fail. +to the table through ``redef`` statements. The table is then printed +in a :bro:id:`bro_init` event. Were we to try to alter the table in +an event handler, Bro would notify the user of an error and the script +would fail. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_const.bro - :language: bro - :linenos: - :lines: 4-12 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_const.bro .. btest:: data_type_const.bro - @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_type_const.bro + @TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_type_const.bro Local Variables ~~~~~~~~~~~~~~~ @@ -392,26 +384,22 @@ its availability is restricted to the body of the event or function in which it was declared. Local variables tend to be used for values that are only needed within a specific scope and once the processing of a script passes beyond that scope and no longer used, the variable -is deleted. While it is possible for a function to return a locally -scoped variable, in doing so it retuns the value instead of the -variable. Bro maintains a difference between variables an example of -which is illustrated below. The script executes the event handler -"bro_init()" which in turn calls the function "add_two(i: count)" with -an argument of 10. Once Bro enters the add_two function, it -provisions a locally scoped variable called "added_two" to hold the -value of i+2, in this case, 12. The add_two function then prints the -value of the added_two variable and returns its value to the -bro_init() event handler. At this point, the variable "added_two" has -fallen out of scope and no longer exists while the value 12 is still -in use and stored in the locally scoped variable "test". When Bro -finishes processing the bro_init function, the variable called "test" -is no longer in scope and, since there exist no other references to -the value "12", the value is also deleted. +is deleted. Bro maintains names of locals separately from globally +visible ones, an example of which is illustrated below. The script +executes the event handler :bro:id:`bro_init` which in turn calls the +function ``add_two(i: count)`` with an argument of ``10``. Once Bro +enters the ``add_two`` function, it provisions a locally scoped +variable called ``added_two`` to hold the value of ``i+2``, in this +case, ``12``. The ``add_two`` function then prints the value of the +``added_two`` variable and returns its value to the ``bro_init`` event +handler. At this point, the variable ``added_two`` has fallen out of +scope and no longer exists while the value ``12`` still in use and +stored in the locally scoped variable ``test``. When Bro finishes +processing the ``bro_init`` function, the variable called ``test`` is +no longer in scope and, since there exist no other references to the +value ``12``, the value is also deleted. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_local.bro - :language: bro - :linenos: - :lines: 4-14 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_local.bro Data Structures @@ -421,12 +409,12 @@ It's difficult to talk about Bro's data types in a practical manner without first covering the data structures available in Bro. Some of the more interesting characteristics of data types are revealed when used inside of a data structure, but given that data structures are -made up of data types, it devolved rather quickly into a -"chicken-and-egg"" problem. As such, we'll introduce data types from -bird's eye view before diving into data structures and from there a +made up of data types, it devolves rather quickly into a +"chicken-and-egg" problem. As such, we'll introduce data types from +a bird's eye view before diving into data structures and from there a more complete exploration of data types. -The table below shows the atomic types used in Bro, of which, the +The table below shows the atomic types used in Bro, of which the first four should seem familiar if you have some scripting experience, while the remaining six are less common in other languages. It should come as no surprise that a scripting language for a Network Security @@ -445,7 +433,7 @@ reinventing the wheel. +-----------+-------------------------------------+ | bool | boolean (T/F) | +-----------+-------------------------------------+ -| addr | ip address, ipv4 and ipv6 | +| addr | IP address, IPv4 and IPv6 | +-----------+-------------------------------------+ | port | transport layer port | +-----------+-------------------------------------+ @@ -461,67 +449,58 @@ reinventing the wheel. Sets ~~~~ -Sets in Bro are used to stored a unique elements of the same data +Sets in Bro are used to store unique elements of the same data type. In essence, you can think of them as "a unique set of integers" -or "a unique set of ip addresses". While the declaration of a set may +or "a unique set of IP addresses". While the declaration of a set may differ based on the data type being collected, the set will always contain unique elements and the elements in the set will always be of the same data type. Such requirements make the set data type perfect -for information that is already naturally unique such as ports or ip +for information that is already naturally unique such as ports or IP addresses. The code snippet below shows both an explicit and implicit declaration of a locally scoped set. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro - :language: bro - :linenos: - :lines: 6,7 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro + :lines: 1-4,22 -As you can see, sets are declared using the format "SCOPE var_name: -set[TYPE]". Adding and removing elements in a set is achieved using -the add and delete statements. Once you have elements inserted into +As you can see, sets are declared using the format ``SCOPE var_name: +set[TYPE]``. Adding and removing elements in a set is achieved using +the ``add`` and ``delete`` statements. Once you have elements inserted into the set, it's likely that you'll need to either iterate over that set or test for membership within the set, both of which are covered by -the in operator. In the case of iterating over a set, combining the -for statement and the in operator will allow you to sequentially +the ``in`` operator. In the case of iterating over a set, combining the +``for`` statement and the ``in`` operator will allow you to sequentially process each element of the set as seen below. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro - :language: bro - :linenos: - :lines: 21-29 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro + :lines: 17-21 -Here, the for statement loops over the contents of the set storing -each element in the temporary variable "i". With each iteration of -the for loop, the next element is chosen. Since sets are not an +Here, the ``for`` statement loops over the contents of the set storing +each element in the temporary variable ``i``. With each iteration of +the ``for`` loop, the next element is chosen. Since sets are not an ordered data type, you cannot guarantee the order of the elements as -the for loop processes. +the ``for`` loop processes. -To test for membership in a set the in statment can be combined with -an if statement to return a true or false value. If the exact element -in the condition is already in the set, the condition returns true and -the body executes. The in statement can also be negated by the ! -operator to create the inverse of the condition. While line 16 of the -code snippet below could be rewrite as "if (!( 587/tcp in ssl_ports -))" try to avoid using this construct; instead, negate the in operator -itself. While the functionality is the same, using the "!in" is more -efficient as well as a more natural construct which will aid in the -readability of your script. +To test for membership in a set the ``in`` statment can be combined +with an ``if`` statement to return a true or false value. If the +exact element in the condition is already in the set, the condition +returns true and the body executes. The ``in`` statement can also be +negated by the ``!`` operator to create the inverse of the condition. +While we could rewrite the corresponding line below as ``if ( !( +587/tcp in ssl_ports ))`` try to avoid using this construct; instead, +negate the in operator itself. While the functionality is the same, +using the ``!in`` is more efficient as well as a more natural construct +which will aid in the readability of your script. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro - :language: bro - :linenos: - :lines: 15-19 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro + :lines: 13-15 You can see the full script and its output below. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_set_declaration.bro - :language: bro - :linenos: - :lines: 4-21 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro .. btest:: data_struct_set_declaration - @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_set_declaration.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_set_declaration.bro Tables ~~~~~~ @@ -529,33 +508,30 @@ Tables A table in Bro is a mapping of a key to a value or yield. While the values don't have to be unique, each key in the table must be unique to preserve a one-to-one mapping of keys to values. In the example -below, we've compiled a table of SSL enable services and their common +below, we've compiled a table of SSL-enabled services and their common ports. The explicit declaration and constructor for the table on lines 3 and 4 lay out the data types of the keys (strings) and the data types of the yields (ports) and then fill in some sample key and -yeild pairs. Line 5 shows how to use a table accessor to insert one -key-yield pair into the table. When using the in operator on a table, +yield pairs. Line 5 shows how to use a table accessor to insert one +key-yield pair into the table. When using the ``in`` operator on a table, you are effectively working with the keys of the table. In the case -of an inf statement, the in operator will check for membership among +of an ``if`` statement, the ``in`` operator will check for membership among the set of keys and return a true or false value. As seen on line 7, -we are checking if "SMTPS" is not in the set of keys for the +we are checking if ``SMTPS`` is not in the set of keys for the ssl_services table and if the condition holds true, we add the -key-yield pair to the table. Line 12 shows the use of a for statement +key-yield pair to the table. Line 12 shows the use of a ``for`` statement to iterate over each key currently in the table. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_declaration.bro - :language: bro - :linenos: - :lines: 4-21 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_table_declaration.bro .. btest:: data_struct_table_declaration - @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_declaration.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_table_declaration.bro Simple examples aside, tables can become extremely complex as the keys and values for the table become more intricate. Tables can have keys comprised of multiple data types and even a series of elements called -a 'tuple'. The flexibility gained with the use of complex tables in +a "tuple". The flexibility gained with the use of complex tables in Bro implies a cost in complexity for the person writing the scripts but pays off in effectiveness given the power of Bro as a network security platform. @@ -564,75 +540,67 @@ The script below shows a sample table of strings indexed by two strings, a count, and a final string. With a tuple acting as an aggregate key, the order is the important as a change in order would result in a new key. Here, we're using the table to track the -Director, Studio, year or release, and lead actor in a series of -samurai flicks. It's important to note that in the case of the for +director, studio, year or release, and lead actor in a series of +samurai flicks. It's important to note that in the case of the ``for`` statement, it's an all or nothing kind of iteration. We cannot -iterate over, say, the directors; We have to iterate with the exact +iterate over, say, the directors; we have to iterate with the exact format as the keys themselves. In this case, we need squared brackets surrounding four temporary variables to act as a collection for our iteration. While this is a contrived example, we could easily have -had keys containin ip addresses(addr), ports(port) and even a string +had keys containin IP addresses (``addr``), ports (``port``) and even a ``string`` calculated as the result of a reverse hostname lookup. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_table_complex.bro - :language: bro - :linenos: - :lines: 4-21 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_table_complex.bro .. btest:: data_struct_table_complex - @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_table_complex.bro + @TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_table_complex.bro Vectors ~~~~~~~ If you're coming to Bro with a programming background, you may or may -not be familiar with the Vector data type depending on your language -of choice. On the surface, vectors perform much of the same -functionality as arrays, but in truth they are more like associative -arrays with zero indexed unsigned integers as the indecies. As such -any time you need to sequentially store data of the same type, in Bro -you'll have to reach for a vector. Vectors are a collection of -objects, all of which are of the same data type, to which elements can -be dynamically added or removed. Since Vectors use contiguous storage -for their elements, the contents of a vector can be accessed through a -zero indexed numerical offset. +not be familiar with a vector data type depending on your language of +choice. On the surface, vectors perform much of the same +functionality as associative arrays with unsigned integers as their +indices. They are however more efficient than that and they allow for +ordered access. As such any time you need to sequentially store data of the +same type, in Bro you should reach for a vector. Vectors are a +collection of objects, all of which are of the same data type, to +which elements can be dynamically added or removed. Since Vectors use +contiguous storage for their elements, the contents of a vector can be +accessed through a zero-indexed numerical offset. The format for the declaration of a Vector follows the pattern of -other declarations, namely, "SCOPE v: vector of T" where v is the name -of your vector of T is the data type of its members. For example, the -following snippet shows an explicit and implicit declaration of two -locally scoped vectors. The script populates the first vector by -inserting values at the end by placing the vector name between two -vertical pipes to get the Vector's current length before printing the -contents of both Vectors and their current lengths. +other declarations, namely, ``SCOPE v: vector of T`` where ``v`` is +the name of your vector, and ``T`` is the data type of its members. +For example, the following snippet shows an explicit and implicit +declaration of two locally scoped vectors. The script populates the +first vector by inserting values at the end; it does that by placing +the vector name between two vertical pipes to get the vector's current +length before printing the contents of both Vectors and their current +lengths. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_vector_declaration.bro - :language: bro - :linenos: - :lines: 4-16 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_vector_declaration.bro .. btest:: data_struct_vector_declaration - @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_declaration.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_vector_declaration.bro In a lot of cases, storing elements in a vector is simply a precursor to then iterating over them. Iterating over a vector is easy with the -for keyword. The sample below iterates over a vector of IP addresses -and for each IP address, masks that address with 18 bits. The for -keyword is used to generate a locally scoped variable called "i" which -will hold the index of the current element in the vector. Using i as -an index to addr_vector we can access the current item in the vector -with addr_vector[i]. +``for`` keyword. The sample below iterates over a vector of IP +addresses and for each IP address, masks that address with 18 bits. +The ``for`` keyword is used to generate a locally scoped variable +called ``i`` which will hold the index of the current element in the +vector. Using ``i`` as an index to addr_vector we can access the +current item in the vector with ``addr_vector[i]``. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_vector_iter.bro - :language: bro - :linenos: - :lines: 4-12 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_vector_iter.bro .. btest:: data_struct_vector_iter - @TEST-EXEC: btest-rst-cmd bro -b ${TESTBASE}/doc/manual/data_struct_vector_iter.bro + @TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_vector_iter.bro Data Types Revisited @@ -641,40 +609,40 @@ Data Types Revisited addr ~~~~ -The addr, or address, data type manages to cover a surprisingly large -amount of ground while remaining succinct. IPv4, IPv6 and even -hostname constants are included in the addr data type. While IPv4 +The ``addr``, or address, data type manages to cover a surprisingly +large amount of ground while remaining succinct. IPv4, IPv6 and even +hostname constants are included in the ``addr`` data type. While IPv4 addresses use the default dotted quad formatting, IPv6 addresses use -RFC 2373 defined notation with the addition of squared brackets +the RFC 2373 defined notation with the addition of squared brackets wrapping the entire address. When you venture into hostname constants, Bro performs a little slight of hand for the benefit of the user; a hostname constant is, in fact, a set of addresses. Bro will issue a DNS request when it sees a hostname constant in use and return a set whose elements are the answers to the DNS request. For example, if you were to use ``local google = www.google.com;`` you would end up -with a locally scoped set of addr elements that represent the current -set of round robin DNS entries for google. At first blush, this seems -trivial, but it is yet another example of Bro making the life of the -common Bro scripter a little easier through abstraction applied in a -practical manner. +with a locally scoped ``set[addr]`` with elements that represent the +current set of round robin DNS entries for google. At first blush, +this seems trivial, but it is yet another example of Bro making the +life of the common Bro scripter a little easier through abstraction +applied in a practical manner. (Note however that these IP addresses +will never get updated during Bro's processing, so often this +mechanism most useful for addresses that are expected to remain +static.). port ~~~~ Transport layer port numbers in Bro are represented in the format of -``unsigned integer/protocol name`` e.g. ``22/tcp`` or ``53/udp``. Bro -supports TCP( /tcp ), UDP( /udp ) , ICMP( /icmp ) and UNKNOWN( -/unknown ) as protocol designations. While ICMP doesn't have an -actual port, Bro supports the concept of ICMP "ports" by using the -ICMP message type and ICMP message code as the source and destination -port respectively. Ports can be compared for equality using the == or -!= operators and can even be compared for ordering. Bro gives the -protocol designations the following "order": unknown < tcp < udp < -icmp. - -Ports can be compared for equality and also for ordering. When -comparing order across transport-level protocols, unknown < tcp < udp -< icmp, for example 65535/tcp is smaller than 0/udp. +``/``, e.g., ``22/tcp`` or +``53/udp``. Bro supports TCP(``/tcp``), UDP(``/udp``), +ICMP(``/icmp``) and UNKNOWN(``/unknown``) as protocol designations. +While ICMP doesn't have an actual port, Bro supports the concept of +ICMP "ports" by using the ICMP message type and ICMP message code as +the source and destination port respectively. Ports can be compared +for equality using the ``==`` or ``!=`` operators and can even be +compared for ordering. Bro gives the protocol designations the +following "order": ``unknown`` < ``tcp`` < ``udp`` < ``icmp``. For +example ``65535/tcp`` is smaller than ``0/udp``. subnet ~~~~~~ @@ -686,69 +654,64 @@ your scripts. The following example below uses a Bro script to determine if a series of IP addresses are within a set of subnets using a 20 bit subnet mask. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_subnets.bro - :language: bro - :linenos: - :lines: 4-19 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_subnets.bro Because this is a script that doesn't use any kind of network -analysis, we can handle the event bro_init() which is always generated -by Bro's core upon startup. On lines six and seven, two locally -scoped vectors are created to hold our lists of subnets and IP -addresses respectively. Then, using a set of nested for loops, we -iterate over every subnet and every IP address and use an if statement -to compare an IP address against a subnet using the in operator. The -in operator returns true if the IP address falls within a given subnet -based on the longest prefix match calculation. For example, 10.0.0.1 -in 10.0.0.0/8 would return true while 192.168.2.1 in 192.168.1.0/24 -would return false. When we run the script, we get the output listing -the IP address and the subnet in which it belongs. +analysis, we can handle the event :bro:id:`bro_init` which is always +generated by Bro's core upon startup. On lines six and seven, two +locally scoped vectors are created to hold our lists of subnets and IP +addresses respectively. Then, using a set of nested ``for`` loops, we +iterate over every subnet and every IP address and use an ``if`` +statement to compare an IP address against a subnet using the ``in`` +operator. The ``in`` operator returns true if the IP address falls +within a given subnet based on the longest prefix match calculation. +For example, ``10.0.0.1 in 10.0.0.0/8`` would return true while +``192.168.2.1 in 192.168.1.0/24`` would return false. When we run the +script, we get the output listing the IP address and the subnet in +which it belongs. .. btest:: data_type_subnets - @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_subnets.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_subnets.bro time ~~~~ While there is currently no supported way to add a time constant in Bro, two built-in functions exist to make use of the ``time`` data -type. Both ``network_time()`` and ``current_time()`` return a +type. Both :bro:id:`network_time` and :bro:id:`current_time` return a ``time`` data type but they each return a time based on different -criteria. The ``current_time()`` function returns what is called the +criteria. The ``current_time`` function returns what is called the wall-clock time as defined by the operating system. However, -``network_time()`` returns the timestamp of the last packet processed +``network_time`` returns the timestamp of the last packet processed be it from a live data stream or saved packet capture. Both functions return the time in epoch seconds, meaning ``strftime`` must be used to turn the output into human readable output. The script below makes -use of the ``connection_established`` event handler to generate text +use of the :bro:id:`connection_established` event handler to generate text every time a SYN/ACK packet is seen responding to a SYN packet as part of a TCP handshake. The text generated, is in the format of a timestamp and an indication of who the originator and responder were. We use the ``strftime`` format string of ``%Y%M%d %H:%m:%S`` to produce a common date time formatted time stamp. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_time.bro - :language: bro - :linenos: - :lines: 4-7 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_time.bro When the script is executed we get an output showing the details of established connections. .. btest:: data_type_time - @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_time.bro + @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_time.bro interval ~~~~~~~~ The interval data type is another area in Bro where rational -application of abstraction made perfect sense. As a data type, the +application of abstraction makes perfect sense. As a data type, the interval represents a relative time as denoted by a numeric constant followed by a unit of time. For example, 2.2 seconds would be ``2.2sec`` and thirty-one days would be represented by ``31days``. -Bro supports usec, msec, sec, min, hr, or day which represent +Bro supports ``usec``, ``msec``, ``sec``, ``min``, ``hr``, or ``day`` which represent microseconds, milliseconds, seconds, minutes, hours, and days respectively. In fact, the interval data type allows for a surprising amount of variation in its definitions. There can be a space between @@ -768,10 +731,7 @@ operator. The script below amends the script started in the section above to include a time delta value printed along with the connection establishment report. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_interval.bro - :language: bro - :linenos: - :lines: 4-20 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_interval.bro This time, when we execute the script we see an additional line in the output to display the time delta since the last fully established @@ -779,7 +739,7 @@ connection. .. btest:: data_type_interval - @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${TESTBASE}/doc/manual/data_type_interval.bro + @TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_interval.bro Pattern @@ -789,35 +749,32 @@ Bro has support for fast text searching operations using regular expressions and even goes so far as to declare a native data type for the patterns used in regular expressions. A pattern constant is created by enclosing text within the forward slash characters. Bro -supports syntax very similar to the flex lexical analyzer syntax. The +supports syntax very similar to the Flex lexical analyzer syntax. The most common use of patterns in Bro you are likely to come across is embedded matching using the ``in`` operator. Embedded matching adheres to a strict format, requiring the regular expression or pattern constant to be on the left side of the ``in`` operator and the string against which it will be tested to be on the right. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_pattern_01.bro - :language: bro - :linenos: - :lines: 4-13 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_pattern_01.bro In the sample above, two local variables are declared to hold our sample sentence and regular expression. Our regular expression in this case will return true if the string contains either the word -"quick" or the word "fox." The ``if`` statement on line six uses +``quick`` or the word ``fox``. The ``if`` statement on line six uses embedded matching and the ``in`` operator to check for the existence of the pattern within the string. If the statement resolves to true, -split is called to break the string into separate pieces. Split takes -a string and a pattern as its arguments and returns a table of strings -indexed by a count. Each element of the table will be the segments -before and after any matches against the pattern but excluding the -actual matches. In this case, our pattern matches twice, and results -in a table with three entries. Lines 11 through 13 print the contents -of the table in order. +:bro:id:`split` is called to break the string into separate pieces. +``Split`` takes a string and a pattern as its arguments and returns a +table of strings indexed by a count. Each element of the table will +be the segments before and after any matches against the pattern but +excluding the actual matches. In this case, our pattern matches +twice, and results in a table with three entries. Lines 11 through 13 +print the contents of the table in order. .. btest:: data_type_pattern - @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_01.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_01.bro Patterns can also be used to compare strings using equality and inequality operators through the ``==`` and ``!=`` operators @@ -827,23 +784,20 @@ ternary conditional statements to illustrate the use of the ``==`` operators with patterns. On lines 5 and 8 the output is altered based on the result of the comparison between the pattern and the string. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_type_pattern_02.bro - :language: bro - :linenos: - :lines: 4-13 +.. btest-include:: ${DOC_ROOT}/scripting/data_type_pattern_02.bro .. btest:: data_type_pattern_02 - @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_type_pattern_02.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_02.bro Record Data Type -================ +---------------- -With Bro's support for a wide array of data types and data structures -an obvious extension of is to include the ability to create custom -data types consisting of the atomic types and ddata structures. To +With Bro's support for a wide array of data types and data structures, +an obvious extension is to include the ability to create custom +data types composed of atomic types and further data structures. To accomplish this, Bro introduces the ``record`` type and the ``type`` keyword. Similar to how you would define a new data structure in C with the ``typedef`` and ``struct`` keywords, Bro allows you to cobble @@ -851,23 +805,18 @@ together new data types to suit the needs of your situation. When combined with the ``type`` keyword, ``record`` can generate a composite type. We have, in fact, already encountered a a complex -example of the ``record`` data type in the earlier sections. The -excerpt below shows the definition of the connection record data type -as defined in the ``Conn`` module. +example of the ``record`` data type in the earlier sections, the +:bro:id:`connection` record passed to many events. Another one, +:bro:id:`Conn::Info`, which corresponds to the fields logged into +``conn.log``, is shown by the exerpt below. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro :lines: 10-12,16,17,19,21,23,25,28,31,35,37,56,62,68,90,93,97,100,104,108,109,114 -While it might be surprising that Bro is tracking and passing around -this much data for each connection, it shouldn't be too surprising, -given our exploration of it earlier, that the connection record -consists of a collection of atomic data types, simple data types and -even another ``record``. Looking at the structure of the definition, -a new collection of data types is being defined as a type called -``Info``. Since this type definition is within the confines of an -export block, what is defined is, in fact, ``Conn::Info``. +Looking at the structure of the definition, a new collection of data +types is being defined as a type called ``Info``. Since this type +definition is within the confines of an export block, what is defined +is, in fact, ``Conn::Info``. The formatting for a declaration of a record type in Bro includes the descriptive name of the type being defined and the seperate fields @@ -875,38 +824,32 @@ that make up the record. The individual fields that make up the new record are not limited in type or number as long as the name for each field is unique. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_01.bro - :language: bro - :linenos: - :lines: 4-25 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_record_01.bro .. btest:: data_struct_record_01 - @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_01.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_01.bro The sample above shows a simple type definition that includes a string, a set of ports, and a count to define a service type. Also included is a function to print each field of a record in a formatted -fashion and a bro_init event handler to show some functionality of -working with records. The defintions of the dns and http services are -both done inline using squared brackets before being passed to the -``print_service`` function. The ``print_service`` function makes use -of the ``$`` dereference operator to access the fields within the -newly defined Service record type. +fashion and a :bro:id:`bro_init` event handler to show some +functionality of working with records. The definitions of the DNS and +HTTP services are both done inline using squared brackets before being +passed to the ``print_service`` function. The ``print_service`` +function makes use of the ``$`` dereference operator to access the +fields within the newly defined Service record type. -As you saw in the definition for the connection record, other records -are even valid as fields within another record. We can extend the -example above to include another record that contains a Service +As you saw in the definition for the ``Conn::Info`` record, other +records are even valid as fields within another record. We can extend +the example above to include another record that contains a Service record. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/data_struct_record_02.bro - :language: bro - :linenos: - :lines: 4-25 +.. btest-include:: ${DOC_ROOT}/scripting/data_struct_record_02.bro .. btest:: data_struct_record_02 - @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/data_struct_record_02.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_02.bro The example above includes a second record type in which a field is used as the data type for a set. Records can be reapeatedly nested @@ -917,9 +860,7 @@ It's also common to see a ``type`` used to simply alias a data structure to a more descriptive name. The example below shows an example of this from Bro's own type definitions file. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/base/init-bare.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/init-bare.bro :lines: 12,19,26 The three lines above alias a type of data structure to a descriptive @@ -930,8 +871,8 @@ consideration can lead to better readability of your code and thus easier maintainability in the future. -Logging Framework -================= +Custom Logging +============== Armed with a decent understanding of the data types and data structures in Bro, exploring the various frameworks available is a @@ -940,23 +881,24 @@ likely to have the most interaction is the Logging Framework. Designed in such a way to so as to abstract much of the process of creating a file and appending ordered and organized data into it, the Logging Framework makes use of some potentially unfamiliar -nomenclature. Specifically, Log streams, Filters and Writers are +nomenclature. Specifically, Log Streams, Filters and Writers are simply abstractions of the processes required to manage a high rate of incoming logs while maintaining full operability. If you've seen Bro -employed in an environment with a large connection, you know that logs -are produced incredibly quickly; the ability to process a large set of -data and write it to disk is due to the design of the Logging -Framework. +employed in an environment with a large number of connections, you +know that logs are produced incredibly quickly; the ability to process +a large set of data and write it to disk is due to the design of the +Logging Framework. -Data is written to a Log stream based on decision making processes in -Bro's scriptland. Log streams correspond to a single log as defined -by the set of name value pairs that make up its fields. That data can +Data is written to a Log Stream based on decision making processes in +Bro's scriptland. Log Streams correspond to a single log as defined +by the set of name/value pairs that make up its fields. That data can then be filtered, modified, or redirected with Logging Filters which, by default, are set to log everything. Filters can be used to break log files into subsets or duplicate that information to another output. The final output of the data is defined by the writer. Bro's default writer is simple tab separated ASCII files but Bro also -includes support for DataSeries and Elasticsearch outputs as well as +includes support for `DataSeries `_ +and `Elasticsearch `_ outputs as well as additional writers currently in development. While these new terms and ideas may give the impression that the Logging Framework is difficult to work with, the actual learning curve is, in actuality, @@ -964,11 +906,11 @@ not very steep at all. The abstraction built into the Logging Framework makes it such that a vast majority of scripts needs not go past the basics. In effect, writing to a log file is as simple as defining the format of your data, letting Bro know that you wish to -create a new log, and then calling the ``Log::write()`` method to +create a new log, and then calling the :bro:id:`Log::write` method to output log records. -The Logging Framework is an are in Bro where, the more you see it used -and the more you use it yourself, the more second nature the +The Logging Framework is an area in Bro where, the more you see it +used and the more you use it yourself, the more second nature the boilerplate parts of the code will become. As such, let's work through a contrived example of simply logging the digits 1 through 10 and their corresponding factorial to the default ASCII log writer. @@ -977,64 +919,59 @@ desired output with ``print`` and ``fmt`` before attempting to dive into the Logging Framework. Below is a script that defines a factorial function to recursively calculate the factorial of a unsigned integer passed as an argument to the function. Using -``print`` and ``fmt`` we can ensure that Bro can perform these +:bro:id:`print` :bro:id:`fmt` we can ensure that Bro can perform these calculations correctly as well get an idea of the answers ourselves. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_01.bro - :language: bro - :linenos: - :lines: 4-25 +.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro -.. btest:: framework_logging_factorial_01 +.. btest:: framework_logging_factorial - @TEST-EXEC: btest-rst-cmd bro ${TESTBASE}/doc/manual/framework_logging_factorial_01.bro + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro The output of the script aligns with what we expect so now it's time to integrate the Logging Framework. As mentioned above we have to -perform a few steps before we can issue the ``Log::write()`` method -and produce a logfile. As we are working within a namespace and -informing an outside entity of workings and data internal to the -namespace, we use an ``export{}`` block. First we need to inform Bro -that we are going to be adding another Log stream by adding a value to -the ``Log::ID`` enumerable. In line 3 of the script, we append the -value ``LOG`` to the Log::ID enumerable, however due to this being in +perform a few steps before we can issue the :bro:id:`Log::write` +method and produce a logfile. As we are working within a namespace +and informing an outside entity of workings and data internal to the +namespace, we use an ``export`` block. First we need to inform Bro +that we are going to be adding another Log Stream by adding a value to +the :bro:id:`Log::ID` enumerable. In line 3 of the script, we append the +value ``LOG`` to the ``Log::ID`` enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs that make up the data of our logs and dictate its format. Lines 5 -through 9 define a new datatype called an Info record (actually, +through 9 define a new datatype called an ``Info`` record (actually, ``Factor::Info``) with two fields, both unsigned integers. Each of the fields in the ``Factor::Log`` record type include the ``&log`` attribute, indicating that these fields should be passed to the -Logging Framework when ``Log::write()`` is called. Were there to be +Logging Framework when ``Log::write`` is called. Were there to be any name value pairs without the ``&log`` attribute, those fields would simply be ignored during logging but remain available for the lifespan of the variable. The next step is to create the logging -stream with ``Log::create_stream()`` which takes a Log::ID and a +stream with :bro:id:`Log::create_stream` which takes a Log::ID and a record as its arguments. In this example, on line 28, we call the -``Log::create_stream()`` method and pass ``Factor::LOG`` and the +``Log::create_stream`` method and pass ``Factor::LOG`` and the ``Factor::Info`` record as arguments. From here on out, if we issue -the ``Log::write()`` command with the correct Log::ID and a properly +the ``Log::write`` command with the correct ``Log::ID`` and a properly formatted ``Factor::Info`` record, a log entry will be generated. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_02.bro - :language: bro - :linenos: - :lines: 4-40 +.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_02.bro Now, if we run the new version of the script, instead of generating logging information to stdout, no output is created. Instead the -output is all in factor.log, properly formatted and organized. +output is all in ``factor.log``, properly formatted and organized. -.. btest:: framework_logging_factorial_02 +.. btest:: framework_logging_factorial-2 - @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_02/factor.log + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_02.bro + @TEST-EXEC: btest-rst-include factor.log While the previous example is a simplistic one, it serves to -demonstrate the small pieces of script that need to be in place in +demonstrate the small pieces of script code hat need to be in place in order to generate logs. For example, it's common to call -``Log::create_stream()`` in ``bro_init()`` and while in a live -example, determining when to call ``Log::write()`` would likely be -done in an event handler, in this case we use ``bro_done()``. +``Log::create_stream`` in :bro:id:`bro_init` and while in a live +example, determining when to call ``Log::write`` would likely be +done in an event handler, in this case we use :bro:id:`bro_done` . If you've already spent time with a deployment of Bro, you've likely had the opportunity to view, search through, or manipulate the logs @@ -1042,7 +979,7 @@ produced by the Logging Framework. The log output from a default installation of Bro is substantial to say the least, however, there are times in which the way the Logging Framework by default isn't ideal for the situation. This can range from needing to log more or -less data with each call to ``Log::write()`` or even the need to split +less data with each call to ``Log::write`` or even the need to split log files based on arbitrary logic. In the later case, Filters come into play along with the Logging Framework. Filters grant a level of customization to Bro's scriptland, allowing the script writer to @@ -1055,34 +992,33 @@ example we've been using, let's extend it so as to write any factorial which is a factor of 5 to an alternate file, while writing the remaining logs to factor.log. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_03.bro - :language: bro +.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_03.bro + :lines: 38-62 :linenos: - :lines: 43-60 To dynamically alter the file in which a stream writes its logs a filter can specify function returns a string to be used as the -filename for the current call to ``Log::write()``. The definition for -this function has to take as its parameters a Log::ID called id, a -string called path and the appropriate record type for the logs called -"rec". You can see the definition of ``mod5`` used in this example on +filename for the current call to ``Log::write``. The definition for +this function has to take as its parameters a ``Log::ID`` called id, a +string called ``path`` and the appropriate record type for the logs called +``rec``. You can see the definition of ``mod5`` used in this example on line one conforms to that requirement. The function simply returns -"factor-mod5" if the factorial is divisible evenly by 5, otherwise, it -returns "factor-non5". In the additional ``bro_init()`` event +``factor-mod5`` if the factorial is divisible evenly by 5, otherwise, it +returns ``factor-non5``. In the additional ``bro_init`` event handler, we define a locally scoped ``Log::Filter`` and assign it a record that defines the ``name`` and ``path_func`` fields. We then -call ``Log::add_filter()`` to add the filter to the ``Factor::LOG`` -Log::ID and call ``Log::remove_filter()`` to remove the ``default`` -filter for Factor::LOG. Had we not removed the ``default`` filter, -we'd have ended up with three log files: factor-mod5.log with all the -factorials that are a factors of 5, factor-non5.log with the -factorials that are not factors of 5, and factor.log which would have +call ``Log::add_filter`` to add the filter to the ``Factor::LOG`` +``Log::ID`` and call ``Log::remove_filter`` to remove the ``default`` +filter for ``Factor::LOG``. Had we not removed the ``default`` filter, +we'd have ended up with three log files: ``factor-mod5.log`` with all the +factorials that are a factors of 5, ``factor-non5.log`` with the +factorials that are not factors of 5, and ``factor.log`` which would have included all factorials. -.. btest:: framework_logging_factorial_02 +.. btest:: framework_logging_factorial-3 - @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_03/factor-mod5.log - @TEST-EXEC: btest-rst-include ${TESTBASE}/Baseline/doc.manual.framework_logging_factorial_03/factor-non5.log + @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_03.bro + @TEST-EXEC: btest-rst-include factor-mod5.log The ability of Bro to generate easily customizable and extensible logs which remain easily parsable is a big part of the reason Bro has @@ -1112,34 +1048,31 @@ block and define the value to be passed to it, in this case the ``Factor::Info`` record. We then list the ``log_factor`` function as the ``$ev`` field in the call to ``Log::create_stream`` -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_logging_factorial_04.bro - :language: bro - :linenos: - :lines: 4-62 +.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_04.bro -Notice Framework -================ +Raising Notices +=============== While Bro's Logging Framework provides an easy and systematic way to generate logs, there still exists a need to indicate when a specific behavior has been detected and a method to allow that detection to come to someone's attention. To that end, the Notice Framework is in place to allow script writers a codified means through which they can -raise a notice and a system through which an operator can opt-in to -receive the notice. Bro holds to the philosophy that it is up to the -individual operator to indicate the behaviors in which they are -interested and as such Bro ships with a large number of policy scripts -which detect behavior that may be of interest but it does not presume -to guess as to which behaviors are "action-able". In effect, Bro -works to separate the act of detection and the responsibility of +raise a notice, as well as a system through which an operator can +opt-in to receive the notice. Bro holds to the philosophy that it is +up to the individual operator to indicate the behaviors in which they +are interested and as such Bro ships with a large number of policy +scripts which detect behavior that may be of interest but it does not +presume to guess as to which behaviors are "action-able". In effect, +Bro works to separate the act of detection and the responsibility of reporting. With the Notice Framework it's simple to raise a notice for any behavior that is detected. To raise a notice in Bro, you only need to indicate to Bro that you -are provide a specific ``Notice::Type`` by exporting it and then make -a call to ``NOTICE()`` supplying it with an appropriate -``Notice::Info`` record. Often times the call to ``NOTICE()`` +are provide a specific :bro:id:`Notice::Type` by exporting it and then +make a call to :bro:id:`NOTICE` supplying it with an appropriate +:bro:id:`Notice::Info` record. Often times the call to ``NOTICE`` includes just the ``Notice::Type``, and a concise message. There are however, significantly more options available when raising notices as seen in the table below. The only field in the table below whose @@ -1154,6 +1087,11 @@ that are commonly included, ``$identifier`` and ``$suppress_for`` are built around the automated suppression feature of the Notice Framework which we will cover shortly. +.. todo:: + + Once the link to ``Notice::Info`` work I think we should take out + the table. That's too easy to get out of date. + +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | Field | Type | Attributes | Use | +=====================+==================================================================+================+========================================+ @@ -1204,16 +1142,14 @@ One of the default policy scripts raises a notice when an SSH login has been heuristically detected and the originating hostname is one that would raise suspicion. Effectively, the script attempts to define a list of hosts from which you would never want to see SSH -traffic originating, dns servers, mail servers, etc. To accomplish -this, the script adhere's to the seperation of detection and reporting -by detecting a behavior and raising a notice. Whether or not that -notice is acted upon is decided by the local Notice Policy, but the -script attempts to supply as much information as possible while -staying concise. +traffic originating, like DNS servers, mail servers, etc. To +accomplish this, the script adhere's to the seperation of detection +and reporting by detecting a behavior and raising a notice. Whether +or not that notice is acted upon is decided by the local Notice +Policy, but the script attempts to supply as much information as +possible while staying concise. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssh/interesting-hostnames.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssh/interesting-hostnames.bro :lines: 1-46 While much of the script relates to the actual detection, the parts @@ -1221,51 +1157,51 @@ specific to the Notice Framework are actually quite interesting in themselves. On line 12 the script's ``export`` block adds the value ``SSH::Interesting_Hostname_Login`` to the enumerable constant ``Notice::Type`` to indicate to the Bro core that a new type of notice -is being defined. The script then calls ``NOTICE()`` and defines the -``$note``, ``$msg``, ``$sub`` and ``$conn`` fields. Line 39 also -includes a ternary if statement that modifies the ``$msg`` text -depending on whether the host is a local address and whether it is the -client or the server. This use of ``fmt()`` and a ternary operators -is a concise way to lend readability to the notices that are generated -without the need for branching ``if`` statements that each raise a -specific notice. +is being defined. The script then calls ``NOTICE`` and defines the +``$note``, ``$msg``, ``$sub`` and ``$conn`` fields of the +:bro:id:`Notice::Info` record. Line 39 also includes a ternary if +statement that modifies the ``$msg`` text depending on whether the +host is a local address and whether it is the client or the server. +This use of :bro:id:`fmt` and a ternary operators is a concise way to +lend readability to the notices that are generated without the need +for branching ``if`` statements that each raise a specific notice. The opt-in system for notices is managed through writing -``Notice::policy`` hooks. A ``Notice::policy`` hook takes as its -argument a ``Notice::Info`` record which will hold the same -information your script provided in its call to ``NOTICE()``. With +:bro:id:`Notice::policy` hooks. A ``Notice::policy`` hook takes as +its argument a ``Notice::Info`` record which will hold the same +information your script provided in its call to ``NOTICE``. With access to the ``Notice::Info`` record for a specific notice you can include logic such as in statements in the body of your hook to alter -the Policy for handling notices on your system. Notice hooks are akin -to functions and event handlers and share the same structure; You can -even think of hooks as multi-bodied functions. You define the hook -and Bro will take care of passing in the ``Notice::Info`` record. The -simplest kind of ``Notice::policy`` hooks simply check the value of -``$note`` in the ``Notice::Info`` record being passed into the hook -and performing an action based on the answer. The hook below adds the -``Notice::ACTION_EMAIL`` action for the -SSH::Interesting_Hostname_Login notice raised in the -interesting-hostnames.bro script. +the policy for handling notices on your system. In Bro, hooks are +akin to a mix of functions and event handlers: like functions, calls +to them are synchronous (i.e., run to completion and return); but like +events, they can have multiple bodies which will all execute. For +defining a notice policy, you define a hook and Bro will take care of +passing in the ``Notice::Info`` record. The simplest kind of +``Notice::policy`` hooks simply check the value of ``$note`` in the +``Notice::Info`` record being passed into the hook and performing an +action based on the answer. The hook below adds the +:bro:id:`Notice::ACTION_EMAIL` action for the +``SSH::Interesting_Hostname_Login`` notice raised in the +:doc:`scripts/policy/protocols/ssh/interesting-hostnames.bro` script. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_hook_01.bro - :language: bro - :linenos: - :lines: 6-12 +.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_hook_01.bro In the example above we've added ``Notice::ACTION_EMAIL`` to the ``n$actions`` set. This set, defined in the Notice Framework scripts, -can only have entries from the Notice::Action type which is itself an -enumerable that defines the values shown in the table below along with -their corresponding meanings. The ``Notice::ACTION_LOG`` action -writes the notice to the ``Notice::LOG`` logging stream which, in the -default configuration, will write each notice to the notice.log file -and take no further action. The ``Notice::ACTION_EMAIL`` action will -send an email to the address or addresses defined in the -``Notice::mail_dest`` variable with the particulars of the notice as -the body of the email. The last action, ``Notice::ACTION_ALARM`` -sends the notice to the ``Notice::ALARM_LOG`` logging stream which is -then rotated hourly and its contents emailed in readable ASCII to the -addresses in ``Notice::mail_dest``. +can only have entries from the :bro:id:`Notice::Action` type, which is +itself an enumerable that defines the values shown in the table below +along with their corresponding meanings. The +:bro:id:`Notice::ACTION_LOG` action writes the notice to the +``Notice::LOG`` logging stream which, in the default configuration, +will write each notice to the ``notice.log`` file and take no further +action. The :bro:id:`Notice::ACTION_EMAIL` action will send an email +to the address or addresses defined in the :bro:id:`Notice::mail_dest` +variable with the particulars of the notice as the body of the email. +The last action, :bro:id:`Notice::ACTION_ALARM` sends the notice to +the :bro:id:`Notice::ALARM_LOG` logging stream which is then rotated +hourly and its contents emailed in readable ASCII to the addresses in +``Notice::mail_dest``. +--------------+-----------------------------------------------------+ | ACTION_NONE | Take no action | @@ -1286,31 +1222,30 @@ identifier. An identifier is a unique string of information collected from the connection relative to the behavior that has been observed by Bro. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssl/expiring-certs.bro - :language: bro - :linenos: +.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssl/expiring-certs.bro :lines: 59-62 -In the ``expiring-certs.bro`` script which identifies when SSL -certificates are set to expire and raises notices when it crosses a -pre-defined threshold, the call to ``NOTICE()`` above also sets the -``$identifier`` entry by concatenating the responder ip, port, and the -hash of the certificate. The selection of responder ip, port and -certificate hash fits perfectly into an appropriate identifier as it -creates a unique identifier with which the suppression can be matched. -Were we to take out any of the entities used for the identifier, for -example the certificate hash, we could be setting our suppression too -broadly, causing an analyst to miss a notice that should have been -raised. Depending on the available data for the identifier, it can be -useful to set the ``$suppress_for`` variable as well. The -``expiring-certs.bro`` script sets ``$suppress_for`` to ``1day``, -telling the Notice Framework to suppress the notice for 24 hours after -the first notice is raised. Once that time limit has passed, another -notice can be raised which will again set the ``1day`` suppression -time. Suppressing for a specific amount of time has benefits beyond -simply not filling up an analyst's email inbox; keeping the notice -alerts timely and succinct helps avoid a case where an analyst might -see the notice and, due to over exposure, ignore it. +In the :doc:`scripts/policy/protocols/ssl/expiring-certs.bro` script +which identifies when SSL certificates are set to expire and raises +notices when it crosses a pre-defined threshold, the call to +``NOTICE`` above also sets the ``$identifier`` entry by concatenating +the responder IP, port, and the hash of the certificate. The +selection of responder IP, port and certificate hash fits perfectly +into an appropriate identifier as it creates a unique identifier with +which the suppression can be matched. Were we to take out any of the +entities used for the identifier, for example the certificate hash, we +could be setting our suppression too broadly, causing an analyst to +miss a notice that should have been raised. Depending on the +available data for the identifier, it can be useful to set the +``$suppress_for`` variable as well. The ``expiring-certs.bro`` script +sets ``$suppress_for`` to ``1day``, telling the Notice Framework to +suppress the notice for 24 hours after the first notice is raised. +Once that time limit has passed, another notice can be raised which +will again set the ``1day`` suppression time. Suppressing for a +specific amount of time has benefits beyond simply not filling up an +analyst's email inbox; keeping the notice alerts timely and succinct +helps avoid a case where an analyst might see the notice and, due to +over exposure, ignore it. The ``$suppress_for`` variable can also be altered in a ``Notice::policy`` hook, allowing a deployment to better suit the @@ -1319,10 +1254,7 @@ environment in which it is be run. Using the example of ``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for`` variable to a shorter time. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro - :language: bro - :linenos: - :lines: 6-12 +.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_hook_suppression_01.bro While ``Notice::policy`` hooks allow you to build custom predicate-based policies for a deployment, there are bound to be times @@ -1333,11 +1265,11 @@ facilitate these types of decisions, the Notice Framework supports Notice Policy shortcuts. These shortcuts are implemented through the means of a group of data structures that map specific, pre-defined details and actions to the effective name of a notice. Primarily -implemented as a set or table of enumerables of ``Notice::Type``, +implemented as a set or table of enumerables of :bro:id:`Notice::Type`, Notice Policy shortcuts can be placed as a single directive in your ``local.bro`` file as a concise readable configuration. As these variables are all constants, it bears mentioning that these variables -are all set at parsetime before Bro is fully up and running and not +are all set at parse-time before Bro is fully up and running and not set dynamically. +------------------------------------+-----------------------------------------------------+-------------------------------------+ @@ -1367,21 +1299,15 @@ suppression being applied to the Notice. The shortcut ``Notice::not_suppressed_types`` can be used to remove the configured suppression from a notice while ``Notice::type_suppression_intervals`` can be used to alter the suppression interval defined by $suppress_for -in the call to ``NOTICE()``. +in the call to ``NOTICE``. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_shortcuts_01.bro - :language: bro - :linenos: - :lines: 7-10 +.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_shortcuts_01.bro The Notice Policy shortcut above adds the ``Notice::Types`` of SSH::Interesting_Hostname_Login and SSH::Login to the Notice::emailed_types set while the shortcut below alters the length of time for which those notices will be suppressed. -.. rootedliteralinclude:: ${BRO_SRC_ROOT}/testing/btest/doc/manual/framework_notice_shortcuts_02.bro - :language: bro - :linenos: - :lines: 7-10 +.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_shortcuts_02.bro diff --git a/testing/btest/doc/manual/using_bro_sandbox_01 b/doc/scripting/using_bro_sandbox_01 similarity index 100% rename from testing/btest/doc/manual/using_bro_sandbox_01 rename to doc/scripting/using_bro_sandbox_01 diff --git a/testing/btest/doc/manual/using_bro_sandbox_02 b/doc/scripting/using_bro_sandbox_02 similarity index 100% rename from testing/btest/doc/manual/using_bro_sandbox_02 rename to doc/scripting/using_bro_sandbox_02 diff --git a/doc/using/index.rst b/doc/using/index.rst index c9226fadd2..1ad05d74f8 100644 --- a/doc/using/index.rst +++ b/doc/using/index.rst @@ -44,7 +44,8 @@ the Unix utility ``head`` and outputting the first lines of the file: .. btest:: using_bro - @TEST-EXEC: btest-rst-cmd "bro -r $TRACES/wikipedia.trace && head -15 conn.log" + @TEST-EXEC: btest-rst-cmd bro -r $TRACES/wikipedia.trace + @TEST-EXEC: btest-rst-include -n 15 conn.log As you can see, the header consists of lines prefixed by ``#`` and includes information such as what separators are being used for diff --git a/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 b/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 new file mode 100644 index 0000000000..869395d05e --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 @@ -0,0 +1,11 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b -r dns-session.trace connection_record_01.bro + [id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={ + + }, addl=, hot=0, history=ShADadFf, uid=UWkUyAuUGXf, tunnel=, conn=[ts=930613226.067666, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ + + }], extract_orig=F, extract_resp=F] + diff --git a/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 b/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 new file mode 100644 index 0000000000..3de3ee79a6 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 @@ -0,0 +1,17 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b -r dns-session.trace connection_record_02.bro + [id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={ + + }, addl=, hot=0, history=ShADadFf, uid=UWkUyAuUGXf, tunnel=, conn=[ts=930613226.067666, uid=UWkUyAuUGXf, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ + + }], extract_orig=F, extract_resp=F, dns=, dns_state=[pending={ + [34798] = [initialized=T, vals={ + + }, settings=[max_len=], top=1, bottom=1, size=0] + }, finished_answers={ + + }]] + diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 b/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 new file mode 100644 index 0000000000..5b8d702333 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 @@ -0,0 +1,12 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_record_01.bro + Service: dns(RFC1035) + port: 53/tcp + port: 53/udp + Service: http(RFC2616) + port: 80/tcp + port: 8080/tcp + diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 b/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 new file mode 100644 index 0000000000..b640862c49 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 @@ -0,0 +1,13 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_record_02.bro + System: morlock + Service: dns(RFC1035) + port: 53/tcp + port: 53/udp + Service: http(RFC2616) + port: 80/tcp + port: 8080/tcp + diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 new file mode 100644 index 0000000000..f22481364a --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 @@ -0,0 +1,14 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_set_declaration.bro + SSL Port: 993/tcp + SSL Port: 22/tcp + SSL Port: 587/tcp + SSL Port: 443/tcp + Non-SSL Port: 143/tcp + Non-SSL Port: 25/tcp + Non-SSL Port: 80/tcp + Non-SSL Port: 23/tcp + diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 b/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 new file mode 100644 index 0000000000..415d6b4436 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 @@ -0,0 +1,10 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b data_struct_table_complex.bro + Kiru was released in 1968 by Toho studios, directed by Kihachi Okamoto and starring Tatsuya Nakadai + Goyokin was released in 1969 by Fuji studios, directed by Hideo Gosha and starring Tatsuya Nakadai + Harakiri was released in 1962 by Shochiku Eiga studios, directed by Masaki Kobayashi and starring Tatsuya Nakadai + Tasogare Seibei was released in 2002 by Eisei Gekijo studios, directed by Yoji Yamada and starring Hiroyuki Sanada + diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 new file mode 100644 index 0000000000..0b6efd6166 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 @@ -0,0 +1,10 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_table_declaration.bro + Service Name: IMAPS - Common Port: 993/tcp + Service Name: HTTPS - Common Port: 443/tcp + Service Name: SSH - Common Port: 22/tcp + Service Name: SMTPS - Common Port: 587/tcp + diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 new file mode 100644 index 0000000000..c282de7c49 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 @@ -0,0 +1,10 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_vector_declaration.bro + contents of v1: [1, 2, 3, 4] + length of v1: 4 + contents of v1: [1, 2, 3, 4] + length of v2: 4 + diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 b/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 new file mode 100644 index 0000000000..88634f57a6 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 @@ -0,0 +1,9 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b data_struct_vector_iter.bro + 1.2.0.0/18 + 2.3.0.0/18 + 3.4.0.0/18 + diff --git a/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 b/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 new file mode 100644 index 0000000000..48532cfb84 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 @@ -0,0 +1,10 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b data_type_const.bro + { + [6666/tcp] = IRC, + [80/tcp] = WWW + } + diff --git a/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 b/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 new file mode 100644 index 0000000000..d200467611 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 @@ -0,0 +1,23 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -r wikipedia.trace data_type_interval.bro + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118 + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 132.0 msecs 97.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 177.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 2.0 msecs 177.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 33.0 msecs 898.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 35.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 2.0 msecs 532.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2 + Time since last connection: 7.0 msecs 866.0 usecs + 2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128 + Time since last connection: 817.0 msecs 703.0 usecs + diff --git a/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 b/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 new file mode 100644 index 0000000000..e74a70e576 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 @@ -0,0 +1,9 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_type_pattern_01.bro + The + brown fox jumped over the + dog. + diff --git a/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 b/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 new file mode 100644 index 0000000000..3097c85bcd --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 @@ -0,0 +1,8 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_type_pattern_02.bro + equality and /^?(equal)$?/ are not equal + equality and /^?(equality)$?/ are equal + diff --git a/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 b/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 new file mode 100644 index 0000000000..92d18b84ba --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 @@ -0,0 +1,10 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_type_subnets.bro + 172.16.4.56 belongs to subnet 172.16.0.0/20 + 172.16.47.254 belongs to subnet 172.16.32.0/20 + 172.16.22.45 belongs to subnet 172.16.16.0/20 + 172.16.1.1 belongs to subnet 172.16.0.0/20 + diff --git a/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 b/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 new file mode 100644 index 0000000000..d83f819038 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 @@ -0,0 +1,15 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -r wikipedia.trace data_type_time.bro + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2^J + 2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128^J + diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 new file mode 100644 index 0000000000..e7fd140e3c --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 @@ -0,0 +1,29 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro framework_logging_factorial_02.bro + +.. code-block:: guess + :linenos: + + #separator \x09 + #set_separator , + #empty_field (empty) + #unset_field - + #path factor + #open 2013-08-30-23-20-49 + #fields num factorial_num + #types count count + 1 1 + 2 2 + 3 6 + 4 24 + 5 120 + 6 720 + 7 5040 + 8 40320 + 9 362880 + 10 3628800 + #close 2013-08-30-23-20-49 + diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 new file mode 100644 index 0000000000..f19018b16c --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 @@ -0,0 +1,25 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro framework_logging_factorial_03.bro + +.. code-block:: guess + :linenos: + + #separator \x09 + #set_separator , + #empty_field (empty) + #unset_field - + #path factor-mod5 + #open 2013-08-30-23-20-49 + #fields num factorial_num + #types count count + 5 120 + 6 720 + 7 5040 + 8 40320 + 9 362880 + 10 3628800 + #close 2013-08-30-23-20-49 + diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 new file mode 100644 index 0000000000..8a64a2da65 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 @@ -0,0 +1,16 @@ +.. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro framework_logging_factorial_01.bro + 1 + 2 + 6 + 24 + 120 + 720 + 5040 + 40320 + 362880 + 3628800 + diff --git a/testing/btest/doc/manual/connection_record_02.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest similarity index 53% rename from testing/btest/doc/manual/connection_record_02.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest index 480e42af0b..43a6ebc554 100644 --- a/testing/btest/doc/manual/connection_record_02.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest @@ -1,10 +1,11 @@ -# @TEST-EXEC: bro -b -r $TRACES/dns-session.trace %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- connection_record_02.bro @load base/protocols/conn @load base/protocols/dns event connection_state_remove(c: connection) - { + { print c; - } \ No newline at end of file + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest new file mode 100644 index 0000000000..43a6ebc554 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- connection_record_02.bro + +@load base/protocols/conn +@load base/protocols/dns + +event connection_state_remove(c: connection) + { + print c; + } diff --git a/testing/btest/doc/manual/data_struct_record_01.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest similarity index 53% rename from testing/btest/doc/manual/data_struct_record_01.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest index 25eb0b02a0..82f1b1f56c 100644 --- a/testing/btest/doc/manual/data_struct_record_01.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest @@ -1,5 +1,6 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_record_01.bro type Service: record { name: string; @@ -10,16 +11,16 @@ type Service: record { function print_service(serv: Service): string { print fmt("Service: %s(RFC%d)",serv$name, serv$rfc); - for (p in serv$ports) - { + + for ( p in serv$ports ) print fmt(" port: %s", p); - } } event bro_init() { - local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; - local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; + local dns: Service = [$name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; + local http: Service = [$name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; + print_service(dns); print_service(http); } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest new file mode 100644 index 0000000000..05b5b9d50c --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest @@ -0,0 +1,45 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_record_02.bro + +type Service: record { + name: string; + ports: set[port]; + rfc: count; + }; + +type System: record { + name: string; + services: set[Service]; + }; + +function print_service(serv: Service): string + { + print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc); + + for ( p in serv$ports ) + print fmt(" port: %s", p); + } + +function print_system(sys: System): string + { + print fmt("System: %s", sys$name); + + for ( s in sys$services ) + print_service(s); + } + +event bro_init() + { + local server01: System; + server01$name = "morlock"; + add server01$services[[ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]]; + add server01$services[[ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]]; + print_system(server01); + + + # local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; + # local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; + # print_service(dns); + # print_service(http); + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest new file mode 100644 index 0000000000..b659563ac3 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest @@ -0,0 +1,9 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_set_declaration.bro + +event bro_init() + { + local ssl_ports: set[port]; + local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp ); + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest new file mode 100644 index 0000000000..5fa1f36475 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest @@ -0,0 +1,9 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_set_declaration.bro + + for ( i in ssl_ports ) + print fmt("SSL Port: %s", i); + + for ( i in non_ssl_ports ) + print fmt("Non-SSL Port: %s", i); diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest new file mode 100644 index 0000000000..48d33b52e5 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest @@ -0,0 +1,7 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_set_declaration.bro + + # Check for SMTPS + if ( 587/tcp !in ssl_ports ) + add ssl_ports[587/tcp]; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest new file mode 100644 index 0000000000..19ddfe81d5 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest @@ -0,0 +1,26 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_set_declaration.bro + +event bro_init() + { + local ssl_ports: set[port]; + local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp ); + + # SSH + add ssl_ports[22/tcp]; + # HTTPS + add ssl_ports[443/tcp]; + # IMAPS + add ssl_ports[993/tcp]; + + # Check for SMTPS + if ( 587/tcp !in ssl_ports ) + add ssl_ports[587/tcp]; + + for ( i in ssl_ports ) + print fmt("SSL Port: %s", i); + + for ( i in non_ssl_ports ) + print fmt("Non-SSL Port: %s", i); + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest new file mode 100644 index 0000000000..a6a1d7a63a --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest @@ -0,0 +1,17 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_table_complex.bro + +event bro_init() + { + local samurai_flicks: table[string, string, count, string] of string; + + samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru"; + samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin"; + samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri"; + samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei"; + + for ( [d, s, y, a] in samurai_flicks ) + print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a); + } + diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest new file mode 100644 index 0000000000..79fe7660ae --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest @@ -0,0 +1,17 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_table_declaration.bro + +event bro_init() + { + local ssl_services: table[string] of port; + + ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp); + ssl_services["IMAPS"] = 993/tcp; + + if ( "SMTPS" !in ssl_services ) + ssl_services["SMTPS"] = 587/tcp; + + for ( k in ssl_services ) + print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]); + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest new file mode 100644 index 0000000000..6b8a81a58f --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest @@ -0,0 +1,19 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_vector_declaration.bro + +event bro_init() + { + local v1: vector of count; + local v2 = vector(1, 2, 3, 4); + + v1[|v1|] = 1; + v1[|v1|] = 2; + v1[|v1|] = 3; + v1[|v1|] = 4; + + print fmt("contents of v1: %s", v1); + print fmt("length of v1: %d", |v1|); + print fmt("contents of v1: %s", v2); + print fmt("length of v2: %d", |v2|); + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest new file mode 100644 index 0000000000..a28522fb64 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_vector_iter.bro + +event bro_init() + { + local addr_vector: vector of addr = vector(1.2.3.4, 2.3.4.5, 3.4.5.6); + + for (i in addr_vector) + print mask_addr(addr_vector[i], 18); + } diff --git a/testing/btest/doc/manual/data_type_const.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest similarity index 72% rename from testing/btest/doc/manual/data_type_const.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest index bdcc888945..a42efd2b72 100644 --- a/testing/btest/doc/manual/data_type_const.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest @@ -1,5 +1,6 @@ -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_const.bro const port_list: table[port] of string &redef; @@ -9,4 +10,4 @@ redef port_list += { [80/tcp] = "WWW" }; event bro_init() { print port_list; - } \ No newline at end of file + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest new file mode 100644 index 0000000000..914f9dc0ec --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest @@ -0,0 +1,8 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_const_simple.bro + +@load base/protocols/http + +redef HTTP::default_capture_password = T; + diff --git a/testing/btest/doc/manual/data_type_declaration.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest similarity index 53% rename from testing/btest/doc/manual/data_type_declaration.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest index ba82e0da20..edd01615fc 100644 --- a/testing/btest/doc/manual/data_type_declaration.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest @@ -1,5 +1,6 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_declaration.bro event bro_init() { @@ -7,8 +8,6 @@ event bro_init() a = 10; local b = 10; - if (a == b) - { + if ( a == b ) print fmt("A: %d, B: %d", a, b); - } - } \ No newline at end of file + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest new file mode 100644 index 0000000000..7954ed9ebe --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest @@ -0,0 +1,22 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_interval.bro + +# Store the time the previous connection was established. +global last_connection_time: time; + +# boolean value to indicate whether we have seen a previous connection. +global connection_seen: bool = F; + +event connection_established(c: connection) + { + local net_time: time = network_time(); + + print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h); + + if ( connection_seen ) + print fmt(" Time since last connection: %s", net_time - last_connection_time); + + last_connection_time = net_time; + connection_seen = T; + } diff --git a/testing/btest/doc/manual/data_type_local.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest similarity index 75% rename from testing/btest/doc/manual/data_type_local.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest index e589f39e9f..850ffeb905 100644 --- a/testing/btest/doc/manual/data_type_local.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest @@ -1,5 +1,6 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_local.bro function add_two(i: count): count { @@ -11,4 +12,4 @@ function add_two(i: count): count event bro_init() { local test = add_two(10); - } \ No newline at end of file + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest new file mode 100644 index 0000000000..475fcd676e --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest @@ -0,0 +1,17 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_pattern_01.bro + +event bro_init() + { + local test_string = "The quick brown fox jumped over the lazy dog."; + local test_pattern = /quick|lazy/; + + if ( test_pattern in test_string ) + { + local results = split(test_string, test_pattern); + print results[1]; + print results[2]; + print results[3]; + } + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest new file mode 100644 index 0000000000..915e8612be --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest @@ -0,0 +1,14 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_pattern_02.bro + +event bro_init() + { + local test_string = "equality"; + + local test_pattern = /equal/; + print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); + + test_pattern = /equality/; + print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); + } diff --git a/testing/btest/doc/manual/data_type_subnets.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest similarity index 63% rename from testing/btest/doc/manual/data_type_subnets.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest index b0d174069a..d2edfd5e9a 100644 --- a/testing/btest/doc/manual/data_type_subnets.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest @@ -1,22 +1,19 @@ -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_subnets.bro event bro_init() { local subnets = vector(172.16.0.0/20, 172.16.16.0/20, 172.16.32.0/20, 172.16.48.0/20); local addresses = vector(172.16.4.56, 172.16.47.254, 172.16.22.45, 172.16.1.1); - for (a in addresses) + + for ( a in addresses ) { - for (s in subnets) + for ( s in subnets ) { - if (addresses[a] in subnets[s]) - { + if ( addresses[a] in subnets[s] ) print fmt("%s belongs to subnet %s", addresses[a], subnets[s]); - } } } } - - - diff --git a/testing/btest/doc/manual/data_type_time.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest similarity index 66% rename from testing/btest/doc/manual/data_type_time.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest index 45bff4479e..960d4ac9bd 100644 --- a/testing/btest/doc/manual/data_type_time.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest @@ -1,7 +1,8 @@ -# @TEST-EXEC: bro -b -r $TRACES/wikipedia.trace %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_time.bro event connection_established(c: connection) - { + { print fmt("%s: New connection established from %s to %s\n", strftime("%Y/%M/%d %H:%m:%S", network_time()), c$id$orig_h, c$id$resp_h); - } \ No newline at end of file + } diff --git a/testing/btest/doc/manual/framework_logging_factorial_01.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest similarity index 73% rename from testing/btest/doc/manual/framework_logging_factorial_01.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest index 961ee584bc..7a18c86509 100644 --- a/testing/btest/doc/manual/framework_logging_factorial_01.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest @@ -1,27 +1,23 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- framework_logging_factorial_01.bro module Factor; function factorial(n: count): count { if ( n == 0 ) - { return 1; - } else - { return ( n * factorial(n - 1) ); - } } event bro_init() { local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + for ( n in numbers ) - { print fmt("%d", factorial(numbers[n])); - } } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest new file mode 100644 index 0000000000..6966f7ea3c --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest @@ -0,0 +1,36 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_logging_factorial_02.bro + +module Factor; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + num: count &log; + factorial_num: count &log; + }; + } + +function factorial(n: count): count + { + if ( n == 0 ) + return 1; + + else + return ( n * factorial(n - 1) ); + } + +event bro_init() + { + Log::create_stream(LOG, [$columns=Info]); + } + +event bro_done() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + for ( n in numbers ) + Log::write( Factor::LOG, [$num=numbers[n], + $factorial_num=factorial(numbers[n])]); + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest new file mode 100644 index 0000000000..c3c16f8d6a --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest @@ -0,0 +1,12 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_logging_factorial_03.bro + +event bro_init() + { + Log::create_stream(LOG, [$columns=Info]); + + local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; + Log::add_filter(Factor::LOG, filter); + Log::remove_filter(Factor::LOG, "default"); + } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest new file mode 100644 index 0000000000..dbedb8e689 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest @@ -0,0 +1,54 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_logging_factorial_04.bro + +module Factor; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + num: count &log; + factorial_num: count &log; + }; + + global log_factor: event(rec: Info); + } + +function factorial(n: count): count + { + if ( n == 0 ) + return 1; + + else + return (n * factorial(n - 1)); + } + +event bro_init() + { + Log::create_stream(LOG, [$columns=Info, $ev=log_factor]); + } + +event bro_done() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + for ( n in numbers ) + Log::write( Factor::LOG, [$num=numbers[n], + $factorial_num=factorial(numbers[n])]); + } + +function mod5(id: Log::ID, path: string, rec: Factor::Info) : string + { + if ( rec$factorial_num % 5 == 0 ) + return "factor-mod5"; + + else + return "factor-non5"; + } + +event bro_init() + { + local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; + Log::add_filter(Factor::LOG, filter); + Log::remove_filter(Factor::LOG, "default"); + } diff --git a/testing/btest/doc/manual/framework_notice_hook_01.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest similarity index 71% rename from testing/btest/doc/manual/framework_notice_hook_01.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest index 3ec0bbff02..70f8c70247 100644 --- a/testing/btest/doc/manual/framework_notice_hook_01.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest @@ -1,12 +1,11 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- framework_notice_hook_01.bro @load policy/protocols/ssh/interesting-hostnames.bro hook Notice::policy(n: Notice::Info) { if ( n$note == SSH::Interesting_Hostname_Login ) - { add n$actions[Notice::ACTION_EMAIL]; - } - } \ No newline at end of file + } diff --git a/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest similarity index 69% rename from testing/btest/doc/manual/framework_notice_hook_suppression_01.bro rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest index 3d948f65b5..522bef5930 100644 --- a/testing/btest/doc/manual/framework_notice_hook_suppression_01.bro +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest @@ -1,12 +1,11 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff %INPUT + +-- framework_notice_hook_suppression_01.bro @load policy/protocols/ssl/expiring-certs.bro hook Notice::policy(n: Notice::Info) { if ( n$note == SSL::Certificate_Expires_Soon ) - { n$suppress_for = 12hrs; - } } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest new file mode 100644 index 0000000000..95eed5f501 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest @@ -0,0 +1,12 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_notice_shortcuts_01.bro + +@load policy/protocols/ssh/interesting-hostnames.bro +@load base/protocols/ssh/ + +redef Notice::emailed_types += { + SSH::Interesting_Hostname_Login, + SSH::Login +}; + diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest new file mode 100644 index 0000000000..8c12558d42 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_notice_shortcuts_02.bro + +@load policy/protocols/ssh/interesting-hostnames.bro +@load base/protocols/ssh/ + +redef Notice::type_suppression_intervals += { + [SSH::Interesting_Hostname_Login] = 1day, + [SSH::Login] = 12hrs, +}; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest new file mode 100644 index 0000000000..088d5d2368 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest @@ -0,0 +1,25 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- event.bif.bro + +## script-level cleanup that needs to be performed for every connection. This +## event is generated not only for TCP sessions but also for UDP and ICMP +## flows. +## +## +global connection_external: event(c: connection , tag: string ); + + +## Generated when a UDP session for a supported protocol has finished. Some of +## Bro's application-layer UDP analyzers flag the end of a session by raising +## Generated when a connection is seen that is marked as being expected. + + +global ipv6_ext_headers: event(c: connection , p: pkt_hdr ); +## their specifics differ slightly. Often, however, both will be raised for +## the same connection if some of its data is missing. We should eventually +## merge the two. +global ack_above_hole: event(c: connection ); + + +## diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest new file mode 100644 index 0000000000..c8e7eaab20 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest @@ -0,0 +1,30 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- Bro_DNS.events.bif.bro + +## Generated for DNS requests. For requests with multiple queries, this event +## is raised once for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## query: The queried name. +## +## qtype: The queried resource record type. +## +## qclass: The queried resource record class. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +global dns_request: event(c: connection , msg: dns_msg , query: string , qtype: count , qclass: count ); diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest new file mode 100644 index 0000000000..7d23c68ae4 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest @@ -0,0 +1,7 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- init-bare.bro + +type string_array: table[count] of string; +type string_set: set[string]; +type addr_set: set[addr]; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest new file mode 100644 index 0000000000..dc18745d57 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest @@ -0,0 +1,28 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- main.bro + +module Conn; + +export { + ## The record type which contains column fields of the connection log. + type Info: record { + ts: time &log; + uid: string &log; + id: conn_id &log; + proto: transport_proto &log; + service: string &log &optional; + duration: interval &log &optional; + orig_bytes: count &log &optional; + resp_bytes: count &log &optional; + conn_state: string &log &optional; + local_orig: bool &log &optional; + missed_bytes: count &log &default=0; + history: string &log &optional; + orig_pkts: count &log &optional; + orig_ip_bytes: count &log &optional; + resp_pkts: count &log &optional; + resp_ip_bytes: count &log &optional; + tunnel_parents: set[string] &log; + }; +} diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest new file mode 100644 index 0000000000..abe74112bd --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest @@ -0,0 +1,10 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- main.bro + +module HTTP; + +export { + ## This setting changes if passwords used in Basic-Auth are captured or not. + const default_capture_password = F &redef; +} diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest new file mode 100644 index 0000000000..b73140fe8e --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest @@ -0,0 +1,61 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- detect-MHR.bro + +##! Detect file downloads that have hash values matching files in Team +##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). + +@load base/frameworks/files +@load base/frameworks/notice +@load frameworks/files/hash-all-files + +module TeamCymruMalwareHashRegistry; + +export { + redef enum Notice::Type += { + ## The hash value of a file transferred over HTTP matched in the + ## malware hash registry. + Match + }; + + ## File types to attempt matching against the Malware Hash Registry. + const match_file_types = /application\/x-dosexec/ | + /application\/vnd.ms-cab-compressed/ | + /application\/pdf/ | + /application\/x-shockwave-flash/ | + /application\/x-java-applet/ | + /application\/jar/ | + /video\/mp4/ &redef; + + ## The malware hash registry runs each malware sample through several A/V engines. + ## Team Cymru returns a percentage to indicate how many A/V engines flagged the + ## sample as malicious. This threshold allows you to require a minimum detection + ## rate. + const notice_threshold = 10 &redef; +} + +event file_hash(f: fa_file, kind: string, hash: string) + { + if ( kind=="sha1" && match_file_types in f$mime_type ) + { + local hash_domain = fmt("%s.malware.hash.cymru.com", hash); + when ( local MHR_result = lookup_hostname_txt(hash_domain) ) + { + # Data is returned as " " + local MHR_answer = split1(MHR_result, / /); + if ( |MHR_answer| == 2 ) + { + local mhr_first_detected = double_to_time(to_double(MHR_answer[1])); + local mhr_detect_rate = to_count(MHR_answer[2]); + + local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected); + if ( mhr_detect_rate >= notice_threshold ) + { + local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected); + local virustotal_url = fmt("https://www.virustotal.com/en/file/%s/analysis/", hash); + NOTICE([$note=Match, $msg=message, $sub=virustotal_url, $f=f]); + } + } + } + } + } diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest new file mode 100644 index 0000000000..51044b36d9 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest @@ -0,0 +1,9 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- detect-MHR.bro + + +module TeamCymruMalwareHashRegistry; + +export { + redef enum Notice::Type += { diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest new file mode 100644 index 0000000000..37de8b6ff7 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest @@ -0,0 +1,17 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- detect-MHR.bro + + ## The hash value of a file transferred over HTTP matched in the + ## malware hash registry. + Match + }; + + ## File types to attempt matching against the Malware Hash Registry. + const match_file_types = /application\/x-dosexec/ | + /application\/vnd.ms-cab-compressed/ | + /application\/pdf/ | + /application\/x-shockwave-flash/ | + /application\/x-java-applet/ | + /application\/jar/ | + /video\/mp4/ &redef; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest new file mode 100644 index 0000000000..19e9d2ee54 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest @@ -0,0 +1,23 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- detect-MHR.bro + + ## The malware hash registry runs each malware sample through several A/V engines. + ## Team Cymru returns a percentage to indicate how many A/V engines flagged the + ## sample as malicious. This threshold allows you to require a minimum detection + ## rate. + const notice_threshold = 10 &redef; +} + +event file_hash(f: fa_file, kind: string, hash: string) + { + if ( kind=="sha1" && match_file_types in f$mime_type ) + { + local hash_domain = fmt("%s.malware.hash.cymru.com", hash); + when ( local MHR_result = lookup_hostname_txt(hash_domain) ) + { + # Data is returned as " " + local MHR_answer = split1(MHR_result, / /); + if ( |MHR_answer| == 2 ) + { + local mhr_first_detected = double_to_time(to_double(MHR_answer[1])); diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest new file mode 100644 index 0000000000..9b0c50c3f4 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest @@ -0,0 +1,9 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- known-hosts.bro + +module Known; + +export { + global known_hosts: set[addr] &create_expire=1day &synchronized &redef; +} diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest new file mode 100644 index 0000000000..73eec1a1b9 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest @@ -0,0 +1,50 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- interesting-hostnames.bro + +##! This script will generate a notice if an apparent SSH login originates +##! or heads to a host with a reverse hostname that looks suspicious. By +##! default, the regular expression to match "interesting" hostnames includes +##! names that are typically used for infrastructure hosts like nameservers, +##! mail servers, web servers and ftp servers. + +@load base/frameworks/notice + +module SSH; + +export { + redef enum Notice::Type += { + ## Generated if a login originates or responds with a host where the + ## reverse hostname lookup resolves to a name matched by the + ## :bro:id:`SSH::interesting_hostnames` regular expression. + Interesting_Hostname_Login, + }; + + ## Strange/bad host names to see successful SSH logins from or to. + const interesting_hostnames = + /^d?ns[0-9]*\./ | + /^smtp[0-9]*\./ | + /^mail[0-9]*\./ | + /^pop[0-9]*\./ | + /^imap[0-9]*\./ | + /^www[0-9]*\./ | + /^ftp[0-9]*\./ &redef; +} + +event SSH::heuristic_successful_login(c: connection) + { + for ( host in set(c$id$orig_h, c$id$resp_h) ) + { + when ( local hostname = lookup_addr(host) ) + { + if ( interesting_hostnames in hostname ) + { + NOTICE([$note=Interesting_Hostname_Login, + $msg=fmt("Possible SSH login involving a %s %s with an interesting hostname.", + Site::is_local_addr(host) ? "local" : "remote", + host == c$id$orig_h ? "client" : "server"), + $sub=hostname, $conn=c]); + } + } + } + } diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest new file mode 100644 index 0000000000..16e2552545 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest @@ -0,0 +1,8 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- expiring-certs.bro + + NOTICE([$note=Certificate_Expires_Soon, + $msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after), + $conn=c, $suppress_for=1day, + $identifier=cat(c$id$resp_h, c$id$resp_p, c$ssl$cert_hash)]); diff --git a/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst b/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst deleted file mode 100644 index 6b59bf64a2..0000000000 --- a/testing/btest/Baseline/doc.sphinx.test/btest-doc.sphinx.test.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. code-block:: none - - # bro -r wikipedia.trace - -.. code-block:: none - - # cat http.log | bro-cut ts id.orig_h | head -5 - 1300475168.843894 141.142.220.118 - 1300475168.975800 141.142.220.118 - 1300475168.976327 141.142.220.118 - 1300475168.979160 141.142.220.118 - 1300475169.012666 141.142.220.118 - diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 index 1512c0c8ef..8958f860f6 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 @@ -1,12 +1,18 @@ .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -r wikipedia.trace + +.. code-block:: guess + :linenos: - # bro -r wikipedia.trace && head -15 conn.log #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path conn - #open 2013-08-22-22-52-46 + #open 2013-08-30-23-20-51 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 1300475167.096535 UWkUyAuUGXf 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 73 0 0 (empty) @@ -16,4 +22,5 @@ 1300475168.854378 FrJExwHcSal 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF - 0 Dd 1 80 1 127 (empty) 1300475168.854837 5OKnoww6xl4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF - 0 Dd 1 66 1 211 (empty) 1300475168.857956 fRFu0wcOle6 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF - 0 Dd 1 66 1 117 (empty) + [...] diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 index 13ddfbb931..b455b9a8e8 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 @@ -1,4 +1,6 @@ .. code-block:: none + :linenos: + :emphasize-lines: 1,1 # cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration 141.142.220.202 5353 224.0.0.251 - diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 index 8a35312c44..8492053976 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 @@ -1,4 +1,6 @@ .. code-block:: none + :linenos: + :emphasize-lines: 1,1 # awk '/^[^#]/ {print $3, $4, $5, $6, $9}' conn.log 141.142.220.202 5353 224.0.0.251 5353 - diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 index f171bab392..8070ca3039 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 @@ -1,4 +1,6 @@ .. code-block:: none + :linenos: + :emphasize-lines: 1,1 # bro-cut -d ts uid host uri < http.log 2011-03-18T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 index 491930cbc1..7aa5ab7e5f 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 @@ -1,4 +1,6 @@ .. code-block:: none + :linenos: + :emphasize-lines: 1,1 # bro-cut -u ts uid host uri < http.log 2011-03-18T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 index a2b2316257..a3d261eca3 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 @@ -1,4 +1,6 @@ .. code-block:: none + :linenos: + :emphasize-lines: 1,1 # bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log 18-03-2011T19:06:08+0000 j4u32Pc5bif bits.wikimedia.org /skins-1.5/monobook/main.css diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 index bdbf0e20a0..5b991fd43b 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 @@ -1,4 +1,6 @@ .. code-block:: none + :linenos: + :emphasize-lines: 1,1 # cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5 VW0XPVINV8a 734 diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 index 67d0417de8..d5a53c234e 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 @@ -1,4 +1,6 @@ .. code-block:: none + :linenos: + :emphasize-lines: 1,1 # cat http.log | bro-cut uid id.resp_h method status_code host uri | grep VW0XPVINV8a VW0XPVINV8a 208.80.152.3 GET 304 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png diff --git a/testing/btest/btest.cfg b/testing/btest/btest.cfg index da0487f5ef..d53c2d8799 100644 --- a/testing/btest/btest.cfg +++ b/testing/btest/btest.cfg @@ -16,6 +16,7 @@ BTEST_PATH=%(testbase)s/../../aux/btest PATH=%(testbase)s/../../build/src:%(testbase)s/../scripts:%(testbase)s/../../aux/btest:%(testbase)s/../../aux/bro-aux/bro-cut:%(default_path)s:%(testbase)s/../../aux/btest/sphinx:%(default_path)s TRACES=%(testbase)s/Traces SCRIPTS=%(testbase)s/../scripts +DOC_ROOT=%(testbase)s/../../doc DIST=%(testbase)s/../.. BUILD=%(testbase)s/../../build TEST_DIFF_CANONIFIER=%(testbase)s/../scripts/diff-canonifier diff --git a/testing/btest/doc/manual/connection_record_01.bro b/testing/btest/doc/manual/connection_record_01.bro deleted file mode 100644 index ffd2f82dcc..0000000000 --- a/testing/btest/doc/manual/connection_record_01.bro +++ /dev/null @@ -1,9 +0,0 @@ -# @TEST-EXEC: bro -b -r $TRACES/dns-session.trace %INPUT -# @TEST-EXEC: btest-diff .stdout - -@load base/protocols/conn - -event connection_state_remove(c: connection) - { - print c; - } \ No newline at end of file diff --git a/testing/btest/doc/manual/data_struct_vector_iter.bro b/testing/btest/doc/manual/data_struct_vector_iter.bro deleted file mode 100644 index 96574eab1b..0000000000 --- a/testing/btest/doc/manual/data_struct_vector_iter.bro +++ /dev/null @@ -1,12 +0,0 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout - -event bro_init() - { - local addr_vector: vector of addr = vector( 1.2.3.4, 2.3.4.5, 3.4.5.6); - - for (i in addr_vector) - { - print mask_addr(addr_vector[i], 18); - } - } diff --git a/testing/btest/doc/sphinx/connection-record-01.btest b/testing/btest/doc/sphinx/connection-record-01.btest new file mode 100644 index 0000000000..b379fb4fbe --- /dev/null +++ b/testing/btest/doc/sphinx/connection-record-01.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${DOC_ROOT}/scripting/connection_record_01.bro diff --git a/testing/btest/doc/sphinx/connection-record-02.btest b/testing/btest/doc/sphinx/connection-record-02.btest new file mode 100644 index 0000000000..292503e12c --- /dev/null +++ b/testing/btest/doc/sphinx/connection-record-02.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/dns-session.trace ${DOC_ROOT}/scripting/connection_record_02.bro diff --git a/testing/btest/doc/sphinx/data_struct_record_01.btest b/testing/btest/doc/sphinx/data_struct_record_01.btest new file mode 100644 index 0000000000..ae52b9a24d --- /dev/null +++ b/testing/btest/doc/sphinx/data_struct_record_01.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_01.bro diff --git a/testing/btest/doc/sphinx/data_struct_record_02.btest b/testing/btest/doc/sphinx/data_struct_record_02.btest new file mode 100644 index 0000000000..d978224e3b --- /dev/null +++ b/testing/btest/doc/sphinx/data_struct_record_02.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_02.bro diff --git a/testing/btest/doc/sphinx/data_struct_set_declaration.btest b/testing/btest/doc/sphinx/data_struct_set_declaration.btest new file mode 100644 index 0000000000..2812479dff --- /dev/null +++ b/testing/btest/doc/sphinx/data_struct_set_declaration.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_set_declaration.bro diff --git a/testing/btest/doc/sphinx/data_struct_table_complex.btest b/testing/btest/doc/sphinx/data_struct_table_complex.btest new file mode 100644 index 0000000000..99117130f8 --- /dev/null +++ b/testing/btest/doc/sphinx/data_struct_table_complex.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_table_complex.bro diff --git a/testing/btest/doc/sphinx/data_struct_table_declaration.btest b/testing/btest/doc/sphinx/data_struct_table_declaration.btest new file mode 100644 index 0000000000..ac83e84e45 --- /dev/null +++ b/testing/btest/doc/sphinx/data_struct_table_declaration.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_table_declaration.bro diff --git a/testing/btest/doc/sphinx/data_struct_vector_declaration.btest b/testing/btest/doc/sphinx/data_struct_vector_declaration.btest new file mode 100644 index 0000000000..b017f84aed --- /dev/null +++ b/testing/btest/doc/sphinx/data_struct_vector_declaration.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_vector_declaration.bro diff --git a/testing/btest/doc/sphinx/data_struct_vector_iter.btest b/testing/btest/doc/sphinx/data_struct_vector_iter.btest new file mode 100644 index 0000000000..f5e6c2a0ba --- /dev/null +++ b/testing/btest/doc/sphinx/data_struct_vector_iter.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_vector_iter.bro diff --git a/testing/btest/doc/sphinx/data_type_const.bro.btest b/testing/btest/doc/sphinx/data_type_const.bro.btest new file mode 100644 index 0000000000..903fed3fbf --- /dev/null +++ b/testing/btest/doc/sphinx/data_type_const.bro.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_type_const.bro diff --git a/testing/btest/doc/sphinx/data_type_interval.btest b/testing/btest/doc/sphinx/data_type_interval.btest new file mode 100644 index 0000000000..0c1baa1372 --- /dev/null +++ b/testing/btest/doc/sphinx/data_type_interval.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_interval.bro diff --git a/testing/btest/doc/sphinx/data_type_pattern.btest b/testing/btest/doc/sphinx/data_type_pattern.btest new file mode 100644 index 0000000000..30ba3c6fe0 --- /dev/null +++ b/testing/btest/doc/sphinx/data_type_pattern.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_01.bro diff --git a/testing/btest/doc/sphinx/data_type_pattern_02.btest b/testing/btest/doc/sphinx/data_type_pattern_02.btest new file mode 100644 index 0000000000..b197cef792 --- /dev/null +++ b/testing/btest/doc/sphinx/data_type_pattern_02.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_02.bro diff --git a/testing/btest/doc/sphinx/data_type_subnets.btest b/testing/btest/doc/sphinx/data_type_subnets.btest new file mode 100644 index 0000000000..c78fe8c71c --- /dev/null +++ b/testing/btest/doc/sphinx/data_type_subnets.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_subnets.bro diff --git a/testing/btest/doc/sphinx/data_type_time.btest b/testing/btest/doc/sphinx/data_type_time.btest new file mode 100644 index 0000000000..29dee6002f --- /dev/null +++ b/testing/btest/doc/sphinx/data_type_time.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_time.bro diff --git a/testing/btest/doc/sphinx/framework_logging_factorial-2.btest b/testing/btest/doc/sphinx/framework_logging_factorial-2.btest new file mode 100644 index 0000000000..c0f1262217 --- /dev/null +++ b/testing/btest/doc/sphinx/framework_logging_factorial-2.btest @@ -0,0 +1,2 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_02.bro +@TEST-EXEC: btest-rst-include factor.log diff --git a/testing/btest/doc/sphinx/framework_logging_factorial-3.btest b/testing/btest/doc/sphinx/framework_logging_factorial-3.btest new file mode 100644 index 0000000000..75f2054661 --- /dev/null +++ b/testing/btest/doc/sphinx/framework_logging_factorial-3.btest @@ -0,0 +1,2 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_03.bro +@TEST-EXEC: btest-rst-include factor-mod5.log diff --git a/testing/btest/doc/sphinx/framework_logging_factorial.btest b/testing/btest/doc/sphinx/framework_logging_factorial.btest new file mode 100644 index 0000000000..798b821f87 --- /dev/null +++ b/testing/btest/doc/sphinx/framework_logging_factorial.btest @@ -0,0 +1 @@ +@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest new file mode 100644 index 0000000000..43a6ebc554 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- connection_record_02.bro + +@load base/protocols/conn +@load base/protocols/dns + +event connection_state_remove(c: connection) + { + print c; + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest new file mode 100644 index 0000000000..43a6ebc554 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- connection_record_02.bro + +@load base/protocols/conn +@load base/protocols/dns + +event connection_state_remove(c: connection) + { + print c; + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest new file mode 100644 index 0000000000..82f1b1f56c --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest @@ -0,0 +1,26 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_record_01.bro + +type Service: record { + name: string; + ports: set[port]; + rfc: count; +}; + +function print_service(serv: Service): string + { + print fmt("Service: %s(RFC%d)",serv$name, serv$rfc); + + for ( p in serv$ports ) + print fmt(" port: %s", p); + } + +event bro_init() + { + local dns: Service = [$name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; + local http: Service = [$name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; + + print_service(dns); + print_service(http); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest new file mode 100644 index 0000000000..05b5b9d50c --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest @@ -0,0 +1,45 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_record_02.bro + +type Service: record { + name: string; + ports: set[port]; + rfc: count; + }; + +type System: record { + name: string; + services: set[Service]; + }; + +function print_service(serv: Service): string + { + print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc); + + for ( p in serv$ports ) + print fmt(" port: %s", p); + } + +function print_system(sys: System): string + { + print fmt("System: %s", sys$name); + + for ( s in sys$services ) + print_service(s); + } + +event bro_init() + { + local server01: System; + server01$name = "morlock"; + add server01$services[[ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]]; + add server01$services[[ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]]; + print_system(server01); + + + # local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; + # local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; + # print_service(dns); + # print_service(http); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest new file mode 100644 index 0000000000..b659563ac3 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest @@ -0,0 +1,9 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_set_declaration.bro + +event bro_init() + { + local ssl_ports: set[port]; + local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp ); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest new file mode 100644 index 0000000000..5fa1f36475 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest @@ -0,0 +1,9 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_set_declaration.bro + + for ( i in ssl_ports ) + print fmt("SSL Port: %s", i); + + for ( i in non_ssl_ports ) + print fmt("Non-SSL Port: %s", i); diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest new file mode 100644 index 0000000000..48d33b52e5 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest @@ -0,0 +1,7 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_set_declaration.bro + + # Check for SMTPS + if ( 587/tcp !in ssl_ports ) + add ssl_ports[587/tcp]; diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest new file mode 100644 index 0000000000..19ddfe81d5 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest @@ -0,0 +1,26 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_set_declaration.bro + +event bro_init() + { + local ssl_ports: set[port]; + local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp ); + + # SSH + add ssl_ports[22/tcp]; + # HTTPS + add ssl_ports[443/tcp]; + # IMAPS + add ssl_ports[993/tcp]; + + # Check for SMTPS + if ( 587/tcp !in ssl_ports ) + add ssl_ports[587/tcp]; + + for ( i in ssl_ports ) + print fmt("SSL Port: %s", i); + + for ( i in non_ssl_ports ) + print fmt("Non-SSL Port: %s", i); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest new file mode 100644 index 0000000000..a6a1d7a63a --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest @@ -0,0 +1,17 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_table_complex.bro + +event bro_init() + { + local samurai_flicks: table[string, string, count, string] of string; + + samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru"; + samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin"; + samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri"; + samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei"; + + for ( [d, s, y, a] in samurai_flicks ) + print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a); + } + diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest new file mode 100644 index 0000000000..79fe7660ae --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest @@ -0,0 +1,17 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_table_declaration.bro + +event bro_init() + { + local ssl_services: table[string] of port; + + ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp); + ssl_services["IMAPS"] = 993/tcp; + + if ( "SMTPS" !in ssl_services ) + ssl_services["SMTPS"] = 587/tcp; + + for ( k in ssl_services ) + print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest new file mode 100644 index 0000000000..6b8a81a58f --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest @@ -0,0 +1,19 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_vector_declaration.bro + +event bro_init() + { + local v1: vector of count; + local v2 = vector(1, 2, 3, 4); + + v1[|v1|] = 1; + v1[|v1|] = 2; + v1[|v1|] = 3; + v1[|v1|] = 4; + + print fmt("contents of v1: %s", v1); + print fmt("length of v1: %d", |v1|); + print fmt("contents of v1: %s", v2); + print fmt("length of v2: %d", |v2|); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest new file mode 100644 index 0000000000..a28522fb64 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_struct_vector_iter.bro + +event bro_init() + { + local addr_vector: vector of addr = vector(1.2.3.4, 2.3.4.5, 3.4.5.6); + + for (i in addr_vector) + print mask_addr(addr_vector[i], 18); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest new file mode 100644 index 0000000000..a42efd2b72 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest @@ -0,0 +1,13 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_const.bro + +const port_list: table[port] of string &redef; + +redef port_list += { [6666/tcp] = "IRC"}; +redef port_list += { [80/tcp] = "WWW" }; + +event bro_init() + { + print port_list; + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest new file mode 100644 index 0000000000..914f9dc0ec --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest @@ -0,0 +1,8 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_const_simple.bro + +@load base/protocols/http + +redef HTTP::default_capture_password = T; + diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest new file mode 100644 index 0000000000..edd01615fc --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest @@ -0,0 +1,13 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_declaration.bro + +event bro_init() + { + local a: int; + a = 10; + local b = 10; + + if ( a == b ) + print fmt("A: %d, B: %d", a, b); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest new file mode 100644 index 0000000000..7954ed9ebe --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest @@ -0,0 +1,22 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_interval.bro + +# Store the time the previous connection was established. +global last_connection_time: time; + +# boolean value to indicate whether we have seen a previous connection. +global connection_seen: bool = F; + +event connection_established(c: connection) + { + local net_time: time = network_time(); + + print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h); + + if ( connection_seen ) + print fmt(" Time since last connection: %s", net_time - last_connection_time); + + last_connection_time = net_time; + connection_seen = T; + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest new file mode 100644 index 0000000000..850ffeb905 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest @@ -0,0 +1,15 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_local.bro + +function add_two(i: count): count + { + local added_two = i+2; + print fmt("i + 2 = %d", added_two); + return added_two; + } + +event bro_init() + { + local test = add_two(10); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest new file mode 100644 index 0000000000..475fcd676e --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest @@ -0,0 +1,17 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_pattern_01.bro + +event bro_init() + { + local test_string = "The quick brown fox jumped over the lazy dog."; + local test_pattern = /quick|lazy/; + + if ( test_pattern in test_string ) + { + local results = split(test_string, test_pattern); + print results[1]; + print results[2]; + print results[3]; + } + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest new file mode 100644 index 0000000000..915e8612be --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest @@ -0,0 +1,14 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_pattern_02.bro + +event bro_init() + { + local test_string = "equality"; + + local test_pattern = /equal/; + print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); + + test_pattern = /equality/; + print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest new file mode 100644 index 0000000000..d2edfd5e9a --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest @@ -0,0 +1,19 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_subnets.bro + +event bro_init() + { + local subnets = vector(172.16.0.0/20, 172.16.16.0/20, 172.16.32.0/20, 172.16.48.0/20); + local addresses = vector(172.16.4.56, 172.16.47.254, 172.16.22.45, 172.16.1.1); + + for ( a in addresses ) + { + for ( s in subnets ) + { + if ( addresses[a] in subnets[s] ) + print fmt("%s belongs to subnet %s", addresses[a], subnets[s]); + } + } + + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest new file mode 100644 index 0000000000..960d4ac9bd --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest @@ -0,0 +1,8 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- data_type_time.bro + +event connection_established(c: connection) + { + print fmt("%s: New connection established from %s to %s\n", strftime("%Y/%M/%d %H:%m:%S", network_time()), c$id$orig_h, c$id$resp_h); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest new file mode 100644 index 0000000000..7a18c86509 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest @@ -0,0 +1,23 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_logging_factorial_01.bro + +module Factor; + +function factorial(n: count): count + { + if ( n == 0 ) + return 1; + else + return ( n * factorial(n - 1) ); + } + +event bro_init() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + for ( n in numbers ) + print fmt("%d", factorial(numbers[n])); + } + + diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest new file mode 100644 index 0000000000..6966f7ea3c --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest @@ -0,0 +1,36 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_logging_factorial_02.bro + +module Factor; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + num: count &log; + factorial_num: count &log; + }; + } + +function factorial(n: count): count + { + if ( n == 0 ) + return 1; + + else + return ( n * factorial(n - 1) ); + } + +event bro_init() + { + Log::create_stream(LOG, [$columns=Info]); + } + +event bro_done() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + for ( n in numbers ) + Log::write( Factor::LOG, [$num=numbers[n], + $factorial_num=factorial(numbers[n])]); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest new file mode 100644 index 0000000000..c3c16f8d6a --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest @@ -0,0 +1,12 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_logging_factorial_03.bro + +event bro_init() + { + Log::create_stream(LOG, [$columns=Info]); + + local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; + Log::add_filter(Factor::LOG, filter); + Log::remove_filter(Factor::LOG, "default"); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest new file mode 100644 index 0000000000..dbedb8e689 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest @@ -0,0 +1,54 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_logging_factorial_04.bro + +module Factor; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + num: count &log; + factorial_num: count &log; + }; + + global log_factor: event(rec: Info); + } + +function factorial(n: count): count + { + if ( n == 0 ) + return 1; + + else + return (n * factorial(n - 1)); + } + +event bro_init() + { + Log::create_stream(LOG, [$columns=Info, $ev=log_factor]); + } + +event bro_done() + { + local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + for ( n in numbers ) + Log::write( Factor::LOG, [$num=numbers[n], + $factorial_num=factorial(numbers[n])]); + } + +function mod5(id: Log::ID, path: string, rec: Factor::Info) : string + { + if ( rec$factorial_num % 5 == 0 ) + return "factor-mod5"; + + else + return "factor-non5"; + } + +event bro_init() + { + local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; + Log::add_filter(Factor::LOG, filter); + Log::remove_filter(Factor::LOG, "default"); + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest new file mode 100644 index 0000000000..70f8c70247 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_notice_hook_01.bro + +@load policy/protocols/ssh/interesting-hostnames.bro + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSH::Interesting_Hostname_Login ) + add n$actions[Notice::ACTION_EMAIL]; + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest new file mode 100644 index 0000000000..522bef5930 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_notice_hook_suppression_01.bro + +@load policy/protocols/ssl/expiring-certs.bro + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSL::Certificate_Expires_Soon ) + n$suppress_for = 12hrs; + } diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest new file mode 100644 index 0000000000..95eed5f501 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest @@ -0,0 +1,12 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_notice_shortcuts_01.bro + +@load policy/protocols/ssh/interesting-hostnames.bro +@load base/protocols/ssh/ + +redef Notice::emailed_types += { + SSH::Interesting_Hostname_Login, + SSH::Login +}; + diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest new file mode 100644 index 0000000000..8c12558d42 --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest @@ -0,0 +1,11 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- framework_notice_shortcuts_02.bro + +@load policy/protocols/ssh/interesting-hostnames.bro +@load base/protocols/ssh/ + +redef Notice::type_suppression_intervals += { + [SSH::Interesting_Hostname_Login] = 1day, + [SSH::Login] = 12hrs, +}; diff --git a/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest new file mode 100644 index 0000000000..088d5d2368 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest @@ -0,0 +1,25 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- event.bif.bro + +## script-level cleanup that needs to be performed for every connection. This +## event is generated not only for TCP sessions but also for UDP and ICMP +## flows. +## +## +global connection_external: event(c: connection , tag: string ); + + +## Generated when a UDP session for a supported protocol has finished. Some of +## Bro's application-layer UDP analyzers flag the end of a session by raising +## Generated when a connection is seen that is marked as being expected. + + +global ipv6_ext_headers: event(c: connection , p: pkt_hdr ); +## their specifics differ slightly. Often, however, both will be raised for +## the same connection if some of its data is missing. We should eventually +## merge the two. +global ack_above_hole: event(c: connection ); + + +## diff --git a/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest new file mode 100644 index 0000000000..c8e7eaab20 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest @@ -0,0 +1,30 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- Bro_DNS.events.bif.bro + +## Generated for DNS requests. For requests with multiple queries, this event +## is raised once for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## query: The queried name. +## +## qtype: The queried resource record type. +## +## qclass: The queried resource record class. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +global dns_request: event(c: connection , msg: dns_msg , query: string , qtype: count , qclass: count ); diff --git a/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest new file mode 100644 index 0000000000..7d23c68ae4 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest @@ -0,0 +1,7 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- init-bare.bro + +type string_array: table[count] of string; +type string_set: set[string]; +type addr_set: set[addr]; diff --git a/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest new file mode 100644 index 0000000000..dc18745d57 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest @@ -0,0 +1,28 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- main.bro + +module Conn; + +export { + ## The record type which contains column fields of the connection log. + type Info: record { + ts: time &log; + uid: string &log; + id: conn_id &log; + proto: transport_proto &log; + service: string &log &optional; + duration: interval &log &optional; + orig_bytes: count &log &optional; + resp_bytes: count &log &optional; + conn_state: string &log &optional; + local_orig: bool &log &optional; + missed_bytes: count &log &default=0; + history: string &log &optional; + orig_pkts: count &log &optional; + orig_ip_bytes: count &log &optional; + resp_pkts: count &log &optional; + resp_ip_bytes: count &log &optional; + tunnel_parents: set[string] &log; + }; +} diff --git a/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest new file mode 100644 index 0000000000..abe74112bd --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest @@ -0,0 +1,10 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- main.bro + +module HTTP; + +export { + ## This setting changes if passwords used in Basic-Auth are captured or not. + const default_capture_password = F &redef; +} diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest new file mode 100644 index 0000000000..b73140fe8e --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest @@ -0,0 +1,61 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- detect-MHR.bro + +##! Detect file downloads that have hash values matching files in Team +##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). + +@load base/frameworks/files +@load base/frameworks/notice +@load frameworks/files/hash-all-files + +module TeamCymruMalwareHashRegistry; + +export { + redef enum Notice::Type += { + ## The hash value of a file transferred over HTTP matched in the + ## malware hash registry. + Match + }; + + ## File types to attempt matching against the Malware Hash Registry. + const match_file_types = /application\/x-dosexec/ | + /application\/vnd.ms-cab-compressed/ | + /application\/pdf/ | + /application\/x-shockwave-flash/ | + /application\/x-java-applet/ | + /application\/jar/ | + /video\/mp4/ &redef; + + ## The malware hash registry runs each malware sample through several A/V engines. + ## Team Cymru returns a percentage to indicate how many A/V engines flagged the + ## sample as malicious. This threshold allows you to require a minimum detection + ## rate. + const notice_threshold = 10 &redef; +} + +event file_hash(f: fa_file, kind: string, hash: string) + { + if ( kind=="sha1" && match_file_types in f$mime_type ) + { + local hash_domain = fmt("%s.malware.hash.cymru.com", hash); + when ( local MHR_result = lookup_hostname_txt(hash_domain) ) + { + # Data is returned as " " + local MHR_answer = split1(MHR_result, / /); + if ( |MHR_answer| == 2 ) + { + local mhr_first_detected = double_to_time(to_double(MHR_answer[1])); + local mhr_detect_rate = to_count(MHR_answer[2]); + + local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected); + if ( mhr_detect_rate >= notice_threshold ) + { + local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected); + local virustotal_url = fmt("https://www.virustotal.com/en/file/%s/analysis/", hash); + NOTICE([$note=Match, $msg=message, $sub=virustotal_url, $f=f]); + } + } + } + } + } diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest new file mode 100644 index 0000000000..51044b36d9 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest @@ -0,0 +1,9 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- detect-MHR.bro + + +module TeamCymruMalwareHashRegistry; + +export { + redef enum Notice::Type += { diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest new file mode 100644 index 0000000000..37de8b6ff7 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest @@ -0,0 +1,17 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- detect-MHR.bro + + ## The hash value of a file transferred over HTTP matched in the + ## malware hash registry. + Match + }; + + ## File types to attempt matching against the Malware Hash Registry. + const match_file_types = /application\/x-dosexec/ | + /application\/vnd.ms-cab-compressed/ | + /application\/pdf/ | + /application\/x-shockwave-flash/ | + /application\/x-java-applet/ | + /application\/jar/ | + /video\/mp4/ &redef; diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest new file mode 100644 index 0000000000..19e9d2ee54 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest @@ -0,0 +1,23 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- detect-MHR.bro + + ## The malware hash registry runs each malware sample through several A/V engines. + ## Team Cymru returns a percentage to indicate how many A/V engines flagged the + ## sample as malicious. This threshold allows you to require a minimum detection + ## rate. + const notice_threshold = 10 &redef; +} + +event file_hash(f: fa_file, kind: string, hash: string) + { + if ( kind=="sha1" && match_file_types in f$mime_type ) + { + local hash_domain = fmt("%s.malware.hash.cymru.com", hash); + when ( local MHR_result = lookup_hostname_txt(hash_domain) ) + { + # Data is returned as " " + local MHR_answer = split1(MHR_result, / /); + if ( |MHR_answer| == 2 ) + { + local mhr_first_detected = double_to_time(to_double(MHR_answer[1])); diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest new file mode 100644 index 0000000000..9b0c50c3f4 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest @@ -0,0 +1,9 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- known-hosts.bro + +module Known; + +export { + global known_hosts: set[addr] &create_expire=1day &synchronized &redef; +} diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest new file mode 100644 index 0000000000..73eec1a1b9 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest @@ -0,0 +1,50 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- interesting-hostnames.bro + +##! This script will generate a notice if an apparent SSH login originates +##! or heads to a host with a reverse hostname that looks suspicious. By +##! default, the regular expression to match "interesting" hostnames includes +##! names that are typically used for infrastructure hosts like nameservers, +##! mail servers, web servers and ftp servers. + +@load base/frameworks/notice + +module SSH; + +export { + redef enum Notice::Type += { + ## Generated if a login originates or responds with a host where the + ## reverse hostname lookup resolves to a name matched by the + ## :bro:id:`SSH::interesting_hostnames` regular expression. + Interesting_Hostname_Login, + }; + + ## Strange/bad host names to see successful SSH logins from or to. + const interesting_hostnames = + /^d?ns[0-9]*\./ | + /^smtp[0-9]*\./ | + /^mail[0-9]*\./ | + /^pop[0-9]*\./ | + /^imap[0-9]*\./ | + /^www[0-9]*\./ | + /^ftp[0-9]*\./ &redef; +} + +event SSH::heuristic_successful_login(c: connection) + { + for ( host in set(c$id$orig_h, c$id$resp_h) ) + { + when ( local hostname = lookup_addr(host) ) + { + if ( interesting_hostnames in hostname ) + { + NOTICE([$note=Interesting_Hostname_Login, + $msg=fmt("Possible SSH login involving a %s %s with an interesting hostname.", + Site::is_local_addr(host) ? "local" : "remote", + host == c$id$orig_h ? "client" : "server"), + $sub=hostname, $conn=c]); + } + } + } + } diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest new file mode 100644 index 0000000000..16e2552545 --- /dev/null +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest @@ -0,0 +1,8 @@ +# @TEST-EXEC: btest-diff %INPUT + +-- expiring-certs.bro + + NOTICE([$note=Certificate_Expires_Soon, + $msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after), + $conn=c, $suppress_for=1day, + $identifier=cat(c$id$resp_h, c$id$resp_p, c$ssl$cert_hash)]); diff --git a/testing/btest/doc/sphinx/using_bro.btest b/testing/btest/doc/sphinx/using_bro.btest index 3551104043..233f415942 100644 --- a/testing/btest/doc/sphinx/using_bro.btest +++ b/testing/btest/doc/sphinx/using_bro.btest @@ -1 +1,2 @@ -@TEST-EXEC: btest-rst-cmd "bro -r $TRACES/wikipedia.trace && head -15 conn.log" +@TEST-EXEC: btest-rst-cmd bro -r $TRACES/wikipedia.trace +@TEST-EXEC: btest-rst-include -n 15 conn.log diff --git a/testing/scripts/rst-filter b/testing/scripts/rst-filter index b06d5efd5e..a62646508e 100755 --- a/testing/scripts/rst-filter +++ b/testing/scripts/rst-filter @@ -2,4 +2,5 @@ # # Filters the output of btest-rst-cmd. -sed "s#${TRACES}/\{0,1\}##g" +sed "s#${TRACES}/\{0,1\}##g" | \ +sed 's#/[^ ]*/doc/\([^/]*/\)*##g' From ef04ce809b39e769918d81e1de3f75b5b56b7aa1 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 31 Aug 2013 10:17:13 -0700 Subject: [PATCH 280/881] Fixing bug introduced during merging. --- src/probabilistic/HyperLogLog.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/probabilistic/HyperLogLog.cc b/src/probabilistic/HyperLogLog.cc index be7db65046..888d8273df 100644 --- a/src/probabilistic/HyperLogLog.cc +++ b/src/probabilistic/HyperLogLog.cc @@ -113,7 +113,7 @@ double CardinalityCounter::Size() answer = (alpha_m * m * m * answer); if ( answer <= 5.0 * (m/2) ) - return m * log((double)(m / V)); + return m * log(((double) m) / V); else if ( answer <= (pow(2, 64) / 30) ) return answer; From fb3ceae6d5ffc8ab037f5195df47ee8cd2f626db Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 31 Aug 2013 10:22:27 -0700 Subject: [PATCH 281/881] Renaming HyperLogLog->CardinalityCounter. For consistency with the class' name. --- src/probabilistic/CMakeLists.txt | 4 ++-- src/probabilistic/{HyperLogLog.cc => CardinalityCounter.cc} | 3 ++- src/probabilistic/{HyperLogLog.h => CardinalityCounter.h} | 4 ++-- .../{hyper-loglog.bif => cardinality-counter.bif} | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) rename src/probabilistic/{HyperLogLog.cc => CardinalityCounter.cc} (99%) rename src/probabilistic/{HyperLogLog.h => CardinalityCounter.h} (98%) rename src/probabilistic/{hyper-loglog.bif => cardinality-counter.bif} (98%) diff --git a/src/probabilistic/CMakeLists.txt b/src/probabilistic/CMakeLists.txt index 7d8b7c7803..b845ecc7a2 100644 --- a/src/probabilistic/CMakeLists.txt +++ b/src/probabilistic/CMakeLists.txt @@ -9,13 +9,13 @@ include_directories(BEFORE set(probabilistic_SRCS BitVector.cc BloomFilter.cc + CardinalityCounter.cc CounterVector.cc Hasher.cc - HyperLogLog.cc Topk.cc) bif_target(bloom-filter.bif) -bif_target(hyper-loglog.bif) +bif_target(cardinality-counter.bif) bif_target(top-k.bif) bro_add_subdir_library(probabilistic ${probabilistic_SRCS}) diff --git a/src/probabilistic/HyperLogLog.cc b/src/probabilistic/CardinalityCounter.cc similarity index 99% rename from src/probabilistic/HyperLogLog.cc rename to src/probabilistic/CardinalityCounter.cc index 888d8273df..5f6b60d0a7 100644 --- a/src/probabilistic/HyperLogLog.cc +++ b/src/probabilistic/CardinalityCounter.cc @@ -3,7 +3,8 @@ #include #include #include -#include "HyperLogLog.h" + +#include "CardinalityCounter.h" #include "Reporter.h" #include "Serializer.h" diff --git a/src/probabilistic/HyperLogLog.h b/src/probabilistic/CardinalityCounter.h similarity index 98% rename from src/probabilistic/HyperLogLog.h rename to src/probabilistic/CardinalityCounter.h index b30f8841a4..909de7a153 100644 --- a/src/probabilistic/HyperLogLog.h +++ b/src/probabilistic/CardinalityCounter.h @@ -1,7 +1,7 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef hyperloglog_h -#define hyperloglog_h +#ifndef PROBABILISTIC_CARDINALITYCOUNTER_H +#define PROBABILISTIC_CARDINALITYCOUNTER_H #include #include diff --git a/src/probabilistic/hyper-loglog.bif b/src/probabilistic/cardinality-counter.bif similarity index 98% rename from src/probabilistic/hyper-loglog.bif rename to src/probabilistic/cardinality-counter.bif index e23de3957e..28f886ff6c 100644 --- a/src/probabilistic/hyper-loglog.bif +++ b/src/probabilistic/cardinality-counter.bif @@ -6,7 +6,7 @@ %%{ -#include "probabilistic/HyperLogLog.h" +#include "probabilistic/CardinalityCounter.h" using namespace probabilistic; %%} From 295987c8d089e68dfbe651391fffa7e35dab2ed6 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 31 Aug 2013 10:23:00 -0700 Subject: [PATCH 282/881] Making the confidence configurable. --- .../sumstats/plugins/hll_unique.bro | 13 ++++-- src/OpaqueVal.cc | 2 +- src/probabilistic/CardinalityCounter.cc | 11 +++-- src/probabilistic/CardinalityCounter.h | 43 +++++++++---------- src/probabilistic/cardinality-counter.bif | 6 ++- testing/btest/bifs/hll_cardinality.bro | 8 ++-- testing/btest/core/leaks/hll_cluster.bro | 4 +- testing/btest/istate/hll.bro | 2 +- 8 files changed, 49 insertions(+), 40 deletions(-) diff --git a/scripts/base/frameworks/sumstats/plugins/hll_unique.bro b/scripts/base/frameworks/sumstats/plugins/hll_unique.bro index 56595ca434..1110e6e105 100644 --- a/scripts/base/frameworks/sumstats/plugins/hll_unique.bro +++ b/scripts/base/frameworks/sumstats/plugins/hll_unique.bro @@ -4,8 +4,11 @@ module SumStats; export { redef record Reducer += { - ## The threshold when we switch to hll + ## The error margin for HLL. hll_error_margin: double &default=0.01; + + ## The confidence for for HLL. + hll_confidence: double &default=0.95; }; redef enum Calculation += { @@ -26,8 +29,9 @@ redef record ResultVal += { # specialized bifs. card: opaque of cardinality &optional; - # We need this in the compose hook. + # We need these in the compose hook. hll_error_margin: double &optional; + hll_confidence: double &optional; }; hook register_observe_plugins() @@ -36,8 +40,9 @@ hook register_observe_plugins() { if ( ! rv?$card ) { - rv$card = hll_cardinality_init(r$hll_error_margin); + rv$card = hll_cardinality_init(r$hll_error_margin, r$hll_confidence); rv$hll_error_margin = r$hll_error_margin; + rv$hll_confidence = r$hll_confidence; rv$hll_unique = 0; } @@ -48,7 +53,7 @@ hook register_observe_plugins() hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { - local rhll = hll_cardinality_init(rv1$hll_error_margin); + local rhll = hll_cardinality_init(rv1$hll_error_margin, rv1$hll_confidence); hll_cardinality_merge_into(rhll, rv1$card); hll_cardinality_merge_into(rhll, rv2$card); diff --git a/src/OpaqueVal.cc b/src/OpaqueVal.cc index d9999c148b..b7ccd770ce 100644 --- a/src/OpaqueVal.cc +++ b/src/OpaqueVal.cc @@ -5,7 +5,7 @@ #include "Reporter.h" #include "Serializer.h" #include "probabilistic/BloomFilter.h" -#include "probabilistic/HyperLogLog.h" +#include "probabilistic/CardinalityCounter.h" bool HashVal::IsValid() const { diff --git a/src/probabilistic/CardinalityCounter.cc b/src/probabilistic/CardinalityCounter.cc index 5f6b60d0a7..91686bbb69 100644 --- a/src/probabilistic/CardinalityCounter.cc +++ b/src/probabilistic/CardinalityCounter.cc @@ -10,7 +10,7 @@ using namespace probabilistic; -int CardinalityCounter::OptimalB(double error) +int CardinalityCounter::OptimalB(double error, double confidence) { double initial_estimate = 2 * (log(1.04) - log(error)) / log(2); int answer = (int) floor(initial_estimate); @@ -20,7 +20,7 @@ int CardinalityCounter::OptimalB(double error) do { answer++; k = pow(2, (answer - initial_estimate) / 2); - } while ( erf(k / sqrt(2)) < HLL_CONF ); + } while ( erf(k / sqrt(2)) < confidence ); return answer; } @@ -30,6 +30,9 @@ void CardinalityCounter::Init(uint64 size) m = size; buckets = new uint8_t[m]; + // The following magic values are taken directly out of the + // description of the HyperLogLog algorithn. + if ( m == 16 ) alpha_m = 0.673; @@ -51,9 +54,9 @@ void CardinalityCounter::Init(uint64 size) V = m; } -CardinalityCounter::CardinalityCounter(double error_margin) +CardinalityCounter::CardinalityCounter(double error_margin, double confidence) { - int b = OptimalB(error_margin); + int b = OptimalB(error_margin, confidence); Init((uint64) pow(2, b)); } diff --git a/src/probabilistic/CardinalityCounter.h b/src/probabilistic/CardinalityCounter.h index 909de7a153..6e1c444d95 100644 --- a/src/probabilistic/CardinalityCounter.h +++ b/src/probabilistic/CardinalityCounter.h @@ -14,18 +14,24 @@ namespace probabilistic { class CardinalityCounter { public: /** - * Constructor. - * - * Based on the error_margin, the number of buckets that need to be - * kept will be determined. Based on the max_size, the number of bits - * that will be used from the hash function will be determined. - * - * We need the hash function to return integers that are uniformly - * distributed from 0 to 2^L-1. And if that happens, the maximum - * cardinality that this counter can handle is approximately 2^L. By - * default, we will assume a value of 64 bits. - */ - CardinalityCounter(double error_margin); + * Constructor. + * + * Based on the error_margin, the number of buckets that need to be + * kept will be determined. Based on the max_size, the number of bits + * that will be used from the hash function will be determined. + * + * We need the hash function to return integers that are uniformly + * distributed from 0 to 2^L-1. And if that happens, the maximum + * cardinality that this counter can handle is approximately 2^L. By + * default, we will assume a value of 64 bits. + * + * Confidence in the estimate given by a cardinality counter is. + * + * In other words, if the cardinality is estimated to be 100 with 2% + * error margin and HLL_CONFis 0.95, then we are 95% sure that the + * actual cardinality is between 98 and 102. + */ + CardinalityCounter(double error_margin, double confidence = 0.95); /** * Constructor used for cloning. @@ -117,8 +123,10 @@ private: * * k is the number of standard deviations that we have to go to have * a confidence level of conf. + * + * confidence: TODO. */ - int OptimalB(double error); + int OptimalB(double error, double confidence); /** * Computes when the first one appears in the element. It looks at the @@ -128,15 +136,6 @@ private: */ uint8_t Rank(uint64 hash_modified); - /** - * Confidence in the estimate given by a cardinality counter is. - * - * In other words, if the cardinality is estimated to be 100 with 2% - * error margin and HLL_CONFis 0.95, then we are 95% sure that the - * actual cardinality is between 98 and 102. - */ - static const double HLL_CONF = .95; - /** * This is the number of buckets that will be stored. The standard * error is 1.04/sqrt(m), so the actual cardinality will be the diff --git a/src/probabilistic/cardinality-counter.bif b/src/probabilistic/cardinality-counter.bif index 28f886ff6c..1ec07529dc 100644 --- a/src/probabilistic/cardinality-counter.bif +++ b/src/probabilistic/cardinality-counter.bif @@ -16,14 +16,16 @@ module GLOBAL; ## Initializes a probabilistic cardinality counter that uses the HyperLogLog algorithm. ## ## err: the desired error rate (e.g. 0.01). +## +## confidence: the desirec confidence for the error rate (e.g., 0.95). ## ## Returns: a HLL cardinality handle. ## ## .. bro:see:: hll_cardinality_estimate hll_cardinality_merge_into hll_cardinality_add ## hll_cardinality_copy -function hll_cardinality_init%(err: double%): opaque of cardinality +function hll_cardinality_init%(err: double, confidence: double%): opaque of cardinality %{ - CardinalityCounter* c = new CardinalityCounter(err); + CardinalityCounter* c = new CardinalityCounter(err, confidence); CardinalityVal* cv = new CardinalityVal(c); return cv; diff --git a/testing/btest/bifs/hll_cardinality.bro b/testing/btest/bifs/hll_cardinality.bro index 96371d268f..d1b0807416 100644 --- a/testing/btest/bifs/hll_cardinality.bro +++ b/testing/btest/bifs/hll_cardinality.bro @@ -5,8 +5,8 @@ event bro_init() { - local c1 = hll_cardinality_init(0.01); - local c2 = hll_cardinality_init(0.01); + local c1 = hll_cardinality_init(0.01, 0.95); + local c2 = hll_cardinality_init(0.01, 0.95); local add1 = 2001; local add2 = 2002; @@ -46,7 +46,7 @@ event bro_init() print "This value should be about 12:"; print hll_cardinality_estimate(c2); - local m2 = hll_cardinality_init(0.02); + local m2 = hll_cardinality_init(0.02, 0.95); print "This value should be around 0:"; print hll_cardinality_estimate(m2); @@ -56,7 +56,7 @@ event bro_init() print "This value should be around 13:"; print hll_cardinality_estimate(c3); - c3 = hll_cardinality_init(0.01); + c3 = hll_cardinality_init(0.01, 0.95); print "This value should be 0:"; print hll_cardinality_estimate(c3); diff --git a/testing/btest/core/leaks/hll_cluster.bro b/testing/btest/core/leaks/hll_cluster.bro index 0e342325c3..65fe8da447 100644 --- a/testing/btest/core/leaks/hll_cluster.bro +++ b/testing/btest/core/leaks/hll_cluster.bro @@ -36,7 +36,7 @@ global runnumber: count &redef; # differentiate runs event remote_connection_handshake_done(p: event_peer) { - local c = hll_cardinality_init(0.01); + local c = hll_cardinality_init(0.01, 0.95); local add1 = 2001; local add2 = 2002; @@ -92,7 +92,7 @@ global hll: opaque of cardinality; event bro_init() { - hll = hll_cardinality_init(0.01); + hll = hll_cardinality_init(0.01, 0.95); } event hll_data(data: opaque of cardinality) diff --git a/testing/btest/istate/hll.bro b/testing/btest/istate/hll.bro index 1dfca6c30f..511a892644 100644 --- a/testing/btest/istate/hll.bro +++ b/testing/btest/istate/hll.bro @@ -13,7 +13,7 @@ event bro_init() if ( runnumber == 1 ) { - card = hll_cardinality_init(0.01); + card = hll_cardinality_init(0.01, 0.95); hll_cardinality_add(card, "a"); hll_cardinality_add(card, "b"); From 41cab5e0dd7f37251c766a2bd107651fbc29862c Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 31 Aug 2013 10:47:19 -0700 Subject: [PATCH 283/881] Updating tests. --- .../canonified_loaded_scripts.log | 7 ++++--- .../canonified_loaded_scripts.log | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index 2cc2140a28..5ee8158ddf 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-08-14-01-19-27 +#open 2013-08-31-17-46-55 #fields name #types string scripts/base/init-bare.bro @@ -12,7 +12,6 @@ scripts/base/init-bare.bro build/scripts/base/bif/strings.bif.bro build/scripts/base/bif/bro.bif.bro build/scripts/base/bif/reporter.bif.bro - build/scripts/base/bif/bloom-filter.bif.bro build/scripts/base/bif/event.bif.bro build/scripts/base/bif/plugins/__load__.bro build/scripts/base/bif/plugins/Bro_ARP.events.bif.bro @@ -96,7 +95,9 @@ scripts/base/init-bare.bro scripts/base/utils/site.bro scripts/base/utils/patterns.bro build/scripts/base/bif/__load__.bro + build/scripts/base/bif/bloom-filter.bif.bro + build/scripts/base/bif/cardinality-counter.bif.bro build/scripts/base/bif/top-k.bif.bro scripts/policy/misc/loaded-scripts.bro scripts/base/utils/paths.bro -#close 2013-08-14-01-19-27 +#close 2013-08-31-17-46-55 diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index 1997857721..a11933c79a 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-08-14-01-19-28 +#open 2013-08-31-17-46-56 #fields name #types string scripts/base/init-bare.bro @@ -12,7 +12,6 @@ scripts/base/init-bare.bro build/scripts/base/bif/strings.bif.bro build/scripts/base/bif/bro.bif.bro build/scripts/base/bif/reporter.bif.bro - build/scripts/base/bif/bloom-filter.bif.bro build/scripts/base/bif/event.bif.bro build/scripts/base/bif/plugins/__load__.bro build/scripts/base/bif/plugins/Bro_ARP.events.bif.bro @@ -96,6 +95,8 @@ scripts/base/init-bare.bro scripts/base/utils/site.bro scripts/base/utils/patterns.bro build/scripts/base/bif/__load__.bro + build/scripts/base/bif/bloom-filter.bif.bro + build/scripts/base/bif/cardinality-counter.bif.bro build/scripts/base/bif/top-k.bif.bro scripts/base/init-default.bro scripts/base/utils/active-http.bro @@ -146,6 +147,7 @@ scripts/base/init-default.bro scripts/base/frameworks/sumstats/main.bro scripts/base/frameworks/sumstats/plugins/__load__.bro scripts/base/frameworks/sumstats/plugins/average.bro + scripts/base/frameworks/sumstats/plugins/hll_unique.bro scripts/base/frameworks/sumstats/plugins/last.bro scripts/base/frameworks/sumstats/plugins/max.bro scripts/base/frameworks/sumstats/plugins/min.bro @@ -218,4 +220,4 @@ scripts/base/init-default.bro scripts/base/files/unified2/main.bro scripts/base/misc/find-checksum-offloading.bro scripts/policy/misc/loaded-scripts.bro -#close 2013-08-14-01-19-28 +#close 2013-08-31-17-46-56 From a8ac7d8a5b1b59d403a8d1d4b8cd5d53fe4089e3 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 31 Aug 2013 10:52:24 -0700 Subject: [PATCH 284/881] Updating tests for HLL merge. --- doc/scripts/DocSourcesList.cmake | 2 ++ .../{.stdout => output} | 10 +++++----- .../scripts/base/frameworks/sumstats/basic-cluster.bro | 2 +- .../btest/scripts/base/frameworks/sumstats/basic.bro | 2 +- .../scripts/base/frameworks/sumstats/thresholding.bro | 4 ++-- 5 files changed, 11 insertions(+), 9 deletions(-) rename testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/{.stdout => output} (100%) diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index cf82618377..0b67ab1995 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -19,6 +19,7 @@ rest_target(${psd} base/init-bare.bro internal) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/analyzer.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/bloom-filter.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/bro.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/cardinality-counter.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/const.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/event.bif.bro) rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/file_analysis.bif.bro) @@ -130,6 +131,7 @@ rest_target(${psd} base/frameworks/sumstats/cluster.bro) rest_target(${psd} base/frameworks/sumstats/main.bro) rest_target(${psd} base/frameworks/sumstats/non-cluster.bro) rest_target(${psd} base/frameworks/sumstats/plugins/average.bro) +rest_target(${psd} base/frameworks/sumstats/plugins/hll_unique.bro) rest_target(${psd} base/frameworks/sumstats/plugins/last.bro) rest_target(${psd} base/frameworks/sumstats/plugins/max.bro) rest_target(${psd} base/frameworks/sumstats/plugins/min.bro) diff --git a/testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/.stdout b/testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/output similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/.stdout rename to testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/output index 3afedd785d..d4ff3b7698 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/.stdout +++ b/testing/btest/Baseline/scripts.base.frameworks.sumstats.thresholding/output @@ -1,6 +1,6 @@ -THRESHOLD_SERIES: hit a threshold series value at 3 for sumstats_key(host=1.2.3.4) -THRESHOLD: hit a threshold value at 6 for sumstats_key(host=1.2.3.4) -THRESHOLD_SERIES: hit a threshold series value at 6 for sumstats_key(host=1.2.3.4) -THRESHOLD: hit a threshold value at 1001 for sumstats_key(host=7.2.1.5) -THRESHOLD_SERIES: hit a threshold series value at 1001 for sumstats_key(host=7.2.1.5) THRESHOLD WITH RATIO BETWEEN REDUCERS: hit a threshold value at 55x for sumstats_key(host=7.2.1.5) +THRESHOLD: hit a threshold value at 1001 for sumstats_key(host=7.2.1.5) +THRESHOLD: hit a threshold value at 6 for sumstats_key(host=1.2.3.4) +THRESHOLD_SERIES: hit a threshold series value at 1001 for sumstats_key(host=7.2.1.5) +THRESHOLD_SERIES: hit a threshold series value at 3 for sumstats_key(host=1.2.3.4) +THRESHOLD_SERIES: hit a threshold series value at 6 for sumstats_key(host=1.2.3.4) diff --git a/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro b/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro index e83096919a..d2fd592855 100644 --- a/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro +++ b/testing/btest/scripts/base/frameworks/sumstats/basic-cluster.bro @@ -29,7 +29,7 @@ event bro_init() &priority=5 $epoch_result(ts: time, key: SumStats::Key, result: SumStats::Result) = { local r = result["test"]; - print fmt("Host: %s - num:%d - sum:%.1f - avg:%.1f - max:%.1f - min:%.1f - var:%.1f - std_dev:%.1f - unique:%d - hllunique:%d", key$host, r$num, r$sum, r$average, r$max, r$min, r$variance, r$std_dev, r$unique, r$hllunique); + print fmt("Host: %s - num:%d - sum:%.1f - avg:%.1f - max:%.1f - min:%.1f - var:%.1f - std_dev:%.1f - unique:%d - hllunique:%d", key$host, r$num, r$sum, r$average, r$max, r$min, r$variance, r$std_dev, r$unique, r$hll_unique); }, $epoch_finished(ts: time) = { diff --git a/testing/btest/scripts/base/frameworks/sumstats/basic.bro b/testing/btest/scripts/base/frameworks/sumstats/basic.bro index d8738b71b7..fb1254baca 100644 --- a/testing/btest/scripts/base/frameworks/sumstats/basic.bro +++ b/testing/btest/scripts/base/frameworks/sumstats/basic.bro @@ -18,7 +18,7 @@ event bro_init() &priority=5 $epoch_result(ts: time, key: SumStats::Key, result: SumStats::Result) = { local r = result["test.metric"]; - print fmt("Host: %s - num:%d - sum:%.1f - var:%.1f - avg:%.1f - max:%.1f - min:%.1f - std_dev:%.1f - unique:%d - hllunique:%d", key$host, r$num, r$sum, r$variance, r$average, r$max, r$min, r$std_dev, r$unique, r$hllunique); + print fmt("Host: %s - num:%d - sum:%.1f - var:%.1f - avg:%.1f - max:%.1f - min:%.1f - std_dev:%.1f - unique:%d - hllunique:%d", key$host, r$num, r$sum, r$variance, r$average, r$max, r$min, r$std_dev, r$unique, r$hll_unique); } ]); diff --git a/testing/btest/scripts/base/frameworks/sumstats/thresholding.bro b/testing/btest/scripts/base/frameworks/sumstats/thresholding.bro index b00b30a375..b7bb826446 100644 --- a/testing/btest/scripts/base/frameworks/sumstats/thresholding.bro +++ b/testing/btest/scripts/base/frameworks/sumstats/thresholding.bro @@ -1,5 +1,5 @@ -# @TEST-EXEC: bro %INPUT -# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: bro %INPUT | sort >output +# @TEST-EXEC: btest-diff output redef enum Notice::Type += { Test_Notice, From de5bb65ff7ec05080c66df17c102d96c6dfd79e0 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 31 Aug 2013 11:03:40 -0700 Subject: [PATCH 285/881] Removing the "uint8*" methods from SerializationFormat. They conflict with the "char" version, so that other classes would now pick the wrong one. Added a bit of casting to HLL to use the "char" versions instead. --- src/SerializationFormat.cc | 28 ------------------------- src/SerializationFormat.h | 6 ------ src/Serializer.h | 1 - src/probabilistic/CardinalityCounter.cc | 7 ++++--- 4 files changed, 4 insertions(+), 38 deletions(-) diff --git a/src/SerializationFormat.cc b/src/SerializationFormat.cc index a005a103cf..10dd4f29ea 100644 --- a/src/SerializationFormat.cc +++ b/src/SerializationFormat.cc @@ -107,15 +107,6 @@ bool BinarySerializationFormat::Read(int* v, const char* tag) return true; } -bool BinarySerializationFormat::Read(uint8* v, const char* tag) - { - if ( ! ReadData(v, sizeof(*v)) ) - return false; - - DBG_LOG(DBG_SERIAL, "Read uint8 %hu [%s]", *v, tag); - return true; - } - bool BinarySerializationFormat::Read(uint16* v, const char* tag) { if ( ! ReadData(v, sizeof(*v)) ) @@ -310,12 +301,6 @@ bool BinarySerializationFormat::Write(char v, const char* tag) return WriteData(&v, 1); } -bool BinarySerializationFormat::Write(uint8 v, const char* tag) - { - DBG_LOG(DBG_SERIAL, "Write uint8 %hu [%s]", v, tag); - return WriteData(&v, sizeof(v)); - } - bool BinarySerializationFormat::Write(uint16 v, const char* tag) { DBG_LOG(DBG_SERIAL, "Write uint16 %hu [%s]", v, tag); @@ -462,12 +447,6 @@ bool XMLSerializationFormat::Read(int* v, const char* tag) return false; } -bool XMLSerializationFormat::Read(uint8* v, const char* tag) - { - reporter->InternalError("no reading of xml"); - return false; - } - bool XMLSerializationFormat::Read(uint16* v, const char* tag) { reporter->InternalError("no reading of xml"); @@ -551,13 +530,6 @@ bool XMLSerializationFormat::Write(char v, const char* tag) return WriteElem(tag, "char", &v, 1); } -bool XMLSerializationFormat::Write(uint8 v, const char* tag) - { - const char* tmp = fmt("%" PRIu8, v); - return WriteElem(tag, "uint8", tmp, strlen(tmp)); - } - - bool XMLSerializationFormat::Write(uint16 v, const char* tag) { const char* tmp = fmt("%" PRIu16, v); diff --git a/src/SerializationFormat.h b/src/SerializationFormat.h index 05cf56d961..f270b61bae 100644 --- a/src/SerializationFormat.h +++ b/src/SerializationFormat.h @@ -23,7 +23,6 @@ public: virtual void EndRead(); virtual bool Read(int* v, const char* tag) = 0; - virtual bool Read(uint8* v, const char* tag) = 0; virtual bool Read(uint16* v, const char* tag) = 0; virtual bool Read(uint32* v, const char* tag) = 0; virtual bool Read(int64* v, const char* tag) = 0; @@ -48,7 +47,6 @@ public: virtual uint32 EndWrite(char** data); // passes ownership virtual bool Write(int v, const char* tag) = 0; - virtual bool Write(uint8 v, const char* tag) = 0; virtual bool Write(uint16 v, const char* tag) = 0; virtual bool Write(uint32 v, const char* tag) = 0; virtual bool Write(int64 v, const char* tag) = 0; @@ -94,7 +92,6 @@ public: virtual ~BinarySerializationFormat(); virtual bool Read(int* v, const char* tag); - virtual bool Read(uint8* v, const char* tag); virtual bool Read(uint16* v, const char* tag); virtual bool Read(uint32* v, const char* tag); virtual bool Read(int64* v, const char* tag); @@ -109,7 +106,6 @@ public: virtual bool Read(struct in_addr* addr, const char* tag); virtual bool Read(struct in6_addr* addr, const char* tag); virtual bool Write(int v, const char* tag); - virtual bool Write(uint8 v, const char* tag); virtual bool Write(uint16 v, const char* tag); virtual bool Write(uint32 v, const char* tag); virtual bool Write(int64 v, const char* tag); @@ -136,7 +132,6 @@ public: // We don't write anything if tag is nil. virtual bool Write(int v, const char* tag); - virtual bool Write(uint8 v, const char* tag); virtual bool Write(uint16 v, const char* tag); virtual bool Write(uint32 v, const char* tag); virtual bool Write(int64 v, const char* tag); @@ -157,7 +152,6 @@ public: // Not implemented. virtual bool Read(int* v, const char* tag); - virtual bool Read(uint8* v, const char* tag); virtual bool Read(uint16* v, const char* tag); virtual bool Read(uint32* v, const char* tag); virtual bool Read(int64* v, const char* tag); diff --git a/src/Serializer.h b/src/Serializer.h index 719d4dc527..72e0723880 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -54,7 +54,6 @@ public: DECLARE_WRITE(type) DECLARE_IO(int) - DECLARE_IO(uint8) DECLARE_IO(uint16) DECLARE_IO(uint32) DECLARE_IO(int64) diff --git a/src/probabilistic/CardinalityCounter.cc b/src/probabilistic/CardinalityCounter.cc index 7a1814d6ae..b9e0744225 100644 --- a/src/probabilistic/CardinalityCounter.cc +++ b/src/probabilistic/CardinalityCounter.cc @@ -161,7 +161,7 @@ bool CardinalityCounter::Serialize(SerialInfo* info) const valid &= SERIALIZE(alpha_m); for ( unsigned int i = 0; i < m; i++ ) - valid &= SERIALIZE(buckets[i]); + valid &= SERIALIZE((char)buckets[i]); return valid; } @@ -183,8 +183,9 @@ CardinalityCounter* CardinalityCounter::Unserialize(UnserialInfo* info) for ( unsigned int i = 0; i < m; i++ ) { - uint8_t* currbucket = buckets + i; - valid &= UNSERIALIZE(currbucket); + char c; + valid &= UNSERIALIZE(&c); + buckets[i] = (uint8)c; } return valid ? c : 0; From bf9eb7c44f5b7aa75dc27eded34517b3e0a8ed00 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 31 Aug 2013 11:22:40 -0700 Subject: [PATCH 286/881] Updating submodule(s). [nomail] --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 738bcc72de..9726c5b982 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 738bcc72de0b0a9a4c3359de8328e9c48f3526ef +Subproject commit 9726c5b982ee0e3e730a15dcd65f49bdee3fe458 From 2392a29b7fe394a18dab4c0b545a5fb5428f9e09 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 31 Aug 2013 18:09:16 -0700 Subject: [PATCH 287/881] Redoing doc.sphinx baselines. --- aux/btest | 2 +- ...doc.sphinx.framework_logging_factorial-2#1 | 4 +- ...doc.sphinx.framework_logging_factorial-3#1 | 4 +- ..._connection_record_02_bro.btest => output} | 2 +- ...scripting_connection_record_02_bro@2.btest | 11 ---- ...scripting_connection_record_02_bro@2.btest | 11 ---- .../output} | 2 +- ..._scripting_data_struct_record_01_bro.btest | 26 -------- ...data_struct_record_01_bro.btest => output} | 2 +- ..._scripting_data_struct_record_02_bro.btest | 45 -------------- ...data_struct_record_02_bro.btest => output} | 2 +- ...ting_data_struct_set_declaration_bro.btest | 9 --- ...truct_set_declaration_bro.btest => output} | 2 +- ...ng_data_struct_set_declaration_bro@2.btest | 9 --- ...uct_set_declaration_bro@2.btest => output} | 2 +- ...ng_data_struct_set_declaration_bro@3.btest | 7 --- ...uct_set_declaration_bro@3.btest => output} | 2 +- ...ng_data_struct_set_declaration_bro@4.btest | 26 -------- ...uct_set_declaration_bro@4.btest => output} | 2 +- ...ipting_data_struct_table_complex_bro.btest | 17 ------ ..._struct_table_complex_bro.btest => output} | 2 +- ...ng_data_struct_table_declaration_bro.btest | 17 ------ ...uct_table_declaration_bro.btest => output} | 2 +- ...g_data_struct_vector_declaration_bro.btest | 19 ------ ...ct_vector_declaration_bro.btest => output} | 2 +- ...cripting_data_struct_vector_iter_bro.btest | 11 ---- ...ta_struct_vector_iter_bro.btest => output} | 2 +- ...de-doc_scripting_data_type_const_bro.btest | 13 ---- ...pting_data_type_const_bro.btest => output} | 2 +- ...scripting_data_type_const_simple_bro.btest | 8 --- ...ata_type_const_simple_bro.btest => output} | 2 +- ..._scripting_data_type_declaration_bro.btest | 13 ---- ...data_type_declaration_bro.btest => output} | 2 +- ...doc_scripting_data_type_interval_bro.btest | 22 ------- ...ng_data_type_interval_bro.btest => output} | 2 +- ...de-doc_scripting_data_type_local_bro.btest | 15 ----- ...pting_data_type_local_bro.btest => output} | 2 +- ...c_scripting_data_type_pattern_01_bro.btest | 17 ------ ..._data_type_pattern_01_bro.btest => output} | 2 +- ...c_scripting_data_type_pattern_02_bro.btest | 14 ----- ..._data_type_pattern_02_bro.btest => output} | 2 +- ...-doc_scripting_data_type_subnets_bro.btest | 19 ------ ...ing_data_type_subnets_bro.btest => output} | 2 +- ...ude-doc_scripting_data_type_time_bro.btest | 8 --- ...ipting_data_type_time_bro.btest => output} | 2 +- ...g_framework_logging_factorial_01_bro.btest | 23 ------- ..._logging_factorial_01_bro.btest => output} | 2 +- ...g_framework_logging_factorial_02_bro.btest | 36 ----------- ..._logging_factorial_02_bro.btest => output} | 2 +- ...g_framework_logging_factorial_03_bro.btest | 12 ---- ..._logging_factorial_03_bro.btest => output} | 2 +- ...g_framework_logging_factorial_04_bro.btest | 54 ---------------- ..._logging_factorial_04_bro.btest => output} | 2 +- ...ripting_framework_notice_hook_01_bro.btest | 11 ---- ...mework_notice_hook_01_bro.btest => output} | 2 +- ...ework_notice_hook_suppression_01_bro.btest | 11 ---- ...e_hook_suppression_01_bro.btest => output} | 2 +- ...ng_framework_notice_shortcuts_01_bro.btest | 12 ---- ...k_notice_shortcuts_01_bro.btest => output} | 2 +- ...ng_framework_notice_shortcuts_02_bro.btest | 11 ---- ...k_notice_shortcuts_02_bro.btest => output} | 2 +- ...clude-scripts_base_bif_event_bif_bro.btest | 25 -------- ...ts_base_bif_event_bif_bro.btest => output} | 2 +- ...e_bif_plugins_Bro_DNS_events_bif_bro.btest | 30 --------- ...ns_Bro_DNS_events_bif_bro.btest => output} | 2 +- ...o.include-scripts_base_init-bare_bro.btest | 7 --- ...cripts_base_init-bare_bro.btest => output} | 2 +- ...scripts_base_protocols_conn_main_bro.btest | 28 --------- ...e_protocols_conn_main_bro.btest => output} | 2 +- ...scripts_base_protocols_http_main_bro.btest | 10 --- ...e_protocols_http_main_bro.btest => output} | 2 +- ...licy_frameworks_files_detect-MHR_bro.btest | 61 ------------------- ...orks_files_detect-MHR_bro.btest => output} | 2 +- ...cy_frameworks_files_detect-MHR_bro@2.btest | 9 --- ...ks_files_detect-MHR_bro@2.btest => output} | 2 +- ...cy_frameworks_files_detect-MHR_bro@3.btest | 17 ------ ...ks_files_detect-MHR_bro@3.btest => output} | 2 +- ...cy_frameworks_files_detect-MHR_bro@4.btest | 23 ------- ...ks_files_detect-MHR_bro@4.btest => output} | 2 +- ...olicy_protocols_conn_known-hosts_bro.btest | 9 --- ...cols_conn_known-hosts_bro.btest => output} | 2 +- ...tocols_ssh_interesting-hostnames_bro.btest | 50 --------------- ...interesting-hostnames_bro.btest => output} | 2 +- ...icy_protocols_ssl_expiring-certs_bro.btest | 8 --- ...ls_ssl_expiring-certs_bro.btest => output} | 2 +- .../btest-doc.sphinx.using_bro#1 | 2 +- ...c_scripting_connection_record_02_bro.btest | 2 +- ...scripting_connection_record_02_bro@2.btest | 2 +- ..._scripting_data_struct_record_01_bro.btest | 2 +- ..._scripting_data_struct_record_02_bro.btest | 2 +- ...ting_data_struct_set_declaration_bro.btest | 2 +- ...ng_data_struct_set_declaration_bro@2.btest | 2 +- ...ng_data_struct_set_declaration_bro@3.btest | 2 +- ...ng_data_struct_set_declaration_bro@4.btest | 2 +- ...ipting_data_struct_table_complex_bro.btest | 2 +- ...ng_data_struct_table_declaration_bro.btest | 2 +- ...g_data_struct_vector_declaration_bro.btest | 2 +- ...cripting_data_struct_vector_iter_bro.btest | 2 +- ...de-doc_scripting_data_type_const_bro.btest | 2 +- ...scripting_data_type_const_simple_bro.btest | 2 +- ..._scripting_data_type_declaration_bro.btest | 2 +- ...doc_scripting_data_type_interval_bro.btest | 2 +- ...de-doc_scripting_data_type_local_bro.btest | 2 +- ...c_scripting_data_type_pattern_01_bro.btest | 2 +- ...c_scripting_data_type_pattern_02_bro.btest | 2 +- ...-doc_scripting_data_type_subnets_bro.btest | 2 +- ...ude-doc_scripting_data_type_time_bro.btest | 2 +- ...g_framework_logging_factorial_01_bro.btest | 2 +- ...g_framework_logging_factorial_02_bro.btest | 2 +- ...g_framework_logging_factorial_03_bro.btest | 2 +- ...g_framework_logging_factorial_04_bro.btest | 2 +- ...ripting_framework_notice_hook_01_bro.btest | 2 +- ...ework_notice_hook_suppression_01_bro.btest | 2 +- ...ng_framework_notice_shortcuts_01_bro.btest | 2 +- ...ng_framework_notice_shortcuts_02_bro.btest | 2 +- ...clude-scripts_base_bif_event_bif_bro.btest | 2 +- ...e_bif_plugins_Bro_DNS_events_bif_bro.btest | 2 +- .../include-scripts_base_init-bare_bro.btest | 2 +- ...scripts_base_protocols_conn_main_bro.btest | 2 +- ...scripts_base_protocols_http_main_bro.btest | 2 +- ...licy_frameworks_files_detect-MHR_bro.btest | 2 +- ...cy_frameworks_files_detect-MHR_bro@2.btest | 2 +- ...cy_frameworks_files_detect-MHR_bro@3.btest | 2 +- ...cy_frameworks_files_detect-MHR_bro@4.btest | 2 +- ...olicy_protocols_conn_known-hosts_bro.btest | 2 +- ...tocols_ssh_interesting-hostnames_bro.btest | 2 +- ...icy_protocols_ssl_expiring-certs_bro.btest | 2 +- 127 files changed, 88 insertions(+), 872 deletions(-) rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest => output} (73%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest rename testing/btest/Baseline/{doc.sphinx.include-doc_scripting_connection_record_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest => doc.sphinx.include-doc_scripting_connection_record_02_bro@2/output} (73%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest => output} (90%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest => output} (95%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest => output} (75%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest => output} (76%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest => output} (69%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest => output} (90%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest => output} (92%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest => output} (88%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest => output} (87%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest => output} (79%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest => output} (79%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest => output} (65%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest => output} (75%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest => output} (92%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest => output} (80%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest => output} (87%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest => output} (87%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest => output} (89%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest => output} (80%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest => output} (87%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest => output} (92%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest => output} (83%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest => output} (95%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest => output} (80%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest => output} (80%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest => output} (79%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest rename testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest => output} (81%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest => output} (93%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest => output} (95%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest => output} (68%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest => output} (94%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest => output} (74%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest => output} (97%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest => output} (64%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest => output} (91%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest => output} (93%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest => output} (68%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest => output} (96%) delete mode 100644 testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest rename testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/{.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest => output} (83%) diff --git a/aux/btest b/aux/btest index 55e2f6c5fc..13a7718b47 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 55e2f6c5fce254e822ff98cfd117e40f89c4c30c +Subproject commit 13a7718b475d670ae22c1914ac1c26bd11be46b6 diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 index 3bd2292105..ed2d0fe653 100644 --- a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 +++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 @@ -12,7 +12,7 @@ #empty_field (empty) #unset_field - #path factor - #open 2013-08-31-22-50-17 + #open 2013-09-01-01-08-18 #fields num factorial_num #types count count 1 1 @@ -25,5 +25,5 @@ 8 40320 9 362880 10 3628800 - #close 2013-08-31-22-50-17 + #close 2013-09-01-01-08-18 diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 index 02ebfcec99..0e6c11c04a 100644 --- a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 +++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 @@ -12,7 +12,7 @@ #empty_field (empty) #unset_field - #path factor-mod5 - #open 2013-08-31-22-50-17 + #open 2013-09-01-01-08-18 #fields num factorial_num #types count count 5 120 @@ -21,5 +21,5 @@ 8 40320 9 362880 10 3628800 - #close 2013-08-31-22-50-17 + #close 2013-09-01-01-08-18 diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/output similarity index 73% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/output index 43a6ebc554..20ffe4c686 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- connection_record_02.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest deleted file mode 100644 index 43a6ebc554..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest +++ /dev/null @@ -1,11 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- connection_record_02.bro - -@load base/protocols/conn -@load base/protocols/dns - -event connection_state_remove(c: connection) - { - print c; - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest deleted file mode 100644 index 43a6ebc554..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro@2.include-doc_scripting_connection_record_02_bro@2.btest +++ /dev/null @@ -1,11 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- connection_record_02.bro - -@load base/protocols/conn -@load base/protocols/dns - -event connection_state_remove(c: connection) - { - print c; - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/output similarity index 73% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/output index 43a6ebc554..20ffe4c686 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_connection_record_02_bro.include-doc_scripting_connection_record_02_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- connection_record_02.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest deleted file mode 100644 index 82f1b1f56c..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest +++ /dev/null @@ -1,26 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_record_01.bro - -type Service: record { - name: string; - ports: set[port]; - rfc: count; -}; - -function print_service(serv: Service): string - { - print fmt("Service: %s(RFC%d)",serv$name, serv$rfc); - - for ( p in serv$ports ) - print fmt(" port: %s", p); - } - -event bro_init() - { - local dns: Service = [$name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; - local http: Service = [$name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; - - print_service(dns); - print_service(http); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/output similarity index 90% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/output index 82f1b1f56c..12a6515235 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_01_bro.include-doc_scripting_data_struct_record_01_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_record_01.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest deleted file mode 100644 index 05b5b9d50c..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest +++ /dev/null @@ -1,45 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_record_02.bro - -type Service: record { - name: string; - ports: set[port]; - rfc: count; - }; - -type System: record { - name: string; - services: set[Service]; - }; - -function print_service(serv: Service): string - { - print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc); - - for ( p in serv$ports ) - print fmt(" port: %s", p); - } - -function print_system(sys: System): string - { - print fmt("System: %s", sys$name); - - for ( s in sys$services ) - print_service(s); - } - -event bro_init() - { - local server01: System; - server01$name = "morlock"; - add server01$services[[ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]]; - add server01$services[[ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]]; - print_system(server01); - - - # local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]; - # local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]; - # print_service(dns); - # print_service(http); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/output similarity index 95% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/output index 05b5b9d50c..dedbca8be7 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_record_02_bro.include-doc_scripting_data_struct_record_02_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_record_02.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest deleted file mode 100644 index b659563ac3..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest +++ /dev/null @@ -1,9 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_set_declaration.bro - -event bro_init() - { - local ssl_ports: set[port]; - local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp ); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/output similarity index 75% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/output index b659563ac3..700c7296d0 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro.include-doc_scripting_data_struct_set_declaration_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_set_declaration.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest deleted file mode 100644 index 5fa1f36475..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest +++ /dev/null @@ -1,9 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_set_declaration.bro - - for ( i in ssl_ports ) - print fmt("SSL Port: %s", i); - - for ( i in non_ssl_ports ) - print fmt("Non-SSL Port: %s", i); diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/output similarity index 76% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/output index 5fa1f36475..b31b65805f 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2.include-doc_scripting_data_struct_set_declaration_bro@2.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_set_declaration.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest deleted file mode 100644 index 48d33b52e5..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest +++ /dev/null @@ -1,7 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_set_declaration.bro - - # Check for SMTPS - if ( 587/tcp !in ssl_ports ) - add ssl_ports[587/tcp]; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/output similarity index 69% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/output index 48d33b52e5..c5bddfb7d1 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3.include-doc_scripting_data_struct_set_declaration_bro@3.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_set_declaration.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest deleted file mode 100644 index 19ddfe81d5..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest +++ /dev/null @@ -1,26 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_set_declaration.bro - -event bro_init() - { - local ssl_ports: set[port]; - local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp ); - - # SSH - add ssl_ports[22/tcp]; - # HTTPS - add ssl_ports[443/tcp]; - # IMAPS - add ssl_ports[993/tcp]; - - # Check for SMTPS - if ( 587/tcp !in ssl_ports ) - add ssl_ports[587/tcp]; - - for ( i in ssl_ports ) - print fmt("SSL Port: %s", i); - - for ( i in non_ssl_ports ) - print fmt("Non-SSL Port: %s", i); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/output similarity index 90% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/output index 19ddfe81d5..5c87335f06 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4.include-doc_scripting_data_struct_set_declaration_bro@4.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_set_declaration.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest deleted file mode 100644 index a6a1d7a63a..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest +++ /dev/null @@ -1,17 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_table_complex.bro - -event bro_init() - { - local samurai_flicks: table[string, string, count, string] of string; - - samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru"; - samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin"; - samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri"; - samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei"; - - for ( [d, s, y, a] in samurai_flicks ) - print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a); - } - diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/output similarity index 92% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/output index a6a1d7a63a..2557adea17 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_complex_bro.include-doc_scripting_data_struct_table_complex_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_table_complex.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest deleted file mode 100644 index 79fe7660ae..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest +++ /dev/null @@ -1,17 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_table_declaration.bro - -event bro_init() - { - local ssl_services: table[string] of port; - - ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp); - ssl_services["IMAPS"] = 993/tcp; - - if ( "SMTPS" !in ssl_services ) - ssl_services["SMTPS"] = 587/tcp; - - for ( k in ssl_services ) - print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/output similarity index 88% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/output index 79fe7660ae..8aab992b18 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro.include-doc_scripting_data_struct_table_declaration_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_table_declaration.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest deleted file mode 100644 index 6b8a81a58f..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest +++ /dev/null @@ -1,19 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_vector_declaration.bro - -event bro_init() - { - local v1: vector of count; - local v2 = vector(1, 2, 3, 4); - - v1[|v1|] = 1; - v1[|v1|] = 2; - v1[|v1|] = 3; - v1[|v1|] = 4; - - print fmt("contents of v1: %s", v1); - print fmt("length of v1: %d", |v1|); - print fmt("contents of v1: %s", v2); - print fmt("length of v2: %d", |v2|); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/output similarity index 87% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/output index 6b8a81a58f..91eaf2432d 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro.include-doc_scripting_data_struct_vector_declaration_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_vector_declaration.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest deleted file mode 100644 index a28522fb64..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest +++ /dev/null @@ -1,11 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_struct_vector_iter.bro - -event bro_init() - { - local addr_vector: vector of addr = vector(1.2.3.4, 2.3.4.5, 3.4.5.6); - - for (i in addr_vector) - print mask_addr(addr_vector[i], 18); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/output similarity index 79% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/output index a28522fb64..73694157d3 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro.include-doc_scripting_data_struct_vector_iter_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_vector_iter.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest deleted file mode 100644 index a42efd2b72..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest +++ /dev/null @@ -1,13 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_const.bro - -const port_list: table[port] of string &redef; - -redef port_list += { [6666/tcp] = "IRC"}; -redef port_list += { [80/tcp] = "WWW" }; - -event bro_init() - { - print port_list; - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/output similarity index 79% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/output index a42efd2b72..f1337275ca 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_bro.include-doc_scripting_data_type_const_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_const.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest deleted file mode 100644 index 914f9dc0ec..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest +++ /dev/null @@ -1,8 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_const_simple.bro - -@load base/protocols/http - -redef HTTP::default_capture_password = T; - diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/output similarity index 65% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/output index 914f9dc0ec..807e92573f 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_const_simple_bro.include-doc_scripting_data_type_const_simple_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_const_simple.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest deleted file mode 100644 index edd01615fc..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest +++ /dev/null @@ -1,13 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_declaration.bro - -event bro_init() - { - local a: int; - a = 10; - local b = 10; - - if ( a == b ) - print fmt("A: %d, B: %d", a, b); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/output similarity index 75% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/output index edd01615fc..56ac2c5fc4 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_declaration_bro.include-doc_scripting_data_type_declaration_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_declaration.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest deleted file mode 100644 index 7954ed9ebe..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest +++ /dev/null @@ -1,22 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_interval.bro - -# Store the time the previous connection was established. -global last_connection_time: time; - -# boolean value to indicate whether we have seen a previous connection. -global connection_seen: bool = F; - -event connection_established(c: connection) - { - local net_time: time = network_time(); - - print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h); - - if ( connection_seen ) - print fmt(" Time since last connection: %s", net_time - last_connection_time); - - last_connection_time = net_time; - connection_seen = T; - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/output similarity index 92% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/output index 7954ed9ebe..fd6d831e8b 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_interval_bro.include-doc_scripting_data_type_interval_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_interval.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest deleted file mode 100644 index 850ffeb905..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest +++ /dev/null @@ -1,15 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_local.bro - -function add_two(i: count): count - { - local added_two = i+2; - print fmt("i + 2 = %d", added_two); - return added_two; - } - -event bro_init() - { - local test = add_two(10); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/output similarity index 80% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/output index 850ffeb905..93f84cc059 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_local_bro.include-doc_scripting_data_type_local_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_local.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest deleted file mode 100644 index 475fcd676e..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest +++ /dev/null @@ -1,17 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_pattern_01.bro - -event bro_init() - { - local test_string = "The quick brown fox jumped over the lazy dog."; - local test_pattern = /quick|lazy/; - - if ( test_pattern in test_string ) - { - local results = split(test_string, test_pattern); - print results[1]; - print results[2]; - print results[3]; - } - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/output similarity index 87% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/output index 475fcd676e..55f68d9e45 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_01_bro.include-doc_scripting_data_type_pattern_01_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_pattern_01.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest deleted file mode 100644 index 915e8612be..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest +++ /dev/null @@ -1,14 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_pattern_02.bro - -event bro_init() - { - local test_string = "equality"; - - local test_pattern = /equal/; - print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); - - test_pattern = /equality/; - print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not"); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/output similarity index 87% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/output index 915e8612be..ed09de2be0 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_pattern_02_bro.include-doc_scripting_data_type_pattern_02_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_pattern_02.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest deleted file mode 100644 index d2edfd5e9a..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest +++ /dev/null @@ -1,19 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_subnets.bro - -event bro_init() - { - local subnets = vector(172.16.0.0/20, 172.16.16.0/20, 172.16.32.0/20, 172.16.48.0/20); - local addresses = vector(172.16.4.56, 172.16.47.254, 172.16.22.45, 172.16.1.1); - - for ( a in addresses ) - { - for ( s in subnets ) - { - if ( addresses[a] in subnets[s] ) - print fmt("%s belongs to subnet %s", addresses[a], subnets[s]); - } - } - - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/output similarity index 89% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/output index d2edfd5e9a..f23f3427ed 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_subnets_bro.include-doc_scripting_data_type_subnets_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_subnets.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest deleted file mode 100644 index 960d4ac9bd..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest +++ /dev/null @@ -1,8 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- data_type_time.bro - -event connection_established(c: connection) - { - print fmt("%s: New connection established from %s to %s\n", strftime("%Y/%M/%d %H:%m:%S", network_time()), c$id$orig_h, c$id$resp_h); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/output similarity index 80% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/output index 960d4ac9bd..fa04f56021 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_data_type_time_bro.include-doc_scripting_data_type_time_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_time.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest deleted file mode 100644 index 7a18c86509..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest +++ /dev/null @@ -1,23 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- framework_logging_factorial_01.bro - -module Factor; - -function factorial(n: count): count - { - if ( n == 0 ) - return 1; - else - return ( n * factorial(n - 1) ); - } - -event bro_init() - { - local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); - - for ( n in numbers ) - print fmt("%d", factorial(numbers[n])); - } - - diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/output similarity index 87% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/output index 7a18c86509..762e8a1651 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro.include-doc_scripting_framework_logging_factorial_01_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_logging_factorial_01.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest deleted file mode 100644 index 6966f7ea3c..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest +++ /dev/null @@ -1,36 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- framework_logging_factorial_02.bro - -module Factor; - -export { - redef enum Log::ID += { LOG }; - - type Info: record { - num: count &log; - factorial_num: count &log; - }; - } - -function factorial(n: count): count - { - if ( n == 0 ) - return 1; - - else - return ( n * factorial(n - 1) ); - } - -event bro_init() - { - Log::create_stream(LOG, [$columns=Info]); - } - -event bro_done() - { - local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); - for ( n in numbers ) - Log::write( Factor::LOG, [$num=numbers[n], - $factorial_num=factorial(numbers[n])]); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/output similarity index 92% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/output index 6966f7ea3c..6972c285f9 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro.include-doc_scripting_framework_logging_factorial_02_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_logging_factorial_02.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest deleted file mode 100644 index c3c16f8d6a..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest +++ /dev/null @@ -1,12 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- framework_logging_factorial_03.bro - -event bro_init() - { - Log::create_stream(LOG, [$columns=Info]); - - local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; - Log::add_filter(Factor::LOG, filter); - Log::remove_filter(Factor::LOG, "default"); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/output similarity index 83% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/output index c3c16f8d6a..9e7846eb59 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro.include-doc_scripting_framework_logging_factorial_03_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_logging_factorial_03.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest deleted file mode 100644 index dbedb8e689..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest +++ /dev/null @@ -1,54 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- framework_logging_factorial_04.bro - -module Factor; - -export { - redef enum Log::ID += { LOG }; - - type Info: record { - num: count &log; - factorial_num: count &log; - }; - - global log_factor: event(rec: Info); - } - -function factorial(n: count): count - { - if ( n == 0 ) - return 1; - - else - return (n * factorial(n - 1)); - } - -event bro_init() - { - Log::create_stream(LOG, [$columns=Info, $ev=log_factor]); - } - -event bro_done() - { - local numbers: vector of count = vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); - for ( n in numbers ) - Log::write( Factor::LOG, [$num=numbers[n], - $factorial_num=factorial(numbers[n])]); - } - -function mod5(id: Log::ID, path: string, rec: Factor::Info) : string - { - if ( rec$factorial_num % 5 == 0 ) - return "factor-mod5"; - - else - return "factor-non5"; - } - -event bro_init() - { - local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5]; - Log::add_filter(Factor::LOG, filter); - Log::remove_filter(Factor::LOG, "default"); - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/output similarity index 95% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/output index dbedb8e689..b2e85f0c90 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro.include-doc_scripting_framework_logging_factorial_04_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_logging_factorial_04.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest deleted file mode 100644 index 70f8c70247..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest +++ /dev/null @@ -1,11 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- framework_notice_hook_01.bro - -@load policy/protocols/ssh/interesting-hostnames.bro - -hook Notice::policy(n: Notice::Info) - { - if ( n$note == SSH::Interesting_Hostname_Login ) - add n$actions[Notice::ACTION_EMAIL]; - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/output similarity index 80% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/output index 70f8c70247..632efc9b90 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro.include-doc_scripting_framework_notice_hook_01_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_notice_hook_01.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest deleted file mode 100644 index 522bef5930..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest +++ /dev/null @@ -1,11 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- framework_notice_hook_suppression_01.bro - -@load policy/protocols/ssl/expiring-certs.bro - -hook Notice::policy(n: Notice::Info) - { - if ( n$note == SSL::Certificate_Expires_Soon ) - n$suppress_for = 12hrs; - } diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/output similarity index 80% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/output index 522bef5930..0d5eb7e25f 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro.include-doc_scripting_framework_notice_hook_suppression_01_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_notice_hook_suppression_01.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest deleted file mode 100644 index 95eed5f501..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest +++ /dev/null @@ -1,12 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- framework_notice_shortcuts_01.bro - -@load policy/protocols/ssh/interesting-hostnames.bro -@load base/protocols/ssh/ - -redef Notice::emailed_types += { - SSH::Interesting_Hostname_Login, - SSH::Login -}; - diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/output similarity index 79% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/output index 95eed5f501..80e464f312 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro.include-doc_scripting_framework_notice_shortcuts_01_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_notice_shortcuts_01.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest deleted file mode 100644 index 8c12558d42..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest +++ /dev/null @@ -1,11 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- framework_notice_shortcuts_02.bro - -@load policy/protocols/ssh/interesting-hostnames.bro -@load base/protocols/ssh/ - -redef Notice::type_suppression_intervals += { - [SSH::Interesting_Hostname_Login] = 1day, - [SSH::Login] = 12hrs, -}; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/output similarity index 81% rename from testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/output index 8c12558d42..0418955ab2 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro.include-doc_scripting_framework_notice_shortcuts_02_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_notice_shortcuts_02.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest deleted file mode 100644 index 088d5d2368..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest +++ /dev/null @@ -1,25 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- event.bif.bro - -## script-level cleanup that needs to be performed for every connection. This -## event is generated not only for TCP sessions but also for UDP and ICMP -## flows. -## -## -global connection_external: event(c: connection , tag: string ); - - -## Generated when a UDP session for a supported protocol has finished. Some of -## Bro's application-layer UDP analyzers flag the end of a session by raising -## Generated when a connection is seen that is marked as being expected. - - -global ipv6_ext_headers: event(c: connection , p: pkt_hdr ); -## their specifics differ slightly. Often, however, both will be raised for -## the same connection if some of its data is missing. We should eventually -## merge the two. -global ack_above_hole: event(c: connection ); - - -## diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output similarity index 93% rename from testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output index 088d5d2368..fc14c86399 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_event_bif_bro.include-scripts_base_bif_event_bif_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- event.bif.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest deleted file mode 100644 index c8e7eaab20..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest +++ /dev/null @@ -1,30 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- Bro_DNS.events.bif.bro - -## Generated for DNS requests. For requests with multiple queries, this event -## is raised once for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## query: The queried name. -## -## qtype: The queried resource record type. -## -## qclass: The queried resource record class. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -global dns_request: event(c: connection , msg: dns_msg , query: string , qtype: count , qclass: count ); diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/output similarity index 95% rename from testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/output index c8e7eaab20..b393c0580b 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- Bro_DNS.events.bif.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest deleted file mode 100644 index 7d23c68ae4..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest +++ /dev/null @@ -1,7 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- init-bare.bro - -type string_array: table[count] of string; -type string_set: set[string]; -type addr_set: set[addr]; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/output similarity index 68% rename from testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/output index 7d23c68ae4..c42a63f6ad 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_init-bare_bro.include-scripts_base_init-bare_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- init-bare.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest deleted file mode 100644 index dc18745d57..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest +++ /dev/null @@ -1,28 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- main.bro - -module Conn; - -export { - ## The record type which contains column fields of the connection log. - type Info: record { - ts: time &log; - uid: string &log; - id: conn_id &log; - proto: transport_proto &log; - service: string &log &optional; - duration: interval &log &optional; - orig_bytes: count &log &optional; - resp_bytes: count &log &optional; - conn_state: string &log &optional; - local_orig: bool &log &optional; - missed_bytes: count &log &default=0; - history: string &log &optional; - orig_pkts: count &log &optional; - orig_ip_bytes: count &log &optional; - resp_pkts: count &log &optional; - resp_ip_bytes: count &log &optional; - tunnel_parents: set[string] &log; - }; -} diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/output similarity index 94% rename from testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/output index dc18745d57..ddbe628009 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_conn_main_bro.include-scripts_base_protocols_conn_main_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- main.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest deleted file mode 100644 index abe74112bd..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest +++ /dev/null @@ -1,10 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- main.bro - -module HTTP; - -export { - ## This setting changes if passwords used in Basic-Auth are captured or not. - const default_capture_password = F &redef; -} diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/output similarity index 74% rename from testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/output index abe74112bd..0acb7a17e8 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_base_protocols_http_main_bro.include-scripts_base_protocols_http_main_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- main.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest deleted file mode 100644 index b73140fe8e..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest +++ /dev/null @@ -1,61 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- detect-MHR.bro - -##! Detect file downloads that have hash values matching files in Team -##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). - -@load base/frameworks/files -@load base/frameworks/notice -@load frameworks/files/hash-all-files - -module TeamCymruMalwareHashRegistry; - -export { - redef enum Notice::Type += { - ## The hash value of a file transferred over HTTP matched in the - ## malware hash registry. - Match - }; - - ## File types to attempt matching against the Malware Hash Registry. - const match_file_types = /application\/x-dosexec/ | - /application\/vnd.ms-cab-compressed/ | - /application\/pdf/ | - /application\/x-shockwave-flash/ | - /application\/x-java-applet/ | - /application\/jar/ | - /video\/mp4/ &redef; - - ## The malware hash registry runs each malware sample through several A/V engines. - ## Team Cymru returns a percentage to indicate how many A/V engines flagged the - ## sample as malicious. This threshold allows you to require a minimum detection - ## rate. - const notice_threshold = 10 &redef; -} - -event file_hash(f: fa_file, kind: string, hash: string) - { - if ( kind=="sha1" && match_file_types in f$mime_type ) - { - local hash_domain = fmt("%s.malware.hash.cymru.com", hash); - when ( local MHR_result = lookup_hostname_txt(hash_domain) ) - { - # Data is returned as " " - local MHR_answer = split1(MHR_result, / /); - if ( |MHR_answer| == 2 ) - { - local mhr_first_detected = double_to_time(to_double(MHR_answer[1])); - local mhr_detect_rate = to_count(MHR_answer[2]); - - local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected); - if ( mhr_detect_rate >= notice_threshold ) - { - local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected); - local virustotal_url = fmt("https://www.virustotal.com/en/file/%s/analysis/", hash); - NOTICE([$note=Match, $msg=message, $sub=virustotal_url, $f=f]); - } - } - } - } - } diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/output similarity index 97% rename from testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/output index b73140fe8e..9220e6abf7 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro.include-scripts_policy_frameworks_files_detect-MHR_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- detect-MHR.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest deleted file mode 100644 index 51044b36d9..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest +++ /dev/null @@ -1,9 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- detect-MHR.bro - - -module TeamCymruMalwareHashRegistry; - -export { - redef enum Notice::Type += { diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output similarity index 64% rename from testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output index 51044b36d9..8d26caba6c 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2.include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- detect-MHR.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest deleted file mode 100644 index 37de8b6ff7..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest +++ /dev/null @@ -1,17 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- detect-MHR.bro - - ## The hash value of a file transferred over HTTP matched in the - ## malware hash registry. - Match - }; - - ## File types to attempt matching against the Malware Hash Registry. - const match_file_types = /application\/x-dosexec/ | - /application\/vnd.ms-cab-compressed/ | - /application\/pdf/ | - /application\/x-shockwave-flash/ | - /application\/x-java-applet/ | - /application\/jar/ | - /video\/mp4/ &redef; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output similarity index 91% rename from testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output index 37de8b6ff7..ace6e79c5e 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3.include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- detect-MHR.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest deleted file mode 100644 index 19e9d2ee54..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest +++ /dev/null @@ -1,23 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- detect-MHR.bro - - ## The malware hash registry runs each malware sample through several A/V engines. - ## Team Cymru returns a percentage to indicate how many A/V engines flagged the - ## sample as malicious. This threshold allows you to require a minimum detection - ## rate. - const notice_threshold = 10 &redef; -} - -event file_hash(f: fa_file, kind: string, hash: string) - { - if ( kind=="sha1" && match_file_types in f$mime_type ) - { - local hash_domain = fmt("%s.malware.hash.cymru.com", hash); - when ( local MHR_result = lookup_hostname_txt(hash_domain) ) - { - # Data is returned as " " - local MHR_answer = split1(MHR_result, / /); - if ( |MHR_answer| == 2 ) - { - local mhr_first_detected = double_to_time(to_double(MHR_answer[1])); diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output similarity index 93% rename from testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output index 19e9d2ee54..6f4cda878c 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4.include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- detect-MHR.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest deleted file mode 100644 index 9b0c50c3f4..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest +++ /dev/null @@ -1,9 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- known-hosts.bro - -module Known; - -export { - global known_hosts: set[addr] &create_expire=1day &synchronized &redef; -} diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/output similarity index 68% rename from testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/output index 9b0c50c3f4..db7f3d355b 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro.include-scripts_policy_protocols_conn_known-hosts_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- known-hosts.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest deleted file mode 100644 index 73eec1a1b9..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest +++ /dev/null @@ -1,50 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- interesting-hostnames.bro - -##! This script will generate a notice if an apparent SSH login originates -##! or heads to a host with a reverse hostname that looks suspicious. By -##! default, the regular expression to match "interesting" hostnames includes -##! names that are typically used for infrastructure hosts like nameservers, -##! mail servers, web servers and ftp servers. - -@load base/frameworks/notice - -module SSH; - -export { - redef enum Notice::Type += { - ## Generated if a login originates or responds with a host where the - ## reverse hostname lookup resolves to a name matched by the - ## :bro:id:`SSH::interesting_hostnames` regular expression. - Interesting_Hostname_Login, - }; - - ## Strange/bad host names to see successful SSH logins from or to. - const interesting_hostnames = - /^d?ns[0-9]*\./ | - /^smtp[0-9]*\./ | - /^mail[0-9]*\./ | - /^pop[0-9]*\./ | - /^imap[0-9]*\./ | - /^www[0-9]*\./ | - /^ftp[0-9]*\./ &redef; -} - -event SSH::heuristic_successful_login(c: connection) - { - for ( host in set(c$id$orig_h, c$id$resp_h) ) - { - when ( local hostname = lookup_addr(host) ) - { - if ( interesting_hostnames in hostname ) - { - NOTICE([$note=Interesting_Hostname_Login, - $msg=fmt("Possible SSH login involving a %s %s with an interesting hostname.", - Site::is_local_addr(host) ? "local" : "remote", - host == c$id$orig_h ? "client" : "server"), - $sub=hostname, $conn=c]); - } - } - } - } diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output similarity index 96% rename from testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output index 73eec1a1b9..2a395ab20e 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- interesting-hostnames.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest deleted file mode 100644 index 16e2552545..0000000000 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.home.robin.bro.master.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest +++ /dev/null @@ -1,8 +0,0 @@ -# @TEST-EXEC: btest-diff %INPUT - --- expiring-certs.bro - - NOTICE([$note=Certificate_Expires_Soon, - $msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after), - $conn=c, $suppress_for=1day, - $identifier=cat(c$id$resp_h, c$id$resp_p, c$ssl$cert_hash)]); diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/output similarity index 83% rename from testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest rename to testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/output index 16e2552545..6a630796c0 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/.Users.robin.bro.docs.testing.btest..tmp.doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro.include-scripts_policy_protocols_ssl_expiring-certs_bro.btest +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/output @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- expiring-certs.bro diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 index 26236f7e81..ee6f8a7a03 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 @@ -12,7 +12,7 @@ #empty_field (empty) #unset_field - #path conn - #open 2013-08-31-22-50-20 + #open 2013-09-01-01-08-21 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] 1300475167.096535 CXWv6p3arKYeMETxOg 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 73 0 0 (empty) diff --git a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest index 43a6ebc554..20ffe4c686 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- connection_record_02.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest index 43a6ebc554..20ffe4c686 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- connection_record_02.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest index 82f1b1f56c..12a6515235 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_record_01.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest index 05b5b9d50c..dedbca8be7 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_record_02.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest index b659563ac3..700c7296d0 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_set_declaration.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest index 5fa1f36475..b31b65805f 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_set_declaration.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest index 48d33b52e5..c5bddfb7d1 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_set_declaration.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest index 19ddfe81d5..5c87335f06 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_set_declaration.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest index a6a1d7a63a..2557adea17 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_table_complex.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest index 79fe7660ae..8aab992b18 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_table_declaration.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest index 6b8a81a58f..91eaf2432d 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_vector_declaration.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest index a28522fb64..73694157d3 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_struct_vector_iter.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest index a42efd2b72..f1337275ca 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_const.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest index 914f9dc0ec..807e92573f 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_const_simple.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest index edd01615fc..56ac2c5fc4 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_declaration.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest index 7954ed9ebe..fd6d831e8b 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_interval.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest index 850ffeb905..93f84cc059 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_local.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest index 475fcd676e..55f68d9e45 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_pattern_01.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest index 915e8612be..ed09de2be0 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_pattern_02.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest index d2edfd5e9a..f23f3427ed 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_subnets.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest index 960d4ac9bd..fa04f56021 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- data_type_time.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest index 7a18c86509..762e8a1651 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_logging_factorial_01.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest index 6966f7ea3c..6972c285f9 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_logging_factorial_02.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest index c3c16f8d6a..9e7846eb59 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_logging_factorial_03.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest index dbedb8e689..b2e85f0c90 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_logging_factorial_04.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest index 70f8c70247..632efc9b90 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_notice_hook_01.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest index 522bef5930..0d5eb7e25f 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_notice_hook_suppression_01.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest index 95eed5f501..80e464f312 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_notice_shortcuts_01.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest index 8c12558d42..0418955ab2 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- framework_notice_shortcuts_02.bro diff --git a/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest index 088d5d2368..fc14c86399 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- event.bif.bro diff --git a/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest index c8e7eaab20..b393c0580b 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- Bro_DNS.events.bif.bro diff --git a/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest index 7d23c68ae4..c42a63f6ad 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- init-bare.bro diff --git a/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest index dc18745d57..ddbe628009 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- main.bro diff --git a/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest index abe74112bd..0acb7a17e8 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- main.bro diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest index b73140fe8e..9220e6abf7 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- detect-MHR.bro diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest index 51044b36d9..8d26caba6c 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- detect-MHR.bro diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest index 37de8b6ff7..ace6e79c5e 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- detect-MHR.bro diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest index 19e9d2ee54..6f4cda878c 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- detect-MHR.bro diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest index 9b0c50c3f4..db7f3d355b 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- known-hosts.bro diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest index 73eec1a1b9..2a395ab20e 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- interesting-hostnames.bro diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest index 16e2552545..6a630796c0 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest @@ -1,4 +1,4 @@ -# @TEST-EXEC: btest-diff %INPUT +# @TEST-EXEC: cat %INPUT >output && btest-diff output -- expiring-certs.bro From db470a637a197cb2e76d7eee7ab55c6555dff1fd Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 3 Sep 2013 15:59:40 -0500 Subject: [PATCH 288/881] Documentation fixes. This cleans up most of the warnings from sphinx (broken :doc: links, broxygen role misuses, etc.). The remaining ones should be harmless, but not quick to silence. I found that the README for each component was a copy from the actual repo, so I turned those in to symlinks so they don't get out of date. --- NEWS | 29 +- aux/broctl | 2 +- doc/components/binpac/README.rst | 69 +- doc/components/bro-aux/README.rst | 71 +- doc/components/broccoli-python/README.rst | 232 +- doc/components/broccoli-ruby/README.rst | 68 +- doc/components/broccoli/README.rst | 142 +- doc/components/broccoli/broccoli-manual.rst | 1356 +----------- doc/components/broctl/README.rst | 1914 +---------------- doc/components/btest/README.rst | 844 +------- doc/components/capstats/README.rst | 108 +- doc/components/pysubnettree/README.rst | 99 +- doc/components/trace-summary/README.rst | 155 +- doc/frameworks/logging-dataseries.rst | 2 +- doc/frameworks/logging.rst | 10 +- doc/frameworks/notice.rst | 2 +- doc/quickstart/index.rst | 17 +- doc/scripting/index.rst | 49 +- doc/scripts/builtins.rst | 2 +- doc/scripts/index.rst | 6 +- scripts/base/frameworks/logging/main.bro | 3 +- scripts/base/frameworks/notice/main.bro | 2 +- scripts/base/frameworks/signatures/main.bro | 4 +- scripts/base/frameworks/sumstats/main.bro | 8 +- scripts/base/protocols/dhcp/utils.bro | 2 - scripts/base/protocols/ssl/__load__.bro | 2 +- scripts/base/utils/active-http.bro | 6 +- .../frameworks/intel/seen/http-headers.bro | 1 + src/analyzer/protocol/dnp3/events.bif | 21 +- src/event.bif | 4 +- src/probabilistic/bloom-filter.bif | 40 +- src/strings.bif | 4 +- 32 files changed, 123 insertions(+), 5151 deletions(-) mode change 100644 => 120000 doc/components/binpac/README.rst mode change 100644 => 120000 doc/components/bro-aux/README.rst mode change 100644 => 120000 doc/components/broccoli-python/README.rst mode change 100644 => 120000 doc/components/broccoli-ruby/README.rst mode change 100644 => 120000 doc/components/broccoli/README.rst mode change 100644 => 120000 doc/components/broccoli/broccoli-manual.rst mode change 100644 => 120000 doc/components/broctl/README.rst mode change 100644 => 120000 doc/components/btest/README.rst mode change 100644 => 120000 doc/components/capstats/README.rst mode change 100644 => 120000 doc/components/pysubnettree/README.rst mode change 100644 => 120000 doc/components/trace-summary/README.rst diff --git a/NEWS b/NEWS index fcc0863b92..2755be9a8d 100644 --- a/NEWS +++ b/NEWS @@ -48,7 +48,7 @@ New Functionality than global state as it was before. - The scripting language now supports a constructing sets, tables, - vectors, and records by name: + vectors, and records by name:: type MyRecordType: record { c: count; @@ -178,7 +178,7 @@ Changed Functionality split_complete() - md5_*, sha1_*, sha256_*, and entropy_* have all changed - their signatures to work with opaque types (see above). + their signatures to work with opaque types (see above). - Removed a now unused argument from "do_split" helper function. @@ -204,7 +204,7 @@ Changed Functionality - What used to be a "redef" of "Notice::policy" now becomes a hook implementation. Example: - Old: + Old:: redef Notice::policy += { [$pred(n: Notice::Info) = { @@ -213,7 +213,7 @@ Changed Functionality $action = Notice::ACTION_EMAIL] }; - New: + New:: hook Notice::policy(n: Notice::Info) { @@ -225,18 +225,18 @@ Changed Functionality handlers for that event, you'll likely just need to change the type accordingly. Example: - Old: + Old:: event notice(n: Notice::Info) { ... } - New: + New:: hook notice(n: Notice::Info) { ... } - The notice_policy.log is gone. That's a result of the new notice policy setup. -- Removed the byte_len() and length() bif functions. Use the "|...|" +- Removed the byte_len() and length() bif functions. Use the ``|...|`` operator instead. - The SSH::Login notice has been superseded by an corresponding @@ -479,8 +479,8 @@ with the new version. The two rules of thumb are: if you need help. Below we summarize changes from 1.x to 2.x in more detail. This list -isn't complete, see the :download:`CHANGES ` file in the -distribution for the full story. +isn't complete, see the ``CHANGES`` file in the distribution or +:doc:`here ` for the full story. Script Organization ------------------- @@ -568,8 +568,8 @@ Logging Framework endpoint. - The new logging framework makes it possible to extend, customize, - and filter logs very easily. See the :doc:`logging framework ` - for more information on usage. + and filter logs very easily. See the :doc:`logging framework + ` for more information on usage. - A common pattern found in the new scripts is to store logging stream records for protocols inside the ``connection`` records so that @@ -590,9 +590,10 @@ Logging Framework Notice Framework ---------------- -The way users interact with "notices" has changed significantly in -order to make it easier to define a site policy and more extensible -for adding customized actions. See the :doc:`notice framework `. +The way users interact with "notices" has changed significantly in order +to make it easier to define a site policy and more extensible for adding +customized actions. See the :doc:`notice framework +`. New Default Settings diff --git a/aux/broctl b/aux/broctl index f66eea64d1..d53d07dafe 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit f66eea64d1bbcbee0e41621e553260cece2a1e48 +Subproject commit d53d07dafe904db24ee1d022b3f831007f824f87 diff --git a/doc/components/binpac/README.rst b/doc/components/binpac/README.rst deleted file mode 100644 index 683b5455f4..0000000000 --- a/doc/components/binpac/README.rst +++ /dev/null @@ -1,68 +0,0 @@ -.. -*- mode: rst-mode -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 0.34-3 - -====== -BinPAC -====== - -.. rst-class:: opening - - BinPAC is a high level language for describing protocol parsers and - generates C++ code. It is currently maintained and distributed with the - Bro Network Security Monitor distribution, however, the generated parsers - may be used with other programs besides Bro. - -Download --------- - -You can find the latest BinPAC release for download at -http://www.bro.org/download. - -BinPAC's git repository is located at `git://git.bro.org/binpac.git -`__. You can browse the repository -`here `__. - -This document describes BinPAC |version|. See the ``CHANGES`` -file for version history. - -Prerequisites -------------- - -BinPAC relies on the following libraries and tools, which need to be -installed before you begin: - - * Flex (Fast Lexical Analyzer) - Flex is already installed on most systems, so with luck you can - skip having to install it yourself. - - * Bison (GNU Parser Generator) - Bison is also already installed on many system. - - * CMake 2.6.3 or greater - CMake is a cross-platform, open-source build system, typically - not installed by default. See http://www.cmake.org for more - information regarding CMake and the installation steps below for - how to use it to build this distribution. CMake generates native - Makefiles that depend on GNU Make by default - -Installation ------------- - -To build and install into ``/usr/local``:: - - ./configure - cd build - make - make install - -This will perform an out-of-source build into the build directory using -the default build options and then install the binpac binary into -``/usr/local/bin``. - -You can specify a different installation directory with:: - - ./configure --prefix=

- -Run ``./configure --help`` for more options. diff --git a/doc/components/binpac/README.rst b/doc/components/binpac/README.rst new file mode 120000 index 0000000000..4eb90ef658 --- /dev/null +++ b/doc/components/binpac/README.rst @@ -0,0 +1 @@ +../../../aux/binpac/README \ No newline at end of file diff --git a/doc/components/bro-aux/README.rst b/doc/components/bro-aux/README.rst deleted file mode 100644 index 822afea358..0000000000 --- a/doc/components/bro-aux/README.rst +++ /dev/null @@ -1,70 +0,0 @@ -.. -*- mode: rst; -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 0.26-5 - -====================== -Bro Auxiliary Programs -====================== - -.. contents:: - -:Version: |version| - -Handy auxiliary programs related to the use of the Bro Network Security -Monitor (http://www.bro.org). - -Note that some files that were formerly distributed with Bro as part -of the aux/ tree are now maintained separately. See the -http://www.bro.org/download for their download locations. - -adtrace -======= - -Makefile and source for the adtrace utility. This program is used -in conjunction with the localnetMAC.pl perl script to compute the -network address that compose the internal and extern nets that bro -is monitoring. This program when run by itself just reads a pcap -(tcpdump) file and writes out the src MAC, dst MAC, src IP, dst -IP for each packet seen in the file. This output is processed by -the localnetMAC.pl script during 'make install'. - - -devel-tools -=========== - -A set of scripts used commonly for Bro development. - -extract-conn-by-uid: - Extracts a connection from a trace file based - on its UID found in Bro's conn.log - -gen-mozilla-ca-list.rb - Generates list of Mozilla SSL root certificates in - a format readable by Bro. - -update-changes - A script to maintain the CHANGES and VERSION files. - -git-show-fastpath - Show commits to the fastpath branch not yet merged into master. - -cpu-bench-with-trace - Run a number of Bro benchmarks on a trace file. - - -nftools -======= - -Utilities for dealing with Bro's custom file format for storing -NetFlow records. nfcollector reads NetFlow data from a socket and -writes it in Bro's format. ftwire2bro reads NetFlow "wire" format -(e.g., as generated by a 'flow-export' directive) and writes it in -Bro's format. - -rst -=== - -Makefile and source for the rst utility. "rst" can be invoked by -a Bro script to terminate an established TCP connection by forging -RST tear-down packets. See terminate_connection() in conn.bro. diff --git a/doc/components/bro-aux/README.rst b/doc/components/bro-aux/README.rst new file mode 120000 index 0000000000..628879525d --- /dev/null +++ b/doc/components/bro-aux/README.rst @@ -0,0 +1 @@ +../../../aux/bro-aux/README \ No newline at end of file diff --git a/doc/components/broccoli-python/README.rst b/doc/components/broccoli-python/README.rst deleted file mode 100644 index b2203a906a..0000000000 --- a/doc/components/broccoli-python/README.rst +++ /dev/null @@ -1,231 +0,0 @@ -.. -*- mode: rst-mode -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 0.54 - -============================ -Python Bindings for Broccoli -============================ - -.. rst-class:: opening - - This Python module provides bindings for Broccoli, Bro's client - communication library. In general, the bindings provide the same - functionality as Broccoli's C API. - -.. contents:: - - -Download --------- - -You can find the latest Broccoli-Python release for download at -http://www.bro.org/download. - -Broccoli-Python's git repository is located at `git://git.bro.org/broccoli-python.git -`__. You can browse the repository -`here `__. - -This document describes Broccoli-Python |version|. See the ``CHANGES`` -file for version history. - - -Installation ------------- - -Installation of the Python module is pretty straight-forward. After -Broccoli itself has been installed, it follows the standard installation -process for Python modules:: - - python setup.py install - -Try the following to test the installation. If you do not see any -error message, everything should be fine:: - - python -c "import broccoli" - -Usage ------ - -The following examples demonstrate how to send and receive Bro -events in Python. - -The main challenge when using Broccoli from Python is dealing with -the data types of Bro event parameters as there is no one-to-one -mapping between Bro's types and Python's types. The Python modules -automatically maps between those types which both systems provide -(such as strings) and provides a set of wrapper classes for Bro -types which do not have a direct Python equivalent (such as IP -addresses). - -Connecting to Bro -~~~~~~~~~~~~~~~~~ - -The following code sets up a connection from Python to a remote Bro -instance (or another Broccoli) and provides a connection handle for -further communication:: - - from broccoli import * - bc = Connection("127.0.0.1:47758") - -An ``IOError`` will be raised if the connection cannot be established. - -Sending Events -~~~~~~~~~~~~~~ - -Once you have a connection handle ``bc`` set up as shown above, you can -start sending events:: - - bc.send("foo", 5, "attack!") - -This sends an event called ``foo`` with two parameters, ``5`` and -``attack!``. Broccoli operates asynchronously, i.e., events scheduled -with ``send()`` are not always sent out immediately but might be -queued for later transmission. To ensure that all events get out -(and incoming events are processed, see below), you need to call -``bc.processInput()`` regularly. - -Data Types -~~~~~~~~~~ - -In the example above, the types of the event parameters are -automatically derived from the corresponding Python types: the first -parameter (``5``) has the Bro type ``int`` and the second one -(``attack!``) has Bro type ``string``. - -For types which do not have a Python equivalent, the ``broccoli`` -module provides wrapper classes which have the same names as the -corresponding Bro types. For example, to send an event called ``bar`` -with one ``addr`` argument and one ``count`` argument, you can write:: - - bc.send("bar", addr("192.168.1.1"), count(42)) - -The following table summarizes the available atomic types and their -usage. - -======== =========== =========================== -Bro Type Python Type Example -======== =========== =========================== -addr ``addr("192.168.1.1")`` -bool bool ``True`` -count ``count(42)`` -double float ``3.14`` -enum Type currently not supported -int int ``5`` -interval ``interval(60)`` -net Type currently not supported -port ``port("80/tcp")`` -string string ``"attack!"`` -subnet ``subnet("192.168.1.0/24")`` -time ``time(1111111111.0)`` -======== =========== =========================== - -The ``broccoli`` module also supports sending Bro records as event -parameters. To send a record, you first define a record type. For -example, a Bro record type:: - - type my_record: record { - a: int; - b: addr; - c: subnet; - }; - -turns into Python as:: - - my_record = record_type("a", "b", "c") - -As the example shows, Python only needs to know the attribute names -but not their types. The types are derived automatically in the same -way as discussed above for atomic event parameters. - -Now you can instantiate a record instance of the newly defined type -and send it out:: - - rec = record(my_record) - rec.a = 5 - rec.b = addr("192.168.1.1") - rec.c = subnet("192.168.1.0/24") - bc.send("my_event", rec) - -.. note:: The Python module does not support nested records at this time. - -Receiving Events -~~~~~~~~~~~~~~~~ - -To receive events, you define a callback function having the same -name as the event and mark it with the ``event`` decorator:: - - @event - def foo(arg1, arg2): - print arg1, arg2 - -Once you start calling ``bc.processInput()`` regularly (see above), -each received ``foo`` event will trigger the callback function. - -By default, the event's arguments are always passed in with built-in -Python types. For Bro types which do not have a direct Python -equivalent (see table above), a substitute built-in type is used -which corresponds to the type the wrapper class' constructor expects -(see the examples in the table). For example, Bro type ``addr`` is -passed in as a string and Bro type ``time`` is passed in as a float. - -Alternatively, you can define a _typed_ prototype for the event. If you -do so, arguments will first be type-checked and then passed to the -call-back with the specified type (which means instances of the -wrapper classes for non-Python types). Example:: - - @event(count, addr) - def bar(arg1, arg2): - print arg1, arg2 - -Here, ``arg1`` will be an instance of the ``count`` wrapper class and -``arg2`` will be an instance of the ``addr`` wrapper class. - -Protoyping works similarly with built-in Python types:: - - @event(int, string): - def foo(arg1, arg2): - print arg1, arg2 - -In general, the prototype specifies the types in which the callback -wants to receive the arguments. This actually provides support for -simple type casts as some types support conversion to into something -different. If for instance the event source sends an event with a -single port argument, ``@event(port)`` will pass the port as an -instance of the ``port`` wrapper class; ``@event(string)`` will pass it -as a string (e.g., ``"80/tcp"``); and ``@event(int)`` will pass it as an -integer without protocol information (e.g., just ``80``). If an -argument cannot be converted into the specified type, a ``TypeError`` -will be raised. - -To receive an event with a record parameter, the record type first -needs to be defined, as described above. Then the type can be used -with the ``@event`` decorator in the same way as atomic types:: - - my_record = record_type("a", "b", "c") - @event(my_record) - def my_event(rec): - print rec.a, rec.b, rec.c - -Helper Functions ----------------- - -The ``broccoli`` module provides one helper function: ``current_time()`` -returns the current time as a float which, if necessary, can be -wrapped into a ``time`` parameter (i.e., ``time(current_time()``) - -Examples --------- - -There are some example scripts in the ``tests/`` subdirectory of the -``broccoli-python`` repository -`here `_: - - - ``broping.py`` is a (simplified) Python version of Broccoli's test program - ``broping``. Start Bro with ``broping.bro``. - - - ``broping-record.py`` is a Python version of Broccoli's ``broping`` - for records. Start Bro with ``broping-record.bro``. - - - ``test.py`` is a very ugly but comprehensive regression test and part of - the communication test-suite. Start Bro with ``test.bro``. diff --git a/doc/components/broccoli-python/README.rst b/doc/components/broccoli-python/README.rst new file mode 120000 index 0000000000..4187e87202 --- /dev/null +++ b/doc/components/broccoli-python/README.rst @@ -0,0 +1 @@ +../../../aux/broccoli/bindings/broccoli-python/README \ No newline at end of file diff --git a/doc/components/broccoli-ruby/README.rst b/doc/components/broccoli-ruby/README.rst deleted file mode 100644 index 647a568cd8..0000000000 --- a/doc/components/broccoli-ruby/README.rst +++ /dev/null @@ -1,67 +0,0 @@ -.. -*- mode: rst-mode -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 1.54 - -=============================================== -Ruby Bindings for Broccoli -=============================================== - -.. rst-class:: opening - - This is the broccoli-ruby extension for Ruby which provides access - to the Broccoli API. Broccoli is a library for - communicating with the Bro Intrusion Detection System. - - -Download -======== - -You can find the latest Broccoli-Ruby release for download at -http://www.bro.org/download. - -Broccoli-Ruby's git repository is located at `git://git.bro.org/broccoli-ruby.git -`__. You can browse the repository -`here `__. - -This document describes Broccoli-Ruby |version|. See the ``CHANGES`` -file for version history. - - -Installation -============ - -To install the extension: - -1. Make sure that the ``broccoli-config`` binary is in your path. - (``export PATH=/usr/local/bro/bin:$PATH``) - -2. Run ``sudo ruby setup.rb``. - -To install the extension as a gem (suggested): - -1. Install `rubygems `_. - -2. Make sure that the ``broccoli-config`` binary is in your path. - (``export PATH=/usr/local/bro/bin:$PATH``) - -3. Run, ``sudo gem install rbroccoli``. - -Usage -===== - -There aren't really any useful docs yet. Your best bet currently is -to read through the examples. - -One thing I should mention however is that I haven't done any optimization -yet. You may find that if you write code that is going to be sending or -receiving extremely large numbers of events, that it won't run fast enough and -will begin to fall behind the Bro server. The dns_requests.rb example is -a good performance test if your Bro server is sitting on a network with many -dns lookups. - -Contact -======= - -If you have a question/comment/patch, see the Bro `contact page -`_. diff --git a/doc/components/broccoli-ruby/README.rst b/doc/components/broccoli-ruby/README.rst new file mode 120000 index 0000000000..da71663099 --- /dev/null +++ b/doc/components/broccoli-ruby/README.rst @@ -0,0 +1 @@ +../../../aux/broccoli/bindings/broccoli-ruby/README \ No newline at end of file diff --git a/doc/components/broccoli/README.rst b/doc/components/broccoli/README.rst deleted file mode 100644 index 4860324292..0000000000 --- a/doc/components/broccoli/README.rst +++ /dev/null @@ -1,141 +0,0 @@ -.. -*- mode: rst-mode -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 1.92-9 - -=============================================== -Broccoli: The Bro Client Communications Library -=============================================== - -.. rst-class:: opening - - Broccoli is the "Bro client communications library". It allows you - to create client sensors for the Bro intrusion detection system. - Broccoli can speak a good subset of the Bro communication protocol, - in particular, it can receive Bro IDs, send and receive Bro events, - and send and receive event requests to/from peering Bros. You can - currently create and receive values of pure types like integers, - counters, timestamps, IP addresses, port numbers, booleans, and - strings. - - -Download --------- - -You can find the latest Broccoli release for download at -http://www.bro.org/download. - -Broccoli's git repository is located at -`git://git.bro.org/broccoli `_. You -can browse the repository `here `_. - -This document describes Broccoli |version|. See the ``CHANGES`` -file for version history. - - -Installation ------------- - -The Broccoli library has been tested on Linux, the BSDs, and Solaris. -A Windows build has not currently been tried but is part of our future -plans. If you succeed in building Broccoli on other platforms, let us -know! - - -Prerequisites -------------- - -Broccoli relies on the following libraries and tools, which need to be -installed before you begin: - - Flex (Fast Lexical Analyzer) - Flex is already installed on most systems, so with luck you - can skip having to install it yourself. - - Bison (GNU Parser Generator) - This comes with many systems, but if you get errors compiling - parse.y, you will need to install it. - - OpenSSL headers and libraries - For encrypted communication. These are likely installed, - though some platforms may require installation of a 'devel' - package for the headers. - - CMake 2.6.3 or greater - CMake is a cross-platform, open-source build system, typically - not installed by default. See http://www.cmake.org for more - information regarding CMake and the installation steps below - for how to use it to build this distribution. CMake generates - native Makefiles that depend on GNU Make by default. - -Broccoli can also make use of some optional libraries if they are found at -installation time: - -Libpcap headers and libraries - Network traffic capture library - - -Installation ------------- - -To build and install into ``/usr/local``:: - - ./configure - make - make install - -This will perform an out-of-source build into the build directory using the -default build options and then install libraries into ``/usr/local/lib``. - -You can specify a different installation directory with:: - - ./configure --prefix= - -Or control the python bindings install destination more precisely with:: - - ./configure --python-install-dir= - -Run ``./configure --help`` for more options. - - -Further notable configure options: - - ``--enable-debug`` - This one enables lots of debugging output. Be sure to disable - this when using the library in a production environment! The - output could easily end up in undersired places when the stdout - of the program you've instrumented is used in other ways. - - ``--with-configfile=FILE`` - Broccoli can read key/value pairs from a config file. By default - it is located in the etc directory of the installation root - (exception: when using ``--prefix=/usr``, ``/etc`` is used - instead of /usr/etc). The default config file name is - broccoli.conf. Using ``--with-configfile``, you can override the - location and name of the config file. - -To use the library in other programs & configure scripts, use the -``broccoli-config`` script. It gives you the necessary configuration flags -and linker flags for your system, see ``--cflags`` and ``--libs``. - -The API is contained in broccoli.h and pretty well documented. A few -usage examples can be found in the test directory, in particular, the -``broping`` tool can be used to test event transmission and reception. Have -a look at the policy file ``broping.bro`` for the events that need to be -defined at the peering Bro. Try ``broping -h`` for a look at the available -options. - -Broccoli knows two kinds of version numbers: the release version number -(as in "broccoli-x.y.tar.gz", or as shipped with Bro) and the shared -library API version number (as in libbroccoli.so.3.0.0). The former -relates to changes in the tree, the latter to compatibility changes in -the API. - -Comments, feedback and patches are appreciated; please check the `Bro -website `_. - -Documentation -------------- - -Please see the `Broccoli User Manual <./broccoli-manual.html>`_ and -the `Broccoli API Reference <../../broccoli-api/index.html>`_. diff --git a/doc/components/broccoli/README.rst b/doc/components/broccoli/README.rst new file mode 120000 index 0000000000..d32c70ccd9 --- /dev/null +++ b/doc/components/broccoli/README.rst @@ -0,0 +1 @@ +../../../aux/broccoli/README \ No newline at end of file diff --git a/doc/components/broccoli/broccoli-manual.rst b/doc/components/broccoli/broccoli-manual.rst deleted file mode 100644 index 4d3c8ec79f..0000000000 --- a/doc/components/broccoli/broccoli-manual.rst +++ /dev/null @@ -1,1355 +0,0 @@ -=============================================== -Broccoli: The Bro Client Communications Library -=============================================== - -This page documents Broccoli, the Bro client communications library. -It allows you to create client sensors for the Bro intrusion detection -system. Broccoli can speak a good subset of the Bro communication -protocol, in particular, it can receive Bro IDs, send and receive Bro -events, and send and receive event requests to/from peering Bros. - -.. contents:: - -Introduction -############ - -What is Broccoli? -================= - -Broccoli is the BRO Client COmmunications LIbrary. It allows you to -write applications that speak the communication protocol of the `Bro -intrusion detection system `_. - -Broccoli is free software under terms of the BSD license as given in the -COPYING file distributed with its source code. - -In this document, we assume that you are familiar with the basic -concepts of Bro, so please first review the documentation/publications -available from the Bro website if necessary. - -Feedback, patches and bug reports are all welcome, please see -http://www.bro.org/community for instructions on how to participate -in the Bro community. - -Why do I care? -============== - -Having a single IDS on your network is good, but things become a lot -more interesting when you can communicate information among multiple -vantage points in your network. Bro agents can communicate with other -Bro agents, sending and receiving events and other state information. In -the Bro context this is particularly interesting because it means that -you can build sophisticated policy-controlled distributed event -management systems. - -Broccoli enters the picture when it comes to integrating components that -are not Bro agents themselves. Broccoli lets you create applications -that can speak the Bro communication protocol. You can compose, send, -request, and receive events. You can register your own event handlers. -You can talk to other Broccoli applications or Bro agents -- Bro agents -cannot tell whether they are talking to another Bro or a Broccoli -application. Broccoli allows you to integrate applications of your -choosing into a distributed policy-controlled event management system. -Broccoli is intended to be portable: it should build on Linux, the BSDs, -Solaris, and Windows (in the `MinGW `_ -environment). - -Unlike other distributed IDSs, Bro does not assume a strict -sensor-manager hierarchy in the information flow. Instead, Bro agents -can request delivery of arbitrary *events* from other instances. When -an event is triggered in a Bro agent, it checks whether any connected -agents have requested notification of this event, and sends a *copy* of -the event, including the *event arguments*. Recall that in Bro, an -event handler is essentially a function defined in the Bro language, -and an event materializes through invocation of an event handler. Each -remote agent can define its own event handlers. - -Broccoli applications will typically do one or more of the following: - -- *Configuration/Management Tasks:* the Broccoli application - is used to configure remotely running Bros without the need for a - restart. - -- *Interfacing with other Systems:* the Broccoli application - is used to convert Bro events to other alert/notice formats, or into - syslogd entries. - -- *Host-based Sensor Feeds into Bro:* the Broccoli - application reports events based on host-based activity generated in - kernel space or user space applications. - -Installing Broccoli -################### - -The installation process will hopefully be painless: Broccoli is -installed from source using the usual ``./configure && make && -make install`` routine after extraction of the tarball. - -Some relevant configuration options to pass to configure are: - -- ``--prefix=``: sets the installation root to DIR. - The default is to install below ``/usr/local``. - -- ``--enable-debug``: enables debugging output. - Please refer to the `Configuring Debugging Output`_ section for - details on configuring and using debugging output. - -- ``--with-configfile=``: use FILE as location of configuration - file. See the section on `Configuration Files`_ for more on this. - -- ``--with-openssl=``: use the OpenSSL installation below DIR. - -After installation, you'll find the library in shared and static -versions in ``/lib``, the header file for compilation in -``/include``. - -Using Broccoli -############## - -Obtaining information about your build using ``broccoli-config`` -================================================================ - -Similarly to many other software packages, the Broccoli distribution -provides a script that you can use to obtain details about your Broccoli -setup. The script currently provides the following flags: - -- ``--build`` prints the name of the machine the build was - made on, when, and whether debugging support was enabled or not. - -- ``--prefix`` prints the directory in the filesystem - below which Broccoli was installed. - -- ``--version`` prints the version of the distribution - you have installed. - -- ``--libs`` prints the flags to pass to the - linker in order to link in the Broccoli library. - -- ``--cflags`` prints the flags to pass to the - compiler in order to properly include Broccoli's header file. - -- ``--config`` prints the location of the system-wide - config file your installation will use. - -The ``--cflags`` and ``--libs`` flags are the suggested way of obtaining -the necessary information for integrating Broccoli into your build -environment. It is generally recommended to use ``broccoli-config`` for -this purpose, rather than, say, develop new **autoconf** tests. If you -use the **autoconf/automake** tools, we recommend something along the -following lines for your ``configure`` script:: - - dnl ################################################## - dnl # Check for Broccoli - dnl ################################################## - AC_ARG_WITH(broccoli-config, - AC_HELP_STRING(\[--with-broccoli-config=FILE], \[Use given broccoli-config]), - [ brocfg="$withval" ], - [ AC_PATH_GENERIC(broccoli,, - brocfg="broccoli-config", - AC_MSG_ERROR(Cannot find Broccoli: Is broccoli-config in path? Use more fertilizer?)) ]) - - broccoli_libs=`$brocfg --libs` - broccoli_cflags=`$brocfg --cflags` - AC_SUBST(broccoli_libs) - AC_SUBST(broccoli_cflags)`` - -You can then use the compiler/linker flags in your Makefile.in/ams by -substituting in the values accordingly, which might look as follows:: - - CFLAGS = -W -Wall -g -DFOOBAR @broccoli_cflags@ - LDFLAGS = -L/usr/lib/foobar @broccoli_libs@ - -Suggestions for instrumenting applications -========================================== - -Often you will want to make existing applications Bro-aware, that is, -*instrument* them so that they can send and receive Bro events at -appropriate moments in the execution flow. This will involve modifying -an existing code tree, so care needs to be taken to avoid unwanted side -effects. By protecting the instrumented code with ``#ifdef``/``#endif`` -statements you can still build the original application, using the -instrumented source tree. The ``broccoli-config`` script helps you in -doing so because it already adds ``-DBROCCOLI`` to the compiler flags -reported when run with the ``--cflags`` option: - -.. console:: - - > broccoli-config --cflags - -I/usr/local/include -I/usr/local/include -DBROCCOLI - -So simply surround all inserted code with a preprocessor check for -``BROCCOLI`` and you will be able to build the original application as -soon as ``BROCCOLI`` is not defined. - -The Broccoli API -================ - -Time for some code. In the code snippets below we will introduce variables -whenever context requires them and not necessarily when C requires them. -The library does not require calling a global initialization function. -In order to make the API known, include ``broccoli.h``: - -.. code:: c - - #ifdef BROCCOLI - #include - #endif - -.. note:: - *Broccoli's memory management philosophy:* - - Broccoli generally does not release objects you allocate. - The approach taken is "you clean up what you allocate." - -Initialization --------------- - -Broccoli requires global initialization before most of its other -functions can be used. Generally, the way to initialize Broccoli is as -follows: - -.. code:: c - - bro_init(NULL); - -The argument to ``bro_init()`` provides optional initialization context, -and may be kept ``NULL`` for normal use. If required, you may allocate a -``BroCtx`` structure locally, initialize it using ``bro_ctx_init()``, -fill in additional values as required and subsequently pass it to -``bro_init()``: - -.. code:: c - - BroCtx ctx; - bro_ctx_init(&ctx); - /* Make adjustments to the context structure as required...*/ - bro_init(&ctx); - -.. note:: The ``BroCtx`` structure currently contains a set of five - different callback function pointers. These are *required* for - thread-safe operation of OpenSSL (Broccoli itself is thread-safe). - If you intend to use Broccoli in a multithreaded environment, you - need to implement functions and register them via the ``BroCtx`` - structure. The O'Reilly book "Network Security with OpenSSL" by - Viega et al. shows how to implement these callbacks. - -.. warning:: You *must* call ``bro_init()`` at the start of your - application. Undefined behavior may result if you don't. - -Data types in Broccoli ----------------------- - -Broccoli declares a number of data types in ``broccoli.h`` that you -should know about. The more complex ones are kept opaque, while you do -get access to the fields in the simpler ones. The full list is as -follows: - -- Simple signed and unsigned types: int, uint, uint16, uint32, uint64 - and uchar. - -- Connection handles: BroConn, kept opaque. - -- Bro events: BroEvent, kept opaque. - -- Buffer objects: BroBuf, kept opaque. See also `Using Dynamic - Buffers`_. - -- Ports: BroPort for network ports, defined as follows: - - .. code:: c - - typedef struct bro_port { - uint16 port_num; /* port number in host byte order */ - int port_proto; /* IPPROTO_xxx */ - } BroPort; - -- Records: BroRecord, kept opaque. See also `Handling Records`_. - -- Strings (character and binary): BroString, defined as follows: - - .. code:: c - - typedef struct bro_string { - int str_len; - char str_val; - } BroString; - -- BroStrings are mostly kept transparent for convenience; please have a - look at the `Broccoli API Reference`_. - -- Tables: BroTable, kept opaque. See also `Handling Tables`_. - -- Sets: BroSet, kept opaque. See also `Handling Sets`_. - -- IP Address: BroAddr, defined as follows: - - .. code:: c - - typedef struct bro_addr { - uint32 addr[4]; /* IP address in network byte order */ - int size; /* Number of 4-byte words occupied in addr */ - } BroAddr; - - Both IPv4 and IPv6 addresses are supported, with the former occupying - only the first 4 bytes of the ``addr`` array. - -- Subnets: BroSubnet, defined as follows: - - .. code:: c - - typedef struct bro_subnet { - BroAddr sn_net; /* IP address in network byte order */ - uint32 sn_width; /* Length of prefix to consider. */ - } BroSubnet; - -Managing Connections --------------------- - -You can use Broccoli to establish a connection to a remote Bro, or to -create a Broccoli-enabled server application that other Bros will -connect to (this means that in principle, you can also use Broccoli -purely as middleware and have multiple Broccoli applications communicate -directly). - -In order to establish a connection to a remote Bro, you first obtain a -connection handle. You then use this connection handle to request -events, connect to the remote Bro, send events, etc. Connection handles -are pointers to ``BroConn`` structures, which are kept opaque. Use -``bro_conn_new()`` or ``bro_conn_new_str()`` to obtain a handle, -depending on what parameters are more convenient for you: the former -accepts the IP address and port number as separate numerical arguments, -the latter uses a single string to encode both, in "hostname:port" -format. - -To write a Broccoli-enabled server, you first need to implement the -usual ``socket()`` / ``bind()`` / ``listen()`` / ``accept()`` routine. -Once you have obtained a file descriptor for the new connection from -``accept()``, you pass it to the third function that returns a -``BroConn`` handle, ``bro_conn_new_socket()``. The rest of the -connection handling then proceeds as in the client scenario. - -All three calls accept additional flags for fine-tuning connection -behaviour. These flags are: - -- ``BRO_CFLAG_NONE``: no functionality. Use when no flags are desired. - -- ``BRO_CFLAG_RECONNECT``: - When using this option, Broccoli will attempt to reconnect to the peer - transparently after losing connectivity. Essentially whenever you try to - read from or write to the peer and its connection has broke down, a full - reconnect including complete handshaking is attempted. You can check - whether the connection to a peer is alive at any time using - ``bro_conn_alive()``. - -- ``BRO_CFLAG_ALWAYS_QUEUE``: - When using this option, Broccoli will queue any events you send for - later transmission when a connection is currently down. Without using - this flag, any events you attempt to send while a connection is down - get dropped on the floor. Note that Broccoli maintains a maximum queue - size per connection so if you attempt to send lots of events while the - connection is down, the oldest events may start to get dropped - nonetheless. Again, you can check whether the connection is currently - okay by using ``bro_conn_alive()``. - -- ``BRO_CFLAG_DONTCACHE``: - When using this option, Broccoli will ask the peer not to use caching - on the objects it sends to us. This is the default, and the flag need - not normally be used. It is kept to maintain backward compatibility. - -- ``BRO_CFLAG_CACHE``: - When using this option, Broccoli will ask the peer to use caching on - the objects it sends to us. Caching is normally disabled. - -- ``BRO_CFLAG_YIELD``: - When using this option, ``bro_conn_process_input()`` processes at most - one event at a time and then returns. - -By obtaining a connection handle, you do not also establish a connection -right away. This is done using ``bro_conn_connect()``. The main reason -for this is to allow you to subscribe to events (using -``bro_event_registry_add()``, see `Receiving Events`_) before -establishing the connection. Upon returning from ``bro_conn_connect()`` -you are guaranteed to receive all instances of the event types you have -requested, while later on during the connection some time may elapse -between the issuing of a request for events and the processing of that -request at the remote end. Connections are established via TCP, -optionally using SSL encryption. See "`Configuring Encrypted -Communication`_", for more information on setting up encryption. The -port numbers Bro agents and Broccoli applications listen on can vary -from peer to peer. - -Finally, ``bro_conn_delete()`` terminates a connection and releases all -resources associated with it. You can create as many connections as you -like, to one or more peers. You can obtain the file descriptor of a -connection using ``bro_conn_get_fd()``: - -.. code:: c - - char host_str = "bro.yourorganization.com"; - int port = 1234; - struct hostent *host; - BroConn *bc; - - if (! (host = gethostbyname(host_str)) || ! - (host->h_addr_list[0])) - { - /* Error handling -- could not resolve host */ - } - - /* In this example, we obtain a connection handle, then register - event handlers, and finally connect to the remote Bro. */ - /* First obtain a connection handle: */ - if (! (bc = bro_conn_new((struct in_addr*) host->h_addr_list[0], - htons(port), BRO_CFLAG_NONE))) - { - /* Error handling - could not get connection handle */ - } - - /* Register event handlers: */ - bro_event_registry_add(bc, "foo", bro_foo_handler, NULL); - /* ... */ - - /* Now connect to the peer: */ - if (! bro_conn_connect(bc)) - { - /* Error handling - could not connect to remote Bro. */ - } - - /* Send and receive events ... */ - - /* Disconnect from Bro and clean up connection */ - bro_conn_delete(bc); - -Or simply use the string-based version: - -.. code:: c - - char host_str = "bro.yourcompany.com:1234"; - BroConn bc; - - /* In this example we don't request any events from the peer, - but we ask it not to use the serialization cache. */ - /* Again, first obtain a connection handle: */ - if (! (bc = bro_conn_new_str(host_str, BRO_CFLAG_DONTCACHE))) - { - /* Error handling - could not get connection handle */ - } - - /* Now connect to the peer: */ - if (! bro_conn_connect(bc)) - { - /* Error handling - could not connect to remote Bro. */ - } - - /* ... */ - -Connection Classes ------------------- - -When you want to establish connections from multiple Broccoli -applications with different purposes, the peer needs a means to -understand what kind of application each connection belongs to. The real -meaning of "kind of application" here is "sets of event types to -request", because depending on the class of an application, the peer -will likely want to receive different types of events. - -Broccoli lets you set the class of a connection using -``bro_conn_set_class()``. When using this feature, you need to call that -function before issuing a ``bro_conn_connect()`` since the class of a -connection is determined at connection startup: - -.. code:: c - - if (! (bc = bro_conn_new_str(host_str, BRO_CFLAG_DONTCACHE))) - { - /* Error handling - could not get connection handle */ - } - - /* Set class of this connection: */ - bro_conn_set_class(bc, "syslog"); - - if (! bro_conn_connect(bc)) - { - /* Error handling - could not connect to remote Bro. */ - } - -If your peer is a Bro node, you need to match the chosen connection -class in the remote Bro's ``Communication::nodes`` configuration. See -`Configuring event reception in Bro scripts`_, for how to do -this. Finally, in order to obtain the class of a connection as -indicated by the remote side, use ``bro_conn_get_peer_class()``. - -Composing and sending events ----------------------------- - -In order to send an event to the remote Bro agent, you first create an -empty event structure with the name of the event, then add parameters to -pass to the event handler at the remote agent, and then send off the -event. - -.. note: - *Bro peers ignore unrequested events.* - - You need to make sure that the remote Bro agent is interested in - receiving the events you send. This interest is expressed in policy - configuration. We'll explain this in more detail in `Configuring - event reception in Bro scripts`_, and for now assume that our - remote peer is configured to receive the events we send. - -Let's assume we want to request a report of all connections a remote Bro -currently keeps state for that match a given destination port and host -name and that have amassed more than a certain number of bytes. The -idea is to send an event to the remote Bro that contains the query, -identifiable through a request ID, and have the remote Bro answer us -with ``remote_conn`` events containing the information we asked for. The -definition of our requesting event could look as follows in the Bro -policy: - -.. code:: bro - - event report_conns(req_id: int, dest_host: string, - dest_port: port, min_size: count); - -First, create a new event: - -.. code:: c - - BroEvent *ev; - - if (! (ev = bro_event_new("report_conns"))) - { - /* Error handling - could not allocate new event. */ - } - -Now we need to add parameters to the event. The sequence and types must -match the event handler declaration -- check the Bro policy to make sure -they match. The function to use for adding parameter values is -``bro_event_add_val()``. All values are passed as *pointer arguments* -and are copied internally, so the object you're pointing to stays -unmodified at all times. You clean up what you allocate. In order to -indicate the type of the value passed into the function, you need to -pass a numerical type identifier along as well. Table-1_ lists the -value types that Broccoli supports along with the type identifier and -data structures to point to. - -.. _Table-1: - -Types, type tags, and data structures for event parameters in Broccoli -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -============================== ===================== ==================== -Type Type tag Data type pointed to -============================== ===================== ==================== -Boolean ``BRO_TYPE_BOOL`` ``int`` -Integer value ``BRO_TYPE_INT`` ``uint64`` -Counter (nonnegative integers) ``BRO_TYPE_COUNT`` ``uint64`` -Enums (enumerated values) ``BRO_TYPE_ENUM`` ``uint64`` (see also description of ``bro_event_add_val()``'s ``type_name`` argument) -Floating-point number ``BRO_TYPE_DOUBLE`` ``double`` -Timestamp ``BRO_TYPE_TIME`` ``double`` (see also ``bro_util_timeval_to_double()`` and ``bro_util_current_time()``) -Time interval ``BRO_TYPE_INTERVAL`` ``double`` -Strings (text and binary) ``BRO_TYPE_STRING`` ``BroString`` (see also family of ``bro_string_xxx()`` functions) -Network ports ``BRO_TYPE_PORT`` ``BroPort``, with the port number in host byte order -IPv4/IPv6 address ``BRO_TYPE_IPADDR`` ``BroAddr``, with the ``addr`` member in network byte order and ``size`` member indicating the address family and number of 4-byte words of ``addr`` that are occupied (1 for IPv4 and 4 for IPv6) -IPv4/IPv6 subnet ``BRO_TYPE_SUBNET`` ``BroSubnet``, with the ``sn_net`` member in network byte order -Record ``BRO_TYPE_RECORD`` ``BroRecord`` (see also the family of ``bro_record_xxx()`` functions and their explanation below) -Table ``BRO_TYPE_TABLE`` ``BroTable`` (see also the family of ``bro_table_xxx()`` functions and their explanation below) -Set ``BRO_TYPE_SET`` ``BroSet`` (see also the family of ``bro_set_xxx()`` functions and their explanation below) -============================== ===================== ==================== - -Knowing these, we can now compose a ``request_connections`` event: - -.. code:: c - - BroString dest_host; - BroPort dest_port; - uint32 min_size; - int req_id = 0; - - bro_event_add_val(ev, BRO_TYPE_INT, NULL, &req_id); - req_id++; - - bro_string_set(&dest_host, "desthost.destdomain.com"); - bro_event_add_val(ev, BRO_TYPE_STRING, NULL, &dest_host); - bro_string_cleanup(&dest_host); - - dest_port.dst_port = 80; - dest_port.dst_proto = IPPROTO_TCP; - bro_event_add_val(ev, BRO_TYPE_PORT, NULL, &dest_port); - - min_size = 1000; bro_event_add_val(ev, BRO_TYPE_COUNT, NULL, &min_size); - -The third argument to ``bro_event_add_val()`` lets you specify a -specialization of the types listed in Table-1_. This is generally not -necessary except for one situation: when using ``BRO_TYPE_ENUM``. You -currently cannot define a Bro-level enum type in Broccoli, and thus when -sending an enum value, you have to specify the type of the enum along -with the value. For example, in order to add an instance of enum -``transport_type`` defined in Bro's ``bro.init``, you would use: - -.. code:: c - - int transport_proto = 2; - /* ... */ - bro_event_add_val(ev, BRO_TYPE_ENUM, "transport_proto", &transport_proto); - -to get the equivalent of "udp" on the remote side. The same system is -used to point out type names when calling ``bro_event_set_val()``, -``bro_record_add_val()``, ``bro_record_set_nth_val()``, and -``bro_record_set_named_val()``. - -All that's left to do now is to send off the event. For this, use -``bro_event_send()`` and pass it the connection handle and the event. -The function returns ``TRUE`` when the event could be sent right away or -if it was queued for later delivery. ``FALSE`` is returned on error. If -the event gets queued, this does not indicate an error -- likely the -connection was just not ready to send the event at this point. Whenever -you call ``bro_event_send()``, Broccoli attempts to send as much of an -existing event queue as possible. Again, the event is copied internally -to make it easier for you to send the same event repeatedly. You clean -up what you allocate: - -.. code:: c - - bro_event_send(bc, ev); - bro_event_free(ev); - -Two other functions may be useful to you: ``bro_event_queue_length()`` -tells you how many events are currently queued, and -``bro_event_queue_flush()`` attempts to flush the current event queue -and returns the number of events that do remain in the queue after the -flush. - -.. note:: you do not normally need to call this function, queue - flushing is attempted every time you send an event. - -Receiving Events ----------------- - -Receiving events is a little more work because you need to - -1. tell Broccoli what to do when requested events arrive, - -#. let the remote Bro agent know that you would like to receive those - events, - -#. find a spot in the code path suitable for extracting and processing - arriving events. - -Each of these steps is explained in the following sections. - -Implementing event callbacks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When Broccoli receives an event, it tries to dispatch the event to -callbacks registered for that event type. The place where callbacks get -registered is called the callback registry. Any callbacks registered for -the arriving event's name are invoked with the parameters shipped with -the event. There are two styles of argument passing to the event -callbacks. Which one is better suited depends on your application. - -Expanded Argument Passing -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Each event argument is passed via a pointer to the callback. This makes -best sense when you know the type of the event and of its arguments, -because it provides you immediate access to arguments as when using a -normal C function. - -In order to register a callback with expanded argument passing, use -``bro_event_registry_add()`` and pass it the connection handle, the name -of the event for which you register the callback, the callback itself -that matches the signature of the ``BroEventFunc`` type, and any user -data (or ``NULL``) you want to see passed to the callback on each -invocation. The callback's type is defined rather generically as -follows: - -.. code:: c - - typedef void (*BroEventFunc) (BroConn *bc, void *user_data, ...); - -It requires a connection handle as its first argument and a pointer to -user-provided callback data as the second argument. Broccoli will pass -the connection handle of the connection on which the event arrived -through to the callback. ``BroEventFunc``'s are variadic, because each -callback you provide is directly invoked with pointers to the parameters -of the event, in a format directly usable in C. All you need to know is -what type to point to in order to receive the parameters in the right -layout. Refer to Table-1_ again for a summary of those types. Record -types are more involved and are addressed in more detail in `Handling -Records`_. - -.. note:: Note that *all* parameters are passed to the - callback as pointers, even elementary types such as ``int`` that - would normally be passed directly. Also note that Broccoli manages - the lifecycle of event parameters and therefore you do *not* have - to clean them up inside the event handler. - -Continuing our example, we will want to process the connection reports -that contain the responses to our ``report_conns`` event. Let's assume -those look as follows: - -.. code:: bro - - event remote_conn(req_id: int, conn: connection); - -The reply events contain the request ID so we can associate requests -with replies, and a connection record (defined in ``bro.init`` in Bro). -(It'd be nicer to report all replies in a single event but we'll -ignore that for now.) For this event, our callback would look like -this: - -.. code:: c - - void remote_conn_cb(BroConn *bc, void *user_data, int *req_id, - BroRecord *conn); - -Once more, you clean up what you allocate, and since you never allocated -the space these arguments point to, you also don't clean them up. -Finally, we register the callback using ``bro_event_registry_add()``: - -.. code:: c - - bro_event_registry_add(bc, "remote_conn", remote_conn_cb, NULL); - -In this case we have no additional data to be passed into the callback, -so we use ``NULL`` for the last argument. If you have multiple events -you are interested in, register each one in this fashion. - -Compact Argument Passing -^^^^^^^^^^^^^^^^^^^^^^^^ - -This is designed for situations when you have to determine how to handle -different types of events at runtime, for example when writing language -bindings or when implementing generic event handlers for multiple event -types. The callback is passed a connection handle and the user data as -above but is only passed one additional pointer, to a BroEvMeta -structure. This structure contains all metadata about the event, -including its name, timestamp (in UTC) of creation, number of arguments, -the arguments' types (via type tags as listed in Table-1_), and the -arguments themselves. - -In order to register a callback with compact argument passing, use -``bro_event_registry_add_compact()`` and pass it similar arguments as -you'd use with ``bro_event_registry_add()``. The callback's type is -defined as follows: - -.. code:: c - - typedef void (*BroCompactEventFunc) (BroConn *bc, void *user_data, - BroEvMeta *meta); - - -.. note:: As before, Broccoli manages the lifecycle of event parameters. - You do not have to clean up the BroEvMeta structure or any of its - contents. - -Below is sample code for extracting the arguments from the BroEvMeta -structure, using our running example. This is still written with the -assumption that we know the types of the arguments, but note that this -is not a requirement for this style of callback: - -.. code:: c - - void remote_conn_cb(BroConn *bc, void *user_data, - BroEvMeta *meta) { - int *req_id; BroRecord *rec; - - /* For demonstration, print out the event's name: */ - - printf("Handling a %s event.\n", meta->ev_name); - - /* Sanity-check the number of arguments: */ - - if (meta->ev_numargs != 2) - { /* error */ } - - /* Sanity-check the argument types: */ - - if (meta->ev_args[0].arg_type != BRO_TYPE_INT) - { /* error */ } - - if (meta->ev_args[1].arg_type != BRO_TYPE_RECORD) - { /* error */ } - - req_id = (int *) meta->ev_args[0].arg_data; - rec = (BroRecord *) meta->ev_args[1].arg_data; - - /* ... */ - } - -Finally, register the callback using -``bro_event_registry_add_compact()``: - -.. code:: c - - bro_event_registry_add_compact(bc, "remote_conn", remote_conn_cb, NULL); - -Requesting event delivery -~~~~~~~~~~~~~~~~~~~~~~~~~ - -At this point, Broccoli knows what to do with the requested events upon -arrival. What's left to do is to let the remote Bro know that you would -like to receive the events for which you registered. If you haven't yet -called ``bro_conn_connect()``, then there is nothing to do, since that -function will request the registered events anyway. Once connected, you -can still request events. To do so, call -``bro_event_registry_request()``: - -.. code:: c - - bro_event_registry_request(bc); - -This mechanism also implies that no unrequested events will be delivered -to us (and if that happened for whatever reason, the event would simply -be dropped on the floor). - -.. note:: At the moment you cannot unrequest events, nor can you request - events based on predicates on the values of the events' arguments. - -Reading events from the connection handle -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -At this point the remote Bro will start sending you the requested events -once they are triggered. What is left to do is to read the arriving -events from the connection and trigger dispatching them to the -registered callbacks. - -If you are writing a new Bro-enabled application, this is easy, and you -can choose among two approaches: polling explicitly via Broccoli's API, -or using ``select()`` on the file handle associated with a BroConn. The -former case is particularly straightforward; all you need to do is call -``bro_conn_process_input()``, which will go off and check if any events -have arrived and if so, dispatch them accordingly. This function does -not block -- if no events have arrived, then the call will return -immediately. For more fine-grained control over your I/O handling, you -will probably want to use ``bro_conn_get_fd()`` to obtain the file -descriptor of your connection and then incorporate that in your standard -``FD_SET``/``select()`` code. Once you have determined that data in fact -are ready to be read from the obtained file descriptor, you can then try -another ``bro_conn_process_input()`` this time knowing that it'll find -something to dispatch. - -As a side note, if you don't process arriving events frequently enough, -then TCP's flow control will start to slow down the sender until -eventually events will queue up and be dropped at the sending end. - -Handling Records ----------------- - -Broccoli supports record structures, i.e., types that pack a set of -values together, placing each value into its own field. In Broccoli, the -way you handle records is somewhat similar to events: after creating an -empty record (of opaque type ``BroRecord``), you can iteratively add -fields and values to it. The main difference is that you must specify a -field name with the value; each value in a record can be identified both -by position (a numerical index starting from zero), and by field name. -You can retrieve vals in a record by field index or field name. You can -also reassign values. There is no explicit, IDL-style definition of -record types. You define the type of a record implicitly by the sequence -of field names and the sequence of the types of the values you put into -the record. - -Note that all fields in a record must be assigned before it can be -shipped. - -The API for record composition consists of ``bro_record_new()``, -``bro_record_free()``, ``bro_record_add_val()``, -``bro_record_set_nth_val()``, and ``bro_record_set_named_val()``. - -On records that use field names, the names of individual fields can be -extracted using ``bro_record_get_nth_name()``. Extracting values from a -record is done using ``bro_record_get_nth_val()`` and -``bro_record_get_named_val()``. The former allows numerical indexing of -the fields in the record, the latter provides name-based lookups. Both -need to be passed the record you want to extract a value from, the index -or name of the field, and either a pointer to an int holding a -BRO_TYPE_xxx value (see again Table-1_ for a summary of those types) or -``NULL``. The pointer, if not ``NULL``, serves two purposes: type -checking and type retrieval. Type checking is performed if the value of -the int upon calling the functions is not BRO_TYPE_UNKNOWN. The type tag -of the requested record field then has to match the type tag stored in -the int, otherwise ``NULL`` is returned. If the int stores -BRO_TYPE_UNKNOWN upon calling, no type-checking is performed. In *both* -cases, the *actual* type of the requested record field is returned in -the int pointed to upon return from the function. Since you have no -guarantees of the type of the value upon return if you pass ``NULL`` as -the int pointer, this is a bad idea and either BRO_TYPE_UNKNOWN or -another type value should always be used. - -For example, you could extract the value of the record field "label", -which we assume should be a string, in the following ways: - -.. code:: c - - BroRecord *rec = /* obtained somehow */ - BroString *string; - int type; - - /* --- Example 1 --- */ - - type = BRO_TYPE_STRING; - /* Use type-checking, will not accept other types */ - - if (! (string = bro_record_get_named_val(rec, "label", &type))) - { - /* Error handling, either there's no field of that value or - the value is not of BRO_TYPE_STRING. The actual type is now - stored in "type". */ - } - - /* --- Example 2 --- */ - - type = BRO_TYPE_UNKNOWN; - /* No type checking, just report the existent type */ - - if (! (string = bro_record_get_named_val(rec, "label", &type))) - { - /* Error handling, no field of that name exists. */ - } - - printf("The type of the value in field 'label' is %i\n", type); - - /* --- Example 3 --- */ - - if (! (string = bro_record_get_named_val(rec, "label", NULL))) - { - /* Error handling, no field of that name exists. */ - } - - /* We now have a value, but we can't really be sure of its type */ - -Record fields can be records, for example in the case of Bro's standard -connection record type. In this case, in order to get to a nested -record, you use ``BRO_TYPE_RECORD``: - -.. code:: c - - void remote_conn_cb(BroConn *bc, int *req_id, BroRecord *conn) - { - BroRecord *conn_id; - int type = BRO_TYPE_RECORD; - if ( ! (conn_id = bro_record_get_named_val(conn, "id", &type))) - { - /* Error handling */ - } - } - -Handling Tables ---------------- - -Broccoli supports Bro-style tables, i.e., associative containers that -map instances of a key type to an instance of a value type. A given key -can only ever point to a single value. The key type can be *composite*, -i.e., it may consist of an ordered sequence of different types, or it -can be *direct*, i.e., consisting of a single type (such as an integer, -a string, or a record). - -The API for table manipulation consists of ``bro_table_new()`` -``bro_table_free()``, ``bro_table_insert()``, ``bro_table_find()``, -``bro_table_get_size()``, ``bro_table_get_types()``, and -``bro_table_foreach()``. - -Tables are handled similarly to records in that typing is determined -dynamically by the initial key/value pair inserted. The resulting types -can be obtained via ``bro_table_get_types()``. Should the types not -have been determined yet, ``BRO_TYPE_UNKNOWN`` will result. Also, as -with records, values inserted into the table are copied internally, and -the ones passed to the insertion functions remain unaffected. - -In contrast to records, table entries can be iterated. By passing a -function of signature ``BroTableCallback()`` and a pointer to data of -your choosing, ``bro_table_foreach()`` will invoke the given function -for each key/value pair stored in the table. Return ``TRUE`` to keep -the iteration going, or ``FALSE`` to stop it. - -.. note:: - The main thing to know about Broccoli's tables is how to use - composite key types. To avoid additional API calls, you may treat - composite key types exactly as records, though you do not need to use - field names when assigning elements to individual fields. So in order - to insert a key/value pair, you create a record with the needed items - assigned to its slots, and use this record as the key object. In - order to differentiate composite index types from direct ones - consisting of a single record, use ``BRO_TYPE_LIST`` as the type of - the record, as opposed to ``BRO_TYPE_RECORD``. Broccoli will then - know to interpret the record as an ordered sequence of items making - up a composite element, not a regular record. - -``brotable.c`` in the ``test/`` subdirectory of the Broccoli tree -contains an extensive example of using tables with composite as well as -direct indexing types. - -Handling Sets -------------- - -Sets are essentially tables with void value types. The API for set -manipulation consists of ``bro_set_new()``, ``bro_set_free()``, -``bro_set_insert()``, ``bro_set_find()``, ``bro_set_get_size()``, -``bro_set_get_type()``, and ``bro_set_foreach()``. - -Associating data with connections ---------------------------------- - -You will often find that you would like to connect data with a -``BroConn``. Broccoli provides an API that lets you associate data items -with a connection handle through a string-based key-value registry. The -functions of interest are ``bro_conn_data_set()``, -``bro_conn_data_get()``, and ``bro_conn_data_del()``. You need to -provide a string identifier for a data item and can then use that string -to register, look up, and remove the associated data item. Note that -there is currently no mechanism to trigger a destructor function for -registered data items when the Bro connection is terminated. You -therefore need to make sure that all data items that you do not have -pointers to via some other means are properly released before calling -``bro_disconnect()``. - -Configuration Files -------------------- - -Imagine you have instrumented the mother of all server applications. -Building it takes forever, and every now and then you need to change -some of the parameters that your Broccoli code uses, such as the host -names of the Bro agents to talk to. To allow you to do this quickly, -Broccoli comes with support for configuration files. All you need to do -is change the settings in the file and restart the application (we're -considering adding support for volatile configuration items that are -read from the file every time they are requested). - -A configuration is read from a single configuration file. This file can -be read from different locations. Broccoli searches in this order -for the config file: - -- The location specified by the ``BROCCOLI_CONFIG_FILE`` environment - variable. - -- A per-user configuration file stored in ``~/.broccoli.conf``. - -- The system-wide configuration file. You can obtain the location - of this config file by running ``broccoli-config --config``. - -.. note:: ``BROCCOLI_CONFIG_FILE`` or ``~/.broccoli.conf`` will only be - used if it is a regular file, not executable, and neither group nor - others have any permissions on the file. That is, the file's - permissions must look like ``-rw-------`` *or* ``-r--------``. - -In the configuration file, a ``#`` anywhere starts a comment that runs to -the end of the line. Configuration items are specified as key-value -pairs:: - - # This is the Broccoli system-wide configuration file. - # - # Entries are of the form , where the - # identifier is a sequence of letters, and value can be a string - # (including whitespace), and floating point or integer numbers. - # Comments start with a "#" and go to the end of the line. For - # boolean values, you may also use "yes", "on", "true", "no", - # "off", or "false". Strings may contain whitespace, but need - # to be surrounded by double quotes '"'. - # - # Examples: - # - Foo/PeerName mybro.securesite.com - Foo/PortNum 123 - Bar/SomeFloat 1.23443543 - Bar/SomeLongStr "Hello World" - -You can also have multiple sections in your configuration. Your -application can select a section as the current one, and queries for -configuration settings will then only be answered with values specified -in that section. A section is started by putting its name (no whitespace -please) between square brackets. Configuration items positioned before -the first section title are in the default domain and will be used by -default:: - - # This section contains all settings for myapp. - [ myapp ] - -You can name identifiers any way you like, but to keep things organized -it is recommended to keep a namespace hierarchy similar to the file -system. In the code, you can query configuration items using -``bro_conf_get_str()``, ``bro_conf_get_int()``, and -``bro_conf_get_dbl()``. You can switch between sections using -``bro_conf_set_domain()``. - -Using Dynamic Buffers ---------------------- - -Broccoli provides an API for dynamically allocatable, growable, -shrinkable, and consumable buffers with ``BroBuf``. You may or may not -find this useful -- Broccoli mainly provides this feature in -``broccoli.h`` because these buffers are used internally anyway and -because they are a typical case of something that people implement -themselves over and over again, for example to collect a set of data -before sending it through a file descriptor, etc. - -The buffers work as follows. The structure implementing a buffer is -called ``BroBuf``, and is initialized to a default size when -created via ``bro_buf_new()`` and released using ``bro_buf_free()``. -Each ``BroBuf`` has a content pointer that points to an arbitrary -location between the start of the buffer and the first byte after the -last byte currently used in the buffer (see ``buf_off`` in the -illustration below). The content pointer can seek to arbitrary -locations, and data can be copied from and into the buffer, adjusting -the content pointer accordingly. You can repeatedly append data to the end -of the buffer's used contents using ``bro_buf_append()``. -:: - - <---------------- allocated buffer space ------------> - <======== used buffer space ========> ^ - ^ ^ ^ | - | | | | - buf buf_ptr buf_off buf_len - -Have a look at the following functions for the details: -``bro_buf_new()``, ``bro_buf_free()``, ``bro_buf_append()``, -``bro_buf_consume()``, ``bro_buf_reset()``, ``bro_buf_get()``, -``bro_buf_get_end()``, ``bro_buf_get_size()``, -``bro_buf_get_used_size()``, ``bro_buf_ptr_get()``, -``bro_buf_ptr_tell()``, ``bro_buf_ptr_seek()``, ``bro_buf_ptr_check()``, -and ``bro_buf_ptr_read()``. - -Configuring Encrypted Communication -=================================== - -Encrypted communication between Bro peers takes place over an SSL -connection in which both endpoints of the connection are authenticated. -This requires at least some PKI in the form of a certificate authority -(CA) which you use to issue and sign certificates for your Bro peers. To -facilitate the SSL setup, each peer requires three documents: a -certificate signed by the CA and containing the public key, the -corresponding private key, and a copy of the CA's certificate. - -The OpenSSL command line tool ``openssl`` can be used to create all -files necessary, but its unstructured arguments and poor documentation -make it a pain to use and waste lots of people a lot of time [#]_. -For an alternative tool to create SSL certificates for secure Bro/Broccoli -communication, see the ``create-cert`` tool available at -ftp://ee.lbl.gov/create-cert.tar.gz. - -In order to enable encrypted communication for your Broccoli -application, you need to put the CA certificate and the peer certificate -in the ``/broccoli/ca_cert`` and ``/broccoli/host_cert`` keys, -respectively, in the configuration file. Optionally, you can store the -private key in a separate file specified by ``/broccoli/host_key``. To -quickly enable/disable a certificate configuration, the -``/broccoli/use_ssl`` key can be used. - -.. note:: - *This is where you configure whether to use encrypted or unencrypted - connections.* - - If the ``/broccoli/use_ssl`` key is present and set to one of "yes", - "true", "on", or 1, then SSL will be used and an incorrect or missing - certificate configuration will cause connection attempts to fail. If - the key's value is one of "no", "false", "off", or 0, then in no case - will SSL be used and connections will always be cleartext. - - If the ``/broccoli/use_ssl`` key is *not* present, then SSL will be - used if a certificate configuration is found, and invalid - certificates will cause the connection to fail. If no certificates - are configured, cleartext connections will be used. - - In no case does an SSL-enabled setup ever fall back to a cleartext - one. - -:: - - /broccoli/use_ssl yes - /broccoli/ca_cert /ca_cert.pem - /broccoli/host_cert /bro_cert.pem - /broccoli/host_key /bro_cert.key - -In a Bro policy, you need to load the ``frameworks/communication/listen.bro`` -script and redef ``Communication::listen_ssl=T``, -``ssl_ca_certificate``, and ``ssl_private_key``, defined in ``bro.init``: - -.. code:: bro - - @load frameworks/communication/listen - - redef Communication::listen_ssl=T; - redef ssl_ca_certificate = "/ca_cert.pem"; - redef ssl_private_key = "/bro.pem"; - -By default, you will be prompted for the passphrase for the private key -matching the public key in your agent's certificate. Depending on your -application's user interface and deployment, this may be inappropriate. -You can store the passphrase in the config file as well, using the -following identifier:: - - /broccoli/host_pass foobar - -.. warning:: *Make sure that access to your configuration is restricted.* - - If you provide the passphrase this way, it is obviously essential to - have restrictive permissions on the configuration file. Broccoli - partially enforces this. Please refer to the section on - `Configuration Files`_ for details. - -Configuring event reception in Bro scripts -========================================== - -Before a remote Bro will accept your connection and your events, it -needs to have its policy configured accordingly: - -1. Load ``frameworks/communication/listen``, and redef the boolean variable - ``Communication::listen_ssl`` depending on whether you want to have - encrypted or cleartext communication. Obviously, encrypting the event - exchange is recommended and cleartext should only be used for early - experimental setups. See below for details on how to set up encrypted - communication via SSL. - -#. You need to find a port to use for the Bros and Broccoli applications - that will listen for connections. Every such agent can use a - different port, though default ports are provided in the Bro - policies. To change the port the Bro agent will be listening on from - its default, redefine the ``Communication::listen_port``. Have a - look at these policies as well as - ``base/frameworks/communication/main.bro`` for the default values. - Here is the policy for the unencrypted case: - - .. code:: bro - - @load frameworks/communication/listen - redef Communication::listen_port = 12345/tcp; - - .. - - Including the settings for the cryptographic files introduced in the - previous section, here is the encrypted one: - - .. code:: bro - - @load frameworks/communication/listen - redef Communication::listen_ssl = T; - redef Communication::listen_port = 12345/tcp; - redef ssl_ca_certificate = "/ca_cert.pem"; - redef ssl_private_key = "/bro.pem"; - - .. - -#. The policy controlling which peers a Bro agent will communicate with - and how this communication will happen are defined in the - ``Communication::nodes`` table defined in - ``base/frameworks/communication/main.bro``. This table contains - entries of type ``Node``, whose members mostly provide default values - so you do not need to define everything. You need to come up with a - tag for the connection under which it can be found in the table (a - creative one would be "broccoli"), the IP address of the peer, the - pattern of names of the events the Bro will accept from you, whether - you want Bro to connect to your machine on startup or not, if so, a - port to connect to (default is ``Communication::default_port`` also defined in - ``base/frameworks/communication/main.bro``), a retry timeout, - whether to use SSL, and the class of a connection as set on the - Broccoli side via ``bro_conn_set_class()``. - - An example could look as follows: - - .. code:: bro - - redef Communication::nodes += { - ["broping"] = [$host = 127.0.0.1, $class="broping", - $events = /ping/, $connect=F, $ssl=F] - }; - - .. - - This example is taken from ``broping.bro``, the policy the remote Bro - must run when you want to use the ``broping`` tool explained in the - section on `test programs`_ below. It will allow an agent on the - local host to connect and send "ping" events. Our Bro will not - attempt to connect, and incoming connections will be expected in - cleartext. - -Configuring Debugging Output -============================ - -If your Broccoli installation was configured with ``--enable-debug``, -Broccoli will report two kinds of debugging information: - -1. function call traces and -#. individual debugging messages. - -Both are enabled by default, but can be adjusted in two ways. - -- In the configuration file: in the appropriate section of the - configuration file, you can set the keys ``/broccoli/debug_messages`` - and ``/broccoli/debug_calltrace`` to ``on``/``off`` to enable/disable - the corresponding output. - -- In code: you can set the variables - ``bro_debug_calltrace`` and ``bro_debug_messages`` to 1/0 at any time - to enable/disable the corresponding output. - -By default, debugging output is inactive (even with debug support -compiled in). You need to enable it explicitly either in your code by -assigning 1 to ``bro_debug_calltrace`` and ``bro_debug_messages`` or by -enabling it in the configuration file. - -Test programs -============= - -The Broccoli distribution comes with a few small test programs, located -in the ``test/`` directory of the tree. The most notable one is -``broping`` [#]_, a mini-version of ping. It sends "ping" events to a -remote Bro agent, expecting "pong" events in return. It operates in two -flavours: one uses atomic types for sending information across, and the -other one uses records. The Bro agent you want to ping needs to run -either the ``broping.bro`` or ``broping-record.bro`` policies. You can -find these in the ``test/`` directory of the source tree, and in -``/share/broccoli`` in the installed version. ``broping.bro`` is -shown below. By default, pinging a Bro on the same machine is -configured. If you want your Bro to be pinged from another machine, you -need to update the ``Communication::nodes`` variable accordingly: - -.. code:: bro - - @load frameworks/communication/listen; - - global ping_log = open_log_file("ping"); - - redef Communication::nodes += { - ["broping"] = [$host = 127.0.0.1, $events = /ping/, - $connect=F, $retry = 60 secs, $ssl=F] - }; - - event ping(src_time: time, seq: count) { - event pong(src_time, current_time(), seq); - } - - event pong(src_time: time, dst_time: time, seq: count) { - print ping_log, - fmt("ping received, seq %d, %f at src, %f at dest, one-way: %f", - seq, src_time, dst_time, dst_time-src_time); - } - -``broping`` sends ping events to Bro. Bro accepts those because they are -configured accordingly in the nodes table. As shown in the -policy, ping events trigger pong events, and ``broccoli`` requests -delivery of all pong events back to it. When running ``broping``, -you'll see something like this: - -.. console:: - - > ./test/broping - pong event from 127.0.0.1: seq=1, time=0.004700/1.010303 s - pong event from 127.0.0.1: seq=2, time=0.053777/1.010266 s - pong event from 127.0.0.1: seq=3, time=0.006435/1.010284 s - pong event from 127.0.0.1: seq=4, time=0.020278/1.010319 s - pong event from 127.0.0.1: seq=5, time=0.004563/1.010187 s - pong event from 127.0.0.1: seq=6, time=0.005685/1.010393 s - -Notes -===== - -.. [#] In other documents and books on OpenSSL you will find this - expressed more politely, using terms such as "daunting to the - uninitiated", "challenging", "complex", "intimidating". - -.. [#] Pronunciation is said to be somewhere on the continuum between - "brooping" and "burping". - -Broccoli API Reference -###################### - -The `API documentation <../../broccoli-api/index.html>`_ -describes Broccoli's public C interface. diff --git a/doc/components/broccoli/broccoli-manual.rst b/doc/components/broccoli/broccoli-manual.rst new file mode 120000 index 0000000000..bd5e8d711f --- /dev/null +++ b/doc/components/broccoli/broccoli-manual.rst @@ -0,0 +1 @@ +../../../aux/broccoli/doc/broccoli-manual.rst \ No newline at end of file diff --git a/doc/components/broctl/README.rst b/doc/components/broctl/README.rst deleted file mode 100644 index 1fd728c7cf..0000000000 --- a/doc/components/broctl/README.rst +++ /dev/null @@ -1,1913 +0,0 @@ -.. Autogenerated. Do not edit. - -.. -*- mode: rst-mode -*- -.. -.. Note: This file includes further autogenerated ones. -.. -.. Version number is filled in automatically. -.. |version| replace:: 1.1-3 - -========== -BroControl -========== - -.. rst-class:: opening - - This document summarizes installation and use of *BroControl*, - Bro's interactive shell for operating Bro installations. *BroControl* - has two modes of operation: a *stand-alone* mode for - managing a traditional, single-system Bro setup; and a *cluster* - mode for maintaining a multi-system setup of coordinated Bro - instances load-balancing the work across a set of independent - machines. Below, we describe the installation process separately - for the two modes. Once installed, the operation is pretty similar - for both types; just keep in mind that if this document refers to - "nodes" and you're in a stand-alone setup, there is only a - single one and no worker/proxies. - -.. contents:: - -Download --------- - -You can find the latest BroControl release for download at -http://www.bro.org/download. - -BroControl's git repository is located at -`git://git.bro.org/broctl `_. You -can browse the repository `here `_. - -This document describes BroControl |version|. See the ``CHANGES`` -file for version history. - -Prerequisites -------------- - -Running *BroControl* requires the following prerequisites: - - - A Unix system. FreeBSD, Linux, and MacOS are supported and - should work out of the box. Other Unix systems will quite likely - require some tweaking. Note that in a cluster setup, all systems - must be running exactly the *same* operating system. - - - A version of *Python* >= 2.6. - - - A *bash* (note in particular, that on FreeBSD, *bash* is not - installed by default). - -Installation ------------- - -Stand-alone Bro -~~~~~~~~~~~~~~~ - -For installing a stand-alone Bro setup, just follow the -Bro :doc:`Quick Start Guide<../../quickstart>`. - -Bro Cluster -~~~~~~~~~~~ - -A *Bro Cluster* is a set of systems jointly analyzing the traffic of -a network link in a coordinated fashion. *BroControl* is able to -operate such a setup from a central manager system pretty much -transparently, hiding much of the complexity of the multi-machine -installation. - -A cluster consists of four types of components: - - Frontends. - One or more frontends: Frontends load-balance the traffic - across a set of worker machines. - - Worker nodes. - Workers are doing the actual analysis, with each seeing a - slice of the overall traffic as split by the frontend(s). - - One or more proxies. - Proxies relay the communication between worker nodes. - - One manager. - The manager provides the cluster's user-interface for - controlling and logging. During operation, the user only - interacts with the manager; this is where *BroControl* is - running. - -For more information about the cluster architecture, including options -for the frontend, see the :doc:`Bro Cluster<../../cluster>` documentation. - -This document focuses on the installation of manager, -workers, and the proxies. If not otherwise -stated, in the following we use the terms "manager", "worker", and -"proxy" to refer to Bro instances, not to physical machines; rather, -we use the term "node" to refer to physical machines. There may be -multiple Bro instances running on the same node. For example, it's -possible to run a proxy on the same node as the manager is operating -on. - -In the following, as an example setup, we will assume that our -cluster consists of four nodes (not counting the frontend). The host -names of the systems will be ``host1``, ``host2``, ``host3``, and -``host4``. We will configure the cluster so that ``host1`` runs the -manager and the (only) proxy, and ``host{2,3,4}`` are each running -one worker. This is a typical setup, which will work well for many -sites. - -When installing a cluster, in addition to the prerequisites -mentioned above, you need to - - - have the same user account set up on all nodes. On the worker - nodes, this user must have access to target network interface in - promiscuous mode. ``ssh`` access from the manager node to this - user account must be setup on all machines, and must work - without asking for a password/passphrase. - - - have some storage available on all nodes under the same path, - which we will call the cluster's *prefix* path. In the - following, we will use ``/usr/local/bro`` as an example. The Bro - user must be able to either create this directory or, where it - already exists, must have write permission inside this directory - on all nodes. - - - have ``ssh`` and ``rsync`` installed. - - -With all prerequisites in place, perform the following steps to -install a Bro cluster (as the Bro user) if you install from the Bro source -code (which includes BroControl): - -- Configure and compile the Bro distribution using the cluster's - prefix path as ``--prefix``:: - - > cd /path/to/bro/source/distribution - > ./configure --prefix=/usr/local/bro && make && make install - -- Add ``/bin`` to your ``PATH``. - -- Create a cluster configuration file. There is an example provided, - which you can edit according to the instructions in the file:: - - > cd /usr/local/bro - > vi etc/broctl.cfg - -- Create a node configuration file to define where manager, workers, - and proxies are to run. There is again an example, which defines - the example scenario described above and can be edited as needed:: - - > cd /usr/local/bro - > vi etc/node.cfg - -- Create a network configuration file that lists all of the networks - which the cluster should consider as local to the monitored - environment. Once again, the installation installs a template for - editing:: - - > cd /usr/local/bro - > vi etc/networks.cfg - -- Install workers and proxies using *BroControl*:: - - > broctl install - - This installation process uses ``ssh`` and ``rdist`` to copy the - configuration over to the remote machines so, as described above, - you need to ensure that logging in via SSH works before the install will - succeed. - -- Some tasks need to be run on a regular basis. On the manager node, - insert a line like this into the crontab of the user running the - cluster:: - - 0-59/5 * * * * /bin/broctl cron - -- Finally, you can start the cluster:: - - > broctl start - -Getting Started ---------------- - -*BroControl* is an interactive interface to the cluster which allows -you to, e.g., start/stop the monitoring or update its configuration. -It is started with the ``broctl`` script and then expects commands -on its command-line (alternatively, ``broctl`` can also be started -with a single command directly on the shell's command line):: - - > broctl - Welcome to BroControl x.y - - Type "help" for help. - - [BroControl] > - -As the message says, type help_ to see a list of -all commands. We will now briefly summarize the most important -commands. A full reference follows `Command Reference`_. - -Once ``broctl.cfg`` and ``node.cfg`` are set up as described above, -the monitoring can be started with the start_ command. In the cluster -setup, this will successively start manager, proxies, and workers. The -status_ command should then show all nodes as operating. To stop the -monitoring, issue the stop_ command. exit_ leaves the shell. - -On the manager system (and on the stand-alone system), you find the -current set of (aggregated) logs in ``logs/current`` (which is a -symlink to the corresponding spool directory). The proxies and workers -log into ``spool/proxy/`` and ``spool//``, respectively. -The manager/stand-alone logs are archived in ``logs/``, by default -once a day. Log files of workers and proxies are discarded at the -same rotation interval. - -Whenever the *BroControl* configuration is modified in any way -(including changes to configuration files and site-specific policy -scripts), install_ installs the new version. *No changes will take -effect until* install_ *is run*. Before you run install_, check_ can be -used to check for any potential errors in the new configuration, e.g., -typos in scripts. If check_ does not report any problems, doing -install_ will pretty likely not break anything. - -Note that generally configuration changes only take effect after a -restart of the affected nodes. The restart_ command triggers this. -Some changes however can be put into effect on-the-fly without -restarting any of the nodes by using the update_ command (again only -after doing install_ first). Such dynamic updates generally work with -all changes done which only modify const variables declared as -*redefinable* (i.e., with Bro's *&redef* attribute). - -Generally, site-specific tuning needs to be done with local policy -scripts, as in any Bro setup. This is described in -`Site-specific Customization`_. - -*BroControl* provides various options to control the behavior of -the setup. These options can be set by editing ``broctl.cfg``. -The config_ command gives a list of all options -with their current values. A list of the most important options also -follows `Option Reference`_. - -Site-specific Customization ---------------------------- - -You'll most likely want to adapt the Bro policy to the local -environment and much of the more specific tuning requires writing -local policy files. - -During the initial install, sample local policy scripts (which you can edit) -are installed in ``share/bro/site``. In the stand-alone setup, a single -file called ``local.bro`` gets loaded automatically. In the cluster -setup, the same ``local.bro`` gets loaded, followed by one of three -other files: ``local-manager.bro``, ``local-worker.bro``, and -``local-proxy.bro`` are loaded by the manager, workers, and proxy, -respectively. - -In the cluster setup, the main exception to putting everything into -``local.bro`` is notice filtering, which should be done only on the -manager. - -The next scripts that are loaded are the ones that are automatically -generated by BroControl. These scripts are created from the -``networks.cfg`` and ``broctl.cfg`` files. - -The last scripts loaded are any node-specific scripts specified with the -option ``aux_scripts`` in ``node.cfg``. This option can be used to -load additional scripts to individual nodes only. For example, one could -add a script ``experimental.bro`` to a single worker for trying out new -experimental code. - -The scripts_ command shows precisely which policy scripts get loaded (and -in what order) by a node; that can be very helpful. - -If you want to change which local policy scripts are loaded by the nodes, -you can set SitePolicyStandalone_ for all Bro instances, -SitePolicyManager_ for the manager, and SitePolicyWorker_ for the -workers. To change the directory where local policy scripts are -located, set the option SitePolicyPath_ to a different path. These -options can be changed in the ``broctl.cfg`` file. - -Command Reference ------------------ - -The following summary lists all commands supported by *BroControl*. -All commands may be either entered interactively or specified on the -shell's command line. If not specified otherwise, commands taking -*[]* as arguments apply their action either to the given set of -nodes, or to all nodes if none is given. - -[?1034h.. Automatically generated. Do not edit. - - -.. _attachgdb: - -*attachgdb* *[]* - Primarily for debugging, the command attaches a *gdb* to the main Bro - process on the given nodes. - - -.. _capstats: - -*capstats* *[] []* - Determines the current load on the network interfaces monitored by - each of the given worker nodes. The load is measured over the - specified interval (in seconds), or by default over 10 seconds. This - command uses the `capstats tool - `_, - which is installed along with ``broctl``. - - (Note: When using a CFlow and the CFlow command line utility is - installed as well, the ``capstats`` command can also query the device - for port statistics. *TODO*: document how to set this up.) - - -.. _check: - -*check* *[]* - Verifies a modified configuration in terms of syntactical correctness - (most importantly correct syntax in policy scripts). This command - should be executed for each configuration change *before* - install_ is used to put the change into place. Note - that ``check`` is the only command which operates correctly without a - former install_ command; ``check`` uses the policy - files as found in SitePolicyPath_ to make - sure they compile correctly. If they do, install_ - will then copy them over to an internal place from where the nodes - will read them at the next start_. This approach - ensures that new errors in a policy script will not affect currently - running nodes, even when one or more of them needs to be restarted. - - -.. _cleanup: - -*cleanup* *[--all] []* - Clears the nodes' spool directories (if they are not running - currently). This implies that their persistent state is flushed. Nodes - that were crashed are reset into *stopped* state. If ``--all`` is - specified, this command also removes the content of the node's - TmpDir_, in particular deleteing any data - potentially saved there for reference from previous crashes. - Generally, if you want to reset the installation back into a clean - state, you can first stop_ all nodes, then execute - ``cleanup --all``, and finally start_ all nodes - again. - - -.. _config: - -*config* - Prints all configuration options with their current values. - - -.. _cron: - -*cron* *[enable|disable|?] | [--no-watch]* - This command has two modes of operation. Without arguments (or just - ``--no-watch``), it performs a set of maintenance tasks, including - the logging of various statistical information, expiring old log - files, checking for dead hosts, and restarting nodes which terminated - unexpectedly. The latter can be suppressed with the ``--no-watch`` - option if no auto-restart is desired. This mode is intended to be - executed regularly via *cron*, as described in the installation - instructions. While not intended for interactive use, no harm will be - caused by executing the command manually: all the maintenance tasks - will then just be performed one more time. - - The second mode is for interactive usage and determines if the regular - tasks are indeed performed when ``broctl cron`` is executed. In other - words, even with ``broctl cron`` in your crontab, you can still - temporarily disable its execution by running ``cron disable``, and - then later reenable with ``cron enable``. This can be helpful while - working, e.g., on the BroControl configuration and ``cron`` would - interfere with that. ``cron ?`` can be used to query the current state. - - -.. _df: - -*df* *[]* - Reports the amount of disk space available on the nodes. Shows only - paths relevant to the broctl installation. - - -.. _diag: - -*diag* *[]* - If a node has terminated unexpectedly, this command prints a (somewhat - cryptic) summary of its final state including excerpts of any - stdout/stderr output, resource usage, and also a stack backtrace if a - core dump is found. The same information is sent out via mail when a - node is found to have crashed (the "crash report"). While the - information is mainly intended for debugging, it can also help to find - misconfigurations (which are usually, but not always, caught by the - check_ command). - - -.. _exec: - -*exec* ** - Executes the given Unix shell command line on all nodes configured to - run at least one Bro instance. This is handy to quickly perform an - action across all systems. - - -.. _exit: - -*exit* - Terminates the shell. - - -.. _help: - -*help* - Prints a brief summary of all commands understood by the shell. - - -.. _install: - -*install* - Reinstalls the given nodes, including all configuration files and - local policy scripts. This command must be executed after *all* - changes to any part of the broctl configuration, otherwise the - modifications will not take effect. Usually all nodes should be - reinstalled at the same time, as any inconsistencies between them will - lead to strange effects. Before executing ``install``, it is recommended - to verify the configuration with check_. - - -.. _netstats: - -*netstats* *[]* - Queries each of the nodes for their current counts of captured and - dropped packets. - - -.. _nodes: - -*nodes* - Prints a list of all configured nodes. - - -.. _peerstatus: - -*peerstatus* *[]* - Primarily for debugging, ``peerstatus`` reports statistics about the - network connections cluster nodes are using to communicate with other - nodes. - - -.. _print: - -*print* * []* - Reports the *current* live value of the given Bro script ID on all of - the specified nodes (which obviously must be running). This can for - example be useful to (1) check that policy scripts are working as - expected, or (2) confirm that configuration changes have in fact been - applied. Note that IDs defined inside a Bro namespace must be - prefixed with ``::`` (e.g., ``print SSH::did*ssh*version`` to - print the corresponding table from ``ssh.bro``.) - - -.. _process: - -*process* * [options] [-- ]* - Runs Bro offline on a given trace file using the same configuration as - when running live. It does, however, use the potentially - not-yet-installed policy files in SitePolicyPath_ and disables log - rotation. Additional Bro command line flags and scripts can - be given (each argument after a ``--`` argument is interpreted as - a script). - - Upon completion, the command prints a path where the log files can be - found. Subsequent runs of this command may delete these logs. - - In cluster mode, Bro is run with *both* manager and worker scripts - loaded into a single instance. While that doesn't fully reproduce the - live setup, it is often sufficient for debugging analysis scripts. - - -.. _quit: - -*quit* - Terminates the shell. - - -.. _restart: - -*restart* *[--clean] []* - Restarts the given nodes, or all nodes if none are specified. The - effect is the same as first executing stop_ followed - by a start_, giving the same nodes in both cases. - This command is most useful to activate any changes made to Bro policy - scripts (after running install_ first). Note that a - subset of policy changes can also be installed on the fly via the - update_, without requiring a restart. - - If ``--clean`` is given, the installation is reset into a clean state - before restarting. More precisely, a ``restart --clean`` turns into - the command sequence stop_, cleanup_ --all, check_, install_, and - start_. - - -.. _scripts: - -*scripts* *[-c] []* - Primarily for debugging Bro configurations, the ``scripts`` - command lists all the Bro scripts loaded by each of the nodes in the - order they will be parsed by the node at startup. - If ``-c`` is given, the command operates as check_ does: it reads - the policy files from their *original* location, not the copies - installed by install_. The latter option is useful to check a - not yet installed configuration. - - -.. _start: - -*start* *[]* - Starts the given nodes, or all nodes if none are specified. Nodes - already running are left untouched. - - -.. _status: - -*status* *[]* - Prints the current status of the given nodes. - - -.. _stop: - -*stop* *[]* - Stops the given nodes, or all nodes if none are specified. Nodes not - running are left untouched. - - -.. _top: - -*top* *[]* - For each of the nodes, prints the status of the two Bro - processes (parent process and child process) in a *top*-like - format, including CPU usage and memory consumption. If - executed interactively, the display is updated frequently - until key ``q`` is pressed. If invoked non-interactively, the - status is printed only once. - - -.. _update: - -*update* *[]* - After a change to Bro policy scripts, this command updates the Bro - processes on the given nodes *while they are running* (i.e., without - requiring a restart_). However, such dynamic - updates work only for a *subset* of Bro's full configuration. The - following changes can be applied on the fly: The value of all - const variables defined with the ``&redef`` attribute can be changed. - More extensive script changes are not possible during runtime and - always require a restart; if you change more than just the values of - ``&redef``-able consts and still issue ``update``, the results are - undefined and can lead to crashes. Also note that before running - ``update``, you still need to do an install_ (preferably after - check_), as otherwise ``update`` will not see the changes and it will - resend the old configuration. - - -Option Reference ----------------- - -This section summarizes the options that can be set in ``broctl.cfg`` -for customizing the behavior of *BroControl*. Usually, one only needs -to change the "user options", which are listed first. The "internal -options" are, as the name suggests, primarily used internally and set -automatically. They are documented here only for reference. - -.. Automatically generated. Do not edit. - -User Options -~~~~~~~~~~~~ -.. _BroArgs: - -*BroArgs* (string, default _empty_) - Additional arguments to pass to Bro on the command-line. - -.. _CFlowAddress: - -*CFlowAddress* (string, default _empty_) - If a cFlow load-balancer is used, the address of the device (format: :). - -.. _CFlowPassword: - -*CFlowPassword* (string, default _empty_) - If a cFlow load-balancer is used, the password for accessing its configuration interface. - -.. _CFlowUser: - -*CFlowUser* (string, default _empty_) - If a cFlow load-balancer is used, the user name for accessing its configuration interface. - -.. _CommTimeout: - -*CommTimeout* (int, default 10) - The number of seconds to wait before assuming Broccoli communication events have timed out. - -.. _CompressCmd: - -*CompressCmd* (string, default "gzip -9") - If archived logs will be compressed, the command to use for that. The specified command must compress its standard input to standard output. - -.. _CompressExtension: - -*CompressExtension* (string, default "gz") - If archived logs will be compressed, the file extension to use on compressed log files. When specifying a file extension, don't include the period character (e.g., specify 'gz' instead of '.gz'). - -.. _CompressLogs: - -*CompressLogs* (bool, default 1) - True to compress archived log files. - -.. _CronCmd: - -*CronCmd* (string, default _empty_) - A custom command to run everytime the cron command has finished. - -.. _Debug: - -*Debug* (bool, default 0) - Enable extensive debugging output in spool/debug.log. - -.. _HaveNFS: - -*HaveNFS* (bool, default 0) - True if shared files are mounted across all nodes via NFS (see FAQ). - -.. _IPv6Comm: - -*IPv6Comm* (bool, default 1) - Enable IPv6 communication between cluster nodes (and also between them and BroControl) - -.. _LogDir: - -*LogDir* (string, default "$\{BroBase}/logs") - Directory for archived log files. - -.. _LogExpireInterval: - -*LogExpireInterval* (int, default 0) - Number of days log files are kept (zero means disabled). - -.. _LogRotationInterval: - -*LogRotationInterval* (int, default 3600) - The frequency of log rotation in seconds for the manager/standalone node. - -.. _MailAlarmsTo: - -*MailAlarmsTo* (string, default "$\{MailTo}") - Destination address for alarm summary mails. Default is to use the same address as MailTo. - -.. _MailFrom: - -*MailFrom* (string, default "Big Brother ") - Originator address for broctl-generated mails. - -.. _MailReplyTo: - -*MailReplyTo* (string, default _empty_) - Reply-to address for broctl-generated mails. - -.. _MailSubjectPrefix: - -*MailSubjectPrefix* (string, default "[Bro]") - General Subject prefix for mails. - -.. _MailTo: - -*MailTo* (string, default "") - Destination address for non-alarm mails. - -.. _MakeArchiveName: - -*MakeArchiveName* (string, default "$\{BroBase}/share/broctl/scripts/make-archive-name") - Script to generate filenames for archived log files. - -.. _MemLimit: - -*MemLimit* (string, default "unlimited") - Maximum amount of memory for Bro processes to use (in KB, or the string 'unlimited'). - -.. _MinDiskSpace: - -*MinDiskSpace* (int, default 5) - Percentage of minimum disk space available before warning is mailed. - -.. _PFRINGClusterID: - -*PFRINGClusterID* (int, default @PF_RING_CLUSTER_ID@) - If PF_RING flow-based load balancing is desired, this is where the PF_RING cluster id is defined. The default value is configuration-dependent and determined automatically by CMake at configure-time based upon whether PF_RING's enhanced libpcap is available. Bro must be linked with PF_RING's libpcap wrapper for this option to work. - -.. _Prefixes: - -*Prefixes* (string, default "local") - Additional script prefixes for Bro, separated by colons. Use this instead of @prefix. - -.. _SaveTraces: - -*SaveTraces* (bool, default 0) - True to let backends capture short-term traces via '-w'. These are not archived but might be helpful for debugging. - -.. _SendMail: - -*SendMail* (string, default "@SENDMAIL@") - Location of the sendmail binary. Make this string blank to prevent email from being sent. The default value is configuration-dependent and determined automatically by CMake at configure-time. - -.. _SitePluginPath: - -*SitePluginPath* (string, default _empty_) - Directories to search for custom plugins, separated by colons. - -.. _SitePolicyManager: - -*SitePolicyManager* (string, default "local-manager.bro") - Space-separated list of local policy files for manager. - -.. _SitePolicyPath: - -*SitePolicyPath* (string, default "$\{PolicyDir}/site") - Directories to search for local policy files, separated by colons. - -.. _SitePolicyStandalone: - -*SitePolicyStandalone* (string, default "local.bro") - Space-separated list of local policy files for all Bro instances. - -.. _SitePolicyWorker: - -*SitePolicyWorker* (string, default "local-worker.bro") - Space-separated list of local policy files for workers. - -.. _StopTimeout: - -*StopTimeout* (int, default 60) - The number of seconds to wait before sending a SIGKILL to a node which was previously issued the 'stop' command but did not terminate gracefully. - -.. _TimeFmt: - -*TimeFmt* (string, default "%d %b %H:%M:%S") - Format string to print date/time specifications (see 'man strftime'). - -.. _TimeMachineHost: - -*TimeMachineHost* (string, default _empty_) - If the manager should connect to a Time Machine, the address of the host it is running on. - -.. _TimeMachinePort: - -*TimeMachinePort* (string, default "47757/tcp") - If the manager should connect to a Time Machine, the port it is running on (in Bro syntax, e.g., 47757/tcp). - -.. _ZoneID: - -*ZoneID* (string, default _empty_) - If the host running BroControl is managing a cluster comprised of nodes with non-global IPv6 addresses, this option indicates what RFC 4007 zone_id to append to node addresses when communicating with them. - - -Internal Options -~~~~~~~~~~~~~~~~ - -.. _BinDir: - -*BinDir* (string, default "$\{BroBase}/bin") - Directory for executable files. - -.. _BroBase: - -*BroBase* (string, default _empty_) - Base path of broctl installation on all nodes. - -.. _CapstatsPath: - -*CapstatsPath* (string, default "$\{bindir}/capstats") - Path to capstats binary; empty if not available. - -.. _CfgDir: - -*CfgDir* (string, default "$\{BroBase}/etc") - Directory for configuration files. - -.. _DebugLog: - -*DebugLog* (string, default "$\{SpoolDir}/debug.log") - Log file for debugging information. - -.. _HelperDir: - -*HelperDir* (string, default "$\{BroBase}/share/broctl/scripts/helpers") - Directory for broctl helper scripts. - -.. _LibDir: - -*LibDir* (string, default "$\{BroBase}/lib") - Directory for library files. - -.. _LibDirInternal: - -*LibDirInternal* (string, default "$\{BroBase}/lib/broctl") - Directory for broctl-specific library files. - -.. _LocalNetsCfg: - -*LocalNetsCfg* (string, default "$\{CfgDir}/networks.cfg") - File defining the local networks. - -.. _LockFile: - -*LockFile* (string, default "$\{SpoolDir}/lock") - Lock file preventing concurrent shell operations. - -.. _NodeCfg: - -*NodeCfg* (string, default "$\{CfgDir}/node.cfg") - Node configuration file. - -.. _OS: - -*OS* (string, default _empty_) - Name of operating system as reported by uname. - -.. _PluginDir: - -*PluginDir* (string, default "$\{LibDirInternal}/plugins") - Directory where standard plugins are located. - -.. _PolicyDir: - -*PolicyDir* (string, default "$\{BroBase}/share/bro") - Directory for standard policy files. - -.. _PolicyDirSiteInstall: - -*PolicyDirSiteInstall* (string, default "$\{SpoolDir}/installed-scripts-do-not-touch/site") - Directory where the shell copies local policy scripts when installing. - -.. _PolicyDirSiteInstallAuto: - -*PolicyDirSiteInstallAuto* (string, default "$\{SpoolDir}/installed-scripts-do-not-touch/auto") - Directory where the shell copies auto-generated local policy scripts when installing. - -.. _PostProcDir: - -*PostProcDir* (string, default "$\{BroBase}/share/broctl/scripts/postprocessors") - Directory for log postprocessors. - -.. _ScriptsDir: - -*ScriptsDir* (string, default "$\{BroBase}/share/broctl/scripts") - Directory for executable scripts shipping as part of broctl. - -.. _SpoolDir: - -*SpoolDir* (string, default "$\{BroBase}/spool") - Directory for run-time data. - -.. _StandAlone: - -*StandAlone* (bool, default 0) - True if running in stand-alone mode (see elsewhere). - -.. _StateFile: - -*StateFile* (string, default "$\{SpoolDir}/broctl.dat") - File storing the current broctl state. - -.. _StaticDir: - -*StaticDir* (string, default "$\{BroBase}/share/broctl") - Directory for static, arch-independent files. - -.. _StatsDir: - -*StatsDir* (string, default "$\{LogDir}/stats") - Directory where statistics are kept. - -.. _StatsLog: - -*StatsLog* (string, default "$\{SpoolDir}/stats.log") - Log file for statistics. - -.. _Time: - -*Time* (string, default _empty_) - Path to time binary. - -.. _TmpDir: - -*TmpDir* (string, default "$\{SpoolDir}/tmp") - Directory for temporary data. - -.. _TmpExecDir: - -*TmpExecDir* (string, default "$\{SpoolDir}/tmp") - Directory where binaries are copied before execution. - -.. _TraceSummary: - -*TraceSummary* (string, default "$\{bindir}/trace-summary") - Path to trace-summary script (empty if not available). Make this string blank to disable the connection summary emails. - -.. _Version: - -*Version* (string, default _empty_) - Version of the broctl. - - -Writing Plugins ---------------- - -BroControl provides a plugin interface to extend its functionality. A -plugin is written in Python and can do any, or all, of the following: - - * Perform actions before or after any of the standard BroControl - commands is executed. When running before the actual command, it - can filter which nodes to operate or stop the execution - altogether. When running after the command, it gets access to - the commands success on a per-node basis (where applicable). - - * Add custom commands to BroControl. - - * Add custom options to BroControl defined in ``broctl.cfg``. - - * Add custom keys to nodes defined in ``node.cfg``. - -A plugin is written by deriving a new class from BroControl class -`Plugin`_. The Python script with the new plugin is then copied into a -plugin directory searched by BroControl at startup. By default, -BroControl searches ``/lib/broctl/plugins``; further may be -configured by setting the PluginDir_ option. Note that any plugin -script must end in ``*.py`` to be found. BroControl comes with some -example plugins that can be used as a starting point; see -the ``/lib/broctl/plugins`` directory. - -In the following, we document the API that is available to plugins. A -plugin must be derived from the `Plugin`_ class, and can use its -methods as well as those of the `Node`_ class. - -.. _Plugin: - -Class ``Plugin`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class **Plugin** - The class ``Plugin`` is the base class for all BroControl plugins. - - The class has a number of methods for plugins to override, and every - plugin must at least override ``name()`` and ``pluginVersion()``. - - For each BroControl command ``foo``, there are two methods, - ``cmd_foo_pre`` and ``cmd_foo_post``, that are called just before the - command is executed and just after it has finished, respectively. The - arguments these methods receive correspond to their command-line - parameters, and are further documented below. - - The ``cmd__pre`` methods have the ability to prevent the command's - execution, either completely or partially for those commands that take - nodes as parameters. In the latter case, the method receives a list of - nodes that the command is to be run on, and it can filter that list and - returns modified version of nodes to actually use. The standard case would - be returning simply the unmodified ``nodes`` parameter. To completely - block the command's execution, return an empty list. To just not execute - the command for a subset, remove the affected ones. For commands that do - not receive nodes as arguments, the return value is interpreted as boolean - indicating whether command execution should proceed (True) or not (False). - - The ``cmd__post`` methods likewise receive the commands arguments as - their parameter, as documented below. For commands taking nodes, the list - corresponds to those nodes for which the command was actually executed - (i.e., after any ``cmd__pre`` filtering). Each node is given as a - tuple ``(node, bool)`` with *node* being the actual `Node`_, and the boolean - indicating whether the command was successful for it. - - Note that if a plugin prevents a command from executing either completely or - partially, it should report its reason via the ``message*()`` or - ``error()`` methods. - - If multiple plugins hook into the same command, all their - ``cmd__{pre,post}`` are executed in undefined order. The command is - executed on the intersection of all ``cmd__pre`` results. - - Finally, note that the ``restart`` command doesn't have its own method as - it's just a combination of other commands and thus their callbacks are - run. - - .. _Plugin.debug: - - **debug** (self, msg) - - Logs a debug message in BroControl's debug log if enabled. - - .. _Plugin.error: - - **error** (self, msg) - - Reports an error to the user. - - .. _Plugin.execute: - - **execute** (self, node, cmd) - - Executes a command on the host for the given *node* of type - `Node`_. Returns a tuple ``(success, output)`` in which ``success`` is - True if the command ran successfully and ``output`` is the combined - stdout/stderr output. - - .. _Plugin.executeParallel: - - **executeParallel** (self, cmds) - - Executes a set of commands in parallel on multiple hosts. ``cmds`` - is a list of tuples ``(node, cmd)``, in which the *node* is a `Node`_ - instance and *cmd* is a string with the command to execute for it. The - method returns a list of tuples ``(node, success, output)``, in which - ``success`` is True if the command ran successfully and ``output`` is - the combined stdout/stderr output for the corresponding ``node``. - - .. _Plugin.getGlobalOption: - - **getGlobalOption** (self, name) - - Returns the value of the global BroControl option or state - attribute *name*. If the user has not set the options, its default - value is returned. See the output of ``broctl config`` for a complete - list. - - .. _Plugin.getOption: - - **getOption** (self, name) - - Returns the value of one of the plugin's options, *name*. The - returned value will always be a string. - - An option has a default value (see *options()*), which can be - overridden by a user in ``broctl.cfg``. An option's value cannot be - changed by the plugin. - - .. _Plugin.getState: - - **getState** (self, name) - - Returns the current value of one of the plugin's state variables, - *name*. The returned value will always be a string. If it has not yet - been set, an empty string will be returned. - - Different from options, state variables can be set by the plugin and - are persistent across restarts. They are not visible to the user. - - Note that a plugin cannot query any global BroControl state variables. - - .. _Plugin.hosts: - - **hosts** (self, nodes) - - Returns a list of all hosts running at least one node from the list - of Nodes_ objects in *nodes*, or configured in if *nodes* is empty. - - .. _Plugin.message: - - **message** (self, msg) - - Reports a message to the user. - - .. _Plugin.nodes: - - **nodes** (self) - - Returns a list of all configured `Node`_ objects. - - .. _Plugin.parseNodes: - - **parseNodes** (self, names) - - Returns `Node`_ objects for a string of space-separated node names. - If a name does not correspond to a known node, an error message is - printed and the node is skipped from the returned list. If no names - are known, an empty list is returned. - - .. _Plugin.setState: - - **setState** (self, name, value) - - Sets one of the plugin's state variables, *name*, to *value*. - *value* must be a string. The change is permanent and will be recorded - to disk. - - Note that a plugin cannot change any global BroControl state - variables. - - .. _Plugin.broProcessDied: - - **broProcessDied** (self, node) - - Called when BroControl finds the Bro process for Node_ *node* - to have terminated unexpectedly. This method will be called just - before BroControl prepares the node's "crash report" and before it - cleans up the node's spool directory. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_attachgdb_post: - - **cmd_attachgdb_post** (self, nodes) - - Called just after the ``attachgdb`` command has finished. Arguments - are as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_attachgdb_pre: - - **cmd_attachgdb_pre** (self, nodes) - - Called just before the ``attachgdb`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_capstats_post: - - **cmd_capstats_post** (self, nodes, interval) - - Called just after the ``capstats`` command has finished. Arguments - are as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_capstats_pre: - - **cmd_capstats_pre** (self, nodes, interval) - - Called just before the ``capstats`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. *integer* is an integer with the measurement interval in - seconds. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_check_post: - - **cmd_check_post** (self, results) - - Called just after the ``check`` command has finished. It receives - the list of 2-tuples ``(node, bool)`` indicating the nodes the command - was executed for, along with their success status. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_check_pre: - - **cmd_check_pre** (self, nodes) - - Called just before the ``check`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_cleanup_post: - - **cmd_cleanup_post** (self, nodes, all) - - Called just after the ``cleanup`` command has finished. Arguments - are as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_cleanup_pre: - - **cmd_cleanup_pre** (self, nodes, all) - - Called just before the ``cleanup`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. *all* is boolean indicating whether the ``--all`` - argument has been given. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_config_post: - - **cmd_config_post** (self) - - Called just after the ``config`` command has finished. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_config_pre: - - **cmd_config_pre** (self) - - Called just before the ``config`` command is run. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_cron_post: - - **cmd_cron_post** (self, arg, watch) - - Called just after the ``cron`` command has finished. Arguments are - as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_cron_pre: - - **cmd_cron_pre** (self, arg, watch) - - Called just before the ``cron`` command is run. *arg* is None if - the cron is executed without arguments. Otherwise, it is one of the - strings: ``enable``, ``disable``, ``?``. *watch* is a boolean - indicating whether ``cron`` should restart abnormally terminated Bro - processes; it's only valid if arg is empty. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_custom: - - **cmd_custom** (self, cmd, args) - - Called when command defined by the ``commands`` method is executed. - ``cmd`` is the command (with the plugin's prefix), and ``args`` is a - single *string* with all arguments. - - If the arguments are actually node names, ``parseNodes`` can - be used to get the `Node`_ objects. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_df_post: - - **cmd_df_post** (self, nodes) - - Called just after the ``df`` command has finished. Arguments are as - with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_df_pre: - - **cmd_df_pre** (self, nodes) - - Called just before the ``df`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_diag_post: - - **cmd_diag_post** (self, nodes) - - Called just after the ``diag`` command has finished. Arguments are - as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_diag_pre: - - **cmd_diag_pre** (self, nodes) - - Called just before the ``diag`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_exec_post: - - **cmd_exec_post** (self, cmdline) - - Called just after the ``exec`` command has finished. Arguments are - as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_exec_pre: - - **cmd_exec_pre** (self, cmdline) - - Called just before the ``exec`` command is run. *cmdline* is a - string with the command line to execute. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_install_post: - - **cmd_install_post** (self) - - Called just after the ``install`` command has finished. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_install_pre: - - **cmd_install_pre** (self) - - Called just before the ``install`` command is run. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_netstats_post: - - **cmd_netstats_post** (self, nodes) - - Called just after the ``netstats`` command has finished. Arguments - are as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_netstats_pre: - - **cmd_netstats_pre** (self, nodes) - - Called just before the ``netstats`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_nodes_post: - - **cmd_nodes_post** (self) - - Called just after the ``nodes`` command has finished. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_nodes_pre: - - **cmd_nodes_pre** (self) - - Called just before the ``nodes`` command is run. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_peerstatus_post: - - **cmd_peerstatus_post** (self, nodes) - - Called just after the ``peerstatus`` command has finished. - Arguments are as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_peerstatus_pre: - - **cmd_peerstatus_pre** (self, nodes) - - Called just before the ``peerstatus`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_print_post: - - **cmd_print_post** (self, nodes, id) - - Called just after the ``print`` command has finished. Arguments are - as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_print_pre: - - **cmd_print_pre** (self, nodes, id) - - Called just before the ``print`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. *id* is a string with the name of the ID to be printed. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_process_post: - - **cmd_process_post** (self, trace, options, scripts, success) - - Called just after the ``process`` command has finished. Arguments - are as with the ``pre`` method, plus an additional boolean *success* - indicating whether Bro terminated normally. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_process_pre: - - **cmd_process_pre** (self, trace, options, scripts) - - Called just before the ``process`` command is run. It receives the - *trace* to read from as a string, a list of additional Bro *options*, - and a list of additional Bro scripts. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_restart_post: - - **cmd_restart_post** (self, results) - - Called just after the ``restart`` command has finished. It receives - the list of 2-tuples ``(node, bool)`` indicating the nodes the command - was executed for, along with their success status. The remaining - arguments are as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_restart_pre: - - **cmd_restart_pre** (self, nodes, clean) - - Called just before the ``restart`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. *clean* is boolean indicating whether the ``--clean`` - argument has been given. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_scripts_post: - - **cmd_scripts_post** (self, nodes, full_path, check) - - Called just after the ``scripts`` command has finished. Arguments - are as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_scripts_pre: - - **cmd_scripts_pre** (self, nodes, full_path, check) - - Called just before the ``scripts`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. ``full_path`` and ``check`` are boolean indicating - whether the ``-p`` and ``-c`` options were given, respectively. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_start_post: - - **cmd_start_post** (self, results) - - Called just after the ``start`` command has finished. It receives - the list of 2-tuples ``(node, bool)`` indicating the nodes the command - was executed for, along with their success status. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_start_pre: - - **cmd_start_pre** (self, nodes) - - Called just before the ``start`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_status_post: - - **cmd_status_post** (self, nodes) - - Called just after the ``status`` command has finished. Arguments - are as with the ``pre`` method. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_status_pre: - - **cmd_status_pre** (self, nodes) - - Called just before the ``status`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_stop_post: - - **cmd_stop_post** (self, results) - - Called just after the ``stop`` command has finished. It receives - the list of 2-tuples ``(node, bool)`` indicating the nodes the command - was executed for, along with their success status. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_stop_pre: - - **cmd_stop_pre** (self, nodes) - - Called just before the ``stop`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_top_post: - - **cmd_top_post** (self, nodes) - - Called just after the ``top`` command has finished. Arguments are - as with the ``pre`` method. Note that when ``top`` is run - interactively to auto-refresh continuously, this method will be called - once after each update. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_top_pre: - - **cmd_top_pre** (self, nodes) - - Called just before the ``top`` command is run. It receives the list - of nodes, and returns the list of nodes that should proceed with the - command. Note that when ``top`` is run interactively to auto-refresh - continuously, this method will be called once before each update. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_update_post: - - **cmd_update_post** (self, results) - - Called just after the ``update`` command has finished. It receives - the list of 2-tuples ``(node, bool)`` indicating the nodes the command - was executed for, along with their success status. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.cmd_update_pre: - - **cmd_update_pre** (self, nodes) - - Called just before the ``update`` command is run. It receives the - list of nodes, and returns the list of nodes that should proceed with - the command. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.commands: - - **commands** (self) - - Returns a set of custom commands provided by the - plugin. - - The return value is a list of 3-tuples each having the following - elements: - - ``command`` - A string with the command's name. Note that the command name - exposed to the user will be prefixed with the plugin's prefix - as returned by *name()* (e.g., ``myplugin.mycommand``). - - ``arguments`` - A string describing the command's arguments in a textual form - suitable for use in the ``help`` command summary (e.g., - ``[]`` for command taking an optional list of nodes). - Empty if no arguments are expected. - - ``description`` - A string with a description of the command's semantics. - - - This method can be overridden by derived classes. The implementation - must not call the parent class' implementation. The default - implementation returns an empty list. - - .. _Plugin.done: - - **done** (self) - - Called once just before BroControl terminates. This method can do - any cleanup the plugin may require. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.hostStatusChanged: - - **hostStatusChanged** (self, host, status) - - Called when BroControl's ``cron`` command finds the availability of - a cluster system to have changed. Initially, all systems are assumed - to be up and running. Once BroControl notices that a system isn't - responding (defined as either it doesn't ping at all, or does not - accept SSH sessions), it calls this method, passing in a string with - the name of the *host* and a boolean *status* set to False. Once the - host becomes available again, the method will be called again for the - same host with *status* now set to True. - - Note that BroControl's ``cron`` tracks a host's availability across - execution, so if the next time it's run the host is still down, this - method will not be called again. - - This method can be overridden by derived classes. The default - implementation does nothing. - - .. _Plugin.init: - - **init** (self) - - Called once just before BroControl starts executing any commands. - This method can do any initialization that the plugin may require. - - Note that when this method executes, BroControl guarantees that all - internals are fully set up (e.g., user-defined options are available). - This may not be the case when the class ``__init__`` method runs. - - Returns a boolean, indicating whether the plugin should be used. If it - returns ``False``, the plugin will be removed and no other methods - called. - - This method can be overridden by derived classes. The default - implementation always returns True. - - .. _Plugin.name: - - **name** (self) - - Returns a string with a descriptive *name* for the plugin (e.g., - ``"TestPlugin"``). The name must not contain any whitespace. - - This method must be overridden by derived classes. The implementation - must not call the parent class' implementation. - - .. _Plugin.nodeKeys: - - **nodeKeys** (self) - - Returns a list of custom keys for ``node.cfg``. The value for a - key will be available from the `Node`_ object as attribute - ``_`` (e.g., ``node.test_mykw``). If not set, the - attribute will be set to None. - - This method can be overridden by derived classes. The implementation - must not call the parent class' implementation. The default - implementation returns an empty list. - - .. _Plugin.options: - - **options** (self) - - Returns a set of local configuration options provided by the - plugin. - - The return value is a list of 4-tuples each having the following - elements: - - ``name`` - A string with name of the option (e.g., ``Path``). Option - names are case-insensitive. Note that the option name exposed - to the user will be prefixed with your plugin's prefix as - returned by *name()* (e.g., ``myplugin.Path``). - - ``type`` - A string with type of the option, which must be one of - ``"bool"``, ``"string"``, or ``"int"``. - - ``default`` - A string with the option's default value. Note that this must - always be a string, even for non-string types. For booleans, - use ``"0"`` for False and ``"1"`` for True. For integers, give - the value as a string ``"42"``. - - ``description`` - A string with a description of the option semantics. - - This method can be overridden by derived classes. The implementation - must not call the parent class' implementation. The default - implementation returns an empty list. - - .. _Plugin.pluginVersion: - - **pluginVersion** (self) - - Returns an integer with a version number for the plugin. Plugins - should increase their version number with any significant change. - - This method must be overridden by derived classes. The implementation - must not call the parent class' implementation. - - .. _Plugin.prefix: - - **prefix** (self) - - Returns a string with a prefix for the plugin's options and - commands names (e.g., "myplugin"). - - This method can be overridden by derived classes. The implementation - must not call the parent class' implementation. The default - implementation returns a lower-cased version of *name()*. - -.. _Node: - -Class ``Node`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class **Node** - Class representing one node of the BroControl maintained setup. In - standalone mode, there's always exactly one node of type ``standalone``. In - a cluster setup, there is exactly one of type ``manager``, one or - more of type ``proxy``, and zero or more of type ``worker``. - - In addition to the methods described above, a ``Node`` object has a number - of keys with values that are set via ``node.cfg`` and can be accessed - directly via corresponding Python attributes (e.g., ``node.name``): - - ``name`` (string) - The name of the node, which corresponds to the ``[]`` - section in ``node.cfg``. - - ``type`` (string) - The type of the node, which will be one of ``standalone``, - ``manager``, ``proxy``, and ``worker``. - - ``host`` (string) - The hostname of the system the node is running on. - - ``interface`` (string) - The network interface for Bro to use; empty if not set. - - ``lb_procs`` (integer) - The number of clustered Bro workers you'd like to start up. - - ``lb_method`` (string) - The load balancing method to distribute packets to all of the - processes (must be one of: ``pf_ring``, ``myricom``, or - ``interfaces``). - - ``lb_interfaces`` (string) - If the load balancing method is ``interfaces``, then this is - a comma-separated list of network interface names to use. - - ``aux_scripts`` (string) - Any node-specific Bro script configured for this node. - - ``zone_id`` (string) - If BroControl is managing a cluster comprised of nodes - using non-global IPv6 addresses, then this configures the - RFC 4007 ``zone_id`` string that the node associates with - the common zone that all cluster nodes are a part of. This - identifier may differ between nodes. - - Any attribute that is not defined in ``node.cfg`` will be empty. - - In addition, plugins can override `Plugin.nodeKeys`_ to define their own - node keys, which can then be likewise set in ``node.cfg``. The key names - will be prepended with the plugin's `Plugin.prefix`_ (e.g., for the plugin - ``test``, the node key ``foo`` is set by adding ``test.foo=value`` to - ``node.cfg``). - - .. _Node.cwd: - - **cwd** (self) - - Returns a string with the node's working directory. - - .. _Node.describe: - - **describe** (self) - - Returns an extended string representation of the node including all - its keys with values. - - .. _Node.getPID: - - **getPID** (self) - - Returns the process ID of the node's Bro process if running, and - None otherwise. - - .. _Node.getPort: - - **getPort** (self) - - Returns an integer with the port that this node's communication - system is listening on for incoming connections, or -1 if no such port - has been set yet. - - .. _Node.hasCrashed: - - **hasCrashed** (self) - - Returns True if the node's Bro process has exited abnormally. - - -Miscellaneous -------------- - -Mails -~~~~~ - -*BroControl* sends four types of mails to the address given in -``MailTo``: - -1. When logs are rotated (per default once a day), a list of all - alarms during the last rotation interval is sent. This can be - disabled by setting ``MailAlarms=0``. - -2. When the ``cron`` command notices that a node has crashed, it - restarts it and sends a notification. It may also send a more - detailed crash report containing information about the crash. - -3. NOTICES with a notice action ``EMAIL``. - -4. If `trace-summary `_ - is installed, a traffic summary is sent each rotation interval. - -Performance Analysis -~~~~~~~~~~~~~~~~~~~~ - -*TODO*: ``broctl cron`` logs a number of statistics, which can be -analyzed/plotted for understanding the clusters run-time behavior. - -Questions and Answers ---------------------- - -*Can I use an NFS-mounted partition as the cluster's base directory to avoid the ``rsync``'ing?* - Yes. BroBase_ can be on an NFS partition. - Configure and install the shell as usual with - ``--prefix=``. Then add ``HaveNFS=1`` and - ``SpoolDir=`` to ``broctl.cfg``, where ```` is a - path on the local disks of the nodes; ```` will be used for - all non-shared data (make sure that the parent directory exists - and is writable on all nodes!). Then run ``make install`` again. - Finally, you can remove ``/spool`` (or link it to ). - In addition, you might want to keep the log files locally on the nodes - as well by setting LogDir_ to a non-NFS directory. (Only - the manager's logs will be kept permanently, the logs of - workers/proxies are discarded upon rotation.) - -*When I'm using the stand-alone mode, do I still need to have ``ssh`` and ``rsync`` installed and configured?* - No. In stand-alone mode all operations are performed directly on the local - file system. - -*What do I need to do when something in the Bro distribution changes?* - After pulling from the main Bro git repository, just re-run ``make - install`` inside your build directory. It will reinstall all the - files from the distribution that are not up-to-date. Then do - ``broctl install`` to make sure everything gets pushed out. - -*Can I change the naming scheme that BroControl uses for archived log files?* - Yes, set MakeArchiveName_ to a - script that outputs the desired destination file name for an - archived log file. The default script for that task is - ``/share/broctl/scripts/make-archive-name``, which you - can use as a template for creating your own version. See - the beginning of that script for instructions. - -*Can BroControl manage a cluster of nodes over non-global IPv6 scope (e.g. link-local)?* - Yes, set ``ZoneID`` in ``broctl.cfg`` to the zone identifier - that the BroControl node uses to identify the scope zone - (the ``ifconfig`` command output is usually helpful, if it doesn't - show the zone identifier appended to the address with a '%' - character, then it may just be the interface name). Then in - ``node.cfg``, add a ``zone_id`` key to each node section - representing that particular node's zone identifier and set - the ``host`` key to the IPv6 address assigned to the node within - the scope zone. Most nodes probably have the same ``zone_id``, but - may not if their interface configuration differs. See RFC 4007 for - more information on IPv6 scoped addresses and zones. diff --git a/doc/components/broctl/README.rst b/doc/components/broctl/README.rst new file mode 120000 index 0000000000..cba305f48a --- /dev/null +++ b/doc/components/broctl/README.rst @@ -0,0 +1 @@ +../../../aux/broctl/doc/broctl.rst \ No newline at end of file diff --git a/doc/components/btest/README.rst b/doc/components/btest/README.rst deleted file mode 100644 index 03a859e735..0000000000 --- a/doc/components/btest/README.rst +++ /dev/null @@ -1,843 +0,0 @@ -.. -*- mode: rst-mode -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 0.4-14 - -============================================ -BTest - A Simple Driver for Basic Unit Tests -============================================ - -.. rst-class:: opening - - The ``btest`` is a simple framework for writing unit tests. Freely - borrowing some ideas from other packages, it's main objective is to - provide an easy-to-use, straightforward driver for a suite of - shell-based tests. Each test consists of a set of command lines that - will be executed, and success is determined based on their exit - codes. ``btest`` comes with some additional tools that can be used - within such tests to compare output against a previously established - baseline. - -.. contents:: - -Download -======== - -You can find the latest BTest release for download at -http://www.bro.org/download. - -BTest's git repository is located at `git://git.bro.org/btest.git -`__. You can browse the repository -`here `__. - -This document describes BTest |version|. See the ``CHANGES`` -file for version history. - - -Installation -============ - -Installation is simple and standard:: - - tar xzvf btest-*.tar.gz - cd btest-* - python setup.py install - -This will install a few scripts: ``btest`` is the main driver program, -and there are a number of further helper scripts that we discuss below -(including ``btest-diff``, which is a tool for comparing output to a -previously established baseline). - -Writing a Simple Test -===================== - -In the most simple case, ``btest`` simply executes a set of command -lines, each of which must be prefixed with ``@TEST-EXEC:`` -:: - - > cat examples/t1 - @TEST-EXEC: echo "Foo" | grep -q Foo - @TEST-EXEC: test -d . - > btest examples/t1 - examples.t1 ... ok - -The test passes as both command lines return success. If one of them -didn't, that would be reported:: - - > cat examples/t2 - @TEST-EXEC: echo "Foo" | grep -q Foo - @TEST-EXEC: test -d DOESNOTEXIST - > btest examples/t2 - examples.t2 ... failed - -Usually you will just run all tests found in a directory:: - - > btest examples - examples.t1 ... ok - examples.t2 ... failed - 1 test failed - -Why do we need the ``@TEST-EXEC:`` prefixes? Because the file -containing the test can simultaneously act as *its input*. Let's -say we want to verify a shell script:: - - > cat examples/t3.sh - # @TEST-EXEC: sh %INPUT - ls /etc | grep -q passwd - > btest examples/t3.sh - examples.t3 ... ok - -Here, ``btest`` is executing (something similar to) ``sh -examples/t3.sh``, and then checks the return value as usual. The -example also shows that the ``@TEST-EXEC`` prefix can appear -anywhere, in particular inside the comment section of another -language. - -Now, let's say we want to check the output of a program, making sure -that it matches what we expect. For that, we first add a command -line to the test that produces the output we want to check, and then -run ``btest-diff`` to make sure it matches a previously recorded -baseline. ``btest-diff`` is itself just a script that returns -success if the output is as expected, and failure otherwise. In the -following example, we use an awk script as a fancy way to print all -file names starting with a dot in the user's home directory. We -write that list into a file called ``dots`` and then check whether -its content matches what we know from last time:: - - > cat examples/t4.awk - # @TEST-EXEC: ls -a $HOME | awk -f %INPUT >dots - # @TEST-EXEC: btest-diff dots - /^\.+/ { print $1 } - -Note that each test gets its own little sandbox directory when run, -so by creating a file like ``dots``, you aren't cluttering up -anything. - -The first time we run this test, we need to record a baseline:: - - > btest -U examples/t4.awk - -Now, ``btest-diff`` has remembered what the ``dots`` file should -look like:: - - > btest examples/t4.awk - examples.t4 ... ok - > touch ~/.NEWDOTFILE - > btest examples/t4.awk - examples.t4 ... failed - 1 test failed - -If we want to see what exactly the unexpected change is that was -introduced to ``dots``, there's a *diff* mode for that:: - - > btest -d examples/t4.awk - examples.t4 ... failed - % 'btest-diff dots' failed unexpectedly (exit code 1) - % cat .diag - == File =============================== - [... current dots file ...] - == Diff =============================== - --- /Users/robin/work/binpacpp/btest/Baseline/examples.t4/dots - 2010-10-28 20:11:11.000000000 -0700 - +++ dots 2010-10-28 20:12:30.000000000 -0700 - @@ -4,6 +4,7 @@ - .CFUserTextEncoding - .DS_Store - .MacOSX - +.NEWDOTFILE - .Rhistory - .Trash - .Xauthority - ======================================= - - % cat .stderr - [... if any of the commands had printed something to stderr, that would follow here ...] - -Once we delete the new file, we are fine again:: - - > rm ~/.NEWDOTFILE - > btest -d examples/t4.awk - examples.t4 ... ok - -That's already the main functionality that the ``btest`` package -provides. In the following, we describe a number of further options -extending/modifying this basic approach. - -Reference -========= - -Command Line Usage ------------------- - -``btest`` must be started with a list of tests and/or directories -given on the command line. In the latter case, the default is to -recursively scan the directories and assume all files found to be -tests to perform. It is however possible to exclude certain files by -specifying a suitable `configuration file`_. - -``btest`` returns exit code 0 if all tests have successfully passed, -and 1 otherwise. - -``btest`` accepts the following options: - - -a ALTERNATIVE, --alternative=ALTERNATIVE - Activates an alternative_ configuration defined in the - configuration file. This option can be given multiple times to - run tests with several alternatives. If ``ALTERNATIVE`` is ``-`` - that refers to running with the standard setup, which can be used - to run tests both with and without alterantives by giving both. - - -b, --brief - Does not output *anything* for tests which pass. If all tests - pass, there will not be any output at all. - - -c CONFIG, --config=CONFIG - Specifies an alternative `configuration file`_ to use. If not - specified, the default is to use a file called ``btest.cfg`` - if found in the current directory. - - -d, --diagnostics - Reports diagnostics for all failed tests. The diagnostics - include the command line that failed, its output to standard - error, and potential additional information recorded by the - command line for diagnostic purposes (see `@TEST-EXEC`_ - below). In the case of ``btest-diff``, the latter is the - ``diff`` between baseline and actual output. - - -D, --diagnostics-all - Reports diagnostics for all tests, including those which pass. - - -f DIAGFILE, --file-diagnostics=DIAGFILE - Writes diagnostics for all failed tests into the given file. - If the file already exists, it will be overwritten. - - -g GROUPS, --group=GROUPS - Runs only tests assigned to the given test groups, see - `@TEST-GROUP`_. Multiple groups can be given as a - comma-separated list. Specifying ``-`` as a group name selects - all tests that do not belong to any group. - - -j [THREADS], --jobs[=THREADS] - Runs up to the given number of tests in parallel. If no number - is given, BTest substitutes the number of available CPU cores - as reported by the OS. - - By default, BTest assumes that all tests can be executed - concurrently without further constraints. One can however - ensure serialization of subsets by assigning them to the same - serialization set, see `@TEST-SERIALIZE`_. - - -q, --quiet - Suppress information output other than about failed tests. - If all tests pass, there will not be any output at all. - - -r, --rerun - Runs only tests that failed last time. After each execution - (except when updating baselines), BTest generates a state file - that records the tests that have failed. Using this option on - the next run then reads that file back in and limits execution - to those tests found in there. - - -t, --tmp-keep - Does not delete any temporary files created for running the - tests (including their outputs). By default, the temporary - files for a test will be located in ``.tmp//``, where - ```` is the relative path of the test file with all slashes - replaced with dots and the file extension removed (e.g., the files - for ``example/t3.sh`` will be in ``.tmp/example.t3``). - - -U, --update-baseline - Records a new baseline for all ``btest-diff`` commands found - in any of the specified tests. To do this, all tests are run - as normal except that when ``btest-diff`` is executed, it - does not compute a diff but instead considers the given file - to be authoritative and records it as the version to compare - with in future runs. - - -u, --update-interactive - Each time a ``btest-diff`` command fails in any tests that are - run, btest will stop and ask whether or not the user wants to - record a new baseline. - - -v, --verbose - Shows all test command lines as they are executed. - - -w, --wait - Interactively waits for ```` after showing diagnostics - for a test. - - -x FILE, --xml=FILE - Records test results in JUnit XML format to the given file. - If the file exists already, it is overwritten. - -.. _configuration file: - -Configuration -------------- - -Specifics of ``btest``'s execution can be tuned with a configuration -file, which by default is ``btest.cfg`` if that's found in the -current directory. It can alternatively be specified with the -``--config`` command line option. The configuration file is -"INI-style", and an example comes with the distribution, see -``btest.cfg.example``. A configuration file has one main section, -``btest``, that defines most options; as well as an optional section -for defining `environment variables`_ and further optional sections -for defining alternatives_. - -Note that all paths specified in the configuration file are relative -to ``btest``'s *base directory*. The base directory is either the -one where the configuration file is located if such is given/found, -or the current working directory if not. When setting values for -configuration options, the absolute path to the base directory is -available by using the macro ``%(testbase)s`` (the weird syntax is -due to Python's ``ConfigParser`` module). - -Furthermore, all values can use standard "backtick-syntax" to -include the output of external commands (e.g., xyz=`\echo test\`). -Note that the backtick expansion is performed after any ``%(..)`` -have already been replaced (including within the backticks). - -Options -~~~~~~~ - -The following options can be set in the ``btest`` section of the -configuration file: - -``TestDirs`` - A space-separated list of directories to search for tests. If - defined, one doesn't need to specify any tests on the command - line. - -``TmpDir`` - A directory where to create temporary files when running tests. - By default, this is set to ``%(testbase)s/.tmp``. - -``BaselineDir`` - A directory where to store the baseline files for ``btest-diff``. - By default, this is set to ``%(testbase)s/Baseline``. - -``IgnoreDirs`` - A space-separated list of relative directory names to ignore - when scanning test directories recursively. Default is empty. - -``IgnoreFiles`` - A space-separated list of filename globs matching files to - ignore when scanning given test directories recursively. - Default is empty. - -``StateFile`` - The name of the state file to record the names of failing tests. Default is - ``.btest.failed.dat``. - -``Finalizer`` - An executable that will be executed each time any test has - successfully run. It runs in the same directory as the test itself - and receives the name of the test as its parameter. The return - value indicates whether the test should indeed be considered - successful. By default, there's no finalizer set. - -.. _environment variables: - -Environment Variables -~~~~~~~~~~~~~~~~~~~~~ - -A special section ``environment`` defines environment variables that -will be propagated to all tests:: - - [environment] - CFLAGS=-O3 - PATH=%(testbase)s/bin:%(default_path)s - -Note how ``PATH`` can be adjusted to include local scripts: the -example above prefixes it with a local ``bin/`` directory inside the -base directory, using the predefined ``default_path`` macro to refer -to the ``PATH`` as it is set by default. - -Furthermore, by setting ``PATH`` to include the ``btest`` -distribution directory, one could skip the installation of the -``btest`` package. - -.. _alternative: - -Alternatives -~~~~~~~~~~~~ - -BTest can run a set of tests with different settings than it would -normally use by specifying an *alternative* configuration. Currently, -three things can be adjusted: - - - Further environment variables can be set that will then be - available to all the commands that a test executes. - - - *Filters* can modify an input file before a test uses it. - - - *Substitutions* can modify command lines executed as part of a - test. - -We discuss the three separately in the following. All of them are -defined by adding sections ``[-]`` where ```` -corresponds to the type of adjustment being made and ```` is the -name of the alternative. Once at least one section is defined for a -name, that alternative can be enabled by BTest's ``--alternative`` -flag. - -Environment Variables -^^^^^^^^^^^^^^^^^^^^^ - -An alternative can add further environment variables by defining an -``[environment-]`` section: - - [environment-myalternative] - CFLAGS=-O3 - -Running ``btest`` with ``--alternative=myalternative`` will now make -the ``CFLAGS`` environment variable available to all commands -executed. - -.. _filters: - -Filters -^^^^^^^ - -Filters are a transparent way to adapt the input to a specific test -command before it is executed. A filter is defined by adding a section -``[filter-]`` to the configuration file. This section must have -exactly one entry, and the name of that entry is interpreted as the -name of a command whose input is to be filtered. The value of that -entry is the name of a filter script that will be run with two -arguments representing input and output files, respectively. Example:: - - [filter-myalternative] - cat=%(testbase)s/bin/filter-cat - -Once the filter is activated by running ``btest`` with -``--alternative=myalternative``, every time a ``@TEST-EXEC: cat -%INPUT`` is found, ``btest`` will first execute (something similar to) -``%(testbase)s/bin/filter-cat %INPUT out.tmp``, and then subsequently -``cat out.tmp`` (i.e., the original command but with the filtered -output). In the simplest case, the filter could be a no-op in the -form ``cp $1 $2``. - -.. note:: - There are a few limitations to the filter concept currently: - - * Filters are *always* fed with ``%INPUT`` as their first - argument. We should add a way to filter other files as well. - - * Filtered commands are only recognized if they are directly - starting the command line. For example, ``@TEST-EXEC: ls | cat - >outout`` would not trigger the example filter above. - - * Filters are only executed for ``@TEST-EXEC``, not for - ``@TEST-EXEC-FAIL``. - -.. _substitution: - -Substitutions -^^^^^^^^^^^^^^ - -Substitutions are similar to filters, yet they do not adapt the input -but the command line being executed. A substitution is defined by -adding a section ``[substitution-]`` to the configuration file. -For each entry in this section, the entry's name specifies the -command that is to be replaced with something else given as its value. -Example:: - - [substitution-myalternative] - gcc=gcc -O2 - -Once the substitution is activated by running ``btest`` with -``--alternative=myalternative``, every time a ``@TEST-EXEC`` executes -``gcc``, that is replaced with ``gcc -O2``. The replacement is simple -string substitution so it works not only with commands but anything -found on the command line; it however only replaces full words, not -subparts of words. - -Writing Tests -------------- - -``btest`` scans a test file for lines containing keywords that -trigger certain functionality. Currently, the following keywords are -supported: - -.. _@TEST-EXEC: - -``@TEST-EXEC: `` - Executes the given command line and aborts the test if it - returns an error code other than zero. The ```` is - passed to the shell and thus can be a pipeline, use redirection, - and any environment variables specified in ```` will be - expanded, etc. - - When running a test, the current working directory for all - command lines will be set to a temporary sandbox (and will be - deleted later). - - There are two macros that can be used in ````: - ``%INPUT`` will be replaced with the full pathname of the file defining - the test; and ``%DIR`` will be replaced with the directory where - the test file is located. The latter can be used to reference - further files also located there. - - In addition to environment variables defined in the - configuration file, there are further ones that are passed into - the commands: - - ``TEST_DIAGNOSTICS`` - A file where further diagnostic information can be saved - in case a command fails. ``--diagnostics`` will show - this file. (This is also where ``btest-diff`` stores its - diff.) - - ``TEST_MODE`` - This is normally set to ``TEST``, but will be ``UPDATE`` - if ``btest`` is run with ``--update-baseline``, or - ``UPDATE_INTERACTIVE`` if run with ``--update-interactive``. - - ``TEST_BASELINE`` - The name of a directory where the command can save permanent - information across ``btest`` runs. (This is where - ``btest-diff`` stores its baseline in ``UPDATE`` mode.) - - ``TEST_NAME`` - The name of the currently executing test. - - ``TEST_VERBOSE`` - The path of a file where the test can record further - information about its execution that will be included with - btest's ``--verbose`` output. This is for further tracking - the execution of commands and should generally generate - output that follows a line-based structure. - - .. note:: - - If a command returns the special exit code 100, the test is - considered failed, however subsequent test commands are still - run. ``btest-diff`` uses this special exit code to indicate that - no baseline has yet been established. - - If a command returns the special exit code 200, the test is - considered failed and all further test executions are aborted. - - -``@TEST-EXEC-FAIL: `` - Like ``@TEST-EXEC``, except that this expects the command to - *fail*, i.e., the test is aborted when the return code is zero. - -``@TEST-REQUIRES: `` - Defines a condition that must be met for the test to be executed. - The given command line will be run before any of the actual test - commands, and it must return success for the test to continue. If - it does not return success, the rest of the test will be skipped - but doing so will not be considered a failure of the test. This allows to - write conditional tests that may not always make sense to run, depending - on whether external constraints are satisfied or not (say, whether - a particular library is available). Multiple requirements may be - specified and then all must be met for the test to continue. - -``@TEST-ALTERNATIVE: `` Runs this test only for the given - alternative (see alternative_). If ```` is - ``default``, the test executes when BTest runs with no alternative - given (which however is the default anyways). - -``@TEST-NOT-ALTERNATIVE: `` Ignores this test for the - given alternative (see alternative_). If ```` is - ``default``, the test is ignored if BTest runs with no alternative - given. - -``@TEST-COPY-FILE: `` - Copy the given file into the test's directory before the test is - run. If ```` is a relative path, it's interpreted relative - to the BTest's base directory. Environment variables in ```` - will be replaced if enclosed in ``${..}``. This command can be - given multiple times. - -``@TEST-START-NEXT`` - This is a short-cut for defining multiple test inputs in the - same file, all executing with the same command lines. When - ``@TEST-START-NEXT`` is encountered, the test file is initially - considered to end at that point, and all ``@TEST-EXEC-*`` are - run with an ``%INPUT`` truncated accordingly. Afterwards, a - *new* ``%INPUT`` is created with everything *following* the - ``@TEST-START-NEXT`` marker, and the *same* commands are run - again (further ``@TEST-EXEC-*`` will be ignored). The effect is - that a single file can actually define two tests, and the - ``btest`` output will enumerate them:: - - > cat examples/t5.sh - # @TEST-EXEC: cat %INPUT | wc -c >output - # @TEST-EXEC: btest-diff output - - This is the first test input in this file. - - # @TEST-START-NEXT - - ... and the second. - - > ./btest -D examples/t5.sh - examples.t5 ... ok - % cat .diag - == File =============================== - 119 - [...] - - examples.t5-2 ... ok - % cat .diag - == File =============================== - 22 - [...] - - Multiple ``@TEST-START-NEXT`` can be used to create more than - two tests per file. - -``@TEST-START-FILE `` - This is used to include an additional input file for a test - right inside the test file. All lines following the keyword will - be written into the given file (and removed from the test's - `%INPUT`) until a terminating ``@TEST-END-FILE`` is found. - Example:: - - > cat examples/t6.sh - # @TEST-EXEC: awk -f %INPUT output - # @TEST-EXEC: btest-diff output - - { lines += 1; } - END { print lines; } - - @TEST-START-FILE foo.dat - 1 - 2 - 3 - @TEST-END-FILE - - > btest -D examples/t6.sh - examples.t6 ... ok - % cat .diag - == File =============================== - 3 - - Multiple such files can be defined within a single test. - - Note that this is only one way to use further input files. - Another is to store a file in the same directory as the test - itself, making sure it's ignored via ``IgnoreFiles``, and then - refer to it via ``%DIR/``. - -.. _@TEST-GROUP: - -``@TEST-GROUP: `` - Assigns the test to a group of name ````. By using option - ``-g`` one can limit execution to all tests that belong to a given - group (or a set of groups). - -.. _@TEST-SERIALIZE: - -``@TEST-SERIALIZE: `` - When using option ``-j`` to parallelize execution, all tests that - specify the same serialization set are guaranteed to run - sequentially. ```` is an arbitrary user-chosen string. - - -Canonifying Diffs -================= - -``btest-diff`` has the capability to filter its input through an -additional script before it compares the current version with the -baseline. This can be useful if certain elements in an output are -*expected* to change (e.g., timestamps). The filter can then -remove/replace these with something consistent. To enable such -canonification, set the environment variable -``TEST_DIFF_CANONIFIER`` to a script reading the original version -from stdin and writing the canonified version to stdout. Note that -both baseline and current output are passed through the filter -before their differences are computed. - -Running Processes in the Background -=================================== - -Sometimes processes need to be spawned in the background for a test, -in particular if multiple processes need to cooperate in some fashion. -``btest`` comes with two helper scripts to make life easier in such a -situation: - -``btest-bg-run `` - This is a script that runs ```` in the background, i.e., - it's like using ``cmdline &`` in a shell script. Test execution - continues immediately with the next command. Note that the spawned - command is *not* run in the current directory, but instead in a - newly created sub-directory called ````. This allows - spawning multiple instances of the same process without needing to - worry about conflicting outputs. If you want to access a command's - output later, like with ``btest-diff``, use ``/foo.log`` to - access it. - -``btest-bg-wait [-k] `` - This script waits for all processes previously spawned via - ``btest-bg-run`` to finish. If any of them exits with a non-zero - return code, ``btest-bg-wait`` does so as well, indicating a - failed test. ```` is mandatory and gives the maximum - number of seconds to wait for any of the processes to terminate. - If any process hasn't done so when the timeout expires, it will be - killed and the test is considered to be failed as long as ``-k`` - is not given. If ``-k`` is given, pending processes are still - killed but the test continues normally, i.e., non-termination is - not considered a failure in this case. This script also collects - the processes' stdout and stderr outputs for diagnostics output. - -Integration with Sphinx -======================= - -``btest`` comes with a new directive for the documentation framework -`Sphinx `_. The directive allows to write a -test directly inside a Sphinx document, and then to include output -from the test's command into the generated documentation. The same -tests can also run externally and will catch if any changes to the -included content occur. The following walks through setting this up. - -Configuration -------------- - -First, you need to tell Sphinx a base directory for the ``btest`` -configuration as well as a directory in there where to store tests -it extracts from the Sphinx documentation. Typically, you'd just -create a new subdirectory ``tests`` in the Sphinx project for the -``btest`` setup and then store the tests in there in, e.g., -``doc/``:: - - cd - mkdir tests - mkdir tests/doc - -Then add the following to your Sphinx ``conf.py``:: - - extensions += ["btest-sphinx"] - btest_base="tests" # Relative to Sphinx-root. - btest_tests="doc" # Relative to btest_base. - -Next, a finalizer to ``btest.cfg``:: - - [btest] - ... - Finalizer=btest-diff-rst - -Finally, create a ``btest.cfg`` in ``tests/`` as usual and add -``doc/`` to the ``TestDirs`` option. - -Including a Test into a Sphinx Document ---------------------------------------- - -The ``btest`` extension provides a new directive to include a test -inside a Sphinx document:: - - - .. btest:: - - - -Here, ```` is a custom name for the test; it will be -stored in ``btest_tests`` under that name. ```` is just -a standard test as you would normally put into one of the -``TestDirs``. Example:: - - - .. btest:: just-a-test - - @TEST-EXEC: expr 2 + 2 - -When you now run Sphinx, it will (1) store the test content into -``tests/doc/just-a-test`` (assuming the above path layout), and (2) -execute the test by running ``btest`` on it. You can then run -``btest`` manually in ``tests/`` as well and it will execute the test -just as it would in a standard setup. If a test fails when Sphinx runs -it, there will be a corresponding error and include the diagnostic output -into the document. - -By default, nothing else will be included into the generated -documentation, i.e., the above test will just turn into an empty text -block. However, ``btest`` comes with a set of scripts that you can use -to specify content to be included. As a simple example, -``btest-rst-cmd `` will execute a command and (if it -succeeds) include both the command line and the standard output into -the documentation. Example:: - - .. btest:: another-test - - @TEST-EXEC: btest-rst-cmd echo Hello, world! - -When running Sphinx, this will render as: - -.. code:: - - # echo Hello, world! - Hello world! - - -When running ``btest`` manually in ``tests/``, the ``Finalizer`` we -added to ``btest.cfg`` (see above) compares the generated reST code -with a previously established baseline, just like ``btest-diff`` does -with files. To establish the initial baseline, run ``btest -u``, like -you would with ``btest-diff``. - -Scripts -------- - -The following Sphinx support scripts come with ``btest``: - -``btest-rst-cmd [options] `` - - By default, this executes ```` and includes both the - command line itself and its standard output into the generated - documentation. See above for an example. - - This script provides the following options: - - -c ALTERNATIVE_CMDLINE - Show ``ALTERNATIVE_CMDLINE`` in the generated - documentation instead of the one actually executed. (It - still runs the ```` given outside the option.) - - -d - Do not actually execute ````; just format it for - the generated documentation and include no further output. - - -f FILTER_CMD - Pipe the command line's output through ``FILTER_CMD`` - before including. If ``-r`` is given, it filters the - file's content instead of stdout. - - -o - Do not include the executed command into the generated - documentation, just its output. - - -r FILE - Insert ``FILE`` into output instead of stdout. - - -``btest-rst-include `` - - Includes ```` inside a code block. - -``btest-rst-pipe `` - - Executes ````, includes its standard output inside a code - block. Note that this script does not include the command line - itself into the code block, just the output. - -.. note:: - - All these scripts can be run directly from the command line to show - the reST code they generate. - -.. note:: - - ``btest-rst-cmd`` can do everything the other scripts provide if - you give it the right options. In fact, the other scripts are - provided just for convenience and leverage ``btest-rst-cmd`` - internally. - -License -======= - -btest is open-source under a BSD licence. - diff --git a/doc/components/btest/README.rst b/doc/components/btest/README.rst new file mode 120000 index 0000000000..0da2935df1 --- /dev/null +++ b/doc/components/btest/README.rst @@ -0,0 +1 @@ +../../../aux/btest/README \ No newline at end of file diff --git a/doc/components/capstats/README.rst b/doc/components/capstats/README.rst deleted file mode 100644 index 1ddc07c51c..0000000000 --- a/doc/components/capstats/README.rst +++ /dev/null @@ -1,107 +0,0 @@ -.. -*- mode: rst-mode -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 0.18 - -=============================================== -capstats - A tool to get some NIC statistics. -=============================================== - -.. rst-class:: opening - - capstats is a small tool to collect statistics on the - current load of a network interface, using either `libpcap - `_ or the native interface for `Endace's - `_. It reports statistics per time interval - and/or for the tool's total run-time. - -Download --------- - -You can find the latest capstats release for download at -http://www.bro.org/download. - -Capstats's git repository is located at `git://git.bro.org/capstats.git -`__. You can browse the repository -`here `__. - -This document describes capstats |version|. See the ``CHANGES`` -file for version history. - - -Output ------- - -Here's an example output with output in one-second intervals until -``CTRL-C`` is hit: - -.. console:: - - >capstats -i nve0 -I 1 - 1186620936.890567 pkts=12747 kpps=12.6 kbytes=10807 mbps=87.5 nic_pkts=12822 nic_drops=0 u=960 t=11705 i=58 o=24 nonip=0 - 1186620937.901490 pkts=13558 kpps=13.4 kbytes=11329 mbps=91.8 nic_pkts=13613 nic_drops=0 u=1795 t=24339 i=119 o=52 nonip=0 - 1186620938.912399 pkts=14771 kpps=14.6 kbytes=13659 mbps=110.7 nic_pkts=14781 nic_drops=0 u=2626 t=38154 i=185 o=111 nonip=0 - 1186620939.012446 pkts=1332 kpps=13.3 kbytes=1129 mbps=92.6 nic_pkts=1367 nic_drops=0 u=2715 t=39387 i=194 o=112 nonip=0 - === Total - 1186620939.012483 pkts=42408 kpps=13.5 kbytes=36925 mbps=96.5 nic_pkts=1 nic_drops=0 u=2715 t=39387 i=194 o=112 nonip=0 - -Each line starts with a timestamp and the other fields are: - - :pkts: - Absolute number of packets seen by ``capstats`` during interval. - - :kpps: - Number of packets per second. - - :kbytes: - Absolute number of KBytes during interval. - - :mbps: - Mbits/sec. - - :nic_pkts: - Number of packets as reported by ``libpcap``'s ``pcap_stats()`` (may not match _pkts_) - - :nic_drops: - Number of packet drops as reported by ``libpcap``'s ``pcap_stats()``. - - :u: - Number of UDP packets. - - :t: - Number of TCP packets. - - :i: - Number of ICMP packets. - - :nonip: - Number of non-IP packets. - -Options -------- - -A list of all options:: - - capstats [Options] -i interface - - -i| --interface Listen on interface - -d| --dag Use native DAG API - -f| --filter BPF filter - -I| --interval Stats logging interval - -l| --syslog Use syslog rather than print to stderr - -n| --number Stop after outputting intervals - -N| --select Use select() for live pcap (for testing only) - -p| --payload Verifies that packets' payloads consist - entirely of bytes of the given value. - -q| --quiet Suppress output, exit code indicates >= count - packets received. - -S| --size Verify packets to have given - -s| --snaplen Use pcap snaplen - -v| --version Print version and exit - -w| --write Write packets to file - -Installation ------------- - -``capstats`` has been tested on Linux, FreeBSD, and MacOS. Please see -the ``INSTALL`` file for installation instructions. diff --git a/doc/components/capstats/README.rst b/doc/components/capstats/README.rst new file mode 120000 index 0000000000..cb2380145d --- /dev/null +++ b/doc/components/capstats/README.rst @@ -0,0 +1 @@ +../../../aux/broctl/aux/capstats/README \ No newline at end of file diff --git a/doc/components/pysubnettree/README.rst b/doc/components/pysubnettree/README.rst deleted file mode 100644 index be97eef9e3..0000000000 --- a/doc/components/pysubnettree/README.rst +++ /dev/null @@ -1,98 +0,0 @@ -.. -*- mode: rst-mode -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 0.19-9 - -=============================================== -PySubnetTree - A Python Module for CIDR Lookups -=============================================== - -.. rst-class:: opening - - The PySubnetTree package provides a Python data structure - ``SubnetTree`` which maps subnets given in `CIDR - `_ notation (incl. - corresponding IPv6 versions) to Python objects. Lookups are - performed by longest-prefix matching. - - -Download --------- - -You can find the latest PySubnetTree release for download at -http://www.bro.org/download. - -PySubnetTree's git repository is located at `git://git.bro.org/pysubnettree.git -`__. You can browse the repository -`here `__. - -This document describes PySubnetTree |version|. See the ``CHANGES`` -file for version history. - - -Example -------- - -A simple example which associates CIDR prefixes with strings:: - - >>> import SubnetTree - >>> t = SubnetTree.SubnetTree() - >>> t["10.1.0.0/16"] = "Network 1" - >>> t["10.1.42.0/24"] = "Network 1, Subnet 42" - >>> t["10.2.0.0/16"] = "Network 2" - >>> print t["10.1.42.1"] - Network 1, Subnet 42 - >>> print t["10.1.43.1"] - Network 1 - >>> print "10.1.42.1" in t - True - >>> print "10.1.43.1" in t - True - >>> print "10.20.1.1" in t - False - >>> print t["10.20.1.1"] - Traceback (most recent call last): - File "", line 1, in - File "SubnetTree.py", line 67, in __getitem__ - def __getitem__(*args): return _SubnetTree.SubnetTree___getitem__(*args) - KeyError: '10.20.1.1' - -By default, CIDR prefixes and IP addresses are given as strings. -Alternatively, a ``SubnetTree`` object can be switched into *binary -mode*, in which single addresses are passed in the form of packed -binary strings as, e.g., returned by `socket.inet_aton -`_:: - - - >>> t.get_binary_lookup_mode() - False - >>> t.set_binary_lookup_mode(True) - >>> t.binary_lookup_mode() - True - >>> import socket - >>> print t[socket.inet_aton("10.1.42.1")] - Network 1, Subnet 42 - -A SubnetTree also provides methods ``insert(prefix,object=None)`` for insertion -of prefixes (``object`` can be skipped to use the tree like a set), and -``remove(prefix)`` for removing entries (``remove`` performs an _exact_ match -rather than longest-prefix). - -Internally, the CIDR prefixes of a ``SubnetTree`` are managed by a -Patricia tree data structure and lookups are therefore efficient -even with a large number of prefixes. - -PySubnetTree comes with a BSD license. - - -Prerequisites -------------- - -This package requires Python 2.4 or newer. - -Installation ------------- - -Installation is pretty simple:: - - > python setup.py install diff --git a/doc/components/pysubnettree/README.rst b/doc/components/pysubnettree/README.rst new file mode 120000 index 0000000000..42ce17d303 --- /dev/null +++ b/doc/components/pysubnettree/README.rst @@ -0,0 +1 @@ +../../../aux/broctl/aux/pysubnettree/README \ No newline at end of file diff --git a/doc/components/trace-summary/README.rst b/doc/components/trace-summary/README.rst deleted file mode 100644 index a47381fc37..0000000000 --- a/doc/components/trace-summary/README.rst +++ /dev/null @@ -1,154 +0,0 @@ -.. -*- mode: rst-mode -*- -.. -.. Version number is filled in automatically. -.. |version| replace:: 0.8 - -==================================================== -trace-summary - Generating network traffic summaries -==================================================== - -.. rst-class:: opening - - ``trace-summary`` is a Python script that generates break-downs of - network traffic, including lists of the top hosts, protocols, - ports, etc. Optionally, it can generate output separately for - incoming vs. outgoing traffic, per subnet, and per time-interval. - -Download --------- - -You can find the latest trace-summary release for download at -http://www.bro.org/download. - -trace-summary's git repository is located at `git://git.bro.org/trace-summary.git -`__. You can browse the repository -`here `__. - -This document describes trace-summary |version|. See the ``CHANGES`` -file for version history. - - -Overview --------- - -The ``trace-summary`` script reads both packet traces in `libpcap -`_ format and connection logs produced by the -`Bro `_ network intrusion detection system -(for the latter, it supports both 1.x and 2.x output formats). - -Here are two example outputs in the most basic form (note that IP -addresses are 'anonymized'). The first is from a packet trace and the -second from a Bro connection log:: - - - >== Total === 2005-01-06-14-23-33 - 2005-01-06-15-23-43 - - Bytes 918.3m - Payload 846.3m - Pkts 1.8m - Frags 0.9% - MBit/s 1.9 - - Ports | Sources | Destinations | Protocols | - 80 33.8% | 131.243.89.214 8.5% | 131.243.89.214 7.7% | 6 76.0% | - 22 16.7% | 128.3.2.102 6.2% | 128.3.2.102 5.4% | 17 23.3% | - 11001 12.4% | 204.116.120.26 4.8% | 131.243.89.4 4.8% | 1 0.5% | - 2049 10.7% | 128.3.161.32 3.6% | 131.243.88.227 3.6% | | - 1023 10.6% | 131.243.89.4 3.5% | 204.116.120.26 3.4% | | - 993 8.2% | 128.3.164.194 2.7% | 131.243.89.64 3.1% | | - 1049 8.1% | 128.3.164.15 2.4% | 128.3.164.229 2.9% | | - 524 6.6% | 128.55.82.146 2.4% | 131.243.89.155 2.5% | | - 33305 4.5% | 131.243.88.227 2.3% | 128.3.161.32 2.3% | | - 1085 3.7% | 131.243.89.155 2.3% | 128.55.82.146 2.1% | | - - - >== Total === 2005-01-06-14-23-33 - 2005-01-06-15-23-42 - - Connections 43.4k - Payload 398.4m - - Ports | Sources | Destinations | Services | Protocols | States | - 80 21.7% | 207.240.215.71 3.0% | 239.255.255.253 8.0% | other 51.0% | 17 55.8% | S0 46.2% | - 427 13.0% | 131.243.91.71 2.2% | 131.243.91.255 4.0% | http 21.7% | 6 36.4% | SF 30.1% | - 443 3.8% | 128.3.161.76 1.7% | 131.243.89.138 2.1% | i-echo 7.3% | 1 7.7% | OTH 7.8% | - 138 3.7% | 131.243.90.138 1.6% | 255.255.255.255 1.7% | https 3.8% | | RSTO 5.8% | - 515 2.4% | 131.243.88.159 1.6% | 128.3.97.204 1.5% | nb-dgm 3.7% | | SHR 4.4% | - 11001 2.3% | 131.243.88.202 1.4% | 131.243.88.107 1.1% | printer 2.4% | | REJ 3.0% | - 53 1.9% | 131.243.89.250 1.4% | 117.72.94.10 1.1% | dns 1.9% | | S1 1.0% | - 161 1.6% | 131.243.89.80 1.3% | 131.243.88.64 1.1% | snmp 1.6% | | RSTR 0.9% | - 137 1.4% | 131.243.90.52 1.3% | 131.243.88.159 1.1% | nb-ns 1.4% | | SH 0.3% | - 2222 1.1% | 128.3.161.252 1.2% | 131.243.91.92 1.1% | ntp 1.0% | | RSTRH 0.2% | - - -Prerequisites -------------- - -* This script requires Python 2.4 or newer. - -* The `pysubnettree - `_ Python - module. - -* Eddie Kohler's `ipsumdump `_ - if using ``trace-summary`` with packet traces (versus Bro connection logs) - -Installation ------------- - -Simply copy the script into some directory which is in your ``PATH``. - -Usage ------ - -The general usage is:: - - trace-summary [options] [input-file] - -Per default, it assumes the ``input-file`` to be a ``libpcap`` trace -file. If it is a Bro connection log, use ``-c``. If ``input-file`` is -not given, the script reads from stdin. It writes its output to -stdout. - -Options -~~~~~~~ - -The most important options are summarized -below. Run ``trace-summary --help`` to see the full list including -some more esoteric ones. - -:-c: - Input is a Bro connection log instead of a ``libpcap`` trace - file. - -:-b: - Counts all percentages in bytes rather than number of - packets/connections. - -:-E : - Gives a file which contains a list of networks to ignore for the - analysis. The file must contain one network per line, where each - network is of the CIDR form ``a.b.c.d/mask`` (including the - corresponding syntax for IPv6 prefixes, e.g., ``1:2:3:4::/64``). - Empty lines and lines starting with a "#" are ignored. - -:-i : - Creates totals for each time interval of the given length - (default is seconds; add "``m``" for minutes and "``h``" for - hours). Use ``-v`` if you also want to see the breakdowns for - each interval. - -:-l : - Generates separate summaries for incoming and outgoing traffic. - ```` is a file which contains a list of networks to be - considered local. Format as for ``-E``. - -:-n : - Show top n entries in each break-down. Default is 10. - -:-r: - Resolves hostnames in the output. - -:-s : - Gives the sample factor if the input has been sampled. - -:-S : - Sample input with the given factor; less accurate but faster and - saves memory. - -:-m: - Does skip memory-expensive statistics. - -:-v: - Generates full break-downs for each time interval. Requires - ``-i``. diff --git a/doc/components/trace-summary/README.rst b/doc/components/trace-summary/README.rst new file mode 120000 index 0000000000..78778364bd --- /dev/null +++ b/doc/components/trace-summary/README.rst @@ -0,0 +1 @@ +../../../aux/broctl/aux/trace-summary/README \ No newline at end of file diff --git a/doc/frameworks/logging-dataseries.rst b/doc/frameworks/logging-dataseries.rst index 139a13f813..667edcbe14 100644 --- a/doc/frameworks/logging-dataseries.rst +++ b/doc/frameworks/logging-dataseries.rst @@ -104,7 +104,7 @@ code like this to your ``local.bro``: } Bro's DataSeries writer comes with a few tuning options, see -:doc:`scripts/base/frameworks/logging/writers/dataseries`. +:doc:`/scripts/base/frameworks/logging/writers/dataseries`. Working with DataSeries ======================= diff --git a/doc/frameworks/logging.rst b/doc/frameworks/logging.rst index 9c8df62043..93cbf24e84 100644 --- a/doc/frameworks/logging.rst +++ b/doc/frameworks/logging.rst @@ -48,7 +48,7 @@ Basics The data fields that a stream records are defined by a record type specified when it is created. Let's look at the script generating Bro's connection summaries as an example, -:doc:`scripts/base/protocols/conn/main`. It defines a record +:doc:`/scripts/base/protocols/conn/main`. It defines a record :bro:type:`Conn::Info` that lists all the fields that go into ``conn.log``, each marked with a ``&log`` attribute indicating that it is part of the information written out. To write a log record, the @@ -92,8 +92,8 @@ Note the fields that are set for the filter: are generated by taking the stream's ID and munging it slightly. :bro:enum:`Conn::LOG` is converted into ``conn``, :bro:enum:`PacketFilter::LOG` is converted into - ``packet_filter``, and :bro:enum:`Notice::POLICY_LOG` is - converted into ``notice_policy``. + ``packet_filter``, and :bro:enum:`Known::CERTS_LOG` is + converted into ``known_certs``. ``include`` A set limiting the fields to the ones given. The names @@ -309,7 +309,7 @@ ASCII Writer Configuration -------------------------- The ASCII writer has a number of options for customizing the format of -its output, see :doc:`scripts/base/frameworks/logging/writers/ascii`. +its output, see :doc:`/scripts/base/frameworks/logging/writers/ascii`. Adding Streams ============== @@ -369,7 +369,7 @@ save the logged ``Foo::Info`` record into the connection record: } See the existing scripts for how to work with such a new connection -field. A simple example is :doc:`scripts/base/protocols/syslog/main`. +field. A simple example is :doc:`/scripts/base/protocols/syslog/main`. When you are developing scripts that add data to the :bro:type:`connection` record, care must be given to when and how long data is stored. diff --git a/doc/frameworks/notice.rst b/doc/frameworks/notice.rst index 1630459b46..1f0cc9da11 100644 --- a/doc/frameworks/notice.rst +++ b/doc/frameworks/notice.rst @@ -283,7 +283,7 @@ information to suppress duplicates for a configurable period of time. The ``$identifier`` field is typically comprised of several pieces of data related to the notice that when combined represent a unique instance of that notice. Here is an example of the script -:doc:`scripts/policy/protocols/ssl/validate-certs` raising a notice +:doc:`/scripts/policy/protocols/ssl/validate-certs` raising a notice for session negotiations where the certificate or certificate chain did not validate successfully against the available certificate authority certificates. diff --git a/doc/quickstart/index.rst b/doc/quickstart/index.rst index e07e729a02..f570ac92db 100644 --- a/doc/quickstart/index.rst +++ b/doc/quickstart/index.rst @@ -1,4 +1,6 @@ +.. _FAQ: http://www.bro.org/documentation/faq.html + .. _quickstart: ================= @@ -60,9 +62,8 @@ policy and output the results in ``$PREFIX/logs``. .. note:: The user starting BroControl needs permission to capture network traffic. If you are not root, you may need to grant further - privileges to the account you're using; see the `FAQ - `_. Also, if it looks - like Bro is not seeing any traffic, check out the FAQ entry on + privileges to the account you're using; see the FAQ_. Also, if it + looks like Bro is not seeing any traffic, check out the FAQ entry on checksum offloading. You can leave it running for now, but to stop this Bro instance you would do: @@ -196,7 +197,7 @@ the variable's value may not change at run-time, but whose initial value can be modified via the ``redef`` operator at parse-time. So let's continue on our path to modify the behavior for the two SSL -and SSH notices. Looking at :doc:`scripts/base/frameworks/notice/main`, +and SSH notices. Looking at :doc:`/scripts/base/frameworks/notice/main`, we see that it advertises: .. code:: bro @@ -299,7 +300,7 @@ tweak the most basic options. Here's some suggestions on what to explore next: * Reading the code of scripts that ship with Bro is also a great way to gain further understanding of the language and how scripts tend to be structured. -* Review the `FAQ `_. +* Review the FAQ_. * Continue reading below for another mini-tutorial on using Bro as a standalone command-line utility. @@ -326,9 +327,9 @@ that's available. Bro will output log files into the working directory. -.. note:: The :doc:`FAQ ` entries about - capturing as an unprivileged user and checksum offloading are particularly - relevant at this point. +.. note:: The FAQ_ entries about + capturing as an unprivileged user and checksum offloading are + particularly relevant at this point. To use the site-specific ``local.bro`` script, just add it to the command-line: diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index a9826d9b3f..197180241e 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -1,12 +1,12 @@ .. _writing-scripts: -.. contents:: - =================== Writing Bro Scripts =================== +.. contents:: + Understanding Bro Scripts ========================= @@ -91,9 +91,9 @@ form of an email generated and sent to a pre-configured address. The workhorse of the script is contained in the event handler for ``log_http``. The ``log_http`` event is defined as an event-hook in -the :doc:`scripts/base/protocols/http/main.bro` script and allows scripts +the :doc:`/scripts/base/protocols/http/main` script and allows scripts to handle a connection as it is being passed to the logging framework. -The event handler is passed an :bro:id:`HTTP::Info` data structure +The event handler is passed an :bro:type:`HTTP::Info` data structure which will be referred to as ``rec`` in body of the event handler. An ``if`` statement is used to check for the existence of a data structure @@ -182,7 +182,7 @@ The Connection Record Data Type =============================== Of all the events defined by Bro, an overwhelmingly large number of -them are passed the :bro:id:`connection` record data type, in effect, +them are passed the :bro:type:`connection` record data type, in effect, making it the backbone of many scripting solutions. The connection record itself, as we will see in a moment, is a mass of nested data types used to track state on a connection through its lifetime. Let's @@ -217,7 +217,7 @@ for a single connection. .. btest-include:: ${DOC_ROOT}/scripting/connection_record_02.bro Again, we start with ``@load``, this time importing the -:doc:`scripts/base/protocols/conn` scripts which supply the tracking +:doc:`/scripts/base/protocols/conn/index` scripts which supply the tracking and logging of general information and state of connections. We handle the :bro:id:`connection_state_remove` event and simply print the contents of the argument passed to it. For this example we're @@ -316,7 +316,7 @@ block that variable is available to any other script through the naming convention of ``MODULE::variable_name``. The declaration below is taken from the -:doc:`scripts/policy/protocols/conn/known-hosts.bro` script and +:doc:`/scripts/policy/protocols/conn/known-hosts` script and declares a variable called ``known_hosts`` as a global set of unique IP addresses within the ``Known`` namespace and exports it for use outside of the ``Known`` namespace. Were we to want to use the @@ -348,8 +348,7 @@ constants are used in Bro scripts as containers for configuration options. For example, the configuration option to log password decrypted from HTTP streams is stored in ``HTTP::default_capture_password`` as shown in the stripped down -excerpt from :doc:`scripts/scripts/base/protocols/http/main.bro` -below. +excerpt from :doc:`/scripts/base/protocols/http/main` below. .. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro :lines: 8-10,19,20,118 @@ -806,8 +805,8 @@ together new data types to suit the needs of your situation. When combined with the ``type`` keyword, ``record`` can generate a composite type. We have, in fact, already encountered a a complex example of the ``record`` data type in the earlier sections, the -:bro:id:`connection` record passed to many events. Another one, -:bro:id:`Conn::Info`, which corresponds to the fields logged into +:bro:type:`connection` record passed to many events. Another one, +:bro:type:`Conn::Info`, which corresponds to the fields logged into ``conn.log``, is shown by the exerpt below. .. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro @@ -919,7 +918,7 @@ desired output with ``print`` and ``fmt`` before attempting to dive into the Logging Framework. Below is a script that defines a factorial function to recursively calculate the factorial of a unsigned integer passed as an argument to the function. Using -:bro:id:`print` :bro:id:`fmt` we can ensure that Bro can perform these +``print`` and :bro:id:`fmt` we can ensure that Bro can perform these calculations correctly as well get an idea of the answers ourselves. .. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro @@ -935,7 +934,7 @@ method and produce a logfile. As we are working within a namespace and informing an outside entity of workings and data internal to the namespace, we use an ``export`` block. First we need to inform Bro that we are going to be adding another Log Stream by adding a value to -the :bro:id:`Log::ID` enumerable. In line 3 of the script, we append the +the :bro:type:`Log::ID` enumerable. In line 3 of the script, we append the value ``LOG`` to the ``Log::ID`` enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs @@ -1070,9 +1069,9 @@ reporting. With the Notice Framework it's simple to raise a notice for any behavior that is detected. To raise a notice in Bro, you only need to indicate to Bro that you -are provide a specific :bro:id:`Notice::Type` by exporting it and then +are provide a specific :bro:type:`Notice::Type` by exporting it and then make a call to :bro:id:`NOTICE` supplying it with an appropriate -:bro:id:`Notice::Info` record. Often times the call to ``NOTICE`` +:bro:type:`Notice::Info` record. Often times the call to ``NOTICE`` includes just the ``Notice::Type``, and a concise message. There are however, significantly more options available when raising notices as seen in the table below. The only field in the table below whose @@ -1159,7 +1158,7 @@ themselves. On line 12 the script's ``export`` block adds the value ``Notice::Type`` to indicate to the Bro core that a new type of notice is being defined. The script then calls ``NOTICE`` and defines the ``$note``, ``$msg``, ``$sub`` and ``$conn`` fields of the -:bro:id:`Notice::Info` record. Line 39 also includes a ternary if +:bro:type:`Notice::Info` record. Line 39 also includes a ternary if statement that modifies the ``$msg`` text depending on whether the host is a local address and whether it is the client or the server. This use of :bro:id:`fmt` and a ternary operators is a concise way to @@ -1181,25 +1180,25 @@ passing in the ``Notice::Info`` record. The simplest kind of ``Notice::policy`` hooks simply check the value of ``$note`` in the ``Notice::Info`` record being passed into the hook and performing an action based on the answer. The hook below adds the -:bro:id:`Notice::ACTION_EMAIL` action for the +:bro:enum:`Notice::ACTION_EMAIL` action for the ``SSH::Interesting_Hostname_Login`` notice raised in the -:doc:`scripts/policy/protocols/ssh/interesting-hostnames.bro` script. +:doc:`/scripts/policy/protocols/ssh/interesting-hostnames` script. .. btest-include:: ${DOC_ROOT}/scripting/framework_notice_hook_01.bro In the example above we've added ``Notice::ACTION_EMAIL`` to the ``n$actions`` set. This set, defined in the Notice Framework scripts, -can only have entries from the :bro:id:`Notice::Action` type, which is +can only have entries from the :bro:type:`Notice::Action` type, which is itself an enumerable that defines the values shown in the table below along with their corresponding meanings. The -:bro:id:`Notice::ACTION_LOG` action writes the notice to the +:bro:enum:`Notice::ACTION_LOG` action writes the notice to the ``Notice::LOG`` logging stream which, in the default configuration, will write each notice to the ``notice.log`` file and take no further -action. The :bro:id:`Notice::ACTION_EMAIL` action will send an email +action. The :bro:enum:`Notice::ACTION_EMAIL` action will send an email to the address or addresses defined in the :bro:id:`Notice::mail_dest` variable with the particulars of the notice as the body of the email. -The last action, :bro:id:`Notice::ACTION_ALARM` sends the notice to -the :bro:id:`Notice::ALARM_LOG` logging stream which is then rotated +The last action, :bro:enum:`Notice::ACTION_ALARM` sends the notice to +the :bro:enum:`Notice::ALARM_LOG` logging stream which is then rotated hourly and its contents emailed in readable ASCII to the addresses in ``Notice::mail_dest``. @@ -1225,7 +1224,7 @@ Bro. .. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssl/expiring-certs.bro :lines: 59-62 -In the :doc:`scripts/policy/protocols/ssl/expiring-certs.bro` script +In the :doc:`/scripts/policy/protocols/ssl/expiring-certs` script which identifies when SSL certificates are set to expire and raises notices when it crosses a pre-defined threshold, the call to ``NOTICE`` above also sets the ``$identifier`` entry by concatenating @@ -1265,7 +1264,7 @@ facilitate these types of decisions, the Notice Framework supports Notice Policy shortcuts. These shortcuts are implemented through the means of a group of data structures that map specific, pre-defined details and actions to the effective name of a notice. Primarily -implemented as a set or table of enumerables of :bro:id:`Notice::Type`, +implemented as a set or table of enumerables of :bro:type:`Notice::Type`, Notice Policy shortcuts can be placed as a single directive in your ``local.bro`` file as a concise readable configuration. As these variables are all constants, it bears mentioning that these variables diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index 275e1dcf95..3605523839 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -654,7 +654,7 @@ The Bro scripting language supports the following built-in types. close(f); Writing to files like this for logging usually isn't recommended, for better - logging support see :doc:`/logging`. + logging support see :doc:`/frameworks/logging`. .. bro:type:: function diff --git a/doc/scripts/index.rst b/doc/scripts/index.rst index e6d9bd6d65..6314951600 100644 --- a/doc/scripts/index.rst +++ b/doc/scripts/index.rst @@ -9,12 +9,12 @@ Script Reference packages builtins - bifs + Built-In Functions (BIFs) scripts packages internal - site/proto-analyzers - site/file-analyzers + proto-analyzers + file-analyzers diff --git a/scripts/base/frameworks/logging/main.bro b/scripts/base/frameworks/logging/main.bro index 30cc9c0d73..0e398ac257 100644 --- a/scripts/base/frameworks/logging/main.bro +++ b/scripts/base/frameworks/logging/main.bro @@ -1,6 +1,7 @@ ##! The Bro logging interface. ##! -##! See :doc:`/logging` for a introduction to Bro's logging framework. +##! See :doc:`/frameworks/logging` for a introduction to Bro's +##! logging framework. module Log; diff --git a/scripts/base/frameworks/notice/main.bro b/scripts/base/frameworks/notice/main.bro index d046e6b076..d87f943554 100644 --- a/scripts/base/frameworks/notice/main.bro +++ b/scripts/base/frameworks/notice/main.bro @@ -2,7 +2,7 @@ ##! are odd or potentially bad. Decisions of the meaning of various notices ##! need to be done per site because Bro does not ship with assumptions about ##! what is bad activity for sites. More extensive documetation about using -##! the notice framework can be found in :doc:`/notice`. +##! the notice framework can be found in :doc:`/frameworks/notice`. module Notice; diff --git a/scripts/base/frameworks/signatures/main.bro b/scripts/base/frameworks/signatures/main.bro index 7e2f71ea8c..42876220f6 100644 --- a/scripts/base/frameworks/signatures/main.bro +++ b/scripts/base/frameworks/signatures/main.bro @@ -1,6 +1,6 @@ ##! Script level signature support. See the -##! :doc:`signature documentation ` for more information about -##! Bro's signature engine. +##! :doc:`signature documentation ` for more +##! information about Bro's signature engine. @load base/frameworks/notice diff --git a/scripts/base/frameworks/sumstats/main.bro b/scripts/base/frameworks/sumstats/main.bro index 293ad6ac65..657a0399c4 100644 --- a/scripts/base/frameworks/sumstats/main.bro +++ b/scripts/base/frameworks/sumstats/main.bro @@ -74,6 +74,9 @@ export { ## Type to store results for multiple reducers. type Result: table[string] of ResultVal; + ## Type to store a table of sumstats results indexed by keys. + type ResultTable: table[Key] of Result; + ## SumStats represent an aggregation of reducers along with ## mechanisms to handle various situations like the epoch ending ## or thresholds being crossed. @@ -142,7 +145,7 @@ export { ## Dynamically request a sumstat key. This function should be ## used sparingly and not as a replacement for the callbacks - ## from the :bro:see:`SumStat` record. The function is only + ## from the :bro:see:`SumStats::SumStat` record. The function is only ## available for use within "when" statements as an asynchronous ## function. ## @@ -162,9 +165,6 @@ export { global key2str: function(key: SumStats::Key): string; } -# Type to store a table of sumstats results indexed by keys. -type ResultTable: table[Key] of Result; - # The function prototype for plugins to do calculations. type ObserveFunc: function(r: Reducer, val: double, data: Observation, rv: ResultVal); diff --git a/scripts/base/protocols/dhcp/utils.bro b/scripts/base/protocols/dhcp/utils.bro index cb06450088..ef4f244d8a 100644 --- a/scripts/base/protocols/dhcp/utils.bro +++ b/scripts/base/protocols/dhcp/utils.bro @@ -1,7 +1,5 @@ ##! Utilities specific for DHCP processing. -@load ./main - module DHCP; export { diff --git a/scripts/base/protocols/ssl/__load__.bro b/scripts/base/protocols/ssl/__load__.bro index 80cb4e216a..5a8590f234 100644 --- a/scripts/base/protocols/ssl/__load__.bro +++ b/scripts/base/protocols/ssl/__load__.bro @@ -2,4 +2,4 @@ @load ./main @load ./mozilla-ca-list -@load-sigs ./dpd.sig \ No newline at end of file +@load-sigs ./dpd.sig diff --git a/scripts/base/utils/active-http.bro b/scripts/base/utils/active-http.bro index eb9a212221..c289691a75 100644 --- a/scripts/base/utils/active-http.bro +++ b/scripts/base/utils/active-http.bro @@ -43,9 +43,9 @@ export { addl_curl_args: string &optional; }; - ## Perform an HTTP request according to the :bro:type:`Request` record. - ## This is an asynchronous function and must be called within a "when" - ## statement. + ## Perform an HTTP request according to the + ## :bro:type:`ActiveHTTP::Request` record. This is an asynchronous + ## function and must be called within a "when" statement. ## ## req: A record instance representing all options for an HTTP request. ## diff --git a/scripts/policy/frameworks/intel/seen/http-headers.bro b/scripts/policy/frameworks/intel/seen/http-headers.bro index 53aeec4394..2a74548023 100644 --- a/scripts/policy/frameworks/intel/seen/http-headers.bro +++ b/scripts/policy/frameworks/intel/seen/http-headers.bro @@ -1,5 +1,6 @@ @load base/frameworks/intel @load ./where-locations +@load base/utils/addrs event http_header(c: connection, is_orig: bool, name: string, value: string) { diff --git a/src/analyzer/protocol/dnp3/events.bif b/src/analyzer/protocol/dnp3/events.bif index 007045ca8e..874e0aeef7 100644 --- a/src/analyzer/protocol/dnp3/events.bif +++ b/src/analyzer/protocol/dnp3/events.bif @@ -20,10 +20,12 @@ event dnp3_application_response_header%(c: connection, is_orig: bool, fc: count, ## is_orig: True if this reflects originator-side activity. ## obj_type: type of object, which is classified based on an 8-bit group number and an 8-bit variation number ## qua_field: qualifier field -## rf_low, rf_high: the structure of the range field depends on the qualified field. In some cases, range field -## contain only one logic part, e.g., number of objects, so only rf_low contains the useful values; in some -## cases, range field contain two logic parts, e.g., start index and stop index, so rf_low contains the start -## index while rf_high contains the stop index +## rf_low: the structure of the range field depends on the qualified field. +## In some cases, range field contains only one logic part, e.g., +## number of objects, so only *rf_low* contains the useful values. +## rf_high: in some cases, range field contain two logic parts, e.g., start +## index and stop index, so *rf_low* contains the start index while +## while *rf_high* contains the stop index. event dnp3_object_header%(c: connection, is_orig: bool, obj_type: count, qua_field: count, number: count, rf_low: count, rf_high: count%); ## Generated for the prefix before a DNP3 object. The structure and the meaning @@ -48,11 +50,12 @@ event dnp3_object_prefix%(c: connection, is_orig: bool, prefix_value: count%); ## src_addr: the "source" field in the DNP3 Pseudo Link Layer event dnp3_header_block%(c: connection, is_orig: bool, start: count, len: count, ctrl: count, dest_addr: count, src_addr: count%); -## Generated for a DNP3 "Response_Data_Object". The "Response_Data_Object" contains two -## parts: object prefix and objects data. In most cases, objects data are defined -## by new record types. But in a few cases, objects data are directly basic types, -## such as int16, or int8; thus we use a additional data_value to record the values -## of those object data. +## Generated for a DNP3 "Response_Data_Object". +## The "Response_Data_Object" contains two parts: object prefix and object +## data. In most cases, objects data are defined by new record types. But +## in a few cases, objects data are directly basic types, such as int16, or +## int8; thus we use a additional data_value to record the values of those +## object data. ## ## c: The connection the DNP3 communication is part of. ## is_orig: True if this reflects originator-side activity. diff --git a/src/event.bif b/src/event.bif index e4d6f8c844..ddadb47f8a 100644 --- a/src/event.bif +++ b/src/event.bif @@ -518,8 +518,8 @@ event load_sample%(samples: load_sample_info, CPU: interval, dmem: int%); ## processing. If a signature with an ``event`` action matches, this event is ## raised. ## -## See the :doc:`user manual ` for more information about Bro's -## signature engine. +## See the :doc:`user manual ` for more information +## about Bro's signature engine. ## ## state: Context about the match, including which signatures triggered the ## event and the connection for which the match was found. diff --git a/src/probabilistic/bloom-filter.bif b/src/probabilistic/bloom-filter.bif index 6994f651dd..a495a603ae 100644 --- a/src/probabilistic/bloom-filter.bif +++ b/src/probabilistic/bloom-filter.bif @@ -23,12 +23,13 @@ module GLOBAL; ## fp: The desired false-positive rate. ## ## capacity: the maximum number of elements that guarantees a false-positive -## rate of *fp*. +## rate of *fp*. ## ## name: A name that uniquely identifies and seeds the Bloom filter. If empty, -## the filter will use :bro:id:`global_hash_seed` if that's set, and otherwise use -## a local seed tied to the current Bro process. Only filters with the same seed -## can be merged with :bro:id:`bloomfilter_merge` . +## the filter will use :bro:id:`global_hash_seed` if that's set, and +## otherwise use a local seed tied to the current Bro process. Only +## filters with the same seed can be merged with +## :bro:id:`bloomfilter_merge` . ## ## Returns: A Bloom filter handle. ## @@ -61,13 +62,14 @@ function bloomfilter_basic_init%(fp: double, capacity: count, ## cells: The number of cells of the underlying bit vector. ## ## name: A name that uniquely identifies and seeds the Bloom filter. If empty, -## the filter will use :bro:id:`global_hash_seed` if that's set, and otherwise use -## a local seed tied to the current Bro process. Only filters with the same seed -## can be merged with :bro:id:`bloomfilter_merge` . +## the filter will use :bro:id:`global_hash_seed` if that's set, and +## otherwise use a local seed tied to the current Bro process. Only +## filters with the same seed can be merged with +## :bro:id:`bloomfilter_merge` . ## ## Returns: A Bloom filter handle. ## -## .. bro:see:: bloom_filter_basic_init bloomfilter_counting_init bloomfilter_add +## .. bro:see:: bloomfilter_basic_init bloomfilter_counting_init bloomfilter_add ## bloomfilter_lookup bloomfilter_clear bloomfilter_merge global_hash_seed function bloomfilter_basic_init2%(k: count, cells: count, name: string &default=""%): opaque of bloomfilter @@ -94,18 +96,20 @@ function bloomfilter_basic_init2%(k: count, cells: count, ## ## k: The number of hash functions to use. ## -## cells: The number of cells of the underlying counter vector. As there's no -## single answer to what's the best parameterization for a counting Bloom filter, -## we refer to the Bloom filter literature here for choosing an appropiate value. +## cells: The number of cells of the underlying counter vector. As there's +## no single answer to what's the best parameterization for a +## counting Bloom filter, we refer to the Bloom filter literature +## here for choosing an appropiate value. ## -## max: The maximum counter value associated with each each element described -## by *w = ceil(log_2(max))* bits. Each bit in the underlying counter vector -## becomes a cell of size *w* bits. +## max: The maximum counter value associated with each each element +## described by *w = ceil(log_2(max))* bits. Each bit in the underlying +## counter vector becomes a cell of size *w* bits. ## ## name: A name that uniquely identifies and seeds the Bloom filter. If empty, -## the filter will use :bro:id:`global_hash_seed` if that's set, and otherwise use -## a local seed tied to the current Bro process. Only filters with the same seed -## can be merged with :bro:id:`bloomfilter_merge` . +## the filter will use :bro:id:`global_hash_seed` if that's set, and +## otherwise use a local seed tied to the current Bro process. Only +## filters with the same seed can be merged with +## :bro:id:`bloomfilter_merge` . ## ## Returns: A Bloom filter handle. ## @@ -193,7 +197,7 @@ function bloomfilter_lookup%(bf: opaque of bloomfilter, x: any%): count ## ## bf: The Bloom filter handle. ## -## .. bro:see:: bloomfilter_basic_init bloomfilter_counting_init2 +## .. bro:see:: bloomfilter_basic_init bloomfilter_basic_init2 ## bloomfilter_counting_init bloomfilter_add bloomfilter_lookup ## bloomfilter_merge function bloomfilter_clear%(bf: opaque of bloomfilter%): any diff --git a/src/strings.bif b/src/strings.bif index 3aa282d155..233071d318 100644 --- a/src/strings.bif +++ b/src/strings.bif @@ -11,7 +11,7 @@ using namespace std; %%} ## Calculates the Levenshtein distance between the two strings. See `Wikipedia -## `_ for more information. +## `__ for more information. ## ## s1: The first string. ## @@ -840,7 +840,7 @@ function string_to_ascii_hex%(s: string%): string %} ## Uses the Smith-Waterman algorithm to find similar/overlapping substrings. -## See `Wikipedia `_. +## See `Wikipedia `__. ## ## s1: The first string. ## From ca9b9162a75d1ab9ce2a52823c3fae2b85173cec Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 4 Sep 2013 10:45:29 -0500 Subject: [PATCH 289/881] Fix raw execution input reader's signal blocking. Signals are generally blocked within threads in Bro so that the main thread does all signal handling, however, signal masks are inherited over fork() and exec(), so they should be unblocked before exec() so that process can respond to signals normally. This fixes the raw reader from leaving behind processes that didn't respond to SIGTERM at shutdown because it was blocked before exec(). --- src/input/readers/Raw.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/input/readers/Raw.cc b/src/input/readers/Raw.cc index 2a890eab4e..f8facca374 100644 --- a/src/input/readers/Raw.cc +++ b/src/input/readers/Raw.cc @@ -14,6 +14,10 @@ #include #include +extern "C" { +#include "setsignal.h" +} + using namespace input::reader; using threading::Value; using threading::Field; @@ -70,14 +74,14 @@ void Raw::DoClose() if ( execute && childpid > 0 && kill(childpid, 0) == 0 ) { // kill child process - kill(childpid, 15); // sigterm + kill(childpid, SIGTERM); if ( forcekill ) { usleep(200); // 200 msecs should be enough for anyone ;) if ( kill(childpid, 0) == 0 ) // perhaps it is already gone - kill(childpid, 9); // TERMINATE + kill(childpid, SIGKILL); } } } @@ -160,6 +164,15 @@ bool Raw::Execute() close(pipes[stderr_out]); + // Signal mask is inherited over fork-exec, so reset any ignored + // signals to default behavior and unblock any blocked signals. + setsignal(SIGPIPE, SIG_DFL); // May be ignored when debugging scripts. + sigset_t mask; + sigfillset(&mask); + // Assuming the fork-one model of pthreads' fork(), using sigprocmask() + // makes sense over pthread_sigmask() here. + sigprocmask(SIG_UNBLOCK, &mask, 0); + execl("/bin/sh", "sh", "-c", fname.c_str(), (char*) NULL); fprintf(stderr, "Exec failed :(......\n"); _exit(255); From 067846835307dac33bfa42a6bb30691904c07c24 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 4 Sep 2013 11:46:53 -0500 Subject: [PATCH 290/881] Internal UID simplifications/nits. --- src/UID.cc | 8 -------- src/UID.h | 15 +++++---------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/UID.cc b/src/UID.cc index 28675c0376..1ba21be6c5 100644 --- a/src/UID.cc +++ b/src/UID.cc @@ -26,11 +26,3 @@ void UID::Set(bro_uint_t bits, const uint64* v, size_t n) if ( res.rem ) uid[0] >>= 64 - res.rem; } - -bool Bro::operator==(const UID& u1, const UID& u2) - { - for ( size_t i = 0; i < BRO_UID_LEN; ++i ) - if ( u1.uid[i] != u2.uid[i] ) - return false; - return true; - } diff --git a/src/UID.h b/src/UID.h index 9ccf0ae0e8..2cda02811f 100644 --- a/src/UID.h +++ b/src/UID.h @@ -72,7 +72,8 @@ public: /** * UID equality operator. */ - friend bool operator==(const UID& u1, const UID& u2); + friend bool operator==(const UID& u1, const UID& u2) + { return memcmp(u1.uid, u2.uid, sizeof(u1.uid)) == 0; } /** * UID inequality operator. @@ -85,21 +86,15 @@ private: bool initialized; // Since technically uid == 0 is a legit UID }; -bool operator==(const UID& u1, const UID& u2); - inline UID::UID(const UID& other) { - for ( size_t i = 0; i < BRO_UID_LEN; ++i ) - uid[i] = other.uid[i]; - + memcpy(uid, other.uid, sizeof(uid)); initialized = other.initialized; } inline UID& UID::operator=(const UID& other) { - for ( size_t i = 0; i < BRO_UID_LEN; ++i ) - uid[i] = other.uid[i]; - + memmove(uid, other.uid, sizeof(uid)); initialized = other.initialized; return *this; } @@ -109,7 +104,7 @@ inline std::string UID::Base62(std::string prefix) const if ( ! initialized ) reporter->InternalError("use of uninitialized UID"); - char tmp[64]; // technically, this should dynamically scale w/ BRO_UID_LEN + char tmp[sizeof(uid) * 8 + 1]; // enough for even binary representation for ( size_t i = 0; i < BRO_UID_LEN; ++i ) prefix.append(uitoa_n(uid[i], tmp, sizeof(tmp), 62)); From f9dc48e5731c16628b5bcb4ddc450308ed2217f0 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 4 Sep 2013 14:25:57 -0500 Subject: [PATCH 291/881] Fix logging filter over-allocation and leak. The leak could happen in a couple cases where adding a log filter fails: OOM and unsupported field type. --- src/logging/Manager.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 61e15a334f..3e03d1d27a 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -538,10 +538,11 @@ bool Manager::TraverseRecord(Stream* stream, Filter* filter, RecordType* rt, filter->fields = (threading::Field**) realloc(filter->fields, - sizeof(threading::Field) * ++filter->num_fields); + sizeof(threading::Field*) * ++filter->num_fields); if ( ! filter->fields ) { + --filter->num_fields; reporter->Error("out of memory in add_filter"); return false; } @@ -623,7 +624,10 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval) include ? include->AsTableVal() : 0, exclude ? exclude->AsTableVal() : 0, "", list()) ) + { + delete filter; return false; + } // Get the path for the filter. Val* path_val = fval->Lookup(rtype->FieldOffset("path")); From 6ad82ff263ba6b4c8d2188c54b0ba0bc819a484b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 4 Sep 2013 14:45:09 -0500 Subject: [PATCH 292/881] Fix invalid/mismatched deallocators. --- src/analyzer/protocol/netbios/NetbiosSSN.cc | 2 +- src/input/readers/Binary.cc | 2 +- src/input/readers/Raw.cc | 2 +- src/scan.l | 9 ++++++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/analyzer/protocol/netbios/NetbiosSSN.cc b/src/analyzer/protocol/netbios/NetbiosSSN.cc index 01544c4b2c..4a7a5dbc59 100644 --- a/src/analyzer/protocol/netbios/NetbiosSSN.cc +++ b/src/analyzer/protocol/netbios/NetbiosSSN.cc @@ -262,7 +262,7 @@ int NetbiosSSN_Interpreter::ParseSessionReq(const u_char* data, int len, if ( ConvertName(data, len, xname, xlen) ) Event(netbios_session_request, xname, xlen); - delete xname; + delete [] xname; return 0; } diff --git a/src/input/readers/Binary.cc b/src/input/readers/Binary.cc index 43df6d7e6b..e49e6b7407 100644 --- a/src/input/readers/Binary.cc +++ b/src/input/readers/Binary.cc @@ -139,7 +139,7 @@ streamsize Binary::GetChunk(char** chunk) if ( ! bytes_read ) { - delete *chunk; + delete [] *chunk; *chunk = 0; return 0; } diff --git a/src/input/readers/Raw.cc b/src/input/readers/Raw.cc index f8facca374..2c2b319793 100644 --- a/src/input/readers/Raw.cc +++ b/src/input/readers/Raw.cc @@ -424,7 +424,7 @@ int64_t Raw::GetLine(FILE* arg_file) // bah, we cannot use realloc because we would have to change the delete in the manager to a free. char * newbuf = new char[block_size*repeats]; memcpy(newbuf, buf, block_size*(repeats-1)); - delete buf; + delete [] buf; buf = newbuf; offset = block_size*(repeats-1); } diff --git a/src/scan.l b/src/scan.l index f23fa10f75..636ec5b251 100644 --- a/src/scan.l +++ b/src/scan.l @@ -616,9 +616,12 @@ static int load_files(const char* orig_file) { if ( it->inode == i ) { - fclose(f); - delete [] full_filename; - delete [] bropath_subpath_delete; + if ( f != stdin ) + { + fclose(f); + delete [] full_filename; + delete [] bropath_subpath_delete; + } return 0; } } From 62de5678f7532fb4c31bd7dce481491f5d11128a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 4 Sep 2013 16:47:44 -0500 Subject: [PATCH 293/881] Fix memory leak in DNS TXT lookups. --- src/DNS_Mgr.cc | 12 +++++++- testing/btest/core/leaks/dns-txt.bro | 43 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 testing/btest/core/leaks/dns-txt.bro diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 4596a7d73a..2005202484 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -713,6 +713,16 @@ void DNS_Mgr::AddResult(DNS_Mgr_Request* dr, struct nb_dns_result* r) TextMap::iterator it = text_mappings.find(dr->ReqHost()); if ( it == text_mappings.end() ) text_mappings[dr->ReqHost()] = new_dm; + else + { + if ( new_dm->Failed() && prev_dm && prev_dm->Valid() ) + ++keep_prev; + else + { + prev_dm = it->second; + it->second = new_dm; + } + } } else { @@ -766,7 +776,7 @@ void DNS_Mgr::AddResult(DNS_Mgr_Request* dr, struct nb_dns_result* r) } } - if ( prev_dm ) + if ( prev_dm && ! dr->ReqIsTxt() ) CompareMappings(prev_dm, new_dm); if ( keep_prev ) diff --git a/testing/btest/core/leaks/dns-txt.bro b/testing/btest/core/leaks/dns-txt.bro new file mode 100644 index 0000000000..44b7c04a0c --- /dev/null +++ b/testing/btest/core/leaks/dns-txt.bro @@ -0,0 +1,43 @@ +# Needs perftools support. +# +# @TEST-GROUP: leaks +# +# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks +# +# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local btest-bg-run bro bro -b -m -r $TRACES/wikipedia.trace %INPUT +# @TEST-EXEC: btest-bg-wait 15 + +@load base/frameworks/communication # keep network time running +redef exit_only_after_terminate = T; + +global n1 = 0; + +function check_term_conditions() + { + if ( n1 > 7 ) + terminate(); + } + + +event do_txt(s: string) + { + when ( local t1 = lookup_hostname_txt(s) ) + { + print "t1", t1; + ++n1; + check_term_conditions(); + } + timeout 100secs + { + print "t1 timeout"; + ++n1; + check_term_conditions(); + } + } + +event connection_established(c: connection) + { + event do_txt("localhost"); + schedule 5sec { do_txt("localhost") }; + } + From 3939b629aeb317d5dcf47c1a77e905052b6c0c4e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 4 Sep 2013 16:49:04 -0500 Subject: [PATCH 294/881] Adjust DNS memory leak test to actually fail if there's a leak. --- testing/btest/core/leaks/dns.bro | 35 ++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/testing/btest/core/leaks/dns.bro b/testing/btest/core/leaks/dns.bro index 66743295af..d02d7b6f3c 100644 --- a/testing/btest/core/leaks/dns.bro +++ b/testing/btest/core/leaks/dns.bro @@ -4,52 +4,79 @@ # # @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks # -# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local btest-bg-run bro bro -m -r $TRACES/wikipedia.trace %INPUT -# @TEST-EXEC: btest-bg-wait -k 15 +# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local btest-bg-run bro bro -b -m -r $TRACES/wikipedia.trace %INPUT +# @TEST-EXEC: btest-bg-wait 15 + +@load base/frameworks/communication # keep network time running +redef exit_only_after_terminate = T; const foo: set[addr] = { google.com }; -# Add the state tracking information variable to the connection record +global n1 = 0; +global n2 = 0; +global n3 = 0; +global n4 = 0; + +function check_term_conditions() + { + if ( n1 > 4 && n2 > 4 && n3 > 4 && n4 > 4 ) + terminate(); + } event connection_established(c: connection) { when ( local addrs = lookup_hostname("localhost") ) { print "1a", c$id$resp_h, addrs; + ++n1; + check_term_conditions(); } timeout 100secs { print "1b", c$id$resp_h; + ++n1; + check_term_conditions(); } when ( local addrs2 = lookup_hostname("qq.ww.ee.rrrrr") ) { print "2a", c$id$resp_h, addrs2; + ++n2; + check_term_conditions(); } timeout 100secs { print "2b", c$id$resp_h; + ++n2; + check_term_conditions(); } when ( local a = lookup_addr(c$id$resp_h) ) { print "3a", c$id$resp_h, a; + ++n3; + check_term_conditions(); } timeout 100secs { print "3b", c$id$resp_h; + ++n3; + check_term_conditions(); } when ( local a2 = lookup_addr(1.2.3.4) ) { print "4a", c$id$resp_h, a2; + ++n4; + check_term_conditions(); } timeout 100secs { print "4b", c$id$resp_h; + ++n4; + check_term_conditions(); } - } From 7799a86a7f845cd1ae6bb24526c2ba80fbaaf2c4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 4 Sep 2013 16:53:58 -0500 Subject: [PATCH 295/881] Adjust HLL cluster leak test so leaks trigger a failure. --- testing/btest/core/leaks/hll_cluster.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/btest/core/leaks/hll_cluster.bro b/testing/btest/core/leaks/hll_cluster.bro index 65fe8da447..a6f704a677 100644 --- a/testing/btest/core/leaks/hll_cluster.bro +++ b/testing/btest/core/leaks/hll_cluster.bro @@ -10,7 +10,7 @@ # @TEST-EXEC: sleep 2 # @TEST-EXEC: btest-bg-run worker-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro runnumber=1 %INPUT # @TEST-EXEC: btest-bg-run worker-2 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro runnumber=2 %INPUT -# @TEST-EXEC: btest-bg-wait -k 10 +# @TEST-EXEC: btest-bg-wait 10 # # @TEST-EXEC: btest-diff manager-1/.stdout # @TEST-EXEC: btest-diff worker-1/.stdout From ef50802fd75c1234746dfe4cd7f79e443e9a631e Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Thu, 5 Sep 2013 12:07:21 -0400 Subject: [PATCH 296/881] Make the notice $actions field have a default empty set to avoid having to check for it's presence. --- scripts/base/frameworks/notice/main.bro | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/base/frameworks/notice/main.bro b/scripts/base/frameworks/notice/main.bro index d87f943554..8479511d43 100644 --- a/scripts/base/frameworks/notice/main.bro +++ b/scripts/base/frameworks/notice/main.bro @@ -113,7 +113,7 @@ export { peer_descr: string &log &optional; ## The actions which have been applied to this notice. - actions: set[Notice::Action] &log &optional; + actions: set[Notice::Action] &log &default=set(); ## By adding chunks of text into this element, other scripts can ## expand on notices that are being emailed. The normal way to add text @@ -533,9 +533,6 @@ function apply_policy(n: Notice::Info) n$peer_descr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host); - if ( ! n?$actions ) - n$actions = set(); - if ( ! n?$email_body_sections ) n$email_body_sections = vector(); if ( ! n?$email_delay_tokens ) From eef432561e2105a7443a4d9d2e7e265ab5456536 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 11:52:40 -0500 Subject: [PATCH 297/881] Fix memory leak if a DNS request fails to be made. A symptom of this is a "can't issue DNS request" warning in reporter.log. (Doesn't look like this should be a typical thing that happens in most environments). --- src/DNS_Mgr.cc | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 2005202484..e57714a047 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -1095,6 +1095,17 @@ void DNS_Mgr::AsyncLookupNameText(string name, LookupCallback* callback) IssueAsyncRequests(); } +static bool DoRequest(nb_dns_info* nb_dns, DNS_Mgr_Request* dr) + { + if ( dr->MakeRequest(nb_dns) ) + // dr stored in nb_dns cookie and deleted later when results available. + return true; + + reporter->Warning("can't issue DNS request"); + delete dr; + return false; + } + void DNS_Mgr::IssueAsyncRequests() { while ( asyncs_queued.size() && asyncs_pending < MAX_PENDING_REQUESTS ) @@ -1104,31 +1115,26 @@ void DNS_Mgr::IssueAsyncRequests() ++num_requests; - DNS_Mgr_Request* dr; - DNS_Mgr_Request* dr6 = 0; + bool success; if ( req->IsAddrReq() ) - dr = new DNS_Mgr_Request(req->host); + success = DoRequest(nb_dns, new DNS_Mgr_Request(req->host)); + else if ( req->is_txt ) + success = DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), + AF_INET, req->is_txt)); else { - dr = new DNS_Mgr_Request(req->name.c_str(), AF_INET, req->is_txt); - if ( ! req->is_txt ) - dr6 = new DNS_Mgr_Request(req->name.c_str(), AF_INET6, req->is_txt); + // If only one request type succeeds, don't consider it a failure. + success = DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), + AF_INET, req->is_txt)); + success = DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), + AF_INET6, req->is_txt)) || success; } - if ( ! dr->MakeRequest(nb_dns) ) + if ( ! success ) { - reporter->Warning("can't issue DNS request"); - ++failed; req->Timeout(); - continue; - } - - if ( dr6 && ! dr6->MakeRequest(nb_dns) ) - { - reporter->Warning("can't issue DNS request"); ++failed; - req->Timeout(); continue; } From 4e8ba6eaa2b7bab2e5cb5408fc5bac02b49ba089 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 13:01:40 -0500 Subject: [PATCH 298/881] Fix signatures that use identifiers of type table. --- src/RuleMatcher.cc | 11 ++++++----- testing/btest/Baseline/signatures.id-lookup/id.out | 1 + testing/btest/signatures/id-lookup.bro | 11 +++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index 5b6f673a8a..974004e2ac 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -1243,15 +1243,16 @@ void id_to_maskedvallist(const char* id, maskedvalue_list* append_to, if ( v->Type()->Tag() == TYPE_TABLE ) { - val_list* vals = v->AsTableVal()->ConvertToPureList()->Vals(); + ListVal* lv = v->AsTableVal()->ConvertToPureList(); + val_list* vals = lv->Vals(); loop_over_list(*vals, i ) if ( ! val_to_maskedval((*vals)[i], append_to, prefix_vector) ) - { - delete_vals(vals); + { + Unref(lv); return; - } + } - delete_vals(vals); + Unref(lv); } else diff --git a/testing/btest/Baseline/signatures.id-lookup/id.out b/testing/btest/Baseline/signatures.id-lookup/id.out index 4a5310a3b2..3f285b85a0 100644 --- a/testing/btest/Baseline/signatures.id-lookup/id.out +++ b/testing/btest/Baseline/signatures.id-lookup/id.out @@ -1 +1,2 @@ +signature_match [orig_h=127.0.0.1, orig_p=30000/udp, resp_h=127.0.0.1, resp_p=13000/udp] - idtable signature_match [orig_h=127.0.0.1, orig_p=30000/udp, resp_h=127.0.0.1, resp_p=13000/udp] - id diff --git a/testing/btest/signatures/id-lookup.bro b/testing/btest/signatures/id-lookup.bro index 2e32224bc8..f055e73725 100644 --- a/testing/btest/signatures/id-lookup.bro +++ b/testing/btest/signatures/id-lookup.bro @@ -6,10 +6,21 @@ signature id { ip-proto == udp_proto_number event "id" } + +signature idtable { + dst-ip == mynets + event "idtable" +} @TEST-END-FILE const udp_proto_number = 17; +const mynets: set[subnet] = { + 192.168.1.0/24, + 10.0.0.0/8, + 127.0.0.0/24 +}; + event signature_match(state: signature_state, msg: string, data: string) { print fmt("signature_match %s - %s", state$conn$id, msg); From 703ef3b90866ce5d92b03107c221923e7552d30a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 15:06:59 -0500 Subject: [PATCH 299/881] Fix mem leak when unserializing an arg in a function call fails. Shouldn't be a typical scenario since hopefully we'd know about and fix the underlying problem w/ unserialization... --- src/Serializer.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Serializer.cc b/src/Serializer.cc index 3dea7ee9e4..683b543e48 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -366,6 +366,7 @@ bool Serializer::UnserializeCall(UnserialInfo* info) if ( ! v ) { delete [] name; + delete_vals(args); return false; } From 766cc0d220ffaf3fd6f85588ef475700f33b79ed Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 15:30:28 -0500 Subject: [PATCH 300/881] Fix mem leak when failing to end a serialization. We'd probably know about it if that actually ever happened in practice (which it shouldn't). --- src/Serializer.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Serializer.cc b/src/Serializer.cc index 683b543e48..145aab3f4d 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -70,12 +70,8 @@ bool Serializer::StartSerialization(SerialInfo* info, const char* descr, bool Serializer::EndSerialization(SerialInfo* info) { - ChunkedIO::Chunk* chunk = new ChunkedIO::Chunk; - chunk->len = format->EndWrite(&chunk->data); - if ( info->chunk ) { - if ( ! io->Write(info->chunk) ) { Error(io->Error()); @@ -83,6 +79,9 @@ bool Serializer::EndSerialization(SerialInfo* info) } } + ChunkedIO::Chunk* chunk = new ChunkedIO::Chunk; + chunk->len = format->EndWrite(&chunk->data); + if ( ! io->Write(chunk) ) { Error(io->Error()); From 75d469532c3a8c5f0230ce43e7779ab1829de82c Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 15:40:10 -0500 Subject: [PATCH 301/881] Fix mem leak when unserializing table entry fails. Shouldn't happen in practice. --- src/Val.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Val.cc b/src/Val.cc index 3e69401918..50521cfee6 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2463,7 +2463,11 @@ bool TableVal::DoUnserialize(UnserialInfo* info) if ( ! UNSERIALIZE(&entry_val->last_access_time) || ! UNSERIALIZE(&eat) ) + { + entry_val->Unref(); + delete entry_val; return false; + } entry_val->SetExpireAccess(eat); From f823b92e5ecb83284d5ae255227d7a3a22f9406b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 15:47:57 -0500 Subject: [PATCH 302/881] Fix mem leak when merging incompatible types. Though this would typically be caused by a scripting error that should be fixed and Bro would exit anyway if encountered at parse time. --- src/Type.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Type.cc b/src/Type.cc index 563bc5afbd..d7236e0344 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -2003,6 +2003,7 @@ BroType* merge_types(const BroType* t1, const BroType* t2) if ( ! y1 || ! y2 ) { t1->Error("incompatible types", t2); + Unref(tl3); return 0; } From 0b5a75a46345e476beac7e5f804cb64cb48017f6 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 16:09:52 -0500 Subject: [PATCH 303/881] Fix mem leak in failing table initialization case. Specifically that case looked like tables that have a compound index and an element assignment fails due to a type mismatch. --- src/Val.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Val.cc b/src/Val.cc index 50521cfee6..970fc02be7 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2079,7 +2079,7 @@ int TableVal::ExpandCompoundAndInit(val_list* vl, int k, Val* new_val) Val* ind_k_v = (*vl)[k]; ListVal* ind_k = ind_k_v->Type()->IsSet() ? ind_k_v->AsTableVal()->ConvertToList() : - ind_k_v->AsListVal(); + ind_k_v->Ref()->AsListVal(); for ( int i = 0; i < ind_k->Length(); ++i ) { @@ -2097,12 +2097,13 @@ int TableVal::ExpandCompoundAndInit(val_list* vl, int k, Val* new_val) Unref(expd); if ( ! success ) + { + Unref(ind_k); return 0; + } } - if ( ind_k_v->Type()->IsSet() ) - Unref(ind_k); - + Unref(ind_k); return 1; } From a9a245e017d26d7c50ebccd900b3cf538ce6d74b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 16:41:51 -0500 Subject: [PATCH 304/881] Workaround type ambiguity w/ default record field. --- scripts/base/frameworks/notice/main.bro | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/base/frameworks/notice/main.bro b/scripts/base/frameworks/notice/main.bro index 8479511d43..facd148491 100644 --- a/scripts/base/frameworks/notice/main.bro +++ b/scripts/base/frameworks/notice/main.bro @@ -41,6 +41,8 @@ export { ACTION_ALARM, }; + type ActionSet: set[Notice::Action]; + ## The notice framework is able to do automatic notice supression by ## utilizing the $identifier field in :bro:type:`Notice::Info` records. ## Set this to "0secs" to completely disable automated notice suppression. @@ -113,7 +115,7 @@ export { peer_descr: string &log &optional; ## The actions which have been applied to this notice. - actions: set[Notice::Action] &log &default=set(); + actions: ActionSet &log &default=ActionSet(); ## By adding chunks of text into this element, other scripts can ## expand on notices that are being emailed. The normal way to add text From b76d8eedbb4e6a8d754547b25e9551814a11b37e Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 5 Sep 2013 16:54:53 -0500 Subject: [PATCH 305/881] Updating submodule. [nomail] --- aux/binpac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/binpac b/aux/binpac index ff22fa7299..d946952e0d 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit ff22fa7299d460d9c4b7f6c7269e2d3aafa06b21 +Subproject commit d946952e0d18c66679511c1519e9feda2fba123f From 7c1dffa66fae46fd578768c7cf518fc4c869e884 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Fri, 6 Sep 2013 15:31:00 -0400 Subject: [PATCH 306/881] Fixed an issue with the HLL_UNIQUE SumStats plugin that caused a reporter error. --- .../base/frameworks/sumstats/plugins/hll_unique.bro | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/base/frameworks/sumstats/plugins/hll_unique.bro b/scripts/base/frameworks/sumstats/plugins/hll_unique.bro index ed2d3b6e6c..fe1bfbd476 100644 --- a/scripts/base/frameworks/sumstats/plugins/hll_unique.bro +++ b/scripts/base/frameworks/sumstats/plugins/hll_unique.bro @@ -43,7 +43,6 @@ hook register_observe_plugins() rv$card = hll_cardinality_init(r$hll_error_margin, r$hll_confidence); rv$hll_error_margin = r$hll_error_margin; rv$hll_confidence = r$hll_confidence; - rv$hll_unique = 0; } hll_cardinality_add(rv$card, obs); @@ -53,9 +52,14 @@ hook register_observe_plugins() hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) { + if ( ! (rv1?$card || rv2?$card) ) + return; + local rhll = hll_cardinality_init(rv1$hll_error_margin, rv1$hll_confidence); - hll_cardinality_merge_into(rhll, rv1$card); - hll_cardinality_merge_into(rhll, rv2$card); + if ( rv1?$card ) + hll_cardinality_merge_into(rhll, rv1$card); + if ( rv2?$card ) + hll_cardinality_merge_into(rhll, rv2$card); result$card = rhll; result$hll_unique = double_to_count(hll_cardinality_estimate(rhll)); From ee1312f2add224eafcf0c7e193d5d818aa34c84f Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Tue, 10 Sep 2013 11:20:18 -0500 Subject: [PATCH 307/881] Fix an error seen when building documentation --- src/probabilistic/cardinality-counter.bif | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/probabilistic/cardinality-counter.bif b/src/probabilistic/cardinality-counter.bif index 4d5316c9a3..5201ce95bb 100644 --- a/src/probabilistic/cardinality-counter.bif +++ b/src/probabilistic/cardinality-counter.bif @@ -63,8 +63,8 @@ function hll_cardinality_add%(handle: opaque of cardinality, elem: any%): bool ## Merges a HLL cardinality counter into another. ## -## .. note:: The same restrictions as for Bloom filter merging apply, see -## :bro:id:`bloomfilter_merge`. +## .. note:: The same restrictions as for Bloom filter merging apply, +## see :bro:id:`bloomfilter_merge`. ## ## handle1: the first HLL handle, which will contain the merged result ## From 1fbeefedbc6470f98090d6edc2f99cf2f66e3ba9 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Sep 2013 13:30:23 -0500 Subject: [PATCH 308/881] Fix two use-after-free bugs. --- src/RemoteSerializer.cc | 2 +- src/logging/Manager.cc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 8cd34aa8fc..9bbaba3d55 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -2575,8 +2575,8 @@ bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal* error: if ( c ) { - delete c; delete [] c->data; + delete c; } FatalError(io->Error()); diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 3e03d1d27a..79e23fb63f 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -402,10 +402,11 @@ bool Manager::RemoveStream(EnumVal* id) } stream->writers.clear(); + string sname(stream->name); delete stream; streams[idx] = 0; - DBG_LOG(DBG_LOGGING, "Removed logging stream '%s'", stream->name.c_str()); + DBG_LOG(DBG_LOGGING, "Removed logging stream '%s'", sname.c_str()); return true; } From c3a4454892fe0224f68efce23b797fb89ca04ee1 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 10 Sep 2013 16:10:10 -0500 Subject: [PATCH 309/881] Fix significant memory leak. Particularly, unserializing a function is frequent and leaked. --- src/Val.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Val.cc b/src/Val.cc index 970fc02be7..3e5b0eff48 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -59,6 +59,9 @@ Val::~Val() if ( type->InternalType() == TYPE_INTERNAL_STRING ) delete val.string_val; + else if ( type->Tag() == TYPE_FUNC ) + Unref(val.func_val); + else if ( type->Tag() == TYPE_FILE ) Unref(val.file_val); From c40a97156ab30db81061a2270c436759b18ec2fe Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 11 Sep 2013 12:39:23 -0700 Subject: [PATCH 310/881] make client and server random available on script-level. Patch by ewust Addresses BIT-950 --- scripts/base/protocols/ssl/main.bro | 4 ++-- src/analyzer/protocol/ssl/events.bif | 10 ++++++++-- src/analyzer/protocol/ssl/ssl-analyzer.pac | 18 +++++++++++------- src/analyzer/protocol/ssl/ssl-protocol.pac | 4 ++-- .../.stdout | 2 ++ .../base/protocols/ssl/tls-1.2-random.test | 12 ++++++++++++ 6 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 testing/btest/Baseline/scripts.base.protocols.ssl.tls-1.2-random/.stdout create mode 100644 testing/btest/scripts/base/protocols/ssl/tls-1.2-random.test diff --git a/scripts/base/protocols/ssl/main.bro b/scripts/base/protocols/ssl/main.bro index 2381b356e4..898b6e9bbb 100644 --- a/scripts/base/protocols/ssl/main.bro +++ b/scripts/base/protocols/ssl/main.bro @@ -151,7 +151,7 @@ function finish(c: connection) disable_analyzer(c$id, c$ssl$analyzer_id); } -event ssl_client_hello(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set) &priority=5 +event ssl_client_hello(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: count_set) &priority=5 { set_session(c); @@ -160,7 +160,7 @@ event ssl_client_hello(c: connection, version: count, possible_ts: time, session c$ssl$session_id = bytestring_to_hexstr(session_id); } -event ssl_server_hello(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count) &priority=5 +event ssl_server_hello(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count) &priority=5 { set_session(c); diff --git a/src/analyzer/protocol/ssl/events.bif b/src/analyzer/protocol/ssl/events.bif index 3d0c7e9d6a..56e5ef59c0 100644 --- a/src/analyzer/protocol/ssl/events.bif +++ b/src/analyzer/protocol/ssl/events.bif @@ -17,13 +17,16 @@ ## ## session_id: The session ID sent by the client (if any). ## +## client_random: The random value sent by the client. For version 2 connections, +## the client challenge is returned. +## ## ciphers: The list of ciphers the client offered to use. The values are ## standardized as part of the SSL/TLS protocol. The ## :bro:id:`SSL::cipher_desc` table maps them to descriptive names. ## ## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello ## ssl_session_ticket_handshake x509_certificate x509_error x509_extension -event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%); +event ssl_client_hello%(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: count_set%); ## Generated for an SSL/TLS server's initial *hello* message. SSL/TLS sessions ## start with an unencrypted handshake, and Bro extracts as much information out @@ -44,6 +47,9 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, sessio ## ## session_id: The session ID as sent back by the server (if any). ## +## server_random: The random value sent by the server. For version 2 connections, +## the connection-id is returned. +## ## cipher: The cipher chosen by the server. The values are standardized as part ## of the SSL/TLS protocol. The :bro:id:`SSL::cipher_desc` table maps ## them to descriptive names. @@ -53,7 +59,7 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, sessio ## ## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension ## ssl_session_ticket_handshake x509_certificate x509_error x509_extension -event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%); +event ssl_server_hello%(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count%); ## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS ## sessions start with an unencrypted handshake, and Bro extracts as much diff --git a/src/analyzer/protocol/ssl/ssl-analyzer.pac b/src/analyzer/protocol/ssl/ssl-analyzer.pac index 3d9564eaab..4043d1ac89 100644 --- a/src/analyzer/protocol/ssl/ssl-analyzer.pac +++ b/src/analyzer/protocol/ssl/ssl-analyzer.pac @@ -152,6 +152,7 @@ refine connection SSL_Conn += { function proc_client_hello(rec: SSLRecord, version : uint16, ts : double, + client_random : bytestring, session_id : uint8[], cipher_suites16 : uint16[], cipher_suites24 : uint24[]) : bool @@ -176,7 +177,8 @@ refine connection SSL_Conn += { } BifEvent::generate_ssl_client_hello(bro_analyzer(), bro_analyzer()->Conn(), - version, ts, + version, ts, new StringVal(client_random.length(), + (const char*) client_random.data()), to_string_val(session_id), cipher_set); @@ -188,6 +190,7 @@ refine connection SSL_Conn += { function proc_server_hello(rec: SSLRecord, version : uint16, ts : double, + server_random : bytestring, session_id : uint8[], cipher_suites16 : uint16[], cipher_suites24 : uint24[], @@ -209,7 +212,8 @@ refine connection SSL_Conn += { BifEvent::generate_ssl_server_hello(bro_analyzer(), bro_analyzer()->Conn(), - version, ts, + version, ts, new StringVal(server_random.length(), + (const char*) server_random.data()), to_string_val(session_id), ciphers->size()==0 ? 0 : ciphers->at(0), comp_method); @@ -419,27 +423,27 @@ refine typeattr ApplicationData += &let { refine typeattr ClientHello += &let { proc : bool = $context.connection.proc_client_hello(rec, client_version, - gmt_unix_time, + gmt_unix_time, random_bytes, session_id, csuits, 0) &requires(state_changed); }; refine typeattr V2ClientHello += &let { proc : bool = $context.connection.proc_client_hello(rec, client_version, 0, - session_id, 0, ciphers) + challenge, session_id, 0, ciphers) &requires(state_changed); }; refine typeattr ServerHello += &let { proc : bool = $context.connection.proc_server_hello(rec, server_version, - gmt_unix_time, session_id, cipher_suite, 0, + gmt_unix_time, random_bytes, session_id, cipher_suite, 0, compression_method) &requires(state_changed); }; refine typeattr V2ServerHello += &let { - proc : bool = $context.connection.proc_server_hello(rec, server_version, 0, 0, - 0, ciphers, 0) + proc : bool = $context.connection.proc_server_hello(rec, server_version, 0, + conn_id_data, 0, 0, ciphers, 0) &requires(state_changed); cert : bool = $context.connection.proc_v2_certificate(rec, cert_data) diff --git a/src/analyzer/protocol/ssl/ssl-protocol.pac b/src/analyzer/protocol/ssl/ssl-protocol.pac index b35d07f18b..adee974055 100644 --- a/src/analyzer/protocol/ssl/ssl-protocol.pac +++ b/src/analyzer/protocol/ssl/ssl-protocol.pac @@ -346,7 +346,7 @@ type HelloRequest(rec: SSLRecord) = empty &let { type ClientHello(rec: SSLRecord) = record { client_version : uint16; gmt_unix_time : uint32; - random_bytes : bytestring &length = 28 &transient; + random_bytes : bytestring &length = 28; session_len : uint8; session_id : uint8[session_len]; csuit_len : uint16 &check(csuit_len > 1 && csuit_len % 2 == 0); @@ -397,7 +397,7 @@ type V2ClientHello(rec: SSLRecord) = record { type ServerHello(rec: SSLRecord) = record { server_version : uint16; gmt_unix_time : uint32; - random_bytes : bytestring &length = 28 &transient; + random_bytes : bytestring &length = 28; session_len : uint8; session_id : uint8[session_len]; cipher_suite : uint16[1]; diff --git a/testing/btest/Baseline/scripts.base.protocols.ssl.tls-1.2-random/.stdout b/testing/btest/Baseline/scripts.base.protocols.ssl.tls-1.2-random/.stdout new file mode 100644 index 0000000000..d71e0171ce --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ssl.tls-1.2-random/.stdout @@ -0,0 +1,2 @@ +8\xd0U@\xf1\xaamI\xb5SE^K\x82\xa4\xe0\x9eG\xf3\xdd\x1f\xeey\xa6[\xcc\xd7^D\x90 +\xa7^B\xf4'&^E]|c\x83KN\xb0^N6F\xbez\xbb^Ny\xbf^O\x85p\x83\x8dX diff --git a/testing/btest/scripts/base/protocols/ssl/tls-1.2-random.test b/testing/btest/scripts/base/protocols/ssl/tls-1.2-random.test new file mode 100644 index 0000000000..acea4fa131 --- /dev/null +++ b/testing/btest/scripts/base/protocols/ssl/tls-1.2-random.test @@ -0,0 +1,12 @@ +# @TEST-EXEC: bro -r $TRACES/tls1.2.trace %INPUT +# @TEST-EXEC: btest-diff .stdout + +event ssl_client_hello(c: connection, version: count, possible_ts: time, client_random: string, session_id: string, ciphers: count_set) + { + print client_random; + } + +event ssl_server_hello(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count) + { + print server_random; + } From 9834755948c92992b80e87058e2813a0a774fed0 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 11 Sep 2013 12:50:29 -0700 Subject: [PATCH 311/881] fix case where hll_error_margin could be undefined (thanks John) --- .../base/frameworks/sumstats/plugins/hll_unique.bro | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/base/frameworks/sumstats/plugins/hll_unique.bro b/scripts/base/frameworks/sumstats/plugins/hll_unique.bro index fe1bfbd476..63a12d3092 100644 --- a/scripts/base/frameworks/sumstats/plugins/hll_unique.bro +++ b/scripts/base/frameworks/sumstats/plugins/hll_unique.bro @@ -55,9 +55,18 @@ hook compose_resultvals_hook(result: ResultVal, rv1: ResultVal, rv2: ResultVal) if ( ! (rv1?$card || rv2?$card) ) return; - local rhll = hll_cardinality_init(rv1$hll_error_margin, rv1$hll_confidence); + local rhll: opaque of cardinality; + if ( rv1?$card ) + { + rhll = hll_cardinality_init(rv1$hll_error_margin, rv1$hll_confidence); hll_cardinality_merge_into(rhll, rv1$card); + } + else # if we do not have rv1, we have to have rv2... + { + rhll = hll_cardinality_init(rv2$hll_error_margin, rv2$hll_confidence); + } + if ( rv2?$card ) hll_cardinality_merge_into(rhll, rv2$card); From b02709f88fea7e8d1a389429d5608bb101fa94e1 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Wed, 11 Sep 2013 16:32:02 -0500 Subject: [PATCH 312/881] Fix broken links in the documentation Also removed a duplicate link under "Script Reference". --- NEWS | 2 +- doc/components/index.rst | 2 +- doc/frameworks/logging-elasticsearch.rst | 2 +- doc/install/guidelines.rst | 2 +- doc/intro/index.rst | 4 ++-- doc/scripts/index.rst | 1 - 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 2755be9a8d..dba45c279d 100644 --- a/NEWS +++ b/NEWS @@ -631,7 +631,7 @@ Variable Naming - Identifiers may have been renamed to conform to new `scripting conventions - `_ + `_ Removed Functionality diff --git a/doc/components/index.rst b/doc/components/index.rst index defae92647..fe05f13683 100644 --- a/doc/components/index.rst +++ b/doc/components/index.rst @@ -24,5 +24,5 @@ current, independent component releases. PySubnetTree - Python module for CIDR lookups trace-summary - Script for generating break-downs of network traffic -The `Broccoli API Reference `_ may also be of +The `Broccoli API Reference <../broccoli-api/index.html>`_ may also be of interest. diff --git a/doc/frameworks/logging-elasticsearch.rst b/doc/frameworks/logging-elasticsearch.rst index 7571c68219..6711d29543 100644 --- a/doc/frameworks/logging-elasticsearch.rst +++ b/doc/frameworks/logging-elasticsearch.rst @@ -25,7 +25,7 @@ respond successfully to the insertion request. Installing ElasticSearch ------------------------ -Download the latest version from: . +Download the latest version from: http://www.elasticsearch.org/download/. Once extracted, start ElasticSearch with:: # ./bin/elasticsearch diff --git a/doc/install/guidelines.rst b/doc/install/guidelines.rst index f0b10eb8d1..7835c83716 100644 --- a/doc/install/guidelines.rst +++ b/doc/install/guidelines.rst @@ -9,7 +9,7 @@ If you're doing an upgrade install (rather than a fresh install), there's two suggested approaches: either install Bro using the same installation prefix directory as before, or pick a new prefix and copy local customizations over. In the following we summarize general -guidelines for upgrading, see the `Release Notes `_ for +guidelines for upgrading, see the :ref:`release-notes` for version-specific information. Re-Using Previous Install Prefix diff --git a/doc/intro/index.rst b/doc/intro/index.rst index 7ba6c070f8..cf448a0c84 100644 --- a/doc/intro/index.rst +++ b/doc/intro/index.rst @@ -163,7 +163,7 @@ History :width: 600 :align: center :alt: Bro History Timeline - :target: history.png + :target: ../_images/history.png Timeline of Bro's History (click to enlarge). @@ -218,7 +218,7 @@ Architecture :width: 400 :align: center :alt: Bro Architecture - :target: {{docroot}}/images/architecture.png + :target: ../_images/architecture.png Bro's internal architecture. diff --git a/doc/scripts/index.rst b/doc/scripts/index.rst index 6314951600..8897504bb0 100644 --- a/doc/scripts/index.rst +++ b/doc/scripts/index.rst @@ -7,7 +7,6 @@ Script Reference .. toctree:: :maxdepth: 1 - packages builtins Built-In Functions (BIFs) scripts From 801f32c8eec261a1796b92d1b78fad50d89e5cc2 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 12 Sep 2013 12:33:24 -0500 Subject: [PATCH 313/881] Updating submodule(s). [nomail] --- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- cmake | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aux/binpac b/aux/binpac index d946952e0d..b8f09f9cb0 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit d946952e0d18c66679511c1519e9feda2fba123f +Subproject commit b8f09f9cb03903b9f9d7ce81c7ec6621830880df diff --git a/aux/bro-aux b/aux/bro-aux index 0b6fce59fc..cfe77b184c 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 0b6fce59fc503fb22d87d5f0cdfeb162885189e2 +Subproject commit cfe77b184c2362fe85d36a597a1cda776aac0a80 diff --git a/aux/broccoli b/aux/broccoli index a0b18634e5..a7b7970ebd 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit a0b18634e5840dca59bd6ca4c486a761f37c076e +Subproject commit a7b7970ebdc649be84cc3c3b3e4f2c1cfda1b1e7 diff --git a/aux/broctl b/aux/broctl index d53d07dafe..704f792b3e 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit d53d07dafe904db24ee1d022b3f831007f824f87 +Subproject commit 704f792b3eb873ba9ee3a2eff98c47e6a5656a27 diff --git a/cmake b/cmake index 370f7efc6e..c966aecf2b 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 370f7efc6e144f978e2309ad80b1a10c83feaaa9 +Subproject commit c966aecf2bc83f7bbfdd1ac716c6627dd95cb2ec From 0b97343ff77509b423d350096b857a8fffea16c9 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 12 Sep 2013 15:23:52 -0500 Subject: [PATCH 314/881] Fix various potential memory leaks. Though I expect most not to be exercised in practice. --- src/BroDoc.cc | 7 +++--- src/Conn.cc | 6 +++++ src/DFA.cc | 4 ++++ src/DebugLogger.cc | 2 ++ src/Expr.cc | 4 ++++ src/Net.cc | 1 + src/PktSrc.cc | 1 + src/RemoteSerializer.cc | 21 +++++++++++++++++ src/RuleMatcher.cc | 1 + src/Serializer.cc | 10 ++++++++ src/Stmt.cc | 1 + src/Var.cc | 3 +-- src/analyzer/protocol/dhcp/dhcp-analyzer.pac | 7 ++++++ src/analyzer/protocol/gnutella/Gnutella.cc | 2 ++ src/analyzer/protocol/login/RSH.cc | 3 +++ src/analyzer/protocol/mime/MIME.cc | 3 ++- src/analyzer/protocol/netbios/NetbiosSSN.cc | 9 +++----- src/analyzer/protocol/rpc/NFS.cc | 1 + src/input/Manager.cc | 20 ++++++++++++++++ src/input/readers/Ascii.cc | 5 ++++ src/input/readers/Benchmark.cc | 2 ++ src/input/readers/SQLite.cc | 24 +++++++++++++++++--- src/logging/WriterFrontend.cc | 1 + src/main.cc | 2 +- src/probabilistic/CardinalityCounter.cc | 8 ++++++- src/probabilistic/Topk.cc | 5 ++-- src/threading/SerialTypes.h | 2 ++ src/util.cc | 17 ++++---------- src/util.h | 2 +- 29 files changed, 142 insertions(+), 32 deletions(-) diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 55dc8ce558..6953680df0 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -99,8 +99,6 @@ void BroDoc::AddImport(const std::string& s) if ( f && full_filename && subpath ) { - fclose(f); - char* tmp = copy_string(full_filename); char* filename = basename(tmp); extern char* PACKAGE_LOADER; @@ -139,6 +137,9 @@ void BroDoc::AddImport(const std::string& s) fprintf(stderr, "Failed to document '@load %s' in file: %s\n", s.c_str(), reST_filename.c_str()); + if ( f ) + fclose(f); + delete [] full_filename; delete [] subpath; } @@ -559,7 +560,7 @@ static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module) e = new CommentedEnumType(e); e->SetTypeID(copy_string(tag_id.c_str())); - ID* dummy_id = new ID(copy_string(tag_id.c_str()), SCOPE_GLOBAL, true); + ID* dummy_id = new ID(tag_id.c_str(), SCOPE_GLOBAL, true); dummy_id->SetType(e); dummy_id->MakeType(); diff --git a/src/Conn.cc b/src/Conn.cc index 77c854c126..2e5aa0513e 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -527,7 +527,13 @@ Val* Connection::BuildVersionVal(const char* s, int len) // We need at least a name. if ( ! name ) + { + Unref(major); + Unref(minor); + Unref(minor2); + Unref(addl); return 0; + } RecordVal* version = new RecordVal(software_version); version->Assign(0, major ? major : new Val(-1, TYPE_INT)); diff --git a/src/DFA.cc b/src/DFA.cc index 06ccfd9342..3bdc444f9e 100644 --- a/src/DFA.cc +++ b/src/DFA.cc @@ -304,6 +304,7 @@ DFA_State_Cache::~DFA_State_Cache() { assert(e->state); delete e->hash; + Unref(e->state); delete e; } } @@ -410,7 +411,10 @@ DFA_Machine::DFA_Machine(NFA_Machine* n, EquivClass* arg_ec) (void) StateSetToDFA_State(state_set, start_state, ec); } else + { start_state = 0; // Jam + delete ns; + } } DFA_Machine::~DFA_Machine() diff --git a/src/DebugLogger.cc b/src/DebugLogger.cc index dc557c4a0a..95049ef70b 100644 --- a/src/DebugLogger.cc +++ b/src/DebugLogger.cc @@ -79,6 +79,8 @@ void DebugLogger::EnableStreams(const char* s) tok = strtok(0, ","); } + + delete [] tmp; } void DebugLogger::Log(DebugStream stream, const char* fmt, ...) diff --git a/src/Expr.cc b/src/Expr.cc index 221f6545ac..e64172675e 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -2964,6 +2964,7 @@ Val* IndexExpr::Eval(Frame* f) const if ( v_v1->Size() != v_v2->Size() ) { Error("size mismatch, boolean index and vector"); + Unref(v_result); return 0; } @@ -3803,6 +3804,8 @@ Val* VectorConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( ! v || ! vec->Assign(i, v) ) { Error(fmt("initialization type mismatch at index %d", i), e); + if ( ! aggr ) + Unref(vec); return 0; } } @@ -5159,6 +5162,7 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const if ( exprs.length() != tl->length() ) { Error("index mismatch", t); + Unref(v); return 0; } diff --git a/src/Net.cc b/src/Net.cc index 73c618b8af..ac4dacf9b8 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -119,6 +119,7 @@ RETSIGTYPE watchdog(int /* signo */) if ( pkt_dumper->IsError() ) { reporter->Error("watchdog: can't open watchdog-pkt.pcap for writing\n"); + delete pkt_dumper; pkt_dumper = 0; } } diff --git a/src/PktSrc.cc b/src/PktSrc.cc index 48b382565b..f318405920 100644 --- a/src/PktSrc.cc +++ b/src/PktSrc.cc @@ -624,6 +624,7 @@ SecondaryPath::SecondaryPath() event_list.append(se); delete h; + Unref(index); } } diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 9bbaba3d55..543bfaee86 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -2699,6 +2699,7 @@ bool RemoteSerializer::ProcessLogCreateWriter() EnumVal* id_val = 0; EnumVal* writer_val = 0; threading::Field** fields = 0; + int delete_fields_up_to = -1; BinarySerializationFormat fmt; fmt.StartRead(current_args->data, current_args->len); @@ -2721,7 +2722,10 @@ bool RemoteSerializer::ProcessLogCreateWriter() { fields[i] = new threading::Field; if ( ! fields[i]->Read(&fmt) ) + { + delete_fields_up_to = i + 1; goto error; + } } fmt.EndRead(); @@ -2731,7 +2735,10 @@ bool RemoteSerializer::ProcessLogCreateWriter() if ( ! log_mgr->CreateWriter(id_val, writer_val, info, num_fields, fields, true, false, true) ) + { + delete_fields_up_to = num_fields; goto error; + } Unref(id_val); Unref(writer_val); @@ -2741,7 +2748,12 @@ bool RemoteSerializer::ProcessLogCreateWriter() error: Unref(id_val); Unref(writer_val); + delete info; + for ( int i = 0; i < delete_fields_up_to; ++i ) + delete fields[i]; + + delete fields; Error("write error for creating writer"); return false; } @@ -2780,8 +2792,15 @@ bool RemoteSerializer::ProcessLogWrite() for ( int i = 0; i < num_fields; i++ ) { vals[i] = new threading::Value; + if ( ! vals[i]->Read(&fmt) ) + { + for ( int j = 0; j <= i; ++j ) + delete vals[j]; + + delete vals; goto error; + } } id_val = new EnumVal(id, BifType::Enum::Log::ID); @@ -4267,6 +4286,8 @@ bool SocketComm::AcceptConnection(int fd) if ( ! peer->io->Init() ) { Error(fmt("can't init peer io: %s", peer->io->Error()), false); + delete peer->io; + delete peer; return false; } diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index 974004e2ac..ed33db6792 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -1226,6 +1226,7 @@ static bool val_to_maskedval(Val* v, maskedvalue_list* append_to, default: rules_error("Wrong type of identifier"); + delete mval; return false; } diff --git a/src/Serializer.cc b/src/Serializer.cc index 145aab3f4d..e6bf6429d7 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -1148,7 +1148,11 @@ Packet* Packet::Unserialize(UnserialInfo* info) UNSERIALIZE(&tv_usec) && UNSERIALIZE(&len) && UNSERIALIZE(&p->link_type)) ) + { + delete p; + delete hdr; return 0; + } hdr->ts.tv_sec = tv_sec; hdr->ts.tv_usec = tv_usec; @@ -1156,12 +1160,18 @@ Packet* Packet::Unserialize(UnserialInfo* info) char* tag; if ( ! info->s->Read((char**) &tag, 0, "tag") ) + { + delete p; + delete hdr; return 0; + } char* pkt; int caplen; if ( ! info->s->Read((char**) &pkt, &caplen, "data") ) { + delete p; + delete hdr; delete [] tag; return 0; } diff --git a/src/Stmt.cc b/src/Stmt.cc index 4b8e6c03e2..28f29aba0b 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -788,6 +788,7 @@ bool SwitchStmt::AddCaseLabelMapping(const Val* v, int idx) } case_label_map.Insert(hk, new int(idx)); + delete hk; return true; } diff --git a/src/Var.cc b/src/Var.cc index e85b1ba124..d384fedc74 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -416,8 +416,7 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, if ( arg_id && ! arg_id->IsGlobal() ) arg_id->Error("argument name used twice"); - arg_id = install_ID(copy_string(arg_i->id), module_name, - false, false); + arg_id = install_ID(arg_i->id, module_name, false, false); arg_id->SetType(arg_i->type->Ref()); } } diff --git a/src/analyzer/protocol/dhcp/dhcp-analyzer.pac b/src/analyzer/protocol/dhcp/dhcp-analyzer.pac index 621c86cfb8..0be31334c1 100644 --- a/src/analyzer/protocol/dhcp/dhcp-analyzer.pac +++ b/src/analyzer/protocol/dhcp/dhcp-analyzer.pac @@ -110,6 +110,10 @@ flow DHCP_Flow(is_orig: bool) { connection()->bro_analyzer()->Conn(), dhcp_msg_val_->Ref(), host_name); break; + + default: + Unref(host_name); + break; } return true; @@ -201,6 +205,9 @@ flow DHCP_Flow(is_orig: bool) { dhcp_msg_val_->Ref(), host_name); break; + default: + Unref(host_name); + break; } return true; diff --git a/src/analyzer/protocol/gnutella/Gnutella.cc b/src/analyzer/protocol/gnutella/Gnutella.cc index c0bab92007..ff71a55fc8 100644 --- a/src/analyzer/protocol/gnutella/Gnutella.cc +++ b/src/analyzer/protocol/gnutella/Gnutella.cc @@ -66,6 +66,8 @@ void Gnutella_Analyzer::Done() ConnectionEvent(gnutella_establish, vl); else if ( ! Established () && gnutella_not_establish ) ConnectionEvent(gnutella_not_establish, vl); + else + delete_vals(vl); } if ( gnutella_partial_binary_msg ) diff --git a/src/analyzer/protocol/login/RSH.cc b/src/analyzer/protocol/login/RSH.cc index 1890fc3098..e70fae1b8c 100644 --- a/src/analyzer/protocol/login/RSH.cc +++ b/src/analyzer/protocol/login/RSH.cc @@ -175,6 +175,9 @@ void Rsh_Analyzer::DeliverStream(int len, const u_char* data, bool orig) else if ( rsh_reply ) ConnectionEvent(rsh_reply, vl); + + else + delete_vals(vl); } void Rsh_Analyzer::ClientUserName(const char* s) diff --git a/src/analyzer/protocol/mime/MIME.cc b/src/analyzer/protocol/mime/MIME.cc index 039f26b905..5748bece86 100644 --- a/src/analyzer/protocol/mime/MIME.cc +++ b/src/analyzer/protocol/mime/MIME.cc @@ -831,7 +831,6 @@ int MIME_Entity::ParseContentEncodingField(MIME_Header* h) int MIME_Entity::ParseFieldParameters(int len, const char* data) { data_chunk_t attr; - BroString* val; while ( 1 ) { @@ -864,11 +863,13 @@ int MIME_Entity::ParseFieldParameters(int len, const char* data) data += offset; len -= offset; + BroString* val = 0; // token or quoted-string offset = MIME_get_value(len, data, val); if ( offset < 0 ) { IllegalFormat("value not found in parameter specification"); + delete val; continue; } diff --git a/src/analyzer/protocol/netbios/NetbiosSSN.cc b/src/analyzer/protocol/netbios/NetbiosSSN.cc index 4a7a5dbc59..bed906135e 100644 --- a/src/analyzer/protocol/netbios/NetbiosSSN.cc +++ b/src/analyzer/protocol/netbios/NetbiosSSN.cc @@ -129,15 +129,12 @@ int NetbiosSSN_Interpreter::ParseBroadcast(const u_char* data, int len, data += dstname->Len()+1; len -= dstname->Len(); - if ( smb_session ) - { - smb_session->Deliver(is_query, len, data); - return 0; - } - delete srcname; delete dstname; + if ( smb_session ) + smb_session->Deliver(is_query, len, data); + return 0; } diff --git a/src/analyzer/protocol/rpc/NFS.cc b/src/analyzer/protocol/rpc/NFS.cc index 51d1b90691..136491ec84 100644 --- a/src/analyzer/protocol/rpc/NFS.cc +++ b/src/analyzer/protocol/rpc/NFS.cc @@ -251,6 +251,7 @@ int NFS_Interp::RPC_BuildReply(RPC_CallInfo* c, BifEnum::rpc_status rpc_status, analyzer->ConnectionEvent(event, vl); } + Unref(reply); return 1; } diff --git a/src/input/Manager.cc b/src/input/Manager.cc index 2534ed1b69..94c025a459 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -416,6 +416,7 @@ bool Manager::CreateEventStream(RecordVal* fval) if ( etype->Flavor() != FUNC_FLAVOR_EVENT ) { reporter->Error("stream event is a function, not an event"); + delete stream; return false; } @@ -424,18 +425,21 @@ bool Manager::CreateEventStream(RecordVal* fval) if ( args->length() < 2 ) { reporter->Error("event takes not enough arguments"); + delete stream; return false; } if ( ! same_type((*args)[1], BifType::Enum::Input::Event, 0) ) { reporter->Error("events second attribute must be of type Input::Event"); + delete stream; return false; } if ( ! same_type((*args)[0], BifType::Record::Input::EventDescription, 0) ) { reporter->Error("events first attribute must be of type Input::EventDescription"); + delete stream; return false; } @@ -444,6 +448,7 @@ bool Manager::CreateEventStream(RecordVal* fval) if ( args->length() != fields->NumFields() + 2 ) { reporter->Error("event has wrong number of arguments"); + delete stream; return false; } @@ -452,6 +457,7 @@ bool Manager::CreateEventStream(RecordVal* fval) if ( !same_type((*args)[i+2], fields->FieldType(i) ) ) { reporter->Error("Incompatible type for event"); + delete stream; return false; } } @@ -463,6 +469,7 @@ bool Manager::CreateEventStream(RecordVal* fval) if ( args->length() != 3 ) { reporter->Error("event has wrong number of arguments"); + delete stream; return false; } @@ -475,6 +482,7 @@ bool Manager::CreateEventStream(RecordVal* fval) reporter->Error("Incompatible type '%s':%s for event, which needs type '%s':%s\n", type_name((*args)[2]->Tag()), desc1.Description(), type_name(fields->Tag()), desc2.Description()); + delete stream; return false; } @@ -493,6 +501,7 @@ bool Manager::CreateEventStream(RecordVal* fval) if ( status ) { reporter->Error("Problem unrolling"); + delete stream; return false; } @@ -560,12 +569,14 @@ bool Manager::CreateTableStream(RecordVal* fval) if ( j >= num ) { reporter->Error("Table type has more indexes than index definition"); + delete stream; return false; } if ( ! same_type(idx->FieldType(j), (*tl)[j]) ) { reporter->Error("Table type does not match index type"); + delete stream; return false; } } @@ -573,6 +584,7 @@ bool Manager::CreateTableStream(RecordVal* fval) if ( num != j ) { reporter->Error("Table has less elements than index definition"); + delete stream; return false; } @@ -589,6 +601,7 @@ bool Manager::CreateTableStream(RecordVal* fval) if ( etype->Flavor() != FUNC_FLAVOR_EVENT ) { reporter->Error("stream event is a function, not an event"); + delete stream; return false; } @@ -597,36 +610,42 @@ bool Manager::CreateTableStream(RecordVal* fval) if ( args->length() != 4 ) { reporter->Error("Table event must take 4 arguments"); + delete stream; return false; } if ( ! same_type((*args)[0], BifType::Record::Input::TableDescription, 0) ) { reporter->Error("table events first attribute must be of type Input::TableDescription"); + delete stream; return false; } if ( ! same_type((*args)[1], BifType::Enum::Input::Event, 0) ) { reporter->Error("table events second attribute must be of type Input::Event"); + delete stream; return false; } if ( ! same_type((*args)[2], idx) ) { reporter->Error("table events index attributes do not match"); + delete stream; return false; } if ( want_record->InternalInt() == 1 && ! same_type((*args)[3], val) ) { reporter->Error("table events value attributes do not match"); + delete stream; return false; } else if ( want_record->InternalInt() == 0 && !same_type((*args)[3], val->FieldType(0) ) ) { reporter->Error("table events value attribute does not match"); + delete stream; return false; } @@ -651,6 +670,7 @@ bool Manager::CreateTableStream(RecordVal* fval) if ( status ) { reporter->Error("Problem unrolling"); + delete stream; return false; } diff --git a/src/input/readers/Ascii.cc b/src/input/readers/Ascii.cc index 9a855b102b..687d37c96f 100644 --- a/src/input/readers/Ascii.cc +++ b/src/input/readers/Ascii.cc @@ -320,6 +320,11 @@ bool Ascii::DoUpdate() { Error(Fmt("Not enough fields in line %s. Found %d fields, want positions %d and %d", line.c_str(), pos, (*fit).position, (*fit).secondary_position)); + + for ( int i = 0; i < fpos; i++ ) + delete fields[i]; + + delete [] fields; return false; } diff --git a/src/input/readers/Benchmark.cc b/src/input/readers/Benchmark.cc index 0584037e05..3e53dfb35f 100644 --- a/src/input/readers/Benchmark.cc +++ b/src/input/readers/Benchmark.cc @@ -212,6 +212,7 @@ threading::Value* Benchmark::EntryToVal(TypeTag type, TypeTag subtype) if ( newval == 0 ) { Error("Error while reading set"); + delete val; return 0; } lvals[pos] = newval; @@ -223,6 +224,7 @@ threading::Value* Benchmark::EntryToVal(TypeTag type, TypeTag subtype) default: Error(Fmt("unsupported field format %d", type)); + delete val; return 0; } diff --git a/src/input/readers/SQLite.cc b/src/input/readers/SQLite.cc index 2739aff572..eec3698540 100644 --- a/src/input/readers/SQLite.cc +++ b/src/input/readers/SQLite.cc @@ -148,6 +148,7 @@ Value* SQLite::EntryToVal(sqlite3_stmt *st, const threading::Field *field, int p if ( sqlite3_column_type(st, pos) != SQLITE_INTEGER ) { Error("Invalid data type for boolean - expected Integer"); + delete val; return 0; } @@ -158,6 +159,7 @@ Value* SQLite::EntryToVal(sqlite3_stmt *st, const threading::Field *field, int p else { Error(Fmt("Invalid value for boolean: %d", res)); + delete val; return 0; } break; @@ -220,12 +222,14 @@ Value* SQLite::EntryToVal(sqlite3_stmt *st, const threading::Field *field, int p { const char *text = (const char*) sqlite3_column_text(st, pos); string s(text, sqlite3_column_bytes(st, pos)); + delete val; val = io->ParseValue(s, "", field->type, field->subtype); break; } default: Error(Fmt("unsupported field format %d", field->type)); + delete val; return 0; } @@ -257,6 +261,8 @@ bool SQLite::DoUpdate() if ( mapping[j] != -1 ) { Error(Fmt("SQLite statement returns several columns with name %s! Cannot decide which to choose, aborting", name)); + delete [] mapping; + delete [] submapping; return false; } @@ -269,6 +275,8 @@ bool SQLite::DoUpdate() if ( submapping[j] != -1 ) { Error(Fmt("SQLite statement returns several columns with name %s! Cannot decide which to choose, aborting", name)); + delete [] mapping; + delete [] submapping; return false; } @@ -282,6 +290,8 @@ bool SQLite::DoUpdate() if ( mapping[i] == -1 ) { Error(Fmt("Required field %s not found after SQLite statement", fields[i]->name)); + delete [] mapping; + delete [] submapping; return false; } } @@ -295,20 +305,28 @@ bool SQLite::DoUpdate() { ofields[j] = EntryToVal(st, fields[j], mapping[j], submapping[j]); if ( ofields[j] == 0 ) + { + for ( int k = 0; k < j; ++k ) + delete ofields[k]; + + delete [] ofields; + delete [] mapping; + delete [] submapping; return false; + } } SendEntry(ofields); } + delete [] mapping; + delete [] submapping; + if ( checkError(errorcode) ) // check the last error code returned by sqlite return false; EndCurrentSend(); - delete [] mapping; - delete [] submapping; - if ( checkError(sqlite3_reset(st)) ) return false; diff --git a/src/logging/WriterFrontend.cc b/src/logging/WriterFrontend.cc index 73cba2ff3a..1e254bfc83 100644 --- a/src/logging/WriterFrontend.cc +++ b/src/logging/WriterFrontend.cc @@ -132,6 +132,7 @@ WriterFrontend::~WriterFrontend() Unref(stream); Unref(writer); delete info; + delete [] name; } void WriterFrontend::Stop() diff --git a/src/main.cc b/src/main.cc index 5acba12367..313e1a40b0 100644 --- a/src/main.cc +++ b/src/main.cc @@ -222,7 +222,7 @@ void usage() fprintf(stderr, " $BROPATH | file search path (%s)\n", bro_path()); fprintf(stderr, " $BROMAGIC | libmagic mime magic database search path (%s)\n", bro_magic_path()); - fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes()); + fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes().c_str()); fprintf(stderr, " $BRO_DNS_FAKE | disable DNS lookups (%s)\n", bro_dns_fake()); fprintf(stderr, " $BRO_SEED_FILE | file to load seeds from (not set)\n"); fprintf(stderr, " $BRO_LOG_SUFFIX | ASCII log file extension (.%s)\n", logging::writer::Ascii::LogExt().c_str()); diff --git a/src/probabilistic/CardinalityCounter.cc b/src/probabilistic/CardinalityCounter.cc index b9e0744225..ec82c31e7f 100644 --- a/src/probabilistic/CardinalityCounter.cc +++ b/src/probabilistic/CardinalityCounter.cc @@ -188,5 +188,11 @@ CardinalityCounter* CardinalityCounter::Unserialize(UnserialInfo* info) buckets[i] = (uint8)c; } - return valid ? c : 0; + if ( ! valid ) + { + delete c; + c = 0; + } + + return c; } diff --git a/src/probabilistic/Topk.cc b/src/probabilistic/Topk.cc index 95d0ac732e..e01b4e41b6 100644 --- a/src/probabilistic/Topk.cc +++ b/src/probabilistic/Topk.cc @@ -161,6 +161,7 @@ void TopkVal::Merge(const TopkVal* value, bool doPrune) Element* e = b->elements.front(); HashKey* key = GetHash(e->value); elementDict->RemoveEntry(key); + delete key; delete e; b->elements.pop_front(); @@ -323,6 +324,7 @@ uint64_t TopkVal::GetCount(Val* value) const { HashKey* key = GetHash(value); Element* e = (Element*) elementDict->Lookup(key); + delete key; if ( e == 0 ) { @@ -330,7 +332,6 @@ uint64_t TopkVal::GetCount(Val* value) const return 0; } - delete key; return e->parent->count; } @@ -338,6 +339,7 @@ uint64_t TopkVal::GetEpsilon(Val* value) const { HashKey* key = GetHash(value); Element* e = (Element*) elementDict->Lookup(key); + delete key; if ( e == 0 ) { @@ -345,7 +347,6 @@ uint64_t TopkVal::GetEpsilon(Val* value) const return 0; } - delete key; return e->epsilon; } diff --git a/src/threading/SerialTypes.h b/src/threading/SerialTypes.h index f4f0bc0957..8a4f46a15c 100644 --- a/src/threading/SerialTypes.h +++ b/src/threading/SerialTypes.h @@ -126,6 +126,8 @@ struct Value { char* data; int length; } string_val; + + _val() { memset(this, 0, sizeof(_val)); } } val; /** diff --git a/src/util.cc b/src/util.cc index 10a1ad94be..f26b3fb0c2 100644 --- a/src/util.cc +++ b/src/util.cc @@ -902,24 +902,17 @@ const char* bro_magic_path() return path; } -const char* bro_prefixes() +string bro_prefixes() { - int len = 1; // room for \0 - loop_over_list(prefixes, i) - len += strlen(prefixes[i]) + 1; - - char* p = new char[len]; + string rval; loop_over_list(prefixes, j) if ( j == 0 ) - strcpy(p, prefixes[j]); + rval.append(prefixes[j]); else - { - strcat(p, ":"); - strcat(p, prefixes[j]); - } + rval.append(":").append(prefixes[j]); - return p; + return rval; } const char* PACKAGE_LOADER = "__load__.bro"; diff --git a/src/util.h b/src/util.h index 05b3f032d0..fcdfd6d499 100644 --- a/src/util.h +++ b/src/util.h @@ -204,7 +204,7 @@ extern int int_list_cmp(const void* v1, const void* v2); extern const char* bro_path(); extern const char* bro_magic_path(); -extern const char* bro_prefixes(); +extern std::string bro_prefixes(); std::string dot_canon(std::string path, std::string file, std::string prefix = ""); const char* normalize_path(const char* path); void get_script_subpath(const std::string& full_filename, const char** subpath); From 1d33883dfc28250363dcb8314898ae6f406719d3 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Fri, 13 Sep 2013 00:30:18 -0500 Subject: [PATCH 315/881] Fix compiler warnings --- src/input/readers/SQLite.cc | 2 +- src/probabilistic/BitVector.cc | 4 +++- src/probabilistic/Hasher.cc | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/input/readers/SQLite.cc b/src/input/readers/SQLite.cc index eec3698540..f97b2cea13 100644 --- a/src/input/readers/SQLite.cc +++ b/src/input/readers/SQLite.cc @@ -306,7 +306,7 @@ bool SQLite::DoUpdate() ofields[j] = EntryToVal(st, fields[j], mapping[j], submapping[j]); if ( ofields[j] == 0 ) { - for ( int k = 0; k < j; ++k ) + for ( unsigned int k = 0; k < j; ++k ) delete ofields[k]; delete [] ofields; diff --git a/src/probabilistic/BitVector.cc b/src/probabilistic/BitVector.cc index 257fc9ad71..79b403960e 100644 --- a/src/probabilistic/BitVector.cc +++ b/src/probabilistic/BitVector.cc @@ -495,6 +495,7 @@ BitVector::size_type BitVector::FindNext(size_type i) const uint64 BitVector::Hash() const { u_char buf[SHA256_DIGEST_LENGTH]; + uint64 digest; SHA256_CTX ctx; sha256_init(&ctx); @@ -502,7 +503,8 @@ uint64 BitVector::Hash() const sha256_update(&ctx, &bits[i], sizeof(bits[i])); sha256_final(&ctx, buf); - return *reinterpret_cast(buf); // Use the first bytes as digest. + memcpy(&digest, buf, sizeof(digest)); // Use the first bytes as digest + return digest; } BitVector::size_type BitVector::lowest_bit(block_type block) diff --git a/src/probabilistic/Hasher.cc b/src/probabilistic/Hasher.cc index b497dba9be..1f5f0910ba 100644 --- a/src/probabilistic/Hasher.cc +++ b/src/probabilistic/Hasher.cc @@ -13,6 +13,7 @@ using namespace probabilistic; uint64 Hasher::MakeSeed(const void* data, size_t size) { u_char buf[SHA256_DIGEST_LENGTH]; + uint64 tmpseed; SHA256_CTX ctx; sha256_init(&ctx); @@ -29,7 +30,8 @@ uint64 Hasher::MakeSeed(const void* data, size_t size) } sha256_final(&ctx, buf); - return *reinterpret_cast(buf); // Use the first bytes as seed. + memcpy(&tmpseed, buf, sizeof(tmpseed)); // Use the first bytes as seed. + return tmpseed; } Hasher::digest_vector Hasher::Hash(const HashKey* key) const From 33a7e96268fc46b9b49d578070392b369b43537d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Sep 2013 12:51:24 -0500 Subject: [PATCH 316/881] Fix another function val reference counting bug. Now that functions get unref'd in the val dtor in order to free mem of unserialized functions, it's important to ref a function when creating a val from a pre-existing function so it's not prematurely free'd. --- src/Val.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Val.cc b/src/Val.cc index 3e5b0eff48..389e76fe1d 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -30,6 +30,7 @@ Val::Val(Func* f) { val.func_val = f; + ::Ref(val.func_val); type = f->FType()->Ref(); attribs = 0; #ifdef DEBUG From a99e873d5c3f7a86f604ef3ea6e83a6a546b8015 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Sep 2013 14:29:45 -0500 Subject: [PATCH 317/881] Fix double-free and deallocator mismatch. --- src/RemoteSerializer.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 543bfaee86..fa5a29386c 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -2753,7 +2753,7 @@ error: for ( int i = 0; i < delete_fields_up_to; ++i ) delete fields[i]; - delete fields; + delete [] fields; Error("write error for creating writer"); return false; } @@ -2798,7 +2798,7 @@ bool RemoteSerializer::ProcessLogWrite() for ( int j = 0; j <= i; ++j ) delete vals[j]; - delete vals; + delete [] vals; goto error; } } @@ -3167,6 +3167,7 @@ bool RemoteSerializer::SendToChild(ChunkedIO::Chunk* c) return true; delete [] c->data; + c->data = 0; if ( ! child_pid ) return false; From 5a992879a060dd247025051990a26d5900feb3a9 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Sep 2013 14:31:03 -0500 Subject: [PATCH 318/881] Fix potential mem leak. --- src/analyzer/protocol/dhcp/dhcp-analyzer.pac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyzer/protocol/dhcp/dhcp-analyzer.pac b/src/analyzer/protocol/dhcp/dhcp-analyzer.pac index 0be31334c1..336c8dc760 100644 --- a/src/analyzer/protocol/dhcp/dhcp-analyzer.pac +++ b/src/analyzer/protocol/dhcp/dhcp-analyzer.pac @@ -69,6 +69,7 @@ flow DHCP_Flow(is_orig: bool) { break; case HOST_NAME_OPTION: + Unref(host_name); host_name = new StringVal((*ptr)->info()->host_name().length(), (const char*) (*ptr)->info()->host_name().begin()); break; @@ -174,6 +175,7 @@ flow DHCP_Flow(is_orig: bool) { break; case HOST_NAME_OPTION: + Unref(host_name); host_name = new StringVal((*ptr)->info()->host_name().length(), (const char*) (*ptr)->info()->host_name().begin()); break; From 3d81432a1e90e46a436b8a1e98cdcb6f0d6a4e1b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Sep 2013 15:05:17 -0500 Subject: [PATCH 319/881] Fix out-of-bounds memory accesses. And remove a variable-length-array usage. --- src/analyzer/protocol/pop3/POP3.cc | 6 ++++-- src/input/Manager.cc | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/analyzer/protocol/pop3/POP3.cc b/src/analyzer/protocol/pop3/POP3.cc index 652fd20e32..ccbbb8df04 100644 --- a/src/analyzer/protocol/pop3/POP3.cc +++ b/src/analyzer/protocol/pop3/POP3.cc @@ -80,7 +80,7 @@ void POP3_Analyzer::DeliverStream(int len, const u_char* data, bool orig) static string trim_whitespace(const char* in) { int n = strlen(in); - char out[n]; + char* out = new char[n + 1]; char* out_p = out; in = skip_whitespace(in); @@ -112,7 +112,9 @@ static string trim_whitespace(const char* in) *out_p = 0; - return string(out); + string rval(out); + delete [] out; + return rval; } void POP3_Analyzer::ProcessRequest(int length, const char* line) diff --git a/src/input/Manager.cc b/src/input/Manager.cc index 94c025a459..d838e8cb75 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -2045,7 +2045,7 @@ int Manager::CopyValue(char *data, const int startpos, const Value* val) case IPv6: length = sizeof(val->val.addr_val.in.in6); memcpy(data + startpos, - (const char*) &(val->val.subnet_val.prefix.in.in4), length); + (const char*) &(val->val.subnet_val.prefix.in.in6), length); break; default: From 735d2c402af678f1fe65a918010d7c5124b5a5f3 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 13 Sep 2013 16:41:41 -0500 Subject: [PATCH 320/881] Fix/improve dereference-before-null-checks. --- src/ChunkedIO.cc | 5 ++--- src/Desc.cc | 11 ----------- src/Desc.h | 2 -- src/RemoteSerializer.cc | 3 +-- src/Serializer.cc | 2 +- src/analyzer/protocol/pia/PIA.cc | 8 +++++--- src/input/readers/Raw.cc | 13 ++++++------- src/input/readers/SQLite.cc | 5 ++++- 8 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/ChunkedIO.cc b/src/ChunkedIO.cc index 2c766c7eb1..7e666ee198 100644 --- a/src/ChunkedIO.cc +++ b/src/ChunkedIO.cc @@ -1074,9 +1074,8 @@ bool ChunkedIOSSL::Read(Chunk** chunk, bool mayblock) read_state = LEN; #ifdef DEBUG - if ( *chunk ) - DBG_LOG(DBG_CHUNKEDIO, "ssl read of size %d [%s]", - (*chunk)->len, fmt_bytes((*chunk)->data, 20)); + DBG_LOG(DBG_CHUNKEDIO, "ssl read of size %d [%s]", + (*chunk)->len, fmt_bytes((*chunk)->data, 20)); #endif return true; diff --git a/src/Desc.cc b/src/Desc.cc index 9d94321427..40b6fcc3d1 100644 --- a/src/Desc.cc +++ b/src/Desc.cc @@ -23,11 +23,7 @@ ODesc::ODesc(desc_type t, BroFile* arg_f) size = DEFAULT_SIZE; base = safe_malloc(size); ((char*) base)[0] = '\0'; - offset = 0; - - if ( ! base ) - OutOfMemory(); } else { @@ -337,16 +333,9 @@ void ODesc::Grow(unsigned int n) { size *= 2; base = safe_realloc(base, size); - if ( ! base ) - OutOfMemory(); } } -void ODesc::OutOfMemory() - { - reporter->InternalError("out of memory"); - } - void ODesc::Clear() { offset = 0; diff --git a/src/Desc.h b/src/Desc.h index 9fa41381ed..c16c00cf13 100644 --- a/src/Desc.h +++ b/src/Desc.h @@ -149,8 +149,6 @@ protected: // Make buffer big enough for n bytes beyond bufp. void Grow(unsigned int n); - void OutOfMemory(); - /** * Returns the location of the first place in the bytes to be hex-escaped. * diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index fa5a29386c..bc006b4b1f 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -2925,8 +2925,7 @@ void RemoteSerializer::GotID(ID* id, Val* val) const char* desc = val->AsString()->CheckString(); current_peer->val->Assign(4, new StringVal(desc)); - Log(LogInfo, fmt("peer_description is %s", - (desc && *desc) ? desc : "not set"), + Log(LogInfo, fmt("peer_description is %s", *desc ? desc : "not set"), current_peer); Unref(id); diff --git a/src/Serializer.cc b/src/Serializer.cc index e6bf6429d7..f7544765fa 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -378,7 +378,7 @@ bool Serializer::UnserializeCall(UnserialInfo* info) ignore = true; } - if ( info->print && types && ! ignore ) + if ( info->print && ! ignore ) v->Describe(&d); } diff --git a/src/analyzer/protocol/pia/PIA.cc b/src/analyzer/protocol/pia/PIA.cc index cc1dd7ea0e..81c7251820 100644 --- a/src/analyzer/protocol/pia/PIA.cc +++ b/src/analyzer/protocol/pia/PIA.cc @@ -147,10 +147,12 @@ void PIA_UDP::ActivateAnalyzer(analyzer::Tag tag, const Rule* rule) return; analyzer::Analyzer* a = Parent()->AddChildAnalyzer(tag); - a->SetSignature(rule); - if ( a ) - ReplayPacketBuffer(a); + if ( ! a ) + return; + + a->SetSignature(rule); + ReplayPacketBuffer(a); } void PIA_UDP::DeactivateAnalyzer(analyzer::Tag tag) diff --git a/src/input/readers/Raw.cc b/src/input/readers/Raw.cc index 2c2b319793..64c29d632c 100644 --- a/src/input/readers/Raw.cc +++ b/src/input/readers/Raw.cc @@ -291,6 +291,12 @@ bool Raw::CloseInput() bool Raw::DoInit(const ReaderInfo& info, int num_fields, const Field* const* fields) { + if ( ! info.source || strlen(info.source) == 0 ) + { + Error("No source path provided"); + return false; + } + fname = info.source; mtime = 0; execute = false; @@ -298,7 +304,6 @@ bool Raw::DoInit(const ReaderInfo& info, int num_fields, const Field* const* fie int want_fields = 1; bool result; - // do Initialization string source = string(info.source); char last = info.source[source.length() - 1]; if ( last == '|' ) @@ -307,12 +312,6 @@ bool Raw::DoInit(const ReaderInfo& info, int num_fields, const Field* const* fie fname = source.substr(0, fname.length() - 1); } - if ( ! info.source || strlen(info.source) == 0 ) - { - Error("No source path provided"); - return false; - } - map::const_iterator it = info.config.find("stdin"); // data that is sent to the child process if ( it != info.config.end() ) { diff --git a/src/input/readers/SQLite.cc b/src/input/readers/SQLite.cc index eec3698540..345dfdc226 100644 --- a/src/input/readers/SQLite.cc +++ b/src/input/readers/SQLite.cc @@ -187,11 +187,14 @@ Value* SQLite::EntryToVal(sqlite3_stmt *st, const threading::Field *field, int p if ( subpos != -1 ) { const char *text = (const char*) sqlite3_column_text(st, subpos); - string s(text, sqlite3_column_bytes(st, subpos)); + if ( text == 0 ) Error("Port protocol definition did not contain text"); else + { + string s(text, sqlite3_column_bytes(st, subpos)); val->val.port_val.proto = io->ParseProto(s); + } } break; } From 20f11ad2378dcbdc0b4cc2fe5203dd87f879d5e9 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Mon, 16 Sep 2013 11:20:07 -0500 Subject: [PATCH 321/881] Fix another compiler warning --- src/builtin-func.l | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/builtin-func.l b/src/builtin-func.l index 0e63b06be6..c70b99b6c8 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -208,7 +208,11 @@ void init_alternative_mode() fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); static char guard[1024]; - getcwd(guard, sizeof(guard)); + if ( getcwd(guard, sizeof(guard)) == NULL ) + { + fprintf(stderr, "Error: cannot get current working directory\n"); + err_exit(); + } strncat(guard, "/", sizeof(guard) - strlen(guard) - 1); strncat(guard, input_filename, sizeof(guard) - strlen(guard) - 1); From c0f780c728503006c3d285cd3369ea3969a5024c Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 16 Sep 2013 10:40:25 -0700 Subject: [PATCH 322/881] update hll documentation, make a few functions private and create a new copy constructor. --- src/probabilistic/CardinalityCounter.cc | 29 ++++- src/probabilistic/CardinalityCounter.h | 128 +++++++++++++--------- src/probabilistic/cardinality-counter.bif | 14 +-- 3 files changed, 108 insertions(+), 63 deletions(-) diff --git a/src/probabilistic/CardinalityCounter.cc b/src/probabilistic/CardinalityCounter.cc index ec82c31e7f..3e274da886 100644 --- a/src/probabilistic/CardinalityCounter.cc +++ b/src/probabilistic/CardinalityCounter.cc @@ -15,6 +15,9 @@ int CardinalityCounter::OptimalB(double error, double confidence) double initial_estimate = 2 * (log(1.04) - log(error)) / log(2); int answer = (int) floor(initial_estimate); + // k is the number of standard deviations that we have to go to have + // a confidence level of conf. + double k = 0; do { @@ -54,6 +57,12 @@ void CardinalityCounter::Init(uint64 size) V = m; } +CardinalityCounter::CardinalityCounter(CardinalityCounter& other) + { + Init(other.GetM()); + Merge(&other); + } + CardinalityCounter::CardinalityCounter(double error_margin, double confidence) { int b = OptimalB(error_margin, confidence); @@ -107,7 +116,16 @@ void CardinalityCounter::AddElement(uint64 hash) buckets[index] = temp; } -double CardinalityCounter::Size() +/** + * Estimate the size by using the the "raw" HyperLogLog estimate. Then, + * check if it's too "large" or "small" because the raw estimate doesn't + * do well in those cases. + * Thus, we correct for those errors as specified in the paper. + * + * Note - we deviate from the HLL algorithm in the paper here, because + * of our 64-bit hashes. + **/ +double CardinalityCounter::Size() const { double answer = 0; for ( unsigned int i = 0; i < m; i++ ) @@ -126,8 +144,11 @@ double CardinalityCounter::Size() return -pow(2, 64) * log(1 - (answer / pow(2, 64))); } -void CardinalityCounter::Merge(CardinalityCounter* c) +bool CardinalityCounter::Merge(CardinalityCounter* c) { + if ( m != c->GetM() ) + return false; + uint8_t* temp = c->GetBuckets(); V = 0; @@ -140,6 +161,8 @@ void CardinalityCounter::Merge(CardinalityCounter* c) if ( buckets[i] == 0 ) ++V; } + + return true; } uint8_t* CardinalityCounter::GetBuckets() @@ -147,7 +170,7 @@ uint8_t* CardinalityCounter::GetBuckets() return buckets; } -uint64 CardinalityCounter::GetM() +uint64 CardinalityCounter::GetM() const { return m; } diff --git a/src/probabilistic/CardinalityCounter.h b/src/probabilistic/CardinalityCounter.h index 2707c53808..a2aeea50eb 100644 --- a/src/probabilistic/CardinalityCounter.h +++ b/src/probabilistic/CardinalityCounter.h @@ -9,81 +9,78 @@ namespace probabilistic { /** - * A probabilisitc cardinality counter using the HyperLogLog algorithm. - * - * TODO: Update doc string. + * A probabilistic cardinality counter using the HyperLogLog algorithm. */ class CardinalityCounter { public: /** * Constructor. * - * Based on the error_margin, the number of buckets that need to be - * kept will be determined. Based on the max_size, the number of bits - * that will be used from the hash function will be determined. + * The number of buckets of the data structure is determined using + * the error margin and the given confidence. * - * We need the hash function to return integers that are uniformly - * distributed from 0 to 2^L-1. And if that happens, the maximum - * cardinality that this counter can handle is approximately 2^L. By - * default, we will assume a value of 64 bits. + * For example, assume an error_margin of 2% and a confidence + * of 95%. If the Size function returns an estimate of 100, this + * means that we are 95% sure that the cardinality is between 98 + * and 102. * - * Confidence in the estimate given by a cardinality counter is. + * @param error_margin error margin * - * In other words, if the cardinality is estimated to be 100 with 2% - * error margin and HLL_CONFis 0.95, then we are 95% sure that the - * actual cardinality is between 98 and 102. + * @param confidence confidence of the error. Default: 0.95 */ CardinalityCounter(double error_margin, double confidence = 0.95); /** - * Constructor used for cloning. + * Copy-Constructor + */ + CardinalityCounter(CardinalityCounter& other); + + /** + * Constructor for a known number of buckets. * - * The error margin will be 1.04/sqrt(m) with approximately 68% + * The error margin is 1.04/sqrt(size) with approximately 68% * probability. + * + * @param size number of buckets to create */ CardinalityCounter(uint64 size); /** - * Deletes the class variables. + * Destructor. */ ~CardinalityCounter(); /** - * This will add an element to the counter. It's responsible for - * adding an element and updating the value of V, if that applies. + * Add a new element to the counter. + * + * The hash function generating the hashes needs to be uniformly + * distributed over 64 bits. + * + * @param hash 64-bit hash value of the element to be added */ void AddElement(uint64 hash); /** - * Returns the size estimate of the set. First, it has the "raw" - * HyperLogLog estimate. And then, we check if it's too "large" or - * "small" because the raw estimate doesn't do well in those cases. - * Thus, we correct for those errors as specified in the paper. - */ - double Size(); - - /** - * Returns the buckets array that holds all of the rough cardinality - * estimates. - */ - uint8_t* GetBuckets(); + * Get the current estimated number of elements in the data + * structure + * + * @return Estimated number of elements + **/ + double Size() const; /** * Merges the argument cardinality counter with this one. The error - * margins are assumed to be the same, so they have the same number of - * buckets. If any of the conditions are violated, then the return - * value of size() is meaningless. + * margins of both counters have to be the same, otherwhise the merge + * operation will not be carried out. + * + * @param c Cardinality counter to merge into the current counter. + * + * @return True if successful */ - void Merge(CardinalityCounter* c); + bool Merge(CardinalityCounter* c); /** - * Returns the value of m. Should be used only for statistical - * purposes. - */ - uint64 GetM(); - - /** -c * Serializes the cardinality counter. + * Serializes the cardinality counter. * * @param info The serializaton information to use. * @@ -97,10 +94,28 @@ c * Serializes the cardinality counter. * @param info The serializaton information to use. * * @return The unserialized cardinality counter, or null if an error - * occured. + * occured. */ static CardinalityCounter* Unserialize(UnserialInfo* info); +protected: + /** + * Return the number of buckets. + * + * @return Number of buckets + */ + uint64 GetM() const; + + /** + * Returns the buckets array that holds all of the rough cardinality + * estimates. + * + * Use GetM() to determine the size. + * + * @return Array containing cardinality estimates + */ + uint8_t* GetBuckets(); + private: /** * Constructor used when unserializing, i.e., all parameters are @@ -110,31 +125,38 @@ private: /** * Helper function with code used jointly by multiple constructors. + * + * @param arg_size: number of buckets that need to be kept */ void Init(uint64 arg_size); /** - * This function will calculate the smallest value of b that will + * This function calculates the smallest value of b that will * satisfy these the constraints of a specified error margin and * confidence level. * * The exact expression for b is as follows: - * Define x = 2*(log(1.04*k/error)/log(2)). Then b is the ceiling of x + * Define x = 2*(log(1.04*k/error)/log(2)). Then b is the ceiling of x. * - * error is the error margin. + * After that initial estimate, the value of b is increased until the + * standard deviation falls within the specified valud. * - * k is the number of standard deviations that we have to go to have - * a confidence level of conf. + * @param error error margin * - * confidence: TODO. + * @param confidence confidence of the error + * + * @return minimal B-value satisfying the error-rate under confidence. */ int OptimalB(double error, double confidence); /** - * Computes when the first one appears in the element. It looks at the - * bitstring from the end though. A precondition is that the argument - * is already divisible by m, so we just ignore the last b bits, since - * m = 2^b and the last b bits will always be 0. + * Determines at which index (counted from the back) the first one-bit + * appears. The last b bits have to be 0 (the element has to be divisible + * by m), hence they are ignored. + * + * @param hash_modified hash value + * + * @returns index of first one-bit */ uint8_t Rank(uint64 hash_modified); diff --git a/src/probabilistic/cardinality-counter.bif b/src/probabilistic/cardinality-counter.bif index 5201ce95bb..46323bc212 100644 --- a/src/probabilistic/cardinality-counter.bif +++ b/src/probabilistic/cardinality-counter.bif @@ -91,7 +91,12 @@ function hll_cardinality_merge_into%(handle1: opaque of cardinality, handle2: op CardinalityCounter* h1 = v1->Get(); CardinalityCounter* h2 = v2->Get(); - h1->Merge(h2); + bool res = h1->Merge(h2); + if ( res == false ) + { + reporter->Error("Carinality counters with different parameters cannot be merged"); + return new Val(0, TYPE_BOOL); + } return new Val(1, TYPE_BOOL); %} @@ -126,12 +131,7 @@ function hll_cardinality_copy%(handle: opaque of cardinality%): opaque of cardin %{ CardinalityVal* cv = static_cast(handle); CardinalityCounter* h = cv->Get(); - - uint64_t m = h->GetM(); - CardinalityCounter* h2 = new CardinalityCounter(m); - - int i = 0; - h2->Merge(h); + CardinalityCounter* h2 = new CardinalityCounter(*h); CardinalityVal* out = new CardinalityVal(h2); return out; From ecc20b932a3697452208ed8ec1ebaa59ac3f7061 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 16 Sep 2013 11:00:54 -0700 Subject: [PATCH 323/881] and const 2 more functions --- src/probabilistic/CardinalityCounter.cc | 4 ++-- src/probabilistic/CardinalityCounter.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/probabilistic/CardinalityCounter.cc b/src/probabilistic/CardinalityCounter.cc index 3e274da886..ed9f4ae078 100644 --- a/src/probabilistic/CardinalityCounter.cc +++ b/src/probabilistic/CardinalityCounter.cc @@ -10,7 +10,7 @@ using namespace probabilistic; -int CardinalityCounter::OptimalB(double error, double confidence) +int CardinalityCounter::OptimalB(double error, double confidence) const { double initial_estimate = 2 * (log(1.04) - log(error)) / log(2); int answer = (int) floor(initial_estimate); @@ -87,7 +87,7 @@ CardinalityCounter::~CardinalityCounter() delete [] buckets; } -uint8_t CardinalityCounter::Rank(uint64 hash_modified) +uint8_t CardinalityCounter::Rank(uint64 hash_modified) const { uint8_t answer = 0; diff --git a/src/probabilistic/CardinalityCounter.h b/src/probabilistic/CardinalityCounter.h index a2aeea50eb..1d1e581d5d 100644 --- a/src/probabilistic/CardinalityCounter.h +++ b/src/probabilistic/CardinalityCounter.h @@ -147,7 +147,7 @@ private: * * @return minimal B-value satisfying the error-rate under confidence. */ - int OptimalB(double error, double confidence); + int OptimalB(double error, double confidence) const; /** * Determines at which index (counted from the back) the first one-bit @@ -158,7 +158,7 @@ private: * * @returns index of first one-bit */ - uint8_t Rank(uint64 hash_modified); + uint8_t Rank(uint64 hash_modified) const; /** * This is the number of buckets that will be stored. The standard From c8758c4f246b88804cb92d2b79f42624e4343ba4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 16 Sep 2013 15:36:18 -0500 Subject: [PATCH 324/881] Fix possible (unlikely) use of uninitialized value. Plus two minor refactors/nits. --- src/Func.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Func.cc b/src/Func.cc index 7859e8d2ad..11749a8a9c 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -281,7 +281,7 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const #ifdef PROFILE_BRO_FUNCTIONS DEBUG_MSG("Function: %s\n", id->Name()); #endif - if ( ! bodies.size() ) + if ( bodies.empty() ) { // Can only happen for events and hooks. assert(Flavor() == FUNC_FLAVOR_EVENT || Flavor() == FUNC_FLAVOR_HOOK); @@ -315,14 +315,14 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const loop_over_list(*args, i) f->SetElement(i, (*args)[i]); - stmt_flow_type flow; + stmt_flow_type flow = FLOW_NEXT; Val* result = 0; if ( sample_logger ) sample_logger->FunctionSeen(this); - for ( unsigned int i = 0; i < bodies.size(); ++i ) + for ( size_t i = 0; i < bodies.size(); ++i ) { if ( sample_logger ) sample_logger->LocationSeen( From 19b15217f0a1b248c96ebe14684255c4774e54fd Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 16 Sep 2013 15:40:44 -0500 Subject: [PATCH 325/881] Minor refactor to broxygen enum comments. Coverity claimed a mismatched iterator here. Don't think it was, but this might make it either go away or make its insane template output understandable. Else at least it makes the code more readable. --- src/Type.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Type.cc b/src/Type.cc index d7236e0344..2b9faa8018 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1403,8 +1403,8 @@ void CommentedEnumType::AddComment(const string& module_name, const char* name, comments[copy_string(fullname.c_str())] = new_comments; else { - comments[fullname.c_str()]->splice(comments[fullname.c_str()]->end(), - *new_comments); + list* prev_comments = comments[fullname.c_str()]; + prev_comments->splice(prev_comments->end(), *new_comments); delete new_comments; } } From e5a589dbfe5fc4392543ac3ee1e1fb1da74380d5 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Mon, 16 Sep 2013 09:14:36 -0700 Subject: [PATCH 326/881] Very basic file-analyzer for x509 certificates. Mostly ripped from the ssl-analyzer and the topic/bernhard/x509 branch. Simply prints information about the encountered certificates (I have not yet my mind up, what I will log...). Next step: extensions... --- scripts/base/files/x509/__load__.bro | 1 + scripts/base/files/x509/main.bro | 14 + scripts/base/init-bare.bro | 20 ++ scripts/base/init-default.bro | 2 +- scripts/base/protocols/ssl/__load__.bro | 1 + scripts/base/protocols/ssl/files.bro | 48 +++ src/analyzer/protocol/ssl/ssl-analyzer.pac | 8 + src/file_analysis/analyzer/CMakeLists.txt | 1 + .../analyzer/x509/CMakeLists.txt | 10 + src/file_analysis/analyzer/x509/Plugin.cc | 10 + src/file_analysis/analyzer/x509/X509.cc | 295 ++++++++++++++++++ src/file_analysis/analyzer/x509/X509.h | 38 +++ src/file_analysis/analyzer/x509/events.bif | 1 + src/file_analysis/analyzer/x509/types.bif | 1 + 14 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 scripts/base/files/x509/__load__.bro create mode 100644 scripts/base/files/x509/main.bro create mode 100644 scripts/base/protocols/ssl/files.bro create mode 100644 src/file_analysis/analyzer/x509/CMakeLists.txt create mode 100644 src/file_analysis/analyzer/x509/Plugin.cc create mode 100644 src/file_analysis/analyzer/x509/X509.cc create mode 100644 src/file_analysis/analyzer/x509/X509.h create mode 100644 src/file_analysis/analyzer/x509/events.bif create mode 100644 src/file_analysis/analyzer/x509/types.bif diff --git a/scripts/base/files/x509/__load__.bro b/scripts/base/files/x509/__load__.bro new file mode 100644 index 0000000000..a10fe855df --- /dev/null +++ b/scripts/base/files/x509/__load__.bro @@ -0,0 +1 @@ +@load ./main diff --git a/scripts/base/files/x509/main.bro b/scripts/base/files/x509/main.bro new file mode 100644 index 0000000000..205b8fbd25 --- /dev/null +++ b/scripts/base/files/x509/main.bro @@ -0,0 +1,14 @@ + +@load base/frameworks/files + +module X509; + +export { + redef enum Log::ID += { LOG }; +} + +event x509_cert(f: fa_file, cert: X509::Certificate) + { + print cert; + } + diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index fe3b84a93b..5d7914dc6b 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -2721,6 +2721,26 @@ export { }; } +module X509; +export { + type X509::Certificate: record { + version: count; ##< Version number. + serial: string; ##< Serial number. + subject: string; ##< Subject. + issuer: string; ##< Issuer. + not_valid_before: time; ##< Timestamp before when certificate is not valid. + not_valid_after: time; ##< Timestamp after when certificate is not valid. + key_alg: string; ##< name of the key algorithm + sig_alg: string; ##< name of the signature algorithm + key_type: string &optional; ##< key-type, if key parseable by openssl (either rsa, dsa or ec) + key_length: count &optional; ##< key-length in bits + exponent: string &optional; ##< exponent, if RSA-certificate + curve: string &optional; ##< curve, if EC-certificate + ca: bool &optional; ##< indicates the CA value in the X509v3 BasicConstraints extension + path_len: count &optional; ##< indicates the path_length value in the X509v3 BasicConstraints extension + }; +} + module SOCKS; export { ## This record is for a SOCKS client or server to provide either a diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 202f8eaaab..c0fb29f081 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -57,6 +57,6 @@ @load base/files/hash @load base/files/extract @load base/files/unified2 - +@load base/files/x509 @load base/misc/find-checksum-offloading diff --git a/scripts/base/protocols/ssl/__load__.bro b/scripts/base/protocols/ssl/__load__.bro index 5a8590f234..42287fb039 100644 --- a/scripts/base/protocols/ssl/__load__.bro +++ b/scripts/base/protocols/ssl/__load__.bro @@ -1,5 +1,6 @@ @load ./consts @load ./main @load ./mozilla-ca-list +@load ./files @load-sigs ./dpd.sig diff --git a/scripts/base/protocols/ssl/files.bro b/scripts/base/protocols/ssl/files.bro new file mode 100644 index 0000000000..7582a428ae --- /dev/null +++ b/scripts/base/protocols/ssl/files.bro @@ -0,0 +1,48 @@ +@load ./main +@load base/utils/conn-ids +@load base/frameworks/files + +module SSL; + +export { + redef record Info += { + ## An ordered vector of file unique IDs which contains + ## all the certificates sent over the connection + fuids: vector of string &log &default=string_vec(); + }; + + ## Default file handle provider for SSL. + global get_file_handle: function(c: connection, is_orig: bool): string; + + ## Default file describer for SSL. + global describe_file: function(f: fa_file): string; +} + +function get_file_handle(c: connection, is_orig: bool): string + { + return cat(Analyzer::ANALYZER_SMTP, c$start_time); + } + +function describe_file(f: fa_file): string + { + # This shouldn't be needed, but just in case... + if ( f$source != "SSL" ) + return ""; + + return ""; + } + +event bro_init() &priority=5 + { + Files::register_protocol(Analyzer::ANALYZER_SSL, + [$get_file_handle = SSL::get_file_handle, + $describe = SSL::describe_file]); + } + +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 + { + if ( c?$ssl ) + c$ssl$fuids[|c$ssl$fuids|] = f$id; + + Files::add_analyzer(f, Files::ANALYZER_X509); + } diff --git a/src/analyzer/protocol/ssl/ssl-analyzer.pac b/src/analyzer/protocol/ssl/ssl-analyzer.pac index 3d9564eaab..4cd7599ef7 100644 --- a/src/analyzer/protocol/ssl/ssl-analyzer.pac +++ b/src/analyzer/protocol/ssl/ssl-analyzer.pac @@ -10,6 +10,8 @@ #include #include + +#include "file_analysis/Manager.h" %} @@ -253,6 +255,11 @@ refine connection SSL_Conn += { { const bytestring& cert = (*certificates)[i]; const uint8* data = cert.data(); + + file_mgr->DataIn(reinterpret_cast(data), cert.length(), + bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn(), false); + file_mgr->EndOfFile(bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn()); + X509* pTemp = d2i_X509_binpac(NULL, &data, cert.length()); if ( ! pTemp ) { @@ -261,6 +268,7 @@ refine connection SSL_Conn += { return false; } + RecordVal* pX509Cert = new RecordVal(x509_type); char tmp[256]; BIO *bio = BIO_new(BIO_s_mem()); diff --git a/src/file_analysis/analyzer/CMakeLists.txt b/src/file_analysis/analyzer/CMakeLists.txt index 1e19b7bd11..ede63dbd1b 100644 --- a/src/file_analysis/analyzer/CMakeLists.txt +++ b/src/file_analysis/analyzer/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(data_event) add_subdirectory(extract) add_subdirectory(hash) add_subdirectory(unified2) +add_subdirectory(x509) diff --git a/src/file_analysis/analyzer/x509/CMakeLists.txt b/src/file_analysis/analyzer/x509/CMakeLists.txt new file mode 100644 index 0000000000..759a01b55c --- /dev/null +++ b/src/file_analysis/analyzer/x509/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro X509) +bro_plugin_cc(X509.cc Plugin.cc ../../Analyzer.cc) +bro_plugin_bif(events.bif types.bif) +bro_plugin_end() diff --git a/src/file_analysis/analyzer/x509/Plugin.cc b/src/file_analysis/analyzer/x509/Plugin.cc new file mode 100644 index 0000000000..1e76e3fdb7 --- /dev/null +++ b/src/file_analysis/analyzer/x509/Plugin.cc @@ -0,0 +1,10 @@ +#include "plugin/Plugin.h" + +#include "X509.h" + +BRO_PLUGIN_BEGIN(Bro, X509) + BRO_PLUGIN_DESCRIPTION("Parse X509 Certificate"); + BRO_PLUGIN_FILE_ANALYZER("X509", X509); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(types); +BRO_PLUGIN_END diff --git a/src/file_analysis/analyzer/x509/X509.cc b/src/file_analysis/analyzer/x509/X509.cc new file mode 100644 index 0000000000..78d746ac9b --- /dev/null +++ b/src/file_analysis/analyzer/x509/X509.cc @@ -0,0 +1,295 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include + +#include "X509.h" +#include "Event.h" + +#include "events.bif.h" +#include "types.bif.h" + +#include "file_analysis/Manager.h" + +#include +#include +#include +#include + +using namespace file_analysis; + +file_analysis::X509::X509(RecordVal* args, file_analysis::File* file) + : file_analysis::Analyzer(file_mgr->GetComponentTag("X509"), args, file) + { + cert_data.clear(); + } + +bool file_analysis::X509::DeliverStream(const u_char* data, uint64 len) + { + // just add it to the data we have so far, since we cannot do anything else anyways... + cert_data.append(reinterpret_cast(data), len); + return true; + } + +bool file_analysis::X509::Undelivered(uint64 offset, uint64 len) + { + return false; + } + +bool file_analysis::X509::EndOfFile() + { + // ok, now we can try to parse the certificate with openssl. Should + // be rather straightforward... + const unsigned char* cert_char = reinterpret_cast(cert_data.data()); + ::X509* ssl_cert = d2i_X509(NULL, &cert_char, cert_data.size()); + if ( !ssl_cert ) + { + reporter->Error("Could not parse X509 certificate"); + return false; + } + + char buf[256]; // we need a buffer for some of the openssl functions + memset(buf, 0, 256); + + RecordVal* pX509Cert = new RecordVal(BifType::Record::X509::Certificate); + BIO *bio = BIO_new(BIO_s_mem()); + + pX509Cert->Assign(0, new Val((uint64) X509_get_version(ssl_cert), TYPE_COUNT)); + i2a_ASN1_INTEGER(bio, X509_get_serialNumber(ssl_cert)); + int len = BIO_read(bio, &(*buf), sizeof buf); + pX509Cert->Assign(1, new StringVal(len, buf)); + + X509_NAME_print_ex(bio, X509_get_subject_name(ssl_cert), 0, XN_FLAG_RFC2253); + len = BIO_gets(bio, &(*buf), sizeof buf); + pX509Cert->Assign(2, new StringVal(len, buf)); + X509_NAME_print_ex(bio, X509_get_issuer_name(ssl_cert), 0, XN_FLAG_RFC2253); + len = BIO_gets(bio, &(*buf), sizeof buf); + pX509Cert->Assign(3, new StringVal(len, buf)); + BIO_free(bio); + + pX509Cert->Assign(4, new Val(get_time_from_asn1(X509_get_notBefore(ssl_cert)), TYPE_TIME)); + pX509Cert->Assign(5, new Val(get_time_from_asn1(X509_get_notAfter(ssl_cert)), TYPE_TIME)); + + // we only read 255 bytes because byte 256 is always 0. + // if the string is longer than 255, that will be our null-termination, + // otherwhise i2t does null-terminate. + if ( ! i2t_ASN1_OBJECT(buf, 255, ssl_cert->cert_info->key->algor->algorithm) ) + buf[0] = 0; + pX509Cert->Assign(6, new StringVal(buf)); + + if ( ! i2t_ASN1_OBJECT(buf, 255, ssl_cert->sig_alg->algorithm) ) + buf[0] = 0; + pX509Cert->Assign(7, new StringVal(buf)); + + // Things we can do when we have the key... + EVP_PKEY *pkey = X509_extract_key(ssl_cert); + if ( pkey != NULL ) + { + if ( pkey->type == EVP_PKEY_DSA ) + { + pX509Cert->Assign(8, new StringVal("dsa")); + } + else if ( pkey->type == EVP_PKEY_RSA ) + { + pX509Cert->Assign(8, new StringVal("rsa")); + char *exponent = BN_bn2dec(pkey->pkey.rsa->e); + if ( exponent != NULL ) + { + pX509Cert->Assign(10, new StringVal(exponent)); + OPENSSL_free(exponent); + exponent = NULL; + } + } +#ifndef OPENSSL_NO_EC + else if ( pkey->type == EVP_PKEY_EC ) + { + pX509Cert->Assign(8, new StringVal("dsa")); + pX509Cert->Assign(11, key_curve(pkey)); + } +#endif + + unsigned int length = key_length(pkey); + if ( length > 0 ) + pX509Cert->Assign(9, new Val(length, TYPE_COUNT)); + } + + val_list* vl = new val_list(); + vl->append(GetFile()->GetVal()->Ref()); + vl->append(pX509Cert); + + mgr.QueueEvent(x509_cert, vl); + + return false; + } + +StringVal* file_analysis::X509::key_curve(EVP_PKEY *key) + { + assert(key != NULL); + +#ifdef OPENSSL_NO_EC + // well, we do not have EC-Support... + return NULL; +#else + if ( key->type != EVP_PKEY_EC ) { + // no EC-key - no curve name + return NULL; + } + + const EC_GROUP *group; + int nid; + if ( (group = EC_KEY_get0_group(key->pkey.ec)) == NULL) + // I guess we could not parse this + return NULL; + + nid = EC_GROUP_get_curve_name(group); + if ( nid == 0 ) + // and an invalid nid... + return NULL; + + const char * curve_name = OBJ_nid2sn(nid); + if ( curve_name == NULL ) + return NULL; + + return new StringVal(curve_name); +#endif + } + +unsigned int file_analysis::X509::key_length(EVP_PKEY *key) + { + assert(key != NULL); + unsigned int length; + + switch(key->type) { + case EVP_PKEY_RSA: + length = BN_num_bits(key->pkey.rsa->n); + break; + case EVP_PKEY_DSA: + length = BN_num_bits(key->pkey.dsa->p); + break; +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + { + const EC_GROUP *group; + BIGNUM* ec_order; + ec_order = BN_new(); + if ( !ec_order ) + // could not malloc bignum? + return 0; + + if ( (group = EC_KEY_get0_group(key->pkey.ec)) == NULL) + // unknown ex-group + return 0; + + if (!EC_GROUP_get_order(group, ec_order, NULL)) + // could not get ec-group-order + return 0; + + length = BN_num_bits(ec_order); + BN_free(ec_order); + break; + } +#endif + default: + return 0; // unknown public key type + } + + return length; + } + +double file_analysis::X509::get_time_from_asn1(const ASN1_TIME * atime) + { + time_t lResult = 0; + + char lBuffer[24]; + char * pBuffer = lBuffer; + + size_t lTimeLength = atime->length; + char * pString = (char *) atime->data; + + if ( atime->type == V_ASN1_UTCTIME ) + { + if ( lTimeLength < 11 || lTimeLength > 17 ) + return 0; + + memcpy(pBuffer, pString, 10); + pBuffer += 10; + pString += 10; + } + else + { + if ( lTimeLength < 13 ) + return 0; + + memcpy(pBuffer, pString, 12); + pBuffer += 12; + pString += 12; + } + + if ((*pString == 'Z') || (*pString == '-') || (*pString == '+')) + { + *(pBuffer++) = '0'; + *(pBuffer++) = '0'; + } + else + { + *(pBuffer++) = *(pString++); + *(pBuffer++) = *(pString++); + + // Skip any fractional seconds... + if (*pString == '.') + { + pString++; + while ((*pString >= '0') && (*pString <= '9')) + pString++; + } + } + + *(pBuffer++) = 'Z'; + *(pBuffer++) = '\0'; + + time_t lSecondsFromUTC; + + if ( *pString == 'Z' ) + lSecondsFromUTC = 0; + + else + { + if ((*pString != '+') && (pString[5] != '-')) + return 0; + + lSecondsFromUTC = ((pString[1]-'0') * 10 + (pString[2]-'0')) * 60; + lSecondsFromUTC += (pString[3]-'0') * 10 + (pString[4]-'0'); + + if (*pString == '-') + lSecondsFromUTC = -lSecondsFromUTC; + } + + tm lTime; + lTime.tm_sec = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0'); + lTime.tm_min = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0'); + lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0'); + lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0'); + lTime.tm_mon = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1; + lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0'); + + if ( lTime.tm_year < 50 ) + lTime.tm_year += 100; // RFC 2459 + + lTime.tm_wday = 0; + lTime.tm_yday = 0; + lTime.tm_isdst = 0; // No DST adjustment requested + + lResult = mktime(&lTime); + + if ( lResult ) + { + if ( 0 != lTime.tm_isdst ) + lResult -= 3600; // mktime may adjust for DST (OS dependent) + + lResult += lSecondsFromUTC; + } + else + lResult = 0; + + return lResult; +} + diff --git a/src/file_analysis/analyzer/x509/X509.h b/src/file_analysis/analyzer/x509/X509.h new file mode 100644 index 0000000000..ce74190b69 --- /dev/null +++ b/src/file_analysis/analyzer/x509/X509.h @@ -0,0 +1,38 @@ +#ifndef FILE_ANALYSIS_X509_H +#define FILE_ANALYSIS_X509_H + +#include + +#include "Val.h" +#include "../File.h" +#include "Analyzer.h" + +#include + +namespace file_analysis { + +class X509 : public file_analysis::Analyzer { +public: + //~X509(); + + static file_analysis::Analyzer* Instantiate(RecordVal* args, File* file) + { return new X509(args, file); } + + virtual bool DeliverStream(const u_char* data, uint64 len); + virtual bool Undelivered(uint64 offset, uint64 len); + virtual bool EndOfFile(); + +protected: + X509(RecordVal* args, File* file); + +private: + static double get_time_from_asn1(const ASN1_TIME * atime); + static StringVal* key_curve(EVP_PKEY *key); + static unsigned int key_length(EVP_PKEY *key); + + std::string cert_data; +}; + +} + +#endif diff --git a/src/file_analysis/analyzer/x509/events.bif b/src/file_analysis/analyzer/x509/events.bif new file mode 100644 index 0000000000..3c3049559d --- /dev/null +++ b/src/file_analysis/analyzer/x509/events.bif @@ -0,0 +1 @@ +event x509_cert%(f: fa_file, cert: X509::Certificate%); diff --git a/src/file_analysis/analyzer/x509/types.bif b/src/file_analysis/analyzer/x509/types.bif new file mode 100644 index 0000000000..9e4fd48420 --- /dev/null +++ b/src/file_analysis/analyzer/x509/types.bif @@ -0,0 +1 @@ +type X509::Certificate: record; From bb8f102b2cb16f0c656bc50ed4a63fee72cf1216 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 16 Sep 2013 16:10:49 -0500 Subject: [PATCH 327/881] Minor refactor to SSL BinPAC grammer. An unsized array already parses indefinitely. &until($element <= 0) just causes nonsense code to be generated. I.e. checking a pointer that can never even be null against <= 0. And the compare would happen after delete'ing the pointer, making it even odder (though still benign). --- src/analyzer/protocol/ssl/ssl-protocol.pac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyzer/protocol/ssl/ssl-protocol.pac b/src/analyzer/protocol/ssl/ssl-protocol.pac index b35d07f18b..41f5994072 100644 --- a/src/analyzer/protocol/ssl/ssl-protocol.pac +++ b/src/analyzer/protocol/ssl/ssl-protocol.pac @@ -667,7 +667,7 @@ type CiphertextRecord(rec: SSLRecord) = record { ###################################################################### type SSLPDU(is_orig: bool) = record { - records : SSLRecord(is_orig)[] &transient &until($element <= 0); + records : SSLRecord(is_orig)[] &transient; } &byteorder = bigendian; From a3b963ad4ee1e10ab79018c025ca7b4d1468faee Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 16 Sep 2013 16:14:01 -0500 Subject: [PATCH 328/881] Refactor Analyzer::AddChildAnalyzer and usages. Make feedback available regarding whether adding a child analyzer fails because one of the same type already exists (so one can avoid invalid pointer access of a delete'd analyzer). --- src/analyzer/Analyzer.cc | 11 +++++------ src/analyzer/Analyzer.h | 9 ++++++--- src/analyzer/protocol/gnutella/Gnutella.cc | 4 +--- src/analyzer/protocol/socks/SOCKS.cc | 10 +++++++--- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/analyzer/Analyzer.cc b/src/analyzer/Analyzer.cc index b8b739f3cb..7a71c2e0d4 100644 --- a/src/analyzer/Analyzer.cc +++ b/src/analyzer/Analyzer.cc @@ -378,13 +378,13 @@ void Analyzer::ForwardEndOfData(bool orig) AppendNewChildren(); } -void Analyzer::AddChildAnalyzer(Analyzer* analyzer, bool init) +bool Analyzer::AddChildAnalyzer(Analyzer* analyzer, bool init) { if ( HasChildAnalyzer(analyzer->GetAnalyzerTag()) ) { analyzer->Done(); delete analyzer; - return; + return false; } // We add new children to new_children first. They are then @@ -401,6 +401,7 @@ void Analyzer::AddChildAnalyzer(Analyzer* analyzer, bool init) DBG_LOG(DBG_ANALYZER, "%s added child %s", fmt_analyzer(this).c_str(), fmt_analyzer(analyzer).c_str()); + return true; } Analyzer* Analyzer::AddChildAnalyzer(Tag analyzer) @@ -409,10 +410,8 @@ Analyzer* Analyzer::AddChildAnalyzer(Tag analyzer) { Analyzer* a = analyzer_mgr->InstantiateAnalyzer(analyzer, conn); - if ( a ) - AddChildAnalyzer(a); - - return a; + if ( a && AddChildAnalyzer(a) ) + return a; } return 0; diff --git a/src/analyzer/Analyzer.h b/src/analyzer/Analyzer.h index 396d45d60e..b709e3dda0 100644 --- a/src/analyzer/Analyzer.h +++ b/src/analyzer/Analyzer.h @@ -353,9 +353,10 @@ public: * discarded. * * @param analyzer The ananlyzer to add. Takes ownership. + * @return false if analyzer type was already a child, else true. */ - void AddChildAnalyzer(Analyzer* analyzer) - { AddChildAnalyzer(analyzer, true); } + bool AddChildAnalyzer(Analyzer* analyzer) + { return AddChildAnalyzer(analyzer, true); } /** * Adds a new child analyzer to the analyzer tree. If an analyzer of @@ -363,6 +364,7 @@ public: * discarded. * * @param tag The type of analyzer to add. + * @return the new analyzer instance that was added. */ Analyzer* AddChildAnalyzer(Tag tag); @@ -600,8 +602,9 @@ protected: * @param analyzer The analyzer to add. Takes ownership. * * @param init If true, Init() will be calle.d + * @return false if analyzer type was already a child, else true. */ - void AddChildAnalyzer(Analyzer* analyzer, bool init); + bool AddChildAnalyzer(Analyzer* analyzer, bool init); /** * Inits all child analyzers. This is an internal method. diff --git a/src/analyzer/protocol/gnutella/Gnutella.cc b/src/analyzer/protocol/gnutella/Gnutella.cc index ff71a55fc8..84a33381a0 100644 --- a/src/analyzer/protocol/gnutella/Gnutella.cc +++ b/src/analyzer/protocol/gnutella/Gnutella.cc @@ -137,10 +137,8 @@ int Gnutella_Analyzer::IsHTTP(string header) analyzer::Analyzer* a = analyzer_mgr->InstantiateAnalyzer("HTTP", Conn()); - if ( a ) + if ( a && Parent()->AddChildAnalyzer(a) ) { - Parent()->AddChildAnalyzer(a); - if ( Parent()->IsAnalyzer("TCP") ) { // Replay buffered data. diff --git a/src/analyzer/protocol/socks/SOCKS.cc b/src/analyzer/protocol/socks/SOCKS.cc index f9d81b8a16..76212d822b 100644 --- a/src/analyzer/protocol/socks/SOCKS.cc +++ b/src/analyzer/protocol/socks/SOCKS.cc @@ -62,9 +62,13 @@ void SOCKS_Analyzer::DeliverStream(int len, const u_char* data, bool orig) if ( ! pia ) { pia = new pia::PIA_TCP(Conn()); - AddChildAnalyzer(pia); - pia->FirstPacket(true, 0); - pia->FirstPacket(false, 0); + if ( AddChildAnalyzer(pia) ) + { + pia->FirstPacket(true, 0); + pia->FirstPacket(false, 0); + } + else + pia = 0; } ForwardStream(len, data, orig); From fdc364084ba515749704b3542c764a6e37cc1bfb Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Mon, 16 Sep 2013 17:45:21 -0500 Subject: [PATCH 329/881] Fix cmake warning about ENABLE_PERFTOOLS not being used --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f64f304b8..1c427188ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,9 +153,10 @@ if (NOT DISABLE_ELASTICSEARCH AND LIBCURL_FOUND) list(APPEND OPTLIBS ${LibCURL_LIBRARIES}) endif() -if (ENABLE_PERFTOOLS_DEBUG) +if (ENABLE_PERFTOOLS_DEBUG OR ENABLE_PERFTOOLS) # Just a no op to prevent CMake from complaining about manually-specified - # ENABLE_PERFTOOLS_DEBUG not being used if google perftools weren't found + # ENABLE_PERFTOOLS_DEBUG or ENABLE_PERFTOOLS not being used if google + # perftools weren't found endif () set(brodeps From fdc0d5c7ec14ee45207bf9b94e7ecd6426769050 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Tue, 17 Sep 2013 15:29:41 -0500 Subject: [PATCH 330/881] Fix compiler warning (time_t is not a pointer type) --- src/bro.bif | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bro.bif b/src/bro.bif index c9b77e4368..93b0da2dcc 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -2945,7 +2945,7 @@ function strftime%(fmt: string, d: time%) : string ## Returns: The time value calculated from parsing *d* with *fmt*. function strptime%(fmt: string, d: string%) : time %{ - const time_t timeval = time_t(NULL); + const time_t timeval = time_t(); struct tm t = *localtime(&timeval); if ( strptime(d->CheckString(), fmt->CheckString(), &t) == NULL ) From a316878d01adec45049c5a65af92ccc71f24e695 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 17 Sep 2013 16:42:48 -0500 Subject: [PATCH 331/881] Add checks to avoid improper negative values use. --- src/Expr.cc | 14 +++++++-- src/Val.cc | 10 +++++++ src/Val.h | 11 +++++++ src/analyzer/protocol/conn-size/ConnSize.cc | 14 +++++---- src/analyzer/protocol/icmp/ICMP.cc | 6 ++-- src/analyzer/protocol/tcp/TCP.cc | 7 ++--- src/analyzer/protocol/udp/UDP.cc | 8 ++--- .../analyzer/data_event/DataEvent.cc | 9 ++---- src/file_analysis/analyzer/extract/Extract.cc | 3 +- src/input/Manager.cc | 30 +++++++++---------- src/logging/Manager.cc | 29 +++++++++--------- src/util.cc | 10 +++++++ 12 files changed, 89 insertions(+), 62 deletions(-) diff --git a/src/Expr.cc b/src/Expr.cc index e64172675e..f060b98602 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3137,12 +3137,14 @@ FieldExpr::FieldExpr(Expr* arg_op, const char* arg_field_name) { RecordType* rt = op->Type()->AsRecordType(); field = rt->FieldOffset(field_name); - td = rt->FieldDecl(field); if ( field < 0 ) ExprError("no such field in record"); else + { SetType(rt->FieldType(field)->Ref()); + td = rt->FieldDecl(field); + } } } @@ -3852,7 +3854,15 @@ void FieldAssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) Val* v = op->Eval(f); if ( v ) - rec->Assign(rt->FieldOffset(field_name.c_str()), v); + { + int idx = rt->FieldOffset(field_name.c_str()); + + if ( idx < 0 ) + reporter->InternalError("Missing record field: %s", + field_name.c_str()); + + rec->Assign(idx, v); + } } int FieldAssignExpr::IsRecordElement(TypeDecl* td) const diff --git a/src/Val.cc b/src/Val.cc index 389e76fe1d..9d1b27b333 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2670,6 +2670,16 @@ Val* RecordVal::LookupWithDefault(int field) const return record_type->FieldDefault(field); } +Val* RecordVal::Lookup(const char* field, bool with_default) const + { + int idx = record_type->FieldOffset(field); + + if ( idx < 0 ) + reporter->InternalError("missing record field: %s", field); + + return with_default ? LookupWithDefault(idx) : Lookup(idx); + } + RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr, bool allow_orphaning) const { if ( ! record_promotion_compatible(t->AsRecordType(), Type()->AsRecordType()) ) diff --git a/src/Val.h b/src/Val.h index 019c390699..a7088313d6 100644 --- a/src/Val.h +++ b/src/Val.h @@ -895,6 +895,17 @@ public: Val* Lookup(int field) const; // Does not Ref() value. Val* LookupWithDefault(int field) const; // Does Ref() value. + /** + * Looks up the value of a field by field name. If the field doesn't + * exist in the record type, it's an internal error: abort. + * @param field name of field to lookup. + * @param with_default whether to rely on field's &default attribute when + * the field has yet to be initialized. + * @return the value in field \a field. It is Ref()'d only if + * \a with_default is true. + */ + Val* Lookup(const char* field, bool with_default = false) const; + void Describe(ODesc* d) const; // This is an experiment to associate a BroObj within the diff --git a/src/analyzer/protocol/conn-size/ConnSize.cc b/src/analyzer/protocol/conn-size/ConnSize.cc index b912fe3d2d..ad08c78c4f 100644 --- a/src/analyzer/protocol/conn-size/ConnSize.cc +++ b/src/analyzer/protocol/conn-size/ConnSize.cc @@ -54,17 +54,19 @@ void ConnSize_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, void ConnSize_Analyzer::UpdateConnVal(RecordVal *conn_val) { // RecordType *connection_type is decleared in NetVar.h - int orig_endp_idx = connection_type->FieldOffset("orig"); - int resp_endp_idx = connection_type->FieldOffset("resp"); - RecordVal *orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - RecordVal *resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); + RecordVal *orig_endp = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp = conn_val->Lookup("resp")->AsRecordVal(); // endpoint is the RecordType from NetVar.h - // TODO: or orig_endp->Type()->AsRecordVal()->FieldOffset() int pktidx = endpoint->FieldOffset("num_pkts"); int bytesidx = endpoint->FieldOffset("num_bytes_ip"); - // TODO: error handling? + if ( pktidx < 0 ) + reporter->InternalError("'endpoint' record missing 'num_pkts' field"); + + if ( bytesidx < 0 ) + reporter->InternalError("'endpoint' record missing 'num_bytes_ip' field"); + orig_endp->Assign(pktidx, new Val(orig_pkts, TYPE_COUNT)); orig_endp->Assign(bytesidx, new Val(orig_bytes, TYPE_COUNT)); resp_endp->Assign(pktidx, new Val(resp_pkts, TYPE_COUNT)); diff --git a/src/analyzer/protocol/icmp/ICMP.cc b/src/analyzer/protocol/icmp/ICMP.cc index 732727d709..a851ebe8ee 100644 --- a/src/analyzer/protocol/icmp/ICMP.cc +++ b/src/analyzer/protocol/icmp/ICMP.cc @@ -440,10 +440,8 @@ void ICMP_Analyzer::Describe(ODesc* d) const void ICMP_Analyzer::UpdateConnVal(RecordVal *conn_val) { - int orig_endp_idx = connection_type->FieldOffset("orig"); - int resp_endp_idx = connection_type->FieldOffset("resp"); - RecordVal *orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - RecordVal *resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); + RecordVal *orig_endp = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp = conn_val->Lookup("resp")->AsRecordVal(); UpdateEndpointVal(orig_endp, 1); UpdateEndpointVal(resp_endp, 0); diff --git a/src/analyzer/protocol/tcp/TCP.cc b/src/analyzer/protocol/tcp/TCP.cc index 8f42e0f2b1..c9cd8ed8d1 100644 --- a/src/analyzer/protocol/tcp/TCP.cc +++ b/src/analyzer/protocol/tcp/TCP.cc @@ -1102,11 +1102,8 @@ void TCP_Analyzer::FlipRoles() void TCP_Analyzer::UpdateConnVal(RecordVal *conn_val) { - int orig_endp_idx = connection_type->FieldOffset("orig"); - int resp_endp_idx = connection_type->FieldOffset("resp"); - - RecordVal *orig_endp_val = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - RecordVal *resp_endp_val = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); + RecordVal *orig_endp_val = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp_val = conn_val->Lookup("resp")->AsRecordVal(); orig_endp_val->Assign(0, new Val(orig->Size(), TYPE_COUNT)); orig_endp_val->Assign(1, new Val(int(orig->state), TYPE_COUNT)); diff --git a/src/analyzer/protocol/udp/UDP.cc b/src/analyzer/protocol/udp/UDP.cc index 3050ea5648..4c26ae5d99 100644 --- a/src/analyzer/protocol/udp/UDP.cc +++ b/src/analyzer/protocol/udp/UDP.cc @@ -170,13 +170,9 @@ void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, void UDP_Analyzer::UpdateConnVal(RecordVal *conn_val) { - int orig_endp_idx = connection_type->FieldOffset("orig"); - int resp_endp_idx = connection_type->FieldOffset("resp"); - RecordVal *orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - RecordVal *resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); + RecordVal *orig_endp = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp = conn_val->Lookup("resp")->AsRecordVal(); - orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); UpdateEndpointVal(orig_endp, 1); UpdateEndpointVal(resp_endp, 0); diff --git a/src/file_analysis/analyzer/data_event/DataEvent.cc b/src/file_analysis/analyzer/data_event/DataEvent.cc index cf2d7e52ec..a9ffa26bf2 100644 --- a/src/file_analysis/analyzer/data_event/DataEvent.cc +++ b/src/file_analysis/analyzer/data_event/DataEvent.cc @@ -20,13 +20,8 @@ DataEvent::DataEvent(RecordVal* args, File* file, file_analysis::Analyzer* DataEvent::Instantiate(RecordVal* args, File* file) { - using BifType::Record::Files::AnalyzerArgs; - - int chunk_off = AnalyzerArgs->FieldOffset("chunk_event"); - int stream_off = AnalyzerArgs->FieldOffset("stream_event"); - - Val* chunk_val = args->Lookup(chunk_off); - Val* stream_val = args->Lookup(stream_off); + Val* chunk_val = args->Lookup("chunk_event"); + Val* stream_val = args->Lookup("stream_event"); if ( ! chunk_val && ! stream_val ) return 0; diff --git a/src/file_analysis/analyzer/extract/Extract.cc b/src/file_analysis/analyzer/extract/Extract.cc index 504ffd9112..1a3917cd0e 100644 --- a/src/file_analysis/analyzer/extract/Extract.cc +++ b/src/file_analysis/analyzer/extract/Extract.cc @@ -33,8 +33,7 @@ Extract::~Extract() static Val* get_extract_field_val(RecordVal* args, const char* name) { - using BifType::Record::Files::AnalyzerArgs; - Val* rval = args->Lookup(AnalyzerArgs->FieldOffset(name)); + Val* rval = args->Lookup(name); if ( ! rval ) reporter->Error("File extraction analyzer missing arg field: %s", name); diff --git a/src/input/Manager.cc b/src/input/Manager.cc index d838e8cb75..d739a96809 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -296,7 +296,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) return false; } - Val* name_val = description->LookupWithDefault(rtype->FieldOffset("name")); + Val* name_val = description->Lookup("name", true); string name = name_val->AsString()->CheckString(); Unref(name_val); @@ -308,10 +308,10 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) return false; } - EnumVal* reader = description->LookupWithDefault(rtype->FieldOffset("reader"))->AsEnumVal(); + EnumVal* reader = description->Lookup("reader", true)->AsEnumVal(); // get the source ... - Val* sourceval = description->LookupWithDefault(rtype->FieldOffset("source")); + Val* sourceval = description->Lookup("source", true); assert ( sourceval != 0 ); const BroString* bsource = sourceval->AsString(); string source((const char*) bsource->Bytes(), bsource->Len()); @@ -321,7 +321,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) rinfo.source = copy_string(source.c_str()); rinfo.name = copy_string(name.c_str()); - EnumVal* mode = description->LookupWithDefault(rtype->FieldOffset("mode"))->AsEnumVal(); + EnumVal* mode = description->Lookup("mode", true)->AsEnumVal(); switch ( mode->InternalInt() ) { case 0: @@ -342,7 +342,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) Unref(mode); - Val* config = description->LookupWithDefault(rtype->FieldOffset("config")); + Val* config = description->Lookup("config", true); info->config = config->AsTableVal(); // ref'd by LookupWithDefault { @@ -401,11 +401,11 @@ bool Manager::CreateEventStream(RecordVal* fval) } - RecordType *fields = fval->LookupWithDefault(rtype->FieldOffset("fields"))->AsType()->AsTypeType()->Type()->AsRecordType(); + RecordType *fields = fval->Lookup("fields", true)->AsType()->AsTypeType()->Type()->AsRecordType(); - Val *want_record = fval->LookupWithDefault(rtype->FieldOffset("want_record")); + Val *want_record = fval->Lookup("want_record", true); - Val* event_val = fval->LookupWithDefault(rtype->FieldOffset("ev")); + Val* event_val = fval->Lookup("ev", true); Func* event = event_val->AsFunc(); Unref(event_val); @@ -547,18 +547,18 @@ bool Manager::CreateTableStream(RecordVal* fval) } } - Val* pred = fval->LookupWithDefault(rtype->FieldOffset("pred")); + Val* pred = fval->Lookup("pred", true); - RecordType *idx = fval->LookupWithDefault(rtype->FieldOffset("idx"))->AsType()->AsTypeType()->Type()->AsRecordType(); + RecordType *idx = fval->Lookup("idx", true)->AsType()->AsTypeType()->Type()->AsRecordType(); RecordType *val = 0; - if ( fval->LookupWithDefault(rtype->FieldOffset("val")) != 0 ) + if ( fval->Lookup("val", true) != 0 ) { - val = fval->LookupWithDefault(rtype->FieldOffset("val"))->AsType()->AsTypeType()->Type()->AsRecordType(); + val = fval->Lookup("val", true)->AsType()->AsTypeType()->Type()->AsRecordType(); Unref(val); // The lookupwithdefault in the if-clause ref'ed val. } - TableVal *dst = fval->LookupWithDefault(rtype->FieldOffset("destination"))->AsTableVal(); + TableVal *dst = fval->Lookup("destination", true)->AsTableVal(); // check if index fields match table description int num = idx->NumFields(); @@ -588,9 +588,9 @@ bool Manager::CreateTableStream(RecordVal* fval) return false; } - Val *want_record = fval->LookupWithDefault(rtype->FieldOffset("want_record")); + Val *want_record = fval->Lookup("want_record", true); - Val* event_val = fval->LookupWithDefault(rtype->FieldOffset("ev")); + Val* event_val = fval->Lookup("ev", true); Func* event = event_val ? event_val->AsFunc() : 0; Unref(event_val); diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 79e23fb63f..87d3be9f13 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -295,7 +295,7 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval) return false; } - RecordType* columns = sval->Lookup(rtype->FieldOffset("columns")) + RecordType* columns = sval->Lookup("columns") ->AsType()->AsTypeType()->Type()->AsRecordType(); bool log_attr_present = false; @@ -322,7 +322,7 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval) return false; } - Val* event_val = sval->Lookup(rtype->FieldOffset("ev")); + Val* event_val = sval->Lookup("ev"); Func* event = event_val ? event_val->AsFunc() : 0; if ( event ) @@ -579,19 +579,18 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval) return false; // Find the right writer type. - int idx = rtype->FieldOffset("writer"); - EnumVal* writer = fval->LookupWithDefault(idx)->AsEnumVal(); + EnumVal* writer = fval->Lookup("writer", true)->AsEnumVal(); // Create a new Filter instance. - Val* name = fval->LookupWithDefault(rtype->FieldOffset("name")); - Val* pred = fval->LookupWithDefault(rtype->FieldOffset("pred")); - Val* path_func = fval->LookupWithDefault(rtype->FieldOffset("path_func")); - Val* log_local = fval->LookupWithDefault(rtype->FieldOffset("log_local")); - Val* log_remote = fval->LookupWithDefault(rtype->FieldOffset("log_remote")); - Val* interv = fval->LookupWithDefault(rtype->FieldOffset("interv")); - Val* postprocessor = fval->LookupWithDefault(rtype->FieldOffset("postprocessor")); - Val* config = fval->LookupWithDefault(rtype->FieldOffset("config")); + Val* name = fval->Lookup("name", true); + Val* pred = fval->Lookup("pred", true); + Val* path_func = fval->Lookup("path_func", true); + Val* log_local = fval->Lookup("log_local", true); + Val* log_remote = fval->Lookup("log_remote", true); + Val* interv = fval->Lookup("interv", true); + Val* postprocessor = fval->Lookup("postprocessor", true); + Val* config = fval->Lookup("config", true); Filter* filter = new Filter; filter->name = name->AsString()->CheckString(); @@ -616,8 +615,8 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval) // Build the list of fields that the filter wants included, including // potentially rolling out fields. - Val* include = fval->Lookup(rtype->FieldOffset("include")); - Val* exclude = fval->Lookup(rtype->FieldOffset("exclude")); + Val* include = fval->Lookup("include"); + Val* exclude = fval->Lookup("exclude"); filter->num_fields = 0; filter->fields = 0; @@ -631,7 +630,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval) } // Get the path for the filter. - Val* path_val = fval->Lookup(rtype->FieldOffset("path")); + Val* path_val = fval->Lookup("path"); if ( path_val ) { diff --git a/src/util.cc b/src/util.cc index f26b3fb0c2..aeb8fdeef8 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1261,6 +1261,16 @@ void _set_processing_status(const char* status) int fd = open(proc_status_file, O_CREAT | O_WRONLY | O_TRUNC, 0700); + if ( fd < 0 ) + { + char buf[256]; + strerror_r(errno, buf, sizeof(buf)); + reporter->Error("Failed to open process status file '%s': %s", + proc_status_file, buf); + errno = old_errno; + return; + } + int len = strlen(status); while ( len ) { From 9d3fc1e7ed5d1972449abcd531ae02fe00290604 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 18 Sep 2013 14:36:59 -0700 Subject: [PATCH 332/881] Updating CHANGES and VERSION. --- CHANGES | 21 +++++++++++++++++++++ VERSION | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 9376f3f459..79041b5368 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,25 @@ +2.1-1344 | 2013-09-16 16:20:55 -0500 + + * Refactor Analyzer::AddChildAnalyzer and usages. (Jon Siwek) + + * Minor refactor to SSL BinPAC grammer. (Jon Siwek) + + * Minor refactor to Broxygen enum comments. (Jon Siwek) + + * Fix possible (unlikely) use of uninitialized value. (Jon Siwek) + + * Fix/improve dereference-before-null-checks. (Jon Siwek) + + * Fix out-of-bounds memory accesses, and remove a + variable-length-array usage. (Jon Siwek) + + * Fix potential mem leak. (Jon Siwek) + + * Fix double-free and deallocator mismatch. (Jon Siwek) + + * Fix another function val reference counting bug. (Jon Siwek) + 2.1-1335 | 2013-09-12 16:13:53 -0500 * Documentation fixes (Daniel Thayer, Jon Siwek) diff --git a/VERSION b/VERSION index c2f9e8bbcc..5a4c59bacf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-1335 +2.1-1344 From d417bd9f3a05d275cbca6685b35a03fc566c7869 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Wed, 18 Sep 2013 23:48:54 -0500 Subject: [PATCH 333/881] Update documentation of required packages --- configure | 2 +- doc/install/install.rst | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 6c557a22d0..1990d78569 100755 --- a/configure +++ b/configure @@ -49,9 +49,9 @@ Usage: $0 [OPTION]... [VAR=VALUE]... --with-flex=PATH path to flex executable --with-bison=PATH path to bison executable --with-perl=PATH path to perl executable + --with-libmagic=PATH path to libmagic install root Optional Packages in Non-Standard Locations: - --with-libmagic=PATH path to libmagic install root --with-geoip=PATH path to the libGeoIP install root --with-perftools=PATH path to Google Perftools install root --with-python=PATH path to Python interpreter diff --git a/doc/install/install.rst b/doc/install/install.rst index 1b775389f3..a29be72472 100644 --- a/doc/install/install.rst +++ b/doc/install/install.rst @@ -29,13 +29,15 @@ before you begin: * Libpcap (http://www.tcpdump.org) * OpenSSL libraries (http://www.openssl.org) * BIND8 library - * Libmagic + * Libmagic 5.04 or greater * Libz * Bash (for BroControl) To build Bro from source, the following additional dependencies are required: * CMake 2.6.3 or greater (http://www.cmake.org) + * Make + * C/C++ compiler * SWIG (http://www.swig.org) * Bison (GNU Parser Generator) * Flex (Fast Lexical Analyzer) From 79bd81c8da1a845ea22d18eb3012224abb0c6ed4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Sep 2013 11:39:52 -0500 Subject: [PATCH 334/881] Fix nesting/indent level whitespace mismatch. The EndData() doesn't make sense as part of the condition that implies the state is such that it's not inside data. It might make sense as part of an else block, but it also seems fine to unconditionally EndData() like it currently does. That way unexpected states (mail != 0) are dealt with sooner rather than later. --- src/analyzer/protocol/smtp/SMTP.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyzer/protocol/smtp/SMTP.cc b/src/analyzer/protocol/smtp/SMTP.cc index b496e97c69..c3fb21b6a4 100644 --- a/src/analyzer/protocol/smtp/SMTP.cc +++ b/src/analyzer/protocol/smtp/SMTP.cc @@ -599,7 +599,7 @@ void SMTP_Analyzer::UpdateState(const int cmd_code, const int reply_code) case 0: if ( st != SMTP_IN_DATA ) UnexpectedCommand(cmd_code, reply_code); - EndData(); + EndData(); state = SMTP_AFTER_DATA; break; From d05a02e848dc0e9ff27293339d3cb90c48ce25ba Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Sep 2013 12:57:14 -0500 Subject: [PATCH 335/881] Update Mozilla root CA certs. --- scripts/base/protocols/ssl/mozilla-ca-list.bro | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/base/protocols/ssl/mozilla-ca-list.bro b/scripts/base/protocols/ssl/mozilla-ca-list.bro index ad8e445912..e97a1b2d50 100644 --- a/scripts/base/protocols/ssl/mozilla-ca-list.bro +++ b/scripts/base/protocols/ssl/mozilla-ca-list.bro @@ -1,5 +1,5 @@ # Don't edit! This file is automatically generated. -# Generated at: Fri Jul 13 22:22:40 -0400 2012 +# Generated at: Thu Sep 19 12:41:00 -0500 2013 @load base/protocols/ssl module SSL; redef root_certs += { @@ -143,4 +143,6 @@ redef root_certs += { ["CN=StartCom Certification Authority G2,O=StartCom Ltd.,C=IL"] = "\x30\x82\x05\x63\x30\x82\x03\x4B\xA0\x03\x02\x01\x02\x02\x01\x3B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x4C\x74\x64\x2E\x31\x2C\x30\x2A\x06\x03\x55\x04\x03\x13\x23\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x47\x32\x30\x1E\x17\x0D\x31\x30\x30\x31\x30\x31\x30\x31\x30\x30\x30\x31\x5A\x17\x0D\x33\x39\x31\x32\x33\x31\x32\x33\x35\x39\x30\x31\x5A\x30\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x4C\x74\x64\x2E\x31\x2C\x30\x2A\x06\x03\x55\x04\x03\x13\x23\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x47\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xB6\x89\x36\x5B\x07\xB7\x20\x36\xBD\x82\xBB\xE1\x16\x20\x03\x95\x7A\xAF\x0E\xA3\x55\xC9\x25\x99\x4A\xC5\xD0\x56\x41\x87\x90\x4D\x21\x60\xA4\x14\x87\x3B\xCD\xFD\xB2\x3E\xB4\x67\x03\x6A\xED\xE1\x0F\x4B\xC0\x91\x85\x70\x45\xE0\x42\x9E\xDE\x29\x23\xD4\x01\x0D\xA0\x10\x79\xB8\xDB\x03\xBD\xF3\xA9\x2F\xD1\xC6\xE0\x0F\xCB\x9E\x8A\x14\x0A\xB8\xBD\xF6\x56\x62\xF1\xC5\x72\xB6\x32\x25\xD9\xB2\xF3\xBD\x65\xC5\x0D\x2C\x6E\xD5\x92\x6F\x18\x8B\x00\x41\x14\x82\x6F\x40\x20\x26\x7A\x28\x0F\xF5\x1E\x7F\x27\xF7\x94\xB1\x37\x3D\xB7\xC7\x91\xF7\xE2\x01\xEC\xFD\x94\x89\xE1\xCC\x6E\xD3\x36\xD6\x0A\x19\x79\xAE\xD7\x34\x82\x65\xFF\x7C\x42\xBB\xB6\xDD\x0B\xA6\x34\xAF\x4B\x60\xFE\x7F\x43\x49\x06\x8B\x8C\x43\xB8\x56\xF2\xD9\x7F\x21\x43\x17\xEA\xA7\x48\x95\x01\x75\x75\xEA\x2B\xA5\x43\x95\xEA\x15\x84\x9D\x08\x8D\x26\x6E\x55\x9B\xAB\xDC\xD2\x39\xD2\x31\x1D\x60\xE2\xAC\xCC\x56\x45\x24\xF5\x1C\x54\xAB\xEE\x86\xDD\x96\x32\x85\xF8\x4C\x4F\xE8\x95\x76\xB6\x05\xDD\x36\x23\x67\xBC\xFF\x15\xE2\xCA\x3B\xE6\xA6\xEC\x3B\xEC\x26\x11\x34\x48\x8D\xF6\x80\x2B\x1A\x23\x02\xEB\x8A\x1C\x3A\x76\x2A\x7B\x56\x16\x1C\x72\x2A\xB3\xAA\xE3\x60\xA5\x00\x9F\x04\x9B\xE2\x6F\x1E\x14\x58\x5B\xA5\x6C\x8B\x58\x3C\xC3\xBA\x4E\x3A\x5C\xF7\xE1\x96\x2B\x3E\xEF\x07\xBC\xA4\xE5\x5D\xCC\x4D\x9F\x0D\xE1\xDC\xAA\xBB\xE1\x6E\x1A\xEC\x8F\xE1\xB6\x4C\x4D\x79\x72\x5D\x17\x35\x0B\x1D\xD7\xC1\x47\xDA\x96\x24\xE0\xD0\x72\xA8\x5A\x5F\x66\x2D\x10\xDC\x2F\x2A\x13\xAE\x26\xFE\x0A\x1C\x19\xCC\xD0\x3E\x0B\x9C\xC8\x09\x2E\xF9\x5B\x96\x7A\x47\x9C\xE9\x7A\xF3\x05\x50\x74\x95\x73\x9E\x30\x09\xF3\x97\x82\x5E\xE6\x8F\x39\x08\x1E\x59\xE5\x35\x14\x42\x13\xFF\x00\x9C\xF7\xBE\xAA\x50\xCF\xE2\x51\x48\xD7\xB8\x6F\xAF\xF8\x4E\x7E\x33\x98\x92\x14\x62\x3A\x75\x63\xCF\x7B\xFA\xDE\x82\x3B\xA9\xBB\x39\xE2\xC4\xBD\x2C\x00\x0E\xC8\x17\xAC\x13\xEF\x4D\x25\x8E\xD8\xB3\x90\x2F\xA9\xDA\x29\x7D\x1D\xAF\x74\x3A\xB2\x27\xC0\xC1\x1E\x3E\x75\xA3\x16\xA9\xAF\x7A\x22\x5D\x9F\x13\x1A\xCF\xA7\xA0\xEB\xE3\x86\x0A\xD3\xFD\xE6\x96\x95\xD7\x23\xC8\x37\xDD\xC4\x7C\xAA\x36\xAC\x98\x1A\x12\xB1\xE0\x4E\xE8\xB1\x3B\xF5\xD6\x6F\xF1\x30\xD7\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4B\xC5\xB4\x40\x6B\xAD\x1C\xB3\xA5\x1C\x65\x6E\x46\x36\x89\x87\x05\x0C\x0E\xB6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x73\x57\x3F\x2C\xD5\x95\x32\x7E\x37\xDB\x96\x92\xEB\x19\x5E\x7E\x53\xE7\x41\xEC\x11\xB6\x47\xEF\xB5\xDE\xED\x74\x5C\xC5\xF1\x8E\x49\xE0\xFC\x6E\x99\x13\xCD\x9F\x8A\xDA\xCD\x3A\x0A\xD8\x3A\x5A\x09\x3F\x5F\x34\xD0\x2F\x03\xD2\x66\x1D\x1A\xBD\x9C\x90\x37\xC8\x0C\x8E\x07\x5A\x94\x45\x46\x2A\xE6\xBE\x7A\xDA\xA1\xA9\xA4\x69\x12\x92\xB0\x7D\x36\xD4\x44\x87\xD7\x51\xF1\x29\x63\xD6\x75\xCD\x16\xE4\x27\x89\x1D\xF8\xC2\x32\x48\xFD\xDB\x99\xD0\x8F\x5F\x54\x74\xCC\xAC\x67\x34\x11\x62\xD9\x0C\x0A\x37\x87\xD1\xA3\x17\x48\x8E\xD2\x17\x1D\xF6\xD7\xFD\xDB\x65\xEB\xFD\xA8\xD4\xF5\xD6\x4F\xA4\x5B\x75\xE8\xC5\xD2\x60\xB2\xDB\x09\x7E\x25\x8B\x7B\xBA\x52\x92\x9E\x3E\xE8\xC5\x77\xA1\x3C\xE0\x4A\x73\x6B\x61\xCF\x86\xDC\x43\xFF\xFF\x21\xFE\x23\x5D\x24\x4A\xF5\xD3\x6D\x0F\x62\x04\x05\x57\x82\xDA\x6E\xA4\x33\x25\x79\x4B\x2E\x54\x19\x8B\xCC\x2C\x3D\x30\xE9\xD1\x06\xFF\xE8\x32\x46\xBE\xB5\x33\x76\x77\xA8\x01\x5D\x96\xC1\xC1\xD5\xBE\xAE\x25\xC0\xC9\x1E\x0A\x09\x20\x88\xA1\x0E\xC9\xF3\x6F\x4D\x82\x54\x00\x20\xA7\xD2\x8F\xE4\x39\x54\x17\x2E\x8D\x1E\xB8\x1B\xBB\x1B\xBD\x9A\x4E\x3B\x10\x34\xDC\x9C\x88\x53\xEF\xA2\x31\x5B\x58\x4F\x91\x62\xC8\xC2\x9A\x9A\xCD\x15\x5D\x38\xA9\xD6\xBE\xF8\x13\xB5\x9F\x12\x69\xF2\x50\x62\xAC\xFB\x17\x37\xF4\xEE\xB8\x75\x67\x60\x10\xFB\x83\x50\xF9\x44\xB5\x75\x9C\x40\x17\xB2\xFE\xFD\x79\x5D\x6E\x58\x58\x5F\x30\xFC\x00\xAE\xAF\x33\xC1\x0E\x4E\x6C\xBA\xA7\xA6\xA1\x7F\x32\xDB\x38\xE0\xB1\x72\x17\x0A\x2B\x91\xEC\x6A\x63\x26\xED\x89\xD4\x78\xCC\x74\x1E\x05\xF8\x6B\xFE\x8C\x6A\x76\x39\x29\xAE\x65\x23\x12\x95\x08\x22\x1C\x97\xCE\x5B\x06\xEE\x0C\xE2\xBB\xBC\x1F\x44\x93\xF6\xD8\x38\x45\x05\x21\xED\xE4\xAD\xAB\x12\xB6\x03\xA4\x42\x2E\x2D\xC4\x09\x3A\x03\x67\x69\x84\x9A\xE1\x59\x90\x8A\x28\x85\xD5\x5D\x74\xB1\xD1\x0E\x20\x58\x9B\x13\xA5\xB0\x63\xA6\xED\x7B\x47\xFD\x45\x55\x30\xA4\xEE\x9A\xD4\xE6\xE2\x87\xEF\x98\xC9\x32\x82\x11\x29\x22\xBC\x00\x0A\x31\x5E\x2D\x0F\xC0\x8E\xE9\x6B\xB2\x8F\x2E\x06\xD8\xD1\x91\xC7\xC6\x12\xF4\x4C\xFD\x30\x17\xC3\xC1\xDA\x38\x5B\xE3\xA9\xEA\xE6\xA1\xBA\x79\xEF\x73\xD8\xB6\x53\x57\x2D\xF6\xD0\xE1\xD7\x48", ["CN=Buypass Class 2 Root CA,O=Buypass AS-983163327,C=NO"] = "\x30\x82\x05\x59\x30\x82\x03\x41\xA0\x03\x02\x01\x02\x02\x01\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x31\x30\x31\x30\x32\x36\x30\x38\x33\x38\x30\x33\x5A\x17\x0D\x34\x30\x31\x30\x32\x36\x30\x38\x33\x38\x30\x33\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xD7\xC7\x5E\xF7\xC1\x07\xD4\x77\xFB\x43\x21\xF4\xF4\xF5\x69\xE4\xEE\x32\x01\xDB\xA3\x86\x1F\xE4\x59\x0D\xBA\xE7\x75\x83\x52\xEB\xEA\x1C\x61\x15\x48\xBB\x1D\x07\xCA\x8C\xAE\xB0\xDC\x96\x9D\xEA\xC3\x60\x92\x86\x82\x28\x73\x9C\x56\x06\xFF\x4B\x64\xF0\x0C\x2A\x37\x49\xB5\xE5\xCF\x0C\x7C\xEE\xF1\x4A\xBB\x73\x30\x65\xF3\xD5\x2F\x83\xB6\x7E\xE3\xE7\xF5\x9E\xAB\x60\xF9\xD3\xF1\x9D\x92\x74\x8A\xE4\x1C\x96\xAC\x5B\x80\xE9\xB5\xF4\x31\x87\xA3\x51\xFC\xC7\x7E\xA1\x6F\x8E\x53\x77\xD4\x97\xC1\x55\x33\x92\x3E\x18\x2F\x75\xD4\xAD\x86\x49\xCB\x95\xAF\x54\x06\x6C\xD8\x06\x13\x8D\x5B\xFF\xE1\x26\x19\x59\xC0\x24\xBA\x81\x71\x79\x90\x44\x50\x68\x24\x94\x5F\xB8\xB3\x11\xF1\x29\x41\x61\xA3\x41\xCB\x23\x36\xD5\xC1\xF1\x32\x50\x10\x4E\x7F\xF4\x86\x93\xEC\x84\xD3\x8E\xBC\x4B\xBF\x5C\x01\x4E\x07\x3D\xDC\x14\x8A\x94\x0A\xA4\xEA\x73\xFB\x0B\x51\xE8\x13\x07\x18\xFA\x0E\xF1\x2B\xD1\x54\x15\x7D\x3C\xE1\xF7\xB4\x19\x42\x67\x62\x5E\x77\xE0\xA2\x55\xEC\xB6\xD9\x69\x17\xD5\x3A\xAF\x44\xED\x4A\xC5\x9E\xE4\x7A\x27\x7C\xE5\x75\xD7\xAA\xCB\x25\xE7\xDF\x6B\x0A\xDB\x0F\x4D\x93\x4E\xA8\xA0\xCD\x7B\x2E\xF2\x59\x01\x6A\xB7\x0D\xB8\x07\x81\x7E\x8B\x38\x1B\x38\xE6\x0A\x57\x99\x3D\xEE\x21\xE8\xA3\xF5\x0C\x16\xDD\x8B\xEC\x34\x8E\x9C\x2A\x1C\x00\x15\x17\x8D\x68\x83\xD2\x70\x9F\x18\x08\xCD\x11\x68\xD5\xC9\x6B\x52\xCD\xC4\x46\x8F\xDC\xB5\xF3\xD8\x57\x73\x1E\xE9\x94\x39\x04\xBF\xD3\xDE\x38\xDE\xB4\x53\xEC\x69\x1C\xA2\x7E\xC4\x8F\xE4\x1B\x70\xAD\xF2\xA2\xF9\xFB\xF7\x16\x64\x66\x69\x9F\x49\x51\xA2\xE2\x15\x18\x67\x06\x4A\x7F\xD5\x6C\xB5\x4D\xB3\x33\xE0\x61\xEB\x5D\xBE\xE9\x98\x0F\x32\xD7\x1D\x4B\x3C\x2E\x5A\x01\x52\x91\x09\xF2\xDF\xEA\x8D\xD8\x06\x40\x63\xAA\x11\xE4\xFE\xC3\x37\x9E\x14\x52\x3F\xF4\xE2\xCC\xF2\x61\x93\xD1\xFD\x67\x6B\xD7\x52\xAE\xBF\x68\xAB\x40\x43\xA0\x57\x35\x53\x78\xF0\x53\xF8\x61\x42\x07\x64\xC6\xD7\x6F\x9B\x4C\x38\x0D\x63\xAC\x62\xAF\x36\x8B\xA2\x73\x0A\x0D\xF5\x21\xBD\x74\xAA\x4D\xEA\x72\x03\x49\xDB\xC7\x5F\x1D\x62\x63\xC7\xFD\xDD\x91\xEC\x33\xEE\xF5\x6D\xB4\x6E\x30\x68\xDE\xC8\xD6\x26\xB0\x75\x5E\x7B\xB4\x07\x20\x98\xA1\x76\x32\xB8\x4D\x6C\x4F\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC9\x80\x77\xE0\x62\x92\x82\xF5\x46\x9C\xF3\xBA\xF7\x4C\xC3\xDE\xB8\xA3\xAD\x39\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x53\x5F\x21\xF5\xBA\xB0\x3A\x52\x39\x2C\x92\xB0\x6C\x00\xC9\xEF\xCE\x20\xEF\x06\xF2\x96\x9E\xE9\xA4\x74\x7F\x7A\x16\xFC\xB7\xF5\xB6\xFB\x15\x1B\x3F\xAB\xA6\xC0\x72\x5D\x10\xB1\x71\xEE\xBC\x4F\xE3\xAD\xAC\x03\x6D\x2E\x71\x2E\xAF\xC4\xE3\xAD\xA3\xBD\x0C\x11\xA7\xB4\xFF\x4A\xB2\x7B\x10\x10\x1F\xA7\x57\x41\xB2\xC0\xAE\xF4\x2C\x59\xD6\x47\x10\x88\xF3\x21\x51\x29\x30\xCA\x60\x86\xAF\x46\xAB\x1D\xED\x3A\x5B\xB0\x94\xDE\x44\xE3\x41\x08\xA2\xC1\xEC\x1D\xD6\xFD\x4F\xB6\xD6\x47\xD0\x14\x0B\xCA\xE6\xCA\xB5\x7B\x77\x7E\x41\x1F\x5E\x83\xC7\xB6\x8C\x39\x96\xB0\x3F\x96\x81\x41\x6F\x60\x90\xE2\xE8\xF9\xFB\x22\x71\xD9\x7D\xB3\x3D\x46\xBF\xB4\x84\xAF\x90\x1C\x0F\x8F\x12\x6A\xAF\xEF\xEE\x1E\x7A\xAE\x02\x4A\x8A\x17\x2B\x76\xFE\xAC\x54\x89\x24\x2C\x4F\x3F\xB6\xB2\xA7\x4E\x8C\xA8\x91\x97\xFB\x29\xC6\x7B\x5C\x2D\xB9\xCB\x66\xB6\xB7\xA8\x5B\x12\x51\x85\xB5\x09\x7E\x62\x78\x70\xFE\xA9\x6A\x60\xB6\x1D\x0E\x79\x0C\xFD\xCA\xEA\x24\x80\x72\xC3\x97\x3F\xF2\x77\xAB\x43\x22\x0A\xC7\xEB\xB6\x0C\x84\x82\x2C\x80\x6B\x41\x8A\x08\xC0\xEB\xA5\x6B\xDF\x99\x12\xCB\x8A\xD5\x5E\x80\x0C\x91\xE0\x26\x08\x36\x48\xC5\xFA\x38\x11\x35\xFF\x25\x83\x2D\xF2\x7A\xBF\xDA\xFD\x8E\xFE\xA5\xCB\x45\x2C\x1F\xC4\x88\x53\xAE\x77\x0E\xD9\x9A\x76\xC5\x8E\x2C\x1D\xA3\xBA\xD5\xEC\x32\xAE\xC0\xAA\xAC\xF7\xD1\x7A\x4D\xEB\xD4\x07\xE2\x48\xF7\x22\x8E\xB0\xA4\x9F\x6A\xCE\x8E\xB2\xB2\x60\xF4\xA3\x22\xD0\x23\xEB\x94\x5A\x7A\x69\xDD\x0F\xBF\x40\x57\xAC\x6B\x59\x50\xD9\xA3\x99\xE1\x6E\xFE\x8D\x01\x79\x27\x23\x15\xDE\x92\x9D\x7B\x09\x4D\x5A\xE7\x4B\x48\x30\x5A\x18\xE6\x0A\x6D\xE6\x8F\xE0\xD2\xBB\xE6\xDF\x7C\x6E\x21\x82\xC1\x68\x39\x4D\xB4\x98\x58\x66\x62\xCC\x4A\x90\x5E\xC3\xFA\x27\x04\xB1\x79\x15\x74\x99\xCC\xBE\xAD\x20\xDE\x26\x60\x1C\xEB\x56\x51\xA6\xA3\xEA\xE4\xA3\x3F\xA7\xFF\x61\xDC\xF1\x5A\x4D\x6C\x32\x23\x43\xEE\xAC\xA8\xEE\xEE\x4A\x12\x09\x3C\x5D\x71\xC2\xBE\x79\xFA\xC2\x87\x68\x1D\x0B\xFD\x5C\x69\xCC\x06\xD0\x9A\x7D\x54\x99\x2A\xC9\x39\x1A\x19\xAF\x4B\x2A\x43\xF3\x63\x5D\x5A\x58\xE2\x2F\xE3\x1D\xE4\xA9\xD6\xD0\x0A\xD0\x9E\xBF\xD7\x81\x09\xF1\xC9\xC7\x26\x0D\xAC\x98\x16\x56\xA0", ["CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO"] = "\x30\x82\x05\x59\x30\x82\x03\x41\xA0\x03\x02\x01\x02\x02\x01\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x31\x30\x31\x30\x32\x36\x30\x38\x32\x38\x35\x38\x5A\x17\x0D\x34\x30\x31\x30\x32\x36\x30\x38\x32\x38\x35\x38\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xA5\xDA\x0A\x95\x16\x50\xE3\x95\xF2\x5E\x9D\x76\x31\x06\x32\x7A\x9B\xF1\x10\x76\xB8\x00\x9A\xB5\x52\x36\xCD\x24\x47\xB0\x9F\x18\x64\xBC\x9A\xF6\xFA\xD5\x79\xD8\x90\x62\x4C\x22\x2F\xDE\x38\x3D\xD6\xE0\xA8\xE9\x1C\x2C\xDB\x78\x11\xE9\x8E\x68\x51\x15\x72\xC7\xF3\x33\x87\xE4\xA0\x5D\x0B\x5C\xE0\x57\x07\x2A\x30\xF5\xCD\xC4\x37\x77\x28\x4D\x18\x91\xE6\xBF\xD5\x52\xFD\x71\x2D\x70\x3E\xE7\xC6\xC4\x8A\xE3\xF0\x28\x0B\xF4\x76\x98\xA1\x8B\x87\x55\xB2\x3A\x13\xFC\xB7\x3E\x27\x37\x8E\x22\xE3\xA8\x4F\x2A\xEF\x60\xBB\x3D\xB7\x39\xC3\x0E\x01\x47\x99\x5D\x12\x4F\xDB\x43\xFA\x57\xA1\xED\xF9\x9D\xBE\x11\x47\x26\x5B\x13\x98\xAB\x5D\x16\x8A\xB0\x37\x1C\x57\x9D\x45\xFF\x88\x96\x36\xBF\xBB\xCA\x07\x7B\x6F\x87\x63\xD7\xD0\x32\x6A\xD6\x5D\x6C\x0C\xF1\xB3\x6E\x39\xE2\x6B\x31\x2E\x39\x00\x27\x14\xDE\x38\xC0\xEC\x19\x66\x86\x12\xE8\x9D\x72\x16\x13\x64\x52\xC7\xA9\x37\x1C\xFD\x82\x30\xED\x84\x18\x1D\xF4\xAE\x5C\xFF\x70\x13\x00\xEB\xB1\xF5\x33\x7A\x4B\xD6\x55\xF8\x05\x8D\x4B\x69\xB0\xF5\xB3\x28\x36\x5C\x14\xC4\x51\x73\x4D\x6B\x0B\xF1\x34\x07\xDB\x17\x39\xD7\xDC\x28\x7B\x6B\xF5\x9F\xF3\x2E\xC1\x4F\x17\x2A\x10\xF3\xCC\xCA\xE8\xEB\xFD\x6B\xAB\x2E\x9A\x9F\x2D\x82\x6E\x04\xD4\x52\x01\x93\x2D\x3D\x86\xFC\x7E\xFC\xDF\xEF\x42\x1D\xA6\x6B\xEF\xB9\x20\xC6\xF7\xBD\xA0\xA7\x95\xFD\xA7\xE6\x89\x24\xD8\xCC\x8C\x34\x6C\xE2\x23\x2F\xD9\x12\x1A\x21\xB9\x55\x91\x6F\x0B\x91\x79\x19\x0C\xAD\x40\x88\x0B\x70\xE2\x7A\xD2\x0E\xD8\x68\x48\xBB\x82\x13\x39\x10\x58\xE9\xD8\x2A\x07\xC6\x12\xDB\x58\xDB\xD2\x3B\x55\x10\x47\x05\x15\x67\x62\x7E\x18\x63\xA6\x46\x3F\x09\x0E\x54\x32\x5E\xBF\x0D\x62\x7A\x27\xEF\x80\xE8\xDB\xD9\x4B\x06\x5A\x37\x5A\x25\xD0\x08\x12\x77\xD4\x6F\x09\x50\x97\x3D\xC8\x1D\xC3\xDF\x8C\x45\x30\x56\xC6\xD3\x64\xAB\x66\xF3\xC0\x5E\x96\x9C\xC3\xC4\xEF\xC3\x7C\x6B\x8B\x3A\x79\x7F\xB3\x49\xCF\x3D\xE2\x89\x9F\xA0\x30\x4B\x85\xB9\x9C\x94\x24\x79\x8F\x7D\x6B\xA9\x45\x68\x0F\x2B\xD0\xF1\xDA\x1C\xCB\x69\xB8\xCA\x49\x62\x6D\xC8\xD0\x63\x62\xDD\x60\x0F\x58\xAA\x8F\xA1\xBC\x05\xA5\x66\xA2\xCF\x1B\x76\xB2\x84\x64\xB1\x4C\x39\x52\xC0\x30\xBA\xF0\x8C\x4B\x02\xB0\xB6\xB7\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x47\xB8\xCD\xFF\xE5\x6F\xEE\xF8\xB2\xEC\x2F\x4E\x0E\xF9\x25\xB0\x8E\x3C\x6B\xC3\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x00\x20\x23\x41\x35\x04\x90\xC2\x40\x62\x60\xEF\xE2\x35\x4C\xD7\x3F\xAC\xE2\x34\x90\xB8\xA1\x6F\x76\xFA\x16\x16\xA4\x48\x37\x2C\xE9\x90\xC2\xF2\x3C\xF8\x0A\x9F\xD8\x81\xE5\xBB\x5B\xDA\x25\x2C\xA4\xA7\x55\x71\x24\x32\xF6\xC8\x0B\xF2\xBC\x6A\xF8\x93\xAC\xB2\x07\xC2\x5F\x9F\xDB\xCC\xC8\x8A\xAA\xBE\x6A\x6F\xE1\x49\x10\xCC\x31\xD7\x80\xBB\xBB\xC8\xD8\xA2\x0E\x64\x57\xEA\xA2\xF5\xC2\xA9\x31\x15\xD2\x20\x6A\xEC\xFC\x22\x01\x28\xCF\x86\xB8\x80\x1E\xA9\xCC\x11\xA5\x3C\xF2\x16\xB3\x47\x9D\xFC\xD2\x80\x21\xC4\xCB\xD0\x47\x70\x41\xA1\xCA\x83\x19\x08\x2C\x6D\xF2\x5D\x77\x9C\x8A\x14\x13\xD4\x36\x1C\x92\xF0\xE5\x06\x37\xDC\xA6\xE6\x90\x9B\x38\x8F\x5C\x6B\x1B\x46\x86\x43\x42\x5F\x3E\x01\x07\x53\x54\x5D\x65\x7D\xF7\x8A\x73\xA1\x9A\x54\x5A\x1F\x29\x43\x14\x27\xC2\x85\x0F\xB5\x88\x7B\x1A\x3B\x94\xB7\x1D\x60\xA7\xB5\x9C\xE7\x29\x69\x57\x5A\x9B\x93\x7A\x43\x30\x1B\x03\xD7\x62\xC8\x40\xA6\xAA\xFC\x64\xE4\x4A\xD7\x91\x53\x01\xA8\x20\x88\x6E\x9C\x5F\x44\xB9\xCB\x60\x81\x34\xEC\x6F\xD3\x7D\xDA\x48\x5F\xEB\xB4\x90\xBC\x2D\xA9\x1C\x0B\xAC\x1C\xD5\xA2\x68\x20\x80\x04\xD6\xFC\xB1\x8F\x2F\xBB\x4A\x31\x0D\x4A\x86\x1C\xEB\xE2\x36\x29\x26\xF5\xDA\xD8\xC4\xF2\x75\x61\xCF\x7E\xAE\x76\x63\x4A\x7A\x40\x65\x93\x87\xF8\x1E\x80\x8C\x86\xE5\x86\xD6\x8F\x0E\xFC\x53\x2C\x60\xE8\x16\x61\x1A\xA2\x3E\x43\x7B\xCD\x39\x60\x54\x6A\xF5\xF2\x89\x26\x01\x68\x83\x48\xA2\x33\xE8\xC9\x04\x91\xB2\x11\x34\x11\x3E\xEA\xD0\x43\x19\x1F\x03\x93\x90\x0C\xFF\x51\x3D\x57\xF4\x41\x6E\xE1\xCB\xA0\xBE\xEB\xC9\x63\xCD\x6D\xCC\xE4\xF8\x36\xAA\x68\x9D\xED\xBD\x5D\x97\x70\x44\x0D\xB6\x0E\x35\xDC\xE1\x0C\x5D\xBB\xA0\x51\x94\xCB\x7E\x16\xEB\x11\x2F\xA3\x92\x45\xC8\x4C\x71\xD9\xBC\xC9\x99\x52\x57\x46\x2F\x50\xCF\xBD\x35\x69\xF4\x3D\x15\xCE\x06\xA5\x2C\x0F\x3E\xF6\x81\xBA\x94\xBB\xC3\xBB\xBF\x65\x78\xD2\x86\x79\xFF\x49\x3B\x1A\x83\x0C\xF0\xDE\x78\xEC\xC8\xF2\x4D\x4C\x1A\xDE\x82\x29\xF8\xC1\x5A\xDA\xED\xEE\xE6\x27\x5E\xE8\x45\xD0\x9D\x1C\x51\xA8\x68\xAB\x44\xE3\xD0\x8B\x6A\xE3\xF8\x3B\xBB\xDC\x4D\xD7\x64\xF2\x51\xBE\xE6\xAA\xAB\x5A\xE9\x31\xEE\x06\xBC\x73\xBF\x13\x62\x0A\x9F\xC7\xB9\x97", + ["CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE"] = "\x30\x82\x03\xC3\x30\x82\x02\xAB\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x2B\x30\x29\x06\x03\x55\x04\x0A\x0C\x22\x54\x2D\x53\x79\x73\x74\x65\x6D\x73\x20\x45\x6E\x74\x65\x72\x70\x72\x69\x73\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x47\x6D\x62\x48\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x0C\x16\x54\x2D\x53\x79\x73\x74\x65\x6D\x73\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6E\x74\x65\x72\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0C\x1C\x54\x2D\x54\x65\x6C\x65\x53\x65\x63\x20\x47\x6C\x6F\x62\x61\x6C\x52\x6F\x6F\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x30\x1E\x17\x0D\x30\x38\x31\x30\x30\x31\x31\x30\x32\x39\x35\x36\x5A\x17\x0D\x33\x33\x31\x30\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x2B\x30\x29\x06\x03\x55\x04\x0A\x0C\x22\x54\x2D\x53\x79\x73\x74\x65\x6D\x73\x20\x45\x6E\x74\x65\x72\x70\x72\x69\x73\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x47\x6D\x62\x48\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x0C\x16\x54\x2D\x53\x79\x73\x74\x65\x6D\x73\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6E\x74\x65\x72\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0C\x1C\x54\x2D\x54\x65\x6C\x65\x53\x65\x63\x20\x47\x6C\x6F\x62\x61\x6C\x52\x6F\x6F\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xBD\x75\x93\xF0\x62\x22\x6F\x24\xAE\xE0\x7A\x76\xAC\x7D\xBD\xD9\x24\xD5\xB8\xB7\xFC\xCD\xF0\x42\xE0\xEB\x78\x88\x56\x5E\x9B\x9A\x54\x1D\x4D\x0C\x8A\xF6\xD3\xCF\x70\xF4\x52\xB5\xD8\x93\x04\xE3\x46\x86\x71\x41\x4A\x2B\xF0\x2A\x2C\x55\x03\xD6\x48\xC3\xE0\x39\x38\xED\xF2\x5C\x3C\x3F\x44\xBC\x93\x3D\x61\xAB\x4E\xCD\x0D\xBE\xF0\x20\x27\x58\x0E\x44\x7F\x04\x1A\x87\xA5\xD7\x96\x14\x36\x90\xD0\x49\x7B\xA1\x75\xFB\x1A\x6B\x73\xB1\xF8\xCE\xA9\x09\x2C\xF2\x53\xD5\xC3\x14\x44\xB8\x86\xA5\xF6\x8B\x2B\x39\xDA\xA3\x33\x54\xD9\xFA\x72\x1A\xF7\x22\x15\x1C\x88\x91\x6B\x7F\x66\xE5\xC3\x6A\x80\xB0\x24\xF3\xDF\x86\x45\x88\xFD\x19\x7F\x75\x87\x1F\x1F\xB1\x1B\x0A\x73\x24\x5B\xB9\x65\xE0\x2C\x54\xC8\x60\xD3\x66\x17\x3F\xE1\xCC\x54\x33\x73\x91\x02\x3A\xA6\x7F\x7B\x76\x39\xA2\x1F\x96\xB6\x38\xAE\xB5\xC8\x93\x74\x1D\x9E\xB9\xB4\xE5\x60\x9D\x2F\x56\xD1\xE0\xEB\x5E\x5B\x4C\x12\x70\x0C\x6C\x44\x20\xAB\x11\xD8\xF4\x19\xF6\xD2\x9C\x52\x37\xE7\xFA\xB6\xC2\x31\x3B\x4A\xD4\x14\x99\xAD\xC7\x1A\xF5\x5D\x5F\xFA\x07\xB8\x7C\x0D\x1F\xD6\x83\x1E\xB3\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB5\x03\xF7\x76\x3B\x61\x82\x6A\x12\xAA\x18\x53\xEB\x03\x21\x94\xBF\xFE\xCE\xCA\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x56\x3D\xEF\x94\xD5\xBD\xDA\x73\xB2\x58\xBE\xAE\x90\xAD\x98\x27\x97\xFE\x01\xB1\xB0\x52\x00\xB8\x4D\xE4\x1B\x21\x74\x1B\x7E\xC0\xEE\x5E\x69\x2A\x25\xAF\x5C\xD6\x1D\xDA\xD2\x79\xC9\xF3\x97\x29\xE0\x86\x87\xDE\x04\x59\x0F\xF1\x59\xD4\x64\x85\x4B\x99\xAF\x25\x04\x1E\xC9\x46\xA9\x97\xDE\x82\xB2\x1B\x70\x9F\x9C\xF6\xAF\x71\x31\xDD\x7B\x05\xA5\x2C\xD3\xB9\xCA\x47\xF6\xCA\xF2\xF6\xE7\xAD\xB9\x48\x3F\xBC\x16\xB7\xC1\x6D\xF4\xEA\x09\xAF\xEC\xF3\xB5\xE7\x05\x9E\xA6\x1E\x8A\x53\x51\xD6\x93\x81\xCC\x74\x93\xF6\xB9\xDA\xA6\x25\x05\x74\x79\x5A\x7E\x40\x3E\x82\x4B\x26\x11\x30\x6E\xE1\x3F\x41\xC7\x47\x00\x35\xD5\xF5\xD3\xF7\x54\x3E\x81\x3D\xDA\x49\x6A\x9A\xB3\xEF\x10\x3D\xE6\xEB\x6F\xD1\xC8\x22\x47\xCB\xCC\xCF\x01\x31\x92\xD9\x18\xE3\x22\xBE\x09\x1E\x1A\x3E\x5A\xB2\xE4\x6B\x0C\x54\x7A\x7D\x43\x4E\xB8\x89\xA5\x7B\xD7\xA2\x3D\x96\x86\xCC\xF2\x26\x34\x2D\x6A\x92\x9D\x9A\x1A\xD0\x30\xE2\x5D\x4E\x04\xB0\x5F\x8B\x20\x7E\x77\xC1\x3D\x95\x82\xD1\x46\x9A\x3B\x3C\x78\xB8\x6F\xA1\xD0\x0D\x64\xA2\x78\x1E\x29\x4E\x93\xC3\xA4\x54\x14\x5B", + ["emailAddress=pki@sk.ee,CN=EE Certification Centre Root CA,O=AS Sertifitseerimiskeskus,C=EE"] = "\x30\x82\x04\x03\x30\x82\x02\xEB\xA0\x03\x02\x01\x02\x02\x10\x54\x80\xF9\xA0\x73\xED\x3F\x00\x4C\xCA\x89\xD8\xE3\x71\xE6\x4A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x0C\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6D\x69\x73\x6B\x65\x73\x6B\x75\x73\x31\x28\x30\x26\x06\x03\x55\x04\x03\x0C\x1F\x45\x45\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x43\x65\x6E\x74\x72\x65\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x18\x30\x16\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x09\x70\x6B\x69\x40\x73\x6B\x2E\x65\x65\x30\x22\x18\x0F\x32\x30\x31\x30\x31\x30\x33\x30\x31\x30\x31\x30\x33\x30\x5A\x18\x0F\x32\x30\x33\x30\x31\x32\x31\x37\x32\x33\x35\x39\x35\x39\x5A\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x0C\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6D\x69\x73\x6B\x65\x73\x6B\x75\x73\x31\x28\x30\x26\x06\x03\x55\x04\x03\x0C\x1F\x45\x45\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x43\x65\x6E\x74\x72\x65\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x18\x30\x16\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x09\x70\x6B\x69\x40\x73\x6B\x2E\x65\x65\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xC8\x20\xC0\xEC\xE0\xC5\x4B\xAB\x07\x78\x95\xF3\x44\xEE\xFB\x0B\x0C\xFF\x74\x8E\x61\xBB\xB1\x62\xEA\x23\xD8\xAB\xA1\x65\x32\x7A\xEB\x8E\x17\x4F\x96\xD8\x0A\x7B\x91\xA2\x63\x6C\xC7\x8C\x4C\x2E\x79\xBF\xA9\x05\xFC\x69\x5C\x95\x8D\x62\xF9\xB9\x70\xED\xC3\x51\x7D\xD0\x93\xE6\x6C\xEB\x30\x4B\xE1\xBC\x7D\xBF\x52\x9B\xCE\x6E\x7B\x65\xF2\x38\xB1\xC0\xA2\x32\xEF\x62\xB2\x68\xE0\x61\x53\xC1\x36\x95\xFF\xEC\x94\xBA\x36\xAE\x9C\x1C\xA7\x32\x0F\xE5\x7C\xB4\xC6\x6F\x74\xFD\x7B\x18\xE8\xAC\x57\xED\x06\x20\x4B\x32\x30\x58\x5B\xFD\xCD\xA8\xE6\xA1\xFC\x70\xBC\x8E\x92\x73\xDB\x97\xA7\x7C\x21\xAE\x3D\xC1\xF5\x48\x87\x6C\x27\xBD\x9F\x25\x74\x81\x55\xB0\xF7\x75\xF6\x3D\xA4\x64\x6B\xD6\x4F\xE7\xCE\x40\xAD\x0F\xDD\x32\xD3\xBC\x8A\x12\x53\x98\xC9\x89\xFB\x10\x1D\x4D\x7E\xCD\x7E\x1F\x56\x0D\x21\x70\x85\xF6\x20\x83\x1F\xF6\xBA\x1F\x04\x8F\xEA\x77\x88\x35\xC4\xFF\xEA\x4E\xA1\x8B\x4D\x3F\x63\x1B\x44\xC3\x44\xD4\x25\x76\xCA\xB7\x8D\xD7\x1E\x4A\x66\x64\xCD\x5C\xC5\x9C\x83\xE1\xC2\x08\x88\x9A\xEC\x4E\xA3\xF1\x3E\x1C\x2C\xD9\x6C\x1D\xA1\x4B\x02\x03\x01\x00\x01\xA3\x81\x8A\x30\x81\x87\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x12\xF2\x5A\x3E\xEA\x56\x1C\xBF\xCD\x06\xAC\xF1\xF1\x25\xC9\xA9\x4B\xD4\x14\x99\x30\x45\x06\x03\x55\x1D\x25\x04\x3E\x30\x3C\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x08\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x09\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7B\xF6\xE4\xC0\x0D\xAA\x19\x47\xB7\x4D\x57\xA3\xFE\xAD\xBB\xB1\x6A\xD5\x0F\x9E\xDB\xE4\x63\xC5\x8E\xA1\x50\x56\x93\x96\xB8\x38\xC0\x24\x22\x66\xBC\x53\x14\x61\x95\xBF\xD0\xC7\x2A\x96\x39\x3F\x7D\x28\xB3\x10\x40\x21\x6A\xC4\xAF\xB0\x52\x77\x18\xE1\x96\xD8\x56\x5D\xE3\xDD\x36\x5E\x1D\xA7\x50\x54\xA0\xC5\x2A\xE4\xAA\x8C\x94\x8A\x4F\x9D\x35\xFF\x76\xA4\x06\x13\x91\xA2\xA2\x7D\x00\x44\x3F\x55\xD3\x82\x3C\x1A\xD5\x5B\xBC\x56\x4C\x22\x2E\x46\x43\x8A\x24\x40\x2D\xF3\x12\xB8\x3B\x70\x1A\xA4\x96\xB9\x1A\xAF\x87\x41\x1A\x6A\x18\x0D\x06\x4F\xC7\x3E\x6E\xB9\x29\x4D\x0D\x49\x89\x11\x87\x32\x5B\xE6\x4B\x04\xC8\xE4\x5C\xE6\x74\x73\x94\x5D\x16\x98\x13\x95\xFE\xFB\xDB\xB1\x44\xE5\x3A\x70\xAC\x37\x6B\xE6\xB3\x33\x72\x28\xC9\xB3\x57\xA0\xF6\x02\x16\x88\x06\x0B\xB6\xA6\x4B\x20\x28\xD4\xDE\x3D\x8B\xAD\x37\x05\x53\x74\xFE\x6E\xCC\xBC\x43\x17\x71\x5E\xF9\xC5\xCC\x1A\xA9\x61\xEE\xF7\x76\x0C\xF3\x72\xF4\x72\xAD\xCF\x72\x02\x36\x07\x47\xCF\xEF\x19\x50\x89\x60\xCC\xE9\x24\x95\x0F\xC2\xCB\x1D\xF2\x6F\x76\x90\xC7\xCC\x75\xC1\x96\xC5\x9D", }; From 1ed210a57247620174326bc530b0fe7a373761b7 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 19 Sep 2013 13:57:51 -0500 Subject: [PATCH 336/881] Set safe umask when creating script profiler tmp files. --- src/Brofiler.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Brofiler.cc b/src/Brofiler.cc index c9a3505069..777be52217 100644 --- a/src/Brofiler.cc +++ b/src/Brofiler.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include "Brofiler.h" #include "util.h" @@ -54,7 +55,10 @@ bool Brofiler::WriteStats() if ( p && ! p[7] ) { + mode_t old_umask = umask(S_IXUSR | S_IRWXO | S_IRWXG); int fd = mkstemp(bf); + umask(old_umask); + if ( fd == -1 ) { reporter->Error("Failed to generate unique file name from BRO_PROFILER_FILE: %s", bf); From 8b48a476ecf58a96d9cb014b275c7172f188a176 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 19 Sep 2013 12:53:45 -0700 Subject: [PATCH 337/881] update mozilla root ca list --- scripts/base/protocols/ssl/mozilla-ca-list.bro | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/base/protocols/ssl/mozilla-ca-list.bro b/scripts/base/protocols/ssl/mozilla-ca-list.bro index e97a1b2d50..75dc057a55 100644 --- a/scripts/base/protocols/ssl/mozilla-ca-list.bro +++ b/scripts/base/protocols/ssl/mozilla-ca-list.bro @@ -1,5 +1,5 @@ # Don't edit! This file is automatically generated. -# Generated at: Thu Sep 19 12:41:00 -0500 2013 +# Generated at: Thu Sep 19 12:40:13 -0700 2013 @load base/protocols/ssl module SSL; redef root_certs += { @@ -7,8 +7,6 @@ redef root_certs += { ["emailAddress=server-certs@thawte.com,CN=Thawte Server CA,OU=Certification Services Division,O=Thawte Consulting cc,L=Cape Town,ST=Western Cape,C=ZA"] = "\x30\x82\x03\x13\x30\x82\x02\x7C\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xC4\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2D\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xC4\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2D\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xD3\xA4\x50\x6E\xC8\xFF\x56\x6B\xE6\xCF\x5D\xB6\xEA\x0C\x68\x75\x47\xA2\xAA\xC2\xDA\x84\x25\xFC\xA8\xF4\x47\x51\xDA\x85\xB5\x20\x74\x94\x86\x1E\x0F\x75\xC9\xE9\x08\x61\xF5\x06\x6D\x30\x6E\x15\x19\x02\xE9\x52\xC0\x62\xDB\x4D\x99\x9E\xE2\x6A\x0C\x44\x38\xCD\xFE\xBE\xE3\x64\x09\x70\xC5\xFE\xB1\x6B\x29\xB6\x2F\x49\xC8\x3B\xD4\x27\x04\x25\x10\x97\x2F\xE7\x90\x6D\xC0\x28\x42\x99\xD7\x4C\x43\xDE\xC3\xF5\x21\x6D\x54\x9F\x5D\xC3\x58\xE1\xC0\xE4\xD9\x5B\xB0\xB8\xDC\xB4\x7B\xDF\x36\x3A\xC2\xB5\x66\x22\x12\xD6\x87\x0D\x02\x03\x01\x00\x01\xA3\x13\x30\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x07\xFA\x4C\x69\x5C\xFB\x95\xCC\x46\xEE\x85\x83\x4D\x21\x30\x8E\xCA\xD9\xA8\x6F\x49\x1A\xE6\xDA\x51\xE3\x60\x70\x6C\x84\x61\x11\xA1\x1A\xC8\x48\x3E\x59\x43\x7D\x4F\x95\x3D\xA1\x8B\xB7\x0B\x62\x98\x7A\x75\x8A\xDD\x88\x4E\x4E\x9E\x40\xDB\xA8\xCC\x32\x74\xB9\x6F\x0D\xC6\xE3\xB3\x44\x0B\xD9\x8A\x6F\x9A\x29\x9B\x99\x18\x28\x3B\xD1\xE3\x40\x28\x9A\x5A\x3C\xD5\xB5\xE7\x20\x1B\x8B\xCA\xA4\xAB\x8D\xE9\x51\xD9\xE2\x4C\x2C\x59\xA9\xDA\xB9\xB2\x75\x1B\xF6\x42\xF2\xEF\xC7\xF2\x18\xF9\x89\xBC\xA3\xFF\x8A\x23\x2E\x70\x47", ["emailAddress=premium-server@thawte.com,CN=Thawte Premium Server CA,OU=Certification Services Division,O=Thawte Consulting cc,L=Cape Town,ST=Western Cape,C=ZA"] = "\x30\x82\x03\x27\x30\x82\x02\x90\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xCE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x19\x70\x72\x65\x6D\x69\x75\x6D\x2D\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x19\x70\x72\x65\x6D\x69\x75\x6D\x2D\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xD2\x36\x36\x6A\x8B\xD7\xC2\x5B\x9E\xDA\x81\x41\x62\x8F\x38\xEE\x49\x04\x55\xD6\xD0\xEF\x1C\x1B\x95\x16\x47\xEF\x18\x48\x35\x3A\x52\xF4\x2B\x6A\x06\x8F\x3B\x2F\xEA\x56\xE3\xAF\x86\x8D\x9E\x17\xF7\x9E\xB4\x65\x75\x02\x4D\xEF\xCB\x09\xA2\x21\x51\xD8\x9B\xD0\x67\xD0\xBA\x0D\x92\x06\x14\x73\xD4\x93\xCB\x97\x2A\x00\x9C\x5C\x4E\x0C\xBC\xFA\x15\x52\xFC\xF2\x44\x6E\xDA\x11\x4A\x6E\x08\x9F\x2F\x2D\xE3\xF9\xAA\x3A\x86\x73\xB6\x46\x53\x58\xC8\x89\x05\xBD\x83\x11\xB8\x73\x3F\xAA\x07\x8D\xF4\x42\x4D\xE7\x40\x9D\x1C\x37\x02\x03\x01\x00\x01\xA3\x13\x30\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x26\x48\x2C\x16\xC2\x58\xFA\xE8\x16\x74\x0C\xAA\xAA\x5F\x54\x3F\xF2\xD7\xC9\x78\x60\x5E\x5E\x6E\x37\x63\x22\x77\x36\x7E\xB2\x17\xC4\x34\xB9\xF5\x08\x85\xFC\xC9\x01\x38\xFF\x4D\xBE\xF2\x16\x42\x43\xE7\xBB\x5A\x46\xFB\xC1\xC6\x11\x1F\xF1\x4A\xB0\x28\x46\xC9\xC3\xC4\x42\x7D\xBC\xFA\xAB\x59\x6E\xD5\xB7\x51\x88\x11\xE3\xA4\x85\x19\x6B\x82\x4C\xA4\x0C\x12\xAD\xE9\xA4\xAE\x3F\xF1\xC3\x49\x65\x9A\x8C\xC5\xC8\x3E\x25\xB7\x94\x99\xBB\x92\x32\x71\x07\xF0\x86\x5E\xED\x50\x27\xA6\x0D\xA6\x23\xF9\xBB\xCB\xA6\x07\x14\x42", ["OU=Equifax Secure Certificate Authority,O=Equifax,C=US"] = "\x30\x82\x03\x20\x30\x82\x02\x89\xA0\x03\x02\x01\x02\x02\x04\x35\xDE\xF4\xCF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x17\x0D\x31\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xC1\x5D\xB1\x58\x67\x08\x62\xEE\xA0\x9A\x2D\x1F\x08\x6D\x91\x14\x68\x98\x0A\x1E\xFE\xDA\x04\x6F\x13\x84\x62\x21\xC3\xD1\x7C\xCE\x9F\x05\xE0\xB8\x01\xF0\x4E\x34\xEC\xE2\x8A\x95\x04\x64\xAC\xF1\x6B\x53\x5F\x05\xB3\xCB\x67\x80\xBF\x42\x02\x8E\xFE\xDD\x01\x09\xEC\xE1\x00\x14\x4F\xFC\xFB\xF0\x0C\xDD\x43\xBA\x5B\x2B\xE1\x1F\x80\x70\x99\x15\x57\x93\x16\xF1\x0F\x97\x6A\xB7\xC2\x68\x23\x1C\xCC\x4D\x59\x30\xAC\x51\x1E\x3B\xAF\x2B\xD6\xEE\x63\x45\x7B\xC5\xD9\x5F\x50\xD2\xE3\x50\x0F\x3A\x88\xE7\xBF\x14\xFD\xE0\xC7\xB9\x02\x03\x01\x00\x01\xA3\x82\x01\x09\x30\x82\x01\x05\x30\x70\x06\x03\x55\x1D\x1F\x04\x69\x30\x67\x30\x65\xA0\x63\xA0\x61\xA4\x5F\x30\x5D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x1A\x06\x03\x55\x1D\x10\x04\x13\x30\x11\x81\x0F\x32\x30\x31\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x48\xE6\x68\xF9\x2B\xD2\xB2\x95\xD7\x47\xD8\x23\x20\x10\x4F\x33\x98\x90\x9F\xD4\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x48\xE6\x68\xF9\x2B\xD2\xB2\x95\xD7\x47\xD8\x23\x20\x10\x4F\x33\x98\x90\x9F\xD4\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x1A\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0D\x30\x0B\x1B\x05\x56\x33\x2E\x30\x63\x03\x02\x06\xC0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x58\xCE\x29\xEA\xFC\xF7\xDE\xB5\xCE\x02\xB9\x17\xB5\x85\xD1\xB9\xE3\xE0\x95\xCC\x25\x31\x0D\x00\xA6\x92\x6E\x7F\xB6\x92\x63\x9E\x50\x95\xD1\x9A\x6F\xE4\x11\xDE\x63\x85\x6E\x98\xEE\xA8\xFF\x5A\xC8\xD3\x55\xB2\x66\x71\x57\xDE\xC0\x21\xEB\x3D\x2A\xA7\x23\x49\x01\x04\x86\x42\x7B\xFC\xEE\x7F\xA2\x16\x52\xB5\x67\x67\xD3\x40\xDB\x3B\x26\x58\xB2\x28\x77\x3D\xAE\x14\x77\x61\xD6\xFA\x2A\x66\x27\xA0\x0D\xFA\xA7\x73\x5C\xEA\x70\xF1\x94\x21\x65\x44\x5F\xFA\xFC\xEF\x29\x68\xA9\xA2\x87\x79\xEF\x79\xEF\x4F\xAC\x07\x77\x38", - ["OU=DSTCA E1,O=Digital Signature Trust Co.,C=US"] = "\x30\x82\x03\x29\x30\x82\x02\x92\xA0\x03\x02\x01\x02\x02\x04\x36\x70\x15\x96\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x30\x1E\x17\x0D\x39\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x17\x0D\x31\x38\x31\x32\x31\x30\x31\x38\x34\x30\x32\x33\x5A\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xA0\x6C\x81\xA9\xCF\x34\x1E\x24\xDD\xFE\x86\x28\xCC\xDE\x83\x2F\xF9\x5E\xD4\x42\xD2\xE8\x74\x60\x66\x13\x98\x06\x1C\xA9\x51\x12\x69\x6F\x31\x55\xB9\x49\x72\x00\x08\x7E\xD3\xA5\x62\x44\x37\x24\x99\x8F\xD9\x83\x48\x8F\x99\x6D\x95\x13\xBB\x43\x3B\x2E\x49\x4E\x88\x37\xC1\xBB\x58\x7F\xFE\xE1\xBD\xF8\xBB\x61\xCD\xF3\x47\xC0\x99\xA6\xF1\xF3\x91\xE8\x78\x7C\x00\xCB\x61\xC9\x44\x27\x71\x69\x55\x4A\x7E\x49\x4D\xED\xA2\xA3\xBE\x02\x4C\x00\xCA\x02\xA8\xEE\x01\x02\x31\x64\x0F\x52\x2D\x13\x74\x76\x36\xB5\x7A\xB4\x2D\x71\x02\x01\x03\xA3\x82\x01\x24\x30\x82\x01\x20\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x68\x06\x03\x55\x1D\x1F\x04\x61\x30\x5F\x30\x5D\xA0\x5B\xA0\x59\xA4\x57\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x81\x0F\x32\x30\x31\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x6A\x79\x7E\x91\x69\x46\x18\x13\x0A\x02\x77\xA5\x59\x5B\x60\x98\x25\x0E\xA2\xF8\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x6A\x79\x7E\x91\x69\x46\x18\x13\x0A\x02\x77\xA5\x59\x5B\x60\x98\x25\x0E\xA2\xF8\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x22\x12\xD8\x7A\x1D\xDC\x81\x06\xB6\x09\x65\xB2\x87\xC8\x1F\x5E\xB4\x2F\xE9\xC4\x1E\xF2\x3C\xC1\xBB\x04\x90\x11\x4A\x83\x4E\x7E\x93\xB9\x4D\x42\xC7\x92\x26\xA0\x5C\x34\x9A\x38\x72\xF8\xFD\x6B\x16\x3E\x20\xEE\x82\x8B\x31\x2A\x93\x36\x85\x23\x88\x8A\x3C\x03\x68\xD3\xC9\x09\x0F\x4D\xFC\x6C\xA4\xDA\x28\x72\x93\x0E\x89\x80\xB0\x7D\xFE\x80\x6F\x65\x6D\x18\x33\x97\x8B\xC2\x6B\x89\xEE\x60\x3D\xC8\x9B\xEF\x7F\x2B\x32\x62\x73\x93\xCB\x3C\xE3\x7B\xE2\x76\x78\x45\xBC\xA1\x93\x04\xBB\x86\x9F\x3A\x5B\x43\x7A\xC3\x8A\x65", - ["OU=DSTCA E2,O=Digital Signature Trust Co.,C=US"] = "\x30\x82\x03\x29\x30\x82\x02\x92\xA0\x03\x02\x01\x02\x02\x04\x36\x6E\xD3\xCE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x30\x1E\x17\x0D\x39\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x17\x0D\x31\x38\x31\x32\x30\x39\x31\x39\x34\x37\x32\x36\x5A\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xBF\x93\x8F\x17\x92\xEF\x33\x13\x18\xEB\x10\x7F\x4E\x16\xBF\xFF\x06\x8F\x2A\x85\xBC\x5E\xF9\x24\xA6\x24\x88\xB6\x03\xB7\xC1\xC3\x5F\x03\x5B\xD1\x6F\xAE\x7E\x42\xEA\x66\x23\xB8\x63\x83\x56\xFB\x28\x2D\xE1\x38\x8B\xB4\xEE\xA8\x01\xE1\xCE\x1C\xB6\x88\x2A\x22\x46\x85\xFB\x9F\xA7\x70\xA9\x47\x14\x3F\xCE\xDE\x65\xF0\xA8\x71\xF7\x4F\x26\x6C\x8C\xBC\xC6\xB5\xEF\xDE\x49\x27\xFF\x48\x2A\x7D\xE8\x4D\x03\xCC\xC7\xB2\x52\xC6\x17\x31\x13\x3B\xB5\x4D\xDB\xC8\xC4\xF6\xC3\x0F\x24\x2A\xDA\x0C\x9D\xE7\x91\x5B\x80\xCD\x94\x9D\x02\x01\x03\xA3\x82\x01\x24\x30\x82\x01\x20\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x68\x06\x03\x55\x1D\x1F\x04\x61\x30\x5F\x30\x5D\xA0\x5B\xA0\x59\xA4\x57\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x81\x0F\x32\x30\x31\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x1E\x82\x4D\x28\x65\x80\x3C\xC9\x41\x6E\xAC\x35\x2E\x5A\xCB\xDE\xEE\xF8\x39\x5B\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1E\x82\x4D\x28\x65\x80\x3C\xC9\x41\x6E\xAC\x35\x2E\x5A\xCB\xDE\xEE\xF8\x39\x5B\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x47\x8D\x83\xAD\x62\xF2\xDB\xB0\x9E\x45\x22\x05\xB9\xA2\xD6\x03\x0E\x38\x72\xE7\x9E\xFC\x7B\xE6\x93\xB6\x9A\xA5\xA2\x94\xC8\x34\x1D\x91\xD1\xC5\xD7\xF4\x0A\x25\x0F\x3D\x78\x81\x9E\x0F\xB1\x67\xC4\x90\x4C\x63\xDD\x5E\xA7\xE2\xBA\x9F\xF5\xF7\x4D\xA5\x31\x7B\x9C\x29\x2D\x4C\xFE\x64\x3E\xEC\xB6\x53\xFE\xEA\x9B\xED\x82\xDB\x74\x75\x4B\x07\x79\x6E\x1E\xD8\x19\x83\x73\xDE\xF5\x3E\xD0\xB5\xDE\xE7\x4B\x68\x7D\x43\x2E\x2A\x20\xE1\x7E\xA0\x78\x44\x9E\x08\xF5\x98\xF9\xC7\x7F\x1B\x1B\xD6\x06\x20\x02\x58\xA1\xC3\xA2\x03", ["OU=Class 3 Public Primary Certification Authority,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x02\x3C\x30\x82\x01\xA5\x02\x10\x70\xBA\xE4\x1D\x10\xD9\x29\x34\xB6\x38\xCA\x7B\x03\xCC\xBA\xBF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02\x05\x00\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x13\x2E\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x13\x2E\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xC9\x5C\x59\x9E\xF2\x1B\x8A\x01\x14\xB4\x10\xDF\x04\x40\xDB\xE3\x57\xAF\x6A\x45\x40\x8F\x84\x0C\x0B\xD1\x33\xD9\xD9\x11\xCF\xEE\x02\x58\x1F\x25\xF7\x2A\xA8\x44\x05\xAA\xEC\x03\x1F\x78\x7F\x9E\x93\xB9\x9A\x00\xAA\x23\x7D\xD6\xAC\x85\xA2\x63\x45\xC7\x72\x27\xCC\xF4\x4C\xC6\x75\x71\xD2\x39\xEF\x4F\x42\xF0\x75\xDF\x0A\x90\xC6\x8E\x20\x6F\x98\x0F\xF8\xAC\x23\x5F\x70\x29\x36\xA4\xC9\x86\xE7\xB1\x9A\x20\xCB\x53\xA5\x85\xE7\x3D\xBE\x7D\x9A\xFE\x24\x45\x33\xDC\x76\x15\xED\x0F\xA2\x71\x64\x4C\x65\x2E\x81\x68\x45\xA7\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02\x05\x00\x03\x81\x81\x00\xBB\x4C\x12\x2B\xCF\x2C\x26\x00\x4F\x14\x13\xDD\xA6\xFB\xFC\x0A\x11\x84\x8C\xF3\x28\x1C\x67\x92\x2F\x7C\xB6\xC5\xFA\xDF\xF0\xE8\x95\xBC\x1D\x8F\x6C\x2C\xA8\x51\xCC\x73\xD8\xA4\xC0\x53\xF0\x4E\xD6\x26\xC0\x76\x01\x57\x81\x92\x5E\x21\xF1\xD1\xB1\xFF\xE7\xD0\x21\x58\xCD\x69\x17\xE3\x44\x1C\x9C\x19\x44\x39\x89\x5C\xDC\x9C\x00\x0F\x56\x8D\x02\x99\xED\xA2\x90\x45\x4C\xE4\xBB\x10\xA4\x3D\xF0\x32\x03\x0E\xF1\xCE\xF8\xE8\xC9\x51\x8C\xE6\x62\x9F\xE6\x9F\xC0\x7D\xB7\x72\x9C\xC9\x36\x3A\x6B\x9F\x4E\xA8\xFF\x64\x0D\x64", ["OU=VeriSign Trust Network,OU=(c) 1998 VeriSign\, Inc. - For authorized use only,OU=Class 3 Public Primary Certification Authority - G2,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x03\x02\x30\x82\x02\x6B\x02\x10\x7D\xD9\xFE\x07\xCF\xA8\x1E\xB7\x10\x79\x67\xFB\xA7\x89\x34\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x1E\x17\x0D\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xCC\x5E\xD1\x11\x5D\x5C\x69\xD0\xAB\xD3\xB9\x6A\x4C\x99\x1F\x59\x98\x30\x8E\x16\x85\x20\x46\x6D\x47\x3F\xD4\x85\x20\x84\xE1\x6D\xB3\xF8\xA4\xED\x0C\xF1\x17\x0F\x3B\xF9\xA7\xF9\x25\xD7\xC1\xCF\x84\x63\xF2\x7C\x63\xCF\xA2\x47\xF2\xC6\x5B\x33\x8E\x64\x40\x04\x68\xC1\x80\xB9\x64\x1C\x45\x77\xC7\xD8\x6E\xF5\x95\x29\x3C\x50\xE8\x34\xD7\x78\x1F\xA8\xBA\x6D\x43\x91\x95\x8F\x45\x57\x5E\x7E\xC5\xFB\xCA\xA4\x04\xEB\xEA\x97\x37\x54\x30\x6F\xBB\x01\x47\x32\x33\xCD\xDC\x57\x9B\x64\x69\x61\xF8\x9B\x1D\x1C\x89\x4F\x5C\x67\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x51\x4D\xCD\xBE\x5C\xCB\x98\x19\x9C\x15\xB2\x01\x39\x78\x2E\x4D\x0F\x67\x70\x70\x99\xC6\x10\x5A\x94\xA4\x53\x4D\x54\x6D\x2B\xAF\x0D\x5D\x40\x8B\x64\xD3\xD7\xEE\xDE\x56\x61\x92\x5F\xA6\xC4\x1D\x10\x61\x36\xD3\x2C\x27\x3C\xE8\x29\x09\xB9\x11\x64\x74\xCC\xB5\x73\x9F\x1C\x48\xA9\xBC\x61\x01\xEE\xE2\x17\xA6\x0C\xE3\x40\x08\x3B\x0E\xE7\xEB\x44\x73\x2A\x9A\xF1\x69\x92\xEF\x71\x14\xC3\x39\xAC\x71\xA7\x91\x09\x6F\xE4\x71\x06\xB3\xBA\x59\x57\x26\x79\x00\xF6\xF8\x0D\xA2\x33\x30\x28\xD4\xAA\x58\xA0\x9D\x9D\x69\x91\xFD", ["CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE"] = "\x30\x82\x03\x75\x30\x82\x02\x5D\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x15\x4B\x5A\xC3\x94\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x57\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x6E\x76\x2D\x73\x61\x31\x10\x30\x0E\x06\x03\x55\x04\x0B\x13\x07\x52\x6F\x6F\x74\x20\x43\x41\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x39\x38\x30\x39\x30\x31\x31\x32\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x31\x32\x38\x31\x32\x30\x30\x30\x30\x5A\x30\x57\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x6E\x76\x2D\x73\x61\x31\x10\x30\x0E\x06\x03\x55\x04\x0B\x13\x07\x52\x6F\x6F\x74\x20\x43\x41\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xDA\x0E\xE6\x99\x8D\xCE\xA3\xE3\x4F\x8A\x7E\xFB\xF1\x8B\x83\x25\x6B\xEA\x48\x1F\xF1\x2A\xB0\xB9\x95\x11\x04\xBD\xF0\x63\xD1\xE2\x67\x66\xCF\x1C\xDD\xCF\x1B\x48\x2B\xEE\x8D\x89\x8E\x9A\xAF\x29\x80\x65\xAB\xE9\xC7\x2D\x12\xCB\xAB\x1C\x4C\x70\x07\xA1\x3D\x0A\x30\xCD\x15\x8D\x4F\xF8\xDD\xD4\x8C\x50\x15\x1C\xEF\x50\xEE\xC4\x2E\xF7\xFC\xE9\x52\xF2\x91\x7D\xE0\x6D\xD5\x35\x30\x8E\x5E\x43\x73\xF2\x41\xE9\xD5\x6A\xE3\xB2\x89\x3A\x56\x39\x38\x6F\x06\x3C\x88\x69\x5B\x2A\x4D\xC5\xA7\x54\xB8\x6C\x89\xCC\x9B\xF9\x3C\xCA\xE5\xFD\x89\xF5\x12\x3C\x92\x78\x96\xD6\xDC\x74\x6E\x93\x44\x61\xD1\x8D\xC7\x46\xB2\x75\x0E\x86\xE8\x19\x8A\xD5\x6D\x6C\xD5\x78\x16\x95\xA2\xE9\xC8\x0A\x38\xEB\xF2\x24\x13\x4F\x73\x54\x93\x13\x85\x3A\x1B\xBC\x1E\x34\xB5\x8B\x05\x8C\xB9\x77\x8B\xB1\xDB\x1F\x20\x91\xAB\x09\x53\x6E\x90\xCE\x7B\x37\x74\xB9\x70\x47\x91\x22\x51\x63\x16\x79\xAE\xB1\xAE\x41\x26\x08\xC8\x19\x2B\xD1\x46\xAA\x48\xD6\x64\x2A\xD7\x83\x34\xFF\x2C\x2A\xC1\x6C\x19\x43\x4A\x07\x85\xE7\xD3\x7C\xF6\x21\x68\xEF\xEA\xF2\x52\x9F\x7F\x93\x90\xCF\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x60\x7B\x66\x1A\x45\x0D\x97\xCA\x89\x50\x2F\x7D\x04\xCD\x34\xA8\xFF\xFC\xFD\x4B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xD6\x73\xE7\x7C\x4F\x76\xD0\x8D\xBF\xEC\xBA\xA2\xBE\x34\xC5\x28\x32\xB5\x7C\xFC\x6C\x9C\x2C\x2B\xBD\x09\x9E\x53\xBF\x6B\x5E\xAA\x11\x48\xB6\xE5\x08\xA3\xB3\xCA\x3D\x61\x4D\xD3\x46\x09\xB3\x3E\xC3\xA0\xE3\x63\x55\x1B\xF2\xBA\xEF\xAD\x39\xE1\x43\xB9\x38\xA3\xE6\x2F\x8A\x26\x3B\xEF\xA0\x50\x56\xF9\xC6\x0A\xFD\x38\xCD\xC4\x0B\x70\x51\x94\x97\x98\x04\xDF\xC3\x5F\x94\xD5\x15\xC9\x14\x41\x9C\xC4\x5D\x75\x64\x15\x0D\xFF\x55\x30\xEC\x86\x8F\xFF\x0D\xEF\x2C\xB9\x63\x46\xF6\xAA\xFC\xDF\xBC\x69\xFD\x2E\x12\x48\x64\x9A\xE0\x95\xF0\xA6\xEF\x29\x8F\x01\xB1\x15\xB5\x0C\x1D\xA5\xFE\x69\x2C\x69\x24\x78\x1E\xB3\xA7\x1C\x71\x62\xEE\xCA\xC8\x97\xAC\x17\x5D\x8A\xC2\xF8\x47\x86\x6E\x2A\xC4\x56\x31\x95\xD0\x67\x89\x85\x2B\xF9\x6C\xA6\x5D\x46\x9D\x0C\xAA\x82\xE4\x99\x51\xDD\x70\xB7\xDB\x56\x3D\x61\xE4\x6A\xE1\x5C\xD6\xF6\xFE\x3D\xDE\x41\xCC\x07\xAE\x63\x52\xBF\x53\x53\xF4\x2B\xE9\xC7\xFD\xB6\xF7\x82\x5F\x85\xD2\x41\x18\xDB\x81\xB3\x04\x1C\xC5\x1F\xA4\x80\x6F\x15\x20\xC9\xDE\x0C\x88\x0A\x1D\xD6\x66\x55\xE2\xFC\x48\xC9\x29\x26\x69\xE0", @@ -19,11 +17,10 @@ redef root_certs += { ["CN=VeriSign Class 3 Public Primary Certification Authority - G3,OU=(c) 1999 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x04\x1A\x30\x82\x03\x02\x02\x11\x00\x9B\x7E\x06\x49\xA3\x3E\x62\xB9\xD5\xEE\x90\x48\x71\x29\xEF\x57\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xCB\xBA\x9C\x52\xFC\x78\x1F\x1A\x1E\x6F\x1B\x37\x73\xBD\xF8\xC9\x6B\x94\x12\x30\x4F\xF0\x36\x47\xF5\xD0\x91\x0A\xF5\x17\xC8\xA5\x61\xC1\x16\x40\x4D\xFB\x8A\x61\x90\xE5\x76\x20\xC1\x11\x06\x7D\xAB\x2C\x6E\xA6\xF5\x11\x41\x8E\xFA\x2D\xAD\x2A\x61\x59\xA4\x67\x26\x4C\xD0\xE8\xBC\x52\x5B\x70\x20\x04\x58\xD1\x7A\xC9\xA4\x69\xBC\x83\x17\x64\xAD\x05\x8B\xBC\xD0\x58\xCE\x8D\x8C\xF5\xEB\xF0\x42\x49\x0B\x9D\x97\x27\x67\x32\x6E\xE1\xAE\x93\x15\x1C\x70\xBC\x20\x4D\x2F\x18\xDE\x92\x88\xE8\x6C\x85\x57\x11\x1A\xE9\x7E\xE3\x26\x11\x54\xA2\x45\x96\x55\x83\xCA\x30\x89\xE8\xDC\xD8\xA3\xED\x2A\x80\x3F\x7F\x79\x65\x57\x3E\x15\x20\x66\x08\x2F\x95\x93\xBF\xAA\x47\x2F\xA8\x46\x97\xF0\x12\xE2\xFE\xC2\x0A\x2B\x51\xE6\x76\xE6\xB7\x46\xB7\xE2\x0D\xA6\xCC\xA8\xC3\x4C\x59\x55\x89\xE6\xE8\x53\x5C\x1C\xEA\x9D\xF0\x62\x16\x0B\xA7\xC9\x5F\x0C\xF0\xDE\xC2\x76\xCE\xAF\xF7\x6A\xF2\xFA\x41\xA6\xA2\x33\x14\xC9\xE5\x7A\x63\xD3\x9E\x62\x37\xD5\x85\x65\x9E\x0E\xE6\x53\x24\x74\x1B\x5E\x1D\x12\x53\x5B\xC7\x2C\xE7\x83\x49\x3B\x15\xAE\x8A\x68\xB9\x57\x97\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x11\x14\x96\xC1\xAB\x92\x08\xF7\x3F\x2F\xC9\xB2\xFE\xE4\x5A\x9F\x64\xDE\xDB\x21\x4F\x86\x99\x34\x76\x36\x57\xDD\xD0\x15\x2F\xC5\xAD\x7F\x15\x1F\x37\x62\x73\x3E\xD4\xE7\x5F\xCE\x17\x03\xDB\x35\xFA\x2B\xDB\xAE\x60\x09\x5F\x1E\x5F\x8F\x6E\xBB\x0B\x3D\xEA\x5A\x13\x1E\x0C\x60\x6F\xB5\xC0\xB5\x23\x22\x2E\x07\x0B\xCB\xA9\x74\xCB\x47\xBB\x1D\xC1\xD7\xA5\x6B\xCC\x2F\xD2\x42\xFD\x49\xDD\xA7\x89\xCF\x53\xBA\xDA\x00\x5A\x28\xBF\x82\xDF\xF8\xBA\x13\x1D\x50\x86\x82\xFD\x8E\x30\x8F\x29\x46\xB0\x1E\x3D\x35\xDA\x38\x62\x16\x18\x4A\xAD\xE6\xB6\x51\x6C\xDE\xAF\x62\xEB\x01\xD0\x1E\x24\xFE\x7A\x8F\x12\x1A\x12\x68\xB8\xFB\x66\x99\x14\x14\x45\x5C\xAE\xE7\xAE\x69\x17\x81\x2B\x5A\x37\xC9\x5E\x2A\xF4\xC6\xE2\xA1\x5C\x54\x9B\xA6\x54\x00\xCF\xF0\xF1\xC1\xC7\x98\x30\x1A\x3B\x36\x16\xDB\xA3\x6E\xEA\xFD\xAD\xB2\xC2\xDA\xEF\x02\x47\x13\x8A\xC0\xF1\xB3\x31\xAD\x4F\x1C\xE1\x4F\x9C\xAF\x0F\x0C\x9D\xF7\x78\x0D\xD8\xF4\x35\x56\x80\xDA\xB7\x6D\x17\x8F\x9D\x1E\x81\x64\xE1\xFE\xC5\x45\xBA\xAD\x6B\xB9\x0A\x7A\x4E\x4F\x4B\x84\xEE\x4B\xF1\x7D\xDD\x11", ["CN=VeriSign Class 4 Public Primary Certification Authority - G3,OU=(c) 1999 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x04\x1A\x30\x82\x03\x02\x02\x11\x00\xEC\xA0\xA7\x8B\x6E\x75\x6A\x01\xCF\xC4\x7C\xCC\x2F\x94\x5E\xD7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xAD\xCB\xA5\x11\x69\xC6\x59\xAB\xF1\x8F\xB5\x19\x0F\x56\xCE\xCC\xB5\x1F\x20\xE4\x9E\x26\x25\x4B\xE0\x73\x65\x89\x59\xDE\xD0\x83\xE4\xF5\x0F\xB5\xBB\xAD\xF1\x7C\xE8\x21\xFC\xE4\xE8\x0C\xEE\x7C\x45\x22\x19\x76\x92\xB4\x13\xB7\x20\x5B\x09\xFA\x61\xAE\xA8\xF2\xA5\x8D\x85\xC2\x2A\xD6\xDE\x66\x36\xD2\x9B\x02\xF4\xA8\x92\x60\x7C\x9C\x69\xB4\x8F\x24\x1E\xD0\x86\x52\xF6\x32\x9C\x41\x58\x1E\x22\xBD\xCD\x45\x62\x95\x08\x6E\xD0\x66\xDD\x53\xA2\xCC\xF0\x10\xDC\x54\x73\x8B\x04\xA1\x46\x33\x33\x5C\x17\x40\xB9\x9E\x4D\xD3\xF3\xBE\x55\x83\xE8\xB1\x89\x8E\x5A\x7C\x9A\x96\x22\x90\x3B\x88\x25\xF2\xD2\x53\x88\x02\x0C\x0B\x78\xF2\xE6\x37\x17\x4B\x30\x46\x07\xE4\x80\x6D\xA6\xD8\x96\x2E\xE8\x2C\xF8\x11\xB3\x38\x0D\x66\xA6\x9B\xEA\xC9\x23\x5B\xDB\x8E\xE2\xF3\x13\x8E\x1A\x59\x2D\xAA\x02\xF0\xEC\xA4\x87\x66\xDC\xC1\x3F\xF5\xD8\xB9\xF4\xEC\x82\xC6\xD2\x3D\x95\x1D\xE5\xC0\x4F\x84\xC9\xD9\xA3\x44\x28\x06\x6A\xD7\x45\xAC\xF0\x6B\x6A\xEF\x4E\x5F\xF8\x11\x82\x1E\x38\x63\x34\x66\x50\xD4\x3E\x93\x73\xFA\x30\xC3\x66\xAD\xFF\x93\x2D\x97\xEF\x03\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8F\xFA\x25\x6B\x4F\x5B\xE4\xA4\x4E\x27\x55\xAB\x22\x15\x59\x3C\xCA\xB5\x0A\xD4\x4A\xDB\xAB\xDD\xA1\x5F\x53\xC5\xA0\x57\x39\xC2\xCE\x47\x2B\xBE\x3A\xC8\x56\xBF\xC2\xD9\x27\x10\x3A\xB1\x05\x3C\xC0\x77\x31\xBB\x3A\xD3\x05\x7B\x6D\x9A\x1C\x30\x8C\x80\xCB\x93\x93\x2A\x83\xAB\x05\x51\x82\x02\x00\x11\x67\x6B\xF3\x88\x61\x47\x5F\x03\x93\xD5\x5B\x0D\xE0\xF1\xD4\xA1\x32\x35\x85\xB2\x3A\xDB\xB0\x82\xAB\xD1\xCB\x0A\xBC\x4F\x8C\x5B\xC5\x4B\x00\x3B\x1F\x2A\x82\xA6\x7E\x36\x85\xDC\x7E\x3C\x67\x00\xB5\xE4\x3B\x52\xE0\xA8\xEB\x5D\x15\xF9\xC6\x6D\xF0\xAD\x1D\x0E\x85\xB7\xA9\x9A\x73\x14\x5A\x5B\x8F\x41\x28\xC0\xD5\xE8\x2D\x4D\xA4\x5E\xCD\xAA\xD9\xED\xCE\xDC\xD8\xD5\x3C\x42\x1D\x17\xC1\x12\x5D\x45\x38\xC3\x38\xF3\xFC\x85\x2E\x83\x46\x48\xB2\xD7\x20\x5F\x92\x36\x8F\xE7\x79\x0F\x98\x5E\x99\xE8\xF0\xD0\xA4\xBB\xF5\x53\xBD\x2A\xCE\x59\xB0\xAF\x6E\x7F\x6C\xBB\xD2\x1E\x00\xB0\x21\xED\xF8\x41\x62\x82\xB9\xD8\xB2\xC4\xBB\x46\x50\xF3\x31\xC5\x8F\x01\xA8\x74\xEB\xF5\x78\x27\xDA\xE7\xF7\x66\x43\xF3\x9E\x83\x3E\x20\xAA\xC3\x35\x60\x91\xCE", ["CN=Entrust.net Secure Server Certification Authority,OU=(c) 1999 Entrust.net Limited,OU=www.entrust.net/CPS incorp. by ref. (limits liab.),O=Entrust.net,C=US"] = "\x30\x82\x04\xD8\x30\x82\x04\x41\xA0\x03\x02\x01\x02\x02\x04\x37\x4A\xD2\x43\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xC3\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x17\x0D\x31\x39\x30\x35\x32\x35\x31\x36\x33\x39\x34\x30\x5A\x30\x81\xC3\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xCD\x28\x83\x34\x54\x1B\x89\xF3\x0F\xAF\x37\x91\x31\xFF\xAF\x31\x60\xC9\xA8\xE8\xB2\x10\x68\xED\x9F\xE7\x93\x36\xF1\x0A\x64\xBB\x47\xF5\x04\x17\x3F\x23\x47\x4D\xC5\x27\x19\x81\x26\x0C\x54\x72\x0D\x88\x2D\xD9\x1F\x9A\x12\x9F\xBC\xB3\x71\xD3\x80\x19\x3F\x47\x66\x7B\x8C\x35\x28\xD2\xB9\x0A\xDF\x24\xDA\x9C\xD6\x50\x79\x81\x7A\x5A\xD3\x37\xF7\xC2\x4A\xD8\x29\x92\x26\x64\xD1\xE4\x98\x6C\x3A\x00\x8A\xF5\x34\x9B\x65\xF8\xED\xE3\x10\xFF\xFD\xB8\x49\x58\xDC\xA0\xDE\x82\x39\x6B\x81\xB1\x16\x19\x61\xB9\x54\xB6\xE6\x43\x02\x01\x03\xA3\x82\x01\xD7\x30\x82\x01\xD3\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x01\x19\x06\x03\x55\x1D\x1F\x04\x82\x01\x10\x30\x82\x01\x0C\x30\x81\xDE\xA0\x81\xDB\xA0\x81\xD8\xA4\x81\xD5\x30\x81\xD2\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x29\xA0\x27\xA0\x25\x86\x23\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x52\x4C\x2F\x6E\x65\x74\x31\x2E\x63\x72\x6C\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x81\x0F\x32\x30\x31\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xF0\x17\x62\x13\x55\x3D\xB3\xFF\x0A\x00\x6B\xFB\x50\x84\x97\xF3\xED\x62\xD0\x1A\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xF0\x17\x62\x13\x55\x3D\xB3\xFF\x0A\x00\x6B\xFB\x50\x84\x97\xF3\xED\x62\xD0\x1A\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x90\xDC\x30\x02\xFA\x64\x74\xC2\xA7\x0A\xA5\x7C\x21\x8D\x34\x17\xA8\xFB\x47\x0E\xFF\x25\x7C\x8D\x13\x0A\xFB\xE4\x98\xB5\xEF\x8C\xF8\xC5\x10\x0D\xF7\x92\xBE\xF1\xC3\xD5\xD5\x95\x6A\x04\xBB\x2C\xCE\x26\x36\x65\xC8\x31\xC6\xE7\xEE\x3F\xE3\x57\x75\x84\x7A\x11\xEF\x46\x4F\x18\xF4\xD3\x98\xBB\xA8\x87\x32\xBA\x72\xF6\x3C\xE2\x3D\x9F\xD7\x1D\xD9\xC3\x60\x43\x8C\x58\x0E\x22\x96\x2F\x62\xA3\x2C\x1F\xBA\xAD\x05\xEF\xAB\x32\x78\x87\xA0\x54\x73\x19\xB5\x5C\x05\xF9\x52\x3E\x6D\x2D\x45\x0B\xF7\x0A\x93\xEA\xED\x06\xF9\xB2", - ["CN=Entrust.net Certification Authority (2048),OU=(c) 1999 Entrust.net Limited,OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),O=Entrust.net"] = "\x30\x82\x04\x5C\x30\x82\x03\x44\xA0\x03\x02\x01\x02\x02\x04\x38\x63\xB9\x66\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xB4\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x40\x30\x3E\x06\x03\x55\x04\x0B\x14\x37\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x5F\x32\x30\x34\x38\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2A\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x1E\x17\x0D\x39\x39\x31\x32\x32\x34\x31\x37\x35\x30\x35\x31\x5A\x17\x0D\x31\x39\x31\x32\x32\x34\x31\x38\x32\x30\x35\x31\x5A\x30\x81\xB4\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x40\x30\x3E\x06\x03\x55\x04\x0B\x14\x37\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x5F\x32\x30\x34\x38\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2A\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xAD\x4D\x4B\xA9\x12\x86\xB2\xEA\xA3\x20\x07\x15\x16\x64\x2A\x2B\x4B\xD1\xBF\x0B\x4A\x4D\x8E\xED\x80\x76\xA5\x67\xB7\x78\x40\xC0\x73\x42\xC8\x68\xC0\xDB\x53\x2B\xDD\x5E\xB8\x76\x98\x35\x93\x8B\x1A\x9D\x7C\x13\x3A\x0E\x1F\x5B\xB7\x1E\xCF\xE5\x24\x14\x1E\xB1\x81\xA9\x8D\x7D\xB8\xCC\x6B\x4B\x03\xF1\x02\x0C\xDC\xAB\xA5\x40\x24\x00\x7F\x74\x94\xA1\x9D\x08\x29\xB3\x88\x0B\xF5\x87\x77\x9D\x55\xCD\xE4\xC3\x7E\xD7\x6A\x64\xAB\x85\x14\x86\x95\x5B\x97\x32\x50\x6F\x3D\xC8\xBA\x66\x0C\xE3\xFC\xBD\xB8\x49\xC1\x76\x89\x49\x19\xFD\xC0\xA8\xBD\x89\xA3\x67\x2F\xC6\x9F\xBC\x71\x19\x60\xB8\x2D\xE9\x2C\xC9\x90\x76\x66\x7B\x94\xE2\xAF\x78\xD6\x65\x53\x5D\x3C\xD6\x9C\xB2\xCF\x29\x03\xF9\x2F\xA4\x50\xB2\xD4\x48\xCE\x05\x32\x55\x8A\xFD\xB2\x64\x4C\x0E\xE4\x98\x07\x75\xDB\x7F\xDF\xB9\x08\x55\x60\x85\x30\x29\xF9\x7B\x48\xA4\x69\x86\xE3\x35\x3F\x1E\x86\x5D\x7A\x7A\x15\xBD\xEF\x00\x8E\x15\x22\x54\x17\x00\x90\x26\x93\xBC\x0E\x49\x68\x91\xBF\xF8\x47\xD3\x9D\x95\x42\xC1\x0E\x4D\xDF\x6F\x26\xCF\xC3\x18\x21\x62\x66\x43\x70\xD6\xD5\xC0\x07\xE1\x02\x03\x01\x00\x01\xA3\x74\x30\x72\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x55\xE4\x81\xD1\x11\x80\xBE\xD8\x89\xB9\x08\xA3\x31\xF9\xA1\x24\x09\x16\xB9\x70\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x55\xE4\x81\xD1\x11\x80\xBE\xD8\x89\xB9\x08\xA3\x31\xF9\xA1\x24\x09\x16\xB9\x70\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x35\x2E\x30\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x59\x47\xAC\x21\x84\x8A\x17\xC9\x9C\x89\x53\x1E\xBA\x80\x85\x1A\xC6\x3C\x4E\x3E\xB1\x9C\xB6\x7C\xC6\x92\x5D\x18\x64\x02\xE3\xD3\x06\x08\x11\x61\x7C\x63\xE3\x2B\x9D\x31\x03\x70\x76\xD2\xA3\x28\xA0\xF4\xBB\x9A\x63\x73\xED\x6D\xE5\x2A\xDB\xED\x14\xA9\x2B\xC6\x36\x11\xD0\x2B\xEB\x07\x8B\xA5\xDA\x9E\x5C\x19\x9D\x56\x12\xF5\x54\x29\xC8\x05\xED\xB2\x12\x2A\x8D\xF4\x03\x1B\xFF\xE7\x92\x10\x87\xB0\x3A\xB5\xC3\x9D\x05\x37\x12\xA3\xC7\xF4\x15\xB9\xD5\xA4\x39\x16\x9B\x53\x3A\x23\x91\xF1\xA8\x82\xA2\x6A\x88\x68\xC1\x79\x02\x22\xBC\xAA\xA6\xD6\xAE\xDF\xB0\x14\x5F\xB8\x87\xD0\xDD\x7C\x7F\x7B\xFF\xAF\x1C\xCF\xE6\xDB\x07\xAD\x5E\xDB\x85\x9D\xD0\x2B\x0D\x33\xDB\x04\xD1\xE6\x49\x40\x13\x2B\x76\xFB\x3E\xE9\x9C\x89\x0F\x15\xCE\x18\xB0\x85\x78\x21\x4F\x6B\x4F\x0E\xFA\x36\x67\xCD\x07\xF2\xFF\x08\xD0\xE2\xDE\xD9\xBF\x2A\xAF\xB8\x87\x86\x21\x3C\x04\xCA\xB7\x94\x68\x7F\xCF\x3C\xE9\x98\xD7\x38\xFF\xEC\xC0\xD9\x50\xF0\x2E\x4B\x58\xAE\x46\x6F\xD0\x2E\xC3\x60\xDA\x72\x55\x72\xBD\x4C\x45\x9E\x61\xBA\xBF\x84\x81\x92\x03\xD1\xD2\x69\x7C\xC5", + ["CN=Entrust.net Certification Authority (2048),OU=(c) 1999 Entrust.net Limited,OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),O=Entrust.net"] = "\x30\x82\x04\x2A\x30\x82\x03\x12\xA0\x03\x02\x01\x02\x02\x04\x38\x63\xDE\xF8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xB4\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x40\x30\x3E\x06\x03\x55\x04\x0B\x14\x37\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x5F\x32\x30\x34\x38\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2A\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x1E\x17\x0D\x39\x39\x31\x32\x32\x34\x31\x37\x35\x30\x35\x31\x5A\x17\x0D\x32\x39\x30\x37\x32\x34\x31\x34\x31\x35\x31\x32\x5A\x30\x81\xB4\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x40\x30\x3E\x06\x03\x55\x04\x0B\x14\x37\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x5F\x32\x30\x34\x38\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2A\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xAD\x4D\x4B\xA9\x12\x86\xB2\xEA\xA3\x20\x07\x15\x16\x64\x2A\x2B\x4B\xD1\xBF\x0B\x4A\x4D\x8E\xED\x80\x76\xA5\x67\xB7\x78\x40\xC0\x73\x42\xC8\x68\xC0\xDB\x53\x2B\xDD\x5E\xB8\x76\x98\x35\x93\x8B\x1A\x9D\x7C\x13\x3A\x0E\x1F\x5B\xB7\x1E\xCF\xE5\x24\x14\x1E\xB1\x81\xA9\x8D\x7D\xB8\xCC\x6B\x4B\x03\xF1\x02\x0C\xDC\xAB\xA5\x40\x24\x00\x7F\x74\x94\xA1\x9D\x08\x29\xB3\x88\x0B\xF5\x87\x77\x9D\x55\xCD\xE4\xC3\x7E\xD7\x6A\x64\xAB\x85\x14\x86\x95\x5B\x97\x32\x50\x6F\x3D\xC8\xBA\x66\x0C\xE3\xFC\xBD\xB8\x49\xC1\x76\x89\x49\x19\xFD\xC0\xA8\xBD\x89\xA3\x67\x2F\xC6\x9F\xBC\x71\x19\x60\xB8\x2D\xE9\x2C\xC9\x90\x76\x66\x7B\x94\xE2\xAF\x78\xD6\x65\x53\x5D\x3C\xD6\x9C\xB2\xCF\x29\x03\xF9\x2F\xA4\x50\xB2\xD4\x48\xCE\x05\x32\x55\x8A\xFD\xB2\x64\x4C\x0E\xE4\x98\x07\x75\xDB\x7F\xDF\xB9\x08\x55\x60\x85\x30\x29\xF9\x7B\x48\xA4\x69\x86\xE3\x35\x3F\x1E\x86\x5D\x7A\x7A\x15\xBD\xEF\x00\x8E\x15\x22\x54\x17\x00\x90\x26\x93\xBC\x0E\x49\x68\x91\xBF\xF8\x47\xD3\x9D\x95\x42\xC1\x0E\x4D\xDF\x6F\x26\xCF\xC3\x18\x21\x62\x66\x43\x70\xD6\xD5\xC0\x07\xE1\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x55\xE4\x81\xD1\x11\x80\xBE\xD8\x89\xB9\x08\xA3\x31\xF9\xA1\x24\x09\x16\xB9\x70\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3B\x9B\x8F\x56\x9B\x30\xE7\x53\x99\x7C\x7A\x79\xA7\x4D\x97\xD7\x19\x95\x90\xFB\x06\x1F\xCA\x33\x7C\x46\x63\x8F\x96\x66\x24\xFA\x40\x1B\x21\x27\xCA\xE6\x72\x73\xF2\x4F\xFE\x31\x99\xFD\xC8\x0C\x4C\x68\x53\xC6\x80\x82\x13\x98\xFA\xB6\xAD\xDA\x5D\x3D\xF1\xCE\x6E\xF6\x15\x11\x94\x82\x0C\xEE\x3F\x95\xAF\x11\xAB\x0F\xD7\x2F\xDE\x1F\x03\x8F\x57\x2C\x1E\xC9\xBB\x9A\x1A\x44\x95\xEB\x18\x4F\xA6\x1F\xCD\x7D\x57\x10\x2F\x9B\x04\x09\x5A\x84\xB5\x6E\xD8\x1D\x3A\xE1\xD6\x9E\xD1\x6C\x79\x5E\x79\x1C\x14\xC5\xE3\xD0\x4C\x93\x3B\x65\x3C\xED\xDF\x3D\xBE\xA6\xE5\x95\x1A\xC3\xB5\x19\xC3\xBD\x5E\x5B\xBB\xFF\x23\xEF\x68\x19\xCB\x12\x93\x27\x5C\x03\x2D\x6F\x30\xD0\x1E\xB6\x1A\xAC\xDE\x5A\xF7\xD1\xAA\xA8\x27\xA6\xFE\x79\x81\xC4\x79\x99\x33\x57\xBA\x12\xB0\xA9\xE0\x42\x6C\x93\xCA\x56\xDE\xFE\x6D\x84\x0B\x08\x8B\x7E\x8D\xEA\xD7\x98\x21\xC6\xF3\xE7\x3C\x79\x2F\x5E\x9C\xD1\x4C\x15\x8D\xE1\xEC\x22\x37\xCC\x9A\x43\x0B\x97\xDC\x80\x90\x8D\xB3\x67\x9B\x6F\x48\x08\x15\x56\xCF\xBF\xF1\x2B\x7C\x5E\x9A\x76\xE9\x59\x90\xC5\x7C\x83\x35\x11\x65\x51", ["CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE"] = "\x30\x82\x03\x77\x30\x82\x02\x5F\xA0\x03\x02\x01\x02\x02\x04\x02\x00\x00\xB9\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x45\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x13\x09\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x31\x13\x30\x11\x06\x03\x55\x04\x0B\x13\x0A\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x31\x32\x31\x38\x34\x36\x30\x30\x5A\x17\x0D\x32\x35\x30\x35\x31\x32\x32\x33\x35\x39\x30\x30\x5A\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x45\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x13\x09\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x31\x13\x30\x11\x06\x03\x55\x04\x0B\x13\x0A\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xA3\x04\xBB\x22\xAB\x98\x3D\x57\xE8\x26\x72\x9A\xB5\x79\xD4\x29\xE2\xE1\xE8\x95\x80\xB1\xB0\xE3\x5B\x8E\x2B\x29\x9A\x64\xDF\xA1\x5D\xED\xB0\x09\x05\x6D\xDB\x28\x2E\xCE\x62\xA2\x62\xFE\xB4\x88\xDA\x12\xEB\x38\xEB\x21\x9D\xC0\x41\x2B\x01\x52\x7B\x88\x77\xD3\x1C\x8F\xC7\xBA\xB9\x88\xB5\x6A\x09\xE7\x73\xE8\x11\x40\xA7\xD1\xCC\xCA\x62\x8D\x2D\xE5\x8F\x0B\xA6\x50\xD2\xA8\x50\xC3\x28\xEA\xF5\xAB\x25\x87\x8A\x9A\x96\x1C\xA9\x67\xB8\x3F\x0C\xD5\xF7\xF9\x52\x13\x2F\xC2\x1B\xD5\x70\x70\xF0\x8F\xC0\x12\xCA\x06\xCB\x9A\xE1\xD9\xCA\x33\x7A\x77\xD6\xF8\xEC\xB9\xF1\x68\x44\x42\x48\x13\xD2\xC0\xC2\xA4\xAE\x5E\x60\xFE\xB6\xA6\x05\xFC\xB4\xDD\x07\x59\x02\xD4\x59\x18\x98\x63\xF5\xA5\x63\xE0\x90\x0C\x7D\x5D\xB2\x06\x7A\xF3\x85\xEA\xEB\xD4\x03\xAE\x5E\x84\x3E\x5F\xFF\x15\xED\x69\xBC\xF9\x39\x36\x72\x75\xCF\x77\x52\x4D\xF3\xC9\x90\x2C\xB9\x3D\xE5\xC9\x23\x53\x3F\x1F\x24\x98\x21\x5C\x07\x99\x29\xBD\xC6\x3A\xEC\xE7\x6E\x86\x3A\x6B\x97\x74\x63\x33\xBD\x68\x18\x31\xF0\x78\x8D\x76\xBF\xFC\x9E\x8E\x5D\x2A\x86\xA7\x4D\x90\xDC\x27\x1A\x39\x02\x03\x01\x00\x01\xA3\x45\x30\x43\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE5\x9D\x59\x30\x82\x47\x58\xCC\xAC\xFA\x08\x54\x36\x86\x7B\x3A\xB5\x04\x4D\xF0\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x03\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x85\x0C\x5D\x8E\xE4\x6F\x51\x68\x42\x05\xA0\xDD\xBB\x4F\x27\x25\x84\x03\xBD\xF7\x64\xFD\x2D\xD7\x30\xE3\xA4\x10\x17\xEB\xDA\x29\x29\xB6\x79\x3F\x76\xF6\x19\x13\x23\xB8\x10\x0A\xF9\x58\xA4\xD4\x61\x70\xBD\x04\x61\x6A\x12\x8A\x17\xD5\x0A\xBD\xC5\xBC\x30\x7C\xD6\xE9\x0C\x25\x8D\x86\x40\x4F\xEC\xCC\xA3\x7E\x38\xC6\x37\x11\x4F\xED\xDD\x68\x31\x8E\x4C\xD2\xB3\x01\x74\xEE\xBE\x75\x5E\x07\x48\x1A\x7F\x70\xFF\x16\x5C\x84\xC0\x79\x85\xB8\x05\xFD\x7F\xBE\x65\x11\xA3\x0F\xC0\x02\xB4\xF8\x52\x37\x39\x04\xD5\xA9\x31\x7A\x18\xBF\xA0\x2A\xF4\x12\x99\xF7\xA3\x45\x82\xE3\x3C\x5E\xF5\x9D\x9E\xB5\xC8\x9E\x7C\x2E\xC8\xA4\x9E\x4E\x08\x14\x4B\x6D\xFD\x70\x6D\x6B\x1A\x63\xBD\x64\xE6\x1F\xB7\xCE\xF0\xF2\x9F\x2E\xBB\x1B\xB7\xF2\x50\x88\x73\x92\xC2\xE2\xE3\x16\x8D\x9A\x32\x02\xAB\x8E\x18\xDD\xE9\x10\x11\xEE\x7E\x35\xAB\x90\xAF\x3E\x30\x94\x7A\xD0\x33\x3D\xA7\x65\x0F\xF5\xFC\x8E\x9E\x62\xCF\x47\x44\x2C\x01\x5D\xBB\x1D\xB5\x32\xD2\x47\xD2\x38\x2E\xD0\xFE\x81\xDC\x32\x6A\x1E\xB5\xEE\x3C\xD5\xFC\xE7\x81\x1D\x19\xC3\x24\x42\xEA\x63\x39\xA9", ["CN=Equifax Secure Global eBusiness CA-1,O=Equifax Secure Inc.,C=US"] = "\x30\x82\x02\x90\x30\x82\x01\xF9\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xBA\xE7\x17\x90\x02\x65\xB1\x34\x55\x3C\x49\xC2\x51\xD5\xDF\xA7\xD1\x37\x8F\xD1\xE7\x81\x73\x41\x52\x60\x9B\x9D\xA1\x17\x26\x78\xAD\xC7\xB1\xE8\x26\x94\x32\xB5\xDE\x33\x8D\x3A\x2F\xDB\xF2\x9A\x7A\x5A\x73\x98\xA3\x5C\xE9\xFB\x8A\x73\x1B\x5C\xE7\xC3\xBF\x80\x6C\xCD\xA9\xF4\xD6\x2B\xC0\xF7\xF9\x99\xAA\x63\xA2\xB1\x47\x02\x0F\xD4\xE4\x51\x3A\x12\x3C\x6C\x8A\x5A\x54\x84\x70\xDB\xC1\xC5\x90\xCF\x72\x45\xCB\xA8\x59\xC0\xCD\x33\x9D\x3F\xA3\x96\xEB\x85\x33\x21\x1C\x3E\x1E\x3E\x60\x6E\x76\x9C\x67\x85\xC5\xC8\xC3\x61\x02\x03\x01\x00\x01\xA3\x66\x30\x64\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xBE\xA8\xA0\x74\x72\x50\x6B\x44\xB7\xC9\x23\xD8\xFB\xA8\xFF\xB3\x57\x6B\x68\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xBE\xA8\xA0\x74\x72\x50\x6B\x44\xB7\xC9\x23\xD8\xFB\xA8\xFF\xB3\x57\x6B\x68\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x30\xE2\x01\x51\xAA\xC7\xEA\x5F\xDA\xB9\xD0\x65\x0F\x30\xD6\x3E\xDA\x0D\x14\x49\x6E\x91\x93\x27\x14\x31\xEF\xC4\xF7\x2D\x45\xF8\xEC\xC7\xBF\xA2\x41\x0D\x23\xB4\x92\xF9\x19\x00\x67\xBD\x01\xAF\xCD\xE0\x71\xFC\x5A\xCF\x64\xC4\xE0\x96\x98\xD0\xA3\x40\xE2\x01\x8A\xEF\x27\x07\xF1\x65\x01\x8A\x44\x2D\x06\x65\x75\x52\xC0\x86\x10\x20\x21\x5F\x6C\x6B\x0F\x6C\xAE\x09\x1C\xAF\xF2\xA2\x18\x34\xC4\x75\xA4\x73\x1C\xF1\x8D\xDC\xEF\xAD\xF9\xB3\x76\xB4\x92\xBF\xDC\x95\x10\x1E\xBE\xCB\xC8\x3B\x5A\x84\x60\x19\x56\x94\xA9\x55", ["CN=Equifax Secure eBusiness CA-1,O=Equifax Secure Inc.,C=US"] = "\x30\x82\x02\x82\x30\x82\x01\xEB\xA0\x03\x02\x01\x02\x02\x01\x04\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x30\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xCE\x2F\x19\xBC\x17\xB7\x77\xDE\x93\xA9\x5F\x5A\x0D\x17\x4F\x34\x1A\x0C\x98\xF4\x22\xD9\x59\xD4\xC4\x68\x46\xF0\xB4\x35\xC5\x85\x03\x20\xC6\xAF\x45\xA5\x21\x51\x45\x41\xEB\x16\x58\x36\x32\x6F\xE2\x50\x62\x64\xF9\xFD\x51\x9C\xAA\x24\xD9\xF4\x9D\x83\x2A\x87\x0A\x21\xD3\x12\x38\x34\x6C\x8D\x00\x6E\x5A\xA0\xD9\x42\xEE\x1A\x21\x95\xF9\x52\x4C\x55\x5A\xC5\x0F\x38\x4F\x46\xFA\x6D\xF8\x2E\x35\xD6\x1D\x7C\xEB\xE2\xF0\xB0\x75\x80\xC8\xA9\x13\xAC\xBE\x88\xEF\x3A\x6E\xAB\x5F\x2A\x38\x62\x02\xB0\x12\x7B\xFE\x8F\xA6\x03\x02\x03\x01\x00\x01\xA3\x66\x30\x64\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x4A\x78\x32\x52\x11\xDB\x59\x16\x36\x5E\xDF\xC1\x14\x36\x40\x6A\x47\x7C\x4C\xA1\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4A\x78\x32\x52\x11\xDB\x59\x16\x36\x5E\xDF\xC1\x14\x36\x40\x6A\x47\x7C\x4C\xA1\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x75\x5B\xA8\x9B\x03\x11\xE6\xE9\x56\x4C\xCD\xF9\xA9\x4C\xC0\x0D\x9A\xF3\xCC\x65\x69\xE6\x25\x76\xCC\x59\xB7\xD6\x54\xC3\x1D\xCD\x99\xAC\x19\xDD\xB4\x85\xD5\xE0\x3D\xFC\x62\x20\xA7\x84\x4B\x58\x65\xF1\xE2\xF9\x95\x21\x3F\xF5\xD4\x7E\x58\x1E\x47\x87\x54\x3E\x58\xA1\xB5\xB5\xF8\x2A\xEF\x71\xE7\xBC\xC3\xF6\xB1\x49\x46\xE2\xD7\xA0\x6B\xE5\x56\x7A\x9A\x27\x98\x7C\x46\x62\x14\xE7\xC9\xFC\x6E\x03\x12\x79\x80\x38\x1D\x48\x82\x8D\xFC\x17\xFE\x2A\x96\x2B\xB5\x62\xA6\xA6\x3D\xBD\x7F\x92\x59\xCD\x5A\x2A\x82\xB2\x37\x79", - ["OU=Equifax Secure eBusiness CA-2,O=Equifax Secure,C=US"] = "\x30\x82\x03\x20\x30\x82\x02\x89\xA0\x03\x02\x01\x02\x02\x04\x37\x70\xCF\xB5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x17\x0D\x31\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xE4\x39\x39\x93\x1E\x52\x06\x1B\x28\x36\xF8\xB2\xA3\x29\xC5\xED\x8E\xB2\x11\xBD\xFE\xEB\xE7\xB4\x74\xC2\x8F\xFF\x05\xE7\xD9\x9D\x06\xBF\x12\xC8\x3F\x0E\xF2\xD6\xD1\x24\xB2\x11\xDE\xD1\x73\x09\x8A\xD4\xB1\x2C\x98\x09\x0D\x1E\x50\x46\xB2\x83\xA6\x45\x8D\x62\x68\xBB\x85\x1B\x20\x70\x32\xAA\x40\xCD\xA6\x96\x5F\xC4\x71\x37\x3F\x04\xF3\xB7\x41\x24\x39\x07\x1A\x1E\x2E\x61\x58\xA0\x12\x0B\xE5\xA5\xDF\xC5\xAB\xEA\x37\x71\xCC\x1C\xC8\x37\x3A\xB9\x97\x52\xA7\xAC\xC5\x6A\x24\x94\x4E\x9C\x7B\xCF\xC0\x6A\xD6\xDF\x21\xBD\x02\x03\x01\x00\x01\xA3\x82\x01\x09\x30\x82\x01\x05\x30\x70\x06\x03\x55\x1D\x1F\x04\x69\x30\x67\x30\x65\xA0\x63\xA0\x61\xA4\x5F\x30\x5D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x1A\x06\x03\x55\x1D\x10\x04\x13\x30\x11\x81\x0F\x32\x30\x31\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x50\x9E\x0B\xEA\xAF\x5E\xB9\x20\x48\xA6\x50\x6A\xCB\xFD\xD8\x20\x7A\xA7\x82\x76\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x50\x9E\x0B\xEA\xAF\x5E\xB9\x20\x48\xA6\x50\x6A\xCB\xFD\xD8\x20\x7A\xA7\x82\x76\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x1A\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0D\x30\x0B\x1B\x05\x56\x33\x2E\x30\x63\x03\x02\x06\xC0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x0C\x86\x82\xAD\xE8\x4E\x1A\xF5\x8E\x89\x27\xE2\x35\x58\x3D\x29\xB4\x07\x8F\x36\x50\x95\xBF\x6E\xC1\x9E\xEB\xC4\x90\xB2\x85\xA8\xBB\xB7\x42\xE0\x0F\x07\x39\xDF\xFB\x9E\x90\xB2\xD1\xC1\x3E\x53\x9F\x03\x44\xB0\x7E\x4B\xF4\x6F\xE4\x7C\x1F\xE7\xE2\xB1\xE4\xB8\x9A\xEF\xC3\xBD\xCE\xDE\x0B\x32\x34\xD9\xDE\x28\xED\x33\x6B\xC4\xD4\xD7\x3D\x12\x58\xAB\x7D\x09\x2D\xCB\x70\xF5\x13\x8A\x94\xA1\x27\xA4\xD6\x70\xC5\x6D\x94\xB5\xC9\x7D\x9D\xA0\xD2\xC6\x08\x49\xD9\x66\x9B\xA6\xD3\xF4\x0B\xDC\xC5\x26\x57\xE1\x91\x30\xEA\xCD", ["CN=AddTrust Class 1 CA Root,OU=AddTrust TTP Network,O=AddTrust AB,C=SE"] = "\x30\x82\x04\x18\x30\x82\x03\x00\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x33\x38\x33\x31\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x33\x38\x33\x31\x5A\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\x96\x96\xD4\x21\x49\x60\xE2\x6B\xE8\x41\x07\x0C\xDE\xC4\xE0\xDC\x13\x23\xCD\xC1\x35\xC7\xFB\xD6\x4E\x11\x0A\x67\x5E\xF5\x06\x5B\x6B\xA5\x08\x3B\x5B\x29\x16\x3A\xE7\x87\xB2\x34\x06\xC5\xBC\x05\xA5\x03\x7C\x82\xCB\x29\x10\xAE\xE1\x88\x81\xBD\xD6\x9E\xD3\xFE\x2D\x56\xC1\x15\xCE\xE3\x26\x9D\x15\x2E\x10\xFB\x06\x8F\x30\x04\xDE\xA7\xB4\x63\xB4\xFF\xB1\x9C\xAE\x3C\xAF\x77\xB6\x56\xC5\xB5\xAB\xA2\xE9\x69\x3A\x3D\x0E\x33\x79\x32\x3F\x70\x82\x92\x99\x61\x6D\x8D\x30\x08\x8F\x71\x3F\xA6\x48\x57\x19\xF8\x25\xDC\x4B\x66\x5C\xA5\x74\x8F\x98\xAE\xC8\xF9\xC0\x06\x22\xE7\xAC\x73\xDF\xA5\x2E\xFB\x52\xDC\xB1\x15\x65\x20\xFA\x35\x66\x69\xDE\xDF\x2C\xF1\x6E\xBC\x30\xDB\x2C\x24\x12\xDB\xEB\x35\x35\x68\x90\xCB\x00\xB0\x97\x21\x3D\x74\x21\x23\x65\x34\x2B\xBB\x78\x59\xA3\xD6\xE1\x76\x39\x9A\xA4\x49\x8E\x8C\x74\xAF\x6E\xA4\x9A\xA3\xD9\x9B\xD2\x38\x5C\x9B\xA2\x18\xCC\x75\x23\x84\xBE\xEB\xE2\x4D\x33\x71\x8E\x1A\xF0\xC2\xF8\xC7\x1D\xA2\xAD\x03\x97\x2C\xF8\xCF\x25\xC6\xF6\xB8\x24\x31\xB1\x63\x5D\x92\x7F\x63\xF0\x25\xC9\x53\x2E\x1F\xBF\x4D\x02\x03\x01\x00\x01\xA3\x81\xD2\x30\x81\xCF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x95\xB1\xB4\xF0\x94\xB6\xBD\xC7\xDA\xD1\x11\x09\x21\xBE\xC1\xAF\x49\xFD\x10\x7B\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x8F\x06\x03\x55\x1D\x23\x04\x81\x87\x30\x81\x84\x80\x14\x95\xB1\xB4\xF0\x94\xB6\xBD\xC7\xDA\xD1\x11\x09\x21\xBE\xC1\xAF\x49\xFD\x10\x7B\xA1\x69\xA4\x67\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x2C\x6D\x64\x1B\x1F\xCD\x0D\xDD\xB9\x01\xFA\x96\x63\x34\x32\x48\x47\x99\xAE\x97\xED\xFD\x72\x16\xA6\x73\x47\x5A\xF4\xEB\xDD\xE9\xF5\xD6\xFB\x45\xCC\x29\x89\x44\x5D\xBF\x46\x39\x3D\xE8\xEE\xBC\x4D\x54\x86\x1E\x1D\x6C\xE3\x17\x27\x43\xE1\x89\x56\x2B\xA9\x6F\x72\x4E\x49\x33\xE3\x72\x7C\x2A\x23\x9A\xBC\x3E\xFF\x28\x2A\xED\xA3\xFF\x1C\x23\xBA\x43\x57\x09\x67\x4D\x4B\x62\x06\x2D\xF8\xFF\x6C\x9D\x60\x1E\xD8\x1C\x4B\x7D\xB5\x31\x2F\xD9\xD0\x7C\x5D\xF8\xDE\x6B\x83\x18\x78\x37\x57\x2F\xE8\x33\x07\x67\xDF\x1E\xC7\x6B\x2A\x95\x76\xAE\x8F\x57\xA3\xF0\xF4\x52\xB4\xA9\x53\x08\xCF\xE0\x4F\xD3\x7A\x53\x8B\xFD\xBB\x1C\x56\x36\xF2\xFE\xB2\xB6\xE5\x76\xBB\xD5\x22\x65\xA7\x3F\xFE\xD1\x66\xAD\x0B\xBC\x6B\x99\x86\xEF\x3F\x7D\xF3\x18\x32\xCA\x7B\xC6\xE3\xAB\x64\x46\x95\xF8\x26\x69\xD9\x55\x83\x7B\x2C\x96\x07\xFF\x59\x2C\x44\xA3\xC6\xE5\xE9\xA9\xDC\xA1\x63\x80\x5A\x21\x5E\x21\xCF\x53\x54\xF0\xBA\x6F\x89\xDB\xA8\xAA\x95\xCF\x8B\xE3\x71\xCC\x1E\x1B\x20\x44\x08\xC0\x7A\xB6\x40\xFD\xC4\xE4\x35\xE1\x1D\x16\x1C\xD0\xBC\x2B\x8E\xD6\x71\xD9", ["CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE"] = "\x30\x82\x04\x36\x30\x82\x03\x1E\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x34\x38\x33\x38\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x34\x38\x33\x38\x5A\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xB7\xF7\x1A\x33\xE6\xF2\x00\x04\x2D\x39\xE0\x4E\x5B\xED\x1F\xBC\x6C\x0F\xCD\xB5\xFA\x23\xB6\xCE\xDE\x9B\x11\x33\x97\xA4\x29\x4C\x7D\x93\x9F\xBD\x4A\xBC\x93\xED\x03\x1A\xE3\x8F\xCF\xE5\x6D\x50\x5A\xD6\x97\x29\x94\x5A\x80\xB0\x49\x7A\xDB\x2E\x95\xFD\xB8\xCA\xBF\x37\x38\x2D\x1E\x3E\x91\x41\xAD\x70\x56\xC7\xF0\x4F\x3F\xE8\x32\x9E\x74\xCA\xC8\x90\x54\xE9\xC6\x5F\x0F\x78\x9D\x9A\x40\x3C\x0E\xAC\x61\xAA\x5E\x14\x8F\x9E\x87\xA1\x6A\x50\xDC\xD7\x9A\x4E\xAF\x05\xB3\xA6\x71\x94\x9C\x71\xB3\x50\x60\x0A\xC7\x13\x9D\x38\x07\x86\x02\xA8\xE9\xA8\x69\x26\x18\x90\xAB\x4C\xB0\x4F\x23\xAB\x3A\x4F\x84\xD8\xDF\xCE\x9F\xE1\x69\x6F\xBB\xD7\x42\xD7\x6B\x44\xE4\xC7\xAD\xEE\x6D\x41\x5F\x72\x5A\x71\x08\x37\xB3\x79\x65\xA4\x59\xA0\x94\x37\xF7\x00\x2F\x0D\xC2\x92\x72\xDA\xD0\x38\x72\xDB\x14\xA8\x45\xC4\x5D\x2A\x7D\xB7\xB4\xD6\xC4\xEE\xAC\xCD\x13\x44\xB7\xC9\x2B\xDD\x43\x00\x25\xFA\x61\xB9\x69\x6A\x58\x23\x11\xB7\xA7\x33\x8F\x56\x75\x59\xF5\xCD\x29\xD7\x46\xB7\x0A\x2B\x65\xB6\xD3\x42\x6F\x15\xB2\xB8\x7B\xFB\xEF\xE9\x5D\x53\xD5\x34\x5A\x27\x02\x03\x01\x00\x01\xA3\x81\xDC\x30\x81\xD9\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xAD\xBD\x98\x7A\x34\xB4\x26\xF7\xFA\xC4\x26\x54\xEF\x03\xBD\xE0\x24\xCB\x54\x1A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x99\x06\x03\x55\x1D\x23\x04\x81\x91\x30\x81\x8E\x80\x14\xAD\xBD\x98\x7A\x34\xB4\x26\xF7\xFA\xC4\x26\x54\xEF\x03\xBD\xE0\x24\xCB\x54\x1A\xA1\x73\xA4\x71\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xB0\x9B\xE0\x85\x25\xC2\xD6\x23\xE2\x0F\x96\x06\x92\x9D\x41\x98\x9C\xD9\x84\x79\x81\xD9\x1E\x5B\x14\x07\x23\x36\x65\x8F\xB0\xD8\x77\xBB\xAC\x41\x6C\x47\x60\x83\x51\xB0\xF9\x32\x3D\xE7\xFC\xF6\x26\x13\xC7\x80\x16\xA5\xBF\x5A\xFC\x87\xCF\x78\x79\x89\x21\x9A\xE2\x4C\x07\x0A\x86\x35\xBC\xF2\xDE\x51\xC4\xD2\x96\xB7\xDC\x7E\x4E\xEE\x70\xFD\x1C\x39\xEB\x0C\x02\x51\x14\x2D\x8E\xBD\x16\xE0\xC1\xDF\x46\x75\xE7\x24\xAD\xEC\xF4\x42\xB4\x85\x93\x70\x10\x67\xBA\x9D\x06\x35\x4A\x18\xD3\x2B\x7A\xCC\x51\x42\xA1\x7A\x63\xD1\xE6\xBB\xA1\xC5\x2B\xC2\x36\xBE\x13\x0D\xE6\xBD\x63\x7E\x79\x7B\xA7\x09\x0D\x40\xAB\x6A\xDD\x8F\x8A\xC3\xF6\xF6\x8C\x1A\x42\x05\x51\xD4\x45\xF5\x9F\xA7\x62\x21\x68\x15\x20\x43\x3C\x99\xE7\x7C\xBD\x24\xD8\xA9\x91\x17\x73\x88\x3F\x56\x1B\x31\x38\x18\xB4\x71\x0F\x9A\xCD\xC8\x0E\x9E\x8E\x2E\x1B\xE1\x8C\x98\x83\xCB\x1F\x31\xF1\x44\x4C\xC6\x04\x73\x49\x76\x60\x0F\xC7\xF8\xBD\x17\x80\x6B\x2E\xE9\xCC\x4C\x0E\x5A\x9A\x79\x0F\x20\x0A\x2E\xD5\x9E\x63\x26\x1E\x55\x92\x94\xD8\x82\x17\x5A\x7B\xD0\xBC\xC7\x8F\x4E\x86\x04", ["CN=AddTrust Public CA Root,OU=AddTrust TTP Network,O=AddTrust AB,C=SE"] = "\x30\x82\x04\x15\x30\x82\x02\xFD\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x34\x31\x35\x30\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x34\x31\x35\x30\x5A\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xE9\x1A\x30\x8F\x83\x88\x14\xC1\x20\xD8\x3C\x9B\x8F\x1B\x7E\x03\x74\xBB\xDA\x69\xD3\x46\xA5\xF8\x8E\xC2\x0C\x11\x90\x51\xA5\x2F\x66\x54\x40\x55\xEA\xDB\x1F\x4A\x56\xEE\x9F\x23\x6E\xF4\x39\xCB\xA1\xB9\x6F\xF2\x7E\xF9\x5D\x87\x26\x61\x9E\x1C\xF8\xE2\xEC\xA6\x81\xF8\x21\xC5\x24\xCC\x11\x0C\x3F\xDB\x26\x72\x7A\xC7\x01\x97\x07\x17\xF9\xD7\x18\x2C\x30\x7D\x0E\x7A\x1E\x62\x1E\xC6\x4B\xC0\xFD\x7D\x62\x77\xD3\x44\x1E\x27\xF6\x3F\x4B\x44\xB3\xB7\x38\xD9\x39\x1F\x60\xD5\x51\x92\x73\x03\xB4\x00\x69\xE3\xF3\x14\x4E\xEE\xD1\xDC\x09\xCF\x77\x34\x46\x50\xB0\xF8\x11\xF2\xFE\x38\x79\xF7\x07\x39\xFE\x51\x92\x97\x0B\x5B\x08\x5F\x34\x86\x01\xAD\x88\x97\xEB\x66\xCD\x5E\xD1\xFF\xDC\x7D\xF2\x84\xDA\xBA\x77\xAD\xDC\x80\x08\xC7\xA7\x87\xD6\x55\x9F\x97\x6A\xE8\xC8\x11\x64\xBA\xE7\x19\x29\x3F\x11\xB3\x78\x90\x84\x20\x52\x5B\x11\xEF\x78\xD0\x83\xF6\xD5\x48\x90\xD0\x30\x1C\xCF\x80\xF9\x60\xFE\x79\xE4\x88\xF2\xDD\x00\xEB\x94\x45\xEB\x65\x94\x69\x40\xBA\xC0\xD5\xB4\xB8\xBA\x7D\x04\x11\xA8\xEB\x31\x05\x96\x94\x4E\x58\x21\x8E\x9F\xD0\x60\xFD\x02\x03\x01\x00\x01\xA3\x81\xD1\x30\x81\xCE\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x81\x3E\x37\xD8\x92\xB0\x1F\x77\x9F\x5C\xB4\xAB\x73\xAA\xE7\xF6\x34\x60\x2F\xFA\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x8E\x06\x03\x55\x1D\x23\x04\x81\x86\x30\x81\x83\x80\x14\x81\x3E\x37\xD8\x92\xB0\x1F\x77\x9F\x5C\xB4\xAB\x73\xAA\xE7\xF6\x34\x60\x2F\xFA\xA1\x68\xA4\x66\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x03\xF7\x15\x4A\xF8\x24\xDA\x23\x56\x16\x93\x76\xDD\x36\x28\xB9\xAE\x1B\xB8\xC3\xF1\x64\xBA\x20\x18\x78\x95\x29\x27\x57\x05\xBC\x7C\x2A\xF4\xB9\x51\x55\xDA\x87\x02\xDE\x0F\x16\x17\x31\xF8\xAA\x79\x2E\x09\x13\xBB\xAF\xB2\x20\x19\x12\xE5\x93\xF9\x4B\xF9\x83\xE8\x44\xD5\xB2\x41\x25\xBF\x88\x75\x6F\xFF\x10\xFC\x4A\x54\xD0\x5F\xF0\xFA\xEF\x36\x73\x7D\x1B\x36\x45\xC6\x21\x6D\xB4\x15\xB8\x4E\xCF\x9C\x5C\xA5\x3D\x5A\x00\x8E\x06\xE3\x3C\x6B\x32\x7B\xF2\x9F\xF0\xB6\xFD\xDF\xF0\x28\x18\x48\xF0\xC6\xBC\xD0\xBF\x34\x80\x96\xC2\x4A\xB1\x6D\x8E\xC7\x90\x45\xDE\x2F\x67\xAC\x45\x04\xA3\x7A\xDC\x55\x92\xC9\x47\x66\xD8\x1A\x8C\xC7\xED\x9C\x4E\x9A\xE0\x12\xBB\xB5\x6A\x4C\x84\xE1\xE1\x22\x0D\x87\x00\x64\xFE\x8C\x7D\x62\x39\x65\xA6\xEF\x42\xB6\x80\x25\x12\x61\x01\xA8\x24\x13\x70\x00\x11\x26\x5F\xFA\x35\x50\xC5\x48\xCC\x06\x47\xE8\x27\xD8\x70\x8D\x5F\x64\xE6\xA1\x44\x26\x5E\x22\xEC\x92\xCD\xFF\x42\x9A\x44\x21\x6D\x5C\xC5\xE3\x22\x1D\x5F\x47\x12\xE7\xCE\x5F\x5D\xFA\xD8\xAA\xB1\x33\x2D\xD9\x76\xF2\x4E\x3A\x33\x0C\x2B\xB3\x2D\x90\x06", @@ -118,7 +115,6 @@ redef root_certs += { ["emailAddress=info@e-szigno.hu,CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU"] = "\x30\x82\x04\x0A\x30\x82\x02\xF2\xA0\x03\x02\x01\x02\x02\x09\x00\xC2\x7E\x43\x04\x4E\x47\x3F\x19\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x0C\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x0C\x1E\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x30\x39\x31\x1F\x30\x1D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x30\x1E\x17\x0D\x30\x39\x30\x36\x31\x36\x31\x31\x33\x30\x31\x38\x5A\x17\x0D\x32\x39\x31\x32\x33\x30\x31\x31\x33\x30\x31\x38\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x0C\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x0C\x1E\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x30\x39\x31\x1F\x30\x1D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xE9\xF8\x8F\xF3\x63\xAD\xDA\x86\xD8\xA7\xE0\x42\xFB\xCF\x91\xDE\xA6\x26\xF8\x99\xA5\x63\x70\xAD\x9B\xAE\xCA\x33\x40\x7D\x6D\x96\x6E\xA1\x0E\x44\xEE\xE1\x13\x9D\x94\x42\x52\x9A\xBD\x75\x85\x74\x2C\xA8\x0E\x1D\x93\xB6\x18\xB7\x8C\x2C\xA8\xCF\xFB\x5C\x71\xB9\xDA\xEC\xFE\xE8\x7E\x8F\xE4\x2F\x1D\xB2\xA8\x75\x87\xD8\xB7\xA1\xE5\x3B\xCF\x99\x4A\x46\xD0\x83\x19\x7D\xC0\xA1\x12\x1C\x95\x6D\x4A\xF4\xD8\xC7\xA5\x4D\x33\x2E\x85\x39\x40\x75\x7E\x14\x7C\x80\x12\x98\x50\xC7\x41\x67\xB8\xA0\x80\x61\x54\xA6\x6C\x4E\x1F\xE0\x9D\x0E\x07\xE9\xC9\xBA\x33\xE7\xFE\xC0\x55\x28\x2C\x02\x80\xA7\x19\xF5\x9E\xDC\x55\x53\x03\x97\x7B\x07\x48\xFF\x99\xFB\x37\x8A\x24\xC4\x59\xCC\x50\x10\x63\x8E\xAA\xA9\x1A\xB0\x84\x1A\x86\xF9\x5F\xBB\xB1\x50\x6E\xA4\xD1\x0A\xCC\xD5\x71\x7E\x1F\xA7\x1B\x7C\xF5\x53\x6E\x22\x5F\xCB\x2B\xE6\xD4\x7C\x5D\xAE\xD6\xC2\xC6\x4C\xE5\x05\x01\xD9\xED\x57\xFC\xC1\x23\x79\xFC\xFA\xC8\x24\x83\x95\xF3\xB5\x6A\x51\x01\xD0\x77\xD6\xE9\x12\xA1\xF9\x1A\x83\xFB\x82\x1B\xB9\xB0\x97\xF4\x76\x06\x33\x43\x49\xA0\xFF\x0B\xB5\xFA\xB5\x02\x03\x01\x00\x01\xA3\x81\x80\x30\x7E\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xCB\x0F\xC6\xDF\x42\x43\xCC\x3D\xCB\xB5\x48\x23\xA1\x1A\x7A\xA6\x2A\xBB\x34\x68\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xCB\x0F\xC6\xDF\x42\x43\xCC\x3D\xCB\xB5\x48\x23\xA1\x1A\x7A\xA6\x2A\xBB\x34\x68\x30\x1B\x06\x03\x55\x1D\x11\x04\x14\x30\x12\x81\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\xC9\xD1\x0E\x5E\x2E\xD5\xCC\xB3\x7C\x3E\xCB\xFC\x3D\xFF\x0D\x28\x95\x93\x04\xC8\xBF\xDA\xCD\x79\xB8\x43\x90\xF0\xA4\xBE\xEF\xF2\xEF\x21\x98\xBC\xD4\xD4\x5D\x06\xF6\xEE\x42\xEC\x30\x6C\xA0\xAA\xA9\xCA\xF1\xAF\x8A\xFA\x3F\x0B\x73\x6A\x3E\xEA\x2E\x40\x7E\x1F\xAE\x54\x61\x79\xEB\x2E\x08\x37\xD7\x23\xF3\x8C\x9F\xBE\x1D\xB1\xE1\xA4\x75\xDB\xA0\xE2\x54\x14\xB1\xBA\x1C\x29\xA4\x18\xF6\x12\xBA\xA2\x14\x14\xE3\x31\x35\xC8\x40\xFF\xB7\xE0\x05\x76\x57\xC1\x1C\x59\xF2\xF8\xBF\xE4\xED\x25\x62\x5C\x84\xF0\x7E\x7E\x1F\xB3\xBE\xF9\xB7\x21\x11\xCC\x03\x01\x56\x70\xA7\x10\x92\x1E\x1B\x34\x81\x1E\xAD\x9C\x1A\xC3\x04\x3C\xED\x02\x61\xD6\x1E\x06\xF3\x5F\x3A\x87\xF2\x2B\xF1\x45\x87\xE5\x3D\xAC\xD1\xC7\x57\x84\xBD\x6B\xAE\xDC\xD8\xF9\xB6\x1B\x62\x70\x0B\x3D\x36\xC9\x42\xF2\x32\xD7\x7A\x61\xE6\xD2\xDB\x3D\xCF\xC8\xA9\xC9\x9B\xDC\xDB\x58\x44\xD7\x6F\x38\xAF\x7F\x78\xD3\xA3\xAD\x1A\x75\xBA\x1C\xC1\x36\x7C\x8F\x1E\x6D\x1C\xC3\x75\x46\xAE\x35\x05\xA6\xF6\x5C\x3D\x21\xEE\x56\xF0\xC9\x82\x22\x2D\x7A\x54\xAB\x70\xC3\x7D\x22\x65\x82\x70\x96", ["CN=e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi,O=Elektronik Bilgi Guvenligi A.S.,C=TR"] = "\x30\x82\x03\xB6\x30\x82\x02\x9E\xA0\x03\x02\x01\x02\x02\x10\x44\x99\x8D\x3C\xC0\x03\x27\xBD\x9C\x76\x95\xB9\xEA\xDB\xAC\xB5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x28\x30\x26\x06\x03\x55\x04\x0A\x13\x1F\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x42\x69\x6C\x67\x69\x20\x47\x75\x76\x65\x6E\x6C\x69\x67\x69\x20\x41\x2E\x53\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x03\x13\x33\x65\x2D\x47\x75\x76\x65\x6E\x20\x4B\x6F\x6B\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\x67\x6C\x61\x79\x69\x63\x69\x73\x69\x30\x1E\x17\x0D\x30\x37\x30\x31\x30\x34\x31\x31\x33\x32\x34\x38\x5A\x17\x0D\x31\x37\x30\x31\x30\x34\x31\x31\x33\x32\x34\x38\x5A\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x28\x30\x26\x06\x03\x55\x04\x0A\x13\x1F\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x42\x69\x6C\x67\x69\x20\x47\x75\x76\x65\x6E\x6C\x69\x67\x69\x20\x41\x2E\x53\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x03\x13\x33\x65\x2D\x47\x75\x76\x65\x6E\x20\x4B\x6F\x6B\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\x67\x6C\x61\x79\x69\x63\x69\x73\x69\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xC3\x12\x20\x9E\xB0\x5E\x00\x65\x8D\x4E\x46\xBB\x80\x5C\xE9\x2C\x06\x97\xD5\xF3\x72\xC9\x70\xB9\xE7\x4B\x65\x80\xC1\x4B\xBE\x7E\x3C\xD7\x54\x31\x94\xDE\xD5\x12\xBA\x53\x16\x02\xEA\x58\x63\xEF\x5B\xD8\xF3\xED\x2A\x1A\xAA\x71\x48\xA3\xDC\x10\x2D\x5F\x5F\xEB\x5C\x4B\x9C\x96\x08\x42\x25\x28\x11\xCC\x8A\x5A\x62\x01\x50\xD5\xEB\x09\x53\x2F\xF8\xC3\x8F\xFE\xB3\xFC\xFD\x9D\xA2\xE3\x5F\x7D\xBE\xED\x0B\xE0\x60\xEB\x69\xEC\x33\xED\xD8\x8D\xFB\x12\x49\x83\x00\xC9\x8B\x97\x8C\x3B\x73\x2A\x32\xB3\x12\xF7\xB9\x4D\xF2\xF4\x4D\x6D\xC7\xE6\xD6\x26\x37\x08\xF2\xD9\xFD\x6B\x5C\xA3\xE5\x48\x5C\x58\xBC\x42\xBE\x03\x5A\x81\xBA\x1C\x35\x0C\x00\xD3\xF5\x23\x7E\x71\x30\x08\x26\x38\xDC\x25\x11\x47\x2D\xF3\xBA\x23\x10\xA5\xBF\xBC\x02\xF7\x43\x5E\xC7\xFE\xB0\x37\x50\x99\x7B\x0F\x93\xCE\xE6\x43\x2C\xC3\x7E\x0D\xF2\x1C\x43\x66\x60\xCB\x61\x31\x47\x87\xA3\x4F\xAE\xBD\x56\x6C\x4C\xBC\xBC\xF8\x05\xCA\x64\xF4\xE9\x34\xA1\x2C\xB5\x73\xE1\xC2\x3E\xE8\xC8\xC9\x34\x25\x08\x5C\xF3\xED\xA6\xC7\x94\x9F\xAD\x88\x43\x25\xD7\xE1\x39\x60\xFE\xAC\x39\x59\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9F\xEE\x44\xB3\x94\xD5\xFA\x91\x4F\x2E\xD9\x55\x9A\x04\x56\xDB\x2D\xC4\xDB\xA5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7F\x5F\xB9\x53\x5B\x63\x3D\x75\x32\xE7\xFA\xC4\x74\x1A\xCB\x46\xDF\x46\x69\x1C\x52\xCF\xAA\x4F\xC2\x68\xEB\xFF\x80\xA9\x51\xE8\x3D\x62\x77\x89\x3D\x0A\x75\x39\xF1\x6E\x5D\x17\x87\x6F\x68\x05\xC1\x94\x6C\xD9\x5D\xDF\xDA\xB2\x59\xCB\xA5\x10\x8A\xCA\xCC\x39\xCD\x9F\xEB\x4E\xDE\x52\xFF\x0C\xF0\xF4\x92\xA9\xF2\x6C\x53\xAB\x9B\xD2\x47\xA0\x1F\x74\xF7\x9B\x9A\xF1\x2F\x15\x9F\x7A\x64\x30\x18\x07\x3C\x2A\x0F\x67\xCA\xFC\x0F\x89\x61\x9D\x65\xA5\x3C\xE5\xBC\x13\x5B\x08\xDB\xE3\xFF\xED\xBB\x06\xBB\x6A\x06\xB1\x7A\x4F\x65\xC6\x82\xFD\x1E\x9C\x8B\xB5\x0D\xEE\x48\xBB\xB8\xBD\xAA\x08\xB4\xFB\xA3\x7C\xCB\x9F\xCD\x90\x76\x5C\x86\x96\x78\x57\x0A\x66\xF9\x58\x1A\x9D\xFD\x97\x29\x60\xDE\x11\xA6\x90\x1C\x19\x1C\xEE\x01\x96\x22\x34\x34\x2E\x91\xF9\xB7\xC4\x27\xD1\x7B\xE6\xBF\xFB\x80\x44\x5A\x16\xE5\xEB\xE0\xD4\x0A\x38\xBC\xE4\x91\xE3\xD5\xEB\x5C\xC1\xAC\xDF\x1B\x6A\x7C\x9E\xE5\x75\xD2\xB6\x97\x87\xDB\xCC\x87\x2B\x43\x3A\x84\x08\xAF\xAB\x3C\xDB\xF7\x3C\x66\x31\x86\xB0\x9D\x53\x79\xED\xF8\x23\xDE\x42\xE3\x2D\x82\xF1\x0F\xE5\xFA\x97", ["CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3"] = "\x30\x82\x03\x5F\x30\x82\x02\x47\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x21\x58\x53\x08\xA2\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x33\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x30\x1E\x17\x0D\x30\x39\x30\x33\x31\x38\x31\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x30\x33\x31\x38\x31\x30\x30\x30\x30\x30\x5A\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x33\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xCC\x25\x76\x90\x79\x06\x78\x22\x16\xF5\xC0\x83\xB6\x84\xCA\x28\x9E\xFD\x05\x76\x11\xC5\xAD\x88\x72\xFC\x46\x02\x43\xC7\xB2\x8A\x9D\x04\x5F\x24\xCB\x2E\x4B\xE1\x60\x82\x46\xE1\x52\xAB\x0C\x81\x47\x70\x6C\xDD\x64\xD1\xEB\xF5\x2C\xA3\x0F\x82\x3D\x0C\x2B\xAE\x97\xD7\xB6\x14\x86\x10\x79\xBB\x3B\x13\x80\x77\x8C\x08\xE1\x49\xD2\x6A\x62\x2F\x1F\x5E\xFA\x96\x68\xDF\x89\x27\x95\x38\x9F\x06\xD7\x3E\xC9\xCB\x26\x59\x0D\x73\xDE\xB0\xC8\xE9\x26\x0E\x83\x15\xC6\xEF\x5B\x8B\xD2\x04\x60\xCA\x49\xA6\x28\xF6\x69\x3B\xF6\xCB\xC8\x28\x91\xE5\x9D\x8A\x61\x57\x37\xAC\x74\x14\xDC\x74\xE0\x3A\xEE\x72\x2F\x2E\x9C\xFB\xD0\xBB\xBF\xF5\x3D\x00\xE1\x06\x33\xE8\x82\x2B\xAE\x53\xA6\x3A\x16\x73\x8C\xDD\x41\x0E\x20\x3A\xC0\xB4\xA7\xA1\xE9\xB2\x4F\x90\x2E\x32\x60\xE9\x57\xCB\xB9\x04\x92\x68\x68\xE5\x38\x26\x60\x75\xB2\x9F\x77\xFF\x91\x14\xEF\xAE\x20\x49\xFC\xAD\x40\x15\x48\xD1\x02\x31\x61\x19\x5E\xB8\x97\xEF\xAD\x77\xB7\x64\x9A\x7A\xBF\x5F\xC1\x13\xEF\x9B\x62\xFB\x0D\x6C\xE0\x54\x69\x16\xA9\x03\xDA\x6E\xE9\x83\x93\x71\x76\xC6\x69\x85\x82\x17\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x8F\xF0\x4B\x7F\xA8\x2E\x45\x24\xAE\x4D\x50\xFA\x63\x9A\x8B\xDE\xE2\xDD\x1B\xBC\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x4B\x40\xDB\xC0\x50\xAA\xFE\xC8\x0C\xEF\xF7\x96\x54\x45\x49\xBB\x96\x00\x09\x41\xAC\xB3\x13\x86\x86\x28\x07\x33\xCA\x6B\xE6\x74\xB9\xBA\x00\x2D\xAE\xA4\x0A\xD3\xF5\xF1\xF1\x0F\x8A\xBF\x73\x67\x4A\x83\xC7\x44\x7B\x78\xE0\xAF\x6E\x6C\x6F\x03\x29\x8E\x33\x39\x45\xC3\x8E\xE4\xB9\x57\x6C\xAA\xFC\x12\x96\xEC\x53\xC6\x2D\xE4\x24\x6C\xB9\x94\x63\xFB\xDC\x53\x68\x67\x56\x3E\x83\xB8\xCF\x35\x21\xC3\xC9\x68\xFE\xCE\xDA\xC2\x53\xAA\xCC\x90\x8A\xE9\xF0\x5D\x46\x8C\x95\xDD\x7A\x58\x28\x1A\x2F\x1D\xDE\xCD\x00\x37\x41\x8F\xED\x44\x6D\xD7\x53\x28\x97\x7E\xF3\x67\x04\x1E\x15\xD7\x8A\x96\xB4\xD3\xDE\x4C\x27\xA4\x4C\x1B\x73\x73\x76\xF4\x17\x99\xC2\x1F\x7A\x0E\xE3\x2D\x08\xAD\x0A\x1C\x2C\xFF\x3C\xAB\x55\x0E\x0F\x91\x7E\x36\xEB\xC3\x57\x49\xBE\xE1\x2E\x2D\x7C\x60\x8B\xC3\x41\x51\x13\x23\x9D\xCE\xF7\x32\x6B\x94\x01\xA8\x99\xE7\x2C\x33\x1F\x3A\x3B\x25\xD2\x86\x40\xCE\x3B\x2C\x86\x78\xC9\x61\x2F\x14\xBA\xEE\xDB\x55\x6F\xDF\x84\xEE\x05\x09\x4D\xBD\x28\xD8\x72\xCE\xD3\x62\x50\x65\x1E\xEB\x92\x97\x83\x31\xD9\xB3\xB5\xCA\x47\x58\x3F\x5F", - ["CN=TC TrustCenter Universal CA III,OU=TC TrustCenter Universal CA,O=TC TrustCenter GmbH,C=DE"] = "\x30\x82\x03\xE1\x30\x82\x02\xC9\xA0\x03\x02\x01\x02\x02\x0E\x63\x25\x00\x01\x00\x02\x14\x8D\x33\x15\x02\xE4\x6C\xF4\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\x49\x49\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x39\x30\x38\x31\x35\x32\x37\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\x49\x49\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xC2\xDA\x9C\x62\xB0\xB9\x71\x12\xB0\x0B\xC8\x1A\x57\xB2\xAE\x83\x14\x99\xB3\x34\x4B\x9B\x90\xA2\xC5\xE7\xE7\x2F\x02\xA0\x4D\x2D\xA4\xFA\x85\xDA\x9B\x25\x85\x2D\x40\x28\x20\x6D\xEA\xE0\xBD\xB1\x48\x83\x22\x29\x44\x9F\x4E\x83\xEE\x35\x51\x13\x73\x74\xD5\xBC\xF2\x30\x66\x94\x53\xC0\x40\x36\x2F\x0C\x84\x65\xCE\x0F\x6E\xC2\x58\x93\xE8\x2C\x0B\x3A\xE9\xC1\x8E\xFB\xF2\x6B\xCA\x3C\xE2\x9C\x4E\x8E\xE4\xF9\x7D\xD3\x27\x9F\x1B\xD5\x67\x78\x87\x2D\x7F\x0B\x47\xB3\xC7\xE8\xC9\x48\x7C\xAF\x2F\xCC\x0A\xD9\x41\xEF\x9F\xFE\x9A\xE1\xB2\xAE\xF9\x53\xB5\xE5\xE9\x46\x9F\x60\xE3\xDF\x8D\xD3\x7F\xFB\x96\x7E\xB3\xB5\x72\xF8\x4B\xAD\x08\x79\xCD\x69\x89\x40\x27\xF5\x2A\xC1\xAD\x43\xEC\xA4\x53\xC8\x61\xB6\xF7\xD2\x79\x2A\x67\x18\x76\x48\x6D\x5B\x25\x01\xD1\x26\xC5\xB7\x57\x69\x23\x15\x5B\x61\x8A\xAD\xF0\x1B\x2D\xD9\xAF\x5C\xF1\x26\x90\x69\xA9\xD5\x0C\x40\xF5\x33\x80\x43\x8F\x9C\xA3\x76\x2A\x45\xB4\xAF\xBF\x7F\x3E\x87\x3F\x76\xC5\xCD\x2A\xDE\x20\xC5\x16\x58\xCB\xF9\x1B\xF5\x0F\xCB\x0D\x11\x52\x64\xB8\xD2\x76\x62\x77\x83\xF1\x58\x9F\xFF\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x56\xE7\xE1\x5B\x25\x43\x80\xE0\xF6\x8C\xE1\x71\xBC\x8E\xE5\x80\x2F\xC4\x48\xE2\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x56\xE7\xE1\x5B\x25\x43\x80\xE0\xF6\x8C\xE1\x71\xBC\x8E\xE5\x80\x2F\xC4\x48\xE2\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x83\xC7\xAF\xEA\x7F\x4D\x0A\x3C\x39\xB1\x68\xBE\x7B\x6D\x89\x2E\xE9\xB3\x09\xE7\x18\x57\x8D\x85\x9A\x17\xF3\x76\x42\x50\x13\x0F\xC7\x90\x6F\x33\xAD\xC5\x49\x60\x2B\x6C\x49\x58\x19\xD4\xE2\xBE\xB7\xBF\xAB\x49\xBC\x94\xC8\xAB\xBE\x28\x6C\x16\x68\xE0\xC8\x97\x46\x20\xA0\x68\x67\x60\x88\x39\x20\x51\xD8\x68\x01\x11\xCE\xA7\xF6\x11\x07\xF6\xEC\xEC\xAC\x1A\x1F\xB2\x66\x6E\x56\x67\x60\x7A\x74\x5E\xC0\x6D\x97\x36\xAE\xB5\x0D\x5D\x66\x73\xC0\x25\x32\x45\xD8\x4A\x06\x07\x8F\xC4\xB7\x07\xB1\x4D\x06\x0D\xE1\xA5\xEB\xF4\x75\xCA\xBA\x9C\xD0\xBD\xB3\xD3\x32\x24\x4C\xEE\x7E\xE2\x76\x04\x4B\x49\x53\xD8\xF2\xE9\x54\x33\xFC\xE5\x71\x1F\x3D\x14\x5C\x96\x4B\xF1\x3A\xF2\x00\xBB\x6C\xB4\xFA\x96\x55\x08\x88\x09\xC1\xCC\x91\x19\x29\xB0\x20\x2D\xFF\xCB\x38\xA4\x40\xE1\x17\xBE\x79\x61\x80\xFF\x07\x03\x86\x4C\x4E\x7B\x06\x9F\x11\x86\x8D\x89\xEE\x27\xC4\xDB\xE2\xBC\x19\x8E\x0B\xC3\xC3\x13\xC7\x2D\x03\x63\x3B\xD3\xE8\xE4\xA2\x2A\xC2\x82\x08\x94\x16\x54\xF0\xEF\x1F\x27\x90\x25\xB8\x0D\x0E\x28\x1B\x47\x77\x47\xBD\x1C\xA8\x25\xF1\x94\xB4\x66", ["CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES"] = "\x30\x82\x06\x14\x30\x82\x03\xFC\xA0\x03\x02\x01\x02\x02\x08\x53\xEC\x3B\xEE\xFB\xB2\x48\x5F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x51\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x42\x30\x40\x06\x03\x55\x04\x03\x0C\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x30\x1E\x17\x0D\x30\x39\x30\x35\x32\x30\x30\x38\x33\x38\x31\x35\x5A\x17\x0D\x33\x30\x31\x32\x33\x31\x30\x38\x33\x38\x31\x35\x5A\x30\x51\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x42\x30\x40\x06\x03\x55\x04\x03\x0C\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xCA\x96\x6B\x8E\xEA\xF8\xFB\xF1\xA2\x35\xE0\x7F\x4C\xDA\xE0\xC3\x52\xD7\x7D\xB6\x10\xC8\x02\x5E\xB3\x43\x2A\xC4\x4F\x6A\xB2\xCA\x1C\x5D\x28\x9A\x78\x11\x1A\x69\x59\x57\xAF\xB5\x20\x42\xE4\x8B\x0F\xE6\xDF\x5B\xA6\x03\x92\x2F\xF5\x11\xE4\x62\xD7\x32\x71\x38\xD9\x04\x0C\x71\xAB\x3D\x51\x7E\x0F\x07\xDF\x63\x05\x5C\xE9\xBF\x94\x6F\xC1\x29\x82\xC0\xB4\xDA\x51\xB0\xC1\x3C\xBB\xAD\x37\x4A\x5C\xCA\xF1\x4B\x36\x0E\x24\xAB\xBF\xC3\x84\x77\xFD\xA8\x50\xF4\xB1\xE7\xC6\x2F\xD2\x2D\x59\x8D\x7A\x0A\x4E\x96\x69\x52\x02\xAA\x36\x98\xEC\xFC\xFA\x14\x83\x0C\x37\x1F\xC9\x92\x37\x7F\xD7\x81\x2D\xE5\xC4\xB9\xE0\x3E\x34\xFE\x67\xF4\x3E\x66\xD1\xD3\xF4\x40\xCF\x5E\x62\x34\x0F\x70\x06\x3E\x20\x18\x5A\xCE\xF7\x72\x1B\x25\x6C\x93\x74\x14\x93\xA3\x73\xB1\x0E\xAA\x87\x10\x23\x59\x5F\x20\x05\x19\x47\xED\x68\x8E\x92\x12\xCA\x5D\xFC\xD6\x2B\xB2\x92\x3C\x20\xCF\xE1\x5F\xAF\x20\xBE\xA0\x76\x7F\x76\xE5\xEC\x1A\x86\x61\x33\x3E\xE7\x7B\xB4\x3F\xA0\x0F\x8E\xA2\xB9\x6A\x6F\xB9\x87\x26\x6F\x41\x6C\x88\xA6\x50\xFD\x6A\x63\x0B\xF5\x93\x16\x1B\x19\x8F\xB2\xED\x9B\x9B\xC9\x90\xF5\x01\x0C\xDF\x19\x3D\x0F\x3E\x38\x23\xC9\x2F\x8F\x0C\xD1\x02\xFE\x1B\x55\xD6\x4E\xD0\x8D\x3C\xAF\x4F\xA4\xF3\xFE\xAF\x2A\xD3\x05\x9D\x79\x08\xA1\xCB\x57\x31\xB4\x9C\xC8\x90\xB2\x67\xF4\x18\x16\x93\x3A\xFC\x47\xD8\xD1\x78\x96\x31\x1F\xBA\x2B\x0C\x5F\x5D\x99\xAD\x63\x89\x5A\x24\x20\x76\xD8\xDF\xFD\xAB\x4E\xA6\x22\xAA\x9D\x5E\xE6\x27\x8A\x7D\x68\x29\xA3\xE7\x8A\xB8\xDA\x11\xBB\x17\x2D\x99\x9D\x13\x24\x46\xF7\xC5\xE2\xD8\x9F\x8E\x7F\xC7\x8F\x74\x6D\x5A\xB2\xE8\x72\xF5\xAC\xEE\x24\x10\xAD\x2F\x14\xDA\xFF\x2D\x9A\x46\x71\x47\xBE\x42\xDF\xBB\x01\xDB\xF4\x7F\xD3\x28\x8F\x31\x59\x5B\xD3\xC9\x02\xA6\xB4\x52\xCA\x6E\x97\xFB\x43\xC5\x08\x26\x6F\x8A\xF4\xBB\xFD\x9F\x28\xAA\x0D\xD5\x45\xF3\x13\x3A\x1D\xD8\xC0\x78\x8F\x41\x67\x3C\x1E\x94\x64\xAE\x7B\x0B\xC5\xE8\xD9\x01\x88\x39\x1A\x97\x86\x64\x41\xD5\x3B\x87\x0C\x6E\xFA\x0F\xC6\xBD\x48\x14\xBF\x39\x4D\xD4\x9E\x41\xB6\x8F\x96\x1D\x63\x96\x93\xD9\x95\x06\x78\x31\x68\x9E\x37\x06\x3B\x80\x89\x45\x61\x39\x23\xC7\x1B\x44\xA3\x15\xE5\x1C\xF8\x92\x30\xBB\x02\x03\x01\x00\x01\xA3\x81\xEF\x30\x81\xEC\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x01\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x65\xCD\xEB\xAB\x35\x1E\x00\x3E\x7E\xD5\x74\xC0\x1C\xB4\x73\x47\x0E\x1A\x64\x2F\x30\x81\xA6\x06\x03\x55\x1D\x20\x04\x81\x9E\x30\x81\x9B\x30\x81\x98\x06\x04\x55\x1D\x20\x00\x30\x81\x8F\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\x2F\x63\x70\x73\x30\x5C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x50\x1E\x4E\x00\x50\x00\x61\x00\x73\x00\x65\x00\x6F\x00\x20\x00\x64\x00\x65\x00\x20\x00\x6C\x00\x61\x00\x20\x00\x42\x00\x6F\x00\x6E\x00\x61\x00\x6E\x00\x6F\x00\x76\x00\x61\x00\x20\x00\x34\x00\x37\x00\x20\x00\x42\x00\x61\x00\x72\x00\x63\x00\x65\x00\x6C\x00\x6F\x00\x6E\x00\x61\x00\x20\x00\x30\x00\x38\x00\x30\x00\x31\x00\x37\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x17\x7D\xA0\xF9\xB4\xDD\xC5\xC5\xEB\xAD\x4B\x24\xB5\xA1\x02\xAB\xDD\xA5\x88\x4A\xB2\x0F\x55\x4B\x2B\x57\x8C\x3B\xE5\x31\xDD\xFE\xC4\x32\xF1\xE7\x5B\x64\x96\x36\x32\x18\xEC\xA5\x32\x77\xD7\xE3\x44\xB6\xC0\x11\x2A\x80\xB9\x3D\x6A\x6E\x7C\x9B\xD3\xAD\xFC\xC3\xD6\xA3\xE6\x64\x29\x7C\xD1\xE1\x38\x1E\x82\x2B\xFF\x27\x65\xAF\xFB\x16\x15\xC4\x2E\x71\x84\xE5\xB5\xFF\xFA\xA4\x47\xBD\x64\x32\xBB\xF6\x25\x84\xA2\x27\x42\xF5\x20\xB0\xC2\x13\x10\x11\xCD\x10\x15\xBA\x42\x90\x2A\xD2\x44\xE1\x96\x26\xEB\x31\x48\x12\xFD\x2A\xDA\xC9\x06\xCF\x74\x1E\xA9\x4B\xD5\x87\x28\xF9\x79\x34\x92\x3E\x2E\x44\xE8\xF6\x8F\x4F\x8F\x35\x3F\x25\xB3\x39\xDC\x63\x2A\x90\x6B\x20\x5F\xC4\x52\x12\x4E\x97\x2C\x2A\xAC\x9D\x97\xDE\x48\xF2\xA3\x66\xDB\xC2\xD2\x83\x95\xA6\x66\xA7\x9E\x25\x0F\xE9\x0B\x33\x91\x65\x0A\x5A\xC3\xD9\x54\x12\xDD\xAF\xC3\x4E\x0E\x1F\x26\x5E\x0D\xDC\xB3\x8D\xEC\xD5\x81\x70\xDE\xD2\x4F\x24\x05\xF3\x6C\x4E\xF5\x4C\x49\x66\x8D\xD1\xFF\xD2\x0B\x25\x41\x48\xFE\x51\x84\xC6\x42\xAF\x80\x04\xCF\xD0\x7E\x64\x49\xE4\xF2\xDF\xA2\xEC\xB1\x4C\xC0\x2A\x1D\xE7\xB4\xB1\x65\xA2\xC4\xBC\xF1\x98\xF4\xAA\x70\x07\x63\xB4\xB8\xDA\x3B\x4C\xFA\x40\x22\x30\x5B\x11\xA6\xF0\x05\x0E\xC6\x02\x03\x48\xAB\x86\x9B\x85\xDD\xDB\xDD\xEA\xA2\x76\x80\x73\x7D\xF5\x9C\x04\xC4\x45\x8D\xE7\xB9\x1C\x8B\x9E\xEA\xD7\x75\xD1\x72\xB1\xDE\x75\x44\xE7\x42\x7D\xE2\x57\x6B\x7D\xDC\x99\xBC\x3D\x83\x28\xEA\x80\x93\x8D\xC5\x4C\x65\xC1\x70\x81\xB8\x38\xFC\x43\x31\xB2\xF6\x03\x34\x47\xB2\xAC\xFB\x22\x06\xCB\x1E\xDD\x17\x47\x1C\x5F\x66\xB9\xD3\x1A\xA2\xDA\x11\xB1\xA4\xBC\x23\xC9\xE4\xBE\x87\xFF\xB9\x94\xB6\xF8\x5D\x20\x4A\xD4\x5F\xE7\xBD\x68\x7B\x65\xF2\x15\x1E\xD2\x3A\xA9\x2D\xE9\xD8\x6B\x24\xAC\x97\x58\x44\x47\xAD\x59\x18\xF1\x21\x65\x70\xDE\xCE\x34\x60\xA8\x40\xF1\xF3\x3C\xA4\xC3\x28\x23\x8C\xFE\x27\x33\x43\x40\xA0\x17\x3C\xEB\xEA\x3B\xB0\x72\xA6\xA3\xB9\x4A\x4B\x5E\x16\x48\xF4\xB2\xBC\xC8\x8C\x92\xC5\x9D\x9F\xAC\x72\x36\xBC\x34\x80\x34\x6B\xA9\x8B\x92\xC0\xB8\x17\xED\xEC\x76\x53\xF5\x24\x01\x8C\xB3\x22\xE8\x4B\x7C\x55\xC6\x9D\xFA\xA3\x14\xBB\x65\x85\x6E\x6E\x4F\x12\x7E\x0A\x3C\x9D\x95", ["CN=Izenpe.com,O=IZENPE S.A.,C=ES"] = "\x30\x82\x05\xF1\x30\x82\x03\xD9\xA0\x03\x02\x01\x02\x02\x10\x00\xB0\xB7\x5A\x16\x48\x5F\xBF\xE1\xCB\xF5\x8B\xD7\x19\xE6\x7D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x38\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0C\x0A\x49\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x30\x37\x31\x32\x31\x33\x31\x33\x30\x38\x32\x38\x5A\x17\x0D\x33\x37\x31\x32\x31\x33\x30\x38\x32\x37\x32\x35\x5A\x30\x38\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0C\x0A\x49\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC9\xD3\x7A\xCA\x0F\x1E\xAC\xA7\x86\xE8\x16\x65\x6A\xB1\xC2\x1B\x45\x32\x71\x95\xD9\xFE\x10\x5B\xCC\xAF\xE7\xA5\x79\x01\x8F\x89\xC3\xCA\xF2\x55\x71\xF7\x77\xBE\x77\x94\xF3\x72\xA4\x2C\x44\xD8\x9E\x92\x9B\x14\x3A\xA1\xE7\x24\x90\x0A\x0A\x56\x8E\xC5\xD8\x26\x94\xE1\xD9\x48\xE1\x2D\x3E\xDA\x0A\x72\xDD\xA3\x99\x15\xDA\x81\xA2\x87\xF4\x7B\x6E\x26\x77\x89\x58\xAD\xD6\xEB\x0C\xB2\x41\x7A\x73\x6E\x6D\xDB\x7A\x78\x41\xE9\x08\x88\x12\x7E\x87\x2E\x66\x11\x63\x6C\x54\xFB\x3C\x9D\x72\xC0\xBC\x2E\xFF\xC2\xB7\xDD\x0D\x76\xE3\x3A\xD7\xF7\xB4\x68\xBE\xA2\xF5\xE3\x81\x6E\xC1\x46\x6F\x5D\x8D\xE0\x4D\xC6\x54\x55\x89\x1A\x33\x31\x0A\xB1\x57\xB9\xA3\x8A\x98\xC3\xEC\x3B\x34\xC5\x95\x41\x69\x7E\x75\xC2\x3C\x20\xC5\x61\xBA\x51\x47\xA0\x20\x90\x93\xA1\x90\x4B\xF3\x4E\x7C\x85\x45\x54\x9A\xD1\x05\x26\x41\xB0\xB5\x4D\x1D\x33\xBE\xC4\x03\xC8\x25\x7C\xC1\x70\xDB\x3B\xF4\x09\x2D\x54\x27\x48\xAC\x2F\xE1\xC4\xAC\x3E\xC8\xCB\x92\x4C\x53\x39\x37\x23\xEC\xD3\x01\xF9\xE0\x09\x44\x4D\x4D\x64\xC0\xE1\x0D\x5A\x87\x22\xBC\xAD\x1B\xA3\xFE\x26\xB5\x15\xF3\xA7\xFC\x84\x19\xE9\xEC\xA1\x88\xB4\x44\x69\x84\x83\xF3\x89\xD1\x74\x06\xA9\xCC\x0B\xD6\xC2\xDE\x27\x85\x50\x26\xCA\x17\xB8\xC9\x7A\x87\x56\x2C\x1A\x01\x1E\x6C\xBE\x13\xAD\x10\xAC\xB5\x24\xF5\x38\x91\xA1\xD6\x4B\xDA\xF1\xBB\xD2\xDE\x47\xB5\xF1\xBC\x81\xF6\x59\x6B\xCF\x19\x53\xE9\x8D\x15\xCB\x4A\xCB\xA9\x6F\x44\xE5\x1B\x41\xCF\xE1\x86\xA7\xCA\xD0\x6A\x9F\xBC\x4C\x8D\x06\x33\x5A\xA2\x85\xE5\x90\x35\xA0\x62\x5C\x16\x4E\xF0\xE3\xA2\xFA\x03\x1A\xB4\x2C\x71\xB3\x58\x2C\xDE\x7B\x0B\xDB\x1A\x0F\xEB\xDE\x21\x1F\x06\x77\x06\x03\xB0\xC9\xEF\x99\xFC\xC0\xB9\x4F\x0B\x86\x28\xFE\xD2\xB9\xEA\xE3\xDA\xA5\xC3\x47\x69\x12\xE0\xDB\xF0\xF6\x19\x8B\xED\x7B\x70\xD7\x02\xD6\xED\x87\x18\x28\x2C\x04\x24\x4C\x77\xE4\x48\x8A\x1A\xC6\x3B\x9A\xD4\x0F\xCA\xFA\x75\xD2\x01\x40\x5A\x8D\x79\xBF\x8B\xCF\x4B\xCF\xAA\x16\xC1\x95\xE4\xAD\x4C\x8A\x3E\x17\x91\xD4\xB1\x62\xE5\x82\xE5\x80\x04\xA4\x03\x7E\x8D\xBF\xDA\x7F\xA2\x0F\x97\x4F\x0C\xD3\x0D\xFB\xD7\xD1\xE5\x72\x7E\x1C\xC8\x77\xFF\x5B\x9A\x0F\xB7\xAE\x05\x46\xE5\xF1\xA8\x16\xEC\x47\xA4\x17\x02\x03\x01\x00\x01\xA3\x81\xF6\x30\x81\xF3\x30\x81\xB0\x06\x03\x55\x1D\x11\x04\x81\xA8\x30\x81\xA5\x81\x0F\x69\x6E\x66\x6F\x40\x69\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\xA4\x81\x91\x30\x81\x8E\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x20\x2D\x20\x43\x49\x46\x20\x41\x30\x31\x33\x33\x37\x32\x36\x30\x2D\x52\x4D\x65\x72\x63\x2E\x56\x69\x74\x6F\x72\x69\x61\x2D\x47\x61\x73\x74\x65\x69\x7A\x20\x54\x31\x30\x35\x35\x20\x46\x36\x32\x20\x53\x38\x31\x43\x30\x41\x06\x03\x55\x04\x09\x0C\x3A\x41\x76\x64\x61\x20\x64\x65\x6C\x20\x4D\x65\x64\x69\x74\x65\x72\x72\x61\x6E\x65\x6F\x20\x45\x74\x6F\x72\x62\x69\x64\x65\x61\x20\x31\x34\x20\x2D\x20\x30\x31\x30\x31\x30\x20\x56\x69\x74\x6F\x72\x69\x61\x2D\x47\x61\x73\x74\x65\x69\x7A\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1D\x1C\x65\x0E\xA8\xF2\x25\x7B\xB4\x91\xCF\xE4\xB1\xB1\xE6\xBD\x55\x74\x6C\x05\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x78\xA6\x0C\x16\x4A\x9F\x4C\x88\x3A\xC0\xCB\x0E\xA5\x16\x7D\x9F\xB9\x48\x5F\x18\x8F\x0D\x62\x36\xF6\xCD\x19\x6B\xAC\xAB\xD5\xF6\x91\x7D\xAE\x71\xF3\x3F\xB3\x0E\x78\x85\x9B\x95\xA4\x27\x21\x47\x42\x4A\x7C\x48\x3A\xF5\x45\x7C\xB3\x0C\x8E\x51\x78\xAC\x95\x13\xDE\xC6\xFD\x7D\xB8\x1A\x90\x4C\xAB\x92\x03\xC7\xED\x42\x01\xCE\x0F\xD8\xB1\xFA\xA2\x92\xE1\x60\x6D\xAE\x7A\x6B\x09\xAA\xC6\x29\xEE\x68\x49\x67\x30\x80\x24\x7A\x31\x16\x39\x5B\x7E\xF1\x1C\x2E\xDD\x6C\x09\xAD\xF2\x31\xC1\x82\x4E\xB9\xBB\xF9\xBE\xBF\x2A\x85\x3F\xC0\x40\xA3\x3A\x59\xFC\x59\x4B\x3C\x28\x24\xDB\xB4\x15\x75\xAE\x0D\x88\xBA\x2E\x73\xC0\xBD\x58\x87\xE5\x42\xF2\xEB\x5E\xEE\x1E\x30\x22\x99\xCB\x37\xD1\xC4\x21\x6C\x81\xEC\xBE\x6D\x26\xE6\x1C\xE4\x42\x20\x9E\x47\xB0\xAC\x83\x59\x70\x2C\x35\xD6\xAF\x36\x34\xB4\xCD\x3B\xF8\x32\xA8\xEF\xE3\x78\x89\xFB\x8D\x45\x2C\xDA\x9C\xB8\x7E\x40\x1C\x61\xE7\x3E\xA2\x92\x2C\x4B\xF2\xCD\xFA\x98\xB6\x29\xFF\xF3\xF2\x7B\xA9\x1F\x2E\xA0\x93\x57\x2B\xDE\x85\x03\xF9\x69\x37\xCB\x9E\x78\x6A\x05\xB4\xC5\x31\x78\x89\xEC\x7A\xA7\x85\xE1\xB9\x7B\x3C\xDE\xBE\x1E\x79\x84\xCE\x9F\x70\x0E\x59\xC2\x35\x2E\x90\x2A\x31\xD9\xE4\x45\x7A\x41\xA4\x2E\x13\x9B\x34\x0E\x66\x7B\x49\xAB\x64\x97\xD0\x46\xC3\x79\x9D\x72\x50\x63\xA6\x98\x5B\x06\xBD\x48\x6D\xD8\x39\x83\x70\xE8\x35\xF0\x05\xD1\xAA\xBC\xE3\xDB\xC8\x02\xEA\x7C\xFD\x82\xDA\xC2\x5B\x52\x35\xAE\x98\x3A\xAD\xBA\x35\x93\x23\xA7\x1F\x48\xDD\x35\x46\x98\xB2\x10\x68\xE4\xA5\x31\xC2\x0A\x58\x2E\x19\x81\x10\xC9\x50\x75\xFC\xEA\x5A\x16\xCE\x11\xD7\xEE\xEF\x50\x88\x2D\x61\xFF\x3F\x42\x73\x05\x94\x43\xD5\x8E\x3C\x4E\x01\x3A\x19\xA5\x1F\x46\x4E\x77\xD0\x5D\xE5\x81\x22\x21\x87\xFE\x94\x7D\x84\xD8\x93\xAD\xD6\x68\x43\x48\xB2\xDB\xEB\x73\x24\xE7\x91\x7F\x54\xA4\xB6\x80\x3E\x9D\xA3\x3C\x4C\x72\xC2\x57\xC4\xA0\xD4\xCC\x38\x27\xCE\xD5\x06\x9E\xA2\x48\xD9\xE9\x9F\xCE\x82\x70\x36\x93\x9A\x3B\xDF\x96\x21\xE3\x59\xB7\x0C\xDA\x91\x37\xF0\xFD\x59\x5A\xB3\x99\xC8\x69\x6C\x43\x26\x01\x35\x63\x60\x55\x89\x03\x3A\x75\xD8\xBA\x4A\xD9\x54\xFF\xEE\xDE\x80\xD8\x2D\xD1\x38\xD5\x5E\x2D\x0B\x98\x7D\x3E\x6C\xDB\xFC\x26\x88\xC7", ["CN=Chambers of Commerce Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU"] = "\x30\x82\x07\x4F\x30\x82\x05\x37\xA0\x03\x02\x01\x02\x02\x09\x00\xA3\xDA\x42\x7E\xA4\xB1\xAE\xDA\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x1E\x17\x0D\x30\x38\x30\x38\x30\x31\x31\x32\x32\x39\x35\x30\x5A\x17\x0D\x33\x38\x30\x37\x33\x31\x31\x32\x32\x39\x35\x30\x5A\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAF\x00\xCB\x70\x37\x2B\x80\x5A\x4A\x3A\x6C\x78\x94\x7D\xA3\x7F\x1A\x1F\xF6\x35\xD5\xBD\xDB\xCB\x0D\x44\x72\x3E\x26\xB2\x90\x52\xBA\x63\x3B\x28\x58\x6F\xA5\xB3\x6D\x94\xA6\xF3\xDD\x64\x0C\x55\xF6\xF6\xE7\xF2\x22\x22\x80\x5E\xE1\x62\xC6\xB6\x29\xE1\x81\x6C\xF2\xBF\xE5\x7D\x32\x6A\x54\xA0\x32\x19\x59\xFE\x1F\x8B\xD7\x3D\x60\x86\x85\x24\x6F\xE3\x11\xB3\x77\x3E\x20\x96\x35\x21\x6B\xB3\x08\xD9\x70\x2E\x64\xF7\x84\x92\x53\xD6\x0E\xB0\x90\x8A\x8A\xE3\x87\x8D\x06\xD3\xBD\x90\x0E\xE2\x99\xA1\x1B\x86\x0E\xDA\x9A\x0A\xBB\x0B\x61\x50\x06\x52\xF1\x9E\x7F\x76\xEC\xCB\x0F\xD0\x1E\x0D\xCF\x99\x30\x3D\x1C\xC4\x45\x10\x58\xAC\xD6\xD3\xE8\xD7\xE5\xEA\xC5\x01\x07\x77\xD6\x51\xE6\x03\x7F\x8A\x48\xA5\x4D\x68\x75\xB9\xE9\xBC\x9E\x4E\x19\x71\xF5\x32\x4B\x9C\x6D\x60\x19\x0B\xFB\xCC\x9D\x75\xDC\xBF\x26\xCD\x8F\x93\x78\x39\x79\x73\x5E\x25\x0E\xCA\x5C\xEB\x77\x12\x07\xCB\x64\x41\x47\x72\x93\xAB\x50\xC3\xEB\x09\x76\x64\x34\xD2\x39\xB7\x76\x11\x09\x0D\x76\x45\xC4\xA9\xAE\x3D\x6A\xAF\xB5\x7D\x65\x2F\x94\x58\x10\xEC\x5C\x7C\xAF\x7E\xE2\xB6\x18\xD9\xD0\x9B\x4E\x5A\x49\xDF\xA9\x66\x0B\xCC\x3C\xC6\x78\x7C\xA7\x9C\x1D\xE3\xCE\x8E\x53\xBE\x05\xDE\x60\x0F\x6B\xE5\x1A\xDB\x3F\xE3\xE1\x21\xC9\x29\xC1\xF1\xEB\x07\x9C\x52\x1B\x01\x44\x51\x3C\x7B\x25\xD7\xC4\xE5\x52\x54\x5D\x25\x07\xCA\x16\x20\xB8\xAD\xE4\x41\xEE\x7A\x08\xFE\x99\x6F\x83\xA6\x91\x02\xB0\x6C\x36\x55\x6A\xE7\x7D\xF5\x96\xE6\xCA\x81\xD6\x97\xF1\x94\x83\xE9\xED\xB0\xB1\x6B\x12\x69\x1E\xAC\xFB\x5D\xA9\xC5\x98\xE9\xB4\x5B\x58\x7A\xBE\x3D\xA2\x44\x3A\x63\x59\xD4\x0B\x25\xDE\x1B\x4F\xBD\xE5\x01\x9E\xCD\xD2\x29\xD5\x9F\x17\x19\x0A\x6F\xBF\x0C\x90\xD3\x09\x5F\xD9\xE3\x8A\x35\xCC\x79\x5A\x4D\x19\x37\x92\xB7\xC4\xC1\xAD\xAF\xF4\x79\x24\x9A\xB2\x01\x0B\xB1\xAF\x5C\x96\xF3\x80\x32\xFB\x5C\x3D\x98\xF1\xA0\x3F\x4A\xDE\xBE\xAF\x94\x2E\xD9\x55\x9A\x17\x6E\x60\x9D\x63\x6C\xB8\x63\xC9\xAE\x81\x5C\x18\x35\xE0\x90\xBB\xBE\x3C\x4F\x37\x22\xB9\x7E\xEB\xCF\x9E\x77\x21\xA6\x3D\x38\x81\xFB\x48\xDA\x31\x3D\x2B\xE3\x89\xF5\xD0\xB5\xBD\x7E\xE0\x50\xC4\x12\x89\xB3\x23\x9A\x10\x31\x85\xDB\xAE\x6F\xEF\x38\x33\x18\x76\x11\x02\x03\x01\x00\x01\xA3\x82\x01\x6C\x30\x82\x01\x68\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xF9\x24\xAC\x0F\xB2\xB5\xF8\x79\xC0\xFA\x60\x88\x1B\xC4\xD9\x4D\x02\x9E\x17\x19\x30\x81\xE3\x06\x03\x55\x1D\x23\x04\x81\xDB\x30\x81\xD8\x80\x14\xF9\x24\xAC\x0F\xB2\xB5\xF8\x79\xC0\xFA\x60\x88\x1B\xC4\xD9\x4D\x02\x9E\x17\x19\xA1\x81\xB4\xA4\x81\xB1\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x82\x09\x00\xA3\xDA\x42\x7E\xA4\xB1\xAE\xDA\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x3D\x06\x03\x55\x1D\x20\x04\x36\x30\x34\x30\x32\x06\x04\x55\x1D\x20\x00\x30\x2A\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1C\x68\x74\x74\x70\x3A\x2F\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x90\x12\xAF\x22\x35\xC2\xA3\x39\xF0\x2E\xDE\xE9\xB5\xE9\x78\x7C\x48\xBE\x3F\x7D\x45\x92\x5E\xE9\xDA\xB1\x19\xFC\x16\x3C\x9F\xB4\x5B\x66\x9E\x6A\xE7\xC3\xB9\x5D\x88\xE8\x0F\xAD\xCF\x23\x0F\xDE\x25\x3A\x5E\xCC\x4F\xA5\xC1\xB5\x2D\xAC\x24\xD2\x58\x07\xDE\xA2\xCF\x69\x84\x60\x33\xE8\x10\x0D\x13\xA9\x23\xD0\x85\xE5\x8E\x7B\xA6\x9E\x3D\x72\x13\x72\x33\xF5\xAA\x7D\xC6\x63\x1F\x08\xF4\xFE\x01\x7F\x24\xCF\x2B\x2C\x54\x09\xDE\xE2\x2B\x6D\x92\xC6\x39\x4F\x16\xEA\x3C\x7E\x7A\x46\xD4\x45\x6A\x46\xA8\xEB\x75\x82\x56\xA7\xAB\xA0\x7C\x68\x13\x33\xF6\x9D\x30\xF0\x6F\x27\x39\x24\x23\x2A\x90\xFD\x90\x29\x35\xF2\x93\xDF\x34\xA5\xC6\xF7\xF8\xEF\x8C\x0F\x62\x4A\x7C\xAE\xD3\xF5\x54\xF8\x8D\xB6\x9A\x56\x87\x16\x82\x3A\x33\xAB\x5A\x22\x08\xF7\x82\xBA\xEA\x2E\xE0\x47\x9A\xB4\xB5\x45\xA3\x05\x3B\xD9\xDC\x2E\x45\x40\x3B\xEA\xDC\x7F\xE8\x3B\xEB\xD1\xEC\x26\xD8\x35\xA4\x30\xC5\x3A\xAC\x57\x9E\xB3\x76\xA5\x20\x7B\xF9\x1E\x4A\x05\x62\x01\xA6\x28\x75\x60\x97\x92\x0D\x6E\x3E\x4D\x37\x43\x0D\x92\x15\x9C\x18\x22\xCD\x51\x99\xA0\x29\x1A\x3C\x5F\x8A\x32\x33\x5B\x30\xC7\x89\x2F\x47\x98\x0F\xA3\x03\xC6\xF6\xF1\xAC\xDF\x32\xF0\xD9\x81\x1A\xE4\x9C\xBD\xF6\x80\x14\xF0\xD1\x2C\xB9\x85\xF5\xD8\xA3\xB1\xC8\xA5\x21\xE5\x1C\x13\x97\xEE\x0E\xBD\xDF\x29\xA9\xEF\x34\x53\x5B\xD3\xE4\x6A\x13\x84\x06\xB6\x32\x02\xC4\x52\xAE\x22\xD2\xDC\xB2\x21\x42\x1A\xDA\x40\xF0\x29\xC9\xEC\x0A\x0C\x5C\xE2\xD0\xBA\xCC\x48\xD3\x37\x0A\xCC\x12\x0A\x8A\x79\xB0\x3D\x03\x7F\x69\x4B\xF4\x34\x20\x7D\xB3\x34\xEA\x8E\x4B\x64\xF5\x3E\xFD\xB3\x23\x67\x15\x0D\x04\xB8\xF0\x2D\xC1\x09\x51\x3C\xB2\x6C\x15\xF0\xA5\x23\xD7\x83\x74\xE4\xE5\x2E\xC9\xFE\x98\x27\x42\xC6\xAB\xC6\x9E\xB0\xD0\x5B\x38\xA5\x9B\x50\xDE\x7E\x18\x98\xB5\x45\x3B\xF6\x79\xB4\xE8\xF7\x1A\x7B\x06\x83\xFB\xD0\x8B\xDA\xBB\xC7\xBD\x18\xAB\x08\x6F\x3C\x80\x6B\x40\x3F\x19\x19\xBA\x65\x8A\xE6\xBE\xD5\x5C\xD3\x36\xD7\xEF\x40\x52\x24\x60\x38\x67\x04\x31\xEC\x8F\xF3\x82\xC6\xDE\xB9\x55\xF3\x3B\x31\x91\x5A\xDC\xB5\x08\x15\xAD\x76\x25\x0A\x0D\x7B\x2E\x87\xE2\x0C\xA6\x06\xBC\x26\x10\x6D\x37\x9D\xEC\xDD\x78\x8C\x7C\x80\xC5\xF0\xD9\x77\x48\xD0", @@ -145,4 +141,13 @@ redef root_certs += { ["CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO"] = "\x30\x82\x05\x59\x30\x82\x03\x41\xA0\x03\x02\x01\x02\x02\x01\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x31\x30\x31\x30\x32\x36\x30\x38\x32\x38\x35\x38\x5A\x17\x0D\x34\x30\x31\x30\x32\x36\x30\x38\x32\x38\x35\x38\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xA5\xDA\x0A\x95\x16\x50\xE3\x95\xF2\x5E\x9D\x76\x31\x06\x32\x7A\x9B\xF1\x10\x76\xB8\x00\x9A\xB5\x52\x36\xCD\x24\x47\xB0\x9F\x18\x64\xBC\x9A\xF6\xFA\xD5\x79\xD8\x90\x62\x4C\x22\x2F\xDE\x38\x3D\xD6\xE0\xA8\xE9\x1C\x2C\xDB\x78\x11\xE9\x8E\x68\x51\x15\x72\xC7\xF3\x33\x87\xE4\xA0\x5D\x0B\x5C\xE0\x57\x07\x2A\x30\xF5\xCD\xC4\x37\x77\x28\x4D\x18\x91\xE6\xBF\xD5\x52\xFD\x71\x2D\x70\x3E\xE7\xC6\xC4\x8A\xE3\xF0\x28\x0B\xF4\x76\x98\xA1\x8B\x87\x55\xB2\x3A\x13\xFC\xB7\x3E\x27\x37\x8E\x22\xE3\xA8\x4F\x2A\xEF\x60\xBB\x3D\xB7\x39\xC3\x0E\x01\x47\x99\x5D\x12\x4F\xDB\x43\xFA\x57\xA1\xED\xF9\x9D\xBE\x11\x47\x26\x5B\x13\x98\xAB\x5D\x16\x8A\xB0\x37\x1C\x57\x9D\x45\xFF\x88\x96\x36\xBF\xBB\xCA\x07\x7B\x6F\x87\x63\xD7\xD0\x32\x6A\xD6\x5D\x6C\x0C\xF1\xB3\x6E\x39\xE2\x6B\x31\x2E\x39\x00\x27\x14\xDE\x38\xC0\xEC\x19\x66\x86\x12\xE8\x9D\x72\x16\x13\x64\x52\xC7\xA9\x37\x1C\xFD\x82\x30\xED\x84\x18\x1D\xF4\xAE\x5C\xFF\x70\x13\x00\xEB\xB1\xF5\x33\x7A\x4B\xD6\x55\xF8\x05\x8D\x4B\x69\xB0\xF5\xB3\x28\x36\x5C\x14\xC4\x51\x73\x4D\x6B\x0B\xF1\x34\x07\xDB\x17\x39\xD7\xDC\x28\x7B\x6B\xF5\x9F\xF3\x2E\xC1\x4F\x17\x2A\x10\xF3\xCC\xCA\xE8\xEB\xFD\x6B\xAB\x2E\x9A\x9F\x2D\x82\x6E\x04\xD4\x52\x01\x93\x2D\x3D\x86\xFC\x7E\xFC\xDF\xEF\x42\x1D\xA6\x6B\xEF\xB9\x20\xC6\xF7\xBD\xA0\xA7\x95\xFD\xA7\xE6\x89\x24\xD8\xCC\x8C\x34\x6C\xE2\x23\x2F\xD9\x12\x1A\x21\xB9\x55\x91\x6F\x0B\x91\x79\x19\x0C\xAD\x40\x88\x0B\x70\xE2\x7A\xD2\x0E\xD8\x68\x48\xBB\x82\x13\x39\x10\x58\xE9\xD8\x2A\x07\xC6\x12\xDB\x58\xDB\xD2\x3B\x55\x10\x47\x05\x15\x67\x62\x7E\x18\x63\xA6\x46\x3F\x09\x0E\x54\x32\x5E\xBF\x0D\x62\x7A\x27\xEF\x80\xE8\xDB\xD9\x4B\x06\x5A\x37\x5A\x25\xD0\x08\x12\x77\xD4\x6F\x09\x50\x97\x3D\xC8\x1D\xC3\xDF\x8C\x45\x30\x56\xC6\xD3\x64\xAB\x66\xF3\xC0\x5E\x96\x9C\xC3\xC4\xEF\xC3\x7C\x6B\x8B\x3A\x79\x7F\xB3\x49\xCF\x3D\xE2\x89\x9F\xA0\x30\x4B\x85\xB9\x9C\x94\x24\x79\x8F\x7D\x6B\xA9\x45\x68\x0F\x2B\xD0\xF1\xDA\x1C\xCB\x69\xB8\xCA\x49\x62\x6D\xC8\xD0\x63\x62\xDD\x60\x0F\x58\xAA\x8F\xA1\xBC\x05\xA5\x66\xA2\xCF\x1B\x76\xB2\x84\x64\xB1\x4C\x39\x52\xC0\x30\xBA\xF0\x8C\x4B\x02\xB0\xB6\xB7\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x47\xB8\xCD\xFF\xE5\x6F\xEE\xF8\xB2\xEC\x2F\x4E\x0E\xF9\x25\xB0\x8E\x3C\x6B\xC3\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x00\x20\x23\x41\x35\x04\x90\xC2\x40\x62\x60\xEF\xE2\x35\x4C\xD7\x3F\xAC\xE2\x34\x90\xB8\xA1\x6F\x76\xFA\x16\x16\xA4\x48\x37\x2C\xE9\x90\xC2\xF2\x3C\xF8\x0A\x9F\xD8\x81\xE5\xBB\x5B\xDA\x25\x2C\xA4\xA7\x55\x71\x24\x32\xF6\xC8\x0B\xF2\xBC\x6A\xF8\x93\xAC\xB2\x07\xC2\x5F\x9F\xDB\xCC\xC8\x8A\xAA\xBE\x6A\x6F\xE1\x49\x10\xCC\x31\xD7\x80\xBB\xBB\xC8\xD8\xA2\x0E\x64\x57\xEA\xA2\xF5\xC2\xA9\x31\x15\xD2\x20\x6A\xEC\xFC\x22\x01\x28\xCF\x86\xB8\x80\x1E\xA9\xCC\x11\xA5\x3C\xF2\x16\xB3\x47\x9D\xFC\xD2\x80\x21\xC4\xCB\xD0\x47\x70\x41\xA1\xCA\x83\x19\x08\x2C\x6D\xF2\x5D\x77\x9C\x8A\x14\x13\xD4\x36\x1C\x92\xF0\xE5\x06\x37\xDC\xA6\xE6\x90\x9B\x38\x8F\x5C\x6B\x1B\x46\x86\x43\x42\x5F\x3E\x01\x07\x53\x54\x5D\x65\x7D\xF7\x8A\x73\xA1\x9A\x54\x5A\x1F\x29\x43\x14\x27\xC2\x85\x0F\xB5\x88\x7B\x1A\x3B\x94\xB7\x1D\x60\xA7\xB5\x9C\xE7\x29\x69\x57\x5A\x9B\x93\x7A\x43\x30\x1B\x03\xD7\x62\xC8\x40\xA6\xAA\xFC\x64\xE4\x4A\xD7\x91\x53\x01\xA8\x20\x88\x6E\x9C\x5F\x44\xB9\xCB\x60\x81\x34\xEC\x6F\xD3\x7D\xDA\x48\x5F\xEB\xB4\x90\xBC\x2D\xA9\x1C\x0B\xAC\x1C\xD5\xA2\x68\x20\x80\x04\xD6\xFC\xB1\x8F\x2F\xBB\x4A\x31\x0D\x4A\x86\x1C\xEB\xE2\x36\x29\x26\xF5\xDA\xD8\xC4\xF2\x75\x61\xCF\x7E\xAE\x76\x63\x4A\x7A\x40\x65\x93\x87\xF8\x1E\x80\x8C\x86\xE5\x86\xD6\x8F\x0E\xFC\x53\x2C\x60\xE8\x16\x61\x1A\xA2\x3E\x43\x7B\xCD\x39\x60\x54\x6A\xF5\xF2\x89\x26\x01\x68\x83\x48\xA2\x33\xE8\xC9\x04\x91\xB2\x11\x34\x11\x3E\xEA\xD0\x43\x19\x1F\x03\x93\x90\x0C\xFF\x51\x3D\x57\xF4\x41\x6E\xE1\xCB\xA0\xBE\xEB\xC9\x63\xCD\x6D\xCC\xE4\xF8\x36\xAA\x68\x9D\xED\xBD\x5D\x97\x70\x44\x0D\xB6\x0E\x35\xDC\xE1\x0C\x5D\xBB\xA0\x51\x94\xCB\x7E\x16\xEB\x11\x2F\xA3\x92\x45\xC8\x4C\x71\xD9\xBC\xC9\x99\x52\x57\x46\x2F\x50\xCF\xBD\x35\x69\xF4\x3D\x15\xCE\x06\xA5\x2C\x0F\x3E\xF6\x81\xBA\x94\xBB\xC3\xBB\xBF\x65\x78\xD2\x86\x79\xFF\x49\x3B\x1A\x83\x0C\xF0\xDE\x78\xEC\xC8\xF2\x4D\x4C\x1A\xDE\x82\x29\xF8\xC1\x5A\xDA\xED\xEE\xE6\x27\x5E\xE8\x45\xD0\x9D\x1C\x51\xA8\x68\xAB\x44\xE3\xD0\x8B\x6A\xE3\xF8\x3B\xBB\xDC\x4D\xD7\x64\xF2\x51\xBE\xE6\xAA\xAB\x5A\xE9\x31\xEE\x06\xBC\x73\xBF\x13\x62\x0A\x9F\xC7\xB9\x97", ["CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE"] = "\x30\x82\x03\xC3\x30\x82\x02\xAB\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x2B\x30\x29\x06\x03\x55\x04\x0A\x0C\x22\x54\x2D\x53\x79\x73\x74\x65\x6D\x73\x20\x45\x6E\x74\x65\x72\x70\x72\x69\x73\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x47\x6D\x62\x48\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x0C\x16\x54\x2D\x53\x79\x73\x74\x65\x6D\x73\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6E\x74\x65\x72\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0C\x1C\x54\x2D\x54\x65\x6C\x65\x53\x65\x63\x20\x47\x6C\x6F\x62\x61\x6C\x52\x6F\x6F\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x30\x1E\x17\x0D\x30\x38\x31\x30\x30\x31\x31\x30\x32\x39\x35\x36\x5A\x17\x0D\x33\x33\x31\x30\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x2B\x30\x29\x06\x03\x55\x04\x0A\x0C\x22\x54\x2D\x53\x79\x73\x74\x65\x6D\x73\x20\x45\x6E\x74\x65\x72\x70\x72\x69\x73\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x47\x6D\x62\x48\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x0C\x16\x54\x2D\x53\x79\x73\x74\x65\x6D\x73\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6E\x74\x65\x72\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0C\x1C\x54\x2D\x54\x65\x6C\x65\x53\x65\x63\x20\x47\x6C\x6F\x62\x61\x6C\x52\x6F\x6F\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xBD\x75\x93\xF0\x62\x22\x6F\x24\xAE\xE0\x7A\x76\xAC\x7D\xBD\xD9\x24\xD5\xB8\xB7\xFC\xCD\xF0\x42\xE0\xEB\x78\x88\x56\x5E\x9B\x9A\x54\x1D\x4D\x0C\x8A\xF6\xD3\xCF\x70\xF4\x52\xB5\xD8\x93\x04\xE3\x46\x86\x71\x41\x4A\x2B\xF0\x2A\x2C\x55\x03\xD6\x48\xC3\xE0\x39\x38\xED\xF2\x5C\x3C\x3F\x44\xBC\x93\x3D\x61\xAB\x4E\xCD\x0D\xBE\xF0\x20\x27\x58\x0E\x44\x7F\x04\x1A\x87\xA5\xD7\x96\x14\x36\x90\xD0\x49\x7B\xA1\x75\xFB\x1A\x6B\x73\xB1\xF8\xCE\xA9\x09\x2C\xF2\x53\xD5\xC3\x14\x44\xB8\x86\xA5\xF6\x8B\x2B\x39\xDA\xA3\x33\x54\xD9\xFA\x72\x1A\xF7\x22\x15\x1C\x88\x91\x6B\x7F\x66\xE5\xC3\x6A\x80\xB0\x24\xF3\xDF\x86\x45\x88\xFD\x19\x7F\x75\x87\x1F\x1F\xB1\x1B\x0A\x73\x24\x5B\xB9\x65\xE0\x2C\x54\xC8\x60\xD3\x66\x17\x3F\xE1\xCC\x54\x33\x73\x91\x02\x3A\xA6\x7F\x7B\x76\x39\xA2\x1F\x96\xB6\x38\xAE\xB5\xC8\x93\x74\x1D\x9E\xB9\xB4\xE5\x60\x9D\x2F\x56\xD1\xE0\xEB\x5E\x5B\x4C\x12\x70\x0C\x6C\x44\x20\xAB\x11\xD8\xF4\x19\xF6\xD2\x9C\x52\x37\xE7\xFA\xB6\xC2\x31\x3B\x4A\xD4\x14\x99\xAD\xC7\x1A\xF5\x5D\x5F\xFA\x07\xB8\x7C\x0D\x1F\xD6\x83\x1E\xB3\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB5\x03\xF7\x76\x3B\x61\x82\x6A\x12\xAA\x18\x53\xEB\x03\x21\x94\xBF\xFE\xCE\xCA\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x56\x3D\xEF\x94\xD5\xBD\xDA\x73\xB2\x58\xBE\xAE\x90\xAD\x98\x27\x97\xFE\x01\xB1\xB0\x52\x00\xB8\x4D\xE4\x1B\x21\x74\x1B\x7E\xC0\xEE\x5E\x69\x2A\x25\xAF\x5C\xD6\x1D\xDA\xD2\x79\xC9\xF3\x97\x29\xE0\x86\x87\xDE\x04\x59\x0F\xF1\x59\xD4\x64\x85\x4B\x99\xAF\x25\x04\x1E\xC9\x46\xA9\x97\xDE\x82\xB2\x1B\x70\x9F\x9C\xF6\xAF\x71\x31\xDD\x7B\x05\xA5\x2C\xD3\xB9\xCA\x47\xF6\xCA\xF2\xF6\xE7\xAD\xB9\x48\x3F\xBC\x16\xB7\xC1\x6D\xF4\xEA\x09\xAF\xEC\xF3\xB5\xE7\x05\x9E\xA6\x1E\x8A\x53\x51\xD6\x93\x81\xCC\x74\x93\xF6\xB9\xDA\xA6\x25\x05\x74\x79\x5A\x7E\x40\x3E\x82\x4B\x26\x11\x30\x6E\xE1\x3F\x41\xC7\x47\x00\x35\xD5\xF5\xD3\xF7\x54\x3E\x81\x3D\xDA\x49\x6A\x9A\xB3\xEF\x10\x3D\xE6\xEB\x6F\xD1\xC8\x22\x47\xCB\xCC\xCF\x01\x31\x92\xD9\x18\xE3\x22\xBE\x09\x1E\x1A\x3E\x5A\xB2\xE4\x6B\x0C\x54\x7A\x7D\x43\x4E\xB8\x89\xA5\x7B\xD7\xA2\x3D\x96\x86\xCC\xF2\x26\x34\x2D\x6A\x92\x9D\x9A\x1A\xD0\x30\xE2\x5D\x4E\x04\xB0\x5F\x8B\x20\x7E\x77\xC1\x3D\x95\x82\xD1\x46\x9A\x3B\x3C\x78\xB8\x6F\xA1\xD0\x0D\x64\xA2\x78\x1E\x29\x4E\x93\xC3\xA4\x54\x14\x5B", ["emailAddress=pki@sk.ee,CN=EE Certification Centre Root CA,O=AS Sertifitseerimiskeskus,C=EE"] = "\x30\x82\x04\x03\x30\x82\x02\xEB\xA0\x03\x02\x01\x02\x02\x10\x54\x80\xF9\xA0\x73\xED\x3F\x00\x4C\xCA\x89\xD8\xE3\x71\xE6\x4A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x0C\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6D\x69\x73\x6B\x65\x73\x6B\x75\x73\x31\x28\x30\x26\x06\x03\x55\x04\x03\x0C\x1F\x45\x45\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x43\x65\x6E\x74\x72\x65\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x18\x30\x16\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x09\x70\x6B\x69\x40\x73\x6B\x2E\x65\x65\x30\x22\x18\x0F\x32\x30\x31\x30\x31\x30\x33\x30\x31\x30\x31\x30\x33\x30\x5A\x18\x0F\x32\x30\x33\x30\x31\x32\x31\x37\x32\x33\x35\x39\x35\x39\x5A\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x0C\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6D\x69\x73\x6B\x65\x73\x6B\x75\x73\x31\x28\x30\x26\x06\x03\x55\x04\x03\x0C\x1F\x45\x45\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x43\x65\x6E\x74\x72\x65\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x18\x30\x16\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x09\x70\x6B\x69\x40\x73\x6B\x2E\x65\x65\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xC8\x20\xC0\xEC\xE0\xC5\x4B\xAB\x07\x78\x95\xF3\x44\xEE\xFB\x0B\x0C\xFF\x74\x8E\x61\xBB\xB1\x62\xEA\x23\xD8\xAB\xA1\x65\x32\x7A\xEB\x8E\x17\x4F\x96\xD8\x0A\x7B\x91\xA2\x63\x6C\xC7\x8C\x4C\x2E\x79\xBF\xA9\x05\xFC\x69\x5C\x95\x8D\x62\xF9\xB9\x70\xED\xC3\x51\x7D\xD0\x93\xE6\x6C\xEB\x30\x4B\xE1\xBC\x7D\xBF\x52\x9B\xCE\x6E\x7B\x65\xF2\x38\xB1\xC0\xA2\x32\xEF\x62\xB2\x68\xE0\x61\x53\xC1\x36\x95\xFF\xEC\x94\xBA\x36\xAE\x9C\x1C\xA7\x32\x0F\xE5\x7C\xB4\xC6\x6F\x74\xFD\x7B\x18\xE8\xAC\x57\xED\x06\x20\x4B\x32\x30\x58\x5B\xFD\xCD\xA8\xE6\xA1\xFC\x70\xBC\x8E\x92\x73\xDB\x97\xA7\x7C\x21\xAE\x3D\xC1\xF5\x48\x87\x6C\x27\xBD\x9F\x25\x74\x81\x55\xB0\xF7\x75\xF6\x3D\xA4\x64\x6B\xD6\x4F\xE7\xCE\x40\xAD\x0F\xDD\x32\xD3\xBC\x8A\x12\x53\x98\xC9\x89\xFB\x10\x1D\x4D\x7E\xCD\x7E\x1F\x56\x0D\x21\x70\x85\xF6\x20\x83\x1F\xF6\xBA\x1F\x04\x8F\xEA\x77\x88\x35\xC4\xFF\xEA\x4E\xA1\x8B\x4D\x3F\x63\x1B\x44\xC3\x44\xD4\x25\x76\xCA\xB7\x8D\xD7\x1E\x4A\x66\x64\xCD\x5C\xC5\x9C\x83\xE1\xC2\x08\x88\x9A\xEC\x4E\xA3\xF1\x3E\x1C\x2C\xD9\x6C\x1D\xA1\x4B\x02\x03\x01\x00\x01\xA3\x81\x8A\x30\x81\x87\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x12\xF2\x5A\x3E\xEA\x56\x1C\xBF\xCD\x06\xAC\xF1\xF1\x25\xC9\xA9\x4B\xD4\x14\x99\x30\x45\x06\x03\x55\x1D\x25\x04\x3E\x30\x3C\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x02\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x03\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x04\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x08\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x09\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7B\xF6\xE4\xC0\x0D\xAA\x19\x47\xB7\x4D\x57\xA3\xFE\xAD\xBB\xB1\x6A\xD5\x0F\x9E\xDB\xE4\x63\xC5\x8E\xA1\x50\x56\x93\x96\xB8\x38\xC0\x24\x22\x66\xBC\x53\x14\x61\x95\xBF\xD0\xC7\x2A\x96\x39\x3F\x7D\x28\xB3\x10\x40\x21\x6A\xC4\xAF\xB0\x52\x77\x18\xE1\x96\xD8\x56\x5D\xE3\xDD\x36\x5E\x1D\xA7\x50\x54\xA0\xC5\x2A\xE4\xAA\x8C\x94\x8A\x4F\x9D\x35\xFF\x76\xA4\x06\x13\x91\xA2\xA2\x7D\x00\x44\x3F\x55\xD3\x82\x3C\x1A\xD5\x5B\xBC\x56\x4C\x22\x2E\x46\x43\x8A\x24\x40\x2D\xF3\x12\xB8\x3B\x70\x1A\xA4\x96\xB9\x1A\xAF\x87\x41\x1A\x6A\x18\x0D\x06\x4F\xC7\x3E\x6E\xB9\x29\x4D\x0D\x49\x89\x11\x87\x32\x5B\xE6\x4B\x04\xC8\xE4\x5C\xE6\x74\x73\x94\x5D\x16\x98\x13\x95\xFE\xFB\xDB\xB1\x44\xE5\x3A\x70\xAC\x37\x6B\xE6\xB3\x33\x72\x28\xC9\xB3\x57\xA0\xF6\x02\x16\x88\x06\x0B\xB6\xA6\x4B\x20\x28\xD4\xDE\x3D\x8B\xAD\x37\x05\x53\x74\xFE\x6E\xCC\xBC\x43\x17\x71\x5E\xF9\xC5\xCC\x1A\xA9\x61\xEE\xF7\x76\x0C\xF3\x72\xF4\x72\xAD\xCF\x72\x02\x36\x07\x47\xCF\xEF\x19\x50\x89\x60\xCC\xE9\x24\x95\x0F\xC2\xCB\x1D\xF2\x6F\x76\x90\xC7\xCC\x75\xC1\x96\xC5\x9D", + ["O=T\C3\9CRKTRUST Bilgi \C4\B0leti\C5\9Fim ve Bili\C5\9Fim G\C3\BCvenli\C4\9Fi Hizmetleri A.\C5\9E. (c) Aral\C4\B1k 2007,L=Ankara,C=TR,CN=T\C3\9CRKTRUST Elektronik Sertifika Hizmet Sa\C4\9Flay\C4\B1c\C4\B1s\C4\B1"] = "\x30\x82\x04\x3D\x30\x82\x03\x25\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBF\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x6E\x6B\x61\x72\x61\x31\x5E\x30\x5C\x06\x03\x55\x04\x0A\x0C\x55\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x20\x28\x63\x29\x20\x41\x72\x61\x6C\xC4\xB1\x6B\x20\x32\x30\x30\x37\x30\x1E\x17\x0D\x30\x37\x31\x32\x32\x35\x31\x38\x33\x37\x31\x39\x5A\x17\x0D\x31\x37\x31\x32\x32\x32\x31\x38\x33\x37\x31\x39\x5A\x30\x81\xBF\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x6E\x6B\x61\x72\x61\x31\x5E\x30\x5C\x06\x03\x55\x04\x0A\x0C\x55\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x20\x28\x63\x29\x20\x41\x72\x61\x6C\xC4\xB1\x6B\x20\x32\x30\x30\x37\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xAB\xB7\x3E\x0A\x8C\xC8\xA5\x58\x15\xE6\x8A\xEF\x27\x3D\x4A\xB4\xE8\x25\xD3\xCD\x33\xC2\x20\xDC\x19\xEE\x88\x3F\x4D\x62\xF0\xDD\x13\x77\x8F\x61\xA9\x2A\xB5\xD4\xF2\xB9\x31\x58\x29\x3B\x2F\x3F\x6A\x9C\x6F\x73\x76\x25\xEE\x34\x20\x80\xEE\xEA\xB7\xF0\xC4\x0A\xCD\x2B\x86\x94\xC9\xE3\x60\xB1\x44\x52\xB2\x5A\x29\xB4\x91\x97\x83\xD8\xB7\xA6\x14\x2F\x29\x49\xA2\xF3\x05\x06\xFB\xB4\x4F\xDA\xA1\x6C\x9A\x66\x9F\xF0\x43\x09\xCA\xEA\x72\x8F\xEB\x00\xD7\x35\x39\xD7\x56\x17\x47\x17\x30\xF4\xBE\xBF\x3F\xC2\x68\xAF\x36\x40\xC1\xA9\xF4\xA9\xA7\xE8\x10\x6B\x08\x8A\xF7\x86\x1E\xDC\x9A\x2A\x15\x06\xF6\xA3\xF0\xF4\xE0\xC7\x14\xD4\x51\x7F\xCF\xB4\xDB\x6D\xAF\x47\x96\x17\x9B\x77\x71\xD8\xA7\x71\x9D\x24\x0C\xF6\x94\x3F\x85\x31\x12\x4F\xBA\xEE\x4E\x82\xB8\xB9\x3E\x8F\x23\x37\x5E\xCC\xA2\xAA\x75\xF7\x18\x6F\x09\xD3\xAE\xA7\x54\x28\x34\xFB\xE1\xE0\x3B\x60\x7D\xA0\xBE\x79\x89\x86\xC8\x9F\x2D\xF9\x0A\x4B\xC4\x50\xA2\xE7\xFD\x79\x16\xC7\x7A\x0B\x18\xCF\xCE\x4C\xEF\x7D\xD6\x07\x6F\x98\xF1\xAF\xB1\xC1\x7A\xD7\x81\x35\xB8\xAA\x17\xB4\xE0\xCB\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x29\xC5\x90\xAB\x25\xAF\x11\xE4\x61\xBF\xA3\xFF\x88\x61\x91\xE6\x0E\xFE\x9C\x81\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x10\x0D\xDA\xF8\x3A\xEC\x28\xD1\x14\x95\x82\xB1\x12\x2C\x51\x7A\x41\x25\x36\x4C\x9F\xEC\x3F\x1F\x84\x9D\x65\x54\x5C\xA8\x16\x02\x40\xFA\x6E\x1A\x37\x84\xEF\x72\x9D\x86\x0A\x55\x9D\x56\x28\xAC\x66\x2C\xD0\x3A\x56\x93\x34\x07\x25\xAD\x08\xB0\x8F\xC8\x0F\x09\x59\xCA\x9D\x98\x1C\xE5\x54\xF8\xB9\x45\x7F\x6A\x97\x6F\x88\x68\x4D\x4A\x06\x26\x37\x88\x02\x0E\xB6\xC6\xD6\x72\x99\xCE\x6B\x77\xDA\x62\x31\xA4\x56\x1F\xAE\x5F\x8D\x77\xDA\x5D\xF6\x88\xFC\x1A\xD9\x9E\xB5\x81\xF0\x32\xB8\xE3\x88\xD0\x9C\xF3\x6A\xA0\xB9\x9B\x14\x59\x35\x36\x4F\xCF\xF3\x8E\x5E\x5D\x17\xAD\x15\x95\xD8\xDD\xB2\xD5\x15\x6E\x00\x4E\xB3\x4B\xCF\x66\x94\xE4\xE0\xCD\xB5\x05\xDA\x63\x57\x8B\xE5\xB3\xAA\xDB\xC0\x2E\x1C\x90\x44\xDB\x1A\x5D\x18\xA4\xEE\xBE\x04\x5B\x99\xD5\x71\x5F\x55\x65\x64\x62\xD5\xA2\x9B\x04\x59\x86\xC8\x62\x77\xE7\x7C\x82\x45\x6A\x3D\x17\xBF\xEC\x9D\x75\x0C\xAE\xA3\x6F\x5A\xD3\x2F\x98\x36\xF4\xF0\xF5\x19\xAB\x11\x5D\xC8\xA6\xE3\x2A\x58\x6A\x42\x09\xC3\xBD\x92\x26\x66\x32\x0D\x5D\x08\x55\x74\xFF\x8C\x98\xD0\x0A\xA6\x84\x6A\xD1\x39\x7D", + ["CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE"] = "\x30\x82\x04\x33\x30\x82\x03\x1B\xA0\x03\x02\x01\x02\x02\x03\x09\x83\xF3\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x4D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x0C\x0C\x44\x2D\x54\x72\x75\x73\x74\x20\x47\x6D\x62\x48\x31\x27\x30\x25\x06\x03\x55\x04\x03\x0C\x1E\x44\x2D\x54\x52\x55\x53\x54\x20\x52\x6F\x6F\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x32\x20\x32\x30\x30\x39\x30\x1E\x17\x0D\x30\x39\x31\x31\x30\x35\x30\x38\x33\x35\x35\x38\x5A\x17\x0D\x32\x39\x31\x31\x30\x35\x30\x38\x33\x35\x35\x38\x5A\x30\x4D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x0C\x0C\x44\x2D\x54\x72\x75\x73\x74\x20\x47\x6D\x62\x48\x31\x27\x30\x25\x06\x03\x55\x04\x03\x0C\x1E\x44\x2D\x54\x52\x55\x53\x54\x20\x52\x6F\x6F\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x32\x20\x32\x30\x30\x39\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\xD3\xB2\x4A\xCF\x7A\x47\xEF\x75\x9B\x23\xFA\x3A\x2F\xD6\x50\x45\x89\x35\x3A\xC6\x6B\xDB\xFE\xDB\x00\x68\xA8\xE0\x03\x11\x1D\x37\x50\x08\x9F\x4D\x4A\x68\x94\x35\xB3\x53\xD1\x94\x63\xA7\x20\x56\xAF\xDE\x51\x78\xEC\x2A\x3D\xF3\x48\x48\x50\x3E\x0A\xDF\x46\x55\x8B\x27\x6D\xC3\x10\x4D\x0D\x91\x52\x43\xD8\x87\xE0\x5D\x4E\x36\xB5\x21\xCA\x5F\x39\x40\x04\x5F\x5B\x7E\xCC\xA3\xC6\x2B\xA9\x40\x1E\xD9\x36\x84\xD6\x48\xF3\x92\x1E\x34\x46\x20\x24\xC1\xA4\x51\x8E\x4A\x1A\xEF\x50\x3F\x69\x5D\x19\x7F\x45\xC3\xC7\x01\x8F\x51\xC9\x23\xE8\x72\xAE\xB4\xBC\x56\x09\x7F\x12\xCB\x1C\xB1\xAF\x29\x90\x0A\xC9\x55\xCC\x0F\xD3\xB4\x1A\xED\x47\x35\x5A\x4A\xED\x9C\x73\x04\x21\xD0\xAA\xBD\x0C\x13\xB5\x00\xCA\x26\x6C\xC4\x6B\x0C\x94\x5A\x95\x94\xDA\x50\x9A\xF1\xFF\xA5\x2B\x66\x31\xA4\xC9\x38\xA0\xDF\x1D\x1F\xB8\x09\x2E\xF3\xA7\xE8\x67\x52\xAB\x95\x1F\xE0\x46\x3E\xD8\xA4\xC3\xCA\x5A\xC5\x31\x80\xE8\x48\x9A\x9F\x94\x69\xFE\x19\xDD\xD8\x73\x7C\x81\xCA\x96\xDE\x8E\xED\xB3\x32\x05\x65\x84\x34\xE6\xE6\xFD\x57\x10\xB5\x5F\x76\xBF\x2F\xB0\x10\x0D\xC5\x02\x03\x01\x00\x01\xA3\x82\x01\x1A\x30\x82\x01\x16\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xFD\xDA\x14\xC4\x9F\x30\xDE\x21\xBD\x1E\x42\x39\xFC\xAB\x63\x23\x49\xE0\xF1\x84\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x81\xD3\x06\x03\x55\x1D\x1F\x04\x81\xCB\x30\x81\xC8\x30\x81\x80\xA0\x7E\xA0\x7C\x86\x7A\x6C\x64\x61\x70\x3A\x2F\x2F\x64\x69\x72\x65\x63\x74\x6F\x72\x79\x2E\x64\x2D\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x4E\x3D\x44\x2D\x54\x52\x55\x53\x54\x25\x32\x30\x52\x6F\x6F\x74\x25\x32\x30\x43\x6C\x61\x73\x73\x25\x32\x30\x33\x25\x32\x30\x43\x41\x25\x32\x30\x32\x25\x32\x30\x32\x30\x30\x39\x2C\x4F\x3D\x44\x2D\x54\x72\x75\x73\x74\x25\x32\x30\x47\x6D\x62\x48\x2C\x43\x3D\x44\x45\x3F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x72\x65\x76\x6F\x63\x61\x74\x69\x6F\x6E\x6C\x69\x73\x74\x30\x43\xA0\x41\xA0\x3F\x86\x3D\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x64\x2D\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x63\x72\x6C\x2F\x64\x2D\x74\x72\x75\x73\x74\x5F\x72\x6F\x6F\x74\x5F\x63\x6C\x61\x73\x73\x5F\x33\x5F\x63\x61\x5F\x32\x5F\x32\x30\x30\x39\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x7F\x97\xDB\x30\xC8\xDF\xA4\x9C\x7D\x21\x7A\x80\x70\xCE\x14\x12\x69\x88\x14\x95\x60\x44\x01\xAC\xB2\xE9\x30\x4F\x9B\x50\xC2\x66\xD8\x7E\x8D\x30\xB5\x70\x31\xE9\xE2\x69\xC7\xF3\x70\xDB\x20\x15\x86\xD0\x0D\xF0\xBE\xAC\x01\x75\x84\xCE\x7E\x9F\x4D\xBF\xB7\x60\x3B\x9C\xF3\xCA\x1D\xE2\x5E\x68\xD8\xA3\x9D\x97\xE5\x40\x60\xD2\x36\x21\xFE\xD0\xB4\xB8\x17\xDA\x74\xA3\x7F\xD4\xDF\xB0\x98\x02\xAC\x6F\x6B\x6B\x2C\x25\x24\x72\xA1\x65\xEE\x25\x5A\xE5\xE6\x32\xE7\xF2\xDF\xAB\x49\xFA\xF3\x90\x69\x23\xDB\x04\xD9\xE7\x5C\x58\xFC\x65\xD4\x97\xBE\xCC\xFC\x2E\x0A\xCC\x25\x2A\x35\x04\xF8\x60\x91\x15\x75\x3D\x41\xFF\x23\x1F\x19\xC8\x6C\xEB\x82\x53\x04\xA6\xE4\x4C\x22\x4D\x8D\x8C\xBA\xCE\x5B\x73\xEC\x64\x54\x50\x6D\xD1\x9C\x55\xFB\x69\xC3\x36\xC3\x8C\xBC\x3C\x85\xA6\x6B\x0A\x26\x0D\xE0\x93\x98\x60\xAE\x7E\xC6\x24\x97\x8A\x61\x5F\x91\x8E\x66\x92\x09\x87\x36\xCD\x8B\x9B\x2D\x3E\xF6\x51\xD4\x50\xD4\x59\x28\xBD\x83\xF2\xCC\x28\x7B\x53\x86\x6D\xD8\x26\x88\x70\xD7\xEA\x91\xCD\x3E\xB9\xCA\xC0\x90\x6E\x5A\xC6\x5E\x74\x65\xD7\x5C\xFE\xA3\xE2", + ["CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE"] = "\x30\x82\x04\x43\x30\x82\x03\x2B\xA0\x03\x02\x01\x02\x02\x03\x09\x83\xF4\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x50\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x0C\x0C\x44\x2D\x54\x72\x75\x73\x74\x20\x47\x6D\x62\x48\x31\x2A\x30\x28\x06\x03\x55\x04\x03\x0C\x21\x44\x2D\x54\x52\x55\x53\x54\x20\x52\x6F\x6F\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x32\x20\x45\x56\x20\x32\x30\x30\x39\x30\x1E\x17\x0D\x30\x39\x31\x31\x30\x35\x30\x38\x35\x30\x34\x36\x5A\x17\x0D\x32\x39\x31\x31\x30\x35\x30\x38\x35\x30\x34\x36\x5A\x30\x50\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x0C\x0C\x44\x2D\x54\x72\x75\x73\x74\x20\x47\x6D\x62\x48\x31\x2A\x30\x28\x06\x03\x55\x04\x03\x0C\x21\x44\x2D\x54\x52\x55\x53\x54\x20\x52\x6F\x6F\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x32\x20\x45\x56\x20\x32\x30\x30\x39\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\x99\xF1\x84\x34\x70\xBA\x2F\xB7\x30\xA0\x8E\xBD\x7C\x04\xCF\xBE\x62\xBC\x99\xFD\x82\x97\xD2\x7A\x0A\x67\x96\x38\x09\xF6\x10\x4E\x95\x22\x73\x99\x8D\xDA\x15\x2D\xE7\x05\xFC\x19\x73\x22\xB7\x8E\x98\x00\xBC\x3C\x3D\xAC\xA1\x6C\xFB\xD6\x79\x25\x4B\xAD\xF0\xCC\x64\xDA\x88\x3E\x29\xB8\x0F\x09\xD3\x34\xDD\x33\xF5\x62\xD1\xE1\xCD\x19\xE9\xEE\x18\x4F\x4C\x58\xAE\xE2\x1E\xD6\x0C\x5B\x15\x5A\xD8\x3A\xB8\xC4\x18\x64\x1E\xE3\x33\xB2\xB5\x89\x77\x4E\x0C\xBF\xD9\x94\x6B\x13\x97\x6F\x12\xA3\xFE\x99\xA9\x04\xCC\x15\xEC\x60\x68\x36\xED\x08\x7B\xB7\xF5\xBF\x93\xED\x66\x31\x83\x8C\xC6\x71\x34\x87\x4E\x17\xEA\xAF\x8B\x91\x8D\x1C\x56\x41\xAE\x22\x37\x5E\x37\xF2\x1D\xD9\xD1\x2D\x0D\x2F\x69\x51\xA7\xBE\x66\xA6\x8A\x3A\x2A\xBD\xC7\x1A\xB1\xE1\x14\xF0\xBE\x3A\x1D\xB9\xCF\x5B\xB1\x6A\xFE\xB4\xB1\x46\x20\xA2\xFB\x1E\x3B\x70\xEF\x93\x98\x7D\x8C\x73\x96\xF2\xC5\xEF\x85\x70\xAD\x29\x26\xFC\x1E\x04\x3E\x1C\xA0\xD8\x0F\xCB\x52\x83\x62\x7C\xEE\x8B\x53\x95\x90\xA9\x57\xA2\xEA\x61\x05\xD8\xF9\x4D\xC4\x27\xFA\x6E\xAD\xED\xF9\xD7\x51\xF7\x6B\xA5\x02\x03\x01\x00\x01\xA3\x82\x01\x24\x30\x82\x01\x20\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD3\x94\x8A\x4C\x62\x13\x2A\x19\x2E\xCC\xAF\x72\x8A\x7D\x36\xD7\x9A\x1C\xDC\x67\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x81\xDD\x06\x03\x55\x1D\x1F\x04\x81\xD5\x30\x81\xD2\x30\x81\x87\xA0\x81\x84\xA0\x81\x81\x86\x7F\x6C\x64\x61\x70\x3A\x2F\x2F\x64\x69\x72\x65\x63\x74\x6F\x72\x79\x2E\x64\x2D\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x4E\x3D\x44\x2D\x54\x52\x55\x53\x54\x25\x32\x30\x52\x6F\x6F\x74\x25\x32\x30\x43\x6C\x61\x73\x73\x25\x32\x30\x33\x25\x32\x30\x43\x41\x25\x32\x30\x32\x25\x32\x30\x45\x56\x25\x32\x30\x32\x30\x30\x39\x2C\x4F\x3D\x44\x2D\x54\x72\x75\x73\x74\x25\x32\x30\x47\x6D\x62\x48\x2C\x43\x3D\x44\x45\x3F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x72\x65\x76\x6F\x63\x61\x74\x69\x6F\x6E\x6C\x69\x73\x74\x30\x46\xA0\x44\xA0\x42\x86\x40\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x64\x2D\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x63\x72\x6C\x2F\x64\x2D\x74\x72\x75\x73\x74\x5F\x72\x6F\x6F\x74\x5F\x63\x6C\x61\x73\x73\x5F\x33\x5F\x63\x61\x5F\x32\x5F\x65\x76\x5F\x32\x30\x30\x39\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x34\xED\x7B\x5A\x3C\xA4\x94\x88\xEF\x1A\x11\x75\x07\x2F\xB3\xFE\x3C\xFA\x1E\x51\x26\xEB\x87\xF6\x29\xDE\xE0\xF1\xD4\xC6\x24\x09\xE9\xC1\xCF\x55\x1B\xB4\x30\xD9\xCE\x1A\xFE\x06\x51\xA6\x15\xA4\x2D\xEF\xB2\x4B\xBF\x20\x28\x25\x49\xD1\xA6\x36\x77\x34\xE8\x64\xDF\x52\xB1\x11\xC7\x73\x7A\xCD\x39\x9E\xC2\xAD\x8C\x71\x21\xF2\x5A\x6B\xAF\xDF\x3C\x4E\x55\xAF\xB2\x84\x65\x14\x89\xB9\x77\xCB\x2A\x31\xBE\xCF\xA3\x6D\xCF\x6F\x48\x94\x32\x46\x6F\xE7\x71\x8C\xA0\xA6\x84\x19\x37\x07\xF2\x03\x45\x09\x2B\x86\x75\x7C\xDF\x5F\x69\x57\x00\xDB\x6E\xD8\xA6\x72\x22\x4B\x50\xD4\x75\x98\x56\xDF\xB7\x18\xFF\x43\x43\x50\xAE\x7A\x44\x7B\xF0\x79\x51\xD7\x43\x3D\xA7\xD3\x81\xD3\xF0\xC9\x4F\xB9\xDA\xC6\x97\x86\xD0\x82\xC3\xE4\x42\x6D\xFE\xB0\xE2\x64\x4E\x0E\x26\xE7\x40\x34\x26\xB5\x08\x89\xD7\x08\x63\x63\x38\x27\x75\x1E\x33\xEA\x6E\xA8\xDD\x9F\x99\x4F\x74\x4D\x81\x89\x80\x4B\xDD\x9A\x97\x29\x5C\x2F\xBE\x81\x41\xB9\x8C\xFF\xEA\x7D\x60\x06\x9E\xCD\xD7\x3D\xD3\x2E\xA3\x15\xBC\xA8\xE6\x26\xE5\x6F\xC3\xDC\xB8\x03\x21\xEA\x9F\x16\xF1\x2C\x54\xB5", + ["CN=PSCProcert,C=VE,O=Sistema Nacional de Certificacion Electronica,OU=Proveedor de Certificados PROCERT,ST=Miranda,L=Chacao,emailAddress=contacto@procert.net.ve"] = "\x30\x82\x09\x86\x30\x82\x07\x6E\xA0\x03\x02\x01\x02\x02\x01\x0B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x82\x01\x1E\x31\x3E\x30\x3C\x06\x03\x55\x04\x03\x13\x35\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x52\x61\x69\x7A\x20\x64\x65\x6C\x20\x45\x73\x74\x61\x64\x6F\x20\x56\x65\x6E\x65\x7A\x6F\x6C\x61\x6E\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x56\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x43\x61\x72\x61\x63\x61\x73\x31\x19\x30\x17\x06\x03\x55\x04\x08\x13\x10\x44\x69\x73\x74\x72\x69\x74\x6F\x20\x43\x61\x70\x69\x74\x61\x6C\x31\x36\x30\x34\x06\x03\x55\x04\x0A\x13\x2D\x53\x69\x73\x74\x65\x6D\x61\x20\x4E\x61\x63\x69\x6F\x6E\x61\x6C\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x45\x6C\x65\x63\x74\x72\x6F\x6E\x69\x63\x61\x31\x43\x30\x41\x06\x03\x55\x04\x0B\x13\x3A\x53\x75\x70\x65\x72\x69\x6E\x74\x65\x6E\x64\x65\x6E\x63\x69\x61\x20\x64\x65\x20\x53\x65\x72\x76\x69\x63\x69\x6F\x73\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x45\x6C\x65\x63\x74\x72\x6F\x6E\x69\x63\x61\x31\x25\x30\x23\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x16\x61\x63\x72\x61\x69\x7A\x40\x73\x75\x73\x63\x65\x72\x74\x65\x2E\x67\x6F\x62\x2E\x76\x65\x30\x1E\x17\x0D\x31\x30\x31\x32\x32\x38\x31\x36\x35\x31\x30\x30\x5A\x17\x0D\x32\x30\x31\x32\x32\x35\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xD1\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x63\x6F\x6E\x74\x61\x63\x74\x6F\x40\x70\x72\x6F\x63\x65\x72\x74\x2E\x6E\x65\x74\x2E\x76\x65\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x13\x06\x43\x68\x61\x63\x61\x6F\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x4D\x69\x72\x61\x6E\x64\x61\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x13\x21\x50\x72\x6F\x76\x65\x65\x64\x6F\x72\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x64\x6F\x73\x20\x50\x52\x4F\x43\x45\x52\x54\x31\x36\x30\x34\x06\x03\x55\x04\x0A\x13\x2D\x53\x69\x73\x74\x65\x6D\x61\x20\x4E\x61\x63\x69\x6F\x6E\x61\x6C\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x45\x6C\x65\x63\x74\x72\x6F\x6E\x69\x63\x61\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x56\x45\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x50\x53\x43\x50\x72\x6F\x63\x65\x72\x74\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xD5\xB7\xF4\xA3\x94\x33\xA1\x46\xA9\x55\x61\x49\x0D\xA8\x87\x73\x5E\x91\x2D\x70\xC1\x06\x1A\x94\xDA\x3D\xEC\x15\x42\xC1\xF5\x8C\xAE\x6A\x17\xF1\x8A\xAD\xFC\x80\x95\xEA\x83\x44\xA2\x5B\x7A\x55\xCE\x4F\xA7\xA5\xD5\xBA\xB8\x1F\xA0\x27\xC0\x50\x53\x3E\x8D\xB9\xC0\x0E\xB8\x15\xDC\xD6\x6C\xF8\x9E\xF8\x04\x25\xDF\x80\x8F\x10\x85\xDD\x7D\x2F\x7B\x80\xDD\x57\x00\x64\x23\xF8\x6E\xC9\xBE\x95\x4F\xE1\x75\xEC\xE0\x7E\x5E\x95\xCD\xB1\xEF\xBE\x7A\x42\xD8\xC9\x2C\xD3\xEB\x1A\x1A\x22\x8B\xB7\x7F\x06\x89\xE5\x3C\xF5\x12\xC0\xBB\xD3\x0B\x99\x5F\x90\x7C\x8E\x2D\x2F\x77\x33\x92\x4A\x21\x46\xA8\xA9\x08\xAC\xF1\xF6\x11\x02\xD9\x95\x16\x9E\x8D\x2F\x96\xE6\x02\xDD\x75\xC2\x14\x2A\x5A\xD6\xC9\x7D\x25\xC2\xC1\xFC\xAA\x67\x85\xE2\xEC\xBE\xD1\x7C\x3C\xFA\xAF\xD5\x6E\xFF\x53\x41\xD4\xF5\x32\x38\xB1\xE2\x5F\xC4\xF9\x8E\x10\xEF\x06\xA9\x02\x89\xFF\xE3\x0C\x6E\x97\xE0\xDF\x9D\xDB\x21\xD0\xF4\x3E\x08\x69\x6C\xD8\xD4\xE4\x36\xF8\x83\xB6\xB2\x36\x8F\x9C\xEF\x3A\x37\x16\x7D\xBF\xA2\x69\xD7\x3B\x5B\x72\xD0\xAF\xAA\x3F\x5C\x66\x93\xAC\x0A\x22\x61\xB6\xD2\xA0\x99\xC8\x54\x93\x5D\xA8\xB6\xD1\xBD\x5D\x0A\x5E\x77\x94\xA2\x2D\xC0\x82\x8E\xBC\xCA\x03\x2A\x34\xAE\x73\xF1\xD4\xB5\x0C\xBD\xBE\x67\x9B\x54\xEB\xE1\xFA\xA0\x5A\xEC\x38\x7E\x3E\xC1\xCC\xA2\xC7\x44\x31\x75\xEA\x3F\xE5\x07\xD2\xAB\xA1\x25\x96\xF6\xE6\xE4\xA0\x5D\x37\x18\x39\x61\x00\x33\x5D\x46\xD4\x00\xC4\xB4\xCA\x3C\xF1\xA2\xA3\x3E\xF3\x3A\xFF\x69\x30\x2E\x40\xDD\xF6\x9F\x9C\x26\xC9\x96\x37\xAD\xE7\x39\xA2\xBF\xEA\x69\xDB\x55\x22\x95\x53\x2A\x94\xB5\xDF\xAD\x16\x38\x81\x75\x66\xE3\xC7\x2C\x1B\x93\x9C\xAA\x8C\xA3\xCA\xD9\x6C\x3C\x17\x6D\x9C\xDC\x7C\x53\xE0\x20\x27\x43\x36\xF9\x12\xE1\x3C\x5C\xBD\x66\xBF\xA2\x69\x23\x38\xB8\x99\x60\x99\x0E\x56\x53\x3A\x9C\x7E\x14\x8C\xB0\x06\x6F\xF1\x86\x76\x90\xAF\xFD\xAF\xFE\x90\xC6\x8F\x9F\x7F\x8B\x92\x23\x9C\xE7\x15\x76\x8F\xD5\x8B\x94\x13\x72\x69\xFB\x2B\x61\x63\x88\xEF\xE6\xA4\x5E\xE6\xA3\x17\x6A\x58\x47\xCB\x71\x4F\x14\x0B\x5E\xC8\x02\x08\x26\xA2\xCB\xE9\xAF\x6B\x8A\x19\xC7\xCB\x14\x56\xF5\xE1\xDA\xB5\xD9\xFC\xBF\x73\x38\xDA\xF9\xE7\xAF\x6E\xA4\x37\xE2\x07\x27\x02\x03\x01\x00\x01\xA3\x82\x03\x17\x30\x82\x03\x13\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x01\x30\x37\x06\x03\x55\x1D\x12\x04\x30\x30\x2E\x82\x0F\x73\x75\x73\x63\x65\x72\x74\x65\x2E\x67\x6F\x62\x2E\x76\x65\xA0\x1B\x06\x05\x60\x86\x5E\x02\x02\xA0\x12\x0C\x10\x52\x49\x46\x2D\x47\x2D\x32\x30\x30\x30\x34\x30\x33\x36\x2D\x30\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x41\x0F\x19\x38\xAA\x99\x7F\x42\x0B\xA4\xD7\x27\x98\x54\xA2\x17\x4C\x2D\x51\x54\x30\x82\x01\x50\x06\x03\x55\x1D\x23\x04\x82\x01\x47\x30\x82\x01\x43\x80\x14\xAD\xBB\x22\x1D\xC6\xE0\xD2\x01\xA8\xFD\x76\x50\x52\x93\xED\x98\xC1\x4D\xAE\xD3\xA1\x82\x01\x26\xA4\x82\x01\x22\x30\x82\x01\x1E\x31\x3E\x30\x3C\x06\x03\x55\x04\x03\x13\x35\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x52\x61\x69\x7A\x20\x64\x65\x6C\x20\x45\x73\x74\x61\x64\x6F\x20\x56\x65\x6E\x65\x7A\x6F\x6C\x61\x6E\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x56\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x43\x61\x72\x61\x63\x61\x73\x31\x19\x30\x17\x06\x03\x55\x04\x08\x13\x10\x44\x69\x73\x74\x72\x69\x74\x6F\x20\x43\x61\x70\x69\x74\x61\x6C\x31\x36\x30\x34\x06\x03\x55\x04\x0A\x13\x2D\x53\x69\x73\x74\x65\x6D\x61\x20\x4E\x61\x63\x69\x6F\x6E\x61\x6C\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x45\x6C\x65\x63\x74\x72\x6F\x6E\x69\x63\x61\x31\x43\x30\x41\x06\x03\x55\x04\x0B\x13\x3A\x53\x75\x70\x65\x72\x69\x6E\x74\x65\x6E\x64\x65\x6E\x63\x69\x61\x20\x64\x65\x20\x53\x65\x72\x76\x69\x63\x69\x6F\x73\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x45\x6C\x65\x63\x74\x72\x6F\x6E\x69\x63\x61\x31\x25\x30\x23\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x16\x61\x63\x72\x61\x69\x7A\x40\x73\x75\x73\x63\x65\x72\x74\x65\x2E\x67\x6F\x62\x2E\x76\x65\x82\x01\x0A\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x4D\x06\x03\x55\x1D\x11\x04\x46\x30\x44\x82\x0E\x70\x72\x6F\x63\x65\x72\x74\x2E\x6E\x65\x74\x2E\x76\x65\xA0\x15\x06\x05\x60\x86\x5E\x02\x01\xA0\x0C\x0C\x0A\x50\x53\x43\x2D\x30\x30\x30\x30\x30\x32\xA0\x1B\x06\x05\x60\x86\x5E\x02\x02\xA0\x12\x0C\x10\x52\x49\x46\x2D\x4A\x2D\x33\x31\x36\x33\x35\x33\x37\x33\x2D\x37\x30\x76\x06\x03\x55\x1D\x1F\x04\x6F\x30\x6D\x30\x46\xA0\x44\xA0\x42\x86\x40\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x73\x75\x73\x63\x65\x72\x74\x65\x2E\x67\x6F\x62\x2E\x76\x65\x2F\x6C\x63\x72\x2F\x43\x45\x52\x54\x49\x46\x49\x43\x41\x44\x4F\x2D\x52\x41\x49\x5A\x2D\x53\x48\x41\x33\x38\x34\x43\x52\x4C\x44\x45\x52\x2E\x63\x72\x6C\x30\x23\xA0\x21\xA0\x1F\x86\x1D\x6C\x64\x61\x70\x3A\x2F\x2F\x61\x63\x72\x61\x69\x7A\x2E\x73\x75\x73\x63\x65\x72\x74\x65\x2E\x67\x6F\x62\x2E\x76\x65\x30\x37\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x01\x04\x2B\x30\x29\x30\x27\x06\x08\x2B\x06\x01\x05\x05\x07\x30\x01\x86\x1B\x68\x74\x74\x70\x3A\x2F\x2F\x6F\x63\x73\x70\x2E\x73\x75\x73\x63\x65\x72\x74\x65\x2E\x67\x6F\x62\x2E\x76\x65\x30\x41\x06\x03\x55\x1D\x20\x04\x3A\x30\x38\x30\x36\x06\x06\x60\x86\x5E\x03\x01\x02\x30\x2C\x30\x2A\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1E\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x73\x75\x73\x63\x65\x72\x74\x65\x2E\x67\x6F\x62\x2E\x76\x65\x2F\x64\x70\x63\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x2B\x59\xEB\x22\x99\xBB\x84\xAA\x4F\xDE\x90\xC6\xD1\x86\x71\x23\x9E\x4B\x03\x91\x47\x70\xBB\xC0\x92\x60\xEC\xE0\xD4\xE7\x6D\xC6\xD3\xED\x67\x83\x77\x52\xD5\xF2\xE5\x77\xA7\x36\xB2\xE3\x54\xBE\xD9\xBB\x0A\x9B\x11\xEF\x61\xF4\xC6\x99\x33\x99\xF5\xAF\x00\x39\x8D\x83\xBF\xA6\xBD\x35\x7E\x2C\x5C\x31\x34\x6F\x6C\xDB\xF3\x64\x01\x98\xAA\x94\x2C\x41\xDD\x15\x86\xCA\x6B\x29\x4E\x16\xC0\x49\xFC\xD7\x83\x48\x13\x07\x51\x84\x31\x52\x88\xBB\x86\x17\xC7\x6B\x2F\x8A\x20\xAD\xC5\x0B\x8F\x70\x3E\x2A\xBB\x1B\x71\x8F\xB9\xA4\xA0\xFD\xD8\x95\xD9\xAF\x59\xBF\x25\x2B\x98\xE9\x63\x93\x2F\x60\x1E\xC4\xAA\xF8\x77\xF5\x8B\x6C\x2F\xED\x7E\x2E\xB5\x4F\x40\x0D\xEE\xBC\x57\x77\xE7\xD9\xB6\xD4\x3F\x95\x27\x3A\x20\xD5\xE5\xAE\xAB\x6C\x35\x9F\xC1\xA1\x1D\x59\xDC\x84\x81\xEE\x4D\x07\xE2\x48\xB6\x9E\x4B\x95\x2D\x41\xB1\xE1\xE8\xDE\x7E\x2F\x05\x1E\x68\xEE\xBF\xBB\x90\x65\x3A\xC8\xEE\xEA\xB1\x18\x37\x1C\x62\x93\xA4\xA0\x31\xEC\x71\x6C\x91\xE6\xA4\x79\x89\x5A\x14\xA7\x14\x50\x05\x4C\xA4\x00\x57\x30\x2C\xC1\xB5\x61\x96\xDC\x3E\x1E\x84\xAF\x39\x42\xCF\xE5\xD0\x2C\xB1\x24\xBC\xDF\x40\xC3\xED\x7F\x63\x4A\xBD\xE1\x4F\x12\x64\x86\x95\xF3\xB0\xE7\xC8\xB7\xE1\x53\xBD\x92\xE6\xF3\x0C\x96\xB9\xEB\xE8\xE6\x92\xED\xA7\x81\x09\x14\x0B\xFC\x95\x7A\xCF\x8F\xD6\x34\x4F\x36\x12\xDC\x5E\xD1\x34\x75\xC6\x46\x80\x2F\x95\x04\x8C\xC7\x86\xC4\xA8\x26\x89\xA8\x3F\x19\x9B\x81\xBB\x51\xA4\x4A\x86\xAB\x0B\x11\x0F\xB1\xAE\x63\x53\x6D\x28\xEA\xDD\x33\x56\x38\x1C\xB2\xAD\x80\xD3\xD7\x72\xBD\x9A\x6C\x99\x63\xE8\x00\xBB\x41\x76\x05\xB7\x5B\x99\x18\x8A\xC3\xB8\x12\x5C\x56\xCF\x56\x0C\x7D\xE8\xE2\xCF\xED\xBC\x74\x47\xFB\xEE\xD3\x17\x4E\x22\x4F\x56\xFF\x50\xF3\x2E\xE6\x39\xA6\x82\xD6\x71\xCA\xDE\xB7\xD5\xBA\x68\x08\xED\x99\xCC\xFD\xA2\x92\xCB\x69\xB8\x9D\xF9\x0A\xA4\xA6\x3E\x4F\x93\x28\x2A\x61\x6C\x07\x26\x00\xFF\x96\x5F\x68\x86\xB8\xB8\xCE\xCA\x55\xE0\xAB\xB1\x3D\x7F\x98\xD7\x33\x0E\x5A\x3D\xD8\x78\xC2\xC4\x60\x2F\xC7\x62\xF0\x61\x91\xD2\x38\xB0\xF6\x9E\x55\xDB\x40\x80\x05\x12\x33\xCE\x1D\x92\x9B\xD1\x69\xB3\xFF\xBF\xF1\x92\x0A\x61\x35\x3F\xDD\xFE\x86\xF4\xBC\xE0\x1A\x71\xB3\x62\xA6", + ["CN=China Internet Network Information Center EV Certificates Root,O=China Internet Network Information Center,C=CN"] = "\x30\x82\x03\xF7\x30\x82\x02\xDF\xA0\x03\x02\x01\x02\x02\x04\x48\x9F\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x8A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4E\x31\x32\x30\x30\x06\x03\x55\x04\x0A\x0C\x29\x43\x68\x69\x6E\x61\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x20\x49\x6E\x66\x6F\x72\x6D\x61\x74\x69\x6F\x6E\x20\x43\x65\x6E\x74\x65\x72\x31\x47\x30\x45\x06\x03\x55\x04\x03\x0C\x3E\x43\x68\x69\x6E\x61\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x20\x49\x6E\x66\x6F\x72\x6D\x61\x74\x69\x6F\x6E\x20\x43\x65\x6E\x74\x65\x72\x20\x45\x56\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x31\x30\x30\x38\x33\x31\x30\x37\x31\x31\x32\x35\x5A\x17\x0D\x33\x30\x30\x38\x33\x31\x30\x37\x31\x31\x32\x35\x5A\x30\x81\x8A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4E\x31\x32\x30\x30\x06\x03\x55\x04\x0A\x0C\x29\x43\x68\x69\x6E\x61\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x20\x49\x6E\x66\x6F\x72\x6D\x61\x74\x69\x6F\x6E\x20\x43\x65\x6E\x74\x65\x72\x31\x47\x30\x45\x06\x03\x55\x04\x03\x0C\x3E\x43\x68\x69\x6E\x61\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x20\x49\x6E\x66\x6F\x72\x6D\x61\x74\x69\x6F\x6E\x20\x43\x65\x6E\x74\x65\x72\x20\x45\x56\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x52\x6F\x6F\x74\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01\x00\x9B\x7E\x73\xEE\xBD\x3B\x78\xAA\x64\x43\x41\xF5\x50\xDF\x94\xF2\x2E\xB2\x8D\x4A\x8E\x46\x54\xD2\x21\x12\xC8\x39\x32\x42\x06\xE9\x83\xD5\x9F\x52\xED\xE5\x67\x03\x3B\x54\xC1\x8C\x99\x99\xCC\xE9\xC0\x0F\xFF\x0D\xD9\x84\x11\xB2\xB8\xD1\xCB\x5B\xDC\x1E\xF9\x68\x31\x64\xE1\x9B\xFA\x74\xEB\x68\xB9\x20\x95\xF7\xC6\x0F\x8D\x47\xAC\x5A\x06\xDD\x61\xAB\xE2\xEC\xD8\x9F\x17\x2D\x9C\xCA\x3C\x35\x97\x55\x71\xCD\x43\x85\xB1\x47\x16\xF5\x2C\x53\x80\x76\xCF\xD3\x00\x64\xBD\x40\x99\xDD\xCC\xD8\xDB\xC4\x9F\xD6\x13\x5F\x41\x83\x8B\xF9\x0D\x87\x92\x56\x34\x6C\x1A\x10\x0B\x17\xD5\x5A\x1C\x97\x58\x84\x3C\x84\x1A\x2E\x5C\x91\x34\x6E\x19\x5F\x7F\x17\x69\xC5\x65\xEF\x6B\x21\xC6\xD5\x50\x3A\xBF\x61\xB9\x05\x8D\xEF\x6F\x34\x3A\xB2\x6F\x14\x63\xBF\x16\x3B\x9B\xA9\x2A\xFD\xB7\x2B\x38\x66\x06\xC5\x2C\xE2\xAA\x67\x1E\x45\xA7\x8D\x04\x66\x42\xF6\x8F\x2B\xEF\x88\x20\x69\x8F\x32\x8C\x14\x73\xDA\x2B\x86\x91\x63\x22\x9A\xF2\xA7\xDB\xCE\x89\x8B\xAB\x5D\xC7\x14\xC1\x5B\x30\x6A\x1F\xB1\xB7\x9E\x2E\x81\x01\x02\xED\xCF\x96\x5E\x63\xDB\xA8\xE6\x38\xB7\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x7C\x72\x4B\x39\xC7\xC0\xDB\x62\xA5\x4F\x9B\xAA\x18\x34\x92\xA2\xCA\x83\x82\x59\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x7C\x72\x4B\x39\xC7\xC0\xDB\x62\xA5\x4F\x9B\xAA\x18\x34\x92\xA2\xCA\x83\x82\x59\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x2A\xC3\xC7\x43\x37\x8F\xDD\xAD\xA4\xB2\x0C\xEE\xDC\x14\x6D\x8F\x28\xA4\x98\x49\xCB\x0C\x80\xEA\xF3\xED\x23\x66\x75\x7D\xC5\xD3\x21\x67\x79\xD1\x73\xC5\xB5\x03\xB7\x58\xAC\x0C\x54\x2F\xC6\x56\x13\x0F\x31\xDA\x06\xE7\x65\x3B\x1D\x6F\x36\xDB\xC8\x1D\xF9\xFD\x80\x06\xCA\xA3\x3D\x66\x16\xA8\x9D\x4C\x16\x7D\xC0\x95\x46\xB5\x51\xE4\xE2\x1F\xD7\xEA\x06\x4D\x63\x8D\x96\x8C\xEF\xE7\x33\x57\x42\x3A\xEB\x8C\xC1\x79\xC8\x4D\x76\x7D\xDE\xF6\xB1\xB7\x81\xE0\xA0\xF9\xA1\x78\x46\x17\x1A\x56\x98\xF0\x4E\x3D\xAB\x1C\xED\xEC\x39\xDC\x07\x48\xF7\x63\xFE\x06\xAE\xC2\xA4\x5C\x6A\x5B\x32\x88\xC5\xC7\x33\x85\xAC\x66\x42\x47\xC2\x58\x24\x99\xE1\xE5\x3E\xE5\x75\x2C\x8E\x43\xD6\x5D\x3C\x78\x1E\xA8\x95\x82\x29\x50\xD1\xD1\x16\xBA\xEF\xC1\xBE\x7A\xD9\xB4\xD8\xCC\x1E\x4C\x46\xE1\x77\xB1\x31\xAB\xBD\x2A\xC8\xCE\x8F\x6E\xA1\x5D\x7F\x03\x75\x34\xE4\xAD\x89\x45\x54\x5E\xBE\xAE\x28\xA5\xBB\x3F\x78\x79\xEB\x73\xB3\x0A\x0D\xFD\xBE\xC9\xF7\x56\xAC\xF6\xB7\xED\x2F\x9B\x21\x29\xC7\x38\xB6\x95\xC4\x04\xF2\xC3\x2D\xFD\x14\x2A\x90\x99\xB9\x07\xCC\x9F", + ["CN=Swisscom Root CA 2,OU=Digital Certificate Services,O=Swisscom,C=ch"] = "\x30\x82\x05\xD9\x30\x82\x03\xC1\xA0\x03\x02\x01\x02\x02\x10\x1E\x9E\x28\xE8\x48\xF2\xE5\xEF\xC3\x7C\x4A\x1E\x5A\x18\x67\xB6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x53\x77\x69\x73\x73\x63\x6F\x6D\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x53\x77\x69\x73\x73\x63\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x31\x31\x30\x36\x32\x34\x30\x38\x33\x38\x31\x34\x5A\x17\x0D\x33\x31\x30\x36\x32\x35\x30\x37\x33\x38\x31\x34\x5A\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x53\x77\x69\x73\x73\x63\x6F\x6D\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x53\x77\x69\x73\x73\x63\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\x95\x42\x4E\x84\x9D\x51\xE6\xD3\x09\xE8\x72\x5A\x23\x69\xDB\x78\x70\x8E\x16\xF1\x2B\x8F\x0D\x03\xCE\x93\xCC\x2E\x00\x08\x7B\xAB\x33\x8C\xF4\xE9\x40\xE6\x17\x4C\xAB\x9E\xB8\x47\x14\x32\x77\x32\xDD\x28\x0C\xDE\x18\x4B\x5F\x76\x9F\xF8\x39\x3B\xFC\x4E\x89\xD8\x7C\xC5\x67\xEF\xAB\xD2\xB9\x34\x5F\x6B\x3A\xF3\x64\x36\xCE\xC2\xB0\xCF\x13\x68\xCA\xC8\xCB\xEB\xB5\xE2\x3D\x2E\x21\xDF\xEA\x2C\xD4\xE0\xF9\x70\x96\x4C\xFF\x6A\x58\x98\xB7\x17\xE4\x1B\x52\xE5\x7E\x07\x00\x1D\x5F\xDA\xE6\x3E\x95\x04\xB7\x69\x88\x39\xA1\x41\x60\x25\x61\x4B\x95\x39\x68\x62\x1C\xB1\x0B\x05\x89\xC0\x36\x82\x14\x21\x3F\xAE\xDB\xA1\xFD\xBC\x6F\x1C\x60\x86\xB6\x53\x94\x49\xB9\x2B\x46\xC5\x4F\x00\x2B\xBF\xA1\xBB\xCB\x3F\xE0\xC7\x57\x1C\x57\xE8\xD6\x69\xF8\xC1\x24\x52\x9D\x88\x55\xDD\xC2\x87\x2E\x74\x23\xD0\x14\xFD\x2A\x47\x5A\xBB\xA6\x9D\xFD\x94\xE4\xD1\x8A\xA5\x5F\x86\x63\x76\x85\xCB\xAF\xFF\x49\x28\xFC\x80\xED\x4C\x79\xD2\xBB\xE4\xC0\xEF\x01\xEE\x50\x41\x08\x35\x23\x70\x2B\xA9\x16\xB4\x8C\x6E\x85\xE9\xB6\x11\xCF\x31\xDD\x53\x26\x1B\xDF\x2D\x5A\x4A\x02\x40\xFC\xC4\xC0\xB6\xE9\x31\x1A\x08\x28\xE5\x60\xC3\x1F\xC4\x90\x8E\x10\x62\x60\x44\x0D\xEC\x0A\xBE\x55\x18\x71\x2C\xA5\xF4\xB2\xBC\x15\x62\xFF\x1C\xE3\xBE\x1D\xDA\x1E\x57\xB3\x3C\x7E\xCD\x82\x1D\x91\xE3\x4B\xEB\x2C\x52\x34\xB0\x8A\xFD\x12\x4E\x96\xB0\xEB\x70\x7F\x9E\x39\xF7\x66\x42\xB1\xAB\xAC\x52\xDA\x76\x40\x57\x7B\x2A\xBD\xE8\x6E\x03\xB2\x0B\x80\x85\x88\x9D\x0C\xC7\xC2\x77\xB0\x9A\x9A\x57\xF4\xB8\xFA\x13\x5C\x68\x93\x3A\x67\xA4\x97\xD0\x1B\x99\xB7\x86\x32\x4B\x60\xD8\xCE\xEF\xD0\x0C\x7F\x95\x9F\x6F\x87\x4F\x87\x8A\x8E\x5F\x08\x7C\xAA\x5B\xFC\x5A\xBE\xA1\x91\x9F\x55\x7D\x4E\xB0\x0B\x69\xCC\xB0\x94\xA8\xA7\x87\xF2\xD3\x4A\x50\xDC\x5F\x72\xB0\x16\x75\x1E\xCB\xB4\x18\x62\x9A\xB0\xA7\x39\xAA\x9B\x9F\x66\xD8\x8D\xA6\x6C\x96\x15\xE3\xE6\xF2\xF8\xF1\x83\x62\x6C\xBB\x55\xE9\x61\x93\xA3\x3D\xF5\xB1\x57\x8B\x4F\x23\xB0\x9B\xE5\x94\x6A\x2F\xDF\x8C\xDF\x95\x51\x29\x60\xA1\x0B\x29\xE4\x5C\x55\x58\xB7\xA8\xFC\x99\xEE\x25\x4D\x4C\x0E\xB3\xD3\x4C\x8F\x84\xE8\x29\x0F\xFD\x10\x54\x02\x85\xC8\xF9\xE5\xC3\x8B\xCF\xE7\x0F\x02\x03\x01\x00\x01\xA3\x81\x86\x30\x81\x83\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1D\x06\x03\x55\x1D\x21\x04\x16\x30\x14\x30\x12\x06\x07\x60\x85\x74\x01\x53\x02\x01\x06\x07\x60\x85\x74\x01\x53\x02\x01\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x07\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4D\x26\x20\x22\x89\x4B\xD3\xD5\xA4\x0A\xA1\x6F\xDE\xE2\x12\x81\xC5\xF1\x3C\x2E\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x4D\x26\x20\x22\x89\x4B\xD3\xD5\xA4\x0A\xA1\x6F\xDE\xE2\x12\x81\xC5\xF1\x3C\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x32\x0A\xB2\xA4\x1B\xCB\x7D\xBE\x82\x57\x89\xB9\x6A\x7F\xF3\xF4\xC1\x2E\x11\x7D\xB8\x19\x3E\x79\xB7\xA8\xA8\x72\x37\x66\x9B\x1A\xED\xAC\x13\x3B\x0E\xBF\x62\xF0\x9C\xDF\x9E\x7B\xA1\x53\x48\x0E\x41\x7A\xCA\x20\xA7\x17\x1B\xB6\x78\xEC\x40\x91\xF3\x42\xAD\x10\xC3\x5C\xEF\xFF\x60\x59\x7F\xCD\x85\xA3\x8B\x3D\x48\x1C\x25\x02\x3C\x67\x7D\xF5\x32\xE9\x2F\x30\xE5\x7D\xA5\x7A\x38\xD0\xF3\x66\x2A\x66\x1E\x8D\x33\x83\x8A\x6F\x7C\x6E\xA8\x5A\x75\x9A\xB8\xD7\xDA\x58\x48\x44\x47\xA8\x4C\xFA\x4C\x49\x0A\x4A\xC2\x12\x37\xA8\x40\x0C\xC3\xC8\xE1\xD0\x57\x0D\x97\x32\x95\xC7\x3A\x9F\x97\xD3\x57\xF8\x0B\xDE\xE5\x72\xF3\xA3\xDB\xFF\xB5\xD8\x59\xB2\x73\xDD\x4D\x2A\x71\xB2\xBA\x49\xF5\xCB\x1C\xD5\xF5\x79\xC8\x99\xB3\xFC\xC1\x4C\x74\xE3\xB4\xBD\x29\x37\x15\x04\x28\x1E\xDE\x45\x46\x70\xEC\xAF\xBA\x78\x0E\x8A\x2A\xCE\x00\x79\xDC\xC0\x5F\x19\x67\x2C\x6B\x4B\xEF\x68\x68\x0B\x43\xE3\xAC\xC1\x62\x09\xEF\xA6\xDD\x65\x61\xA0\xAF\x84\x55\x48\x91\x52\x1C\xC6\x25\x91\x2A\xD0\xC1\x22\x23\x61\x59\xAF\x45\x11\x85\x1D\x01\x24\x34\x8F\xCF\xB3\xFF\x17\x72\x20\x13\xC2\x80\xAA\x21\x2C\x71\x39\x0E\xD0\x8F\x5C\xC1\xD3\xD1\x8E\x22\x72\x46\x4C\x1D\x96\xAE\x4F\x71\xB1\xE1\x05\x29\x96\x59\xF4\xBB\x9E\x75\x3D\xCF\x0D\x37\x0D\x62\xDB\x26\x8C\x63\xA9\x23\xDF\x67\x06\x3C\x7C\x3A\xDA\x34\x42\xE1\x66\xB4\x46\x04\xDE\xC6\x96\x98\x0F\x4B\x48\x7A\x24\x32\x75\x91\x9F\xAC\xF7\x68\xE9\x2A\xB9\x55\x65\xCE\x5D\x61\xD3\x27\x70\xD8\x37\xFE\x9F\xB9\xAF\xA0\x2E\x56\xB7\xA3\x65\x51\xED\x3B\xAB\x14\xBF\x4C\x51\x03\xE8\x5F\x8A\x05\x9B\xEE\x8A\x6E\x9C\xEF\xBF\x68\xFA\xC8\xDA\x0B\xE3\x42\xC9\xD0\x17\x14\x9C\xB7\x4A\xE0\xAF\x93\x27\x21\x55\x26\xB5\x64\x2F\x8D\xF1\xFF\xA6\x40\x05\x85\x05\x5C\xCA\x07\x19\x5C\x0B\x13\x28\x4C\x58\x7F\xC2\xA5\xEF\x45\xDA\x60\xD3\xAE\x65\x61\x9D\x53\x83\x74\xC2\xAE\xF2\x5C\xC2\x16\xED\x92\x3E\x84\x3E\x73\x60\x88\xBC\x76\xF4\x2C\xCF\xD0\x7D\x7D\xD3\xB8\x5E\xD1\x91\x12\x10\xE9\xCD\xDD\xCA\x25\xE3\xD5\xED\x99\x2F\xBE\x75\x81\x4B\x24\xF9\x45\x46\x94\xC9\x29\x21\x53\x9C\x26\x45\xAA\x13\x17\xE4\xE7\xCD\x78\xE2\x39\xC1\x2B\x12\x9E\xA6\x9E\x1B\xC5\xE6\x0E\xD9\x31\xD9", + ["CN=Swisscom Root EV CA 2,OU=Digital Certificate Services,O=Swisscom,C=ch"] = "\x30\x82\x05\xE0\x30\x82\x03\xC8\xA0\x03\x02\x01\x02\x02\x11\x00\xF2\xFA\x64\xE2\x74\x63\xD3\x8D\xFD\x10\x1D\x04\x1F\x76\xCA\x58\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x67\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x53\x77\x69\x73\x73\x63\x6F\x6D\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1E\x30\x1C\x06\x03\x55\x04\x03\x13\x15\x53\x77\x69\x73\x73\x63\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x45\x56\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x31\x31\x30\x36\x32\x34\x30\x39\x34\x35\x30\x38\x5A\x17\x0D\x33\x31\x30\x36\x32\x35\x30\x38\x34\x35\x30\x38\x5A\x30\x67\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x53\x77\x69\x73\x73\x63\x6F\x6D\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1E\x30\x1C\x06\x03\x55\x04\x03\x13\x15\x53\x77\x69\x73\x73\x63\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x45\x56\x20\x43\x41\x20\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC4\xF7\x1D\x2F\x57\xEA\x57\x6C\xF7\x70\x5D\x63\xB0\x71\x52\x09\x60\x44\x28\x33\xA3\x7A\x4E\x0A\xFA\xD8\xEA\x6C\x8B\x51\x16\x1A\x55\xAE\x54\x26\xC4\xCC\x45\x07\x41\x4F\x10\x79\x7F\x71\xD2\x7A\x4E\x3F\x38\x4E\xB3\x00\xC6\x95\xCA\x5B\xCD\xC1\x2A\x83\xD7\x27\x1F\x31\x0E\x23\x16\xB7\x25\xCB\x1C\xB4\xB9\x80\x32\x5E\x1A\x9D\x93\xF1\xE8\x3C\x60\x2C\xA7\x5E\x57\x19\x58\x51\x5E\xBC\x2C\x56\x0B\xB8\xD8\xEF\x8B\x82\xB4\x3C\xB8\xC2\x24\xA8\x13\xC7\xA0\x21\x36\x1B\x7A\x57\x29\x28\xA7\x2E\xBF\x71\x25\x90\xF3\x44\x83\x69\x50\xA4\xE4\xE1\x1B\x62\x19\x94\x09\xA3\xF3\xC3\xBC\xEF\xF4\xBD\xEC\xDB\x13\x9D\xCF\x9D\x48\x09\x52\x67\xC0\x37\x29\x11\x1E\xFB\xD2\x11\xA7\x85\x18\x74\x79\xE4\x4F\x85\x14\xEB\x52\x37\xE2\xB1\x45\xD8\xCC\x0D\x43\x7F\xAE\x13\xD2\x6B\x2B\x3F\xA7\xC2\xE2\xA8\x6D\x76\x5B\x43\x9F\xBE\xB4\x9D\xB3\x26\x86\x3B\x1F\x7F\xE5\xF2\xE8\x66\x28\x16\x25\xD0\x4B\x97\x38\xA7\xE4\xCF\x09\xD1\x36\xC3\x0B\xBE\xDA\x3B\x44\x58\x8D\xBE\xF1\x9E\x09\x6B\x3E\xF3\x32\xC7\x2B\x87\xC6\xEC\x5E\x9C\xF6\x87\x65\xAD\x33\x29\xC4\x2F\x89\xD9\xB9\xCB\xC9\x03\x9D\xFB\x6C\x94\x51\x97\x10\x1B\x86\x0B\x1A\x1B\x3F\xF6\x02\x7E\x7B\xD4\xC5\x51\x64\x28\x9D\xF5\xD3\xAC\x83\x81\x88\xD3\x74\xB4\x59\x9D\xC1\xEB\x61\x33\x5A\x45\xD1\xCB\x39\xD0\x06\x6A\x53\x60\x1D\xAF\xF6\xFB\x69\xBC\x6A\xDC\x01\xCF\xBD\xF9\x8F\xD9\xBD\x5B\xC1\x3A\x5F\x8E\xDA\x0F\x4B\xA9\x9B\x9D\x2A\x28\x6B\x1A\x0A\x7C\x3C\xAB\x22\x0B\xE5\x77\x2D\x71\xF6\x82\x35\x81\xAE\xF8\x7B\x81\xE6\xEA\xFE\xAC\xF4\x1A\x9B\x74\x5C\xE8\x8F\x24\xF6\x5D\x9D\x46\xC4\x2C\xD2\x1E\x2B\x21\x6A\x83\x27\x67\x55\x4A\xA4\xE3\xC8\x32\x97\x66\x90\x72\xDA\xE3\xD4\x64\x2E\x5F\xE3\xA1\x6A\xF6\x60\xD4\xE7\x35\xCD\xCA\xC4\x68\x8D\xD7\x71\xC8\xD3\x24\x33\x73\xB1\x6C\xF9\x6A\xE1\x28\xDB\x5F\xC6\x3D\xE8\xBE\x55\xE6\x37\x1B\xED\x24\xD9\x0F\x19\x8F\x5F\x63\x18\x58\x50\x81\x51\x65\x6F\xF2\x9F\x7E\x6A\x04\xE7\x34\x24\x71\xBA\x76\x4B\x58\x1E\x19\xBD\x15\x60\x45\xAA\x0C\x12\x40\x01\x9D\x10\xE2\xC7\x38\x07\x72\x0A\x65\xC0\xB6\xBB\x25\x29\xDA\x16\x9E\x8B\x35\x8B\x61\xED\xE5\x71\x57\x83\xB5\x3C\x71\x9F\xE3\x4F\xBF\x7E\x1E\x81\x9F\x41\x97\x02\x03\x01\x00\x01\xA3\x81\x86\x30\x81\x83\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1D\x06\x03\x55\x1D\x21\x04\x16\x30\x14\x30\x12\x06\x07\x60\x85\x74\x01\x53\x02\x02\x06\x07\x60\x85\x74\x01\x53\x02\x02\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x03\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x45\xD9\xA5\x81\x6E\x3D\x88\x4D\x8D\x71\xD2\x46\xC1\x6E\x45\x1E\xF3\xC4\x80\x9D\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x45\xD9\xA5\x81\x6E\x3D\x88\x4D\x8D\x71\xD2\x46\xC1\x6E\x45\x1E\xF3\xC4\x80\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x94\x3A\x73\x06\x9F\x52\x4B\x30\x5C\xD4\xFE\xB1\x5C\x25\xF9\xD7\x8E\x6F\xF5\x87\x64\x9F\xED\x14\x8E\xB8\x04\x8E\x28\x4B\x8F\xAA\x7B\x8E\x39\xB4\xD9\x58\xF6\x7B\xA1\x35\x0A\xA1\x9D\x8A\xF7\x63\xE5\xEB\xBD\x39\x82\xD4\xE3\x7A\x2D\x6F\xDF\x13\x3C\xBA\xFE\x7E\x56\x98\x0B\xF3\x54\x9F\xCD\x44\x4E\x6E\x3C\xE1\x3E\x15\xBF\x06\x26\x9D\xE4\xF0\x90\xB6\xD4\xC2\x9E\x30\x2E\x1F\xEF\xC7\x7A\xC4\x50\xC7\xEA\x7B\xDA\x50\xCB\x7A\x26\xCB\x00\xB4\x5A\xAB\xB5\x93\x1F\x80\x89\x84\x04\x95\x8D\x8D\x7F\x09\x93\xBF\xD4\xA8\xA8\xE4\x63\x6D\xD9\x64\xE4\xB8\x29\x5A\x08\xBF\x50\xE1\x84\x0F\x55\x7B\x5F\x08\x22\x1B\xF5\xBD\x99\x1E\x14\xF6\xCE\xF4\x58\x10\x82\xB3\x0A\x3D\x19\xC1\xBF\x5B\xAB\xAA\x99\xD8\xF2\x31\xBD\xE5\x38\x66\xDC\x58\x05\xC7\xED\x63\x1A\x2E\x0A\x97\x7C\x87\x93\x2B\xB2\x8A\xE3\xF1\xEC\x18\xE5\x75\xB6\x29\x87\xE7\xDC\x8B\x1A\x7E\xB4\xD8\xC9\xD3\x8A\x17\x6C\x7D\x29\x44\xBE\x8A\xAA\xF5\x7E\x3A\x2E\x68\x31\x93\xB9\x6A\xDA\x9A\xE0\xDB\xE9\x2E\xA5\x84\xCD\x1C\x0A\xB8\x4A\x08\xF9\x9C\xF1\x61\x26\x98\x93\xB7\x7B\x66\xEC\x91\x5E\xDD\x51\x3F\xDB\x73\x0F\xAD\x04\x58\x09\xDD\x04\x02\x95\x0A\x3E\xD3\x76\xDF\xA6\x10\x1E\x80\x3D\xE8\xCD\xA4\x64\xD1\x33\xC7\x92\xC7\xE2\x4E\x44\xE3\x09\xC9\x4E\xC2\x5D\x87\x0E\x12\x9E\xBF\x0F\xC9\x05\x10\xDE\x7A\xA3\xB1\x3C\xF2\x3F\xA5\xAA\x27\x79\xAD\x31\x7D\x1F\xFD\xFC\x19\x69\xC5\xDD\xB9\x3F\x7C\xCD\xC6\xB4\xC2\x30\x1E\x7E\x6E\x92\xD7\x7F\x61\x76\x5A\x8F\xEB\x95\x4D\xBC\x11\x6E\x21\x7C\x59\x37\x99\xD0\x06\xBC\xF9\x06\x6D\x32\x16\xA5\xD9\x69\xA8\xE1\xDC\x3C\x80\x1E\x60\x51\xDC\xD7\x54\x21\x1E\xCA\x62\x77\x4F\xFA\xD8\x8F\xB3\x2B\x3A\x0D\x78\x72\xC9\x68\x41\x5A\x47\x4A\xC2\xA3\xEB\x1A\xD7\x0A\xAB\x3C\x32\x55\xC8\x0A\x11\x9C\xDF\x74\xD6\xF0\x40\x15\x1D\xC8\xB9\x8F\xB5\x36\xC5\xAF\xF8\x22\xB8\xCA\x1D\xF3\xD6\xB6\x19\x0F\x9F\x61\x65\x6A\xEA\x74\xC8\x7C\x8F\xC3\x4F\x5D\x65\x82\x1F\xD9\x0D\x89\xDA\x75\x72\xFB\xEF\xF1\x47\x67\x13\xB3\xC8\xD1\x19\x88\x27\x26\x9A\x99\x79\x7F\x1E\xE4\x2C\x3F\x7B\xEE\xF1\xDE\x4D\x8B\x96\x97\xC3\xD5\x3F\x7C\x1B\x23\xED\xA4\xB3\x1D\x16\x72\x43\x4B\x20\xE1\x59\x7E\xC2\xE8\xAD\x26\xBF\xA2\xF7", + ["CN=CA Disig Root R1,O=Disig a.s.,L=Bratislava,C=SK"] = "\x30\x82\x05\x69\x30\x82\x03\x51\xA0\x03\x02\x01\x02\x02\x09\x00\xC3\x03\x9A\xEE\x50\x90\x6E\x28\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x52\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4B\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x42\x72\x61\x74\x69\x73\x6C\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x44\x69\x73\x69\x67\x20\x61\x2E\x73\x2E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x43\x41\x20\x44\x69\x73\x69\x67\x20\x52\x6F\x6F\x74\x20\x52\x31\x30\x1E\x17\x0D\x31\x32\x30\x37\x31\x39\x30\x39\x30\x36\x35\x36\x5A\x17\x0D\x34\x32\x30\x37\x31\x39\x30\x39\x30\x36\x35\x36\x5A\x30\x52\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4B\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x42\x72\x61\x74\x69\x73\x6C\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x44\x69\x73\x69\x67\x20\x61\x2E\x73\x2E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x43\x41\x20\x44\x69\x73\x69\x67\x20\x52\x6F\x6F\x74\x20\x52\x31\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAA\xC3\x78\xF7\xDC\x98\xA3\xA7\x5A\x5E\x77\x18\xB2\xDD\x04\x64\x0F\x63\xFD\x9B\x96\x09\x80\xD5\xE8\xAA\xA5\xE2\x9C\x26\x94\x3A\xE8\x99\x73\x8C\x9D\xDF\xD7\xDF\x83\xF3\x78\x4F\x40\xE1\x7F\xD2\xA7\xD2\xE5\xCA\x13\x93\xE7\xED\xC6\x77\x5F\x36\xB5\x94\xAF\xE8\x38\x8E\xDB\x9B\xE5\x7C\xBB\xCC\x8D\xEB\x75\x73\xE1\x24\xCD\xE6\xA7\x2D\x19\x2E\xD8\xD6\x8A\x6B\x14\xEB\x08\x62\x0A\xD8\xDC\xB3\x00\x4D\xC3\x23\x7C\x5F\x43\x08\x23\x32\x12\xDC\xED\x0C\xAD\xC0\x7D\x0F\xA5\x7A\x42\xD9\x5A\x70\xD9\xBF\xA7\xD7\x01\x1C\xF6\x9B\xAB\x8E\xB7\x4A\x86\x78\xA0\x1E\x56\x31\xAE\xEF\x82\x0A\x80\x41\xF7\x1B\xC9\xAE\xAB\x32\x26\xD4\x2C\x6B\xED\x7D\x6B\xE4\xE2\x5E\x22\x0A\x45\xCB\x84\x31\x4D\xAC\xFE\xDB\xD1\x47\xBA\xF9\x60\x97\x39\xB1\x65\xC7\xDE\xFB\x99\xE4\x0A\x22\xB1\x2D\x4D\xE5\x48\x26\x69\xAB\xE2\xAA\xF3\xFB\xFC\x92\x29\x32\xE9\xB3\x3E\x4D\x1F\x27\xA1\xCD\x8E\xB9\x17\xFB\x25\x3E\xC9\x6E\xF3\x77\xDA\x0D\x12\xF6\x5D\xC7\xBB\x36\x10\xD5\x54\xD6\xF3\xE0\xE2\x47\x48\xE6\xDE\x14\xDA\x61\x52\xAF\x26\xB4\xF5\x71\x4F\xC9\xD7\xD2\x06\xDF\x63\xCA\xFF\x21\xE8\x59\x06\xE0\x08\xD5\x84\x15\x53\xF7\x43\xE5\x7C\xC5\xA0\x89\x98\x6B\x73\xC6\x68\xCE\x65\xDE\xBD\x7F\x05\xF7\xB1\xEE\xF6\x57\xA1\x60\x95\xC5\xCC\xEA\x93\x3A\xBE\x99\xAE\x9B\x02\xA3\xAD\xC9\x16\xB5\xCE\xDD\x5E\x99\x78\x7E\x1A\x39\x7E\xB2\xC0\x05\xA4\xC0\x82\xA5\xA3\x47\x9E\x8C\xEA\x5C\xB6\xBC\x67\xDB\xE6\x2A\x4D\xD2\x04\xDC\xA3\xAE\x45\xF7\xBC\x8B\x9C\x1C\xA7\xD6\xD5\x03\xDC\x08\xCB\x2E\x16\xCA\x5C\x40\x33\xE8\x67\xC3\x2E\xE7\xA6\x44\xEA\x11\x45\x1C\x35\x65\x2D\x1E\x45\x61\x24\x1B\x82\x2E\xA5\x9D\x33\x5D\x65\xF8\x41\xF9\x2E\xCB\x94\x3F\x1F\xA3\x0C\x31\x24\x44\xED\xC7\x5E\xAD\x50\xBA\xC6\x41\x9B\xAC\xF0\x17\x65\xC0\xF8\x5D\x6F\x5B\xA0\x0A\x34\x3C\xEE\xD7\xEA\x88\x9F\x98\xF9\xAF\x4E\x24\xFA\x97\xB2\x64\x76\xDA\xAB\xF4\xED\xE3\xC3\x60\xEF\xD5\xF9\x02\xC8\x2D\x9F\x83\xAF\x67\x69\x06\xA7\x31\x55\xD5\xCF\x4B\x6F\xFF\x04\x05\xC7\x58\xAC\x5F\x16\x1B\xE5\xD2\xA3\xEB\x31\xDB\x1F\x33\x15\x4D\xD0\xF2\xA5\x53\xF5\xCB\xE1\x3D\x4E\x68\x2D\xD8\x12\xDD\xAA\xF2\xE6\x4D\x9B\x49\xE5\xC5\x28\xA1\xBA\xB0\x5A\xC6\xA0\xB5\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x89\x0A\xB4\x38\x93\x1A\xE6\xAB\xEE\x9B\x91\x18\xF9\xF5\x3C\x3E\x35\xD0\xD3\x82\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x32\x8B\xF6\x9D\x4A\xC9\xBE\x14\xE5\x8C\xAC\x38\xCA\x3A\x09\xD4\x1B\xCE\x86\xB3\xDD\xEB\xD4\xBA\x28\xBE\x12\xAE\x45\x2C\x04\x74\xAC\x13\x51\xC5\x58\x18\x66\x4D\x82\xDA\xD5\xDC\x93\xC0\x27\xE1\xBE\x7C\x9F\x52\x9E\x12\x56\xF6\xD5\x9C\xA9\xF4\x75\x9C\xFA\x37\x12\x8F\x1C\x93\xEC\x57\xFE\x07\x0F\xAB\xD5\x12\xF7\x0F\xAE\x61\x5E\x56\x80\x49\xF5\xFC\x30\xF5\x9B\x4F\x1F\x41\x2F\x1C\x84\xD3\x89\xC7\xE2\xDA\x02\x76\xED\x09\xCF\x6C\xC1\xB8\x1C\x83\x1C\x16\xFA\x94\xCD\x7D\xA0\xC8\x18\xD2\xC8\x9D\x6E\xF5\xBD\x69\xD4\x6D\x3D\x35\xE8\x1E\xA2\x4F\x60\xD7\x07\x29\xFC\xB2\xA3\xA4\x9D\x6E\x15\x92\x56\x19\x4C\x0A\xB0\xE9\x7C\xD2\x19\x4D\x42\x46\xEC\xBD\xFD\xF6\x57\x5B\xDD\x98\x7E\xA4\x4D\xCC\x72\x03\x83\x58\x5D\xEF\x93\x3A\x41\x7A\x63\xAA\x7C\x3A\xA8\xF5\xAC\xA4\xD1\xDD\xA2\x2D\xB6\x2A\xFC\x9F\x01\x8E\xE2\x10\xB1\xC4\xCA\xE4\x67\xDB\x55\x25\x19\x3F\xFD\xE8\x36\x7E\xB3\xE1\xE1\x81\xAF\x11\x16\x8B\x50\x97\x60\x19\x82\x00\xC0\x6B\x4D\x73\xB8\xD1\x13\x07\x3E\xEA\xB6\x31\x4F\xF0\x42\x9A\x6D\xE2\x11\x74\xE5\x94\xAC\x8D\x84\x95\x3C\x21\xAF\xC5\xDA\x47\xC8\xDF\x39\x62\x62\xCB\x5B\x50\x0B\xD7\x81\x40\x05\x9C\x9B\xED\xBA\xB6\x8B\x1E\x04\x6F\x96\x20\x39\xED\xA4\x7D\x29\xDB\x48\xCE\x82\xDC\xD4\x02\x8D\x1D\x04\x31\x5A\xC7\x4B\xF0\x6C\x61\x52\xD7\xB4\x51\xC2\x81\x6C\xCD\xE1\xFB\xA7\xA1\xD2\x92\x76\xCF\xB1\x0F\x37\x58\xA4\xF2\x52\x71\x67\x3F\x0C\x88\x78\x80\x89\xC1\xC8\xB5\x1F\x92\x63\xBE\xA7\x7A\x8A\x56\x2C\x1A\xA8\xA6\x9C\xB5\x5D\xB3\x63\xD0\x13\x20\xA1\xEB\x91\x6C\xD0\x8D\x7D\xAF\xDF\x0B\xE4\x17\xB9\x86\x9E\x38\xB1\x94\x0C\x58\x8C\xE0\x55\xAA\x3B\x63\x6D\x9A\x89\x60\xB8\x64\x2A\x92\xC6\x37\xF4\x7E\x43\x43\xB7\x73\xE8\x01\xE7\x7F\x97\x0F\xD7\xF2\x7B\x19\xFD\x1A\xD7\x8F\xC9\xFA\x85\x6B\x7A\x9D\x9E\x89\xB6\xA6\x28\x99\x93\x88\x40\xF7\x3E\xCD\x51\xA3\xCA\xEA\xEF\x79\x47\x21\xB5\xFE\x32\xE2\xC7\xC3\x51\x6F\xBE\x80\x74\xF0\xA4\xC3\x3A\xF2\x4F\xE9\x5F\xDF\x19\x0A\xF2\x3B\x13\x43\xAC\x31\xA4\xB3\xE7\xEB\xFC\x18\xD6\x01\xA9\xF3\x2A\x8F\x36\x0E\xEB\xB4\xB1\xBC\xB7\x4C\xC9\x6B\xBF\xA1\xF3\xD9\xF4\xED\xE2\xF0\xE3\xED\x64\x9E\x3D\x2F\x96\x52\x4F\x80\x53\x8B", + ["CN=CA Disig Root R2,O=Disig a.s.,L=Bratislava,C=SK"] = "\x30\x82\x05\x69\x30\x82\x03\x51\xA0\x03\x02\x01\x02\x02\x09\x00\x92\xB8\x88\xDB\xB0\x8A\xC1\x63\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x52\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4B\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x42\x72\x61\x74\x69\x73\x6C\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x44\x69\x73\x69\x67\x20\x61\x2E\x73\x2E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x43\x41\x20\x44\x69\x73\x69\x67\x20\x52\x6F\x6F\x74\x20\x52\x32\x30\x1E\x17\x0D\x31\x32\x30\x37\x31\x39\x30\x39\x31\x35\x33\x30\x5A\x17\x0D\x34\x32\x30\x37\x31\x39\x30\x39\x31\x35\x33\x30\x5A\x30\x52\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4B\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x42\x72\x61\x74\x69\x73\x6C\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x44\x69\x73\x69\x67\x20\x61\x2E\x73\x2E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x43\x41\x20\x44\x69\x73\x69\x67\x20\x52\x6F\x6F\x74\x20\x52\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xA2\xA3\xC4\x00\x09\xD6\x85\x5D\x2D\x6D\x14\xF6\xC2\xC3\x73\x9E\x35\xC2\x71\x55\x7E\x81\xFB\xAB\x46\x50\xE0\xC1\x7C\x49\x78\xE6\xAB\x79\x58\x3C\xDA\xFF\x7C\x1C\x9F\xD8\x97\x02\x78\x3E\x6B\x41\x04\xE9\x41\xBD\xBE\x03\x2C\x45\xF6\x2F\x64\xD4\xAB\x5D\xA3\x47\x3D\x64\x9B\xE9\x68\x9A\xC6\xCC\x1B\x3F\xBA\xBE\xB2\x8B\x34\x02\x2E\x98\x55\x19\xFC\x8C\x6F\xAA\x5F\xDA\x4C\xCE\x4D\x03\x21\xA3\xD8\xD2\x34\x93\x56\x96\xCB\x4C\x0C\x00\x16\x3C\x5F\x1A\xCD\xC8\xC7\x6C\xA6\xAD\xD3\x31\xA7\xBC\xE8\xE5\xE1\x66\xD6\xD2\xFB\x03\xB4\x41\x65\xC9\x10\xAE\x0E\x05\x63\xC6\x80\x6A\x69\x30\xFD\xD2\xEE\x90\xEF\x0D\x27\xDF\x9F\x95\x73\xF4\xE1\x25\xDA\x6C\x16\xDE\x41\x38\x34\xEA\x8B\xFC\xD1\xE8\x04\x14\x61\x2D\x41\x7E\xAC\xC7\x77\x4E\xCB\x51\x54\xFB\x5E\x92\x18\x1B\x04\x5A\x68\xC6\xC9\xC4\xFA\xB7\x13\xA0\x98\xB7\x11\x2B\xB7\xD6\x57\xCC\x7C\x9E\x17\xD1\xCB\x25\xFE\x86\x4E\x24\x2E\x56\x0C\x78\x4D\x9E\x01\x12\xA6\x2B\xA7\x01\x65\x6E\x7C\x62\x1D\x84\x84\xDF\xEA\xC0\x6B\xB5\xA5\x2A\x95\x83\xC3\x53\x11\x0C\x73\x1D\x0B\xB2\x46\x90\xD1\x42\x3A\xCE\x40\x6E\x95\xAD\xFF\xC6\x94\xAD\x6E\x97\x84\x8E\x7D\x6F\x9E\x8A\x80\x0D\x49\x6D\x73\xE2\x7B\x92\x1E\xC3\xF3\xC1\xF3\xEB\x2E\x05\x6F\xD9\x1B\xCF\x37\x76\x04\xC8\xB4\x5A\xE4\x17\xA7\xCB\xDD\x76\x1F\xD0\x19\x76\xE8\x2C\x05\xB3\xD6\x9C\x34\xD8\x96\xDC\x61\x87\x91\x05\xE4\x44\x08\x33\xC1\xDA\xB9\x08\x65\xD4\xAE\xB2\x36\x0D\xEB\xBA\x38\xBA\x0C\xE5\x9B\x9E\xEB\x8D\x66\xDD\x99\xCF\xD6\x89\x41\xF6\x04\x92\x8A\x29\x29\x6D\x6B\x3A\x1C\xE7\x75\x7D\x02\x71\x0E\xF3\xC0\xE7\xBD\xCB\x19\xDD\x9D\x60\xB2\xC2\x66\x60\xB6\xB1\x04\xEE\xC9\xE6\x86\xB9\x9A\x66\x40\xA8\xE7\x11\xED\x81\x45\x03\x8B\xF6\x67\x59\xE8\xC1\x06\x11\xBD\xDD\xCF\x80\x02\x4F\x65\x40\x78\x5C\x47\x50\xC8\x9B\xE6\x1F\x81\x7B\xE4\x44\xA8\x5B\x85\x9A\xE2\xDE\x5A\xD5\xC7\xF9\x3A\x44\x66\x4B\xE4\x32\x54\x7C\xE4\x6C\x9C\xB3\x0E\x3D\x17\xA2\xB2\x34\x12\xD6\x7E\xB2\xA8\x49\xBB\xD1\x7A\x28\x40\xBE\xA2\x16\x1F\xDF\xE4\x37\x1F\x11\x73\xFB\x90\x0A\x65\x43\xA2\x0D\x7C\xF8\x06\x01\x55\x33\x7D\xB0\x0D\xB8\xF4\xF5\xAE\xA5\x42\x57\x7C\x36\x11\x8C\x7B\x5E\xC4\x03\x9D\x8C\x79\x9D\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB5\x99\xF8\xAF\xB0\x94\xF5\xE3\x20\xD6\x0A\xAD\xCE\x4E\x56\xA4\x2E\x6E\x42\xED\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x26\x06\x5E\x70\xE7\x65\x33\xC8\x82\x6E\xD9\x9C\x17\x3A\x1B\x7A\x66\xB2\x01\xF6\x78\x3B\x69\x5E\x2F\xEA\xFF\x4E\xF9\x28\xC3\x98\x2A\x61\x4C\xB4\x24\x12\x8A\x7D\x6D\x11\x14\xF7\x9C\xB5\xCA\xE6\xBC\x9E\x27\x8E\x4C\x19\xC8\xA9\xBD\x7A\xC0\xD7\x36\x0E\x6D\x85\x72\x6E\xA8\xC6\xA2\x6D\xF6\xFA\x73\x63\x7F\xBC\x6E\x79\x08\x1C\x9D\x8A\x9F\x1A\x8A\x53\xA6\xD8\xBB\xD9\x35\x55\xB1\x11\xC5\xA9\x03\xB3\x56\x3B\xB9\x84\x93\x22\x5E\x7E\xC1\xF6\x12\x52\x8B\xEA\x2C\x67\xBC\xFE\x36\x4C\xF5\xB8\xCF\xD1\xB3\x49\x92\x3B\xD3\x29\x0E\x99\x1B\x96\xF7\x61\xB8\x3B\xC4\x2B\xB6\x78\x6C\xB4\x23\x6F\xF0\xFD\xD3\xB2\x5E\x75\x1F\x99\x95\xA8\xAC\xF6\xDA\xE1\xC5\x31\x7B\xFB\xD1\x46\xB3\xD2\xBC\x67\xB4\x62\x54\xBA\x09\xF7\x63\xB0\x93\xA2\x9A\xF9\xE9\x52\x2E\x8B\x60\x12\xAB\xFC\xF5\x60\x56\xEF\x10\x5C\x8B\xC4\x1A\x42\xDC\x83\x5B\x64\x0E\xCB\xB5\xBC\xD6\x4F\xC1\x7C\x3C\x6E\x8D\x13\x6D\xFB\x7B\xEB\x30\xD0\xDC\x4D\xAF\xC5\xD5\xB6\xA5\x4C\x5B\x71\xC9\xE8\x31\xBE\xE8\x38\x06\x48\xA1\x1A\xE2\xEA\xD2\xDE\x12\x39\x58\x1A\xFF\x80\x0E\x82\x75\xE6\xB7\xC9\x07\x6C\x0E\xEF\xFF\x38\xF1\x98\x71\xC4\xB7\x7F\x0E\x15\xD0\x25\x69\xBD\x22\x9D\x2B\xED\x05\xF6\x46\x47\xAC\xED\xC0\xF0\xD4\x3B\xE2\xEC\xEE\x96\x5B\x90\x13\x4E\x1E\x56\x3A\xEB\xB0\xEF\x96\xBB\x96\x23\x11\xBA\xF2\x43\x86\x74\x64\x95\xC8\x28\x75\xDF\x1D\x35\xBA\xD2\x37\x83\x38\x53\x38\x36\x3B\xCF\x6C\xE9\xF9\x6B\x0E\xD0\xFB\x04\xE8\x4F\x77\xD7\x65\x01\x78\x86\x0C\x7A\x3E\x21\x62\xF1\x7F\x63\x71\x0C\xC9\x9F\x44\xDB\xA8\x27\xA2\x75\xBE\x6E\x81\x3E\xD7\xC0\xEB\x1B\x98\x0F\x70\x5C\x34\xB2\x8A\xCC\xC0\x85\x18\xEB\x6E\x7A\xB3\xF7\x5A\xA1\x07\xBF\xA9\x42\x92\xF3\x60\x22\x97\xE4\x14\xA1\x07\x9B\x4E\x76\xC0\x8E\x7D\xFD\xA4\x25\xC7\x47\xED\xFF\x1F\x73\xAC\xCC\xC3\xA5\xE9\x6F\x0A\x8E\x9B\x65\xC2\x50\x85\xB5\xA3\xA0\x53\x12\xCC\x55\x87\x61\xF3\x81\xAE\x10\x46\x61\xBD\x44\x21\xB8\xC2\x3D\x74\xCF\x7E\x24\x35\xFA\x1C\x07\x0E\x9B\x3D\x22\xCA\xEF\x31\x2F\x8C\xAC\x12\xBD\xEF\x40\x28\xFC\x29\x67\x9F\xB2\x13\x4F\x66\x24\xC4\x53\x19\xE9\x1E\x29\x15\xEF\xE6\x6D\xB0\x7F\x2D\x67\xFD\xF3\x6C\x1B\x75\x46\xA3\xE5\x4A\x17\xE9\xA4\xD7\x0B", }; From 78ef31577b3a6d6f478f74f28743a1c5efe2e145 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 19 Sep 2013 16:16:09 -0500 Subject: [PATCH 338/881] Add links to Intelligence Framework documentation --- doc/frameworks/intel.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/frameworks/intel.rst b/doc/frameworks/intel.rst index 616de3b858..f90092aac3 100644 --- a/doc/frameworks/intel.rst +++ b/doc/frameworks/intel.rst @@ -59,15 +59,15 @@ intelligence framework has distribution mechanisms which will push data out to all of the nodes that need it. Here is an example of the intelligence data format. Note that all -whitespace separators are literal tabs and fields containing only a -hyphen are considered to be null values.:: +whitespace field separators are literal tabs and fields containing only a +hyphen are considered to be null values. :: #fields indicator indicator_type meta.source meta.desc meta.url 1.2.3.4 Intel::ADDR source1 Sending phishing email http://source1.com/badhosts/1.2.3.4 a.b.com Intel::DOMAIN source2 Name used for data exfiltration - -For more examples of built in `indicator_type` values, please refer to the -autogenerated documentation for the intelligence framework. +For a list of all built-in `indicator_type` values, please refer to the +documentation of :bro:see:`Intel::Type`. To load the data once files are created, use the following example code to define files to load with your own file names of course:: @@ -87,7 +87,7 @@ When some bit of data is extracted (such as an email address in the "From" header in a message over SMTP), the Intelligence Framework needs to be informed that this data was discovered and it's presence should be checked within the intelligence data set. This is -accomplished through the Intel::seen function. +accomplished through the :bro:see:`Intel::seen` function. Typically users won't need to work with this function due to built in hook scripts that Bro ships with that will "see" data and send it into @@ -95,8 +95,8 @@ the intelligence framework. A user may only need to load the entire package of hook scripts as a module or pick and choose specific scripts to load. Keep in mind that as more data is sent into the intelligence framework, the CPU load consumed by Bro will increase -depending on how many times the Intel::seen function is being called -which is heavily traffic dependent. +depending on how many times the :bro:see:`Intel::seen` function is +being called which is heavily traffic dependent. The full package of hook scripts that Bro ships with for sending this "seen" data into the intelligence framework can be loading by adding @@ -110,12 +110,12 @@ Intelligence Matches Against all hopes, most networks will eventually have a hit on intelligence data which could indicate a possible compromise or other unwanted activity. The Intelligence Framework provides an event that -is generated whenever a match is discovered named Intel::match (TODO: -make a link to inline docs). Due to design restrictions placed upon +is generated whenever a match is discovered named :bro:see:`Intel::match`. +Due to design restrictions placed upon the intelligence framework, there is no assurance as to where this event will be generated. It could be generated on the worker where -the data was seen or on the manager. When the Intel::match event is +the data was seen or on the manager. When the ``Intel::match`` event is handled, only the data given as event arguments to the event can be assured since the host where the data was seen may not be where -Intel::match is handled. +``Intel::match`` is handled. From df552ca87d842ca66a9bd234f0feea2ac8174929 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 19 Sep 2013 14:35:11 -0700 Subject: [PATCH 339/881] parse out extension. One event for general extensions (just returns the openssl-parsed string-value), one event for basicconstraints (is a certificate a CA or not) and one event for subject-alternative-names (only DNS parts). --- scripts/base/files/x509/main.bro | 15 ++ scripts/base/init-bare.bro | 22 ++- src/analyzer/protocol/ssl/SSL.h | 2 +- src/analyzer/protocol/ssl/events.bif | 2 +- src/analyzer/protocol/ssl/ssl-analyzer.pac | 28 ---- src/file_analysis/analyzer/x509/X509.cc | 153 ++++++++++++++++++++- src/file_analysis/analyzer/x509/X509.h | 6 + src/file_analysis/analyzer/x509/events.bif | 3 + src/file_analysis/analyzer/x509/types.bif | 4 + 9 files changed, 202 insertions(+), 33 deletions(-) diff --git a/scripts/base/files/x509/main.bro b/scripts/base/files/x509/main.bro index 205b8fbd25..458a389934 100644 --- a/scripts/base/files/x509/main.bro +++ b/scripts/base/files/x509/main.bro @@ -12,3 +12,18 @@ event x509_cert(f: fa_file, cert: X509::Certificate) print cert; } +event x509_extension(f: fa_file, ext: X509::Extension) +{ +print ext; +} + +event x509_ext_basic_constraints(f: fa_file, ext: X509::BasicConstraints) +{ +print ext; +} + +event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativeName) +{ +print ext; +} + diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 5d7914dc6b..c8e2e52b8a 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -2736,9 +2736,27 @@ export { key_length: count &optional; ##< key-length in bits exponent: string &optional; ##< exponent, if RSA-certificate curve: string &optional; ##< curve, if EC-certificate - ca: bool &optional; ##< indicates the CA value in the X509v3 BasicConstraints extension - path_len: count &optional; ##< indicates the path_length value in the X509v3 BasicConstraints extension + #ca: bool &optional; ##< indicates the CA value in the X509v3 BasicConstraints extension + #path_len: count &optional; ##< indicates the path_length value in the X509v3 BasicConstraints extension }; + + type X509::Extension: record { + name: string; ##< long name of extension. oid if name not known + short_name: string &optional; ##< short name of extension if known. + oid: string; ##< oid of extension + critical: bool; ##< true if extension is critical + value: string; ##< extension content parsed to string for known extensions. Raw data otherwise. + }; + + type X509::BasicConstraints: record { + ca: bool; ##< CA flag set? + path_len: count &optional; + }; + + type X509::SubjectAlternativeName: record { + names: vector of string; + }; + } module SOCKS; diff --git a/src/analyzer/protocol/ssl/SSL.h b/src/analyzer/protocol/ssl/SSL.h index 6423d1b155..5749066780 100644 --- a/src/analyzer/protocol/ssl/SSL.h +++ b/src/analyzer/protocol/ssl/SSL.h @@ -28,7 +28,7 @@ public: { return ( ssl_client_hello || ssl_server_hello || ssl_established || ssl_extension || ssl_alert || - x509_certificate || x509_extension || x509_error ); + x509_certificate || x509_error ); } protected: diff --git a/src/analyzer/protocol/ssl/events.bif b/src/analyzer/protocol/ssl/events.bif index 3d0c7e9d6a..b7586561fc 100644 --- a/src/analyzer/protocol/ssl/events.bif +++ b/src/analyzer/protocol/ssl/events.bif @@ -176,7 +176,7 @@ event x509_certificate%(c: connection, is_orig: bool, cert: X509, chain_idx: cou ## ## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension ## ssl_server_hello x509_certificate x509_error x509_verify -event x509_extension%(c: connection, is_orig: bool, data: string%); +#event x509_extension%(c: connection, is_orig: bool, data: string%); ## Generated when errors occur during parsing an X509 certificate. ## diff --git a/src/analyzer/protocol/ssl/ssl-analyzer.pac b/src/analyzer/protocol/ssl/ssl-analyzer.pac index 4cd7599ef7..43e2ac5c73 100644 --- a/src/analyzer/protocol/ssl/ssl-analyzer.pac +++ b/src/analyzer/protocol/ssl/ssl-analyzer.pac @@ -296,34 +296,6 @@ refine connection SSL_Conn += { i, certificates->size(), der_cert); - // Are there any X509 extensions? - //printf("Number of x509 extensions: %d\n", X509_get_ext_count(pTemp)); - if ( x509_extension && X509_get_ext_count(pTemp) > 0 ) - { - int num_ext = X509_get_ext_count(pTemp); - for ( int k = 0; k < num_ext; ++k ) - { - unsigned char *pBuffer = 0; - int length = 0; - - X509_EXTENSION* ex = X509_get_ext(pTemp, k); - if (ex) - { - ASN1_STRING *pString = X509_EXTENSION_get_data(ex); - length = ASN1_STRING_to_UTF8(&pBuffer, pString); - //i2t_ASN1_OBJECT(&pBuffer, length, obj) - // printf("extension length: %d\n", length); - // -1 indicates an error. - if ( length >= 0 ) - { - StringVal* value = new StringVal(length, (char*)pBuffer); - BifEvent::generate_x509_extension(bro_analyzer(), - bro_analyzer()->Conn(), ${rec.is_orig}, value); - } - OPENSSL_free(pBuffer); - } - } - } X509_free(pTemp); } } diff --git a/src/file_analysis/analyzer/x509/X509.cc b/src/file_analysis/analyzer/x509/X509.cc index 78d746ac9b..3d7871be9a 100644 --- a/src/file_analysis/analyzer/x509/X509.cc +++ b/src/file_analysis/analyzer/x509/X509.cc @@ -47,6 +47,27 @@ bool file_analysis::X509::EndOfFile() return false; } + ParseCertificate(ssl_cert); + + // after parsing the certificate - parse the extensions... + + int num_ext = X509_get_ext_count(ssl_cert); + for ( int k = 0; k < num_ext; ++k ) + { + X509_EXTENSION* ex = X509_get_ext(ssl_cert, k); + if ( !ex ) + continue; + + ParseExtension(ex); + } + + X509_free(ssl_cert); + + return false; + } + +void file_analysis::X509::ParseCertificate(::X509* ssl_cert) + { char buf[256]; // we need a buffer for some of the openssl functions memset(buf, 0, 256); @@ -117,8 +138,138 @@ bool file_analysis::X509::EndOfFile() vl->append(pX509Cert); mgr.QueueEvent(x509_cert, vl); + } + +void file_analysis::X509::ParseExtension(X509_EXTENSION* ex) + { + char name[256]; + char oid[256]; + + ASN1_OBJECT* ext_asn = X509_EXTENSION_get_object(ex); + const char* short_name = OBJ_nid2sn(OBJ_obj2nid(ext_asn)); + + OBJ_obj2txt(name, 255, ext_asn, 0); + OBJ_obj2txt(oid, 255, ext_asn, 1); + + int critical = 0; + if ( X509_EXTENSION_get_critical(ex) != 0 ) + critical = 1; + + BIO *bio = BIO_new(BIO_s_mem()); + if(!X509V3_EXT_print(bio, ex, 0, 0)) + M_ASN1_OCTET_STRING_print(bio,ex->value); - return false; + BIO_flush(bio); + int length = BIO_pending(bio); + char *buffer = new char[length]; + BIO_read(bio, (void*)buffer, length); + StringVal* ext_val = new StringVal(length, buffer); + delete(buffer); + BIO_free_all(bio); + + RecordVal* pX509Ext = new RecordVal(BifType::Record::X509::Extension); + pX509Ext->Assign(0, new StringVal(name)); + if ( short_name and strlen(short_name) > 0 ) + pX509Ext->Assign(1, new StringVal(short_name)); + pX509Ext->Assign(2, new StringVal(oid)); + pX509Ext->Assign(3, new Val(critical, TYPE_BOOL)); + pX509Ext->Assign(4, ext_val); + + // send off generic extension event + // + // and then look if we have a specialized event for the extension we just + // parsed. And if we have it, we send the specialized event on top of the + // generic event that we just had. I know, that is... kind of not nice, + // but I am not sure if there is a better way to do it... + val_list* vl = new val_list(); + vl->append(GetFile()->GetVal()->Ref()); + vl->append(pX509Ext); + + mgr.QueueEvent(x509_extension, vl); + + + // look if we have a specialized handler for this event... + if ( OBJ_obj2nid(ext_asn) == NID_basic_constraints ) + ParseBasicConstraints(ex); + else if ( OBJ_obj2nid(ext_asn) == NID_subject_alt_name ) + ParseSAN(ex); + + + + } +void file_analysis::X509::ParseBasicConstraints(X509_EXTENSION* ex) + { + assert(OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == NID_basic_constraints); + + RecordVal* pBasicConstraint = new RecordVal(BifType::Record::X509::BasicConstraints); + BASIC_CONSTRAINTS *constr = (BASIC_CONSTRAINTS *) X509V3_EXT_d2i(ex); + if ( !constr ) + { + reporter->Error("Certificate with invalid BasicConstraint"); + } + else + { + pBasicConstraint->Assign(0, new Val(constr->ca ? 1 : 0, TYPE_BOOL)); + if ( constr->pathlen ) { + pBasicConstraint->Assign(1, new Val((int32_t) ASN1_INTEGER_get(constr->pathlen), TYPE_COUNT)); + } + val_list* vl = new val_list(); + vl->append(GetFile()->GetVal()->Ref()); + vl->append(pBasicConstraint); + + mgr.QueueEvent(x509_ext_basic_constraints, vl); + + } + + } + +void file_analysis::X509::ParseSAN(X509_EXTENSION* ext) + { + assert(OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_subject_alt_name); + + GENERAL_NAMES *altname = (GENERAL_NAMES*)X509V3_EXT_d2i(ext); + if ( !altname ) + { + reporter->Error("could not parse subject alternative names"); + return; + } + + VectorVal* names = new VectorVal(internal_type("string_vec")->AsVectorType()); + + int j = 0; + for ( int i = 0; i < sk_GENERAL_NAME_num(altname); i++ ) + { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(altname, i); + assert(gen); + + if ( gen->type == GEN_DNS ) + { + if (ASN1_STRING_type(gen->d.ia5) != V_ASN1_IA5STRING) + { + reporter->Error("DNS-field does not contain an IA5String"); + continue; + } + const char* name = (const char*) ASN1_STRING_data(gen->d.ia5); + StringVal* bs = new StringVal(name); + names->Assign(j, bs); + j++; + } + else + { + // we should perhaps sometime parse out ip-addresses + reporter->Error("Subject alternative name contained non-dns fields"); + continue; + } + } + + RecordVal* pSan = new RecordVal(BifType::Record::X509::SubjectAlternativeName); + pSan->Assign(0, names); + + val_list* vl = new val_list(); + vl->append(GetFile()->GetVal()->Ref()); + vl->append(pSan); + + mgr.QueueEvent(x509_ext_basic_constraints, vl); } StringVal* file_analysis::X509::key_curve(EVP_PKEY *key) diff --git a/src/file_analysis/analyzer/x509/X509.h b/src/file_analysis/analyzer/x509/X509.h index ce74190b69..cc0131afac 100644 --- a/src/file_analysis/analyzer/x509/X509.h +++ b/src/file_analysis/analyzer/x509/X509.h @@ -7,6 +7,7 @@ #include "../File.h" #include "Analyzer.h" +#include #include namespace file_analysis { @@ -30,6 +31,11 @@ private: static StringVal* key_curve(EVP_PKEY *key); static unsigned int key_length(EVP_PKEY *key); + void ParseCertificate(::X509* ssl_cert); + void ParseExtension(X509_EXTENSION* ex); + void ParseBasicConstraints(X509_EXTENSION* ex); + void ParseSAN(X509_EXTENSION* ex); + std::string cert_data; }; diff --git a/src/file_analysis/analyzer/x509/events.bif b/src/file_analysis/analyzer/x509/events.bif index 3c3049559d..148d09ec00 100644 --- a/src/file_analysis/analyzer/x509/events.bif +++ b/src/file_analysis/analyzer/x509/events.bif @@ -1 +1,4 @@ event x509_cert%(f: fa_file, cert: X509::Certificate%); +event x509_extension%(f: fa_file, ext: X509::Extension%); +event x509_ext_basic_constraints%(f: fa_file, ext: X509::BasicConstraints%); +event x509_ext_subject_alternative_name%(f: fa_file, ext: X509::SubjectAlternativeName%); diff --git a/src/file_analysis/analyzer/x509/types.bif b/src/file_analysis/analyzer/x509/types.bif index 9e4fd48420..49a915c7fc 100644 --- a/src/file_analysis/analyzer/x509/types.bif +++ b/src/file_analysis/analyzer/x509/types.bif @@ -1 +1,5 @@ type X509::Certificate: record; +type X509::Extension: record; +type X509::BasicConstraints: record; +type X509::SubjectAlternativeName: record; + From fe3c14c9faf1627905635c88afc66380b4705a3b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 19 Sep 2013 15:14:53 -0700 Subject: [PATCH 340/881] Updating submodule(s). [nomail] --- aux/binpac | 2 +- aux/bro-aux | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aux/binpac b/aux/binpac index 75e6906efb..eeb19daacc 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 75e6906efb23036ea5a11936487498761a5f7eab +Subproject commit eeb19daacc9f12bc4e7c885fa70e71f856a90b1f diff --git a/aux/bro-aux b/aux/bro-aux index 3e1c8bf5f3..eb24e62864 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 3e1c8bf5f34868759d578f2afc6707fd1797f958 +Subproject commit eb24e628648c7d7b931bdb57d38ab32c28296e72 From 1e21fc177c9b3245f6652711f1f926112169a5af Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 19 Sep 2013 15:22:30 -0700 Subject: [PATCH 341/881] Updating submodule(s). [nomail] --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 13a7718b47..3918bd9f5f 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 13a7718b475d670ae22c1914ac1c26bd11be46b6 +Subproject commit 3918bd9f5f99863faec2501e5bc7839ffb17bdc9 From bfbf1f7305e150bd3f4b2c62bfec4bbd81bb98ec Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 19 Sep 2013 17:34:07 -0500 Subject: [PATCH 342/881] Add more links in the GeoLocation document --- doc/frameworks/geoip.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/frameworks/geoip.rst b/doc/frameworks/geoip.rst index 3c3883a607..f54ea03096 100644 --- a/doc/frameworks/geoip.rst +++ b/doc/frameworks/geoip.rst @@ -67,8 +67,8 @@ functionality: function lookup_location(a:addr): geo_location -There is also the ``geo_location`` data structure that is returned -from the ``lookup_location`` function: +There is also the :bro:see:`geo_location` data structure that is returned +from the :bro:see:`lookup_location` function: .. code:: bro From e5a4123b4e1bb901b9ff495f0d4c4171915d7360 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 20 Sep 2013 09:38:52 -0500 Subject: [PATCH 343/881] Kill raw input reader's child by process group. This should help on systems where the default shell (e.g. dash on Ubuntu) fork-execs in order to run commands. In that case, we were just killing the shell and the shell would exit without killing the actual process corresponding to command that was requested. Setting a process group for the shell exec'd from Bro and killing by process group should help clean everything up since process group will be inherited by any procs that shell fork-execs. --- src/input/readers/Raw.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/input/readers/Raw.cc b/src/input/readers/Raw.cc index 64c29d632c..34408b79d2 100644 --- a/src/input/readers/Raw.cc +++ b/src/input/readers/Raw.cc @@ -73,15 +73,15 @@ void Raw::DoClose() if ( execute && childpid > 0 && kill(childpid, 0) == 0 ) { - // kill child process - kill(childpid, SIGTERM); + // kill child process group + kill(-childpid, SIGTERM); if ( forcekill ) { usleep(200); // 200 msecs should be enough for anyone ;) if ( kill(childpid, 0) == 0 ) // perhaps it is already gone - kill(childpid, SIGKILL); + kill(-childpid, SIGKILL); } } } @@ -146,6 +146,11 @@ bool Raw::Execute() else if ( childpid == 0 ) { // we are the child. + + // Obtain a process group w/ child's PID. + if ( setpgid(0, 0) == -1 ) + _exit(251); + close(pipes[stdout_in]); if ( dup2(pipes[stdout_out], stdout_fileno) == -1 ) _exit(252); @@ -180,6 +185,15 @@ bool Raw::Execute() else { // we are the parent + + // Parent also sets child process group immediately to avoid a race. + if ( setpgid(childpid, childpid) == -1 ) + { + char buf[256]; + strerror_r(errno, buf, sizeof(buf)); + Warning(Fmt("Could not set child process group: %s", buf)); + } + if ( ! UnlockForkMutex() ) return false; From 17bc3955f90b62659f55a85ad11dfc710be2a484 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Fri, 20 Sep 2013 11:43:45 -0400 Subject: [PATCH 344/881] Update the lines included from events.bif.bro. Previously listed connection_established and connection_finished which are no longer in place in events.bif.bro. --- doc/scripting/index.rst | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 197180241e..aca1a9472e 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -197,13 +197,8 @@ such, there are events defined for the primary parts of the connection life-cycle as you'll see from the small selection of connection-related events below. -.. todo:: - - Update the line numbers, this isn't pulling in the right events - anymore but I don't know which ones it were. - .. btest-include:: ${BRO_SRC_ROOT}/build/scripts/base/bif/event.bif.bro - :lines: 135-138,154,204-208,218,255-256,266,335-340,351 + :lines: 69-72,88,106-109,129,132-137,148 Of the events listed, the event that will give us the best insight into the connection record data type will be From 5fede2f73e6d7758bbb27a73440a01efba04731c Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Fri, 20 Sep 2013 12:22:12 -0400 Subject: [PATCH 345/881] Spelling corrections. Apparently I am unable to spell "separate". --- doc/scripting/index.rst | 44 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index aca1a9472e..b01165a5bc 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -33,7 +33,7 @@ are invalid. This entire process is setup by telling Bro that should it see a server or client issue an SSL ``HELLO`` message, we want to know about the information about that connection. -It's often the easiest to understand Bro's scripting language by +It's often easiest to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how Bro queries the `Team Cymru Malware hash registry @@ -76,7 +76,7 @@ this level of granularity might not be entirely necessary though. The export section redefines an enumerable constant that describes the type of notice we will generate with the logging framework. Bro -allows for redefinable constants, which at first, might seem +allows for re-definable constants, which at first, might seem counter-intuitive. We'll get more in-depth with constants in a later chapter, for now, think of them as variables that can only be altered before Bro starts running. The notice type listed allows for the use @@ -84,7 +84,7 @@ of the :bro:id:`NOTICE` function to generate notices of type ``Malware_Hash_Registry_Match`` as done in the next section. Notices allow Bro to generate some kind of extra notification beyond its default log types. Often times, this extra notification comes in the -form of an email generated and sent to a pre-configured address. +form of an email generated and sent to a preconfigured address. .. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro :lines: 26-44 @@ -112,9 +112,9 @@ The ``when`` block performs a DNS TXT lookup and stores the result in the local variable ``MHR_result``. Effectively, processing for this event continues and upon receipt of the values returned by :bro:id:`lookup_hostname_txt`, the ``when`` block is executed. The -``when`` block splits the string returned into two seperate values and +``when`` block splits the string returned into two separate values and checks to ensure an expected format. If the format is invalid, the -script assumes that the hash wasn't found in the respository and +script assumes that the hash wasn't found in the repository and processing is concluded. If the format is as expected and the detection rate is above the threshold set by ``MHR_threshold``, two new local variables are created and used in the notice issued by @@ -168,7 +168,7 @@ the event, and a concise explanation of the functions use. :lines: 29-54 Above is a segment of the documentation for the event -:bro:id:`dns_request` (and the preceeding link points to the +:bro:id:`dns_request` (and the preceding link points to the documentation generated out of that). It's organized such that the documentation, commentary, and list of arguments precede the actual event definition used by Bro. As Bro detects DNS requests being @@ -240,7 +240,7 @@ information gleaned from the analysis of a connection as a complete unit. To break down this collection of information, you will have to make use of use Bro's field delimiter ``$``. For example, the originating host is referenced by ``c$id$orig_h`` which if given a -narritive relates to ``orig_h`` which is a member of ``id`` which is +narrative relates to ``orig_h`` which is a member of ``id`` which is a member of the data structure referred to as ``c`` that was passed into the event handler." Given that the responder port (``c$id$resp_p``) is ``53/tcp``, it's likely that Bro's base DNS scripts @@ -338,7 +338,7 @@ Constants Bro also makes use of constants, which are denoted by the ``const`` keyword. Unlike globals, constants can only be set or altered at parse time if the ``&redef`` attribute has been used. Afterwards (in -runtime) the constants are unalterable. In most cases, redefinable +runtime) the constants are unalterable. In most cases, re-definable constants are used in Bro scripts as containers for configuration options. For example, the configuration option to log password decrypted from HTTP streams is stored in @@ -354,7 +354,7 @@ following line to our ``site/local.bro`` file before firing up Bro. .. btest-include:: ${DOC_ROOT}/scripting/data_type_const_simple.bro -While the idea of a redefinable constant might be odd, the constraint +While the idea of a re-definable constant might be odd, the constraint that constants can only be altered at parse-time remains even with the ``&redef`` attribute. In the code snippet below, a table of strings indexed by ports is declared as a constant before two values are added @@ -412,7 +412,7 @@ The table below shows the atomic types used in Bro, of which the first four should seem familiar if you have some scripting experience, while the remaining six are less common in other languages. It should come as no surprise that a scripting language for a Network Security -Monitoring platform has a fairly robust set of network centric data +Monitoring platform has a fairly robust set of network-centric data types and taking note of them here may well save you a late night of reinventing the wheel. @@ -474,7 +474,7 @@ the ``for`` loop, the next element is chosen. Since sets are not an ordered data type, you cannot guarantee the order of the elements as the ``for`` loop processes. -To test for membership in a set the ``in`` statment can be combined +To test for membership in a set the ``in`` statement can be combined with an ``if`` statement to return a true or false value. If the exact element in the condition is already in the set, the condition returns true and the body executes. The ``in`` statement can also be @@ -541,7 +541,7 @@ iterate over, say, the directors; we have to iterate with the exact format as the keys themselves. In this case, we need squared brackets surrounding four temporary variables to act as a collection for our iteration. While this is a contrived example, we could easily have -had keys containin IP addresses (``addr``), ports (``port``) and even a ``string`` +had keys containing IP addresses (``addr``), ports (``port``) and even a ``string`` calculated as the result of a reverse hostname lookup. .. btest-include:: ${DOC_ROOT}/scripting/data_struct_table_complex.bro @@ -642,7 +642,7 @@ subnet ~~~~~~ Bro has full support for CIDR notation subnets as a base data type. -There is no need to manage the IP and the subnet mask as two seperate +There is no need to manage the IP and the subnet mask as two separate entities when you can provide the same information in CIDR notation in your scripts. The following example below uses a Bro script to determine if a series of IP addresses are within a set of subnets @@ -802,7 +802,7 @@ composite type. We have, in fact, already encountered a a complex example of the ``record`` data type in the earlier sections, the :bro:type:`connection` record passed to many events. Another one, :bro:type:`Conn::Info`, which corresponds to the fields logged into -``conn.log``, is shown by the exerpt below. +``conn.log``, is shown by the excerpt below. .. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro :lines: 10-12,16,17,19,21,23,25,28,31,35,37,56,62,68,90,93,97,100,104,108,109,114 @@ -813,7 +813,7 @@ definition is within the confines of an export block, what is defined is, in fact, ``Conn::Info``. The formatting for a declaration of a record type in Bro includes the -descriptive name of the type being defined and the seperate fields +descriptive name of the type being defined and the separate fields that make up the record. The individual fields that make up the new record are not limited in type or number as long as the name for each field is unique. @@ -829,7 +829,7 @@ string, a set of ports, and a count to define a service type. Also included is a function to print each field of a record in a formatted fashion and a :bro:id:`bro_init` event handler to show some functionality of working with records. The definitions of the DNS and -HTTP services are both done inline using squared brackets before being +HTTP services are both done in-line using squared brackets before being passed to the ``print_service`` function. The ``print_service`` function makes use of the ``$`` dereference operator to access the fields within the newly defined Service record type. @@ -846,7 +846,7 @@ record. @TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_02.bro The example above includes a second record type in which a field is -used as the data type for a set. Records can be reapeatedly nested +used as the data type for a set. Records can be repeatedly nested within other records, their fields reachable through repeated chains of the ``$`` dereference operator. @@ -1123,7 +1123,7 @@ which we will cover shortly. +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | policy_items | set[count] | &log &optional | Policy items that have been applied | +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ -| email_body_sections | vector | &optinal | Body of the email for email notices. | +| email_body_sections | vector | &optional | Body of the email for email notices. | +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | email_delay_tokens | set[string] | &optional | Delay functionality for email notices. | +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ @@ -1137,7 +1137,7 @@ has been heuristically detected and the originating hostname is one that would raise suspicion. Effectively, the script attempts to define a list of hosts from which you would never want to see SSH traffic originating, like DNS servers, mail servers, etc. To -accomplish this, the script adhere's to the seperation of detection +accomplish this, the script adheres to the separation of detection and reporting by detecting a behavior and raising a notice. Whether or not that notice is acted upon is decided by the local Notice Policy, but the script attempts to supply as much information as @@ -1221,7 +1221,7 @@ Bro. In the :doc:`/scripts/policy/protocols/ssl/expiring-certs` script which identifies when SSL certificates are set to expire and raises -notices when it crosses a pre-defined threshold, the call to +notices when it crosses a predefined threshold, the call to ``NOTICE`` above also sets the ``$identifier`` entry by concatenating the responder IP, port, and the hash of the certificate. The selection of responder IP, port and certificate hash fits perfectly @@ -1257,7 +1257,7 @@ In short, there will be notice policy considerations where a broad decision can be made based on the ``Notice::Type`` alone. To facilitate these types of decisions, the Notice Framework supports Notice Policy shortcuts. These shortcuts are implemented through the -means of a group of data structures that map specific, pre-defined +means of a group of data structures that map specific, predefined details and actions to the effective name of a notice. Primarily implemented as a set or table of enumerables of :bro:type:`Notice::Type`, Notice Policy shortcuts can be placed as a single directive in your @@ -1303,5 +1303,3 @@ Notice::emailed_types set while the shortcut below alters the length of time for which those notices will be suppressed. .. btest-include:: ${DOC_ROOT}/scripting/framework_notice_shortcuts_02.bro - - From dbbbea312c9a1b133c90fb74b1f37364e9c01ee6 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 20 Sep 2013 11:37:19 -0500 Subject: [PATCH 346/881] Fix DNS_Mgr iterator mismatch. But not really since the global dns_mgr should be equal to "this" while in all the member funcs. Still, better that they always refer to their own instance instead of the global one. --- src/DNS_Mgr.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index e57714a047..5880a02c57 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -928,7 +928,7 @@ void DNS_Mgr::Save(FILE* f, const HostMap& m) const char* DNS_Mgr::LookupAddrInCache(const IPAddr& addr) { - AddrMap::iterator it = dns_mgr->addr_mappings.find(addr); + AddrMap::iterator it = addr_mappings.find(addr); if ( it == addr_mappings.end() ) return 0; @@ -937,7 +937,7 @@ const char* DNS_Mgr::LookupAddrInCache(const IPAddr& addr) if ( d->Expired() ) { - dns_mgr->addr_mappings.erase(it); + addr_mappings.erase(it); delete d; return 0; } @@ -949,10 +949,10 @@ const char* DNS_Mgr::LookupAddrInCache(const IPAddr& addr) TableVal* DNS_Mgr::LookupNameInCache(string name) { - HostMap::iterator it = dns_mgr->host_mappings.find(name); - if ( it == dns_mgr->host_mappings.end() ) + HostMap::iterator it = host_mappings.find(name); + if ( it == host_mappings.end() ) { - it = dns_mgr->host_mappings.begin(); + it = host_mappings.begin(); return 0; } @@ -964,7 +964,7 @@ TableVal* DNS_Mgr::LookupNameInCache(string name) if ( d4->Expired() || d6->Expired() ) { - dns_mgr->host_mappings.erase(it); + host_mappings.erase(it); delete d4; delete d6; return 0; @@ -979,15 +979,15 @@ TableVal* DNS_Mgr::LookupNameInCache(string name) const char* DNS_Mgr::LookupTextInCache(string name) { - TextMap::iterator it = dns_mgr->text_mappings.find(name); - if ( it == dns_mgr->text_mappings.end() ) + TextMap::iterator it = text_mappings.find(name); + if ( it == text_mappings.end() ) return 0; DNS_Mapping* d = it->second; if ( d->Expired() ) { - dns_mgr->text_mappings.erase(it); + text_mappings.erase(it); delete d; return 0; } From 9033b0384be630b28f00a7b4f58b6f710796d162 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 20 Sep 2013 12:11:10 -0500 Subject: [PATCH 347/881] Fix invalidated iterator usage. --- src/DbgBreakpoint.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/DbgBreakpoint.cc b/src/DbgBreakpoint.cc index 11847fc4dc..f1ad551a00 100644 --- a/src/DbgBreakpoint.cc +++ b/src/DbgBreakpoint.cc @@ -85,10 +85,17 @@ void DbgBreakpoint::RemoveFromGlobalMap() pair p; p = g_debugger_state.breakpoint_map.equal_range(at_stmt); - for ( BPMapType::iterator i = p.first; i != p.second; ++i ) + for ( BPMapType::iterator i = p.first; i != p.second; ) { if ( i->second == this ) + { + BPMapType::iterator next = i; + ++next; g_debugger_state.breakpoint_map.erase(i); + i = next; + } + else + ++i; } } From 8e3c6ada0fc0249fece2864faaa04dfd1b330c2c Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Fri, 20 Sep 2013 13:25:49 -0400 Subject: [PATCH 348/881] Rewrite the MHR detection description. Now that the MHR script uses the file analysis framework, the description needed to be rewritten to reflect the changes. Robin commented that he didn't feel the MHR script was a good introductory script and he might be right, however, I couldn't find one that was easier to explain. --- doc/scripting/index.rst | 95 ++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index b01165a5bc..077d5a9c45 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -10,13 +10,6 @@ Writing Bro Scripts Understanding Bro Scripts ========================= -.. todo:: - - The MHR integration has changed significantly since the text was - written. We need to update it, however I'm actually not sure this - script is a good introductory example anymore unfortunately. - -Robin - Bro includes an event-driven scripting language that provides the primary means for an organization to extend and customize Bro's functionality. Virtually all of the output generated by Bro @@ -51,82 +44,96 @@ appropriate DNS lookup and parsing the response. .. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro Visually, there are three distinct sections of the script. A base -level with no indentation followed by an indented and formatted -section explaining the custom variables being provided (``export``) and another -indented and formatted section describing the instructions for a -specific event (``event log_http``). Don't get discouraged if you don't +level with no indentation where libraries are included in the script through ``@load`` +and a namespace is defined with ``module``. This is followed by an indented and formatted +section explaining the custom variables being provided (``export``) as part of the script's namespace. +Finally there is a second indented and formatted section describing the instructions to take for a +specific event (``event file_hash``). Don't get discouraged if you don't understand every section of the script; we'll cover the basics of the script and much more in following sections. .. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro - :lines: 7-11 + :lines: 4-6 Lines 7 and 8 of the script process the ``__load__.bro`` script in the respective directories being loaded. The ``@load`` directives are often considered good practice or even just good manners when writing -Bro scripts to make sure they can be -used on their own. While it's unlikely that in a +Bro scripts to make sure they can be used on their own. While it's unlikely that in a full production deployment of Bro these additional resources wouldn't already be loaded, it's not a bad habit to try to get into as you get more experienced with Bro scripting. If you're just starting out, -this level of granularity might not be entirely necessary though. +this level of granularity might not be entirely necessary. The ``@load`` directives +are ensuring the Files framework, the Notice framework and the script to hash all files has +been loaded by Bro. .. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro - :lines: 12-24 + :lines: 10-31 The export section redefines an enumerable constant that describes the -type of notice we will generate with the logging framework. Bro +type of notice we will generate with the Notice framework. Bro allows for re-definable constants, which at first, might seem counter-intuitive. We'll get more in-depth with constants in a later chapter, for now, think of them as variables that can only be altered before Bro starts running. The notice type listed allows for the use of the :bro:id:`NOTICE` function to generate notices of type -``Malware_Hash_Registry_Match`` as done in the next section. Notices +``TeamCymruMalwareHashRegistry::Match`` as done in the next section. Notices allow Bro to generate some kind of extra notification beyond its default log types. Often times, this extra notification comes in the -form of an email generated and sent to a preconfigured address. +form of an email generated and sent to a preconfigured address, but can be altered +depending on the needs of the deployment. The export section is finished off with +the definition of two constants that list the kind of files we want to match against and +the minimum percentage of detection threshold in which we are interested. + +Up until this point, the script has merely done some basic setup. With the next section, +the script starts to define instructions to take in a given event. .. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro - :lines: 26-44 + :lines: 33-57 The workhorse of the script is contained in the event handler for -``log_http``. The ``log_http`` event is defined as an event-hook in -the :doc:`/scripts/base/protocols/http/main` script and allows scripts -to handle a connection as it is being passed to the logging framework. -The event handler is passed an :bro:type:`HTTP::Info` data structure -which will be referred to as ``rec`` in body of the event handler. +``file_hash``. The ``file_hash`` event is defined in the +:doc:`/scripts/base/bif/plugins/Bro_FileHash.events.bif.bro` script and allows scripts to access +the information associated with a file for which Bro's file analysis framework has +generated a hash. The event handler is passed the file itself as ``f``, the type of digest +algorithm used as ``kind`` and the hash generated as ``hash``. -An ``if`` statement is used to check for the existence of a data structure -named ``md5`` nested within the ``rec`` data structure. Bro uses the ``$`` as -a deference operator and as such, and it is employed in this script to -check if ``rec$md5`` is present by including the ``?`` operator within the -path. If the ``rec`` data structure includes a nested data structure -named ``md5``, the statement is processed as true and a local variable -named ``hash_domain`` is provisioned and given a format string based on -the contents of ``rec$md5`` to produce a valid DNS lookup. +On line 35, an ``if`` statement is used to check for the correct type of hash, in this case +a SHA1 hash. It also checks for a mime type we've defined as being of interest as defined in the +constant ``match_file_types``. The comparison is made against the variable ``f$mime_type`` which uses +the ``$`` dereference operator to check the value ``mime_type`` inside the variable ``f``. Once both +values resolve to true, a local variable is defined to hold a string comprised of the SHA1 hash concatenated +with ".malware.hash.cymru.com"; this value will be the domain queried in the malware hash registry. The rest of the script is contained within a ``when`` block. In short, a ``when`` block is used when Bro needs to perform asynchronous -actions, such a DNS lookup, to ensure that performance isn't effected. +actions, such as a DNS lookup, to ensure that performance isn't effected. The ``when`` block performs a DNS TXT lookup and stores the result in the local variable ``MHR_result``. Effectively, processing for this event continues and upon receipt of the values returned by :bro:id:`lookup_hostname_txt`, the ``when`` block is executed. The -``when`` block splits the string returned into two separate values and -checks to ensure an expected format. If the format is invalid, the -script assumes that the hash wasn't found in the repository and -processing is concluded. If the format is as expected and the -detection rate is above the threshold set by ``MHR_threshold``, two -new local variables are created and used in the notice issued by -:bro:id:`NOTICE`. +``when`` block splits the string returned into a portion for the date on which +the malware was first detected and the detection rate by splitting on an text space +and storing the values returned in a local table variable. In line 42, if the table +returned by ``split1`` has two entries, indicating a sucessful split, we store the detection +date in ``mhr_first_detect`` and the rate in ``mhr_detect_rate`` on lines 45 and 45 respectively +using the appropriate conversion functions. From this point on, Bro knows it has seen a file +transmitted which has a hash that has been seen by the Team Cymru Malware Hash Registry, the rest +of the script is dedicated to producing a notice. -In approximately 15 lines of actual code, Bro provides an amazing +On line 47, the detection time is processed into a string representation and stored in +``readable_first_detected``. The script then compares the detection rate against the +``notice_threshold`` that was defined on line 30. If the detection rate is high enough, the script +creates a concise description of the notice on line 50, a possible URL to check the sample against +virustotal.com's database, and makes the call to :bro:id:`NOTICE` to hand the relevant information +off to the Notice framework. + +In approximately 25 lines of code, Bro provides an amazing utility that would be incredibly difficult to implement and deploy -with other products. In truth, claiming that Bro does this in 15 +with other products. In truth, claiming that Bro does this in 25 lines is a misdirection; there is a truly massive number of things going on behind-the-scenes in Bro, but it is the inclusion of the scripting language that gives analysts access to those underlying -layers in a succinct and well defined manner. +layers in a succinct and well defined manner. The Event Queue and Event Handlers ================================== From 89090ec34af8e2bba63d069fd077825080962103 Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Fri, 20 Sep 2013 13:33:44 -0400 Subject: [PATCH 349/881] Include a better description for detect-MHR.bro I added a better more concise and accurate description of what is going on behind the scenes of detect-MHR.bro to not only bring it into line with the Files framework but to help make it a bit more clear as to where the various responsibilities lie. --- doc/scripting/index.rst | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 077d5a9c45..aeaeac1726 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -29,17 +29,16 @@ about the information about that connection. It's often easiest to understand Bro's scripting language by looking at a complete script and breaking it down into its identifiable components. In this example, we'll take a look at how -Bro queries the `Team Cymru Malware hash registry -`_ for downloads via -HTTP. Part of the Team Cymru Malware Hash registry includes the -ability to do a host lookup on a domain with the format -``MALWARE_HASH.malware.hash.cymru.com`` where ``MALWARE_HASH`` is the MD5 or -SHA1 hash of a file. Team Cymru also populates the TXT record of -their DNS responses with both a "last seen" timestamp and a numerical -"detection rate". The important aspect to understand is Bro already -generates hashes for files it can parse from HTTP streams, but the -script ``detect-MHR.bro`` is responsible for generating the -appropriate DNS lookup and parsing the response. +Bro checks the SHA1 hash of various files extracted from network traffic +against the `Team Cymru Malware hash registry +`_. Part of the Team Cymru Malware +Hash registry includes the ability to do a host lookup on a domain with the format +``MALWARE_HASH.malware.hash.cymru.com`` where ``MALWARE_HASH`` is the SHA1 hash of a file. +Team Cymru also populates the TXT record of their DNS responses with both a "first seen" +timestamp and a numerical "detection rate". The important aspect to understand is Bro already +generating hashes for files via the Files framework, but it is the +script ``detect-MHR.bro`` that is responsible for generating the +appropriate DNS lookup, parsing the response, and generating a notice if appropriate. .. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro From 261b9e1e9747631bd5b0ae8f4bbfcc3b4cda9f0a Mon Sep 17 00:00:00 2001 From: Scott Runnels Date: Fri, 20 Sep 2013 13:36:56 -0400 Subject: [PATCH 350/881] Spelling corrections. --- doc/scripting/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index aeaeac1726..7c484af7e9 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -113,7 +113,7 @@ this event continues and upon receipt of the values returned by ``when`` block splits the string returned into a portion for the date on which the malware was first detected and the detection rate by splitting on an text space and storing the values returned in a local table variable. In line 42, if the table -returned by ``split1`` has two entries, indicating a sucessful split, we store the detection +returned by ``split1`` has two entries, indicating a successful split, we store the detection date in ``mhr_first_detect`` and the rate in ``mhr_detect_rate`` on lines 45 and 45 respectively using the appropriate conversion functions. From this point on, Bro knows it has seen a file transmitted which has a hash that has been seen by the Team Cymru Malware Hash Registry, the rest From 4e2e690bffa1dd348016f08c78ebcef53da23720 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 20 Sep 2013 14:21:03 -0500 Subject: [PATCH 351/881] Fix unintentional always-false condition. --- src/logging/Manager.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 87d3be9f13..8d833ddbc6 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -791,7 +791,7 @@ bool Manager::Write(EnumVal* id, RecordVal* columns) if ( ! v ) return false; - if ( ! v->Type()->Tag() == TYPE_STRING ) + if ( v->Type()->Tag() != TYPE_STRING ) { reporter->Error("path_func did not return string"); Unref(v); From 1750e351c4fec8b9f9e51fbca279de25cfa2e171 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 20 Sep 2013 16:36:00 -0500 Subject: [PATCH 352/881] Prevent division/modulo by zero in scripts. Integral/floating-point division/modulo by zero in C++ is undefined behavior, so to prevent such cases in a script from crashing Bro, they're now reported as an error (with script location information) and the event handler in which it occurred returns immediately. --- src/Expr.cc | 43 ++++++++++++++++++++- testing/btest/Baseline/core.div-by-zero/out | 5 +++ testing/btest/core/div-by-zero.bro | 36 +++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 testing/btest/Baseline/core.div-by-zero/out create mode 100644 testing/btest/core/div-by-zero.bro diff --git a/src/Expr.cc b/src/Expr.cc index f060b98602..5447999dd9 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -779,9 +779,48 @@ Val* BinaryExpr::Fold(Val* v1, Val* v2) const case EXPR_SUB: DO_FOLD(-); break; case EXPR_REMOVE_FROM: DO_FOLD(-); break; case EXPR_TIMES: DO_FOLD(*); break; - case EXPR_DIVIDE: DO_FOLD(/); break; + case EXPR_DIVIDE: + { + if ( is_integral ) + { + if ( i2 == 0 ) + reporter->ExprRuntimeError(this, "division by zero"); + i3 = i1 / i2; + } + else if ( is_unsigned ) + { + if ( u2 == 0 ) + reporter->ExprRuntimeError(this, "division by zero"); + u3 = u1 / u2; + } + else + { + if ( d2 == 0 ) + reporter->ExprRuntimeError(this, "division by zero"); + d3 = d1 / d2; + } + } + break; + + case EXPR_MOD: + { + if ( is_integral ) + { + if ( i2 == 0 ) + reporter->ExprRuntimeError(this, "modulo by zero"); + i3 = i1 % i2; + } + else if ( is_unsigned ) + { + if ( u2 == 0 ) + reporter->ExprRuntimeError(this, "modulo by zero"); + u3 = u1 % u2; + } + else + Internal("bad type in BinaryExpr::Fold"); + } + break; - case EXPR_MOD: DO_INT_FOLD(%); break; case EXPR_AND: DO_INT_FOLD(&&); break; case EXPR_OR: DO_INT_FOLD(||); break; diff --git a/testing/btest/Baseline/core.div-by-zero/out b/testing/btest/Baseline/core.div-by-zero/out new file mode 100644 index 0000000000..f5524b0cbf --- /dev/null +++ b/testing/btest/Baseline/core.div-by-zero/out @@ -0,0 +1,5 @@ +expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.div-by-zero/div-by-zero.bro, line 6: division by zero [a / b] +expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.div-by-zero/div-by-zero.bro, line 11: division by zero [a / b] +expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.div-by-zero/div-by-zero.bro, line 16: division by zero [a / b] +expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.div-by-zero/div-by-zero.bro, line 21: modulo by zero [a % b] +expression error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/core.div-by-zero/div-by-zero.bro, line 26: modulo by zero [a % b] diff --git a/testing/btest/core/div-by-zero.bro b/testing/btest/core/div-by-zero.bro new file mode 100644 index 0000000000..d1221638d6 --- /dev/null +++ b/testing/btest/core/div-by-zero.bro @@ -0,0 +1,36 @@ +# @TEST-EXEC: bro -b %INPUT >out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out + +event div_int(a: int, b: int) + { + print a / b; + } + +event div_count(a: count, b: count) + { + print a / b; + } + +event div_double(a: double, b: double) + { + print a / b; + } + +event mod_int(a: int, b: int) + { + print a % b; + } + +event mod_count(a: count, b: count) + { + print a % b; + } + +event bro_init() + { + event div_int(10, 0); + event div_count(10, 0); + event div_double(10.0, 0.0); + event mod_int(10, 0); + event mod_count(10, 0); + } From d070b018286b4d78e6968066f390a870250c68cb Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 20 Sep 2013 14:38:15 -0700 Subject: [PATCH 353/881] Updating baselines for doc changes. --- CHANGES | 2 +- VERSION | 2 +- .../output | 32 ++++++++----------- .../output | 8 ++--- .../output | 9 ++++++ .../output | 20 ++++++++---- 6 files changed, 41 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index aca5882f6c..9ff7b2368c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ -2.1-1376 | 2013-09-20 14:18:30 -0700 +2.1-1377 | 2013-09-20 14:38:15 -0700 * Updates to the scripting introduction. (Scott Runnels) diff --git a/VERSION b/VERSION index 174fa556a3..326b107a34 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-1376 +2.1-1377 diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output index fc14c86399..0d981e7fc0 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output @@ -2,24 +2,20 @@ -- event.bif.bro +## Generated for every new connection. This event is raised with the first +## packet of a previously unknown connection. Bro uses a flow-based definition +## of "connection" here that includes not only TCP sessions but also UDP and +## ICMP flows. +global new_connection: event(c: connection ); +## Generated when a TCP connection timed out. This event is raised when +## no activity was seen for an interval of at least +## :bro:id:`tcp_connection_linger`, and either one endpoint has already +## closed the connection or one side never became active. +global connection_timeout: event(c: connection ); +## Generated when a connection's internal state is about to be removed from +## memory. Bro generates this event reliably once for every connection when it +## is about to delete the internal state. As such, the event is well-suited for ## script-level cleanup that needs to be performed for every connection. This ## event is generated not only for TCP sessions but also for UDP and ICMP ## flows. -## -## -global connection_external: event(c: connection , tag: string ); - - -## Generated when a UDP session for a supported protocol has finished. Some of -## Bro's application-layer UDP analyzers flag the end of a session by raising -## Generated when a connection is seen that is marked as being expected. - - -global ipv6_ext_headers: event(c: connection , p: pkt_hdr ); -## their specifics differ slightly. Often, however, both will be raised for -## the same connection if some of its data is missing. We should eventually -## merge the two. -global ack_above_hole: event(c: connection ); - - -## +global connection_state_remove: event(c: connection ); diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output index 8d26caba6c..656abf3ba1 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output @@ -2,8 +2,6 @@ -- detect-MHR.bro - -module TeamCymruMalwareHashRegistry; - -export { - redef enum Notice::Type += { +@load base/frameworks/files +@load base/frameworks/notice +@load frameworks/files/hash-all-files diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output index ace6e79c5e..75d94f6990 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output @@ -2,6 +2,8 @@ -- detect-MHR.bro +export { + redef enum Notice::Type += { ## The hash value of a file transferred over HTTP matched in the ## malware hash registry. Match @@ -15,3 +17,10 @@ /application\/x-java-applet/ | /application\/jar/ | /video\/mp4/ &redef; + + ## The malware hash registry runs each malware sample through several A/V engines. + ## Team Cymru returns a percentage to indicate how many A/V engines flagged the + ## sample as malicious. This threshold allows you to require a minimum detection + ## rate. + const notice_threshold = 10 &redef; +} diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output index 6f4cda878c..7e3e1b0a11 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output @@ -2,13 +2,6 @@ -- detect-MHR.bro - ## The malware hash registry runs each malware sample through several A/V engines. - ## Team Cymru returns a percentage to indicate how many A/V engines flagged the - ## sample as malicious. This threshold allows you to require a minimum detection - ## rate. - const notice_threshold = 10 &redef; -} - event file_hash(f: fa_file, kind: string, hash: string) { if ( kind=="sha1" && match_file_types in f$mime_type ) @@ -21,3 +14,16 @@ event file_hash(f: fa_file, kind: string, hash: string) if ( |MHR_answer| == 2 ) { local mhr_first_detected = double_to_time(to_double(MHR_answer[1])); + local mhr_detect_rate = to_count(MHR_answer[2]); + + local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected); + if ( mhr_detect_rate >= notice_threshold ) + { + local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected); + local virustotal_url = fmt("https://www.virustotal.com/en/file/%s/analysis/", hash); + NOTICE([$note=Match, $msg=message, $sub=virustotal_url, $f=f]); + } + } + } + } + } From 8d7b9f0627b080e7cadaf0b276af219a8e3b951d Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 20 Sep 2013 14:52:58 -0700 Subject: [PATCH 354/881] Updating submodule(s). [nomail] --- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- aux/btest | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aux/binpac b/aux/binpac index eeb19daacc..c066a3ecbe 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit eeb19daacc9f12bc4e7c885fa70e71f856a90b1f +Subproject commit c066a3ecbe733916a1b0902d1f8e1a6a95e2a734 diff --git a/aux/bro-aux b/aux/bro-aux index eb24e62864..ca8db41e05 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit eb24e628648c7d7b931bdb57d38ab32c28296e72 +Subproject commit ca8db41e05e3198e4d6fccb00b1a56acbdb22d71 diff --git a/aux/broccoli b/aux/broccoli index 5bcee43070..dc596253a5 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 5bcee430700f714b19a9e794de75cb42408c9ecf +Subproject commit dc596253a5cb0dd3be34d915536c4ecb8f1db138 diff --git a/aux/broctl b/aux/broctl index d842372655..dbd2d48454 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit d84237265557779f02d65ac65aa5e122b35391b6 +Subproject commit dbd2d48454c924d5a0c0d926c5ad4d444bb2b03f diff --git a/aux/btest b/aux/btest index 3918bd9f5f..6e940b7315 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 3918bd9f5f99863faec2501e5bc7839ffb17bdc9 +Subproject commit 6e940b73152a14ae63a4405f6a4bc23cf6cbeec1 From c7fe809ee5de6aa3364e714f7554be1e2e42a071 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 20 Sep 2013 14:55:29 -0700 Subject: [PATCH 355/881] Updating submodule(s). [nomail] --- aux/bro-aux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/bro-aux b/aux/bro-aux index ca8db41e05..11d346ba99 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit ca8db41e05e3198e4d6fccb00b1a56acbdb22d71 +Subproject commit 11d346ba992b17f0106271b28da5183937819e22 From 7c1bead09a7ed673d702c9ffe17e1d140d6a6c11 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 20 Sep 2013 15:10:52 -0700 Subject: [PATCH 356/881] Updating submodule(s). [nomail] --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index dbd2d48454..5c6052bf5e 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit dbd2d48454c924d5a0c0d926c5ad4d444bb2b03f +Subproject commit 5c6052bf5e2340410fa579dbc6d531a4febf98d9 From b8504a565404ac90f21ea9ae267857ab8cf7e178 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Fri, 20 Sep 2013 15:37:37 -0700 Subject: [PATCH 357/881] Updating submodule(s). [nomail] --- aux/bro-aux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/bro-aux b/aux/bro-aux index 11d346ba99..045e25e660 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 11d346ba992b17f0106271b28da5183937819e22 +Subproject commit 045e25e660003ea61b5e4ca7d909870d08ea553f From 2049025288dfb3652e96d5bf85d2decc92778841 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 23 Sep 2013 13:16:13 -0500 Subject: [PATCH 358/881] Change submodules to fixed URL. --- .gitmodules | 16 ++++++++-------- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.gitmodules b/.gitmodules index afac9bfc6b..87826d2ef6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,24 +1,24 @@ [submodule "aux/bro-aux"] path = aux/bro-aux - url = ../bro-aux + url = git://git.bro.org/bro-aux [submodule "aux/binpac"] path = aux/binpac - url = ../binpac + url = git://git.bro.org/binpac [submodule "aux/broccoli"] path = aux/broccoli - url = ../broccoli + url = git://git.bro.org/broccoli [submodule "aux/broctl"] path = aux/broctl - url = ../broctl + url = git://git.bro.org/broctl [submodule "aux/btest"] path = aux/btest - url = ../btest + url = git://git.bro.org/btest [submodule "cmake"] path = cmake - url = ../cmake + url = git://git.bro.org/cmake [submodule "magic"] path = magic - url = ../bromagic + url = git://git.bro.org/bromagic [submodule "src/3rdparty"] path = src/3rdparty - url = ../bro-3rdparty + url = git://git.bro.org/bro-3rdparty diff --git a/aux/binpac b/aux/binpac index c066a3ecbe..5f9d4afe82 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit c066a3ecbe733916a1b0902d1f8e1a6a95e2a734 +Subproject commit 5f9d4afe8274b1c1125757ca0e971f66d6d35384 diff --git a/aux/bro-aux b/aux/bro-aux index 045e25e660..387e26609a 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 045e25e660003ea61b5e4ca7d909870d08ea553f +Subproject commit 387e26609a923f5abd10be593ae127690f7a6b72 diff --git a/aux/broccoli b/aux/broccoli index dc596253a5..baf003ac16 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit dc596253a5cb0dd3be34d915536c4ecb8f1db138 +Subproject commit baf003ac1648f63cd871942b20f8da82184af784 diff --git a/aux/broctl b/aux/broctl index 5c6052bf5e..629e155c71 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 5c6052bf5e2340410fa579dbc6d531a4febf98d9 +Subproject commit 629e155c712deea170330842ad7bfa9ae666f325 From 09b7ccba231c857681dd961d5b8f8b4a2bfb4d18 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 Sep 2013 11:48:38 -0700 Subject: [PATCH 359/881] Fix required for compiling with clang 3.3. --- src/Expr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Expr.cc b/src/Expr.cc index e64172675e..0eaa7ce918 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -2403,7 +2403,7 @@ RefExpr::RefExpr(Expr* arg_op) : UnaryExpr(EXPR_REF, arg_op) if ( IsError() ) return; - if ( ! is_assignable(op->Type()) ) + if ( ! ::is_assignable(op->Type()) ) ExprError("illegal assignment target"); else SetType(op->Type()->Ref()); From 601cdbc6cfa75fe46cbf67c4923b1988dae43ee0 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 Sep 2013 11:48:56 -0700 Subject: [PATCH 360/881] Fixing an always false condition. Reported by clang. --- src/logging/Manager.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 79e23fb63f..0de41fb642 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -792,7 +792,7 @@ bool Manager::Write(EnumVal* id, RecordVal* columns) if ( ! v ) return false; - if ( ! v->Type()->Tag() == TYPE_STRING ) + if ( v->Type()->Tag() != TYPE_STRING ) { reporter->Error("path_func did not return string"); Unref(v); From ed2798ae73f021d5af0ee925b98956766138fd2b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 Sep 2013 11:49:22 -0700 Subject: [PATCH 361/881] Updating NEWS. --- NEWS | 334 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 207 insertions(+), 127 deletions(-) diff --git a/NEWS b/NEWS index dba45c279d..e192c52380 100644 --- a/NEWS +++ b/NEWS @@ -1,53 +1,147 @@ This document summarizes the most important changes in the current Bro -release. For a complete list of changes, see the ``CHANGES`` file +release. For an exhaustive list of changes, see the ``CHANGES`` file (note that submodules, such as BroControl and Broccoli, come with -their own CHANGES.) +their own ``CHANGES``.) -Bro 2.2 (Work In Progress) -========================== +Bro 2.2 Beta +============ New Functionality ----------------- +- A new file analysis framework moves most of the processing of file + content from script-land into the core, where it belongs. See + ``doc/file-analysis.rst``, or the online documentation, for more + information. + + Much of this is an internal change, but the framework also comes + with the following user-visible functionality (some of that was + already available before but is done differently, and more + efficiently, now): + + - HTTP: + * Identify MIME type of messages. + * Extract messages to disk. + * Compute MD5 for messages. + + - SMTP: + * Identify MIME type of messages. + * Extract messages to disk. + * Compute MD5 for messages. + * Provide access to start of entity data. + + - FTP data transfers: + * Identify MIME types of data. + * Record to disk. + + - IRC DCC transfers: Record to disk. + + - Support for analyzing data transfered via HTTP range requests. + + - A binary input reader interfaces the input framework with the + file analysis, allowing to inject files on disk into Bro's + content processing. + +- A new framework for computing a wide array of summary statistics, + such as counters and thresholds checks, standard deviation and mean, + set cardinality, top K, and more. The framework operates in + real-time, independent of the underlying data, and can aggregate + information from many independent monitoring points (including + clusters). It provides a transparent, easy-to-use user interface, + and can optionally deploy a set of probabilistic data structures for + memory-efficient operation. The framework is located in + ``scripts/base/frameworks/sumstats``. + + A number of new applications now ship with Bro that are built on top + of the summary statistics framework: + + * Scan detection: Detectors for port and address scans. See + ``policy/misc/scan.bro`` (these scan detectors used to exist in + Bro versions <2.0; it's now back, but quite different). + + * Tracerouter detector: ``policy/misc/detect-traceroute.bro`` + + * Web application detection/measurement: + ``policy/misc/app-stats/*`` + + * FTP and SSH brute-forcing detector: + ``policy/protocols/ftp/detect-bruteforcing.bro``, + ``policy/protocols/ssh/detect-bruteforcing.bro`` + + * HTTP-based SQL injection detector: + ``policy/protocols/http/detect-sqli.bro`` (existed before, but + now ported to the new framework) + +- GridFTP support. This is an extension to the standard FTP analyzer + and includes: + + - An analyzer for the GSI mechanism of GSSAPI FTP AUTH method. + GSI authentication involves an encoded TLS/SSL handshake over + the FTP control session. For FTP sessions that attempt GSI + authentication, the ``service`` field of the connection log + will include ``gridftp`` (as well as also ``ftp`` and + ``ssl``). + + - An example of a GridFTP data channel detection script. It + relies on the heuristics of GridFTP data channels commonly + default to SSL mutual authentication with a NULL bulk cipher + and that they usually transfer large datasets (default + threshold of script is 1 GB). For identified GridFTP data + channels, the ``services`` fields of the connection log will + include ``gridftp-data``. + +- Modbus and DNP3 support. Script-level support is only basic at this + point but see ``src/analyzer/protocol/{modbus,dnp3}/events.bif``, or + the online documentation, for the events Bro generates. For Modbus, + there are also some example policies in + ``policy/protocols/modbus/*``. + +- The documentation now includes a new introduction to writing Bro + scripts. See ``doc/scripting/index.rst`` or, much better, the online + version. There's also the beginning of a chapter on "Using Bro" in + ``doc/using/index.rst``. + - GPRS Tunnelling Protocol (GTPv1) decapsulation. -- GridFTP support. TODO: Extend. +- The scripting language now provide "hooks", a new flavor of + functions that share characteristics of both standard functions and + events. They are like events in that multiple bodies can be defined + for the same hook identifier. They are more like functions in the + way they are invoked/called, because, unlike events, their execution + is immediate and they do not get scheduled through an event queue. + Also, a unique feature of a hook is that a given hook handler body + can short-circuit the execution of remaining hook handlers simply by + exiting from the body as a result of a ``break`` statement (as + opposed to a ``return`` or just reaching the end of the body). See + ``doc/scripts/builtins.rst``, or the online documentation, for more + informatin. -- Modbus support. TODO: Extend. +- Bro's language now has a working ``switch`` statement that generally + behaves like C-style switches (except that case labels can be + comprised of multiple literal constants delimited by commas). Only + atomic types are allowed for now. Case label bodies that don't + execute a ``return`` or ``break`` statement will fall through to + subsequent cases. A ``default`` case label is supported. -- DNP3 support. TODO: Extend. - -- ssl.log now also records the subject client and issuer certificates. - -- Hooks: TODO: Briefly summarize the documention from - doc/scripts/builtins.rst here. - -- The ASCII writer can now output CSV files on a per filter basis. - -- Bro's language now has a working "switch" statement that generally - behaves like C-style switches except case labels can be comprised of - multiple literal constants delimited by commas. Only atomic types - are allowed for now. Case label bodies that don't execute a - "return" or "break" statement will fall through to subsequent cases. - A default case label is allowed. - -- Bro's language now has a new set of types "opaque of X". Opaque +- Bro's language now has a new set of types ``opaque of X``. Opaque values can be passed around like other values but they can only be manipulated with BiF functions, not with other operators. Currently, - the following opaque types are supported: + the following opaque types are supported:: - - opaque of md5 - - opaque of sha1 - - opaque of sha256 - - opaquey of entropy. + opaque of md5 + opaque of sha1 + opaque of sha256 + opaque of cardinality + opaque of topk + opaque of bloomfilter - They go along with the corrsponding BiF functions md5_*, sha1_*, - sha256_*, and entropy_*, respectively. Note that these functions - have changed their signatures to work with opaques types rather - than global state as it was before. + These go along with the corrsponding BiF functions ``md5_*``, + ``sha1_*``, ``sha256_*``, ``entropy_*``, etc. . Note that where + these functions existed before, they have changed their signatures + to work with opaques types rather than global state. -- The scripting language now supports a constructing sets, tables, +- The scripting language now supports constructing sets, tables, vectors, and records by name:: type MyRecordType: record { @@ -61,57 +155,33 @@ New Functionality global s = MySet([$c=1], [$c=2]); - Strings now support the subscript operator to extract individual - characters and substrings (e.g., s[4], s[1,5]). The index expression - can take up to two indices for the start and end index of the - substring to return (e.g. "mystring[1,3]"). + characters and substrings (e.g., ``s[4]``, ``s[1,5]``). The index + expression can take up to two indices for the start and end index of + the substring to return (e.g. ``mystring[1,3]``). -- Functions now support default parameters, e.g.: +- Functions now support default parameters, e.g.:: - global foo: function(s: string, t: string &default="abc", u: count &default=0); + global foo: function(s: string, t: string &default="abc", u: count &default=0); -- Scripts can now use two new "magic constants" @DIR and @FILENAME - that expand to the directory path of the current script and just the - script file name without path, respectively. (Jon Siwek) +- Scripts can now use two new "magic constants" ``@DIR`` and + ``@FILENAME`` that expand to the directory path of the current + script and just the script file name without path, respectively. -- The new file analysis framework moves most of the processing of file - content from script-land into the core, where it belongs. See - doc/file-analysis.rst for more information. +- ``ssl.log`` now also records the subject client and issuer + certificates. - Much of this is an internal change, but the framework also comes - with the following user-visibible functionality (some of that was - already available before, but done differently): +- The ASCII writer can now output CSV files on a per filter basis. - [TODO: Update with changes from 984e9793db56.] +- New SQLite reader and writer plugins for the logging framework allow + to read/write persistent data from on disk SQLite databases. - - A binary input reader interfaces the input framework with file - analysis, allowing to inject files on disk into Bro's - processing. - - - Supports for analyzing data transfereed via HTTP range - requests. - - - HTTP: - * Identify MIME type of message. - * Extract message to disk. - * Compute MD5 for messages. - - - SMTP: - * Identify MIME type of message. - * Extract message to disk. - * Compute MD5 for messages. - * Provide access to start of entity data. - - - FTP data transfers: Identify MIME type; record to disk. - - - IRC DCC transfers: Record to disk. - -- New packet filter framework supports BPF-based load-balancing, +- A new packet filter framework supports BPF-based load-balancing, shunting, and sampling; plus plugin support to customize filters dynamically. - Bro now provides Bloom filters of two kinds: basic Bloom filters supporting membership tests, and counting Bloom filters that track - the frequency of elements. The corresponding functions are: + the frequency of elements. The corresponding functions are:: bloomfilter_basic_init(fp: double, capacity: count, name: string &default=""): opaque of bloomfilter bloomfilter_basic_init2(k: count, cells: count, name: string &default=""): opaque of bloomfilter @@ -121,10 +191,11 @@ New Functionality bloomfilter_merge(bf1: opaque of bloomfilter, bf2: opaque of bloomfilter): opaque of bloomfilter bloomfilter_clear(bf: opaque of bloomfilter) - See for full documentation. + See ``src/probabilistic/bloom-filter.bif``, or the online + documentation, for full documentation. - Bro now provides a probabilistic data structure for computing - "top k" elements. The corresponding functions are: + "top k" elements. The corresponding functions are:: topk_init(size: count): opaque of topk topk_add(handle: opaque of topk, value: any) @@ -136,73 +207,82 @@ New Functionality topk_merge(handle1: opaque of topk, handle2: opaque of topk) topk_merge_prune(handle1: opaque of topk, handle2: opaque of topk) - See for full documentation. + See ``src/probabilistic/top-k.bif``, or the online documentation, + for full documentation. -- base/utils/exec.bro provides a module to start external processes - asynchronously and retrieve their output on termination. - base/utils/dir.bro uses it to monitor a directory for changes, and - base/utils/active-http.bro for providing an interface for querying - remote web servers. +- Bro now provides a probabilistic data structure for computing set + cardinality, using the HyperLogLog algorithm. The corresponding + functions are:: -- Summary statistics framework. [Extend] + hll_cardinality_init(err: double, confidence: double): opaque of cardinality + hll_cardinality_add(handle: opaque of cardinality, elem: any): bool + hll_cardinality_merge_into(handle1: opaque of cardinality, handle2: opaque of cardinality): bool + hll_cardinality_estimate(handle: opaque of cardinality): double + hll_cardinality_copy(handle: opaque of cardinality): opaque of cardinality -- A number of new applications build on top of the summary statistics - framework: + See ``src/probabilistic/cardinality-counter.bif``, or the online + documentation, for full documentation. - * Scan detection: Detectors for port and address scans return. See - policy/misc/scan.bro. +- ``base/utils/exec.bro`` provides a module to start external + processes asynchronously and retrieve their output on termination. + ``base/utils/dir.bro`` uses it to monitor a directory for changes, + and ``base/utils/active-http.bro`` for providing an interface for + querying remote web servers. - * Tracerouter detector: policy/misc/detect-traceroute +- BroControl can now pin Bro processes to CPUs on supported platforms: + To use CPU pinning, a new per-node option ``pin_cpus`` can be + specified in node.cfg if the OS is either Linux or FreeBSD. - * Web application detection/measurement: policy/misc/app-metrics.bro +- BroControl comes with its own test-suite now. ``make test`` in + ``aux/broctl`` will run it. - * FTP brute-forcing detector: policy/protocols/ftp/detect-bruteforcing.bro - - * HTTP-based SQL injection detector: policy/protocols/http/detect-sqli.bro - (existed before, but now ported to the new framework) - - * SSH brute-forcing detector feeding the intelligence framework: - policy/protocols/ssh/detect-bruteforcing.bro +In addition to these, Bro 2.2 comes with a large set of smaller +extensions, tweaks, and fixes across the whole code base, including +most submodules. Changed Functionality --------------------- -- We removed the following, already deprecated, functionality: +- The interface to extracting content from application-layer protocols + (including HTTP, SMTP, FTP) has changed significantly due to the + introduction of the new file analysis framework (see above). + +- Removed the following, already deprecated, functionality: * Scripting language: - - &disable_print_hook attribute. + - ``&disable_print_hook attribute``. * BiF functions: - - parse_dotted_addr(), dump_config(), - make_connection_persistent(), generate_idmef(), - split_complete() + - ``parse_dotted_addr()``, ``dump_config()``, + ``make_connection_persistent()``, ``generate_idmef()``, + ``split_complete()`` - - md5_*, sha1_*, sha256_*, and entropy_* have all changed - their signatures to work with opaque types (see above). + - ``md5_*``, ``sha1_*``, ``sha256_*``, and ``entropy_*`` have + all changed their signatures to work with opaque types (see + above). +- Removed a now unused argument from ``do_split`` helper function. -- Removed a now unused argument from "do_split" helper function. +- ``this`` is no longer a reserved keyword. -- "this" is no longer a reserved keyword. - -- The Input Framework's update_finished event has been renamed to - end_of_data. It will now not only fire after table-reads have been - completed, but also after the last event of a whole-file-read (or - whole-db-read, etc.). +- The Input Framework's ``update_finished`` event has been renamed to + ``end_of_data``. It will now not only fire after table-reads have + been completed, but also after the last event of a whole-file-read + (or whole-db-read, etc.). - Renamed the option defining the frequency of alarm summary mails to - 'Logging::default_alarm_mail_interval'. When using BroControl, the + ``Logging::default_alarm_mail_interval``. When using BroControl, the value can now be set with the new broctl.cfg option - "MailAlarmsInterval". + ``MailAlarmsInterval``. -- We have completely reworded the "notice_policy" mechanism. It now no - linger uses a record of policy items but a "hook", a new language - element that's roughly equivalent to a function with multiple - bodies. The documentation [TODO: insert link] describes how to use - the new notice policy. For existing code, the two main changes are: +- We have completely rewritten the ``notice_policy`` mechanism. It now + no longer uses a record of policy items but a ``hook``, a new + language element that's roughly equivalent to a function with + multiple bodies (see above). For existing code, the two main changes + are: - - What used to be a "redef" of "Notice::policy" now becomes a hook - implementation. Example: + - What used to be a ``redef`` of ``Notice::policy`` now becomes a + hook implementation. Example: Old:: @@ -221,9 +301,9 @@ Changed Functionality add n$actions[Notice::ACTION_EMAIL]; } - - notice() is now likewise a hook, no longer an event. If you have - handlers for that event, you'll likely just need to change the - type accordingly. Example: + - notice() is now likewise a hook, no longer an event. If you + have handlers for that event, you'll likely just need to change + the type accordingly. Example: Old:: @@ -233,17 +313,17 @@ Changed Functionality hook notice(n: Notice::Info) { ... } -- The notice_policy.log is gone. That's a result of the new notice +- The ``notice_policy.log`` is gone. That's a result of the new notice policy setup. -- Removed the byte_len() and length() bif functions. Use the ``|...|`` - operator instead. +- Removed the ``byte_len()`` and ``length()`` bif functions. Use the + ``|...|`` operator instead. -- The SSH::Login notice has been superseded by an corresponding - intelligence framework observation (SSH::SUCCESSFUL_LOGIN). +- The ``SSH::Login`` notice has been superseded by an corresponding + intelligence framework observation (``SSH::SUCCESSFUL_LOGIN``). -- PacketFilter::all_packets has been replaced with - PacketFilter::enable_auto_protocol_capture_filters. +- ``PacketFilter::all_packets`` has been replaced with + ``PacketFilter::enable_auto_protocol_capture_filters``. - We removed the BitTorrent DPD signatures pending further updates to that analyzer. From 00a3ad03dd73ac3058be16a56c1f8a8368ecc4f0 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 Sep 2013 11:54:48 -0700 Subject: [PATCH 362/881] Updating submodule(s). [nomail] --- CHANGES | 10 ++++++++++ VERSION | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 9ff7b2368c..00cd9b9176 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,14 @@ +2.1-1387 | 2013-09-23 11:54:48 -0700 + + * Change submodules to fixed URL. (Jon Siwek) + + * Updating NEWS. (Robin Sommer) + + * Fixing an always false condition. (Robin Sommer) + + * Fix required for compiling with clang 3.3. (Robin Sommer) + 2.1-1377 | 2013-09-20 14:38:15 -0700 * Updates to the scripting introduction. (Scott Runnels) diff --git a/VERSION b/VERSION index 326b107a34..deed660f20 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-1377 +2.1-1387 diff --git a/aux/broccoli b/aux/broccoli index baf003ac16..2a886a31f2 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit baf003ac1648f63cd871942b20f8da82184af784 +Subproject commit 2a886a31f23ebecd17274af1af581f9e40f1810d diff --git a/aux/broctl b/aux/broctl index 629e155c71..f80ddc95cd 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 629e155c712deea170330842ad7bfa9ae666f325 +Subproject commit f80ddc95cdfae6c6a4f20169de60767271b240e1 From 6e71c97bfe09d3b3c19cc0b137ecc784da4f7eeb Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 23 Sep 2013 14:44:50 -0500 Subject: [PATCH 363/881] Update 'make dist' target. --- Makefile | 13 +++++++------ aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index d915050b6b..cbc44c6780 100644 --- a/Makefile +++ b/Makefile @@ -44,13 +44,14 @@ broxygenclean: configured dist: @rm -rf $(VERSION_FULL) $(VERSION_FULL).tgz @rm -rf $(VERSION_MIN) $(VERSION_MIN).tgz - @mkdir $(VERSION_FULL) - @tar --exclude=$(VERSION_FULL)* --exclude=$(VERSION_MIN)* --exclude=.git -cf - . | ( cd $(VERSION_FULL) && tar -xpf - ) - @( cd $(VERSION_FULL) && cp -R ../.git . && git reset -q --hard HEAD && git clean -xdfq && rm -rf .git ) + @git clone --recursive . $(VERSION_FULL) >/dev/null 2>&1 + @find $(VERSION_FULL) -name .git\* | xargs rm -rf @tar -czf $(VERSION_FULL).tgz $(VERSION_FULL) && echo Package: $(VERSION_FULL).tgz && rm -rf $(VERSION_FULL) - @$(HAVE_MODULES) && mkdir $(VERSION_MIN) || exit 0 - @$(HAVE_MODULES) && tar --exclude=$(VERSION_FULL)* --exclude=$(VERSION_MIN)* --exclude=.git `git submodule | awk '{print "--exclude="$$2}' | grep -v cmake | tr '\n' ' '` -cf - . | ( cd $(VERSION_MIN) && tar -xpf - ) || exit 0 - @$(HAVE_MODULES) && ( cd $(VERSION_MIN) && cp -R ../.git . && git reset -q --hard HEAD && git clean -xdfq && rm -rf .git ) || exit 0 + @$(HAVE_MODULES) && git clone . $(VERSION_MIN) >/dev/null 2>&1 || exit 0 + @$(HAVE_MODULES) && (cd $(VERSION_MIN) && git submodule update --init cmake >/dev/null 2>&1) || exit 0 + @$(HAVE_MODULES) && (cd $(VERSION_MIN) && git submodule update --init src/3rdparty >/dev/null 2>&1) || exit 0 + @$(HAVE_MODULES) && (cd $(VERSION_MIN) && git submodule update --init magic >/dev/null 2>&1) || exit 0 + @$(HAVE_MODULES) && find $(VERSION_MIN) -name .git\* | xargs rm -rf || exit 0 @$(HAVE_MODULES) && tar -czf $(VERSION_MIN).tgz $(VERSION_MIN) && echo Package: $(VERSION_MIN).tgz && rm -rf $(VERSION_MIN) || exit 0 bindist: diff --git a/aux/binpac b/aux/binpac index 5f9d4afe82..3c29b917e5 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 5f9d4afe8274b1c1125757ca0e971f66d6d35384 +Subproject commit 3c29b917e59e8d8200f669d3d9729d36c34b9245 diff --git a/aux/bro-aux b/aux/bro-aux index 387e26609a..ee2d64928e 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 387e26609a923f5abd10be593ae127690f7a6b72 +Subproject commit ee2d64928edc38b10e508bd577a22f52b024c992 diff --git a/aux/broccoli b/aux/broccoli index 2a886a31f2..c0d5345bf2 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 2a886a31f23ebecd17274af1af581f9e40f1810d +Subproject commit c0d5345bf25d25f6965f3201048344687bacc860 diff --git a/aux/broctl b/aux/broctl index f80ddc95cd..3582f494de 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit f80ddc95cdfae6c6a4f20169de60767271b240e1 +Subproject commit 3582f494de247784fc7634b319ddf99aef44b6e1 From e4e7c78925e8c3a049f16875fdc33faf4312ec5d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 23 Sep 2013 16:57:31 -0500 Subject: [PATCH 364/881] Remove unused variable assignments, dead code. --- src/CompHash.cc | 1 - src/Debug.cc | 3 +-- src/PersistenceSerializer.cc | 2 -- src/Stmt.cc | 3 +-- src/Val.cc | 6 ++---- 5 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/CompHash.cc b/src/CompHash.cc index e793a104e0..b2eb08c589 100644 --- a/src/CompHash.cc +++ b/src/CompHash.cc @@ -207,7 +207,6 @@ char* CompositeHash::SingleValHash(int type_check, char* kp0, unsigned int* kp = AlignAndPadType(kp0); VectorVal* vv = v->AsVectorVal(); VectorType* vt = v->Type()->AsVectorType(); - vector* indices = v->AsVector(); *kp = vv->Size(); kp1 = reinterpret_cast(kp+1); for ( unsigned int i = 0; i < vv->Size(); ++i ) diff --git a/src/Debug.cc b/src/Debug.cc index 8cf2e38596..b5aaf91f9f 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -194,8 +194,7 @@ static void parse_function_name(vector& result, return; } - FuncType* ftype; - if ( ! (ftype = id->Type()->AsFuncType()) ) + if ( ! id->Type()->AsFuncType() ) { debug_msg("Function %s not declared.\n", id->Name()); plr.type = plrUnknown; diff --git a/src/PersistenceSerializer.cc b/src/PersistenceSerializer.cc index d9baad05bb..4c6f72d815 100644 --- a/src/PersistenceSerializer.cc +++ b/src/PersistenceSerializer.cc @@ -400,8 +400,6 @@ bool PersistenceSerializer::RunSerialization(SerialStatus* status) while ( (id = status->ids->NextEntry(status->id_cookie)) ) { - ID* g = global_scope()->Lookup(id->Name()); - if ( ! DoIDSerialization(status, id) ) return false; diff --git a/src/Stmt.cc b/src/Stmt.cc index 28f29aba0b..d879c598d2 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -1218,9 +1218,8 @@ Val* ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const const PDict(TableEntryVal)* loop_vals = tv->AsTable(); HashKey* k; - TableEntryVal* iter_val; IterCookie* c = loop_vals->InitForIteration(); - while ( (iter_val = loop_vals->NextEntry(k, c)) ) + while ( loop_vals->NextEntry(k, c) ) { ListVal* ind_lv = tv->RecoverIndex(k); delete k; diff --git a/src/Val.cc b/src/Val.cc index 9d1b27b333..30c3797253 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1656,8 +1656,7 @@ int TableVal::RemoveFrom(Val* val) const IterCookie* c = tbl->InitForIteration(); HashKey* k; - TableEntryVal* v; - while ( (v = tbl->NextEntry(k, c)) ) + while ( tbl->NextEntry(k, c) ) { Val* index = RecoverIndex(k); @@ -1955,8 +1954,7 @@ ListVal* TableVal::ConvertToList(TypeTag t) const IterCookie* c = tbl->InitForIteration(); HashKey* k; - TableEntryVal* v; - while ( (v = tbl->NextEntry(k, c)) ) + while ( tbl->NextEntry(k, c) ) { ListVal* index = table_hash->RecoverVals(k); From f89b62684f4b02e5e83dc279edc8aabeab4ec55f Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 Sep 2013 20:18:14 -0700 Subject: [PATCH 365/881] Updating submodule(s). [nomail] --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index 3582f494de..9eb0ab28f8 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 3582f494de247784fc7634b319ddf99aef44b6e1 +Subproject commit 9eb0ab28f85f0de2ed4c85017160d9d1d0a64f3f From abba39c261eb2a94de8584f17c4f3af6e7178734 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 Sep 2013 20:31:28 -0700 Subject: [PATCH 366/881] Updating submodule(s). [nomail] --- CHANGES | 4 ++++ VERSION | 2 +- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- aux/btest | 2 +- 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 00cd9b9176..b5c1c83937 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +2.2-beta | 2013-09-23 20:31:28 -0700 + + * Update 'make dist' target. (Jon Siwek) + 2.1-1387 | 2013-09-23 11:54:48 -0700 * Change submodules to fixed URL. (Jon Siwek) diff --git a/VERSION b/VERSION index deed660f20..bd5bc6105b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-1387 +2.2-beta diff --git a/aux/binpac b/aux/binpac index 3c29b917e5..8156c9eb58 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 3c29b917e59e8d8200f669d3d9729d36c34b9245 +Subproject commit 8156c9eb581324de90b6f0e6a00bf5c79c56651c diff --git a/aux/bro-aux b/aux/bro-aux index ee2d64928e..044f83b8bb 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit ee2d64928edc38b10e508bd577a22f52b024c992 +Subproject commit 044f83b8bb933eeaa8c47cac0579f25bcd18e096 diff --git a/aux/broccoli b/aux/broccoli index c0d5345bf2..261dd2365d 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit c0d5345bf25d25f6965f3201048344687bacc860 +Subproject commit 261dd2365d4877106940f70070de4f4a914b2b0b diff --git a/aux/broctl b/aux/broctl index 9eb0ab28f8..c7210af732 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 9eb0ab28f85f0de2ed4c85017160d9d1d0a64f3f +Subproject commit c7210af732fff03a18737de12db9a5ec9101124e diff --git a/aux/btest b/aux/btest index 6e940b7315..d01422b9c8 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 6e940b73152a14ae63a4405f6a4bc23cf6cbeec1 +Subproject commit d01422b9c8022ce787b157eb59580f5be169d060 From a5a6e35d5ebc9c4b86d3cba4eb2811903bd1bf41 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 23 Sep 2013 20:57:48 -0700 Subject: [PATCH 367/881] Updating submodule(s). [nomail] --- CHANGES | 2 +- aux/binpac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index b5c1c83937..61ec42c3e4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ -2.2-beta | 2013-09-23 20:31:28 -0700 +2.2-beta | 2013-09-23 20:57:48 -0700 * Update 'make dist' target. (Jon Siwek) diff --git a/aux/binpac b/aux/binpac index 8156c9eb58..d5d8ce30c5 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 8156c9eb581324de90b6f0e6a00bf5c79c56651c +Subproject commit d5d8ce30c596acb1408618e1f88dec59c1c96bab From 66a6ec490ab62398b113c55efb56e25587b3bba5 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 24 Sep 2013 13:16:51 -0700 Subject: [PATCH 368/881] Removing :doc: roles so that we can render this with docutils directly. --- NEWS | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index e192c52380..41b29358ba 100644 --- a/NEWS +++ b/NEWS @@ -559,8 +559,8 @@ with the new version. The two rules of thumb are: if you need help. Below we summarize changes from 1.x to 2.x in more detail. This list -isn't complete, see the ``CHANGES`` file in the distribution or -:doc:`here ` for the full story. +isn't complete, see the ``CHANGES`` file in the distribution. +for the full story. Script Organization ------------------- @@ -648,8 +648,7 @@ Logging Framework endpoint. - The new logging framework makes it possible to extend, customize, - and filter logs very easily. See the :doc:`logging framework - ` for more information on usage. + and filter logs very easily. - A common pattern found in the new scripts is to store logging stream records for protocols inside the ``connection`` records so that @@ -672,8 +671,7 @@ Notice Framework The way users interact with "notices" has changed significantly in order to make it easier to define a site policy and more extensible for adding -customized actions. See the :doc:`notice framework -`. +customized actions. New Default Settings From 5408931870365b2a68f9484125b373fab3cdd32b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 24 Sep 2013 13:17:34 -0700 Subject: [PATCH 369/881] Whitespace fix. --- doc/scripting/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 9f98c43a5f..4181704d63 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -1129,7 +1129,7 @@ which we will cover shortly. +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | policy_items | set[count] | &log &optional | Policy items that have been applied | +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ -| email_body_sections | vector | &optional | Body of the email for email notices. | +| email_body_sections | vector | &optional | Body of the email for email notices. | +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ | email_delay_tokens | set[string] | &optional | Delay functionality for email notices. | +---------------------+------------------------------------------------------------------+----------------+----------------------------------------+ From 7706ba1b2f2766e29d8a52e4b7e6c4e9c11e0981 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 24 Sep 2013 13:22:56 -0700 Subject: [PATCH 370/881] Fix for setting REPO in Makefile. The basename wasn't sufficient as it could leave the repo URL in. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cbc44c6780..4984f6db31 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # BUILD=build -REPO=`basename \`git config --get remote.origin.url\`` +REPO=`basename \`git config --get remote.origin.url | sed 's/^[^:]*://g'\`` VERSION_FULL=$(REPO)-`cat VERSION` VERSION_MIN=$(REPO)-`cat VERSION`-minimal HAVE_MODULES=git submodule | grep -v cmake >/dev/null From bb4b26281374ba3051b22293d22145907a0653c4 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 24 Sep 2013 13:23:30 -0700 Subject: [PATCH 371/881] Updating submodule(s). [nomail] --- CHANGES | 9 +++++++++ VERSION | 2 +- aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 61ec42c3e4..3ee13d6b94 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,13 @@ +2.2-beta-4 | 2013-09-24 13:23:30 -0700 + + * Fix for setting REPO in Makefile. (Robin Sommer) + + * Whitespace fix. (Robin Sommer) + + * Removing :doc: roles so that we can render this with docutils + directly. (Robin Sommer) + 2.2-beta | 2013-09-23 20:57:48 -0700 * Update 'make dist' target. (Jon Siwek) diff --git a/VERSION b/VERSION index bd5bc6105b..24fbd69410 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2-beta +2.2-beta-4 diff --git a/aux/binpac b/aux/binpac index d5d8ce30c5..d4331881f9 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit d5d8ce30c596acb1408618e1f88dec59c1c96bab +Subproject commit d4331881f91068da9a7a7d6639559ce752e178ad diff --git a/aux/bro-aux b/aux/bro-aux index 044f83b8bb..c09d0d81a1 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 044f83b8bb933eeaa8c47cac0579f25bcd18e096 +Subproject commit c09d0d81a15f69d22274d472ba9345e5e691caa2 diff --git a/aux/broccoli b/aux/broccoli index 261dd2365d..e0f34599cb 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 261dd2365d4877106940f70070de4f4a914b2b0b +Subproject commit e0f34599cb11f0df37ae1cc036d87c1794b1c0b2 diff --git a/aux/broctl b/aux/broctl index c7210af732..bec9c66064 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit c7210af732fff03a18737de12db9a5ec9101124e +Subproject commit bec9c6606414438655a3298db76e1e43464c8d44 From 4ec641990614ba5e8b979c26c4b2d14dc6121685 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 24 Sep 2013 13:41:33 -0700 Subject: [PATCH 372/881] Updating submodule(s). [nomail] --- aux/bro-aux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/bro-aux b/aux/bro-aux index c09d0d81a1..de33d520c6 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit c09d0d81a15f69d22274d472ba9345e5e691caa2 +Subproject commit de33d520c6f7957aafcce30d86b170306a1c0c49 From daf5d0d098a589dcdc593c21f91fa8c3592710ef Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 24 Sep 2013 17:38:22 -0500 Subject: [PATCH 373/881] Improve return value checking and error handling. --- src/Expr.cc | 2 +- src/Obj.cc | 13 ++++++++----- src/PolicyFile.cc | 8 +++++++- src/SerialObj.h | 9 +++++++-- src/Serializer.cc | 7 ++++++- src/Type.cc | 3 ++- src/Val.cc | 19 +++++++++++++++---- src/input/readers/Raw.cc | 25 ++++++++++++++++++++++--- src/input/readers/Raw.h | 1 + src/logging/WriterBackend.h | 11 ----------- src/logging/writers/Ascii.cc | 11 ++++++++++- src/logging/writers/DataSeries.cc | 11 ++++++++++- src/main.cc | 5 ++++- src/util.cc | 9 ++++++++- 14 files changed, 101 insertions(+), 33 deletions(-) diff --git a/src/Expr.cc b/src/Expr.cc index e78a7145e6..e49150f3ac 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -5435,7 +5435,7 @@ TraversalCode ListExpr::Traverse(TraversalCallback* cb) const loop_over_list(exprs, i) { - exprs[i]->Traverse(cb); + tc = exprs[i]->Traverse(cb); HANDLE_TC_EXPR_PRE(tc); } diff --git a/src/Obj.cc b/src/Obj.cc index 0b82695f3d..33aaa8f44e 100644 --- a/src/Obj.cc +++ b/src/Obj.cc @@ -28,11 +28,14 @@ bool Location::DoSerialize(SerialInfo* info) const { DO_SERIALIZE(SER_LOCATION, SerialObj); info->s->WriteOpenTag("Location"); - SERIALIZE(filename); - SERIALIZE(first_line); - SERIALIZE(last_line); - SERIALIZE(first_column); - SERIALIZE(last_column); + + if ( ! (SERIALIZE(filename) && + SERIALIZE(first_line) && + SERIALIZE(last_line) && + SERIALIZE(first_column) && + SERIALIZE(last_column)) ) + return false; + info->s->WriteCloseTag("Location"); return true; } diff --git a/src/PolicyFile.cc b/src/PolicyFile.cc index 9f67ee88a1..369d8c18f4 100644 --- a/src/PolicyFile.cc +++ b/src/PolicyFile.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -80,7 +81,12 @@ bool LoadPolicyFileText(const char* policy_filename) policy_files.insert(PolicyFileMap::value_type(policy_filename, pf)); struct stat st; - fstat(fileno(f), &st); + if ( fstat(fileno(f), &st) != 0 ) + { + char buf[256]; + strerror_r(errno, buf, sizeof(buf)); + reporter->InternalError("fstat failed on %s: %s", policy_filename, buf); + } pf->lmtime = st.st_mtime; off_t size = st.st_size; diff --git a/src/SerialObj.h b/src/SerialObj.h index c3dc65684c..4794f2bf20 100644 --- a/src/SerialObj.h +++ b/src/SerialObj.h @@ -319,7 +319,8 @@ public: \ if ( has_it ) \ { \ - info->s->Read(&dst, 0, "has_" #dst); \ + if ( ! info->s->Read(&dst, 0, "has_" #dst) ) \ + return false; \ if ( ! dst ) \ return false; \ } \ @@ -339,7 +340,11 @@ public: \ if ( has_it ) \ { \ - info->s->Read(&dst, 0, "has_" #dst); \ + if ( ! info->s->Read(&dst, 0, "has_" #dst) ) \ + { \ + delete del; \ + return 0; \ + } \ if ( ! dst ) \ { \ delete del; \ diff --git a/src/Serializer.cc b/src/Serializer.cc index f7544765fa..bd1be77a2d 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -136,7 +136,12 @@ bool Serializer::Serialize(SerialInfo* info, const char* func, val_list* args) Write(network_time, "time"); Write(a, "len"); - loop_over_list(*args, i) (*args)[i]->Serialize(info); + loop_over_list(*args, i) + if ( ! (*args)[i]->Serialize(info) ) + { + Error("failed"); + return false; + } WriteCloseTag("call"); WriteSeparator(); diff --git a/src/Type.cc b/src/Type.cc index 2b9faa8018..706a15aea2 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -179,7 +179,8 @@ unsigned int BroType::MemoryAllocation() const bool BroType::Serialize(SerialInfo* info) const { // We always send full types (see below). - SERIALIZE(true); + if ( ! SERIALIZE(true) ) + return false; bool ret = SerialObj::Serialize(info); return ret; diff --git a/src/Val.cc b/src/Val.cc index 30c3797253..ffe98ab7bc 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -81,7 +81,9 @@ Val* Val::Clone() const SerialInfo sinfo(&ss); sinfo.cache = false; - this->Serialize(&sinfo); + if ( ! this->Serialize(&sinfo) ) + return 0; + char* data; uint32 len = form->EndWrite(&data); form->StartRead(data, len); @@ -2326,7 +2328,7 @@ bool TableVal::DoSerialize(SerialInfo* info) const else reporter->InternalError("unknown continuation state"); - HashKey* k; + HashKey* k = 0; int count = 0; assert((!info->cont.ChildSuspended()) || state->v); @@ -2339,12 +2341,21 @@ bool TableVal::DoSerialize(SerialInfo* info) const if ( ! state->c ) { // No next one. - SERIALIZE(false); + if ( ! SERIALIZE(false) ) + { + delete k; + return false; + } + break; } // There's a value coming. - SERIALIZE(true); + if ( ! SERIALIZE(true) ) + { + delete k; + return false; + } if ( state->v->Value() ) state->v->Ref(); diff --git a/src/input/readers/Raw.cc b/src/input/readers/Raw.cc index 7b3f0595b5..70c24eed76 100644 --- a/src/input/readers/Raw.cc +++ b/src/input/readers/Raw.cc @@ -95,6 +95,18 @@ void Raw::ClosePipeEnd(int i) pipes[i] = -1; } +bool Raw::SetFDFlags(int fd, int cmd, int flags) + { + if ( fcntl(fd, cmd, flags) != -1 ) + return true; + + char buf[256]; + strerror_r(errno, buf, sizeof(buf)); + Error(Fmt("failed to set fd flags: %s", buf)); + return false; + } + + bool Raw::LockForkMutex() { int res = pthread_mutex_lock(&fork_mutex); @@ -200,11 +212,13 @@ bool Raw::Execute() ClosePipeEnd(stdout_out); if ( Info().mode == MODE_STREAM ) - fcntl(pipes[stdout_in], F_SETFL, O_NONBLOCK); + if ( ! SetFDFlags(pipes[stdout_in], F_SETFL, O_NONBLOCK) ) + return false; ClosePipeEnd(stdin_in); if ( stdin_towrite ) + { // Ya, just always set this to nonblocking. we do not // want to block on a program receiving data. Note // that there is a small gotcha with it. More data is @@ -213,14 +227,19 @@ bool Raw::Execute() // mode_manual where the first write cannot write // everything, the rest will be stuck in a queue that // is never emptied. - fcntl(pipes[stdin_out], F_SETFL, O_NONBLOCK); + if ( ! SetFDFlags(pipes[stdin_out], F_SETFL, O_NONBLOCK) ) + return false; + } else ClosePipeEnd(stdin_out); ClosePipeEnd(stderr_out); if ( use_stderr ) - fcntl(pipes[stderr_in], F_SETFL, O_NONBLOCK); // true for this too. + { + if ( ! SetFDFlags(pipes[stderr_in], F_SETFL, O_NONBLOCK) ) + return false; + } else ClosePipeEnd(stderr_in); diff --git a/src/input/readers/Raw.h b/src/input/readers/Raw.h index ae6f72524d..c549125174 100644 --- a/src/input/readers/Raw.h +++ b/src/input/readers/Raw.h @@ -31,6 +31,7 @@ protected: private: void ClosePipeEnd(int i); + bool SetFDFlags(int fd, int cmd, int flags); bool LockForkMutex(); bool UnlockForkMutex(); diff --git a/src/logging/WriterBackend.h b/src/logging/WriterBackend.h index b326366b72..f5c74e582c 100644 --- a/src/logging/WriterBackend.h +++ b/src/logging/WriterBackend.h @@ -242,17 +242,6 @@ public: * Note: Exactly one of the two FinishedRotation() methods must be * called by a writer's implementation of DoRotate() once rotation * has finished. - * - * @param new_name The filename of the rotated file. - * - * @param old_name The filename of the original file. - * - * @param open: The timestamp when the original file was opened. - * - * @param close: The timestamp when the origina file was closed. - * - * @param terminating: True if the original rotation request occured - * due to the main Bro process shutting down. */ bool FinishedRotation(); diff --git a/src/logging/writers/Ascii.cc b/src/logging/writers/Ascii.cc index ddb63db36f..1a9cc5c4cd 100644 --- a/src/logging/writers/Ascii.cc +++ b/src/logging/writers/Ascii.cc @@ -261,7 +261,16 @@ bool Ascii::DoRotate(const char* rotated_path, double open, double close, bool t CloseFile(close); string nname = string(rotated_path) + "." + LogExt(); - rename(fname.c_str(), nname.c_str()); + + if ( rename(fname.c_str(), nname.c_str()) != 0 ) + { + char buf[256]; + strerror_r(errno, buf, sizeof(buf)); + Error(Fmt("failed to rename %s to %s: %s", fname.c_str(), + nname.c_str(), buf)); + FinishedRotation(); + return false; + } if ( ! FinishedRotation(nname.c_str(), fname.c_str(), open, close, terminating) ) { diff --git a/src/logging/writers/DataSeries.cc b/src/logging/writers/DataSeries.cc index bc15c6f5b9..087a7061ea 100644 --- a/src/logging/writers/DataSeries.cc +++ b/src/logging/writers/DataSeries.cc @@ -423,7 +423,16 @@ bool DataSeries::DoRotate(const char* rotated_path, double open, double close, b string dsname = string(Info().path) + ".ds"; string nname = string(rotated_path) + ".ds"; - rename(dsname.c_str(), nname.c_str()); + + if ( rename(dsname.c_str(), nname.c_str()) != 0 ) + { + char buf[256]; + strerror_r(errno, buf, sizeof(buf)); + Error(Fmt("failed to rename %s to %s: %s", dsname.c_str(), + nname.c_str(), buf)); + FinishedRotation(); + return false; + } if ( ! FinishedRotation(nname.c_str(), dsname.c_str(), open, close, terminating) ) { diff --git a/src/main.cc b/src/main.cc index 313e1a40b0..0f60a4c70f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -782,7 +782,10 @@ int main(int argc, char** argv) bro_init_magic(&magic_desc_cookie, MAGIC_NONE); bro_init_magic(&magic_mime_cookie, MAGIC_MIME); - sqlite3_initialize(); + int r = sqlite3_initialize(); + + if ( r != SQLITE_OK ) + reporter->Error("Failed to initialize sqlite3: %s", sqlite3_errstr(r)); // FIXME: On systems that don't provide /dev/urandom, OpenSSL doesn't // seed the PRNG. We should do this here (but at least Linux, FreeBSD diff --git a/src/util.cc b/src/util.cc index aeb8fdeef8..a2a21c7bc6 100644 --- a/src/util.cc +++ b/src/util.cc @@ -935,7 +935,7 @@ static const char* check_for_dir(const char* filename, bool load_pkgs) return copy_string(filename); } -FILE* open_file(const char* filename, const char** full_filename, bool load_pkgs) +static FILE* open_file(const char* filename, const char** full_filename, bool load_pkgs) { filename = check_for_dir(filename, load_pkgs); @@ -944,6 +944,13 @@ FILE* open_file(const char* filename, const char** full_filename, bool load_pkgs FILE* f = fopen(filename, "r"); + if ( ! f ) + { + char buf[256]; + strerror_r(errno, buf, sizeof(buf)); + reporter->Error("Failed to open file %s: %s", filename, buf); + } + delete [] filename; return f; From 3c37e818ce1cd78a8de128b6632077f6f95986b8 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 25 Sep 2013 11:16:46 -0500 Subject: [PATCH 374/881] A couple null ptr checks. --- src/BroDoc.cc | 26 ++++++++++++++++++++++---- src/Debug.cc | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 6953680df0..dd0e8ff37c 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -504,17 +504,35 @@ static void WritePluginComponents(FILE* f, const plugin::Plugin* p) { switch ( (*it)->Type() ) { case plugin::component::ANALYZER: - WriteAnalyzerComponent(f, - dynamic_cast(*it)); + { + const analyzer::Component* c = + dynamic_cast(*it); + + if ( c ) + WriteAnalyzerComponent(f, c); + else + reporter->InternalError("component type mismatch"); + } break; + case plugin::component::FILE_ANALYZER: - WriteAnalyzerComponent(f, - dynamic_cast(*it)); + { + const file_analysis::Component* c = + dynamic_cast(*it); + + if ( c ) + WriteAnalyzerComponent(f, c); + else + reporter->InternalError("component type mismatch"); + } break; + case plugin::component::READER: reporter->InternalError("docs for READER component unimplemented"); + case plugin::component::WRITER: reporter->InternalError("docs for WRITER component unimplemented"); + default: reporter->InternalError("docs for unknown component unimplemented"); } diff --git a/src/Debug.cc b/src/Debug.cc index b5aaf91f9f..d3cf042ccc 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -721,7 +721,7 @@ static char* get_prompt(bool reset_counter = false) string get_context_description(const Stmt* stmt, const Frame* frame) { ODesc d; - const BroFunc* func = frame->GetFunction(); + const BroFunc* func = frame ? frame->GetFunction() : 0; if ( func ) func->DescribeDebug(&d, frame->GetFuncArgs()); From 2203600e0523c70815d69512a5c00a2e5a0d5b2a Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 25 Sep 2013 12:04:07 -0500 Subject: [PATCH 375/881] Fix logic for failed DNS TXT lookups. A failed request should not evict a previous result from the local cache/mapping. --- src/DNS_Mgr.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 5880a02c57..08e8889a10 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -711,17 +711,19 @@ void DNS_Mgr::AddResult(DNS_Mgr_Request* dr, struct nb_dns_result* r) if ( dr->ReqIsTxt() ) { TextMap::iterator it = text_mappings.find(dr->ReqHost()); + if ( it == text_mappings.end() ) text_mappings[dr->ReqHost()] = new_dm; else { - if ( new_dm->Failed() && prev_dm && prev_dm->Valid() ) - ++keep_prev; - else - { - prev_dm = it->second; - it->second = new_dm; - } + prev_dm = it->second; + it->second = new_dm; + } + + if ( new_dm->Failed() && prev_dm && prev_dm->Valid() ) + { + text_mappings[dr->ReqHost()] = prev_dm; + ++keep_prev; } } else From 4072afb363b24cfa5e783f293d0c3864b905d296 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 25 Sep 2013 12:49:46 -0500 Subject: [PATCH 376/881] Remove dead/unfinished code in unary not expr. The code that looks like it was intended to make it apply to a vector operand couldn't be reached and making it reachable would still require changes to other methods for it to work so just removing for now. --- src/Expr.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Expr.cc b/src/Expr.cc index e49150f3ac..2bd06054d6 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -1129,15 +1129,10 @@ NotExpr::NotExpr(Expr* arg_op) : UnaryExpr(EXPR_NOT, arg_op) return; BroType* t = op->Type(); - if ( IsVector(t->Tag()) ) - t = t->AsVectorType()->YieldType(); - TypeTag bt = t->Tag(); if ( ! IsIntegral(bt) && bt != TYPE_BOOL ) ExprError("requires an integral or boolean operand"); - else if ( IsVector(bt) ) - SetType(new VectorType(base_type(TYPE_BOOL))); else SetType(base_type(TYPE_BOOL)); } @@ -1151,7 +1146,7 @@ Expr* NotExpr::DoSimplify() // !!x == x return ((NotExpr*) op)->Op()->Ref(); - if ( op->IsConst() && ! is_vector(op->ExprVal()) ) + if ( op->IsConst() ) return new ConstExpr(Fold(op->ExprVal())); return this; From 64f3bef96da548bc5e13112dbd090b064d940d03 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 25 Sep 2013 13:37:46 -0500 Subject: [PATCH 377/881] Remove logically dead code. --- src/RemoteSerializer.cc | 2 +- src/Val.cc | 2 +- src/analyzer/protocol/ayiya/ayiya-analyzer.pac | 2 +- src/input/Manager.cc | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index bc006b4b1f..e36686b487 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -1247,7 +1247,7 @@ bool RemoteSerializer::SendCapabilities(Peer* peer) caps |= Peer::PID_64BIT; caps |= Peer::NEW_CACHE_STRATEGY; - return caps ? SendToChild(MSG_CAPS, peer, 3, caps, 0, 0) : true; + return SendToChild(MSG_CAPS, peer, 3, caps, 0, 0); } bool RemoteSerializer::Listen(const IPAddr& ip, uint16 port, bool expect_ssl, diff --git a/src/Val.cc b/src/Val.cc index ffe98ab7bc..bd065f0d8f 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2162,7 +2162,7 @@ void TableVal::DoExpire(double t) else if ( v->ExpireAccessTime() + expire_time < t ) { - Val* val = v ? v->Value() : 0; + Val* val = v->Value(); if ( expire_expr ) { diff --git a/src/analyzer/protocol/ayiya/ayiya-analyzer.pac b/src/analyzer/protocol/ayiya/ayiya-analyzer.pac index 7a151453c1..56fcc794bc 100644 --- a/src/analyzer/protocol/ayiya/ayiya-analyzer.pac +++ b/src/analyzer/protocol/ayiya/ayiya-analyzer.pac @@ -79,7 +79,7 @@ flow AYIYA_Flow sessions->DoNextInnerPacket(network_time(), 0, inner, e, ec); - return (result == 0) ? true : false; + return true; %} }; diff --git a/src/input/Manager.cc b/src/input/Manager.cc index d739a96809..f76ab67f0d 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -1153,7 +1153,6 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals) { // just quit and delete everything we created. delete idxhash; - delete h; return stream->num_val_fields + stream->num_idx_fields; } From 706363a295ca484db0b9d5840736b98e66903494 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 25 Sep 2013 16:44:39 -0400 Subject: [PATCH 378/881] Fixes for the 2.2 beta. --- scripts/base/frameworks/software/main.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/base/frameworks/software/main.bro b/scripts/base/frameworks/software/main.bro index fefc465e1a..83002481c1 100644 --- a/scripts/base/frameworks/software/main.bro +++ b/scripts/base/frameworks/software/main.bro @@ -436,7 +436,7 @@ function found(id: conn_id, info: Info): bool { Reporter::error("No unparsed version string present in Info record with version in Software::found"); return F; - } + } local sw = parse(info$unparsed_version); info$unparsed_version = sw$unparsed_version; info$name = sw$name; From 9264e2e7d3f1eda8a408db3da777afbd8b1f5f51 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Wed, 25 Sep 2013 22:21:56 -0700 Subject: [PATCH 379/881] add new tls cipher suites --- scripts/base/protocols/ssl/consts.bro | 228 ++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) diff --git a/scripts/base/protocols/ssl/consts.bro b/scripts/base/protocols/ssl/consts.bro index 42989a4cb9..94416c5ad1 100644 --- a/scripts/base/protocols/ssl/consts.bro +++ b/scripts/base/protocols/ssl/consts.bro @@ -303,6 +303,122 @@ export { const TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039; const TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A; const TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B; + # RFC 6209 + const TLS_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC03C; + const TLS_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC03D; + const TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 = 0xC03E; + const TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 = 0xC03F; + const TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC040; + const TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC041; + const TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 = 0xC042; + const TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 = 0xC043; + const TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC044; + const TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC045; + const TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256 = 0xC046; + const TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384 = 0xC047; + const TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 = 0xC048; + const TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 = 0xC049; + const TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 = 0xC04A; + const TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 = 0xC04B; + const TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC04C; + const TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC04D; + const TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 = 0xC04E; + const TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 = 0xC04F; + const TLS_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC050; + const TLS_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC051; + const TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC052; + const TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC053; + const TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC054; + const TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC055; + const TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC056; + const TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC057; + const TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC058; + const TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC059; + const TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256 = 0xC05A; + const TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384 = 0xC05B; + const TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05C; + const TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05D; + const TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05E; + const TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05F; + const TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC060; + const TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC061; + const TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC062; + const TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC063; + const TLS_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC064; + const TLS_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC065; + const TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC066; + const TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC067; + const TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC068; + const TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC069; + const TLS_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06A; + const TLS_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06B; + const TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06C; + const TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06D; + const TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06E; + const TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06F; + const TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 = 0xC070; + const TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 = 0xC071; + # RFC 6367 + const TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC072; + const TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC073; + const TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC074; + const TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC075; + const TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC076; + const TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC077; + const TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC078; + const TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC079; + const TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07A; + const TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07B; + const TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07C; + const TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07D; + const TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07E; + const TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07F; + const TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080; + const TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081; + const TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC082; + const TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC083; + const TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256 = 0xC084; + const TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384 = 0xC085; + const TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086; + const TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087; + const TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC088; + const TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC089; + const TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08A; + const TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08B; + const TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08C; + const TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08D; + const TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08E; + const TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08F; + const TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090; + const TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091; + const TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC092; + const TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC093; + const TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC094; + const TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC095; + const TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC096; + const TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC097; + const TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC098; + const TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC099; + const TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC09A; + const TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC09B; + # RFC 6655 + const TLS_RSA_WITH_AES_128_CCM = 0xC09C; + const TLS_RSA_WITH_AES_256_CCM = 0xC09D; + const TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E; + const TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F; + const TLS_RSA_WITH_AES_128_CCM_8 = 0xC0A0; + const TLS_RSA_WITH_AES_256_CCM_8 = 0xC0A1; + const TLS_DHE_RSA_WITH_AES_128_CCM_8 = 0xC0A2; + const TLS_DHE_RSA_WITH_AES_256_CCM_8 = 0xC0A3; + const TLS_PSK_WITH_AES_128_CCM = 0xC0A4; + const TLS_PSK_WITH_AES_256_CCM = 0xC0A5; + const TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6; + const TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7; + const TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8; + const TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9; + const TLS_PSK_DHE_WITH_AES_128_CCM_8 = 0xC0AA; + const TLS_PSK_DHE_WITH_AES_256_CCM_8 = 0xC0AB; + const SSL_RSA_FIPS_WITH_DES_CBC_SHA = 0xFEFE; const SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA = 0xFEFF; const SSL_RSA_FIPS_WITH_DES_CBC_SHA_2 = 0xFFE1; @@ -535,6 +651,118 @@ export { [TLS_ECDHE_PSK_WITH_NULL_SHA] = "TLS_ECDHE_PSK_WITH_NULL_SHA", [TLS_ECDHE_PSK_WITH_NULL_SHA256] = "TLS_ECDHE_PSK_WITH_NULL_SHA256", [TLS_ECDHE_PSK_WITH_NULL_SHA384] = "TLS_ECDHE_PSK_WITH_NULL_SHA384", + [TLS_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_RSA_WITH_ARIA_128_CBC_SHA256", + [TLS_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_RSA_WITH_ARIA_256_CBC_SHA384", + [TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256] = "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256", + [TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384] = "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384", + [TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256", + [TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384", + [TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256] = "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256", + [TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384] = "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384", + [TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256", + [TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384", + [TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256] = "TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256", + [TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384] = "TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384", + [TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256", + [TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384", + [TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256", + [TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384", + [TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256", + [TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384", + [TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256", + [TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384", + [TLS_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_RSA_WITH_ARIA_128_GCM_SHA256", + [TLS_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_RSA_WITH_ARIA_256_GCM_SHA384", + [TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256", + [TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384", + [TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256", + [TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384", + [TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256] = "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256", + [TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384] = "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384", + [TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256] = "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256", + [TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384] = "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384", + [TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256] = "TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256", + [TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384] = "TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384", + [TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256] = "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256", + [TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384] = "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", + [TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256] = "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256", + [TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384] = "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384", + [TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256", + [TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384", + [TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256] = "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256", + [TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384] = "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384", + [TLS_PSK_WITH_ARIA_128_CBC_SHA256] = "TLS_PSK_WITH_ARIA_128_CBC_SHA256", + [TLS_PSK_WITH_ARIA_256_CBC_SHA384] = "TLS_PSK_WITH_ARIA_256_CBC_SHA384", + [TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256] = "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256", + [TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384] = "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384", + [TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256] = "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256", + [TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384] = "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384", + [TLS_PSK_WITH_ARIA_128_GCM_SHA256] = "TLS_PSK_WITH_ARIA_128_GCM_SHA256", + [TLS_PSK_WITH_ARIA_256_GCM_SHA384] = "TLS_PSK_WITH_ARIA_256_GCM_SHA384", + [TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256] = "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256", + [TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384] = "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384", + [TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256] = "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256", + [TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384] = "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384", + [TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256] = "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256", + [TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384] = "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384", + [TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", + [TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", + [TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", + [TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", + [TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", + [TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", + [TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256", + [TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384", + [TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256] = "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256", + [TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384] = "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384", + [TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256", + [TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384", + [TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", + [TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", + [TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256", + [TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384", + [TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256] = "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", + [TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384] = "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", + [TLS_RSA_WITH_AES_128_CCM] = "TLS_RSA_WITH_AES_128_CCM", + [TLS_RSA_WITH_AES_256_CCM] = "TLS_RSA_WITH_AES_256_CCM", + [TLS_DHE_RSA_WITH_AES_128_CCM] = "TLS_DHE_RSA_WITH_AES_128_CCM", + [TLS_DHE_RSA_WITH_AES_256_CCM] = "TLS_DHE_RSA_WITH_AES_256_CCM", + [TLS_RSA_WITH_AES_128_CCM_8] = "TLS_RSA_WITH_AES_128_CCM_8", + [TLS_RSA_WITH_AES_256_CCM_8] = "TLS_RSA_WITH_AES_256_CCM_8", + [TLS_DHE_RSA_WITH_AES_128_CCM_8] = "TLS_DHE_RSA_WITH_AES_128_CCM_8", + [TLS_DHE_RSA_WITH_AES_256_CCM_8] = "TLS_DHE_RSA_WITH_AES_256_CCM_8", + [TLS_PSK_WITH_AES_128_CCM] = "TLS_PSK_WITH_AES_128_CCM", + [TLS_PSK_WITH_AES_256_CCM] = "TLS_PSK_WITH_AES_256_CCM", + [TLS_DHE_PSK_WITH_AES_128_CCM] = "TLS_DHE_PSK_WITH_AES_128_CCM", + [TLS_DHE_PSK_WITH_AES_256_CCM] = "TLS_DHE_PSK_WITH_AES_256_CCM", + [TLS_PSK_WITH_AES_128_CCM_8] = "TLS_PSK_WITH_AES_128_CCM_8", + [TLS_PSK_WITH_AES_256_CCM_8] = "TLS_PSK_WITH_AES_256_CCM_8", + [TLS_PSK_DHE_WITH_AES_128_CCM_8] = "TLS_PSK_DHE_WITH_AES_128_CCM_8", + [TLS_PSK_DHE_WITH_AES_256_CCM_8] = "TLS_PSK_DHE_WITH_AES_256_CCM_8", [SSL_RSA_FIPS_WITH_DES_CBC_SHA] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA", [SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", [SSL_RSA_FIPS_WITH_DES_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA_2", From 497ada12e8597d842a4ccb73a60169198b9058d9 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Thu, 26 Sep 2013 10:03:17 -0700 Subject: [PATCH 380/881] ...and a few more ciphers. --- scripts/base/protocols/ssl/consts.bro | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/scripts/base/protocols/ssl/consts.bro b/scripts/base/protocols/ssl/consts.bro index 94416c5ad1..5a7522c159 100644 --- a/scripts/base/protocols/ssl/consts.bro +++ b/scripts/base/protocols/ssl/consts.bro @@ -178,6 +178,21 @@ export { const TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B; const TLS_DH_ANON_WITH_AES_128_CBC_SHA256 = 0x006C; const TLS_DH_ANON_WITH_AES_256_CBC_SHA256 = 0x006D; + # draft-ietf-tls-openpgp-keys-06 + const TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD = 0x0072; + const TLS_DHE_DSS_WITH_AES_128_CBC_RMD = 0x0073; + const TLS_DHE_DSS_WITH_AES_256_CBC_RMD = 0x0074; + const TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD = 0x0077; + const TLS_DHE_RSA_WITH_AES_128_CBC_RMD = 0x0078; + const TLS_DHE_RSA_WITH_AES_256_CBC_RMD = 0x0079; + const TLS_RSA_WITH_3DES_EDE_CBC_RMD = 0x007C; + const TLS_RSA_WITH_AES_128_CBC_RMD = 0x007D; + const TLS_RSA_WITH_AES_256_CBC_RMD = 0x007E; + # draft-chudov-cryptopro-cptls-04 + const TLS_GOSTR341094_WITH_28147_CNT_IMIT = 0x0080; + const TLS_GOSTR341001_WITH_28147_CNT_IMIT = 0x0081; + const TLS_GOSTR341094_WITH_NULL_GOSTR3411 = 0x0082; + const TLS_GOSTR341001_WITH_NULL_GOSTR3411 = 0x0083; const TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084; const TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085; const TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086; @@ -244,6 +259,7 @@ export { const TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3; const TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4; const TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5; + # RFC 4492 const TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001; const TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002; const TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003; @@ -526,6 +542,19 @@ export { [TLS_DHE_RSA_WITH_AES_256_CBC_SHA256] = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", [TLS_DH_ANON_WITH_AES_128_CBC_SHA256] = "TLS_DH_ANON_WITH_AES_128_CBC_SHA256", [TLS_DH_ANON_WITH_AES_256_CBC_SHA256] = "TLS_DH_ANON_WITH_AES_256_CBC_SHA256", + [TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD] = "TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD", + [TLS_DHE_DSS_WITH_AES_128_CBC_RMD] = "TLS_DHE_DSS_WITH_AES_128_CBC_RMD", + [TLS_DHE_DSS_WITH_AES_256_CBC_RMD] = "TLS_DHE_DSS_WITH_AES_256_CBC_RMD", + [TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD] = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD", + [TLS_DHE_RSA_WITH_AES_128_CBC_RMD] = "TLS_DHE_RSA_WITH_AES_128_CBC_RMD", + [TLS_DHE_RSA_WITH_AES_256_CBC_RMD] = "TLS_DHE_RSA_WITH_AES_256_CBC_RMD", + [TLS_RSA_WITH_3DES_EDE_CBC_RMD] = "TLS_RSA_WITH_3DES_EDE_CBC_RMD", + [TLS_RSA_WITH_AES_128_CBC_RMD] = "TLS_RSA_WITH_AES_128_CBC_RMD", + [TLS_RSA_WITH_AES_256_CBC_RMD] = "TLS_RSA_WITH_AES_256_CBC_RMD", + [TLS_GOSTR341094_WITH_28147_CNT_IMIT] = "TLS_GOSTR341094_WITH_28147_CNT_IMIT", + [TLS_GOSTR341001_WITH_28147_CNT_IMIT] = "TLS_GOSTR341001_WITH_28147_CNT_IMIT", + [TLS_GOSTR341094_WITH_NULL_GOSTR3411] = "TLS_GOSTR341094_WITH_NULL_GOSTR3411", + [TLS_GOSTR341001_WITH_NULL_GOSTR3411] = "TLS_GOSTR341001_WITH_NULL_GOSTR3411", [TLS_RSA_WITH_CAMELLIA_256_CBC_SHA] = "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", [TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA] = "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", [TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA] = "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", From 97503dafe509e512fc24d65050d9e1e3445e09d0 Mon Sep 17 00:00:00 2001 From: Daniel Thayer Date: Thu, 26 Sep 2013 15:32:14 -0500 Subject: [PATCH 381/881] Fix a "make doc" warning --- doc/scripting/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 4181704d63..5c85781300 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -90,8 +90,7 @@ the script starts to define instructions to take in a given event. :lines: 33-57 The workhorse of the script is contained in the event handler for -``file_hash``. The ``file_hash`` event is defined in the -:doc:`/scripts/base/bif/plugins/Bro_FileHash.events.bif.bro` script and allows scripts to access +``file_hash``. The :bro:see:`file_hash` event allows scripts to access the information associated with a file for which Bro's file analysis framework has generated a hash. The event handler is passed the file itself as ``f``, the type of digest algorithm used as ``kind`` and the hash generated as ``hash``. From 775ec6795e7d078fff37a882740523f455dfdaeb Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Fri, 27 Sep 2013 10:13:52 -0500 Subject: [PATCH 382/881] Fix uninitialized (or unused) fields. --- src/Anon.cc | 2 + src/Attr.h | 2 +- src/BPF_Program.cc | 3 +- src/ChunkedIO.cc | 4 +- src/ChunkedIO.h | 5 ++- src/CompHash.cc | 1 + src/Conn.cc | 1 + src/DFA.cc | 1 + src/DNS_Mgr.cc | 12 +++++- src/DbgBreakpoint.cc | 2 + src/Debug.cc | 1 + src/Dict.cc | 4 ++ src/Expr.cc | 11 +++++- src/Expr.h | 5 +-- src/File.h | 1 - src/FlowSrc.cc | 1 - src/FlowSrc.h | 3 -- src/RemoteSerializer.cc | 4 ++ src/Rule.h | 1 + src/RuleMatcher.h | 2 +- src/SerialInfo.h | 1 + src/SerializationFormat.cc | 3 +- src/Serializer.cc | 1 + src/Serializer.h | 1 + src/Sessions.h | 7 +--- src/SmithWaterman.cc | 2 +- src/SmithWaterman.h | 4 +- src/Stats.cc | 1 + src/Stats.h | 12 +----- src/Type.cc | 4 +- src/Val.cc | 1 + src/Val.h | 2 +- src/analyzer/Analyzer.cc | 3 +- src/analyzer/protocol/conn-size/ConnSize.cc | 3 +- src/analyzer/protocol/dns/DNS.cc | 3 +- src/analyzer/protocol/dns/DNS.h | 1 - src/analyzer/protocol/http/HTTP.cc | 1 + src/analyzer/protocol/icmp/ICMP.cc | 5 +-- src/analyzer/protocol/login/Login.cc | 2 +- src/analyzer/protocol/login/NVT.cc | 11 ++---- src/analyzer/protocol/login/RSH.cc | 3 ++ src/analyzer/protocol/mime/MIME.cc | 5 ++- src/analyzer/protocol/mime/MIME.h | 1 - src/analyzer/protocol/netbios/NetbiosSSN.cc | 2 +- src/analyzer/protocol/pia/PIA.cc | 3 +- src/analyzer/protocol/pop3/POP3.cc | 3 ++ src/analyzer/protocol/rpc/RPC.cc | 5 +-- src/analyzer/protocol/smb/SMB.cc | 3 ++ src/analyzer/protocol/tcp/TCP.cc | 3 +- src/analyzer/protocol/tcp/TCP_Endpoint.cc | 3 ++ src/bif_arg.cc | 1 + .../analyzer/unified2/Unified2.h | 1 - src/input/Manager.cc | 37 ++++++++----------- src/input/ReaderBackend.cc | 2 + src/input/readers/Ascii.cc | 3 +- src/input/readers/Benchmark.cc | 2 + src/input/readers/Raw.cc | 3 ++ src/input/readers/SQLite.cc | 4 +- src/logging/WriterFrontend.cc | 3 ++ src/logging/writers/DataSeries.cc | 4 ++ src/logging/writers/SQLite.cc | 6 +-- src/threading/SerialTypes.h | 2 +- 62 files changed, 135 insertions(+), 98 deletions(-) diff --git a/src/Anon.cc b/src/Anon.cc index f58057b2fc..87791501a4 100644 --- a/src/Anon.cc +++ b/src/Anon.cc @@ -147,7 +147,9 @@ void AnonymizeIPAddr_A50::init() special_nodes[0].input = special_nodes[0].output = 0; special_nodes[1].input = special_nodes[1].output = 0xFFFFFFFF; + method = 0; before_anonymization = 1; + new_mapping = 0; } int AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits) diff --git a/src/Attr.h b/src/Attr.h index c3e05d4762..7becbb27eb 100644 --- a/src/Attr.h +++ b/src/Attr.h @@ -96,7 +96,7 @@ public: bool operator==(const Attributes& other) const; protected: - Attributes() { type = 0; attrs = 0; } + Attributes() : type(), attrs(), in_record() { } void CheckAttr(Attr* attr); DECLARE_SERIAL(Attributes); diff --git a/src/BPF_Program.cc b/src/BPF_Program.cc index a6d3d80c05..5260429eb0 100644 --- a/src/BPF_Program.cc +++ b/src/BPF_Program.cc @@ -58,9 +58,8 @@ int pcap_compile_nopcap(int snaplen_arg, int linktype_arg, } #endif -BPF_Program::BPF_Program() +BPF_Program::BPF_Program() : m_compiled(), m_program() { - m_compiled = false; } BPF_Program::~BPF_Program() diff --git a/src/ChunkedIO.cc b/src/ChunkedIO.cc index 7e666ee198..22489bbb0c 100644 --- a/src/ChunkedIO.cc +++ b/src/ChunkedIO.cc @@ -14,9 +14,8 @@ #include "NetVar.h" #include "RemoteSerializer.h" -ChunkedIO::ChunkedIO() +ChunkedIO::ChunkedIO() : stats(), tag(), pure() { - pure = false; } void ChunkedIO::Stats(char* buffer, int length) @@ -656,6 +655,7 @@ SSL_CTX* ChunkedIOSSL::ctx; ChunkedIOSSL::ChunkedIOSSL(int arg_socket, bool arg_server) { socket = arg_socket; + last_ret = 0; eof = false; setup = false; server = arg_server; diff --git a/src/ChunkedIO.h b/src/ChunkedIO.h index 56b5656945..6ee79cd3c4 100644 --- a/src/ChunkedIO.h +++ b/src/ChunkedIO.h @@ -292,8 +292,9 @@ private: // Wrapper class around a another ChunkedIO which the (un-)compresses data. class CompressedChunkedIO : public ChunkedIO { public: - CompressedChunkedIO(ChunkedIO* arg_io) - : io(arg_io) {} // takes ownership + CompressedChunkedIO(ChunkedIO* arg_io) // takes ownership + : io(arg_io), zin(), zout(), error(), compress(), uncompress(), + uncompressed_bytes_read(), uncompressed_bytes_written() {} virtual ~CompressedChunkedIO() { delete io; } virtual bool Init(); // does *not* call arg_io->Init() diff --git a/src/CompHash.cc b/src/CompHash.cc index b2eb08c589..5a972f6016 100644 --- a/src/CompHash.cc +++ b/src/CompHash.cc @@ -11,6 +11,7 @@ CompositeHash::CompositeHash(TypeList* composite_type) { type = composite_type; Ref(type); + singleton_tag = TYPE_INTERNAL_ERROR; // If the only element is a record, don't treat it as a // singleton, since it needs to be evaluated specially. diff --git a/src/Conn.cc b/src/Conn.cc index 2e5aa0513e..e221bb20e0 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -141,6 +141,7 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, suppress_event = 0; record_contents = record_packets = 1; + record_current_packet = record_current_content = 0; timers_canceled = 0; inactivity_timeout = 0; diff --git a/src/DFA.cc b/src/DFA.cc index 3bdc444f9e..ad9521709e 100644 --- a/src/DFA.cc +++ b/src/DFA.cc @@ -20,6 +20,7 @@ DFA_State::DFA_State(int arg_state_num, const EquivClass* ec, nfa_states = arg_nfa_states; accept = arg_accept; mark = 0; + centry = 0; SymPartition(ec); diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 08e8889a10..c1036accdd 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -47,8 +47,14 @@ extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); class DNS_Mgr_Request { public: DNS_Mgr_Request(const char* h, int af, bool is_txt) - { host = copy_string(h); fam = af; qtype = is_txt ? 16 : 0; } - DNS_Mgr_Request(const IPAddr& a) { addr = a; host = 0; fam = 0; } + : host(copy_string(h)), fam(af), qtype(is_txt ? 16 : 0), addr(), + request_pending() + { } + + DNS_Mgr_Request(const IPAddr& a) + : host(), fam(), qtype(), addr(a), request_pending() + { } + ~DNS_Mgr_Request() { delete [] host; } // Returns nil if this was an address request. @@ -192,6 +198,8 @@ DNS_Mapping::DNS_Mapping(FILE* f) init_failed = 1; req_host = 0; + req_ttl = 0; + creation_time = 0; char buf[512]; diff --git a/src/DbgBreakpoint.cc b/src/DbgBreakpoint.cc index f1ad551a00..9000d89077 100644 --- a/src/DbgBreakpoint.cc +++ b/src/DbgBreakpoint.cc @@ -49,6 +49,8 @@ DbgBreakpoint::DbgBreakpoint() repeat_count = hit_count = 0; description[0] = 0; + source_filename = 0; + source_line = 0; } DbgBreakpoint::~DbgBreakpoint() diff --git a/src/Debug.cc b/src/Debug.cc index d3cf042ccc..f4ac8c2fdf 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -40,6 +40,7 @@ DebuggerState::DebuggerState() next_bp_id = next_watch_id = next_display_id = 1; BreakBeforeNextStmt(false); curr_frame_idx = 0; + already_did_list = false; BreakFromSignal(false); // ### Don't choose this arbitrary size! Extend Frame. diff --git a/src/Dict.cc b/src/Dict.cc index c71cf4c417..cd7792b539 100644 --- a/src/Dict.cc +++ b/src/Dict.cc @@ -64,6 +64,10 @@ Dictionary::Dictionary(dict_order ordering, int initial_size) SetDensityThresh(DEFAULT_DENSITY_THRESH); delete_func = 0; + tbl_next_ind = 0; + + num_buckets2 = num_entries2 = max_num_entries2 = thresh_entries2 = 0; + den_thresh2 = 0; } Dictionary::~Dictionary() diff --git a/src/Expr.cc b/src/Expr.cc index 2bd06054d6..a8aab865ca 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -2472,6 +2472,7 @@ AssignExpr::AssignExpr(Expr* arg_op1, Expr* arg_op2, int arg_is_init, : BinaryExpr(EXPR_ASSIGN, arg_is_init ? arg_op1 : arg_op1->MakeLvalue(), arg_op2) { + val = 0; is_init = arg_is_init; if ( IsError() ) @@ -3345,14 +3346,14 @@ bool HasFieldExpr::DoSerialize(SerialInfo* info) const { DO_SERIALIZE(SER_HAS_FIELD_EXPR, UnaryExpr); - // Serialize the former "bool is_attr" first for backwards compatibility. + // Serialize former "bool is_attr" member first for backwards compatibility. return SERIALIZE(false) && SERIALIZE(field_name) && SERIALIZE(field); } bool HasFieldExpr::DoUnserialize(UnserialInfo* info) { DO_UNSERIALIZE(UnaryExpr); - // Unserialize the former "bool is_attr" first for backwards compatibility. + // Unserialize former "bool is_attr" member for backwards compatibility. bool not_used; return UNSERIALIZE(¬_used) && UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field); } @@ -3361,6 +3362,8 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list, BroType* arg_type) : UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list) { + ctor_type = 0; + if ( IsError() ) return; @@ -3501,6 +3504,8 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list, attr_list* arg_attrs, BroType* arg_type) : UnaryExpr(EXPR_TABLE_CONSTRUCTOR, constructor_list) { + attrs = 0; + if ( IsError() ) return; @@ -3625,6 +3630,8 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, attr_list* arg_attrs, BroType* arg_type) : UnaryExpr(EXPR_SET_CONSTRUCTOR, constructor_list) { + attrs = 0; + if ( IsError() ) return; diff --git a/src/Expr.h b/src/Expr.h index ba173feae0..26f20fcbe9 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -331,12 +331,10 @@ protected: BinaryExpr() { op1 = op2 = 0; } BinaryExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) - : Expr(arg_tag) + : Expr(arg_tag), op1(arg_op1), op2(arg_op2) { if ( ! (arg_op1 && arg_op2) ) return; - op1 = arg_op1; - op2 = arg_op2; if ( op1->IsError() || op2->IsError() ) SetError(); } @@ -749,7 +747,6 @@ protected: DECLARE_SERIAL(HasFieldExpr); - bool is_attr; const char* field_name; int field; }; diff --git a/src/File.h b/src/File.h index a37b7fe0a6..dc56c5a3fe 100644 --- a/src/File.h +++ b/src/File.h @@ -147,7 +147,6 @@ protected: Timer* rotate_timer; double open_time; - bool dont_rotate; // See InstallRotateTimer() bool print_hook; bool raw_output; diff --git a/src/FlowSrc.cc b/src/FlowSrc.cc index f5fb0bd1e6..7a79e9063b 100644 --- a/src/FlowSrc.cc +++ b/src/FlowSrc.cc @@ -64,7 +64,6 @@ void FlowSrc::Close() FlowSocketSrc::~FlowSocketSrc() { - delete [] listenparms; } int FlowSocketSrc::ExtractNextPDU() diff --git a/src/FlowSrc.h b/src/FlowSrc.h index 7b0b14ad15..03dda2761d 100644 --- a/src/FlowSrc.h +++ b/src/FlowSrc.h @@ -67,9 +67,6 @@ public: virtual ~FlowSocketSrc(); int ExtractNextPDU(); - -protected: - char* listenparms; }; class FlowFileSrc : public FlowSrc { diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index e36686b487..43a963ab21 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -541,6 +541,10 @@ RemoteSerializer::RemoteSerializer() in_sync = 0; last_flush = 0; received_logs = 0; + current_id = 0; + current_msgtype = 0; + current_args = 0; + source_peer = 0; } RemoteSerializer::~RemoteSerializer() diff --git a/src/Rule.h b/src/Rule.h index 959008fbf9..e5ae703d39 100644 --- a/src/Rule.h +++ b/src/Rule.h @@ -28,6 +28,7 @@ public: idx = rule_counter++; location = arg_location; active = true; + next = 0; } ~Rule(); diff --git a/src/RuleMatcher.h b/src/RuleMatcher.h index 351c3c30bf..0d7a2fbf7c 100644 --- a/src/RuleMatcher.h +++ b/src/RuleMatcher.h @@ -103,7 +103,7 @@ private: friend class RuleMatcher; struct PatternSet { - PatternSet() {} + PatternSet() : re() {} // If we're above the 'RE_level' (see RuleMatcher), this // expr contains all patterns on this node. If we're on diff --git a/src/SerialInfo.h b/src/SerialInfo.h index aa4c382349..de2d9eeb61 100644 --- a/src/SerialInfo.h +++ b/src/SerialInfo.h @@ -20,6 +20,7 @@ public: SerialInfo(const SerialInfo& info) { + chunk = info.chunk; s = info.s; may_suspend = info.may_suspend; cache = info.cache; diff --git a/src/SerializationFormat.cc b/src/SerializationFormat.cc index 10dd4f29ea..eb8462521e 100644 --- a/src/SerializationFormat.cc +++ b/src/SerializationFormat.cc @@ -6,8 +6,9 @@ #include "Reporter.h" SerializationFormat::SerializationFormat() + : output(), output_size(), output_pos(), input(), input_len(), input_pos(), + bytes_written(), bytes_read() { - output = 0; } SerializationFormat::~SerializationFormat() diff --git a/src/Serializer.cc b/src/Serializer.cc index bd1be77a2d..66ff98ec5d 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -1037,6 +1037,7 @@ void ConversionSerializer::GotPacket(Packet* p) } EventPlayer::EventPlayer(const char* file) + : stream_time(), replay_time(), ne_time(), ne_handler(), ne_args() { if ( ! OpenFile(file, true) || fd < 0 ) Error(fmt("event replayer: cannot open %s", file)); diff --git a/src/Serializer.h b/src/Serializer.h index 72e0723880..30095ff4fc 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -403,6 +403,7 @@ public: hdr_size = 0; free = arg_free; tag = arg_tag; + link_type = 0; } ~Packet() diff --git a/src/Sessions.h b/src/Sessions.h index 27b052ba2d..1788541f45 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -55,15 +55,12 @@ struct SessionStats { class TimerMgrExpireTimer : public Timer { public: TimerMgrExpireTimer(double t, TimerMgr* arg_mgr) - : Timer(t, TIMER_TIMERMGR_EXPIRE) - { - mgr = arg_mgr; - } + : Timer(t, TIMER_TIMERMGR_EXPIRE), mgr(arg_mgr) + { } virtual void Dispatch(double t, int is_expire); protected: - double interval; TimerMgr* mgr; }; diff --git a/src/SmithWaterman.cc b/src/SmithWaterman.cc index e051032756..5f2786caa0 100644 --- a/src/SmithWaterman.cc +++ b/src/SmithWaterman.cc @@ -11,7 +11,7 @@ #include "Reporter.h" BroSubstring::BroSubstring(const BroSubstring& bst) -: BroString((const BroString&) bst), _new(bst._new) +: BroString((const BroString&) bst), _num(), _new(bst._new) { for ( BSSAlignVecCIt it = bst._aligns.begin(); it != bst._aligns.end(); ++it ) _aligns.push_back(*it); diff --git a/src/SmithWaterman.h b/src/SmithWaterman.h index 6ea191f5d9..190ecda597 100644 --- a/src/SmithWaterman.h +++ b/src/SmithWaterman.h @@ -42,10 +42,10 @@ public: typedef BSSAlignVec::const_iterator BSSAlignVecCIt; BroSubstring(const string& string) - : BroString(string), _new(false) { } + : BroString(string), _num(), _new(false) { } BroSubstring(const BroString& string) - : BroString(string), _new(false) { } + : BroString(string), _num(), _new(false) { } BroSubstring(const BroSubstring& bst); diff --git a/src/Stats.cc b/src/Stats.cc index 9b839ec672..c4b0ed45b1 100644 --- a/src/Stats.cc +++ b/src/Stats.cc @@ -399,6 +399,7 @@ PacketProfiler::PacketProfiler(unsigned int mode, double freq, last_Utime = last_Stime = last_Rtime = 0.0; last_timestamp = time = 0.0; pkt_cnt = byte_cnt = 0; + last_mem = 0; file->Write("time dt npkts nbytes dRtime dUtime dStime dmem\n"); } diff --git a/src/Stats.h b/src/Stats.h index 8137ad16cf..1bcc2e18dc 100644 --- a/src/Stats.h +++ b/src/Stats.h @@ -29,26 +29,18 @@ public: // The constructor takes some way of identifying the segment. SegmentProfiler(SegmentStatsReporter* arg_reporter, const char* arg_name) + : reporter(arg_reporter), name(arg_name), loc(), initial_rusage() { - reporter = arg_reporter; if ( reporter ) - { - name = arg_name; - loc = 0; Init(); - } } SegmentProfiler(SegmentStatsReporter* arg_reporter, const Location* arg_loc) + : reporter(arg_reporter), name(), loc(arg_loc), initial_rusage() { - reporter = arg_reporter; if ( reporter ) - { - name = 0; - loc = arg_loc; Init(); - } } ~SegmentProfiler() diff --git a/src/Type.cc b/src/Type.cc index 706a15aea2..a6d8b90c6c 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1564,10 +1564,8 @@ bool EnumType::DoUnserialize(UnserialInfo* info) } VectorType::VectorType(BroType* element_type) -: BroType(TYPE_VECTOR) + : BroType(TYPE_VECTOR), yield_type(element_type) { - if ( element_type ) - yield_type = element_type; } VectorType::~VectorType() diff --git a/src/Val.cc b/src/Val.cc index bd065f0d8f..d791ff195d 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2572,6 +2572,7 @@ unsigned int TableVal::MemoryAllocation() const RecordVal::RecordVal(RecordType* t) : MutableVal(t) { + origin = 0; record_type = t; int n = record_type->NumFields(); val_list* vl = val.val_list_val = new val_list(n); diff --git a/src/Val.h b/src/Val.h index a7088313d6..33bd89c0d5 100644 --- a/src/Val.h +++ b/src/Val.h @@ -466,7 +466,7 @@ public: protected: MutableVal(BroType* t) : Val(t) { props = 0; id = 0; last_modified = SerialObj::ALWAYS; } - MutableVal() { id = 0; last_modified = SerialObj::ALWAYS; } + MutableVal() { props = 0; id = 0; last_modified = SerialObj::ALWAYS; } ~MutableVal(); friend class ID; diff --git a/src/analyzer/Analyzer.cc b/src/analyzer/Analyzer.cc index 7a71c2e0d4..03734f1a22 100644 --- a/src/analyzer/Analyzer.cc +++ b/src/analyzer/Analyzer.cc @@ -20,7 +20,7 @@ public: void Dispatch(double t, int is_expire); protected: - AnalyzerTimer() {} + AnalyzerTimer() : analyzer(), timer(), do_expire() {} void Init(Analyzer* analyzer, analyzer_timer_func timer, int do_expire); @@ -124,6 +124,7 @@ void Analyzer::CtorInit(const Tag& arg_tag, Connection* arg_conn) tag = arg_tag; id = ++id_counter; protocol_confirmed = false; + timers_canceled = false; skip = false; finished = false; removing = false; diff --git a/src/analyzer/protocol/conn-size/ConnSize.cc b/src/analyzer/protocol/conn-size/ConnSize.cc index ad08c78c4f..227a4b1be2 100644 --- a/src/analyzer/protocol/conn-size/ConnSize.cc +++ b/src/analyzer/protocol/conn-size/ConnSize.cc @@ -11,7 +11,8 @@ using namespace analyzer::conn_size; ConnSize_Analyzer::ConnSize_Analyzer(Connection* c) -: Analyzer("CONNSIZE", c) + : Analyzer("CONNSIZE", c), + orig_bytes(), resp_bytes(), orig_pkts(), resp_pkts() { } diff --git a/src/analyzer/protocol/dns/DNS.cc b/src/analyzer/protocol/dns/DNS.cc index 4901df4417..806cb9ae75 100644 --- a/src/analyzer/protocol/dns/DNS.cc +++ b/src/analyzer/protocol/dns/DNS.cc @@ -894,6 +894,7 @@ DNS_MsgInfo::DNS_MsgInfo(DNS_RawMsgHdr* hdr, int arg_is_query) answer_type = DNS_QUESTION; skip_event = 0; + tsig = 0; } DNS_MsgInfo::~DNS_MsgInfo() @@ -1002,7 +1003,7 @@ Contents_DNS::Contents_DNS(Connection* conn, bool orig, interp = arg_interp; msg_buf = 0; - buf_n = msg_size = 0; + buf_n = buf_len = msg_size = 0; state = DNS_LEN_HI; } diff --git a/src/analyzer/protocol/dns/DNS.h b/src/analyzer/protocol/dns/DNS.h index 373250e8f4..af4b8de22f 100644 --- a/src/analyzer/protocol/dns/DNS.h +++ b/src/analyzer/protocol/dns/DNS.h @@ -144,7 +144,6 @@ public: // More values for spesific DNS types. // struct EDNS_ADDITIONAL* edns; - int tsig_init; struct TSIG_DATA* tsig; }; diff --git a/src/analyzer/protocol/http/HTTP.cc b/src/analyzer/protocol/http/HTTP.cc index 71c0052b4b..4bb2385c27 100644 --- a/src/analyzer/protocol/http/HTTP.cc +++ b/src/analyzer/protocol/http/HTTP.cc @@ -534,6 +534,7 @@ HTTP_Message::HTTP_Message(HTTP_Analyzer* arg_analyzer, top_level = new HTTP_Entity(this, 0, expect_body); BeginEntity(top_level); + buffer_offset = buffer_size = 0; data_buffer = 0; total_buffer_size = 0; diff --git a/src/analyzer/protocol/icmp/ICMP.cc b/src/analyzer/protocol/icmp/ICMP.cc index a851ebe8ee..048c6e51ce 100644 --- a/src/analyzer/protocol/icmp/ICMP.cc +++ b/src/analyzer/protocol/icmp/ICMP.cc @@ -17,11 +17,10 @@ using namespace analyzer::icmp; ICMP_Analyzer::ICMP_Analyzer(Connection* c) -: TransportLayerAnalyzer("ICMP", c) + : TransportLayerAnalyzer("ICMP", c), + icmp_conn_val(), type(), code(), request_len(-1), reply_len(-1) { - icmp_conn_val = 0; c->SetInactivityTimeout(icmp_inactivity_timeout); - request_len = reply_len = -1; } void ICMP_Analyzer::Done() diff --git a/src/analyzer/protocol/login/Login.cc b/src/analyzer/protocol/login/Login.cc index 335b855f1d..de2445d81f 100644 --- a/src/analyzer/protocol/login/Login.cc +++ b/src/analyzer/protocol/login/Login.cc @@ -25,7 +25,7 @@ static RE_Matcher* re_login_timeouts; static RE_Matcher* init_RE(ListVal* l); Login_Analyzer::Login_Analyzer(const char* name, Connection* conn) -: tcp::TCP_ApplicationAnalyzer(name, conn) + : tcp::TCP_ApplicationAnalyzer(name, conn), user_text() { state = LOGIN_STATE_AUTHENTICATE; num_user_lines_seen = lines_scanned = 0; diff --git a/src/analyzer/protocol/login/NVT.cc b/src/analyzer/protocol/login/NVT.cc index 62e4d0c050..752ce54df2 100644 --- a/src/analyzer/protocol/login/NVT.cc +++ b/src/analyzer/protocol/login/NVT.cc @@ -364,14 +364,11 @@ void TelnetBinaryOption::InconsistentOption(unsigned int /* type */) NVT_Analyzer::NVT_Analyzer(Connection* conn, bool orig) -: tcp::ContentLine_Analyzer("NVT", conn, orig) + : tcp::ContentLine_Analyzer("NVT", conn, orig), + peer(), pending_IAC(), IAC_pos(), is_suboption(), last_was_IAC(), + binary_mode(), encrypting_mode(), authentication_has_been_accepted(), + auth_name(), options(), num_options() { - peer = 0; - is_suboption = last_was_IAC = pending_IAC = 0; - IAC_pos = 0; - num_options = 0; - authentication_has_been_accepted = encrypting_mode = binary_mode = 0; - auth_name = 0; } NVT_Analyzer::~NVT_Analyzer() diff --git a/src/analyzer/protocol/login/RSH.cc b/src/analyzer/protocol/login/RSH.cc index e70fae1b8c..8aebb89116 100644 --- a/src/analyzer/protocol/login/RSH.cc +++ b/src/analyzer/protocol/login/RSH.cc @@ -22,7 +22,10 @@ Contents_Rsh_Analyzer::Contents_Rsh_Analyzer(Connection* conn, bool orig, if ( orig ) state = save_state = RSH_FIRST_NULL; else + { state = RSH_LINE_MODE; + save_state = RSH_UNKNOWN; + } } Contents_Rsh_Analyzer::~Contents_Rsh_Analyzer() diff --git a/src/analyzer/protocol/mime/MIME.cc b/src/analyzer/protocol/mime/MIME.cc index 5748bece86..c66a0b9be7 100644 --- a/src/analyzer/protocol/mime/MIME.cc +++ b/src/analyzer/protocol/mime/MIME.cc @@ -1257,7 +1257,7 @@ TableVal* MIME_Message::BuildHeaderTable(MIME_HeaderList& hlist) } MIME_Mail::MIME_Mail(analyzer::Analyzer* mail_analyzer, int buf_size) -: MIME_Message(mail_analyzer) + : MIME_Message(mail_analyzer), md5_hash() { analyzer = mail_analyzer; @@ -1280,12 +1280,13 @@ MIME_Mail::MIME_Mail(analyzer::Analyzer* mail_analyzer, int buf_size) if ( mime_content_hash ) { compute_content_hash = 1; - content_hash_length = 0; md5_init(&md5_hash); } else compute_content_hash = 0; + content_hash_length = 0; + top_level = new MIME_Entity(this, 0); // to be changed to MIME_Mail BeginEntity(top_level); } diff --git a/src/analyzer/protocol/mime/MIME.h b/src/analyzer/protocol/mime/MIME.h index 4d7a89f37a..8d83609cc1 100644 --- a/src/analyzer/protocol/mime/MIME.h +++ b/src/analyzer/protocol/mime/MIME.h @@ -247,7 +247,6 @@ protected: int max_chunk_length; int buffer_start; int data_start; - int buffer_offset; int compute_content_hash; int content_hash_length; MD5_CTX md5_hash; diff --git a/src/analyzer/protocol/netbios/NetbiosSSN.cc b/src/analyzer/protocol/netbios/NetbiosSSN.cc index bed906135e..4d6ed8e1f1 100644 --- a/src/analyzer/protocol/netbios/NetbiosSSN.cc +++ b/src/analyzer/protocol/netbios/NetbiosSSN.cc @@ -346,7 +346,7 @@ Contents_NetbiosSSN::Contents_NetbiosSSN(Connection* conn, bool orig, interp = arg_interp; type = flags = msg_size = 0; msg_buf = 0; - buf_n = msg_size = 0; + buf_n = buf_len = msg_size = 0; state = NETBIOS_SSN_TYPE; } diff --git a/src/analyzer/protocol/pia/PIA.cc b/src/analyzer/protocol/pia/PIA.cc index 81c7251820..e94053b8a5 100644 --- a/src/analyzer/protocol/pia/PIA.cc +++ b/src/analyzer/protocol/pia/PIA.cc @@ -7,9 +7,8 @@ using namespace analyzer::pia; PIA::PIA(analyzer::Analyzer* arg_as_analyzer) + : state(INIT), as_analyzer(arg_as_analyzer), conn(), current_packet() { - current_packet.data = 0; - as_analyzer = arg_as_analyzer; } PIA::~PIA() diff --git a/src/analyzer/protocol/pop3/POP3.cc b/src/analyzer/protocol/pop3/POP3.cc index ccbbb8df04..52f9eb8445 100644 --- a/src/analyzer/protocol/pop3/POP3.cc +++ b/src/analyzer/protocol/pop3/POP3.cc @@ -43,6 +43,9 @@ POP3_Analyzer::POP3_Analyzer(Connection* conn) multiLine = false; backOff = false; + lastRequiredCommand = 0; + authLines = 0; + mail = 0; AddSupportAnalyzer(new tcp::ContentLine_Analyzer(conn, true)); diff --git a/src/analyzer/protocol/rpc/RPC.cc b/src/analyzer/protocol/rpc/RPC.cc index ea037c227f..559e629e57 100644 --- a/src/analyzer/protocol/rpc/RPC.cc +++ b/src/analyzer/protocol/rpc/RPC.cc @@ -679,10 +679,9 @@ void Contents_RPC::DeliverStream(int len, const u_char* data, bool orig) RPC_Analyzer::RPC_Analyzer(const char* name, Connection* conn, RPC_Interpreter* arg_interp) -: tcp::TCP_ApplicationAnalyzer(name, conn) + : tcp::TCP_ApplicationAnalyzer(name, conn), + interp(arg_interp), orig_rpc(), resp_rpc() { - interp = arg_interp; - if ( Conn()->ConnTransport() == TRANSPORT_UDP ) ADD_ANALYZER_TIMER(&RPC_Analyzer::ExpireTimer, network_time + rpc_timeout, 1, TIMER_RPC_EXPIRE); diff --git a/src/analyzer/protocol/smb/SMB.cc b/src/analyzer/protocol/smb/SMB.cc index 798e2bfd1f..4393626217 100644 --- a/src/analyzer/protocol/smb/SMB.cc +++ b/src/analyzer/protocol/smb/SMB.cc @@ -100,6 +100,9 @@ static int lookup_IPC_name(BroString* name) SMB_Session::SMB_Session(analyzer::Analyzer* arg_analyzer) { analyzer = arg_analyzer; + req_cmd = 0; + smb_mailslot_prot = false; + smb_pipe_prot = false; dce_rpc_session = 0; init_SMB_command_name(); diff --git a/src/analyzer/protocol/tcp/TCP.cc b/src/analyzer/protocol/tcp/TCP.cc index c9cd8ed8d1..4631833dca 100644 --- a/src/analyzer/protocol/tcp/TCP.cc +++ b/src/analyzer/protocol/tcp/TCP.cc @@ -2043,7 +2043,8 @@ RecordVal* TCPStats_Endpoint::BuildStats() } TCPStats_Analyzer::TCPStats_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer("TCPSTATS", c) + : TCP_ApplicationAnalyzer("TCPSTATS", c), + orig_stats(), resp_stats() { } diff --git a/src/analyzer/protocol/tcp/TCP_Endpoint.cc b/src/analyzer/protocol/tcp/TCP_Endpoint.cc index 3beafdeb8a..144d4598dd 100644 --- a/src/analyzer/protocol/tcp/TCP_Endpoint.cc +++ b/src/analyzer/protocol/tcp/TCP_Endpoint.cc @@ -25,12 +25,15 @@ TCP_Endpoint::TCP_Endpoint(TCP_Analyzer* arg_analyzer, int arg_is_orig) window_scale = 0; window_seq = window_ack_seq = 0; contents_start_seq = 0; + FIN_seq = 0; SYN_cnt = FIN_cnt = RST_cnt = 0; did_close = 0; contents_file = 0; tcp_analyzer = arg_analyzer; is_orig = arg_is_orig; + hist_last_SYN = hist_last_FIN = hist_last_RST = 0; + src_addr = is_orig ? tcp_analyzer->Conn()->RespAddr() : tcp_analyzer->Conn()->OrigAddr(); dst_addr = is_orig ? tcp_analyzer->Conn()->OrigAddr() : diff --git a/src/bif_arg.cc b/src/bif_arg.cc index 64b0cb131a..92e228032b 100644 --- a/src/bif_arg.cc +++ b/src/bif_arg.cc @@ -28,6 +28,7 @@ BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, int arg_type) name = arg_name; type = arg_type; type_str = ""; + attr_str = ""; } BuiltinFuncArg::BuiltinFuncArg(const char* arg_name, const char* arg_type_str, diff --git a/src/file_analysis/analyzer/unified2/Unified2.h b/src/file_analysis/analyzer/unified2/Unified2.h index bd172d2b6b..c2ee9e00da 100644 --- a/src/file_analysis/analyzer/unified2/Unified2.h +++ b/src/file_analysis/analyzer/unified2/Unified2.h @@ -30,7 +30,6 @@ private: binpac::Unified2::Unified2_Analyzer* interp; string filename; - int fd; }; } // namespace file_analysis diff --git a/src/input/Manager.cc b/src/input/Manager.cc index f76ab67f0d..e2562338c8 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -84,16 +84,16 @@ public: RecordVal* description; - Stream(); virtual ~Stream(); + +protected: + Stream(StreamType t); }; -Manager::Stream::Stream() +Manager::Stream::Stream(StreamType t) + : name(), removed(), stream_type(t), type(), reader(), config(), + description() { - type = 0; - reader = 0; - description = 0; - removed = false; } Manager::Stream::~Stream() @@ -154,24 +154,17 @@ public: ~AnalysisStream(); }; -Manager::TableStream::TableStream() : Manager::Stream::Stream() +Manager::TableStream::TableStream() + : Manager::Stream::Stream(TABLE_STREAM), + num_idx_fields(), num_val_fields(), want_record(), tab(), rtype(), + itype(), currDict(), lastDict(), pred(), event() { - stream_type = TABLE_STREAM; - - tab = 0; - itype = 0; - rtype = 0; - - currDict = 0; - lastDict = 0; - - pred = 0; } -Manager::EventStream::EventStream() : Manager::Stream::Stream() +Manager::EventStream::EventStream() + : Manager::Stream::Stream(EVENT_STREAM), + event(), fields(), num_fields(), want_record() { - fields = 0; - stream_type = EVENT_STREAM; } Manager::EventStream::~EventStream() @@ -204,9 +197,9 @@ Manager::TableStream::~TableStream() } } -Manager::AnalysisStream::AnalysisStream() : Manager::Stream::Stream() +Manager::AnalysisStream::AnalysisStream() + : Manager::Stream::Stream(ANALYSIS_STREAM), file_id() { - stream_type = ANALYSIS_STREAM; } Manager::AnalysisStream::~AnalysisStream() diff --git a/src/input/ReaderBackend.cc b/src/input/ReaderBackend.cc index 0aaadc3cdc..abf369dd54 100644 --- a/src/input/ReaderBackend.cc +++ b/src/input/ReaderBackend.cc @@ -163,6 +163,8 @@ ReaderBackend::ReaderBackend(ReaderFrontend* arg_frontend) : MsgThread() disabled = true; // disabled will be set correcty in init. frontend = arg_frontend; info = new ReaderInfo(frontend->Info()); + num_fields = 0; + fields = 0; SetName(frontend->Name()); } diff --git a/src/input/readers/Ascii.cc b/src/input/readers/Ascii.cc index 687d37c96f..8f61e17fc0 100644 --- a/src/input/readers/Ascii.cc +++ b/src/input/readers/Ascii.cc @@ -18,7 +18,7 @@ using threading::Value; using threading::Field; FieldMapping::FieldMapping(const string& arg_name, const TypeTag& arg_type, int arg_position) - : name(arg_name), type(arg_type) + : name(arg_name), type(arg_type), subtype(TYPE_ERROR) { position = arg_position; secondary_position = -1; @@ -49,6 +49,7 @@ FieldMapping FieldMapping::subType() Ascii::Ascii(ReaderFrontend *frontend) : ReaderBackend(frontend) { file = 0; + mtime = 0; separator.assign( (const char*) BifConst::InputAscii::separator->Bytes(), BifConst::InputAscii::separator->Len()); diff --git a/src/input/readers/Benchmark.cc b/src/input/readers/Benchmark.cc index 3e53dfb35f..ec6b382ebb 100644 --- a/src/input/readers/Benchmark.cc +++ b/src/input/readers/Benchmark.cc @@ -18,6 +18,7 @@ using threading::Field; Benchmark::Benchmark(ReaderFrontend *frontend) : ReaderBackend(frontend) { + num_lines = 0; multiplication_factor = double(BifConst::InputBenchmark::factor); autospread = double(BifConst::InputBenchmark::autospread); spread = int(BifConst::InputBenchmark::spread); @@ -25,6 +26,7 @@ Benchmark::Benchmark(ReaderFrontend *frontend) : ReaderBackend(frontend) autospread_time = 0; stopspreadat = int(BifConst::InputBenchmark::stopspreadat); timedspread = double(BifConst::InputBenchmark::timedspread); + heartbeatstarttime = 0; heartbeat_interval = double(BifConst::Threading::heartbeat_interval); ascii = new AsciiFormatter(this, AsciiFormatter::SeparatorInfo()); diff --git a/src/input/readers/Raw.cc b/src/input/readers/Raw.cc index 70c24eed76..1947a907cb 100644 --- a/src/input/readers/Raw.cc +++ b/src/input/readers/Raw.cc @@ -34,6 +34,9 @@ Raw::Raw(ReaderFrontend *frontend) : ReaderBackend(frontend) { file = 0; stderrfile = 0; + execute = false; + firstrun = true; + mtime = 0; forcekill = false; separator.assign( (const char*) BifConst::InputRaw::record_separator->Bytes(), BifConst::InputRaw::record_separator->Len()); diff --git a/src/input/readers/SQLite.cc b/src/input/readers/SQLite.cc index 84b57e2509..abb155e3bc 100644 --- a/src/input/readers/SQLite.cc +++ b/src/input/readers/SQLite.cc @@ -17,7 +17,9 @@ using namespace input::reader; using threading::Value; using threading::Field; -SQLite::SQLite(ReaderFrontend *frontend) : ReaderBackend(frontend) +SQLite::SQLite(ReaderFrontend *frontend) + : ReaderBackend(frontend), + fields(), num_fields(), mode(), started(), query(), db(), st() { set_separator.assign( (const char*) BifConst::LogSQLite::set_separator->Bytes(), diff --git a/src/logging/WriterFrontend.cc b/src/logging/WriterFrontend.cc index 1e254bfc83..09490ce3d1 100644 --- a/src/logging/WriterFrontend.cc +++ b/src/logging/WriterFrontend.cc @@ -112,6 +112,9 @@ WriterFrontend::WriterFrontend(const WriterBackend::WriterInfo& arg_info, EnumVa write_buffer_pos = 0; info = new WriterBackend::WriterInfo(arg_info); + num_fields = 0; + fields = 0; + const char* w = arg_writer->Type()->AsEnumType()->Lookup(arg_writer->InternalInt()); name = copy_string(fmt("%s/%s", arg_info.path, w)); diff --git a/src/logging/writers/DataSeries.cc b/src/logging/writers/DataSeries.cc index 087a7061ea..1073e31a08 100644 --- a/src/logging/writers/DataSeries.cc +++ b/src/logging/writers/DataSeries.cc @@ -233,6 +233,10 @@ DataSeries::DataSeries(WriterFrontend* frontend) : WriterBackend(frontend) ds_set_separator = ","; ascii = new AsciiFormatter(this, AsciiFormatter::SeparatorInfo()); + + compress_type = Extent::compress_none; + log_file = 0; + log_output = 0; } DataSeries::~DataSeries() diff --git a/src/logging/writers/SQLite.cc b/src/logging/writers/SQLite.cc index 81c52fe198..c1614f1aed 100644 --- a/src/logging/writers/SQLite.cc +++ b/src/logging/writers/SQLite.cc @@ -16,7 +16,9 @@ using namespace writer; using threading::Value; using threading::Field; -SQLite::SQLite(WriterFrontend* frontend) : WriterBackend(frontend) +SQLite::SQLite(WriterFrontend* frontend) + : WriterBackend(frontend), + fields(), num_fields(), db(), st() { set_separator.assign( (const char*) BifConst::LogSQLite::set_separator->Bytes(), @@ -33,9 +35,7 @@ SQLite::SQLite(WriterFrontend* frontend) : WriterBackend(frontend) BifConst::LogSQLite::empty_field->Len() ); - db = 0; io = new AsciiFormatter(this, AsciiFormatter::SeparatorInfo(set_separator, unset_field, empty_field)); - st = 0; } SQLite::~SQLite() diff --git a/src/threading/SerialTypes.h b/src/threading/SerialTypes.h index 8a4f46a15c..e056f6c170 100644 --- a/src/threading/SerialTypes.h +++ b/src/threading/SerialTypes.h @@ -81,7 +81,7 @@ private: friend class ::RemoteSerializer; // Force usage of constructor above. - Field() {}; + Field() {} }; /** From 29740ae070e64d6c4de982537bfeb155e5aed0fc Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 28 Sep 2013 11:18:12 -0700 Subject: [PATCH 383/881] Updating submodule(s). [nomail] --- aux/bro-aux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/bro-aux b/aux/bro-aux index de33d520c6..aab939632c 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit de33d520c6f7957aafcce30d86b170306a1c0c49 +Subproject commit aab939632c856dc5de672422b937f2abb14c07fa From eeaf3e9baf25265633da5219fa3a6b0e5d792e57 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 30 Sep 2013 10:49:48 -0500 Subject: [PATCH 384/881] Updating submodule(s). [nomail] --- aux/broccoli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broccoli b/aux/broccoli index e0f34599cb..1aef055802 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit e0f34599cb11f0df37ae1cc036d87c1794b1c0b2 +Subproject commit 1aef055802f842502d701ad152305bcd74bba632 From 945051582182af6fc4e514c9a1f9c4ad3126e3f3 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 1 Oct 2013 13:11:35 -0500 Subject: [PATCH 385/881] Fix getopt() usage. Using 'char' versus 'int' to store the return value is a problem since 'char' varies in signedness depending on platform/implementation (works some places, others not). --- src/builtin-func.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtin-func.l b/src/builtin-func.l index c70b99b6c8..b032fd1d9c 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -275,7 +275,7 @@ void finish_alternative_mode() int main(int argc, char* argv[]) { - char opt; + int opt; while ( (opt = getopt(argc, argv, "p:s")) != -1 ) { From 6c8cbef997d5a4bed987c0a56f48d76b937fbd0e Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 1 Oct 2013 11:31:55 -0700 Subject: [PATCH 386/881] Updating bifcl usage message. --- CHANGES | 6 ++++++ VERSION | 2 +- src/builtin-func.l | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 718df3fff8..f7e68bab3f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,10 @@ +2.2-beta-13 | 2013-10-01 11:31:55 -0700 + + * Updating bifcl usage message. (Robin Sommer) + + * Fix bifcl getopt() usage. (Jon Siwek) + 2.2-beta-8 | 2013-09-28 11:16:29 -0700 * Fix a "make doc" warning. (Daniel Thayer) diff --git a/VERSION b/VERSION index 0432695703..b96a4b7109 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2-beta-8 +2.2-beta-13 diff --git a/src/builtin-func.l b/src/builtin-func.l index b032fd1d9c..3e5f7bce0a 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -180,7 +180,7 @@ FILE* open_output_file(const char* surfix) void usage() { - fprintf(stderr, "usage: bifcl [-p] *.bif\n"); + fprintf(stderr, "usage: bifcl [-p | -s] *.bif\n"); exit(1); } From b59b5ca59b84dd609c37c1bdd2eb6ceb07c908ce Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 1 Oct 2013 11:42:33 -0700 Subject: [PATCH 387/881] Updating submodule(s). [nomail] --- aux/broccoli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broccoli b/aux/broccoli index e0f34599cb..1aef055802 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit e0f34599cb11f0df37ae1cc036d87c1794b1c0b2 +Subproject commit 1aef055802f842502d701ad152305bcd74bba632 From ea766d71bba4e771b6d6320c3867679a73ed77e1 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 1 Oct 2013 16:01:37 -0700 Subject: [PATCH 388/881] add ciphers to cipher_desc table that were already present but apparently forgotten. --- scripts/base/protocols/ssl/consts.bro | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/base/protocols/ssl/consts.bro b/scripts/base/protocols/ssl/consts.bro index 5a7522c159..5e3b9ec019 100644 --- a/scripts/base/protocols/ssl/consts.bro +++ b/scripts/base/protocols/ssl/consts.bro @@ -796,6 +796,11 @@ export { [SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", [SSL_RSA_FIPS_WITH_DES_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA_2", [SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2", + [SSL_RSA_WITH_RC2_CBC_MD5] = "SSL_RSA_WITH_RC2_CBC_MD5", + [SSL_RSA_WITH_IDEA_CBC_MD5] = "SSL_RSA_WITH_IDEA_CBC_MD5", + [SSL_RSA_WITH_DES_CBC_MD5] = "SSL_RSA_WITH_DES_CBC_MD5", + [SSL_RSA_WITH_3DES_EDE_CBC_MD5] = "SSL_RSA_WITH_3DES_EDE_CBC_MD5", + [TLS_EMPTY_RENEGOTIATION_INFO_SCSV] = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", } &default=function(i: count):string { return fmt("unknown-%d", i); }; ## Mapping between the constants and string values for SSL/TLS errors. From 2b87499fd96ea28cf66f999ffd97b94f5596a7b2 Mon Sep 17 00:00:00 2001 From: Bernhard Amann Date: Tue, 1 Oct 2013 16:20:55 -0700 Subject: [PATCH 389/881] rip out x509 code from ssl analyzer. Note that since at the moment the file analyzer does not yet re-populate the info record that means quite a lot of information is simply not available. --- scripts/base/protocols/ssl/main.bro | 43 ------- src/analyzer/protocol/ssl/CMakeLists.txt | 1 - src/analyzer/protocol/ssl/Plugin.cc | 1 - src/analyzer/protocol/ssl/SSL.h | 3 +- src/analyzer/protocol/ssl/events.bif | 73 +----------- src/analyzer/protocol/ssl/functions.bif | 132 --------------------- src/analyzer/protocol/ssl/ssl-analyzer.pac | 57 +-------- 7 files changed, 12 insertions(+), 298 deletions(-) delete mode 100644 src/analyzer/protocol/ssl/functions.bif diff --git a/scripts/base/protocols/ssl/main.bro b/scripts/base/protocols/ssl/main.bro index 2381b356e4..1b487ef4bf 100644 --- a/scripts/base/protocols/ssl/main.bro +++ b/scripts/base/protocols/ssl/main.bro @@ -168,49 +168,6 @@ event ssl_server_hello(c: connection, version: count, possible_ts: time, session c$ssl$cipher = cipher_desc[cipher]; } -event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=5 - { - set_session(c); - - # We aren't doing anything with client certificates yet. - if ( is_orig ) - { - if ( chain_idx == 0 ) - { - # Save the primary cert. - c$ssl$client_cert = der_cert; - - # Also save other certificate information about the primary cert. - c$ssl$client_subject = cert$subject; - c$ssl$client_issuer_subject = cert$issuer; - } - else - { - # Otherwise, add it to the cert validation chain. - c$ssl$client_cert_chain[|c$ssl$client_cert_chain|] = der_cert; - } - } - else - { - if ( chain_idx == 0 ) - { - # Save the primary cert. - c$ssl$cert = der_cert; - - # Also save other certificate information about the primary cert. - c$ssl$subject = cert$subject; - c$ssl$issuer_subject = cert$issuer; - c$ssl$not_valid_before = cert$not_valid_before; - c$ssl$not_valid_after = cert$not_valid_after; - } - else - { - # Otherwise, add it to the cert validation chain. - c$ssl$cert_chain[|c$ssl$cert_chain|] = der_cert; - } - } - } - event ssl_extension(c: connection, is_orig: bool, code: count, val: string) &priority=5 { set_session(c); diff --git a/src/analyzer/protocol/ssl/CMakeLists.txt b/src/analyzer/protocol/ssl/CMakeLists.txt index f1838e5f3b..2591c5dfec 100644 --- a/src/analyzer/protocol/ssl/CMakeLists.txt +++ b/src/analyzer/protocol/ssl/CMakeLists.txt @@ -6,6 +6,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI bro_plugin_begin(Bro SSL) bro_plugin_cc(SSL.cc Plugin.cc) bro_plugin_bif(events.bif) -bro_plugin_bif(functions.bif) bro_plugin_pac(ssl.pac ssl-analyzer.pac ssl-protocol.pac ssl-defs.pac) bro_plugin_end() diff --git a/src/analyzer/protocol/ssl/Plugin.cc b/src/analyzer/protocol/ssl/Plugin.cc index c63be864f8..c1783b357d 100644 --- a/src/analyzer/protocol/ssl/Plugin.cc +++ b/src/analyzer/protocol/ssl/Plugin.cc @@ -7,5 +7,4 @@ BRO_PLUGIN_BEGIN(Bro, SSL) BRO_PLUGIN_DESCRIPTION("SSL analyzer"); BRO_PLUGIN_ANALYZER("SSL", ssl::SSL_Analyzer); BRO_PLUGIN_BIF_FILE(events); - BRO_PLUGIN_BIF_FILE(functions); BRO_PLUGIN_END diff --git a/src/analyzer/protocol/ssl/SSL.h b/src/analyzer/protocol/ssl/SSL.h index 5749066780..f674d64fed 100644 --- a/src/analyzer/protocol/ssl/SSL.h +++ b/src/analyzer/protocol/ssl/SSL.h @@ -27,8 +27,7 @@ public: static bool Available() { return ( ssl_client_hello || ssl_server_hello || - ssl_established || ssl_extension || ssl_alert || - x509_certificate || x509_error ); + ssl_established || ssl_extension || ssl_alert ); } protected: diff --git a/src/analyzer/protocol/ssl/events.bif b/src/analyzer/protocol/ssl/events.bif index b7586561fc..aff5f4798c 100644 --- a/src/analyzer/protocol/ssl/events.bif +++ b/src/analyzer/protocol/ssl/events.bif @@ -22,7 +22,7 @@ ## :bro:id:`SSL::cipher_desc` table maps them to descriptive names. ## ## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +## ssl_session_ticket_handshake event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%); ## Generated for an SSL/TLS server's initial *hello* message. SSL/TLS sessions @@ -52,7 +52,7 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, sessio ## standardized as part of the SSL/TLS protocol. ## ## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +## ssl_session_ticket_handshake event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%); ## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS @@ -71,7 +71,7 @@ event ssl_server_hello%(c: connection, version: count, possible_ts: time, sessio ## val: The raw extension value that was sent in the message. ## ## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +## ssl_session_ticket_handshake event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%); ## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with @@ -86,7 +86,7 @@ event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%); ## c: The connection. ## ## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +## ssl_session_ticket_handshake event ssl_established%(c: connection%); ## Generated for SSL/TLS alert records. SSL/TLS sessions start with an @@ -109,7 +109,7 @@ event ssl_established%(c: connection%); ## defined as part of the SSL/TLS protocol. ## ## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +## ssl_session_ticket_handshake event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%); ## Generated for SSL/TLS handshake messages that are a part of the @@ -130,66 +130,5 @@ event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%); ## ticket: The raw ticket data. ## ## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello -## x509_certificate x509_error x509_extension ssl_alert +## ssl_alert event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count, ticket: string%); - -## Generated for X509 certificates seen in SSL/TLS connections. During the -## initial SSL/TLS handshake, certificates are exchanged in the clear. Bro -## raises this event for each certificate seen (including both a site's primary -## cert, and further certs sent as part of the validation chain). -## -## See `Wikipedia `__ for more information -## about the X.509 format. -## -## c: The connection. -## -## is_orig: True if event is raised for originator side of the connection. -## -## cert: The parsed certificate. -## -## chain_idx: The index in the validation chain that this cert has. Index zero -## indicates an endpoint's primary cert, while higher indices -## indicate the place in the validation chain (which has length -## *chain_len*). -## -## chain_len: The total length of the validation chain that this cert is part -## of. -## -## der_cert: The complete cert encoded in `DER -## `__ -## format. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension -## ssl_server_hello x509_error x509_extension x509_verify -event x509_certificate%(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string%); - -## Generated for X509 extensions seen in a certificate. -## -## See `Wikipedia `__ for more information -## about the X.509 format. -## -## c: The connection. -## -## is_orig: True if event is raised for originator side of the connection. -## -## data: The raw data associated with the extension. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension -## ssl_server_hello x509_certificate x509_error x509_verify -#event x509_extension%(c: connection, is_orig: bool, data: string%); - -## Generated when errors occur during parsing an X509 certificate. -## -## See `Wikipedia `__ for more information -## about the X.509 format. -## -## c: The connection. -## -## is_orig: True if event is raised for originator side of the connection. -## -## err: An error code describing what went wrong. :bro:id:`SSL::x509_errors` -## maps error codes to a textual description. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension -## ssl_server_hello x509_certificate x509_extension x509_err2str x509_verify -event x509_error%(c: connection, is_orig: bool, err: count%); diff --git a/src/analyzer/protocol/ssl/functions.bif b/src/analyzer/protocol/ssl/functions.bif deleted file mode 100644 index f2d4861007..0000000000 --- a/src/analyzer/protocol/ssl/functions.bif +++ /dev/null @@ -1,132 +0,0 @@ - -%%{ -#include -#include -#include - -// This is the indexed map of X509 certificate stores. -static map x509_stores; - -// ### NOTE: while d2i_X509 does not take a const u_char** pointer, -// here we assume d2i_X509 does not write to , so it is safe to -// convert data to a non-const pointer. Could some X509 guru verify -// this? - -X509* d2i_X509_(X509** px, const u_char** in, int len) - { -#ifdef OPENSSL_D2I_X509_USES_CONST_CHAR - return d2i_X509(px, in, len); -#else - return d2i_X509(px, (u_char**)in, len); -#endif - } - -%%} - - -## Verifies a certificate. -## -## der_cert: The X.509 certificate in DER format. -## -## cert_stack: Specifies a certificate chain to validate against, with index 0 -## typically being the root CA. Bro uses the Mozilla root CA list -## by default. -## -## root_certs: A list of additional root certificates that extends -## *cert_stack*. -## -## Returns: A status code of the verification which can be converted into an -## ASCII string via :bro:id:`x509_err2str`. -## -## .. bro:see:: x509_err2str -function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: table_string_of_string%): count - %{ - X509_STORE* ctx = 0; - int i = 0; - - // If this certificate store was built previously, just reuse the old one. - if ( x509_stores.count(root_certs) > 0 ) - ctx = x509_stores[root_certs]; - - if ( ! ctx ) // lookup to see if we have this one built already! - { - ctx = X509_STORE_new(); - TableVal* root_certs2 = root_certs->AsTableVal(); - ListVal* idxs = root_certs2->ConvertToPureList(); - - // Build the validation store - for ( i = 0; i < idxs->Length(); ++i ) - { - Val* key = idxs->Index(i); - StringVal *sv = root_certs2->Lookup(key)->AsStringVal(); - const uint8* data = sv->Bytes(); - X509* x = d2i_X509_(NULL, &data, sv->Len()); - if ( ! x ) - { - builtin_error(fmt("Root CA error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); - return new Val((uint64) ERR_get_error(), TYPE_COUNT); - } - X509_STORE_add_cert(ctx, x); - } - delete idxs; - - // Save the newly constructed certificate store into the cacheing map. - x509_stores[root_certs] = ctx; - } - - const uint8 *cert_data = der_cert->Bytes(); - X509* cert = d2i_X509_(NULL, &cert_data, der_cert->Len()); - if ( ! cert ) - { - builtin_error(fmt("Certificate error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); - return new Val((uint64) ERR_get_error(), TYPE_COUNT); - } - - STACK_OF(X509)* untrusted_certs = sk_X509_new_null(); - if ( ! untrusted_certs ) - { - builtin_error(fmt("Untrusted certificate stack initialization error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); - return new Val((uint64) ERR_get_error(), TYPE_COUNT); - } - - VectorVal *cert_stack_vec = cert_stack->AsVectorVal(); - for ( i = 0; i < (int) cert_stack_vec->Size(); ++i ) - { - StringVal *sv = cert_stack_vec->Lookup(i)->AsStringVal(); - const uint8 *data = sv->Bytes(); - X509* x = d2i_X509_(NULL, &data, sv->Len()); - if ( ! x ) - { - X509_free(cert); - sk_X509_pop_free(untrusted_certs, X509_free); - builtin_error(fmt("Untrusted certificate stack creation error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); - return new Val((uint64) ERR_get_error(), TYPE_COUNT); - } - sk_X509_push(untrusted_certs, x); - } - - X509_STORE_CTX csc; - X509_STORE_CTX_init(&csc, ctx, cert, untrusted_certs); - X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time); - - int result = X509_verify_cert(&csc); - X509_STORE_CTX_cleanup(&csc); - - if ( untrusted_certs ) - sk_X509_pop_free(untrusted_certs, X509_free); - X509_free(cert); - - return new Val((uint64) csc.error, TYPE_COUNT); - %} - -## Converts a certificate verification error code into an ASCII string. -## -## err_num: The error code. -## -## Returns: A string representation of *err_num*. -## -## .. bro:see:: x509_verify -function x509_err2str%(err_num: count%): string - %{ - return new StringVal(X509_verify_cert_error_string(err_num)); - %} diff --git a/src/analyzer/protocol/ssl/ssl-analyzer.pac b/src/analyzer/protocol/ssl/ssl-analyzer.pac index 43e2ac5c73..4bf1e27d64 100644 --- a/src/analyzer/protocol/ssl/ssl-analyzer.pac +++ b/src/analyzer/protocol/ssl/ssl-analyzer.pac @@ -8,9 +8,6 @@ #include "util.h" -#include -#include - #include "file_analysis/Manager.h" %} @@ -247,57 +244,13 @@ refine connection SSL_Conn += { if ( certificates->size() == 0 ) return true; - if ( x509_certificate ) + for ( unsigned int i = 0; i < certificates->size(); ++i ) { - STACK_OF(X509)* untrusted_certs = 0; + const bytestring& cert = (*certificates)[i]; - for ( unsigned int i = 0; i < certificates->size(); ++i ) - { - const bytestring& cert = (*certificates)[i]; - const uint8* data = cert.data(); - - file_mgr->DataIn(reinterpret_cast(data), cert.length(), - bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn(), false); - file_mgr->EndOfFile(bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn()); - - X509* pTemp = d2i_X509_binpac(NULL, &data, cert.length()); - if ( ! pTemp ) - { - BifEvent::generate_x509_error(bro_analyzer(), bro_analyzer()->Conn(), - ${rec.is_orig}, ERR_get_error()); - return false; - } - - - RecordVal* pX509Cert = new RecordVal(x509_type); - char tmp[256]; - BIO *bio = BIO_new(BIO_s_mem()); - - pX509Cert->Assign(0, new Val((uint64) X509_get_version(pTemp), TYPE_COUNT)); - i2a_ASN1_INTEGER(bio, X509_get_serialNumber(pTemp)); - int len = BIO_read(bio, &(*tmp), sizeof tmp); - pX509Cert->Assign(1, new StringVal(len, tmp)); - - X509_NAME_print_ex(bio, X509_get_subject_name(pTemp), 0, XN_FLAG_RFC2253); - len = BIO_gets(bio, &(*tmp), sizeof tmp); - pX509Cert->Assign(2, new StringVal(len, tmp)); - X509_NAME_print_ex(bio, X509_get_issuer_name(pTemp), 0, XN_FLAG_RFC2253); - len = BIO_gets(bio, &(*tmp), sizeof tmp); - pX509Cert->Assign(3, new StringVal(len, tmp)); - BIO_free(bio); - - pX509Cert->Assign(4, new Val(get_time_from_asn1(X509_get_notBefore(pTemp)), TYPE_TIME)); - pX509Cert->Assign(5, new Val(get_time_from_asn1(X509_get_notAfter(pTemp)), TYPE_TIME)); - StringVal* der_cert = new StringVal(cert.length(), (const char*) cert.data()); - - BifEvent::generate_x509_certificate(bro_analyzer(), bro_analyzer()->Conn(), - ${rec.is_orig}, - pX509Cert, - i, certificates->size(), - der_cert); - - X509_free(pTemp); - } + file_mgr->DataIn(reinterpret_cast(cert.data()), cert.length(), + bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn(), ${rec.is_orig}); + file_mgr->EndOfFile(bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn()); } return true; %} From aa08d359cdbceac061cc03c04baf9efffc665ec5 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 2 Oct 2013 11:05:58 -0700 Subject: [PATCH 390/881] Updating submodule(s). [nomail] --- aux/broctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broctl b/aux/broctl index bec9c66064..a43f3d8fc7 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit bec9c6606414438655a3298db76e1e43464c8d44 +Subproject commit a43f3d8fc7868ba2666e37ed53d012241e86bdc5 From 6734260136804560ba08b88a7a2317031eb2f0bd Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 2 Oct 2013 11:32:03 -0700 Subject: [PATCH 391/881] Fixing merge relict. --- src/analyzer/protocol/rpc/RPC.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyzer/protocol/rpc/RPC.cc b/src/analyzer/protocol/rpc/RPC.cc index c1736a8384..fd76bf551b 100644 --- a/src/analyzer/protocol/rpc/RPC.cc +++ b/src/analyzer/protocol/rpc/RPC.cc @@ -680,7 +680,7 @@ void Contents_RPC::DeliverStream(int len, const u_char* data, bool orig) RPC_Analyzer::RPC_Analyzer(const char* name, Connection* conn, RPC_Interpreter* arg_interp) : tcp::TCP_ApplicationAnalyzer(name, conn), - nterp(arg_interp), orig_rpc(), resp_rpc() + interp(arg_interp), orig_rpc(), resp_rpc() { if ( Conn()->ConnTransport() == TRANSPORT_UDP ) ADD_ANALYZER_TIMER(&RPC_Analyzer::ExpireTimer, From 5a857a6dfc809a23237f983d8e19c559dc382331 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 3 Oct 2013 10:42:04 -0500 Subject: [PATCH 392/881] Initial skeleton of new Broxygen infrastructure. Doesn't generate any docs, but it's hooked in to all places needed to gather the necessary stuff w/ significantly less coupling than before. The gathering now always occurs unconditionally to make documentation available at runtime and a command line switch (-X) only toggles whether to output docs to disk (reST format). Should also improve the treatment of type name aliasing which wasn't a big problem in practice before, but I think it's more correct now: there's now a distinct BroType for each alias, but extensible types (record/enum) will automatically update the types for aliases on redef. Other misc refactoring of note: - Removed a redundant/unused way of declaring event types. - Changed type serialization format/process to preserve type name information and remove compatibility code (since broccoli will have be updated anyway). --- src/BroDoc.cc | 2 + src/Brofiler.h | 2 + src/CMakeLists.txt | 2 + src/Expr.cc | 1 + src/ID.cc | 6 +- src/Serializer.h | 2 +- src/Type.cc | 260 +++++++-------------- src/Type.h | 68 ++---- src/Var.cc | 67 ++---- src/Var.h | 2 +- src/broxygen/Manager.cc | 88 ++++++++ src/broxygen/Manager.h | 43 ++++ src/main.cc | 41 ++-- src/parse.y | 411 ++++++++-------------------------- src/plugin/ComponentManager.h | 4 +- src/scan.l | 221 +++--------------- src/util.cc | 8 +- src/util.h | 3 +- 18 files changed, 393 insertions(+), 838 deletions(-) create mode 100644 src/broxygen/Manager.cc create mode 100644 src/broxygen/Manager.h diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 6953680df0..5733c586bf 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -556,6 +556,7 @@ static void WritePluginBifItems(FILE* f, const plugin::Plugin* p, static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module) { + /* TODO string tag_id= module + "::Tag"; e = new CommentedEnumType(e); e->SetTypeID(copy_string(tag_id.c_str())); @@ -570,6 +571,7 @@ static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module) BroDocObj bdo(dummy_id, r, true); bdo.WriteReST(f); + */ } static bool ComponentsMatch(const plugin::Plugin* p, plugin::component::Type t, diff --git a/src/Brofiler.h b/src/Brofiler.h index 22e5808bf6..88ce434070 100644 --- a/src/Brofiler.h +++ b/src/Brofiler.h @@ -78,4 +78,6 @@ private: }; }; +extern Brofiler brofiler; + #endif /* BROFILER_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c881cc4df1..4145984f3b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -370,6 +370,8 @@ set(bro_SRCS plugin/Plugin.cc plugin/Macros.h + broxygen/Manager.cc + nb_dns.c digest.h ) diff --git a/src/Expr.cc b/src/Expr.cc index 0eaa7ce918..303b3cf5c7 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -5111,6 +5111,7 @@ BroType* ListExpr::InitType() const types->append(td); } + return new RecordType(types); } diff --git a/src/ID.cc b/src/ID.cc index a6e592146b..ed561016ff 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -619,6 +619,7 @@ void ID::DescribeExtended(ODesc* d) const void ID::DescribeReSTShort(ODesc* d) const { + /* TODO if ( is_type ) d->Add(":bro:type:`"); else @@ -668,6 +669,7 @@ void ID::DescribeReSTShort(ODesc* d) const d->SP(); attrs->DescribeReST(d); } + */ } void ID::DescribeReST(ODesc* d, bool is_role) const @@ -697,10 +699,10 @@ void ID::DescribeReST(ODesc* d, bool is_role) const { d->Add(":Type: "); - if ( ! is_type && type->GetTypeID() ) + if ( ! is_type && ! type->GetName().empty() ) { d->Add(":bro:type:`"); - d->Add(type->GetTypeID()); + d->Add(type->GetName()); d->Add("`"); } else diff --git a/src/Serializer.h b/src/Serializer.h index 72e0723880..c1af1a2c4f 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -125,7 +125,7 @@ protected: // This will be increased whenever there is an incompatible change // in the data format. - static const uint32 DATA_FORMAT_VERSION = 23; + static const uint32 DATA_FORMAT_VERSION = 24; ChunkedIO* io; diff --git a/src/Type.cc b/src/Type.cc index 2b9faa8018..a659dc473b 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -8,13 +8,12 @@ #include "Scope.h" #include "Serializer.h" #include "Reporter.h" +#include "broxygen/Manager.h" #include #include #include -extern int generate_documentation; - // Note: This function must be thread-safe. const char* type_name(TypeTag t) { @@ -47,7 +46,6 @@ BroType::BroType(TypeTag t, bool arg_base_type) tag = t; is_network_order = 0; base_type = arg_base_type; - type_id = 0; switch ( tag ) { case TYPE_VOID: @@ -110,10 +108,26 @@ BroType::BroType(TypeTag t, bool arg_base_type) } -BroType::~BroType() +BroType* BroType::Clone() const { - if ( type_id ) - delete [] type_id; + SerializationFormat* form = new BinarySerializationFormat(); + form->StartWrite(); + CloneSerializer ss(form); + SerialInfo sinfo(&ss); + sinfo.cache = false; + + this->Serialize(&sinfo); + char* data; + uint32 len = form->EndWrite(&data); + form->StartRead(data, len); + + UnserialInfo uinfo(&ss); + uinfo.cache = false; + BroType* rval = this->Unserialize(&uinfo); + + delete [] data; + + return rval; } int BroType::MatchesIndex(ListExpr*& index) const @@ -222,9 +236,21 @@ BroType* BroType::Unserialize(UnserialInfo* info, TypeTag want) if ( ! t ) return 0; - // For base types, we return our current instance - // if not in "documentation mode". - if ( t->base_type && ! generate_documentation ) + if ( ! t->name.empty() ) + { + // Avoid creating a new type if it's known by name. + // Also avoids loss of base type name alias (from condition below). + ID* id = global_scope()->Lookup(t->name.c_str()); + BroType* t2 = id ? id->AsType() : 0; + + if ( t2 ) + { + Unref(t); + return t2->Ref(); + } + } + + if ( t->base_type ) { BroType* t2 = ::base_type(TypeTag(t->tag)); Unref(t); @@ -247,21 +273,10 @@ bool BroType::DoSerialize(SerialInfo* info) const if ( ! (SERIALIZE(char(tag)) && SERIALIZE(char(internal_tag))) ) return false; - if ( ! (SERIALIZE(is_network_order) && SERIALIZE(base_type) && - // Serialize the former "bool is_global_attributes_type" for - // backwards compatibility. - SERIALIZE(false)) ) + if ( ! (SERIALIZE(is_network_order) && SERIALIZE(base_type)) ) return false; - // Likewise, serialize the former optional "RecordType* attributes_type" - // for backwards compatibility. - void* null = NULL; - SERIALIZE(null); - - if ( generate_documentation ) - { - SERIALIZE_OPTIONAL_STR(type_id); - } + SERIALIZE_STR(name.c_str(), name.size()); info->s->WriteCloseTag("Type"); @@ -279,24 +294,15 @@ bool BroType::DoUnserialize(UnserialInfo* info) tag = (TypeTag) c1; internal_tag = (InternalTypeTag) c2; - bool not_used; - - if ( ! (UNSERIALIZE(&is_network_order) && UNSERIALIZE(&base_type) - // Unerialize the former "bool is_global_attributes_type" for - // backwards compatibility. - && UNSERIALIZE(¬_used)) ) + if ( ! (UNSERIALIZE(&is_network_order) && UNSERIALIZE(&base_type)) ) return 0; - BroType* not_used_either; + const char* n; + if ( ! UNSERIALIZE_STR(&n, 0) ) + return false; - // Likewise, unserialize the former optional "RecordType* - // attributes_type" for backwards compatibility. - UNSERIALIZE_OPTIONAL(not_used_either, BroType::Unserialize(info, TYPE_RECORD)); - - if ( generate_documentation ) - { - UNSERIALIZE_OPTIONAL_STR(type_id); - } + name = n; + delete [] n; return true; } @@ -470,10 +476,10 @@ void IndexType::DescribeReST(ODesc* d) const const BroType* t = (*IndexTypes())[i]; - if ( t->GetTypeID() ) + if ( ! t->GetName().empty() ) { d->Add(":bro:type:`"); - d->Add(t->GetTypeID()); + d->Add(t->GetName()); d->Add("`"); } else @@ -486,10 +492,10 @@ void IndexType::DescribeReST(ODesc* d) const { d->Add(" of "); - if ( yield_type->GetTypeID() ) + if ( ! yield_type->GetName().empty() ) { d->Add(":bro:type:`"); - d->Add(yield_type->GetTypeID()); + d->Add(yield_type->GetName()); d->Add("`"); } else @@ -781,10 +787,10 @@ void FuncType::DescribeReST(ODesc* d) const { d->AddSP(" :"); - if ( yield->GetTypeID() ) + if ( ! yield->GetName().empty() ) { d->Add(":bro:type:`"); - d->Add(yield->GetTypeID()); + d->Add(yield->GetName()); d->Add("`"); } else @@ -873,6 +879,17 @@ TypeDecl::TypeDecl(BroType* t, const char* i, attr_list* arg_attrs, bool in_reco id = i; } +TypeDecl::TypeDecl(const TypeDecl& other) + { + type = other.type->Ref(); + attrs = other.attrs; + + if ( attrs ) + ::Ref(attrs); + + id = copy_string(other.id); + } + TypeDecl::~TypeDecl() { Unref(type); @@ -914,10 +931,10 @@ void TypeDecl::DescribeReST(ODesc* d) const d->Add(id); d->Add(": "); - if ( type->GetTypeID() ) + if ( ! type->GetName().empty() ) { d->Add(":bro:type:`"); - d->Add(type->GetTypeID()); + d->Add(type->GetName()); d->Add("`"); } else @@ -930,37 +947,6 @@ void TypeDecl::DescribeReST(ODesc* d) const } } -CommentedTypeDecl::CommentedTypeDecl(BroType* t, const char* i, - attr_list* attrs, bool in_record, std::list* cmnt_list) - : TypeDecl(t, i, attrs, in_record) - { - comments = cmnt_list; - } - -CommentedTypeDecl::~CommentedTypeDecl() - { - if ( comments ) delete comments; - } - -void CommentedTypeDecl::DescribeReST(ODesc* d) const - { - TypeDecl::DescribeReST(d); - - if ( comments ) - { - d->PushIndent(); - std::list::const_iterator i; - - for ( i = comments->begin(); i != comments->end(); ++i) - { - if ( i != comments->begin() ) d->NL(); - d->Add(i->c_str()); - } - - d->PopIndentNoNL(); - } - } - RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD) { types = arg_types; @@ -1328,38 +1314,12 @@ bool OpaqueType::DoUnserialize(UnserialInfo* info) return true; } -EnumType::EnumType(const string& arg_name) -: BroType(TYPE_ENUM) - { - name = arg_name; - counter = 0; - } - -EnumType::EnumType(EnumType* e) -: BroType(TYPE_ENUM) - { - name = e->name; - counter = e->counter; - - for ( NameMap::iterator it = e->names.begin(); it != e->names.end(); ++it ) - names[copy_string(it->first)] = it->second; - } - EnumType::~EnumType() { for ( NameMap::iterator iter = names.begin(); iter != names.end(); ++iter ) delete [] iter->first; } -CommentedEnumType::~CommentedEnumType() - { - for ( CommentMap::iterator iter = comments.begin(); iter != comments.end(); ++iter ) - { - delete [] iter->first; - delete iter->second; - } - } - // Note, we use reporter->Error() here (not Error()) to include the current script // location in the error message, rather than the one where the type was // originally defined. @@ -1372,7 +1332,7 @@ void EnumType::AddName(const string& module_name, const char* name, bool is_expo SetError(); return; } - AddNameInternal(module_name, name, counter, is_export); + CheckAndAddName(module_name, name, counter, is_export); counter++; } @@ -1386,32 +1346,12 @@ void EnumType::AddName(const string& module_name, const char* name, bro_int_t va return; } counter = -1; - AddNameInternal(module_name, name, val, is_export); + CheckAndAddName(module_name, name, val, is_export); } -void CommentedEnumType::AddComment(const string& module_name, const char* name, - std::list* new_comments) +void EnumType::CheckAndAddName(const string& module_name, const char* name, + bro_int_t val, bool is_export) { - if ( ! new_comments ) - return; - - string fullname = make_full_var_name(module_name.c_str(), name); - - CommentMap::iterator it = comments.find(fullname.c_str()); - - if ( it == comments.end() ) - comments[copy_string(fullname.c_str())] = new_comments; - else - { - list* prev_comments = comments[fullname.c_str()]; - prev_comments->splice(prev_comments->end(), *new_comments); - delete new_comments; - } - } - -void EnumType::AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export) - { - ID *id; if ( Lookup(val) ) { reporter->Error("enumerator value in enumerated type definition already exists"); @@ -1419,12 +1359,14 @@ void EnumType::AddNameInternal(const string& module_name, const char* name, bro_ return; } - id = lookup_ID(name, module_name.c_str()); + ID* id = lookup_ID(name, module_name.c_str()); + if ( ! id ) { id = install_ID(name, module_name.c_str(), true, is_export); id->SetType(this->Ref()); id->SetEnumConst(); + broxygen_mgr->Identifier(id); } else { @@ -1433,11 +1375,19 @@ void EnumType::AddNameInternal(const string& module_name, const char* name, bro_ return; } - string fullname = make_full_var_name(module_name.c_str(), name); - names[copy_string(fullname.c_str())] = val; + AddNameInternal(module_name, name, val, is_export); + + set types = type_aliases[GetName()]; + set::const_iterator it; + + for ( it = types.begin(); it != types.end(); ++it ) + if ( *it != this ) + (*it)->AsEnumType()->AddNameInternal(module_name, name, val, + is_export); } -void CommentedEnumType::AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export) +void EnumType::AddNameInternal(const string& module_name, const char* name, + bro_int_t val, bool is_export) { string fullname = make_full_var_name(module_name.c_str(), name); names[copy_string(fullname.c_str())] = val; @@ -1466,54 +1416,8 @@ const char* EnumType::Lookup(bro_int_t value) void EnumType::DescribeReST(ODesc* d) const { - d->Add(":bro:type:`"); - d->Add(name.c_str()); - d->Add("`"); - } - -void CommentedEnumType::DescribeReST(ODesc* d) const - { - // create temporary, reverse name map so that enums can be documented - // in ascending order of their actual integral value instead of by name - typedef std::map< bro_int_t, const char* > RevNameMap; - RevNameMap rev; - for ( NameMap::const_iterator it = names.begin(); it != names.end(); ++it ) - rev[it->second] = it->first; - - d->Add(":bro:type:`"); - d->Add(type_name(Tag())); - d->Add("`"); - d->PushIndent(); - d->NL(); - - for ( RevNameMap::const_iterator it = rev.begin(); it != rev.end(); ++it ) - { - if ( it != rev.begin() ) - { - d->NL(); - d->NL(); - } - - d->Add(".. bro:enum:: "); - d->AddSP(it->second); - d->Add(GetTypeID()); - - CommentMap::const_iterator cmnt_it = comments.find(it->second); - if ( cmnt_it != comments.end() ) - { - d->PushIndent(); - d->NL(); - std::list::const_iterator i; - const std::list* cmnt_list = cmnt_it->second; - for ( i = cmnt_list->begin(); i != cmnt_list->end(); ++i) - { - if ( i != cmnt_list->begin() ) d->NL(); - d->Add(i->c_str()); - } - d->PopIndentNoNL(); - } - } - d->PopIndentNoNL(); + // TODO: this probably goes away + d->Add(":bro:type:`enum`"); } IMPLEMENT_SERIAL(EnumType, SER_ENUM_TYPE); diff --git a/src/Type.h b/src/Type.h index a6163d5152..be27426546 100644 --- a/src/Type.h +++ b/src/Type.h @@ -4,7 +4,7 @@ #define type_h #include -#include +#include #include #include "Obj.h" @@ -73,7 +73,9 @@ const int MATCHES_INDEX_VECTOR = 2; class BroType : public BroObj { public: BroType(TypeTag tag, bool base_type = false); - ~BroType(); + ~BroType() { } + + BroType* Clone() const; TypeTag Tag() const { return tag; } InternalTypeTag InternalType() const { return internal_tag; } @@ -232,11 +234,11 @@ public: bool Serialize(SerialInfo* info) const; static BroType* Unserialize(UnserialInfo* info, TypeTag want = TYPE_ANY); - void SetTypeID(const char* id) { type_id = id; } - const char* GetTypeID() const { return type_id; } + void SetName(const string& arg_name) { name = arg_name; } + string GetName() const { return name; } protected: - BroType() { type_id = 0; } + BroType() { } void SetError(); @@ -247,10 +249,7 @@ private: InternalTypeTag internal_tag; bool is_network_order; bool base_type; - - // This type_id field is only used by the documentation framework to - // track the names of declared types. - const char* type_id; + string name; }; class TypeList : public BroType { @@ -408,6 +407,7 @@ protected: class TypeDecl { public: TypeDecl(BroType* t, const char* i, attr_list* attrs = 0, bool in_record = false); + TypeDecl(const TypeDecl& other); virtual ~TypeDecl(); const Attr* FindAttr(attr_tag a) const @@ -423,17 +423,6 @@ public: const char* id; }; -class CommentedTypeDecl : public TypeDecl { -public: - CommentedTypeDecl(BroType* t, const char* i, attr_list* attrs = 0, - bool in_record = false, std::list* cmnt_list = 0); - virtual ~CommentedTypeDecl(); - - void DescribeReST(ODesc* d) const; - - std::list* comments; -}; - class RecordType : public BroType { public: RecordType(type_decl_list* types); @@ -522,8 +511,7 @@ protected: class EnumType : public BroType { public: - EnumType(const string& arg_name); - EnumType(EnumType* e); + EnumType() : BroType(TYPE_ENUM) { counter = 0; } ~EnumType(); // The value of this name is next internal counter value, starting @@ -539,17 +527,17 @@ public: bro_int_t Lookup(const string& module_name, const char* name); const char* Lookup(bro_int_t value); // Returns 0 if not found - string Name() const { return name; } - void DescribeReST(ODesc* d) const; protected: - EnumType() { counter = 0; } DECLARE_SERIAL(EnumType) - virtual void AddNameInternal(const string& module_name, + void AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export); + void CheckAndAddName(const string& module_name, + const char* name, bro_int_t val, bool is_export); + typedef std::map< const char*, bro_int_t, ltstr > NameMap; NameMap names; @@ -560,31 +548,6 @@ protected: // as a flag to prevent mixing of auto-increment and explicit // enumerator specifications. bro_int_t counter; - - // The name of the enum type is stored for documentation purposes. - string name; -}; - -class CommentedEnumType: public EnumType { -public: - CommentedEnumType(const string& arg_name) : EnumType(arg_name) {} - CommentedEnumType(EnumType* e) : EnumType(e) {} - ~CommentedEnumType(); - - void DescribeReST(ODesc* d) const; - void AddComment(const string& module_name, const char* name, - std::list* comments); - -protected: - // This overriden method does not install the given ID name into a - // scope and it also does not do any kind of checking that the - // provided name already exists. - void AddNameInternal(const string& module_name, const char* name, - bro_int_t val, bool is_export); - - // Comments are only filled when in "documentation mode". - typedef std::map< const char*, std::list*, ltstr > CommentMap; - CommentMap comments; }; class VectorType : public BroType { @@ -609,6 +572,9 @@ protected: BroType* yield_type; }; +typedef std::map > TypeAliasMap; +extern TypeAliasMap type_aliases; + extern OpaqueType* md5_type; extern OpaqueType* sha1_type; extern OpaqueType* sha256_type; diff --git a/src/Var.cc b/src/Var.cc index d384fedc74..821c9e207b 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -10,8 +10,6 @@ #include "RemoteSerializer.h" #include "EventRegistry.h" -extern int generate_documentation; - static Val* init_val(Expr* init, const BroType* t, Val* aggr) { return init->InitVal(t, aggr); @@ -261,61 +259,26 @@ extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val) return new AssignExpr(new NameExpr(id), init, 0, val); } -void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */) +void add_type(ID* id, BroType* t, attr_list* attr) { - BroType* tnew = t; + string new_type_name(id->Name()); + string old_type_name(t->GetName()); + BroType* tnew = 0; - // In "documentation mode", we'd like to to be able to associate - // an identifier name with a declared type. Dealing with declared - // types that are "aliases" to a builtin type requires that the BroType - // is cloned before setting the identifier name that resolves to it. - // And still this is not enough to document cases where the declared type - // is an alias for another declared type -- but that's not a natural/common - // practice. If documenting that corner case is desired, one way - // is to add an ID* to class ID that tracks aliases and set it here if - // t->GetTypeID() is true. - if ( generate_documentation ) - { - switch ( t->Tag() ) { - // Only "shallow" copy types that may contain records because - // we want to be able to see additions to the original record type's - // list of fields - case TYPE_RECORD: - tnew = new RecordType(t->AsRecordType()->Types()); - break; - case TYPE_TABLE: - tnew = new TableType(t->AsTableType()->Indices(), - t->AsTableType()->YieldType()); - break; - case TYPE_VECTOR: - tnew = new VectorType(t->AsVectorType()->YieldType()); - break; - case TYPE_FUNC: - tnew = new FuncType(t->AsFuncType()->Args(), - t->AsFuncType()->YieldType(), - t->AsFuncType()->Flavor()); - break; - default: - SerializationFormat* form = new BinarySerializationFormat(); - form->StartWrite(); - CloneSerializer ss(form); - SerialInfo sinfo(&ss); - sinfo.cache = false; + if ( (t->Tag() == TYPE_RECORD || t->Tag() == TYPE_ENUM) && + ! old_type_name.empty() ) + // Clone the type to preserve type name aliasing. + tnew = t->Clone(); + else + // An extensible types (record/enum) being declared for first time. + tnew = t; - t->Serialize(&sinfo); - char* data; - uint32 len = form->EndWrite(&data); - form->StartRead(data, len); + type_aliases[new_type_name].insert(tnew); - UnserialInfo uinfo(&ss); - uinfo.cache = false; - tnew = t->Unserialize(&uinfo); + if ( new_type_name != old_type_name && ! old_type_name.empty() ) + type_aliases[old_type_name].insert(tnew); - delete [] data; - } - - tnew->SetTypeID(copy_string(id->Name())); - } + tnew->SetName(id->Name()); id->SetType(tnew); id->MakeType(); diff --git a/src/Var.h b/src/Var.h index 8b9866ed2d..bcdd45dad2 100644 --- a/src/Var.h +++ b/src/Var.h @@ -18,7 +18,7 @@ extern Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init, attr_list* attr, decl_type dt); extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val = 0); -extern void add_type(ID* id, BroType* t, attr_list* attr, int is_event); +extern void add_type(ID* id, BroType* t, attr_list* attr); extern void begin_func(ID* id, const char* module_name, function_flavor flavor, int is_redef, FuncType* t); diff --git a/src/broxygen/Manager.cc b/src/broxygen/Manager.cc new file mode 100644 index 0000000000..30c9008787 --- /dev/null +++ b/src/broxygen/Manager.cc @@ -0,0 +1,88 @@ +#include "Manager.h" + +using namespace broxygen; + +Manager::Manager(const std::string& config) + { + // TODO + } + +void Manager::GenerateDocs() const + { + // TODO + + // may be a no-op if no config + + // does the old canon_doc_func_param stuff happen here now on the fly + // for functions we're about to document? + } + +void Manager::File(const std::string& path) + { + // TODO + // determine bropath subpath + // can be a file or directory? + } + +void Manager::ScriptDependency(const std::string& path, const std::string& dep) + { + // TODO: + // need anything from BroDoc::AddImport? + // warn about unconsumed comments (and discard any) + } + +void Manager::ModuleUsage(const std::string& path, const std::string& module) + { + // TODO lookup script and add module to a set + } + +void Manager::Identifier(const ID *id) + { + // TODO: lookup script to associate w/ by GetLocationInfo()->filename + // do different things depending on Type? (eg function flavor versus state) + // do different things based on redef attr + const ? + // consume any buffered comments and associate w/ id + // deal w/ type aliasing + // special enum or record handing? + // if it's a function we may already have added it (decl versus impl) + } + +void Manager::RecordField(const ID *id, const TypeDecl *field, + const std::string& path) + { + // TODO: consume comments + // redef is implicit -- script path of field will differ from ID/type's + } + +void Manager::Redef(const ID* id, const string& path) + { + // TODO: lookup script w/ 'path' to associate the id in as redef'd + // consume any buffered comments and associate w/ redef'd id + // can sort notices here + } + +void Manager::SummaryComment(const std::string& script, + const std::string& comment) + { + // TODO + // canon_doc_comment ? + } + +void Manager::PreComment(const std::string& comment) + { + // TODO + // canon_doc_comment + } + +void Manager::PostComment(const std::string& comment) + { + // TODO this gets associated with the last thing registered + // canon_doc_comment + } + + +// TODO: "canon_doc_comment" means treat "##Text" and "## Text" the same +// so that a single space doesn't generate an indentation level. + + +// TODO: creating proto/file analyzer docs diff --git a/src/broxygen/Manager.h b/src/broxygen/Manager.h new file mode 100644 index 0000000000..d0665c307d --- /dev/null +++ b/src/broxygen/Manager.h @@ -0,0 +1,43 @@ +#ifndef BROXYGEN_MANAGER_H +#define BROXYGEN_MANAGER_H + +#include + +#include "ID.h" +#include "Type.h" + +namespace broxygen { + +class Manager { + +public: + + Manager(const std::string& config); + + void GenerateDocs() const; + + void File(const std::string& path); + + void ScriptDependency(const std::string& path, const std::string& dep); + + void ModuleUsage(const std::string& path, const std::string& module); + + void Identifier(const ID* id); + + void RecordField(const ID* id, const TypeDecl* field, + const std::string& path); + + void Redef(const ID* id, const std::string& path); + + void SummaryComment(const std::string& path, const std::string& comment); + + void PreComment(const std::string& comment); + + void PostComment(const std::string& comment); +}; + +} // namespace broxygen + +extern broxygen::Manager* broxygen_mgr; + +#endif diff --git a/src/main.cc b/src/main.cc index 313e1a40b0..bdb6499445 100644 --- a/src/main.cc +++ b/src/main.cc @@ -61,8 +61,8 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void); #include "analyzer/Manager.h" #include "analyzer/Tag.h" #include "plugin/Manager.h" - #include "file_analysis/Manager.h" +#include "broxygen/Manager.h" #include "binpac_bro.h" @@ -100,6 +100,7 @@ input::Manager* input_mgr = 0; plugin::Manager* plugin_mgr = 0; analyzer::Manager* analyzer_mgr = 0; file_analysis::Manager* file_mgr = 0; +broxygen::Manager* broxygen_mgr = 0; Stmt* stmts; EventHandlerPtr net_done = 0; RuleMatcher* rule_matcher = 0; @@ -116,7 +117,6 @@ int signal_val = 0; int optimize = 0; int do_notice_analysis = 0; int rule_bench = 0; -int generate_documentation = 0; SecondaryPath* secondary_path = 0; extern char version[]; char* command_line_policy = 0; @@ -124,6 +124,8 @@ vector params; char* proc_status_file = 0; int snaplen = 0; // this gets set from the scripting-layer's value +TypeAliasMap type_aliases; + OpaqueType* md5_type = 0; OpaqueType* sha1_type = 0; OpaqueType* sha256_type = 0; @@ -132,8 +134,6 @@ OpaqueType* cardinality_type = 0; OpaqueType* topk_type = 0; OpaqueType* bloomfilter_type = 0; -extern std::list docs_generated; - // Keep copy of command line int bro_argc; char** bro_argv; @@ -203,7 +203,7 @@ void usage() fprintf(stderr, " -T|--re-level | set 'RE_level' for rules\n"); fprintf(stderr, " -U|--status-file | Record process status in file\n"); fprintf(stderr, " -W|--watchdog | activate watchdog timer\n"); - fprintf(stderr, " -Z|--doc-scripts | generate documentation for all loaded scripts\n"); + fprintf(stderr, " -X|--broxygen | generate documentation based on config file\n"); #ifdef USE_PERFTOOLS_DEBUG fprintf(stderr, " -m|--mem-leaks | show leaks [perftools]\n"); @@ -373,6 +373,7 @@ void terminate_bro() plugin_mgr->FinishPlugins(); + delete broxygen_mgr; delete timer_mgr; delete dns_mgr; delete persistence_serializer; @@ -473,7 +474,7 @@ int main(int argc, char** argv) {"filter", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {"iface", required_argument, 0, 'i'}, - {"doc-scripts", no_argument, 0, 'Z'}, + {"broxygen", required_argument, 0, 'X'}, {"prefix", required_argument, 0, 'p'}, {"readfile", required_argument, 0, 'r'}, {"flowfile", required_argument, 0, 'y'}, @@ -532,7 +533,7 @@ int main(int argc, char** argv) if ( p ) add_to_name_list(p, ':', prefixes); - string active_file; + string broxygen_config; #ifdef USE_IDMEF string libidmef_dtd_path = "idmef-message.dtd"; @@ -545,7 +546,7 @@ int main(int argc, char** argv) opterr = 0; char opts[256]; - safe_strncpy(opts, "B:D:e:f:I:i:K:l:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGLNOPSWbdghvZ", + safe_strncpy(opts, "B:D:e:f:I:i:K:l:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGLNOPSWbdghv", sizeof(opts)); #ifdef USE_PERFTOOLS_DEBUG @@ -727,8 +728,8 @@ int main(int argc, char** argv) break; #endif - case 'Z': - generate_documentation = 1; + case 'X': + broxygen_config = optarg; break; #ifdef USE_IDMEF @@ -760,6 +761,7 @@ int main(int argc, char** argv) reporter = new Reporter(); thread_mgr = new threading::Manager(); + broxygen_mgr = new broxygen::Manager(broxygen_config); #ifdef DEBUG if ( debug_streams ) @@ -888,23 +890,6 @@ int main(int argc, char** argv) } #endif - if ( generate_documentation ) - { - CreateProtoAnalyzerDoc("proto-analyzers.rst"); - CreateFileAnalyzerDoc("file-analyzers.rst"); - - std::list::iterator it; - - for ( it = docs_generated.begin(); it != docs_generated.end(); ++it ) - (*it)->WriteDocFile(); - - for ( it = docs_generated.begin(); it != docs_generated.end(); ++it ) - delete *it; - - terminate_bro(); - return 0; - } - if ( reporter->Errors() > 0 ) { delete dns_mgr; @@ -915,6 +900,8 @@ int main(int argc, char** argv) init_general_global_var(); + broxygen_mgr->GenerateDocs(); + if ( user_pcap_filter ) { ID* id = global_scope()->Lookup("cmd_line_bpf_filter"); diff --git a/src/parse.y b/src/parse.y index 98df0de2a3..ed79808c78 100644 --- a/src/parse.y +++ b/src/parse.y @@ -2,7 +2,7 @@ // See the file "COPYING" in the main distribution directory for copyright. %} -%expect 85 +%expect 75 %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF @@ -28,8 +28,6 @@ %token TOK_DEBUG -%token TOK_DOC TOK_POST_DOC - %token TOK_NO_TEST %nonassoc TOK_HOOK @@ -47,8 +45,7 @@ %left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR %type opt_no_test opt_no_test_block -%type TOK_ID TOK_PATTERN_TEXT single_pattern TOK_DOC TOK_POST_DOC -%type opt_doc_list opt_post_doc_list +%type TOK_ID TOK_PATTERN_TEXT single_pattern %type local_id global_id def_global_id event_id global_or_event_id resolve_id begin_func %type local_id_list %type init_class @@ -83,17 +80,13 @@ #include "RE.h" #include "Scope.h" #include "Reporter.h" -#include "BroDoc.h" -#include "BroDocObj.h" #include "Brofiler.h" +#include "broxygen/Manager.h" -#include +#include #include -extern Brofiler brofiler; -extern BroDoc* current_reST_doc; -extern int generate_documentation; -extern std::list* reST_doc_comments; +extern const char* filename; // Absolute path of file currently being parsed. YYLTYPE GetCurrentLocation(); extern int yyerror(const char[]); @@ -127,24 +120,13 @@ bool defining_global_ID = false; ID* func_id = 0; EnumType *cur_enum_type = 0; -CommentedEnumType *cur_enum_type_doc = 0; -const char* cur_enum_elem_id = 0; - -type_decl_list* fake_type_decl_list = 0; -TypeDecl* last_fake_type_decl = 0; - static ID* cur_decl_type_id = 0; static void parser_new_enum (void) { /* Starting a new enum definition. */ assert(cur_enum_type == NULL); - cur_enum_type = new EnumType(cur_decl_type_id->Name()); - - // For documentation purposes, a separate type object is created - // in order to avoid overlap that can be caused by redefs. - if ( generate_documentation ) - cur_enum_type_doc = new CommentedEnumType(cur_decl_type_id->Name()); + cur_enum_type = new EnumType(); } static void parser_redef_enum (ID *id) @@ -160,53 +142,75 @@ static void parser_redef_enum (ID *id) if ( ! cur_enum_type ) id->Error("not an enum"); } - - if ( generate_documentation ) - cur_enum_type_doc = new CommentedEnumType(id->Name()); } -static void add_enum_comment (std::list* comments) +static type_decl_list* copy_type_decl_list(type_decl_list* tdl) { - cur_enum_type_doc->AddComment(current_module, cur_enum_elem_id, comments); - } + if ( ! tdl ) + return 0; -static ID* create_dummy_id (ID* id, BroType* type) - { - ID* fake_id = new ID(copy_string(id->Name()), (IDScope) id->Scope(), - is_export); + type_decl_list* rval = new type_decl_list(); - fake_id->SetType(type->Ref()); - - if ( id->AsType() ) + loop_over_list(*tdl, i) { - type->SetTypeID(copy_string(id->Name())); - fake_id->MakeType(); + TypeDecl* td = (*tdl)[i]; + rval->append(new TypeDecl(*td)); } - return fake_id; + return rval; } -static std::list* concat_opt_docs (std::list* pre, - std::list* post) +static attr_list* copy_attr_list(attr_list* al) { - if ( ! pre && ! post ) return 0; + if ( ! al ) + return 0; - if ( pre && ! post ) return pre; + attr_list* rval = new attr_list(); - if ( ! pre && post ) return post; + loop_over_list(*al, i) + { + Attr* a = (*al)[i]; + ::Ref(a); + rval->append(a); + } - pre->splice(pre->end(), *post); - delete post; - - return pre; + return rval; } +static void extend_record(ID* id, type_decl_list* fields, attr_list* attrs) + { + set types = type_aliases[id->Name()]; + + if ( types.empty() ) + { + id->Error("failed to redef record: no types found in alias map"); + return; + } + + for ( set::const_iterator it = types.begin(); it != types.end(); ) + { + RecordType* add_to = (*it)->AsRecordType(); + const char* error = 0; + ++it; + + if ( it == types.end() ) + error = add_to->AddFields(fields, attrs); + else + error = add_to->AddFields(copy_type_decl_list(fields), + copy_attr_list(attrs)); + + if ( error ) + { + id->Error(error); + break; + } + } + } %} %union { bool b; char* str; - std::list* str_l; ID* id; id_list* id_l; init_class ic; @@ -699,46 +703,24 @@ single_pattern: ; enum_body: - enum_body_list opt_post_doc_list + enum_body_list { $$ = cur_enum_type; - - if ( generate_documentation ) - { - add_enum_comment($2); - cur_enum_elem_id = 0; - } - cur_enum_type = NULL; } - | enum_body_list ',' opt_post_doc_list + | enum_body_list ',' { $$ = cur_enum_type; - - if ( generate_documentation ) - { - add_enum_comment($3); - cur_enum_elem_id = 0; - } - cur_enum_type = NULL; } ; enum_body_list: - enum_body_elem opt_post_doc_list - { - if ( generate_documentation ) - add_enum_comment($2); - } + enum_body_elem - | enum_body_list ',' opt_post_doc_list - { - if ( generate_documentation ) - add_enum_comment($3); - } enum_body_elem -; + | enum_body_list ',' enum_body_elem + ; enum_body_elem: /* TODO: We could also define this as TOK_ID '=' expr, (or @@ -746,25 +728,19 @@ enum_body_elem: error messages if someboy tries to use constant variables as enumerator. */ - opt_doc_list TOK_ID '=' TOK_CONSTANT + TOK_ID '=' TOK_CONSTANT { - set_location(@2, @4); + set_location(@1, @3); assert(cur_enum_type); - if ( $4->Type()->Tag() != TYPE_COUNT ) + if ( $3->Type()->Tag() != TYPE_COUNT ) reporter->Error("enumerator is not a count constant"); else - cur_enum_type->AddName(current_module, $2, $4->InternalUnsigned(), is_export); - - if ( generate_documentation ) - { - cur_enum_type_doc->AddName(current_module, $2, $4->InternalUnsigned(), is_export); - cur_enum_elem_id = $2; - add_enum_comment($1); - } + cur_enum_type->AddName(current_module, $1, + $3->InternalUnsigned(), is_export); } - | opt_doc_list TOK_ID '=' '-' TOK_CONSTANT + | TOK_ID '=' '-' TOK_CONSTANT { /* We only accept counts as enumerator, but we want to return a nice error message if users triy to use a negative integer (will also @@ -773,18 +749,11 @@ enum_body_elem: reporter->Error("enumerator is not a count constant"); } - | opt_doc_list TOK_ID + | TOK_ID { - set_location(@2); + set_location(@1); assert(cur_enum_type); - cur_enum_type->AddName(current_module, $2, is_export); - - if ( generate_documentation ) - { - cur_enum_type_doc->AddName(current_module, $2, is_export); - cur_enum_elem_id = $2; - add_enum_comment($1); - } + cur_enum_type->AddName(current_module, $1, is_export); } ; @@ -872,12 +841,11 @@ type: } | TOK_RECORD '{' - { ++in_record; do_doc_token_start(); } + { ++in_record; } type_decl_list { --in_record; } '}' { - do_doc_token_stop(); set_location(@1, @5); $$ = new RecordType($4); } @@ -889,9 +857,8 @@ type: $$ = 0; } - | TOK_ENUM '{' { set_location(@1); parser_new_enum(); do_doc_token_start(); } enum_body '}' + | TOK_ENUM '{' { set_location(@1); parser_new_enum(); } enum_body '}' { - do_doc_token_stop(); set_location(@1, @5); $4->UpdateLocationEndInfo(@5); $$ = $4; @@ -983,45 +950,21 @@ type_decl_list: type_decl_list type_decl { $1->append($2); - - if ( generate_documentation && last_fake_type_decl ) - { - fake_type_decl_list->append(last_fake_type_decl); - last_fake_type_decl = 0; - } } | { $$ = new type_decl_list(); - - if ( generate_documentation ) - fake_type_decl_list = new type_decl_list(); } ; type_decl: - opt_doc_list TOK_ID ':' type opt_attr ';' opt_post_doc_list + TOK_ID ':' type opt_attr ';' { - set_location(@2, @6); + set_location(@1, @4); + $$ = new TypeDecl($3, $1, $4, (in_record > 0)); - if ( generate_documentation ) - { - // TypeDecl ctor deletes the attr list, so make a copy - attr_list* a = $5; - attr_list* a_copy = 0; - - if ( a ) - { - a_copy = new attr_list; - loop_over_list(*a, i) - a_copy->append((*a)[i]); - } - - last_fake_type_decl = new CommentedTypeDecl( - $4, $2, a_copy, (in_record > 0), concat_opt_docs($1, $7)); - } - - $$ = new TypeDecl($4, $2, $5, (in_record > 0)); + if ( in_record > 0 ) + broxygen_mgr->RecordField(cur_decl_type_id, $$, ::filename); } ; @@ -1055,9 +998,7 @@ decl: TOK_MODULE TOK_ID ';' { current_module = $2; - - if ( generate_documentation ) - current_reST_doc->AddModule(current_module); + broxygen_mgr->ModuleUsage(::filename, current_module); } | TOK_EXPORT '{' { is_export = true; } decl_list '}' @@ -1066,171 +1007,43 @@ decl: | TOK_GLOBAL def_global_id opt_type init_class opt_init opt_attr ';' { add_global($2, $3, $4, $5, $6, VAR_REGULAR); - - if ( generate_documentation ) - { - ID* id = $2; - if ( id->Type()->Tag() == TYPE_FUNC ) - { - switch ( id->Type()->AsFuncType()->Flavor() ) { - - case FUNC_FLAVOR_FUNCTION: - current_reST_doc->AddFunction( - new BroDocObj(id, reST_doc_comments)); - break; - - case FUNC_FLAVOR_EVENT: - current_reST_doc->AddEvent( - new BroDocObj(id, reST_doc_comments)); - break; - - case FUNC_FLAVOR_HOOK: - current_reST_doc->AddHook( - new BroDocObj(id, reST_doc_comments)); - break; - - default: - reporter->InternalError("invalid function flavor"); - break; - } - } - - else - { - current_reST_doc->AddStateVar( - new BroDocObj(id, reST_doc_comments)); - } - } + broxygen_mgr->Identifier($2); } | TOK_CONST def_global_id opt_type init_class opt_init opt_attr ';' { add_global($2, $3, $4, $5, $6, VAR_CONST); - - if ( generate_documentation ) - { - if ( $2->FindAttr(ATTR_REDEF) ) - current_reST_doc->AddOption( - new BroDocObj($2, reST_doc_comments)); - else - current_reST_doc->AddConstant( - new BroDocObj($2, reST_doc_comments)); - } + broxygen_mgr->Identifier($2); } | TOK_REDEF global_id opt_type init_class opt_init opt_attr ';' { add_global($2, $3, $4, $5, $6, VAR_REDEF); - - if ( generate_documentation && - ! streq("capture_filters", $2->Name()) ) - { - ID* fake_id = create_dummy_id($2, $2->Type()); - BroDocObj* o = new BroDocObj(fake_id, reST_doc_comments, true); - o->SetRole(true); - current_reST_doc->AddRedef(o); - } + broxygen_mgr->Redef($2, ::filename); } | TOK_REDEF TOK_ENUM global_id TOK_ADD_TO - '{' { parser_redef_enum($3); do_doc_token_start(); } enum_body '}' ';' + '{' { parser_redef_enum($3); } enum_body '}' ';' { - do_doc_token_stop(); - - if ( generate_documentation ) - { - ID* fake_id = create_dummy_id($3, cur_enum_type_doc); - cur_enum_type_doc = 0; - BroDocObj* o = new BroDocObj(fake_id, reST_doc_comments, true); - o->SetRole(true); - - if ( extract_module_name(fake_id->Name()) == "Notice" && - extract_var_name(fake_id->Name()) == "Type" ) - current_reST_doc->AddNotice(o); - else - current_reST_doc->AddRedef(o); - } + // Broxygen already grabbed new enum IDs as the type created them. } - | TOK_REDEF TOK_RECORD global_id TOK_ADD_TO - '{' { ++in_record; do_doc_token_start(); } - type_decl_list - { --in_record; do_doc_token_stop(); } '}' opt_attr ';' + | TOK_REDEF TOK_RECORD global_id { cur_decl_type_id = $3; } TOK_ADD_TO + '{' { ++in_record; } type_decl_list { --in_record; } '}' opt_attr ';' { + cur_decl_type_id = 0; + if ( ! $3->Type() ) $3->Error("unknown identifier"); else - { - RecordType* add_to = $3->Type()->AsRecordType(); - if ( ! add_to ) - $3->Error("not a record type"); - else - { - const char* error = add_to->AddFields($7, $10); - if ( error ) - $3->Error(error); - else if ( generate_documentation ) - { - if ( fake_type_decl_list ) - { - BroType* fake_record = - new RecordType(fake_type_decl_list); - ID* fake = create_dummy_id($3, fake_record); - fake_type_decl_list = 0; - BroDocObj* o = - new BroDocObj(fake, reST_doc_comments, true); - o->SetRole(true); - current_reST_doc->AddRedef(o); - } - else - { - fprintf(stderr, "Warning: doc mode did not process " - "record extension for '%s', CommentedTypeDecl" - "list unavailable.\n", $3->Name()); - } - } - } - } + extend_record($3, $8, $11); } | TOK_TYPE global_id ':' { cur_decl_type_id = $2; } type opt_attr ';' { cur_decl_type_id = 0; - add_type($2, $5, $6, 0); - - if ( generate_documentation ) - { - TypeTag t = $2->AsType()->Tag(); - if ( t == TYPE_ENUM && cur_enum_type_doc ) - { - ID* fake = create_dummy_id($2, cur_enum_type_doc); - cur_enum_type_doc = 0; - current_reST_doc->AddType( - new BroDocObj(fake, reST_doc_comments, true)); - } - - else if ( t == TYPE_RECORD && fake_type_decl_list ) - { - BroType* fake_record = new RecordType(fake_type_decl_list); - ID* fake = create_dummy_id($2, fake_record); - fake_type_decl_list = 0; - current_reST_doc->AddType( - new BroDocObj(fake, reST_doc_comments, true)); - } - - else - current_reST_doc->AddType( - new BroDocObj($2, reST_doc_comments)); - } - } - - | TOK_EVENT event_id ':' type_list opt_attr ';' - { - add_type($2, $4, $5, 1); - - if ( generate_documentation ) - current_reST_doc->AddEvent( - new BroDocObj($2, reST_doc_comments)); + add_type($2, $5, $6); + broxygen_mgr->Identifier($2); } | func_hdr func_body @@ -1258,18 +1071,13 @@ func_hdr: begin_func($2, current_module.c_str(), FUNC_FLAVOR_FUNCTION, 0, $3); $$ = $3; - if ( generate_documentation ) - current_reST_doc->AddFunction( - new BroDocObj($2, reST_doc_comments)); + broxygen_mgr->Identifier($2); } | TOK_EVENT event_id func_params { begin_func($2, current_module.c_str(), FUNC_FLAVOR_EVENT, 0, $3); $$ = $3; - if ( generate_documentation ) - current_reST_doc->AddEventHandler( - new BroDocObj($2, reST_doc_comments)); } | TOK_HOOK def_global_id func_params { @@ -1278,9 +1086,6 @@ func_hdr: begin_func($2, current_module.c_str(), FUNC_FLAVOR_HOOK, 0, $3); $$ = $3; - if ( generate_documentation ) - current_reST_doc->AddHookHandler( - new BroDocObj($2, reST_doc_comments)); } | TOK_REDEF TOK_EVENT event_id func_params { @@ -1729,40 +1534,6 @@ resolve_id: } ; -opt_post_doc_list: - opt_post_doc_list TOK_POST_DOC - { - $1->push_back($2); - $$ = $1; - } - | - TOK_POST_DOC - { - $$ = new std::list(); - $$->push_back($1); - delete [] $1; - } - | - { $$ = 0; } - ; - -opt_doc_list: - opt_doc_list TOK_DOC - { - $1->push_back($2); - $$ = $1; - } - | - TOK_DOC - { - $$ = new std::list(); - $$->push_back($1); - delete [] $1; - } - | - { $$ = 0; } - ; - opt_no_test: TOK_NO_TEST { $$ = true; } @@ -1788,10 +1559,6 @@ int yyerror(const char msg[]) else sprintf(msgbuf, "%s, at or near \"%s\"", msg, last_tok); - if ( generate_documentation ) - strcat(msgbuf, "\nDocumentation mode is enabled: " - "remember to check syntax of ## style comments\n"); - if ( in_debug ) g_curr_debug_error = copy_string(msg); diff --git a/src/plugin/ComponentManager.h b/src/plugin/ComponentManager.h index 16f9d80743..7d90f93bf1 100644 --- a/src/plugin/ComponentManager.h +++ b/src/plugin/ComponentManager.h @@ -130,9 +130,9 @@ template ComponentManager::ComponentManager(const string& arg_module) : module(arg_module) { - tag_enum_type = new EnumType(module + "::Tag"); + tag_enum_type = new EnumType(); ::ID* id = install_ID("Tag", module.c_str(), true, true); - add_type(id, tag_enum_type, 0, 0); + add_type(id, tag_enum_type, 0); } template diff --git a/src/scan.l b/src/scan.l index 636ec5b251..b126b2ee1f 100644 --- a/src/scan.l +++ b/src/scan.l @@ -23,16 +23,15 @@ #include "Debug.h" #include "PolicyFile.h" #include "broparse.h" -#include "BroDoc.h" #include "Reporter.h" #include "RE.h" #include "Net.h" #include "analyzer/Analyzer.h" +#include "broxygen/Manager.h" extern YYLTYPE yylloc; // holds start line and column of token extern int print_loaded_scripts; -extern int generate_documentation; // Track the @if... depth. ptr_compat_int current_depth = 0; @@ -40,10 +39,7 @@ ptr_compat_int current_depth = 0; int_list if_stack; int line_number = 1; -const char* filename = 0; -BroDoc* current_reST_doc = 0; -static BroDoc* last_reST_doc = 0; -string current_scanned_file_path; +const char* filename = 0; // Absolute path of file currently being parsed. char last_tok[128]; @@ -56,41 +52,15 @@ char last_tok[128]; if ( ((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin) ) \ reporter->Error("read failed with \"%s\"", strerror(errno)); -// reST documents that we've created (or have at least opened so far). -std::list docs_generated; - -// reST comments (those starting with ##) seen so far. -std::list* reST_doc_comments = 0; - -// Print current contents of reST_doc_comments list to stderr. -void print_current_reST_doc_comments(); - -// Delete the reST_doc_comments list object. -void clear_reST_doc_comments(); - -// Adds changes to capture_filter to the current script's reST documentation. -static void check_capture_filter_changes(); - -static const char* canon_doc_comment(const char* comment) +static string get_dirname(const char* path) { - // "##Text" and "## Text" are treated the same in order to be able - // to still preserve indentation level, but not unintentionally - // signify an indentation level for all the text when using - // the "## Text" style. - return ( comment[0] == ' ' ) ? comment + 1 : comment; - } + if ( ! path ) + return ""; -static std::string canon_doc_func_param(const char* id_start) - { - std::string id_name(id_start, strcspn(id_start, ":")); - const char* comment = id_start + id_name.size() + 1; - std::string doc; - - if ( id_name == "Returns" ) - doc.append(":returns:").append(comment); - else - doc.append(":param ").append(id_name).append(":").append(comment); - return doc; + char* tmp = copy_string(path); + string rval = dirname(tmp); + delete[] tmp; + return rval; } static ino_t get_inode_num(FILE* f, const char* filename) @@ -99,7 +69,8 @@ static ino_t get_inode_num(FILE* f, const char* filename) if ( fstat(fileno(f), &b) ) { - reporter->Error("failed to fstat fd of %s\n", filename); + reporter->Error("failed to fstat fd of %s: %s\n", filename, + strerror(errno)); exit(1); } @@ -116,8 +87,6 @@ public: const char* name; int line; int level; - BroDoc* doc; - string path; }; // A stack of input buffers we're scanning. file_stack[len-1] is the @@ -141,7 +110,6 @@ static int load_files(const char* file); %x RE %x IGNORE -%s DOC OWS [ \t]* WS [ \t]+ @@ -159,63 +127,15 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) %% ##!.* { - // Add this format of comments to the script documentation's "summary". - if ( generate_documentation ) - current_reST_doc->AddSummary(canon_doc_comment(yytext + 3)); + broxygen_mgr->SummaryComment(::filename, yytext + 3); } -##<.* { - yylval.str = copy_string(canon_doc_comment(yytext + 3)); - return TOK_POST_DOC; -} - -##{OWS}{ID}:{WS}.* { - const char* id_start = skip_whitespace(yytext + 2); - yylval.str = copy_string(canon_doc_func_param(id_start).c_str()); - return TOK_DOC; -} - -##.* { - if ( yytext[2] != '#' ) - { - yylval.str = copy_string(canon_doc_comment(yytext + 2)); - return TOK_DOC; - } -} - -##{OWS}{ID}:{WS}.* { - if ( generate_documentation ) - { - // Comment is documenting either a function parameter or return type, - // so appropriate reST markup substitutions are automatically made - // in order to distinguish them from other comments. - if ( ! reST_doc_comments ) - reST_doc_comments = new std::list(); - - // always insert a blank line so that this param/return markup - // 1) doesn't show up in the summary section in the case that it's - // the first comment for the function/event - // 2) has a blank line between it and non-field-list reST markup, - // which is required for correct HTML rendering by Sphinx - reST_doc_comments->push_back(""); - const char* id_start = skip_whitespace(yytext + 2); - reST_doc_comments->push_back(canon_doc_func_param(id_start)); - } -} - ##<.* { - if ( generate_documentation && BroDocObj::last ) - BroDocObj::last->AddDocString(canon_doc_comment(yytext + 3)); + broxygen_mgr->PostComment(yytext + 3); } ##.* { - if ( generate_documentation && (yytext[2] != '#') ) - { - if ( ! reST_doc_comments ) - reST_doc_comments = new std::list(); - - reST_doc_comments->push_back(canon_doc_comment(yytext + 2)); - } + broxygen_mgr->PreComment(yytext + 2); } #{OWS}@no-test.* return TOK_NO_TEST; @@ -224,7 +144,7 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) {WS} /* eat whitespace */ -\n { +\n { ++line_number; ++yylloc.first_line; ++yylloc.last_line; @@ -345,7 +265,7 @@ when return TOK_WHEN; @DEBUG return TOK_DEBUG; // marks input for debugger @DIR { - string rval = current_scanned_file_path; + string rval = get_dirname(::filename); if ( ! rval.empty() && rval[0] == '.' ) { @@ -374,25 +294,15 @@ when return TOK_WHEN; @load{WS}{FILE} { const char* new_file = skip_whitespace(yytext + 5); // Skip "@load". - if ( generate_documentation ) - { - current_reST_doc->AddImport(new_file); - - if ( reST_doc_comments ) - { - fprintf(stderr, "Warning: unconsumed reST documentation is being " - "discarded before doing '@load %s' in %s:\n", - new_file, current_reST_doc->GetSourceFileName()); - clear_reST_doc_comments(); - } - } + broxygen_mgr->ScriptDependency(::filename, new_file); (void) load_files(new_file); } @load-sigs{WS}{FILE} { const char* new_sig_file = skip_whitespace(yytext + 10); const char* full_filename = 0; - FILE* f = search_for_file(new_sig_file, "sig", &full_filename, false, 0); + FILE* f = search_for_file(new_sig_file, "sig", &full_filename, false, 0, + get_dirname(::filename)); if ( f ) { @@ -411,7 +321,8 @@ when return TOK_WHEN; // All we have to do is pretend we've already scanned it. const char* full_filename; - FILE* f = search_for_file(new_file, "bro", &full_filename, true, 0); + FILE* f = search_for_file(new_file, "bro", &full_filename, true, 0, + get_dirname(::filename)); if ( f ) { @@ -603,7 +514,7 @@ static int load_files(const char* orig_file) else { - f = search_for_file(orig_file, "bro", &full_filename, true, &bropath_subpath); + f = search_for_file(orig_file, "bro", &full_filename, true, &bropath_subpath, get_dirname(::filename)); bropath_subpath_delete = bropath_subpath; // This will be deleted. } @@ -666,15 +577,7 @@ static int load_files(const char* orig_file) else file_stack.append(new FileInfo); - char* tmp = copy_string(full_filename); - current_scanned_file_path = dirname(tmp); - delete [] tmp; - - if ( generate_documentation ) - { - current_reST_doc = new BroDoc(bropath_subpath, full_filename); - docs_generated.push_back(current_reST_doc); - } + broxygen_mgr->File(full_filename); delete [] bropath_subpath_delete; @@ -776,28 +679,11 @@ void do_atendif() --current_depth; } -void do_doc_token_start() - { - if ( generate_documentation ) - BEGIN(DOC); - } - -void do_doc_token_stop() - { - if ( generate_documentation ) - BEGIN(INITIAL); - } - // Be careful to never delete things from this list, as the strings // are referred to (in order to save the locations of tokens and statements, // for error reporting and debugging). static name_list input_files; -const char* get_current_input_filename() - { - return ::filename; - } - void add_input_file(const char* file) { if ( ! file ) @@ -852,8 +738,6 @@ int yywrap() // Stack is now empty. while ( input_files.length() > 0 ) { - check_capture_filter_changes(); - if ( load_files(input_files[0]) ) { // Don't delete the filename - it's pointed to by @@ -867,8 +751,6 @@ int yywrap() (void) input_files.remove_nth(0); } - check_capture_filter_changes(); - // For each file scanned so far, and for each @prefix, look for a // prefixed and flattened version of the loaded file in BROPATH. The // flattening involves taking the path in BROPATH in which the @@ -893,7 +775,8 @@ int yywrap() string s; s = dot_canon(it->subpath.c_str(), it->name.c_str(), prefixes[i]); - FILE* f = search_for_file(s.c_str(), "bro", 0, false, 0); + FILE* f = search_for_file(s.c_str(), "bro", 0, false, 0, + get_dirname(::filename)); //printf("====== prefix search ======\n"); //printf("File : %s\n", it->name.c_str()); @@ -977,9 +860,6 @@ int yywrap() return 0; } - if ( generate_documentation ) - clear_reST_doc_comments(); - // Otherwise, we are done. return 1; } @@ -990,8 +870,6 @@ FileInfo::FileInfo(string arg_restore_module) restore_module = arg_restore_module; name = ::filename; line = ::line_number; - doc = ::current_reST_doc; - path = current_scanned_file_path; } FileInfo::~FileInfo() @@ -1002,56 +880,7 @@ FileInfo::~FileInfo() yy_switch_to_buffer(buffer_state); yylloc.filename = filename = name; yylloc.first_line = yylloc.last_line = line_number = line; - last_reST_doc = current_reST_doc; - current_reST_doc = doc; - current_scanned_file_path = path; if ( restore_module != "" ) current_module = restore_module; } - -static void check_capture_filter_changes() - { - if ( ! generate_documentation ) - return; - - // Lookup the "capture_filters" identifier, if it has any defined - // value, add it to the script's reST documentation, and finally - // clear the table so it doesn't taint the documentation for - // subsequent scripts. - - ID* capture_filters = global_scope()->Lookup("capture_filters"); - - if ( capture_filters ) - { - ODesc desc; - desc.SetIndentSpaces(4); - capture_filters->ID_Val()->Describe(&desc); - last_reST_doc->SetPacketFilter(desc.Description()); - capture_filters->ID_Val()->AsTableVal()->RemoveAll(); - } - } - -void print_current_reST_doc_comments() - { - if ( ! reST_doc_comments ) - return; - - std::list::iterator it; - - for ( it = reST_doc_comments->begin(); it != reST_doc_comments->end(); ++it ) - fprintf(stderr, "##%s\n", it->c_str()); - } - -void clear_reST_doc_comments() - { - if ( ! reST_doc_comments ) - return; - - fprintf(stderr, "Warning: %zu unconsumed reST comments:\n", - reST_doc_comments->size()); - - print_current_reST_doc_comments(); - delete reST_doc_comments; - reST_doc_comments = 0; - } diff --git a/src/util.cc b/src/util.cc index f26b3fb0c2..d06c6aff96 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1060,11 +1060,9 @@ void get_script_subpath(const std::string& full_filename, const char** subpath) *subpath = normalize_path(my_subpath.c_str()); } -extern string current_scanned_file_path; - FILE* search_for_file(const char* filename, const char* ext, const char** full_filename, bool load_pkgs, - const char** bropath_subpath) + const char** bropath_subpath, string prepend_to_search_path) { // If the file is a literal absolute path we don't have to search, // just return the result of trying to open it. If the file is @@ -1088,9 +1086,9 @@ FILE* search_for_file(const char* filename, const char* ext, // Prepend the currently loading script's path to BROPATH so that // @loads can be referenced relatively. - if ( current_scanned_file_path != "" && filename[0] == '.' ) + if ( ! prepend_to_search_path.empty() && filename[0] == '.' ) safe_snprintf(path, sizeof(path), "%s:%s", - current_scanned_file_path.c_str(), bro_path()); + prepend_to_search_path.c_str(), bro_path()); else safe_strncpy(path, bro_path(), sizeof(path)); diff --git a/src/util.h b/src/util.h index fcdfd6d499..e7ac4d33af 100644 --- a/src/util.h +++ b/src/util.h @@ -209,7 +209,8 @@ std::string dot_canon(std::string path, std::string file, std::string prefix = " const char* normalize_path(const char* path); void get_script_subpath(const std::string& full_filename, const char** subpath); extern FILE* search_for_file(const char* filename, const char* ext, - const char** full_filename, bool load_pkgs, const char** bropath_subpath); + const char** full_filename, bool load_pkgs, const char** bropath_subpath, + std::string prepend_to_search_path = ""); // Renames the given file to a new temporary name, and opens a new file with // the original name. Returns new file or NULL on error. Inits rotate_info if From 90477df973ae34896e265c4def5547fc6540f6c3 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 7 Oct 2013 15:01:03 -0500 Subject: [PATCH 393/881] Refactor search_for_file() util function. It was getting too bloated and allocated memory in ways that were difficult to understand how to manage. Separated out primarily in to new find_file() and open_file()/open_package() functions. Also renamed other util functions for path-related things. --- src/BroDoc.cc | 2 + src/Debug.cc | 10 +- src/Net.h | 8 +- src/OSFinger.cc | 3 +- src/RuleMatcher.cc | 2 +- src/broxygen/Manager.cc | 2 +- src/scan.l | 252 ++++++++++++++++------------------ src/util.cc | 292 ++++++++++++++++++++-------------------- src/util.h | 64 ++++++++- 9 files changed, 331 insertions(+), 304 deletions(-) diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 05d9d8f562..2c3d6f6d77 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -85,6 +85,7 @@ BroDoc::~BroDoc() void BroDoc::AddImport(const std::string& s) { + /* std::string lname(s); // First strip any .bro extension. size_t ext_pos = lname.find(".bro"); @@ -142,6 +143,7 @@ void BroDoc::AddImport(const std::string& s) delete [] full_filename; delete [] subpath; + */ } void BroDoc::SetPacketFilter(const std::string& s) diff --git a/src/Debug.cc b/src/Debug.cc index f4ac8c2fdf..94b8abf952 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -342,18 +342,16 @@ vector parse_location_string(const string& s) if ( ! sscanf(line_string.c_str(), "%d", &plr.line) ) plr.type = plrUnknown; - FILE* throwaway = search_for_file(filename.c_str(), "bro", - &full_filename, true, 0); - if ( ! throwaway ) + string path(find_file(filename, bro_path(), "bro")); + + if ( path.empty() ) { debug_msg("No such policy file: %s.\n", filename.c_str()); plr.type = plrUnknown; return result; } - fclose(throwaway); - - loc_filename = full_filename; + loc_filename = copy_string(path.c_str()); plr.type = plrFileAndLine; } } diff --git a/src/Net.h b/src/Net.h index 5b959d1688..07c856d1dd 100644 --- a/src/Net.h +++ b/src/Net.h @@ -4,6 +4,7 @@ #define net_h #include "net_util.h" +#include "util.h" #include "BPF_Program.h" #include "List.h" #include "PktSrc.h" @@ -97,15 +98,14 @@ struct ScannedFile { ino_t inode; int include_level; string name; - string subpath; // Path in BROPATH's policy/ containing the file. bool skipped; // This ScannedFile was @unload'd. bool prefixes_checked; // If loading prefixes for this file has been tried. - ScannedFile(ino_t arg_inode, int arg_include_level, string arg_name, - string arg_subpath = "", bool arg_skipped = false, + ScannedFile(ino_t arg_inode, int arg_include_level, const string& arg_name, + bool arg_skipped = false, bool arg_prefixes_checked = false) : inode(arg_inode), include_level(arg_include_level), - name(arg_name), subpath(arg_subpath), skipped(arg_skipped), + name(arg_name), skipped(arg_skipped), prefixes_checked(arg_prefixes_checked) { } }; diff --git a/src/OSFinger.cc b/src/OSFinger.cc index 3368a8e40c..bcb00e324b 100644 --- a/src/OSFinger.cc +++ b/src/OSFinger.cc @@ -294,7 +294,8 @@ void OSFingerprint::load_config(const char* file) uint32 ln=0; char buf[MAXLINE]; char* p; - FILE* c = search_for_file(file, "osf", 0, false, 0); + + FILE* c = open_file(find_file(file, bro_path(), "osf")); if (!c) { diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index ed33db6792..84ff5af774 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -226,7 +226,7 @@ bool RuleMatcher::ReadFiles(const name_list& files) for ( int i = 0; i < files.length(); ++i ) { - rules_in = search_for_file(files[i], "sig", 0, false, 0); + rules_in = open_file(find_file(files[i], bro_path(), "sig")); if ( ! rules_in ) { reporter->Error("Can't open signature file %s", files[i]); diff --git a/src/broxygen/Manager.cc b/src/broxygen/Manager.cc index 30c9008787..ee995d8b4a 100644 --- a/src/broxygen/Manager.cc +++ b/src/broxygen/Manager.cc @@ -20,8 +20,8 @@ void Manager::GenerateDocs() const void Manager::File(const std::string& path) { // TODO - // determine bropath subpath // can be a file or directory? + // determine path within BROPATH } void Manager::ScriptDependency(const std::string& path, const std::string& dep) diff --git a/src/scan.l b/src/scan.l index b126b2ee1f..899fa77b66 100644 --- a/src/scan.l +++ b/src/scan.l @@ -31,7 +31,6 @@ #include "broxygen/Manager.h" extern YYLTYPE yylloc; // holds start line and column of token -extern int print_loaded_scripts; // Track the @if... depth. ptr_compat_int current_depth = 0; @@ -52,31 +51,38 @@ char last_tok[128]; if ( ((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin) ) \ reporter->Error("read failed with \"%s\"", strerror(errno)); -static string get_dirname(const char* path) +static string find_relative_file(const string& filename, const string& ext) { - if ( ! path ) - return ""; + if ( filename.empty() ) + return string(); - char* tmp = copy_string(path); - string rval = dirname(tmp); - delete[] tmp; - return rval; + if ( filename[0] == '.' ) + return find_file(filename, safe_dirname(::filename), ext); + else + return find_file(filename, bro_path(), ext); } -static ino_t get_inode_num(FILE* f, const char* filename) +static ino_t get_inode_num(FILE* f, const string& path) { struct stat b; if ( fstat(fileno(f), &b) ) - { - reporter->Error("failed to fstat fd of %s: %s\n", filename, - strerror(errno)); - exit(1); - } + reporter->FatalError("fstat of %s failed: %s\n", path.c_str(), + strerror(errno)); return b.st_ino; } +static ino_t get_inode_num(const string& path) + { + FILE* f = open_file(path); + + if ( ! f ) + reporter->FatalError("failed to open %s\n", path.c_str()); + + return get_inode_num(f, path); + } + class FileInfo { public: FileInfo(string restore_module = ""); @@ -265,7 +271,7 @@ when return TOK_WHEN; @DEBUG return TOK_DEBUG; // marks input for debugger @DIR { - string rval = get_dirname(::filename); + string rval(safe_dirname(::filename)); if ( ! rval.empty() && rval[0] == '.' ) { @@ -299,42 +305,29 @@ when return TOK_WHEN; } @load-sigs{WS}{FILE} { - const char* new_sig_file = skip_whitespace(yytext + 10); - const char* full_filename = 0; - FILE* f = search_for_file(new_sig_file, "sig", &full_filename, false, 0, - get_dirname(::filename)); + const char* file = skip_whitespace(yytext + 10); + string path(find_relative_file(file, "sig")); - if ( f ) - { - sig_files.push_back(full_filename); - fclose(f); - delete [] full_filename; - } - else + if ( path.empty() ) reporter->Error("failed to find file associated with @load-sigs %s", - new_sig_file); + file); + else + sig_files.push_back(copy_string(path.c_str())); } @unload{WS}{FILE} { // Skip "@unload". - const char* new_file = skip_whitespace(yytext + 7); - - // All we have to do is pretend we've already scanned it. - const char* full_filename; - FILE* f = search_for_file(new_file, "bro", &full_filename, true, 0, - get_dirname(::filename)); - - if ( f ) - { - ScannedFile sf(get_inode_num(f, full_filename), file_stack.length(), full_filename, "", true); - files_scanned.push_back(sf); - - fclose(f); - delete [] full_filename; - } + const char* file = skip_whitespace(yytext + 7); + string path(find_relative_file(file, "bro")); + if ( path.empty() ) + reporter->Error("failed find file associated with @unload %s", file); else - reporter->Error("failed find file associated with @unload %s", new_file); + { + // All we have to do is pretend we've already scanned it. + ScannedFile sf(get_inode_num(path), file_stack.length(), path, true); + files_scanned.push_back(sf); + } } @prefixes{WS}("+"?)={WS}{PREFIX} { @@ -488,22 +481,35 @@ YYLTYPE GetCurrentLocation() return currloc; } + +static bool already_scanned(ino_t i) + { + list::const_iterator it; + + for ( it = files_scanned.begin(); it != files_scanned.end(); ++it ) + if ( it->inode == i ) + return true; + + return false; + } + +static bool already_scanned(const string& path) + { + return already_scanned(get_inode_num(path)); + } + static int load_files(const char* orig_file) { // Whether we pushed on a FileInfo that will restore the // current module after the final file has been scanned. bool did_module_restore = false; - - const char* full_filename = ""; - const char* bropath_subpath = ""; - const char* bropath_subpath_delete = 0; - FILE* f; + string file_path; + FILE* f = 0; if ( streq(orig_file, "-") ) { f = stdin; - full_filename = ""; - bropath_subpath = ""; + file_path = ""; if ( g_policy_debug ) { @@ -514,90 +520,62 @@ static int load_files(const char* orig_file) else { - f = search_for_file(orig_file, "bro", &full_filename, true, &bropath_subpath, get_dirname(::filename)); - bropath_subpath_delete = bropath_subpath; // This will be deleted. - } + file_path = find_relative_file(orig_file, "bro"); - if ( f ) - { - ino_t i = get_inode_num(f, full_filename); - std::list::const_iterator it; + if ( file_path.empty() ) + reporter->FatalError("can't find %s", orig_file); - for ( it = files_scanned.begin(); it != files_scanned.end(); ++it ) - { - if ( it->inode == i ) - { - if ( f != stdin ) - { - fclose(f); - delete [] full_filename; - delete [] bropath_subpath_delete; - } - return 0; - } - } - - ScannedFile sf(i, file_stack.length(), full_filename, bropath_subpath); - files_scanned.push_back(sf); - - if ( g_policy_debug ) - { - // Add the filename to the file mapping - // table (Debug.h). - Filemap* map = new Filemap; - - // Make sure it wasn't already read in. - HashKey* key = new HashKey(full_filename); - if ( g_dbgfilemaps.Lookup(key) ) - { - // reporter->Warning("Not re-reading policy file; check BRO_PREFIXES:", full_filename); - fclose(f); - delete key; - return 0; - } - else - { - g_dbgfilemaps.Insert(key, map); - } - - if ( full_filename ) - LoadPolicyFileText(full_filename); - } - - // Remember where we were. If this is the first - // file being pushed on the stack, i.e., the *last* - // one that will be processed, then we want to - // restore the module scope in which this @load - // was done when we're finished processing it. - if ( ! did_module_restore ) - { - file_stack.append(new FileInfo(current_module)); - did_module_restore = true; - } + if ( is_dir(file_path.c_str()) ) + f = open_package(file_path); else - file_stack.append(new FileInfo); + f = open_file(file_path); - broxygen_mgr->File(full_filename); - - delete [] bropath_subpath_delete; - - // "orig_file", could be an alias for yytext, which is ephemeral - // and will be zapped after the yy_switch_to_buffer() below. - yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); - - yylloc.first_line = yylloc.last_line = line_number = 1; - - // Don't delete the old filename - it's pointed to by - // every BroObj created when parsing it. - yylloc.filename = filename = full_filename; + if ( ! f ) + reporter->FatalError("can't open %s", file_path.c_str()); } - else + ino_t i = get_inode_num(f, file_path); + + if ( already_scanned(i) ) + return 0; + + ScannedFile sf(i, file_stack.length(), file_path); + files_scanned.push_back(sf); + + if ( g_policy_debug && ! file_path.empty() ) { - reporter->Error("can't open %s", full_filename); - exit(1); + // Add the filename to the file mapping table (Debug.h). + Filemap* map = new Filemap; + HashKey* key = new HashKey(file_path.c_str()); + g_dbgfilemaps.Insert(key, map); + LoadPolicyFileText(file_path.c_str()); } + // Remember where we were. If this is the first + // file being pushed on the stack, i.e., the *last* + // one that will be processed, then we want to + // restore the module scope in which this @load + // was done when we're finished processing it. + if ( ! did_module_restore ) + { + file_stack.append(new FileInfo(current_module)); + did_module_restore = true; + } + else + file_stack.append(new FileInfo); + + broxygen_mgr->File(file_path); + + // "orig_file", could be an alias for yytext, which is ephemeral + // and will be zapped after the yy_switch_to_buffer() below. + yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); + + yylloc.first_line = yylloc.last_line = line_number = 1; + + // Don't delete the old filename - it's pointed to by + // every BroObj created when parsing it. + yylloc.filename = filename = copy_string(file_path.c_str()); + return 1; } @@ -773,24 +751,22 @@ int yywrap() if ( ! prefixes[i][0] ) continue; - string s; - s = dot_canon(it->subpath.c_str(), it->name.c_str(), prefixes[i]); - FILE* f = search_for_file(s.c_str(), "bro", 0, false, 0, - get_dirname(::filename)); + string sub(find_dir_in_bropath(it->name)); + string flat(flatten_script_name(sub, it->name, prefixes[i])); + string path(find_relative_file(flat, "bro")); + + if ( ! path.empty() ) + { + add_input_file(path.c_str()); + found_prefixed_files = true; + } //printf("====== prefix search ======\n"); //printf("File : %s\n", it->name.c_str()); - //printf("Path : %s\n", it->subpath.c_str()); - //printf("Dotted: %s\n", s.c_str()); + //printf("Path : %s\n", sub.c_str()); + //printf("Dotted: %s\n", flat.c_str()); //printf("Found : %s\n", f ? "T" : "F"); //printf("===========================\n"); - - if ( f ) - { - add_input_file(s.c_str()); - found_prefixed_files = true; - fclose(f); - } } } diff --git a/src/util.cc b/src/util.cc index ad6d0368a4..1f087a697a 100644 --- a/src/util.cc +++ b/src/util.cc @@ -917,90 +917,127 @@ string bro_prefixes() const char* PACKAGE_LOADER = "__load__.bro"; -// If filename is pointing to a directory that contains a file called -// PACKAGE_LOADER, returns the files path. Otherwise returns filename itself. -// In both cases, the returned string is newly allocated. -static const char* check_for_dir(const char* filename, bool load_pkgs) +FILE* open_file(const string& path, const string& mode) { - if ( load_pkgs && is_dir(filename) ) - { - char init_filename_buf[1024]; - safe_snprintf(init_filename_buf, sizeof(init_filename_buf), - "%s/%s", filename, PACKAGE_LOADER); + if ( path.empty() ) + return 0; - if ( access(init_filename_buf, R_OK) == 0 ) - return copy_string(init_filename_buf); - } + FILE* rval = fopen(path.c_str(), mode.c_str()); - return copy_string(filename); - } - -static FILE* open_file(const char* filename, const char** full_filename, bool load_pkgs) - { - filename = check_for_dir(filename, load_pkgs); - - if ( full_filename ) - *full_filename = copy_string(filename); - - FILE* f = fopen(filename, "r"); - - if ( ! f ) + if ( ! rval ) { char buf[256]; strerror_r(errno, buf, sizeof(buf)); reporter->Error("Failed to open file %s: %s", filename, buf); } - delete [] filename; - - return f; + return rval; } -// Canonicalizes a given 'file' that lives in 'path' into a flattened, -// dotted format. If the optional 'prefix' argument is given, it is -// prepended to the dotted-format, separated by another dot. -// If 'file' is __load__.bro, that part is discarded when constructing -// the final dotted-format. -string dot_canon(string path, string file, string prefix) +static bool can_read(const string& path) + { + return access(path.c_str(), R_OK) == 0; + } + +FILE* open_package(string& path, const string& mode) + { + string arg_path(path); + path.append("/").append(PACKAGE_LOADER); + + if ( can_read(path) ) + return open_file(path, mode); + + reporter->Error("Failed to open package '%s': missing '%s' file", + arg_path.c_str(), PACKAGE_LOADER); + return 0; + } + +string safe_dirname(const char* path) + { + if ( ! path ) + return "."; + return safe_dirname(string(path)); + } + +string safe_dirname(const string& path) + { + char* tmp = copy_string(path.c_str()); + string rval(dirname(tmp)); + delete [] tmp; + return rval; + } + +string safe_basename(const char* path) + { + if ( ! path ) + return "."; + return safe_basename(string(path)); + } + +string safe_basename(const string& path) + { + char* tmp = copy_string(path.c_str()); + string rval(basename(tmp)); + delete [] tmp; + return rval; + } + +string flatten_script_name(const string& dir, const string& file, + const string& prefix) { string dottedform(prefix); + if ( prefix != "" ) dottedform.append("."); - dottedform.append(path); - char* tmp = copy_string(file.c_str()); - char* bname = basename(tmp); - if ( ! streq(bname, PACKAGE_LOADER) ) + + dottedform.append(dir); + string bname(safe_basename(file)); + + if ( bname != string(PACKAGE_LOADER) ) { - if ( path != "" ) + if ( dir != "" ) dottedform.append("."); + dottedform.append(bname); } - delete [] tmp; + size_t n; + while ( (n = dottedform.find("/")) != string::npos ) dottedform.replace(n, 1, "."); + return dottedform; } -// returns a normalized version of a path, removing duplicate slashes, -// extraneous dots that refer to the current directory, and pops as many -// parent directories referred to by "../" as possible -const char* normalize_path(const char* path) +static vector* tokenize_string(string input, const string& delim, + vector* rval) + { + if ( ! rval ) + rval = new vector(); + + size_t n; + + while ( (n = input.find(delim)) != string::npos ) + { + rval->push_back(input.substr(0, n)); + input.erase(0, n + 1); + } + + rval->push_back(input); + return rval; + } + + +string normalize_path(const string& path) { size_t n; - string p(path); vector components, final_components; string new_path; - if ( p[0] == '/' ) + if ( path[0] == '/' ) new_path = "/"; - while ( (n = p.find("/")) != string::npos ) - { - components.push_back(p.substr(0, n)); - p.erase(0, n + 1); - } - components.push_back(p); + tokenize_string(path, "/", &components); vector::const_iterator it; for ( it = components.begin(); it != components.end(); ++it ) @@ -1026,125 +1063,86 @@ const char* normalize_path(const char* path) if ( new_path.size() > 1 && new_path[new_path.size() - 1] == '/' ) new_path.erase(new_path.size() - 1); - return copy_string(new_path.c_str()); + return new_path; } -// Returns the subpath of the root Bro script install/source/build directory in -// which the loaded file is located. If it's not under a subpath of that -// directory (e.g. cwd or custom path) then the full path is returned. -void get_script_subpath(const std::string& full_filename, const char** subpath) +string find_dir_in_bropath(const string& path) { size_t p; - std::string my_subpath(full_filename); + string rval(path); // get the parent directory of file (if not already a directory) - if ( ! is_dir(full_filename.c_str()) ) - { - char* tmp = copy_string(full_filename.c_str()); - my_subpath = dirname(tmp); - delete [] tmp; - } + if ( ! is_dir(path.c_str()) ) + rval = safe_dirname(path); // first check if this is some subpath of the installed scripts root path, // if not check if it's a subpath of the script source root path, // then check if it's a subpath of the build directory (where BIF scripts // will get generated). // If none of those, will just use the given directory. - if ( (p = my_subpath.find(BRO_SCRIPT_INSTALL_PATH)) != std::string::npos ) - my_subpath.erase(0, strlen(BRO_SCRIPT_INSTALL_PATH)); - else if ( (p = my_subpath.find(BRO_SCRIPT_SOURCE_PATH)) != std::string::npos ) - my_subpath.erase(0, strlen(BRO_SCRIPT_SOURCE_PATH)); - else if ( (p = my_subpath.find(BRO_BUILD_SOURCE_PATH)) != std::string::npos ) - my_subpath.erase(0, strlen(BRO_BUILD_SOURCE_PATH)); - else if ( (p = my_subpath.find(BRO_BUILD_SCRIPTS_PATH)) != std::string::npos ) - my_subpath.erase(0, strlen(BRO_BUILD_SCRIPTS_PATH)); + if ( (p = rval.find(BRO_SCRIPT_INSTALL_PATH)) != std::string::npos ) + rval.erase(0, strlen(BRO_SCRIPT_INSTALL_PATH)); + else if ( (p = rval.find(BRO_SCRIPT_SOURCE_PATH)) != std::string::npos ) + rval.erase(0, strlen(BRO_SCRIPT_SOURCE_PATH)); + else if ( (p = rval.find(BRO_BUILD_SOURCE_PATH)) != std::string::npos ) + rval.erase(0, strlen(BRO_BUILD_SOURCE_PATH)); + else if ( (p = rval.find(BRO_BUILD_SCRIPTS_PATH)) != std::string::npos ) + rval.erase(0, strlen(BRO_BUILD_SCRIPTS_PATH)); // if root path found, remove path separators until next path component if ( p != std::string::npos ) - while ( my_subpath.size() && my_subpath[0] == '/' ) - my_subpath.erase(0, 1); + while ( rval.size() && rval[0] == '/' ) + rval.erase(0, 1); - *subpath = normalize_path(my_subpath.c_str()); + return normalize_path(rval); } -FILE* search_for_file(const char* filename, const char* ext, - const char** full_filename, bool load_pkgs, - const char** bropath_subpath, string prepend_to_search_path) +static string find_file_in_path(const string& filename, const string& path, + const string& opt_ext = "") { - // If the file is a literal absolute path we don't have to search, - // just return the result of trying to open it. If the file is - // might be a relative path, check first if it's a real file that - // can be referenced from cwd, else we'll try to search for it based - // on what path the currently-loading script is in as well as the - // standard BROPATH paths. - if ( filename[0] == '/' || - (filename[0] == '.' && access(filename, R_OK) == 0) ) + if ( filename.empty() ) + return string(); + + // If file name is an absolute path, searching within *path* is pointless. + if ( filename[0] == '/' ) { - if ( bropath_subpath ) - { - char* tmp = copy_string(filename); - *bropath_subpath = copy_string(dirname(tmp)); - delete [] tmp; - } - return open_file(filename, full_filename, load_pkgs); - } - - char path[1024], full_filename_buf[1024]; - - // Prepend the currently loading script's path to BROPATH so that - // @loads can be referenced relatively. - if ( ! prepend_to_search_path.empty() && filename[0] == '.' ) - safe_snprintf(path, sizeof(path), "%s:%s", - prepend_to_search_path.c_str(), bro_path()); - else - safe_strncpy(path, bro_path(), sizeof(path)); - - char* dir_beginning = path; - char* dir_ending = path; - int more = *dir_beginning != '\0'; - - while ( more ) - { - while ( *dir_ending && *dir_ending != ':' ) - ++dir_ending; - - if ( *dir_ending == ':' ) - *dir_ending = '\0'; + if ( can_read(filename) ) + return filename; else - more = 0; - - safe_snprintf(full_filename_buf, sizeof(full_filename_buf), - "%s/%s.%s", dir_beginning, filename, ext); - if ( access(full_filename_buf, R_OK) == 0 && - ! is_dir(full_filename_buf) ) - { - if ( bropath_subpath ) - get_script_subpath(full_filename_buf, bropath_subpath); - return open_file(full_filename_buf, full_filename, load_pkgs); - } - - safe_snprintf(full_filename_buf, sizeof(full_filename_buf), - "%s/%s", dir_beginning, filename); - if ( access(full_filename_buf, R_OK) == 0 ) - { - if ( bropath_subpath ) - get_script_subpath(full_filename_buf, bropath_subpath); - return open_file(full_filename_buf, full_filename, load_pkgs); - } - - dir_beginning = ++dir_ending; + return string(); } - if ( full_filename ) - *full_filename = copy_string(filename); - if ( bropath_subpath ) - { - char* tmp = copy_string(filename); - *bropath_subpath = copy_string(dirname(tmp)); - delete [] tmp; - } + string abs_path(path + '/' + filename); - return 0; + if ( ! opt_ext.empty() ) + { + string with_ext(abs_path + '.' + opt_ext); + + if ( can_read(with_ext) ) + return with_ext; + } + + if ( can_read(abs_path) ) + return abs_path; + + return string(); + } + +string find_file(const string& filename, const string& path_set, + const string& opt_ext) + { + vector paths; + tokenize_string(path_set, ":", &paths); + + for ( size_t n = 0; n < paths.size(); ++n ) + { + string f = find_file_in_path(filename, paths[n], opt_ext); + + if ( ! f.empty() ) + return f; + } + + return string(); } FILE* rotate_file(const char* name, RecordVal* rotate_info) diff --git a/src/util.h b/src/util.h index e7ac4d33af..e35a1605e5 100644 --- a/src/util.h +++ b/src/util.h @@ -205,12 +205,64 @@ extern int int_list_cmp(const void* v1, const void* v2); extern const char* bro_path(); extern const char* bro_magic_path(); extern std::string bro_prefixes(); -std::string dot_canon(std::string path, std::string file, std::string prefix = ""); -const char* normalize_path(const char* path); -void get_script_subpath(const std::string& full_filename, const char** subpath); -extern FILE* search_for_file(const char* filename, const char* ext, - const char** full_filename, bool load_pkgs, const char** bropath_subpath, - std::string prepend_to_search_path = ""); + +// Wrappers for dirname(3) that won't modify argument. +std::string safe_dirname(const char* path); +std::string safe_dirname(const std::string& path); + +// Wrappers for basename(3) that won't modify argument. +std::string safe_basename(const char* path); +std::string safe_basename(const std::string& path); + +/** + * Flatten a script name by replacing '/' path separators with '.'. + * @param dir A directory containing \a file. + * @param file A path to a Bro script. If it is a __load__.bro, that part + * is discarded when constructing the flattened the name. + * @param prefix A string to prepend to the flattened script name. + * @return The flattened script name. + */ +std::string flatten_script_name(const std::string& dir, + const std::string& file, + const std::string& prefix = ""); + +/** + * Return a canonical/shortened path string by removing superfluous elements + * (path delimiters, dots referring to CWD or parent dir). + * @param path A filesystem path. + * @return A canonical/shortened version of \a path. + */ +std::string normalize_path(const std::string& path); + +/** + * Locate a file/direcotry within BROPATH. + * @param path A file/directory to locate within BROPATH. + * @return The directory within BROPATH that \a path located or an absolute + * path to \a path if it couldn't be located in BROPATH + */ +std::string find_dir_in_bropath(const std::string& path); + +/** + * Locate a file within a given search path. + * @param filename Name of a file to find. + * @param path_set Colon-delimited set of paths to search for the file. + * @param opt_ext A filename extension/suffix to allow. + * @return Path to the found file, or an empty string if not found. + */ +std::string find_file(const std::string& filename, const std::string& path_set, + const std::string& opt_ext = ""); + +// Wrapper around fopen(3). Emits an error when failing to open. +FILE* open_file(const std::string& path, const std::string& mode = "r"); + +/** Opens a Bro script package. + * @param path Location of a Bro script package (a directory). Will be changed + * to the path of the package's loader script. + * @param mode An fopen(3) mode. + * @return The return value of fopen(3) on the loader script or null if one + * doesn't exist. + */ +FILE* open_package(std::string& path, const std::string& mode = "r"); // Renames the given file to a new temporary name, and opens a new file with // the original name. Returns new file or NULL on error. Inits rotate_info if From 0fe474e23278a9c68b1e687cb8c008b3ceeea698 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 7 Oct 2013 15:53:46 -0700 Subject: [PATCH 394/881] Polishing the reference section of the manual. Mostly resorting and renaming a few things. --- doc/index.rst | 2 -- doc/scripts/builtins.rst | 4 ++-- doc/scripts/index.rst | 9 +++++---- doc/scripts/scripts.rst | 6 +++--- src/BroDoc.cc | 12 ++++++++---- src/bro.bif | 5 ++++- src/input.bif | 2 +- src/probabilistic/bloom-filter.bif | 6 +----- src/probabilistic/cardinality-counter.bif | 7 +------ src/probabilistic/top-k.bif | 7 +------ 10 files changed, 26 insertions(+), 34 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index ac667fc089..b79f1b67a6 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -18,8 +18,6 @@ Bro Documentation scripts/index.rst components/index.rst -* `Notice Index `_ (TODO: Move to reference - section, but can't figure out how to include it into toctree) * :ref:`General Index ` * :ref:`search` diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index 3605523839..aa1a097683 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -1,5 +1,5 @@ -Built-in Types and Attributes -============================= +Types and Attributes +==================== Types ----- diff --git a/doc/scripts/index.rst b/doc/scripts/index.rst index 8897504bb0..5a19bd23f0 100644 --- a/doc/scripts/index.rst +++ b/doc/scripts/index.rst @@ -7,13 +7,14 @@ Script Reference .. toctree:: :maxdepth: 1 - builtins - Built-In Functions (BIFs) - scripts packages - internal proto-analyzers file-analyzers + notices + builtins + Built-in Functions (BIFs) + internal + scripts diff --git a/doc/scripts/scripts.rst b/doc/scripts/scripts.rst index d454063002..8aceacf329 100644 --- a/doc/scripts/scripts.rst +++ b/doc/scripts/scripts.rst @@ -1,8 +1,8 @@ .. This is a stub doc to which broxygen appends during the build process -======================== -Index of All Bro Scripts -======================== +=============== +All Bro Scripts +=============== .. toctree:: :maxdepth: 1 diff --git a/src/BroDoc.cc b/src/BroDoc.cc index dd0e8ff37c..93d8a34848 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -610,8 +610,10 @@ void CreateProtoAnalyzerDoc(const char* filename) { FILE* f = fopen(filename, "w"); - fprintf(f, "Protocol Analyzer Reference\n"); - fprintf(f, "===========================\n\n"); + fprintf(f, "Protocol Analyzers\n"); + fprintf(f, "==================\n\n\n"); + fprintf(f, ".. contents::\n"); + fprintf(f, " :depth: 1\n\n"); WriteAnalyzerTagDefn(f, analyzer_mgr->GetTagEnumType(), "Analyzer"); @@ -640,8 +642,10 @@ void CreateFileAnalyzerDoc(const char* filename) { FILE* f = fopen(filename, "w"); - fprintf(f, "File Analyzer Reference\n"); - fprintf(f, "=======================\n\n"); + fprintf(f, "File Analyzers\n"); + fprintf(f, "==============\n\n"); + fprintf(f, ".. contents::\n"); + fprintf(f, " :depth: 1\n\n"); WriteAnalyzerTagDefn(f, file_mgr->GetTagEnumType(), "Files"); diff --git a/src/bro.bif b/src/bro.bif index 93b0da2dcc..f699c1e162 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -1,7 +1,10 @@ ##! A collection of built-in functions that implement a variety of things ##! such as general programming algorithms, string processing, math functions, ##! introspection, type conversion, file/directory manipulation, packet filtering, -##! inter-process communication and controlling protocol analyzer behavior. +##! inter-process communication and controlling protocol analyzer behavior. +##! +##! You'll find most of Bro's built-in functions that aren't protocol-specific in +##! this file. %%{ // C segment #include diff --git a/src/input.bif b/src/input.bif index d6a880d9e9..f7c4d37a67 100644 --- a/src/input.bif +++ b/src/input.bif @@ -1,4 +1,4 @@ -# functions and types for the input framework +##! Internal functions and types used by the input framework. module Input; diff --git a/src/probabilistic/bloom-filter.bif b/src/probabilistic/bloom-filter.bif index a495a603ae..f76a10a900 100644 --- a/src/probabilistic/bloom-filter.bif +++ b/src/probabilistic/bloom-filter.bif @@ -1,8 +1,4 @@ -# =========================================================================== -# -# Bloom Filter Functions -# -# =========================================================================== +##! Functions to create and manipulate Bloom filters. %%{ diff --git a/src/probabilistic/cardinality-counter.bif b/src/probabilistic/cardinality-counter.bif index 3f3f9653e6..f1113d73fc 100644 --- a/src/probabilistic/cardinality-counter.bif +++ b/src/probabilistic/cardinality-counter.bif @@ -1,9 +1,4 @@ -# =========================================================================== -# -# HyperLogLog Functions -# -# =========================================================================== - +##! Functions to create and manipulate probabilistic cardinality counters. %%{ #include "probabilistic/CardinalityCounter.h" diff --git a/src/probabilistic/top-k.bif b/src/probabilistic/top-k.bif index 9ad36cadef..2725fe0422 100644 --- a/src/probabilistic/top-k.bif +++ b/src/probabilistic/top-k.bif @@ -1,9 +1,4 @@ -# =========================================================================== -# -# Top-K Functions -# -# =========================================================================== - +##! Functions to probabilistically determine top-k elements. %%{ #include "probabilistic/Topk.h" From 1bdfa3dff2454b5e38c51150f3cc3fce4744c30b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 7 Oct 2013 16:45:42 -0700 Subject: [PATCH 395/881] Updating Broxygen stylesheet. --- doc/_static/broxygen.css | 52 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/doc/_static/broxygen.css b/doc/_static/broxygen.css index 967dcd6eaa..5259c3adfc 100644 --- a/doc/_static/broxygen.css +++ b/doc/_static/broxygen.css @@ -150,8 +150,14 @@ sup, sub { line-height:0; } -pre { - white-space:pre; +pre, code { + white-space: pre; + overflow: auto; + margin-left: 2em; + margin-right: 2em; + margin-top: .5em; + margin-bottom: 1.5em; + word-wrap: normal; } pre, code, tt { @@ -166,6 +172,10 @@ dl dt { font-weight: bold; } +li dl dt { + font-weight: normal; +} + dd { margin:0 0 20px 20px; } @@ -174,6 +184,16 @@ small { font-size:75%; } +.small-text { + font-size:75%; +} + +.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + a:link, a:visited, a:active @@ -434,4 +454,32 @@ li { padding-bottom: 0em; margin-bottom: .5em; margin-top: 0em; +} + +.btest-cmd .hll { + font-weight: bold; + background: #FFFAE2; + } + +.btest-include .hll { + display: block; + text-align: center; + font-family: Palatino; + background: #FFFAE2; + } + +.btest-include .hll * { + color: #aaa; + } + +.linenodiv pre { + margin-left: 0px; + margin-right: 0px; + width: 1.5em; + text-align: right; + background: #000; +} + +.btest-cmd .code pre, .btest-include .code pre { + margin-left: 0px; } \ No newline at end of file From 364cdb86044409fc998ffbf4fc6538cde874c553 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 7 Oct 2013 16:48:38 -0700 Subject: [PATCH 396/881] Updating Sphinx tests for manual. --- .../btest-doc.sphinx.connection-record-01#1 | 20 +++---- .../btest-doc.sphinx.connection-record-02#1 | 32 +++++------ .../btest-doc.sphinx.data_struct_record_01#1 | 22 ++++---- .../btest-doc.sphinx.data_struct_record_02#1 | 24 +++++---- ...t-doc.sphinx.data_struct_set_declaration#1 | 26 ++++----- ...est-doc.sphinx.data_struct_table_complex#1 | 18 ++++--- ...doc.sphinx.data_struct_table_declaration#1 | 18 ++++--- ...oc.sphinx.data_struct_vector_declaration#1 | 18 ++++--- ...btest-doc.sphinx.data_struct_vector_iter#1 | 16 +++--- .../btest-doc.sphinx.data_type_const.bro#1 | 18 ++++--- .../btest-doc.sphinx.data_type_interval#1 | 44 +++++++-------- .../btest-doc.sphinx.data_type_pattern#1 | 16 +++--- .../btest-doc.sphinx.data_type_pattern_02#1 | 14 ++--- .../btest-doc.sphinx.data_type_subnets#1 | 18 ++++--- .../btest-doc.sphinx.data_type_time#1 | 28 +++++----- ...doc.sphinx.framework_logging_factorial-2#1 | 54 ++++++++++--------- ...doc.sphinx.framework_logging_factorial-3#1 | 46 ++++++++-------- ...t-doc.sphinx.framework_logging_factorial#1 | 30 ++++++----- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../output | 2 +- .../btest-doc.sphinx.using_bro#1 | 48 +++++++++-------- .../btest-doc.sphinx.using_bro#2 | 32 +++++------ .../btest-doc.sphinx.using_bro#3 | 32 +++++------ .../btest-doc.sphinx.using_bro#4 | 22 ++++---- .../btest-doc.sphinx.using_bro#5 | 22 ++++---- .../btest-doc.sphinx.using_bro#6 | 22 ++++---- .../btest-doc.sphinx.using_bro#7 | 20 +++---- .../btest-doc.sphinx.using_bro#8 | 12 +++-- ...c_scripting_connection_record_02_bro.btest | 2 +- ...scripting_connection_record_02_bro@2.btest | 2 +- ..._scripting_data_struct_record_01_bro.btest | 2 +- ..._scripting_data_struct_record_02_bro.btest | 2 +- ...ting_data_struct_set_declaration_bro.btest | 2 +- ...ng_data_struct_set_declaration_bro@2.btest | 2 +- ...ng_data_struct_set_declaration_bro@3.btest | 2 +- ...ng_data_struct_set_declaration_bro@4.btest | 2 +- ...ipting_data_struct_table_complex_bro.btest | 2 +- ...ng_data_struct_table_declaration_bro.btest | 2 +- ...g_data_struct_vector_declaration_bro.btest | 2 +- ...cripting_data_struct_vector_iter_bro.btest | 2 +- ...de-doc_scripting_data_type_const_bro.btest | 2 +- ...scripting_data_type_const_simple_bro.btest | 2 +- ..._scripting_data_type_declaration_bro.btest | 2 +- ...doc_scripting_data_type_interval_bro.btest | 2 +- ...de-doc_scripting_data_type_local_bro.btest | 2 +- ...c_scripting_data_type_pattern_01_bro.btest | 2 +- ...c_scripting_data_type_pattern_02_bro.btest | 2 +- ...-doc_scripting_data_type_subnets_bro.btest | 2 +- ...ude-doc_scripting_data_type_time_bro.btest | 2 +- ...g_framework_logging_factorial_01_bro.btest | 2 +- ...g_framework_logging_factorial_02_bro.btest | 2 +- ...g_framework_logging_factorial_03_bro.btest | 2 +- ...g_framework_logging_factorial_04_bro.btest | 2 +- ...ripting_framework_notice_hook_01_bro.btest | 2 +- ...ework_notice_hook_suppression_01_bro.btest | 2 +- ...ng_framework_notice_shortcuts_01_bro.btest | 2 +- ...ng_framework_notice_shortcuts_02_bro.btest | 2 +- ...clude-scripts_base_bif_event_bif_bro.btest | 2 +- ...e_bif_plugins_Bro_DNS_events_bif_bro.btest | 2 +- .../include-scripts_base_init-bare_bro.btest | 2 +- ...scripts_base_protocols_conn_main_bro.btest | 2 +- ...scripts_base_protocols_http_main_bro.btest | 2 +- ...licy_frameworks_files_detect-MHR_bro.btest | 2 +- ...cy_frameworks_files_detect-MHR_bro@2.btest | 2 +- ...cy_frameworks_files_detect-MHR_bro@3.btest | 2 +- ...cy_frameworks_files_detect-MHR_bro@4.btest | 2 +- ...olicy_protocols_conn_known-hosts_bro.btest | 2 +- ...tocols_ssh_interesting-hostnames_bro.btest | 2 +- ...icy_protocols_ssl_expiring-certs_bro.btest | 2 +- 108 files changed, 447 insertions(+), 389 deletions(-) diff --git a/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 b/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 index d3ba4e3d1c..1deb2583a9 100644 --- a/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 +++ b/testing/btest/Baseline/doc.sphinx.connection-record-01/btest-doc.sphinx.connection-record-01#1 @@ -1,11 +1,13 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro -b -r dns-session.trace connection_record_01.bro - [id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={ - - }, addl=, hot=0, history=ShADadFf, uid=CXWv6p3arKYeMETxOg, tunnel=, conn=[ts=930613226.067666, uid=CXWv6p3arKYeMETxOg, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ - - }], extract_orig=F, extract_resp=F] + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b -r dns-session.trace connection_record_01.bro + [id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={ + + }, addl=, hot=0, history=ShADadFf, uid=CXWv6p3arKYeMETxOg, tunnel=, conn=[ts=930613226.067666, uid=CXWv6p3arKYeMETxOg, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ + + }], extract_orig=F, extract_resp=F] diff --git a/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 b/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 index 8671de3372..42d0a56e21 100644 --- a/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 +++ b/testing/btest/Baseline/doc.sphinx.connection-record-02/btest-doc.sphinx.connection-record-02#1 @@ -1,17 +1,19 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro -b -r dns-session.trace connection_record_02.bro - [id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={ - - }, addl=, hot=0, history=ShADadFf, uid=CXWv6p3arKYeMETxOg, tunnel=, conn=[ts=930613226.067666, uid=CXWv6p3arKYeMETxOg, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ - - }], extract_orig=F, extract_resp=F, dns=, dns_state=[pending={ - [34798] = [initialized=T, vals={ - - }, settings=[max_len=], top=1, bottom=1, size=0] - }, finished_answers={ - - }]] + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b -r dns-session.trace connection_record_02.bro + [id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], orig=[size=29, state=5, num_pkts=6, num_bytes_ip=273, flow_label=0], resp=[size=44, state=5, num_pkts=5, num_bytes_ip=248, flow_label=0], start_time=930613226.067666, duration=0.709643, service={ + + }, addl=, hot=0, history=ShADadFf, uid=CXWv6p3arKYeMETxOg, tunnel=, conn=[ts=930613226.067666, uid=CXWv6p3arKYeMETxOg, id=[orig_h=212.180.42.100, orig_p=25000/tcp, resp_h=131.243.64.3, resp_p=53/tcp], proto=tcp, service=, duration=0.709643, orig_bytes=29, resp_bytes=44, conn_state=SF, local_orig=, missed_bytes=0, history=ShADadFf, orig_pkts=6, orig_ip_bytes=273, resp_pkts=5, resp_ip_bytes=248, tunnel_parents={ + + }], extract_orig=F, extract_resp=F, dns=, dns_state=[pending={ + [34798] = [initialized=T, vals={ + + }, settings=[max_len=], top=1, bottom=1, size=0] + }, finished_answers={ + + }]] diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 b/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 index 5b8d702333..6bb5fcdefb 100644 --- a/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 +++ b/testing/btest/Baseline/doc.sphinx.data_struct_record_01/btest-doc.sphinx.data_struct_record_01#1 @@ -1,12 +1,14 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro data_struct_record_01.bro - Service: dns(RFC1035) - port: 53/tcp - port: 53/udp - Service: http(RFC2616) - port: 80/tcp - port: 8080/tcp + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_record_01.bro + Service: dns(RFC1035) + port: 53/tcp + port: 53/udp + Service: http(RFC2616) + port: 80/tcp + port: 8080/tcp diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 b/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 index b640862c49..69c0e9e217 100644 --- a/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 +++ b/testing/btest/Baseline/doc.sphinx.data_struct_record_02/btest-doc.sphinx.data_struct_record_02#1 @@ -1,13 +1,15 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro data_struct_record_02.bro - System: morlock - Service: dns(RFC1035) - port: 53/tcp - port: 53/udp - Service: http(RFC2616) - port: 80/tcp - port: 8080/tcp + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_record_02.bro + System: morlock + Service: dns(RFC1035) + port: 53/tcp + port: 53/udp + Service: http(RFC2616) + port: 80/tcp + port: 8080/tcp diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 index f22481364a..d86aebc894 100644 --- a/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 +++ b/testing/btest/Baseline/doc.sphinx.data_struct_set_declaration/btest-doc.sphinx.data_struct_set_declaration#1 @@ -1,14 +1,16 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro data_struct_set_declaration.bro - SSL Port: 993/tcp - SSL Port: 22/tcp - SSL Port: 587/tcp - SSL Port: 443/tcp - Non-SSL Port: 143/tcp - Non-SSL Port: 25/tcp - Non-SSL Port: 80/tcp - Non-SSL Port: 23/tcp + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_set_declaration.bro + SSL Port: 993/tcp + SSL Port: 22/tcp + SSL Port: 587/tcp + SSL Port: 443/tcp + Non-SSL Port: 143/tcp + Non-SSL Port: 25/tcp + Non-SSL Port: 80/tcp + Non-SSL Port: 23/tcp diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 b/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 index 415d6b4436..d6f175dda2 100644 --- a/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 +++ b/testing/btest/Baseline/doc.sphinx.data_struct_table_complex/btest-doc.sphinx.data_struct_table_complex#1 @@ -1,10 +1,12 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro -b data_struct_table_complex.bro - Kiru was released in 1968 by Toho studios, directed by Kihachi Okamoto and starring Tatsuya Nakadai - Goyokin was released in 1969 by Fuji studios, directed by Hideo Gosha and starring Tatsuya Nakadai - Harakiri was released in 1962 by Shochiku Eiga studios, directed by Masaki Kobayashi and starring Tatsuya Nakadai - Tasogare Seibei was released in 2002 by Eisei Gekijo studios, directed by Yoji Yamada and starring Hiroyuki Sanada + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b data_struct_table_complex.bro + Kiru was released in 1968 by Toho studios, directed by Kihachi Okamoto and starring Tatsuya Nakadai + Goyokin was released in 1969 by Fuji studios, directed by Hideo Gosha and starring Tatsuya Nakadai + Harakiri was released in 1962 by Shochiku Eiga studios, directed by Masaki Kobayashi and starring Tatsuya Nakadai + Tasogare Seibei was released in 2002 by Eisei Gekijo studios, directed by Yoji Yamada and starring Hiroyuki Sanada diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 index 0b6efd6166..ec1e66216a 100644 --- a/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 +++ b/testing/btest/Baseline/doc.sphinx.data_struct_table_declaration/btest-doc.sphinx.data_struct_table_declaration#1 @@ -1,10 +1,12 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro data_struct_table_declaration.bro - Service Name: IMAPS - Common Port: 993/tcp - Service Name: HTTPS - Common Port: 443/tcp - Service Name: SSH - Common Port: 22/tcp - Service Name: SMTPS - Common Port: 587/tcp + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_table_declaration.bro + Service Name: IMAPS - Common Port: 993/tcp + Service Name: HTTPS - Common Port: 443/tcp + Service Name: SSH - Common Port: 22/tcp + Service Name: SMTPS - Common Port: 587/tcp diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 b/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 index c282de7c49..d6e63d72ba 100644 --- a/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 +++ b/testing/btest/Baseline/doc.sphinx.data_struct_vector_declaration/btest-doc.sphinx.data_struct_vector_declaration#1 @@ -1,10 +1,12 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro data_struct_vector_declaration.bro - contents of v1: [1, 2, 3, 4] - length of v1: 4 - contents of v1: [1, 2, 3, 4] - length of v2: 4 + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_struct_vector_declaration.bro + contents of v1: [1, 2, 3, 4] + length of v1: 4 + contents of v1: [1, 2, 3, 4] + length of v2: 4 diff --git a/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 b/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 index 88634f57a6..4ee9351803 100644 --- a/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 +++ b/testing/btest/Baseline/doc.sphinx.data_struct_vector_iter/btest-doc.sphinx.data_struct_vector_iter#1 @@ -1,9 +1,11 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro -b data_struct_vector_iter.bro - 1.2.0.0/18 - 2.3.0.0/18 - 3.4.0.0/18 + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b data_struct_vector_iter.bro + 1.2.0.0/18 + 2.3.0.0/18 + 3.4.0.0/18 diff --git a/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 b/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 index 48532cfb84..d1fcd91551 100644 --- a/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 +++ b/testing/btest/Baseline/doc.sphinx.data_type_const.bro/btest-doc.sphinx.data_type_const.bro#1 @@ -1,10 +1,12 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro -b data_type_const.bro - { - [6666/tcp] = IRC, - [80/tcp] = WWW - } + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -b data_type_const.bro + { + [6666/tcp] = IRC, + [80/tcp] = WWW + } diff --git a/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 b/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 index d200467611..cba6436e3d 100644 --- a/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 +++ b/testing/btest/Baseline/doc.sphinx.data_type_interval/btest-doc.sphinx.data_type_interval#1 @@ -1,23 +1,25 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro -r wikipedia.trace data_type_interval.bro - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118 - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 - Time since last connection: 132.0 msecs 97.0 usecs - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 - Time since last connection: 177.0 usecs - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 - Time since last connection: 2.0 msecs 177.0 usecs - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 - Time since last connection: 33.0 msecs 898.0 usecs - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 - Time since last connection: 35.0 usecs - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 - Time since last connection: 2.0 msecs 532.0 usecs - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2 - Time since last connection: 7.0 msecs 866.0 usecs - 2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128 - Time since last connection: 817.0 msecs 703.0 usecs + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -r wikipedia.trace data_type_interval.bro + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118 + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 132.0 msecs 97.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 177.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 2.0 msecs 177.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 33.0 msecs 898.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 35.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3 + Time since last connection: 2.0 msecs 532.0 usecs + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2 + Time since last connection: 7.0 msecs 866.0 usecs + 2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128 + Time since last connection: 817.0 msecs 703.0 usecs diff --git a/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 b/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 index e74a70e576..99281b205e 100644 --- a/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 +++ b/testing/btest/Baseline/doc.sphinx.data_type_pattern/btest-doc.sphinx.data_type_pattern#1 @@ -1,9 +1,11 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro data_type_pattern_01.bro - The - brown fox jumped over the - dog. + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_type_pattern_01.bro + The + brown fox jumped over the + dog. diff --git a/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 b/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 index 3097c85bcd..9c0cfee2d4 100644 --- a/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 +++ b/testing/btest/Baseline/doc.sphinx.data_type_pattern_02/btest-doc.sphinx.data_type_pattern_02#1 @@ -1,8 +1,10 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro data_type_pattern_02.bro - equality and /^?(equal)$?/ are not equal - equality and /^?(equality)$?/ are equal + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_type_pattern_02.bro + equality and /^?(equal)$?/ are not equal + equality and /^?(equality)$?/ are equal diff --git a/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 b/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 index 92d18b84ba..f7a3f918fa 100644 --- a/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 +++ b/testing/btest/Baseline/doc.sphinx.data_type_subnets/btest-doc.sphinx.data_type_subnets#1 @@ -1,10 +1,12 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro data_type_subnets.bro - 172.16.4.56 belongs to subnet 172.16.0.0/20 - 172.16.47.254 belongs to subnet 172.16.32.0/20 - 172.16.22.45 belongs to subnet 172.16.16.0/20 - 172.16.1.1 belongs to subnet 172.16.0.0/20 + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro data_type_subnets.bro + 172.16.4.56 belongs to subnet 172.16.0.0/20 + 172.16.47.254 belongs to subnet 172.16.32.0/20 + 172.16.22.45 belongs to subnet 172.16.16.0/20 + 172.16.1.1 belongs to subnet 172.16.0.0/20 diff --git a/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 b/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 index d83f819038..e0f9ca2d11 100644 --- a/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 +++ b/testing/btest/Baseline/doc.sphinx.data_type_time/btest-doc.sphinx.data_type_time#1 @@ -1,15 +1,17 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro -r wikipedia.trace data_type_time.bro - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118^J - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J - 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2^J - 2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128^J + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -r wikipedia.trace data_type_time.bro + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3^J + 2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2^J + 2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128^J diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 index ed2d0fe653..9edd79d146 100644 --- a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 +++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-2/btest-doc.sphinx.framework_logging_factorial-2#1 @@ -1,29 +1,33 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro framework_logging_factorial_02.bro + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 -.. code-block:: guess - :linenos: + # bro framework_logging_factorial_02.bro - #separator \x09 - #set_separator , - #empty_field (empty) - #unset_field - - #path factor - #open 2013-09-01-01-08-18 - #fields num factorial_num - #types count count - 1 1 - 2 2 - 3 6 - 4 24 - 5 120 - 6 720 - 7 5040 - 8 40320 - 9 362880 - 10 3628800 - #close 2013-09-01-01-08-18 +.. rst-class:: btest-include + + .. code-block:: guess + :linenos: + + #separator \x09 + #set_separator , + #empty_field (empty) + #unset_field - + #path factor + #open 2013-10-07-23-48-11 + #fields num factorial_num + #types count count + 1 1 + 2 2 + 3 6 + 4 24 + 5 120 + 6 720 + 7 5040 + 8 40320 + 9 362880 + 10 3628800 + #close 2013-10-07-23-48-11 diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 index 0e6c11c04a..cc0f1c1444 100644 --- a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 +++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial-3/btest-doc.sphinx.framework_logging_factorial-3#1 @@ -1,25 +1,29 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro framework_logging_factorial_03.bro + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 -.. code-block:: guess - :linenos: + # bro framework_logging_factorial_03.bro - #separator \x09 - #set_separator , - #empty_field (empty) - #unset_field - - #path factor-mod5 - #open 2013-09-01-01-08-18 - #fields num factorial_num - #types count count - 5 120 - 6 720 - 7 5040 - 8 40320 - 9 362880 - 10 3628800 - #close 2013-09-01-01-08-18 +.. rst-class:: btest-include + + .. code-block:: guess + :linenos: + + #separator \x09 + #set_separator , + #empty_field (empty) + #unset_field - + #path factor-mod5 + #open 2013-10-07-23-48-12 + #fields num factorial_num + #types count count + 5 120 + 6 720 + 7 5040 + 8 40320 + 9 362880 + 10 3628800 + #close 2013-10-07-23-48-12 diff --git a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 index 8a64a2da65..bd6c14f966 100644 --- a/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 +++ b/testing/btest/Baseline/doc.sphinx.framework_logging_factorial/btest-doc.sphinx.framework_logging_factorial#1 @@ -1,16 +1,18 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro framework_logging_factorial_01.bro - 1 - 2 - 6 - 24 - 120 - 720 - 5040 - 40320 - 362880 - 3628800 + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro framework_logging_factorial_01.bro + 1 + 2 + 6 + 24 + 120 + 720 + 5040 + 40320 + 362880 + 3628800 diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/output index 20ffe4c686..e4552b8580 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- connection_record_02.bro +connection_record_02.bro @load base/protocols/conn @load base/protocols/dns diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/output index 20ffe4c686..e4552b8580 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_connection_record_02_bro@2/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- connection_record_02.bro +connection_record_02.bro @load base/protocols/conn @load base/protocols/dns diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/output index 12a6515235..ea390412f6 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_01_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_record_01.bro +data_struct_record_01.bro type Service: record { name: string; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/output index dedbca8be7..143e6c5672 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_record_02_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_record_02.bro +data_struct_record_02.bro type Service: record { name: string; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/output index 700c7296d0..47aa12030b 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_set_declaration.bro +data_struct_set_declaration.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/output index b31b65805f..12020f4b67 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@2/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_set_declaration.bro +data_struct_set_declaration.bro for ( i in ssl_ports ) print fmt("SSL Port: %s", i); diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/output index c5bddfb7d1..b7a68af4aa 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@3/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_set_declaration.bro +data_struct_set_declaration.bro # Check for SMTPS if ( 587/tcp !in ssl_ports ) diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/output index 5c87335f06..53b193850c 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_set_declaration_bro@4/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_set_declaration.bro +data_struct_set_declaration.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/output index 2557adea17..c92d338cec 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_complex_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_table_complex.bro +data_struct_table_complex.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/output index 8aab992b18..752af3a934 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_table_declaration_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_table_declaration.bro +data_struct_table_declaration.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/output index 91eaf2432d..575b5a18b4 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_declaration_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_vector_declaration.bro +data_struct_vector_declaration.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/output index 73694157d3..5f16dcc5af 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_struct_vector_iter_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_vector_iter.bro +data_struct_vector_iter.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/output index f1337275ca..20a4f8d71e 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_const.bro +data_type_const.bro const port_list: table[port] of string &redef; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/output index 807e92573f..29844f2b01 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_const_simple_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_const_simple.bro +data_type_const_simple.bro @load base/protocols/http diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/output index 56ac2c5fc4..a153f3066c 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_declaration_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_declaration.bro +data_type_declaration.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/output index fd6d831e8b..25076f3e8e 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_interval_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_interval.bro +data_type_interval.bro # Store the time the previous connection was established. global last_connection_time: time; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/output index 93f84cc059..0e034dddd2 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_local_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_local.bro +data_type_local.bro function add_two(i: count): count { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/output index 55f68d9e45..f108efb795 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_01_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_pattern_01.bro +data_type_pattern_01.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/output index ed09de2be0..4e4d8992df 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_pattern_02_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_pattern_02.bro +data_type_pattern_02.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/output index f23f3427ed..75600794ec 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_subnets_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_subnets.bro +data_type_subnets.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/output index fa04f56021..00a3e20813 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_data_type_time_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_time.bro +data_type_time.bro event connection_established(c: connection) { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/output index 762e8a1651..e542572647 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_01_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_logging_factorial_01.bro +framework_logging_factorial_01.bro module Factor; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/output index 6972c285f9..ce2a9106cd 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_02_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_logging_factorial_02.bro +framework_logging_factorial_02.bro module Factor; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/output index 9e7846eb59..631875ba2a 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_03_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_logging_factorial_03.bro +framework_logging_factorial_03.bro event bro_init() { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/output index b2e85f0c90..035f8d90bc 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_logging_factorial_04_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_logging_factorial_04.bro +framework_logging_factorial_04.bro module Factor; diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/output index 632efc9b90..96a3b5a921 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_01_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_notice_hook_01.bro +framework_notice_hook_01.bro @load policy/protocols/ssh/interesting-hostnames.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/output index 0d5eb7e25f..b51bd2eebe 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_hook_suppression_01_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_notice_hook_suppression_01.bro +framework_notice_hook_suppression_01.bro @load policy/protocols/ssl/expiring-certs.bro diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/output index 80e464f312..0202fa3a28 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_01_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_notice_shortcuts_01.bro +framework_notice_shortcuts_01.bro @load policy/protocols/ssh/interesting-hostnames.bro @load base/protocols/ssh/ diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/output index 0418955ab2..266a2e1fbb 100644 --- a/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-doc_scripting_framework_notice_shortcuts_02_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_notice_shortcuts_02.bro +framework_notice_shortcuts_02.bro @load policy/protocols/ssh/interesting-hostnames.bro @load base/protocols/ssh/ diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output index 0d981e7fc0..c77e08c5a1 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_event_bif_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- event.bif.bro +event.bif.bro ## Generated for every new connection. This event is raised with the first ## packet of a previously unknown connection. Bro uses a flow-based definition diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/output index b393c0580b..6e15ece5e0 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- Bro_DNS.events.bif.bro +Bro_DNS.events.bif.bro ## Generated for DNS requests. For requests with multiple queries, this event ## is raised once for each. diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/output index c42a63f6ad..0057a78cc4 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_init-bare_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- init-bare.bro +init-bare.bro type string_array: table[count] of string; type string_set: set[string]; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/output index ddbe628009..9966341119 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_conn_main_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- main.bro +main.bro module Conn; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/output index 0acb7a17e8..c2e558bac8 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_base_protocols_http_main_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- main.bro +main.bro module HTTP; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/output index 9220e6abf7..26911a534c 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- detect-MHR.bro +detect-MHR.bro ##! Detect file downloads that have hash values matching files in Team ##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output index 656abf3ba1..4ce4383efb 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@2/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- detect-MHR.bro +detect-MHR.bro @load base/frameworks/files @load base/frameworks/notice diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output index 75d94f6990..b8a0abf363 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@3/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- detect-MHR.bro +detect-MHR.bro export { redef enum Notice::Type += { diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output index 7e3e1b0a11..57d2d7ee50 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_frameworks_files_detect-MHR_bro@4/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- detect-MHR.bro +detect-MHR.bro event file_hash(f: fa_file, kind: string, hash: string) { diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/output index db7f3d355b..150de38f35 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_conn_known-hosts_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- known-hosts.bro +known-hosts.bro module Known; diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output index 2a395ab20e..2ff1a711be 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- interesting-hostnames.bro +interesting-hostnames.bro ##! This script will generate a notice if an apparent SSH login originates ##! or heads to a host with a reverse hostname that looks suspicious. By diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/output index 6a630796c0..aff7dffff7 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssl_expiring-certs_bro/output @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- expiring-certs.bro +expiring-certs.bro NOTICE([$note=Certificate_Expires_Soon, $msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after), diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 index ee6f8a7a03..65c802ccf2 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#1 @@ -1,26 +1,30 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro -r wikipedia.trace + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 -.. code-block:: guess - :linenos: + # bro -r wikipedia.trace - #separator \x09 - #set_separator , - #empty_field (empty) - #unset_field - - #path conn - #open 2013-09-01-01-08-21 - #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents - #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] - 1300475167.096535 CXWv6p3arKYeMETxOg 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 73 0 0 (empty) - 1300475167.097012 CjhGID4nQcgTWjvg4c fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp - - - - S0 - 0 D 1 199 0 0 (empty) - 1300475167.099816 CCvvfg3TEfuqmmG4bh 141.142.220.50 5353 224.0.0.251 5353 udp - - - - S0 - 0 D 1 179 0 0 (empty) - 1300475168.853899 CPbrpk1qSsw6ESzHV4 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF - 0 Dd 1 66 1 117 (empty) - 1300475168.854378 C6pKV8GSxOnSLghOa 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF - 0 Dd 1 80 1 127 (empty) - 1300475168.854837 CIPOse170MGiRM1Qf4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF - 0 Dd 1 66 1 211 (empty) - 1300475168.857956 CMXxB5GvmoxJFXdTa 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF - 0 Dd 1 66 1 117 (empty) - [...] +.. rst-class:: btest-include + + .. code-block:: guess + :linenos: + + #separator \x09 + #set_separator , + #empty_field (empty) + #unset_field - + #path conn + #open 2013-10-07-23-48-15 + #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents + #types time string addr port addr port enum string interval count count string bool count string count count count count table[string] + 1300475167.096535 CXWv6p3arKYeMETxOg 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - 0 D 1 73 0 0 (empty) + 1300475167.097012 CjhGID4nQcgTWjvg4c fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp - - - - S0 - 0 D 1 199 0 0 (empty) + 1300475167.099816 CCvvfg3TEfuqmmG4bh 141.142.220.50 5353 224.0.0.251 5353 udp - - - - S0 - 0 D 1 179 0 0 (empty) + 1300475168.853899 CPbrpk1qSsw6ESzHV4 141.142.220.118 43927 141.142.2.2 53 udp dns 0.000435 38 89 SF - 0 Dd 1 66 1 117 (empty) + 1300475168.854378 C6pKV8GSxOnSLghOa 141.142.220.118 37676 141.142.2.2 53 udp dns 0.000420 52 99 SF - 0 Dd 1 80 1 127 (empty) + 1300475168.854837 CIPOse170MGiRM1Qf4 141.142.220.118 40526 141.142.2.2 53 udp dns 0.000392 38 183 SF - 0 Dd 1 66 1 211 (empty) + 1300475168.857956 CMXxB5GvmoxJFXdTa 141.142.220.118 32902 141.142.2.2 53 udp dns 0.000317 38 89 SF - 0 Dd 1 66 1 117 (empty) + [...] diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 index b455b9a8e8..2b060fc2ff 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#2 @@ -1,17 +1,19 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration - 141.142.220.202 5353 224.0.0.251 - - fe80::217:f2ff:fed7:cf65 5353 ff02::fb - - 141.142.220.50 5353 224.0.0.251 - - 141.142.220.118 43927 141.142.2.2 0.000435 - 141.142.220.118 37676 141.142.2.2 0.000420 - 141.142.220.118 40526 141.142.2.2 0.000392 - 141.142.220.118 32902 141.142.2.2 0.000317 - 141.142.220.118 59816 141.142.2.2 0.000343 - 141.142.220.118 59714 141.142.2.2 0.000375 - 141.142.220.118 58206 141.142.2.2 0.000339 - [...] + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration + 141.142.220.202 5353 224.0.0.251 - + fe80::217:f2ff:fed7:cf65 5353 ff02::fb - + 141.142.220.50 5353 224.0.0.251 - + 141.142.220.118 43927 141.142.2.2 0.000435 + 141.142.220.118 37676 141.142.2.2 0.000420 + 141.142.220.118 40526 141.142.2.2 0.000392 + 141.142.220.118 32902 141.142.2.2 0.000317 + 141.142.220.118 59816 141.142.2.2 0.000343 + 141.142.220.118 59714 141.142.2.2 0.000375 + 141.142.220.118 58206 141.142.2.2 0.000339 + [...] diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 index 8492053976..92378e6c08 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#3 @@ -1,17 +1,19 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # awk '/^[^#]/ {print $3, $4, $5, $6, $9}' conn.log - 141.142.220.202 5353 224.0.0.251 5353 - - fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 - - 141.142.220.50 5353 224.0.0.251 5353 - - 141.142.220.118 43927 141.142.2.2 53 0.000435 - 141.142.220.118 37676 141.142.2.2 53 0.000420 - 141.142.220.118 40526 141.142.2.2 53 0.000392 - 141.142.220.118 32902 141.142.2.2 53 0.000317 - 141.142.220.118 59816 141.142.2.2 53 0.000343 - 141.142.220.118 59714 141.142.2.2 53 0.000375 - 141.142.220.118 58206 141.142.2.2 53 0.000339 - [...] + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # awk '/^[^#]/ {print $3, $4, $5, $6, $9}' conn.log + 141.142.220.202 5353 224.0.0.251 5353 - + fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 - + 141.142.220.50 5353 224.0.0.251 5353 - + 141.142.220.118 43927 141.142.2.2 53 0.000435 + 141.142.220.118 37676 141.142.2.2 53 0.000420 + 141.142.220.118 40526 141.142.2.2 53 0.000392 + 141.142.220.118 32902 141.142.2.2 53 0.000317 + 141.142.220.118 59816 141.142.2.2 53 0.000343 + 141.142.220.118 59714 141.142.2.2 53 0.000375 + 141.142.220.118 58206 141.142.2.2 53 0.000339 + [...] diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 index a41a275d32..511e8f18f5 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#4 @@ -1,12 +1,14 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro-cut -d ts uid host uri < http.log - 2011-03-18T19:06:08+0000 CRJuHdVW0XPVINV8a bits.wikimedia.org /skins-1.5/monobook/main.css - 2011-03-18T19:06:08+0000 CJ3xTn1c4Zw9TmAE05 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png - 2011-03-18T19:06:08+0000 C7XEbhP654jzLoe3a upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png - 2011-03-18T19:06:08+0000 C3SfNE4BWaU4aSuwkc upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png - 2011-03-18T19:06:08+0000 CyAhVIzHqb7t7kv28 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png - [...] + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro-cut -d ts uid host uri < http.log + 2011-03-18T19:06:08+0000 CRJuHdVW0XPVINV8a bits.wikimedia.org /skins-1.5/monobook/main.css + 2011-03-18T19:06:08+0000 CJ3xTn1c4Zw9TmAE05 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png + 2011-03-18T19:06:08+0000 C7XEbhP654jzLoe3a upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png + 2011-03-18T19:06:08+0000 C3SfNE4BWaU4aSuwkc upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png + 2011-03-18T19:06:08+0000 CyAhVIzHqb7t7kv28 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png + [...] diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 index 1d3caa52b9..e743720247 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#5 @@ -1,12 +1,14 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro-cut -u ts uid host uri < http.log - 2011-03-18T19:06:08+0000 CRJuHdVW0XPVINV8a bits.wikimedia.org /skins-1.5/monobook/main.css - 2011-03-18T19:06:08+0000 CJ3xTn1c4Zw9TmAE05 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png - 2011-03-18T19:06:08+0000 C7XEbhP654jzLoe3a upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png - 2011-03-18T19:06:08+0000 C3SfNE4BWaU4aSuwkc upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png - 2011-03-18T19:06:08+0000 CyAhVIzHqb7t7kv28 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png - [...] + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro-cut -u ts uid host uri < http.log + 2011-03-18T19:06:08+0000 CRJuHdVW0XPVINV8a bits.wikimedia.org /skins-1.5/monobook/main.css + 2011-03-18T19:06:08+0000 CJ3xTn1c4Zw9TmAE05 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png + 2011-03-18T19:06:08+0000 C7XEbhP654jzLoe3a upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png + 2011-03-18T19:06:08+0000 C3SfNE4BWaU4aSuwkc upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png + 2011-03-18T19:06:08+0000 CyAhVIzHqb7t7kv28 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png + [...] diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 index e53883ceb0..be00724ab3 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#6 @@ -1,12 +1,14 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log - 18-03-2011T19:06:08+0000 CRJuHdVW0XPVINV8a bits.wikimedia.org /skins-1.5/monobook/main.css - 18-03-2011T19:06:08+0000 CJ3xTn1c4Zw9TmAE05 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png - 18-03-2011T19:06:08+0000 C7XEbhP654jzLoe3a upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png - 18-03-2011T19:06:08+0000 C3SfNE4BWaU4aSuwkc upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png - 18-03-2011T19:06:08+0000 CyAhVIzHqb7t7kv28 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png - [...] + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log + 18-03-2011T19:06:08+0000 CRJuHdVW0XPVINV8a bits.wikimedia.org /skins-1.5/monobook/main.css + 18-03-2011T19:06:08+0000 CJ3xTn1c4Zw9TmAE05 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png + 18-03-2011T19:06:08+0000 C7XEbhP654jzLoe3a upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png + 18-03-2011T19:06:08+0000 C3SfNE4BWaU4aSuwkc upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png + 18-03-2011T19:06:08+0000 CyAhVIzHqb7t7kv28 upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png + [...] diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 index 4ec7817003..cf990652be 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#7 @@ -1,11 +1,13 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5 - CyAhVIzHqb7t7kv28 734 - CkDsfG2YIeWJmXWNWj 734 - CJ3xTn1c4Zw9TmAE05 734 - C3SfNE4BWaU4aSuwkc 734 - CzA03V1VcgagLjnO92 733 + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5 + CyAhVIzHqb7t7kv28 734 + CkDsfG2YIeWJmXWNWj 734 + CJ3xTn1c4Zw9TmAE05 734 + C3SfNE4BWaU4aSuwkc 734 + CzA03V1VcgagLjnO92 733 diff --git a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 index 72c290affb..b4ce9dfc87 100644 --- a/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 +++ b/testing/btest/Baseline/doc.sphinx.using_bro/btest-doc.sphinx.using_bro#8 @@ -1,7 +1,9 @@ -.. code-block:: none - :linenos: - :emphasize-lines: 1,1 +.. rst-class:: btest-cmd - # cat http.log | bro-cut uid id.resp_h method status_code host uri | grep VW0XPVINV8a - CRJuHdVW0XPVINV8a 208.80.152.118 GET 304 bits.wikimedia.org /skins-1.5/monobook/main.css + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # cat http.log | bro-cut uid id.resp_h method status_code host uri | grep VW0XPVINV8a + CRJuHdVW0XPVINV8a 208.80.152.118 GET 304 bits.wikimedia.org /skins-1.5/monobook/main.css diff --git a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest index 20ffe4c686..e4552b8580 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- connection_record_02.bro +connection_record_02.bro @load base/protocols/conn @load base/protocols/dns diff --git a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest index 20ffe4c686..e4552b8580 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_connection_record_02_bro@2.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- connection_record_02.bro +connection_record_02.bro @load base/protocols/conn @load base/protocols/dns diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest index 12a6515235..ea390412f6 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_01_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_record_01.bro +data_struct_record_01.bro type Service: record { name: string; diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest index dedbca8be7..143e6c5672 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_record_02_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_record_02.bro +data_struct_record_02.bro type Service: record { name: string; diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest index 700c7296d0..47aa12030b 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_set_declaration.bro +data_struct_set_declaration.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest index b31b65805f..12020f4b67 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@2.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_set_declaration.bro +data_struct_set_declaration.bro for ( i in ssl_ports ) print fmt("SSL Port: %s", i); diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest index c5bddfb7d1..b7a68af4aa 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@3.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_set_declaration.bro +data_struct_set_declaration.bro # Check for SMTPS if ( 587/tcp !in ssl_ports ) diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest index 5c87335f06..53b193850c 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_set_declaration_bro@4.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_set_declaration.bro +data_struct_set_declaration.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest index 2557adea17..c92d338cec 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_complex_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_table_complex.bro +data_struct_table_complex.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest index 8aab992b18..752af3a934 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_table_declaration_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_table_declaration.bro +data_struct_table_declaration.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest index 91eaf2432d..575b5a18b4 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_declaration_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_vector_declaration.bro +data_struct_vector_declaration.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest index 73694157d3..5f16dcc5af 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_struct_vector_iter_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_struct_vector_iter.bro +data_struct_vector_iter.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest index f1337275ca..20a4f8d71e 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_const.bro +data_type_const.bro const port_list: table[port] of string &redef; diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest index 807e92573f..29844f2b01 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_const_simple_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_const_simple.bro +data_type_const_simple.bro @load base/protocols/http diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest index 56ac2c5fc4..a153f3066c 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_declaration_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_declaration.bro +data_type_declaration.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest index fd6d831e8b..25076f3e8e 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_interval_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_interval.bro +data_type_interval.bro # Store the time the previous connection was established. global last_connection_time: time; diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest index 93f84cc059..0e034dddd2 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_local_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_local.bro +data_type_local.bro function add_two(i: count): count { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest index 55f68d9e45..f108efb795 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_01_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_pattern_01.bro +data_type_pattern_01.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest index ed09de2be0..4e4d8992df 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_pattern_02_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_pattern_02.bro +data_type_pattern_02.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest index f23f3427ed..75600794ec 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_subnets_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_subnets.bro +data_type_subnets.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest index fa04f56021..00a3e20813 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_data_type_time_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- data_type_time.bro +data_type_time.bro event connection_established(c: connection) { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest index 762e8a1651..e542572647 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_01_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_logging_factorial_01.bro +framework_logging_factorial_01.bro module Factor; diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest index 6972c285f9..ce2a9106cd 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_02_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_logging_factorial_02.bro +framework_logging_factorial_02.bro module Factor; diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest index 9e7846eb59..631875ba2a 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_03_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_logging_factorial_03.bro +framework_logging_factorial_03.bro event bro_init() { diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest index b2e85f0c90..035f8d90bc 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_logging_factorial_04_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_logging_factorial_04.bro +framework_logging_factorial_04.bro module Factor; diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest index 632efc9b90..96a3b5a921 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_01_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_notice_hook_01.bro +framework_notice_hook_01.bro @load policy/protocols/ssh/interesting-hostnames.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest index 0d5eb7e25f..b51bd2eebe 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_hook_suppression_01_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_notice_hook_suppression_01.bro +framework_notice_hook_suppression_01.bro @load policy/protocols/ssl/expiring-certs.bro diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest index 80e464f312..0202fa3a28 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_01_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_notice_shortcuts_01.bro +framework_notice_shortcuts_01.bro @load policy/protocols/ssh/interesting-hostnames.bro @load base/protocols/ssh/ diff --git a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest index 0418955ab2..266a2e1fbb 100644 --- a/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest +++ b/testing/btest/doc/sphinx/include-doc_scripting_framework_notice_shortcuts_02_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- framework_notice_shortcuts_02.bro +framework_notice_shortcuts_02.bro @load policy/protocols/ssh/interesting-hostnames.bro @load base/protocols/ssh/ diff --git a/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest index 0d981e7fc0..c77e08c5a1 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_bif_event_bif_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- event.bif.bro +event.bif.bro ## Generated for every new connection. This event is raised with the first ## packet of a previously unknown connection. Bro uses a flow-based definition diff --git a/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest index b393c0580b..6e15ece5e0 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_bif_plugins_Bro_DNS_events_bif_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- Bro_DNS.events.bif.bro +Bro_DNS.events.bif.bro ## Generated for DNS requests. For requests with multiple queries, this event ## is raised once for each. diff --git a/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest index c42a63f6ad..0057a78cc4 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_init-bare_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- init-bare.bro +init-bare.bro type string_array: table[count] of string; type string_set: set[string]; diff --git a/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest index ddbe628009..9966341119 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_protocols_conn_main_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- main.bro +main.bro module Conn; diff --git a/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest b/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest index 0acb7a17e8..c2e558bac8 100644 --- a/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_base_protocols_http_main_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- main.bro +main.bro module HTTP; diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest index 9220e6abf7..26911a534c 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- detect-MHR.bro +detect-MHR.bro ##! Detect file downloads that have hash values matching files in Team ##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest index 656abf3ba1..4ce4383efb 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@2.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- detect-MHR.bro +detect-MHR.bro @load base/frameworks/files @load base/frameworks/notice diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest index 75d94f6990..b8a0abf363 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@3.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- detect-MHR.bro +detect-MHR.bro export { redef enum Notice::Type += { diff --git a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest index 7e3e1b0a11..57d2d7ee50 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_frameworks_files_detect-MHR_bro@4.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- detect-MHR.bro +detect-MHR.bro event file_hash(f: fa_file, kind: string, hash: string) { diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest index db7f3d355b..150de38f35 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_conn_known-hosts_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- known-hosts.bro +known-hosts.bro module Known; diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest index 2a395ab20e..2ff1a711be 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- interesting-hostnames.bro +interesting-hostnames.bro ##! This script will generate a notice if an apparent SSH login originates ##! or heads to a host with a reverse hostname that looks suspicious. By diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest index 6a630796c0..aff7dffff7 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssl_expiring-certs_bro.btest @@ -1,6 +1,6 @@ # @TEST-EXEC: cat %INPUT >output && btest-diff output --- expiring-certs.bro +expiring-certs.bro NOTICE([$note=Certificate_Expires_Soon, $msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after), From f30b527581999712aa8cb07b3dee04b315e552bb Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 7 Oct 2013 16:59:09 -0700 Subject: [PATCH 397/881] Line numbers in scripting introduction were off now. I don't quite like yet how line numbers are shown but it has to work for now. --- aux/btest | 2 +- doc/scripting/index.rst | 38 +++++++++++++++++++------------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/aux/btest b/aux/btest index d01422b9c8..e79c3e2cf3 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit d01422b9c8022ce787b157eb59580f5be169d060 +Subproject commit e79c3e2cf3efab51fee3c6b77dc8beb4d6af2ee7 diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 5c85781300..8e503fcc97 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -54,7 +54,7 @@ script and much more in following sections. .. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro :lines: 4-6 -Lines 7 and 8 of the script process the ``__load__.bro`` script in the +Lines 3 to 5 of the script process the ``__load__.bro`` script in the respective directories being loaded. The ``@load`` directives are often considered good practice or even just good manners when writing Bro scripts to make sure they can be used on their own. While it's unlikely that in a @@ -95,7 +95,7 @@ the information associated with a file for which Bro's file analysis framework h generated a hash. The event handler is passed the file itself as ``f``, the type of digest algorithm used as ``kind`` and the hash generated as ``hash``. -On line 35, an ``if`` statement is used to check for the correct type of hash, in this case +On line 3, an ``if`` statement is used to check for the correct type of hash, in this case a SHA1 hash. It also checks for a mime type we've defined as being of interest as defined in the constant ``match_file_types``. The comparison is made against the expression ``f$mime_type``, which uses the ``$`` dereference operator to check the value ``mime_type`` inside the variable ``f``. Once both @@ -111,18 +111,18 @@ this event continues and upon receipt of the values returned by :bro:id:`lookup_hostname_txt`, the ``when`` block is executed. The ``when`` block splits the string returned into a portion for the date on which the malware was first detected and the detection rate by splitting on an text space -and storing the values returned in a local table variable. In line 42, if the table +and storing the values returned in a local table variable. In line 12, if the table returned by ``split1`` has two entries, indicating a successful split, we store the detection -date in ``mhr_first_detect`` and the rate in ``mhr_detect_rate`` on lines 45 and 45 respectively +date in ``mhr_first_detected`` and the rate in ``mhr_detect_rate`` on lines 14 and 15 respectively using the appropriate conversion functions. From this point on, Bro knows it has seen a file transmitted which has a hash that has been seen by the Team Cymru Malware Hash Registry, the rest of the script is dedicated to producing a notice. -On line 47, the detection time is processed into a string representation and stored in +On line 17, the detection time is processed into a string representation and stored in ``readable_first_detected``. The script then compares the detection rate against the -``notice_threshold`` that was defined on line 30. If the detection rate is high enough, the script -creates a concise description of the notice on line 50, a possible URL to check the sample against -virustotal.com's database, and makes the call to :bro:id:`NOTICE` to hand the relevant information +``notice_threshold`` that was defined earlier. If the detection rate is high enough, the script +creates a concise description of the notice on line 22, a possible URL to check the sample against +``virustotal.com``'s database, and makes the call to :bro:id:`NOTICE` to hand the relevant information off to the Notice framework. In approximately 25 lines of code, Bro provides an amazing @@ -509,16 +509,16 @@ values don't have to be unique, each key in the table must be unique to preserve a one-to-one mapping of keys to values. In the example below, we've compiled a table of SSL-enabled services and their common ports. The explicit declaration and constructor for the table on -lines 3 and 4 lay out the data types of the keys (strings) and the +lines 5 and 7 lay out the data types of the keys (strings) and the data types of the yields (ports) and then fill in some sample key and -yield pairs. Line 5 shows how to use a table accessor to insert one +yield pairs. Line 8 shows how to use a table accessor to insert one key-yield pair into the table. When using the ``in`` operator on a table, you are effectively working with the keys of the table. In the case of an ``if`` statement, the ``in`` operator will check for membership among -the set of keys and return a true or false value. As seen on line 7, +the set of keys and return a true or false value. As seen on line 10, we are checking if ``SMTPS`` is not in the set of keys for the ssl_services table and if the condition holds true, we add the -key-yield pair to the table. Line 12 shows the use of a ``for`` statement +key-yield pair to the table. Line 13 shows the use of a ``for`` statement to iterate over each key currently in the table. .. btest-include:: ${DOC_ROOT}/scripting/data_struct_table_declaration.bro @@ -780,7 +780,7 @@ inequality operators through the ``==`` and ``!=`` operators respectively. When used in this manner however, the string must match entirely to resolve to true. For example, the script below uses two ternary conditional statements to illustrate the use of the ``==`` -operators with patterns. On lines 5 and 8 the output is altered based +operators with patterns. On lines 8 and 11 the output is altered based on the result of the comparison between the pattern and the string. .. btest-include:: ${DOC_ROOT}/scripting/data_type_pattern_02.bro @@ -934,12 +934,12 @@ method and produce a logfile. As we are working within a namespace and informing an outside entity of workings and data internal to the namespace, we use an ``export`` block. First we need to inform Bro that we are going to be adding another Log Stream by adding a value to -the :bro:type:`Log::ID` enumerable. In line 3 of the script, we append the +the :bro:type:`Log::ID` enumerable. In line 6 of the script, we append the value ``LOG`` to the ``Log::ID`` enumerable, however due to this being in an export block the value appended to ``Log::ID`` is actually ``Factor::Log``. Next, we need to define the name and value pairs -that make up the data of our logs and dictate its format. Lines 5 -through 9 define a new datatype called an ``Info`` record (actually, +that make up the data of our logs and dictate its format. Lines 8 +through 11 define a new datatype called an ``Info`` record (actually, ``Factor::Info``) with two fields, both unsigned integers. Each of the fields in the ``Factor::Log`` record type include the ``&log`` attribute, indicating that these fields should be passed to the @@ -948,7 +948,7 @@ any name value pairs without the ``&log`` attribute, those fields would simply be ignored during logging but remain available for the lifespan of the variable. The next step is to create the logging stream with :bro:id:`Log::create_stream` which takes a Log::ID and a -record as its arguments. In this example, on line 28, we call the +record as its arguments. In this example, on line 25, we call the ``Log::create_stream`` method and pass ``Factor::LOG`` and the ``Factor::Info`` record as arguments. From here on out, if we issue the ``Log::write`` command with the correct ``Log::ID`` and a properly @@ -1153,12 +1153,12 @@ possible while staying concise. While much of the script relates to the actual detection, the parts specific to the Notice Framework are actually quite interesting in -themselves. On line 12 the script's ``export`` block adds the value +themselves. On line 18 the script's ``export`` block adds the value ``SSH::Interesting_Hostname_Login`` to the enumerable constant ``Notice::Type`` to indicate to the Bro core that a new type of notice is being defined. The script then calls ``NOTICE`` and defines the ``$note``, ``$msg``, ``$sub`` and ``$conn`` fields of the -:bro:type:`Notice::Info` record. Line 39 also includes a ternary if +:bro:type:`Notice::Info` record. Line 42 also includes a ternary if statement that modifies the ``$msg`` text depending on whether the host is a local address and whether it is the client or the server. This use of :bro:id:`fmt` and a ternary operators is a concise way to From 138d5707d4540acf9799b7c2841d5ce7d606d068 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 7 Oct 2013 17:06:38 -0700 Subject: [PATCH 398/881] Updating copyright notice. --- COPYING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/COPYING b/COPYING index 7b0a94a03b..2c66f98113 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 1995-2012, The Regents of the University of California +Copyright (c) 1995-2013, The Regents of the University of California through the Lawrence Berkeley National Laboratory and the International Computer Science Institute. All rights reserved. From 541f9121f0d1d9a84d26eaf818f267f931af2041 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 7 Oct 2013 17:13:13 -0700 Subject: [PATCH 399/881] Fixing the historical CHANGES record. Some entries were duplicated, while others were missing. --- CHANGES | 9787 ++++++++------------------------------------------ aux/binpac | 2 +- aux/bro-aux | 2 +- aux/broccoli | 2 +- aux/broctl | 2 +- aux/btest | 2 +- 6 files changed, 1522 insertions(+), 8275 deletions(-) diff --git a/CHANGES b/CHANGES index 1fd1222e7c..4acb9d06eb 100644 --- a/CHANGES +++ b/CHANGES @@ -4496,30 +4496,67 @@ - ClamAV support has been removed, which has been non-functional for a while already. -1.5.2.7 Sun Sep 12 19:39:49 PDT 2010 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -- Addressed a number of lint nits (Vern Paxson). +1.5.3 Thu Mar 3 08:55:11 PST 2011 +- Removing aux/broctl/policy/cluster-addrs.hot.bro from the + distribution. The script is no longer needed and could in fact break + an installation because it redefines an old variable that has went + away. (Robin Sommer) -1.5.2.6 Sun Sep 12 17:00:13 PDT 2010 +- Smarter way to increase the communication module's pipe's socket + buffer size, resulting in a value closer to the allowed maximum. + (Craig Leres) + +- BroControl now also maintains links from the log archive to the + current set of logs when running in standalone mode. (Robin Sommer) + +- Bug fix for a file descriptor leak in the remote communication + module. (Scott Campbell) + +- Bug fix for BroControl to now activate trace-summary's sampling in + cluster mode, but not anymore in standalone mode. (Robin Sommer) + +- Broccoli updates: + + * Accept empty strings ("") as values in the configuration file. + (Craig Leres) + + * Support for specifying a separate host key for SSL-enabled + operation, with documentation update. (Craig Leres) + +1.5.2 Wed Jan 12 17:34:55 PST 2011 + +- Portability fixes for --enable-int64 (Vern Paxson). + +- Bug fix for Active Mapping support (Kevin Lo). + +- Broccoli compiler warning fixes (Kevin Lo). + +- Bug fixes for --enable-int64 and for avoiding bogus statistics / + bad memory references when generating profiling information upon + exit (Vern Paxson). + +- Bug fixes for terminating connections (Tyler Schoenke and Vern Paxson). + +- Removed now-quite-stale SSHv1 overflow detection, as it's more prone + to false positives than useful detection (Vern Paxson). - The SWIG file now explicitly lists those pieces from broccoli.h which it wants to wrap, rather than just including all of broccoli.h (Robin Sommer). - This fixes the problem that the SWIG bindings depend on what configure - finds out about the availability of libpcap even though the corresponding - functions don't need to be wrapped anyway. -- http-header.bro now includes a global include_header: set[string] - (Robin Sommer). If it contains any strings, then only those headers - will be processed. If left empty, then you continue to get the current - behavior of processing all headers. +- http-header.bro now includes a global "include_header: set[string]" If it + contains any strings, then only those headers will be processed. If left + empty, then you continue to get the current behavior of processing all + headers. (Robin Sommer). - Several changes to drop.bro (Robin Sommer): - * If true, the new flag Drop::dont_drop_locals indicates that + * If True, the new flag Drop::dont_drop_locals indicates that local hosts should never be dropped. On by default. - * If true, the new flag Drop::debugging activates extensive debugging + * If True, the new flag Drop::debugging activates extensive debugging output for the catch-and-release logic. Off by default. * The timeout for tracking dropping information is now 1 day @@ -4533,14 +4570,14 @@ Sommer). - The HTTP analyzer no longer attempts to track Server/User-Agent - versions, as these are hugely voluminous (Seth Hall). Ideally this - would still be available as an option for someone who truly wants - the full set. + versions, as these are hugely voluminous (Seth Hall). - HTTP and SMTP no longer have extra-short inactivity timeouts, as these were too often leading to premature expiration of a connection (Robin Sommer). +- Tracking of HTTP refer[r]er's by setting log_referrer. (Vern Paxson). + - The "rst" tool (aux/rst/) now takes an optional "-I " argument that instructs it to inject as payload rather than sending a RST packet (Vern Paxson). must be NUL-terminated, and the NUL is not @@ -4549,39 +4586,113 @@ - Bug fix for crashes in the DNS analyzer when processing replies for which no request was seen (Robin Sommer). +- Addressed a number of lint nits (Vern Paxson). -1.5.2.5 Mon Jul 19 16:20:58 PDT 2010 +- Rotation post-processors are now passed an additional argument + indicating whether Bro is terminating (Robin Sommer). -- Removed now-quite-stale SSHv1 overflow detection, as it's more prone - to false positives than useful detection (Vern Paxson). +- Bro now consistently generates a file_opened event for all fopen() calls. + (Robin Sommer). +- The "cf" utility now ignores a leading "t=" prefix, for compatibility + with Bro's "tagged" logging format (Robin Sommer). -1.5.2.4 Fri Jun 4 16:02:11 PDT 2010 +- You can now redefine the email_notice_to function (Robin Sommer). -- Bug fixes for terminating connections (Tyler Schoenke and Vern Paxson). +- Fix for packet processing resumption when a remote Bro dies during + state synchronization (Robin Sommer). +- OpenSSL/X509 portability fix, at long last (Gregor Maier & Christian + Kreibich). -1.5.2.3 Wed Mar 24 18:23:57 PDT 2010 +- Fix for compatibility with newer versions of autoconf (Gregor Maier). -- Bug fixes for --enable-int64 and for avoiding bogus statistics / - bad memory references when generating profiling information upon - exit (Vern Paxson). +- A larger BroControl update (Robin Sommer, if not marked otherwise): + o Increasing default timeouts for scan detector significantly. -1.5.2.2 Tue Jan 12 12:33:42 PST 2010 + o Increasing the manager's max_remote_events_processed to + something large, as it would slow down the process too much + otherwise and there's no other work to be interleaved with it + anyway. -- Broccoli compiler warning fixes (Kevin Lo). + o Adding debug output to cluster's part of catch-and-release + (extends the debugging already present in policy/debug.bro) + o Fixing typo in util.py. Closes #223. -1.5.2.1 Sun Jan 10 16:59:01 PST 2010 + o Added note to README pointing to HTML version. -- Bug fix for Active Mapping support (Kevin Lo). + o Disabling print_hook for proxies' remote.log. + o broctl's capstats now reports a total as well, and stats.log + tracks these totals. Closes #160. -1.5.2 Sat Dec 26 18:38:37 PST 2009 + o Avoiding spurious "waiting for lock" messages in cron mode. + Closes #206. -- Portability fixes for --enable-int64 (Vern Paxson). + o Bug fixes for installation on NFS. + o Bug fix for top command on FreeBSD 8. + + o crash-diag now checks whether gdb is available. + + o trace-summary reports the sample factor in use in its output, + and now also applies it to the top-local-networks output (not + doing the latter was a bug). + + o Removed the default twice-a-day rotation for conn.log. The + default rotation for conn.log now is now once every 24h, just + like for all other logs with the exception of mail.log (which is + still rotated twice a day, and thus the alarms are still mailed + out twice a day). + + o Fixed the problem of logs sometimes being filed into the wrong + directory (see the (now gone) FAQ entry in the README). + + o One can now customize the archive naming scheme. See the + corresponding FAQ entry in the README. + + o Cleaned up, and extended, collection of cluster statistics. + + ${logdir}/stats now looks like this: + + drwxr-xr-x 4 bro wheel 59392 Apr 5 17:55 . + drwxr-xr-x 96 bro wheel 2560 Apr 6 12:00 .. + -rw-r--r-- 1 bro wheel 576 Apr 6 16:40 meta.dat + drwxr-xr-x 2 bro wheel 2048 Apr 6 16:40 profiling + -rw-r--r-- 1 bro wheel 771834825 Apr 6 16:40 stats.log + drwxr-xr-x 2 bro wheel 2048 Apr 6 16:25 www + + stats.log accumulates cluster statistics collected every time + "cron" is called. + + - profiling/ keeps the nodes' prof.logs. + + - www/ keeps a subset of stats.log in CSV format for easy plotting. + + - meta.dat contains meta information about the current cluster + state (in particular which nodes we have, and when the last + stats update was done). + + Note that there is no Web setup yet to actually visualize the data in + www/. + + o BroControl now automatically maintains links inside today's log + archive directory pointing to the current live version of the + corresponding log file (if Bro is running). For example: + + smtp.log.11:52:18-current -> /usr/local/cluster/spool/manager/smtp.log + + o Alarms mailed out by BroControl now (1) have the notice msg in the + subject; and (2) come with the full mail.log entry in the body. + + o Fixing broctl's top output. (Seth Hall). + + o Fixing broctl's df output in certain situations. + + o BroControl fix for dealing with large vsize values reported by + "top" (Craig Leres). 1.5.1 Fri Dec 18 15:17:12 PST 2009 @@ -10513,8314 +10624,1450 @@ a sorted version (Ruoming Pang). It currently uses an N^2 algorithm so shouldn't be used on large arrays. +- The new built-in subst() substitutes all instances of a given pattern + in a given string with another string (Ruoming Pang). For example, + subst("fooboo", /oo/, "xxx") returns "fxxxbxxx". +- The new built-in cut_tail() trims characters from the end of a string + (Ruoming Pang). For example, cut_tail("fooboo", 2) returns "foob". +- sub_bytes() can now take a negative argument, which is with respect to + the end of the string rather than the beginning (Ruoming Pang). -2.1-826 | 2013-07-25 10:12:26 -0700 +- The new built-in md5_hmac() returns an HMAC-MD5 hash of the given string + (Ruoming Pang). The HMAC secret key is generated from available entropy + when Bro starts up, or it can be specified for repeatability using + the new -K flag. - * bif files declared with bif_target() are now automatically - compiled in. No more manual includes to pull them in. (Robin - Sommer) +- The new built-in split_all() is like split() except that the returned + array also includes the parts of the string that match the pattern + used for the splitting (Ruoming Pang). - * Covenience make target in testing/btest to update the three - coverage tests that usually need tweaking when scripts get - added/removed. (Robin Sommer) +- The new built-in split_n() splits up to a given number of instances, + optionally returning the parts matching the split pattern (Ruoming Pang). -2.1-824 | 2013-07-22 14:25:14 -0400 +- The new built-in split_complete() is the most general of the split functions + (the others are written in terms of it). It splits a given string + with separators that appear in either a given pattern or a given set + of strings, optionally including the text matching the separators in + its return value, and optionally limiting the number of matches to + a specified maximum. (Ruoming Pang) - * Fixed a scriptland state issue that manifested especially badly on proxies. (Seth Hall) +- The new built-in to_string_literal() returns an escaped version of a string + suitable to feeding into Bro's parser. For example, calling it on + "foo\nbar" (where '\n' is an embedded newline) returns "foo\x0abar". + (Ruoming Pang) - * Another test fix. (Robin Sommer) +- subst_substring() has been renamed subst_string (Ruoming Pang). - * Canonyfying the output of core.print-bpf-filters. (Robin Sommer) +- unescape_URI() no longer takes the connection as an argument (Ruoming Pang). -2.1-820 | 2013-07-18 12:30:04 -0700 +- config.guess and config.sub updated - * Extending external canonifier to remove fractional values from - capture_loss.log. (Robin Sommer) +- String escape expansion has been refined (Ruoming Pang) and some bugs + fixed. It now supports a format that's consistent with Bro string literals. - * Canonifying internal order for plugins and their components to - make it deterministic. (Robin Sommer) +- Scanning of octal and hex escape sequences now stops after 3 or 2 + characters, respectively. For example, "\0007" now expands to a + NUL followed by the character '7'. (Ruoming Pang) - * Small raw reader tweaks that got left our earlier. (Robin Sommer) - -2.1-814 | 2013-07-15 18:18:20 -0700 +- Bug fixes for handling of bare and 's when expected + (Ruoming Pang), and associated "weird" events. - * Fixing raw reader crash when accessing nonexistant file, and - memory leak when reading from file. Addresses #1038. (Bernhard - Amann) +- A bug in signature matching reassembly has been fixed (Robin Sommer). -2.1-811 | 2013-07-14 08:01:54 -0700 - - * Bump sqlite to 3.7.17. (Bernhard Amann) - - * Small test fixes. (Seth Hall) - - * Fix a bug where the same analyzer tag was reused for two different - analyzers. (Seth Hall) - - * Moved DPD signatures into script specific directories. Left out - the BitTorrent signatures pending further updates to that - analyzer. (Seth Hall) - -2.1-802 | 2013-07-10 10:55:14 -0700 - - * Const adjustment for methods. (Jon Siwek) - -2.1-798 | 2013-07-08 13:05:37 -0700 - - * Rewrite of the packet filter framework. (Seth Hall) - - This includes: - - - Plugin interface for adding filtering mechanisms. - - - Integrated the packet filter framework with the analyzer - framework to retrieve well-known ports from there. - - - Support for BPF-based load balancing (IPv4 and IPv6). This will - tie in with upcoming BroControl support for configuring this. - - - Support for BPF-based connection sampling. - - - Support for "shunting" traffic with BPF filters. - - - Replaced PacketFilter::all_packets with - PacketFilter::enable_auto_protocol_capture_filters. - -2.1-784 | 2013-07-04 22:28:48 -0400 - - * Add a call to lookup_connection in SSH scripts to update connval. (Seth Hall) - - * Updating submodule(s). (Robin Sommer) - -2.1-782 | 2013-07-03 17:00:39 -0700 - - * Remove the SSL log queueing mechanism that was included with the - log delay mechanism. (Seth Hall) - -2.1-780 | 2013-07-03 16:46:26 -0700 - - * Rewrite of the RAW input reader for improved robustness and new - features. (Bernhard Amann) This includes: - - - Send "end_of_data" event for all kind of streams. - - Send "process_finished" event with exit code of child - process at process termination. - - Expose name of input stream to readers. - - Better error handling. - - New "force_kill" option which SIGKILLs processes on reader termination. - - Supports reading from stdout and stderr simultaneously. - - Support sending data to stdin of child process. - - Streaming reads from external commands work without blocking. - -2.1-762 | 2013-07-03 16:33:22 -0700 - - * Fix to correct support for TLS 1.2. Addresses #1020. (Seth Hall, - with help from Rafal Lesniak). - -2.1-760 | 2013-07-03 16:31:36 -0700 - - * Teach broxygen to generate protocol analyzer plugin reference. - (Jon Siwek) - - * Adding 'const' to a number of C++ methods. (Jon Siwek) - -2.1-757 | 2013-07-03 16:28:10 -0700 - - * Fix redef of table index from clearing table. - - `redef foo["x"] = 1` now acts like `redef foo += { ["x"] = 1 }` - instead of `redef foo = { ["x"] = 1 }`. - - Addresses #1013. (Jon Siwek) - - -2.1-755 | 2013-07-03 16:22:43 -0700 - - * Add a general file analysis overview/how-to document. (Jon Siwek) - - * Improve file analysis doxygen comments. (Jon Siwek) - - * Improve tracking of HTTP file extraction. http.log now has files - taken from request and response bodies in different fields for - each, and can now track multiple files per body. That is, the - "extraction_file" field is now "extracted_request_files" and - "extracted_response_files". Addresses #988. (Jon Siwek) - - * Fix HTTP multipart body file analysis. Each part now gets assigned - a different file handle/id. (Jon Siwek) - - * Remove logging of analyzers field of FileAnalysis::Info. (Jon - Siwek) - - * Remove extraction counter in default file extraction scripts. (Jon - Siwek) - - * Remove FileAnalysis::postpone_timeout. - FileAnalysis::set_timeout_interval can now perform same function. - (Jon Siwek) - - * Make default get_file_handle handlers &priority=5 so they're - easier to override. (Jon Siwek) - - * Add input interface to forward data for file analysis. The new - Input::add_analysis function is used to automatically forward - input data on to the file analysis framework. (Jon Siwek) - - * File analysis framework interface simplifications. (Jon Siwek) - - - Remove script-layer data input interface (will be managed directly - by input framework later). - - - Only track files internally by file id hash. Chance of collision - too small to justify also tracking unique file string. - - -2.1-741 | 2013-06-07 17:28:50 -0700 - - * Fixing typo that could cause an assertion to falsely trigger. - (Robin Sommer) - -2.1-740 | 2013-06-07 16:37:32 -0700 - - * Fix for CMake 2.6.x. (Robin Sommer) - -2.1-738 | 2013-06-07 08:38:13 -0700 - - * Remove invalid free on non-allocated pointer in hash function - object. Addresses #1018. (Matthias Vallentin) - -2.1-736 | 2013-06-06 10:05:20 -0700 - - * New "magic constants" @DIR and @FILENAME that expand to the - directory path of the current script and just the script file name - without path, respectively. (Jon Siwek) - -2.1-731 | 2013-06-04 21:19:08 -0700 - - * Reorginization of internal protocol analyzer code. We're moving - them to a modularized structure, based on a plugin model. Along - with this change comes generic plugin infrastructure that we'll - later extend to other Bro component as well. For now all plugins - are compiled in statically, but in the future we plan to also - enable dynamic loading at run time. (Robin Sommer) - - * Ignoring file ids in external tests. (Robin Sommer) - -2.1-675 | 2013-06-02 20:03:19 -0700 - - * Fix a compiler warning. (Robin Sommer) - - * Allow named vector/set/table/record constructors. Addresses #983. - (Jon Siwek) - - * Adding Makefile target test-all that also runs the BroControl test - suite. (Robin Sommer) - -2.1-664 | 2013-05-28 21:37:46 -0700 - - * Dangling pointer fix. Addresses #1004. (Jon Siwek) - -2.1-659 | 2013-05-24 17:24:18 -0700 - - * Fix broken/missing documentation. (Jon Siwek) - - * Fixing test that would fail without ES/curl support. (Robin - Sommer) - -2.1-656 | 2013-05-17 15:58:07 -0700 - - * Fix mutex lock problem for writers. (Bernhard Amann) - -2.1-654 | 2013-05-17 13:49:52 -0700 - - * Tweaks to sqlite3 configuration to address threading issues. - (Bernhard Amann) - -2.1-651 | 2013-05-17 13:37:16 -0700 - - * Fix uninitialized DPM member. (Jon Siwek) - - * Fix issue with transaction ID reuse in a single DNS connection. (Seth Hall) - - * New function added to the queue.bro script to support peeking at - the new gettable item in the queue without removing it. (Seth Hall) - -2.1-647 | 2013-05-17 07:47:14 -0700 - - * Fixing Broxygen generation to have BROMAGIC set. (Robin Sommer) - - * Fix for 'fchmod undeclared here' on FreeBSD. (Robin Sommer) - - * CMake policy fix to avoid errors with older versions. (Robin - Sommer) - -2.1-641 | 2013-05-15 18:15:09 -0700 - - * Test update. (Robin Sommer) - -2.1-640 | 2013-05-15 17:24:09 -0700 - - * Support for cleaning up threads that have terminated. (Bernhard - Amann and Robin Sommer). Includes: - - - Both logging and input frameworks now clean up threads once - they aren't further needed anymnore. - - - New function Log::remove_stream() that removes a logging - stream, stopping all writer threads that are associated with - it. Note, however, that removing a *filter* from a stream - still doesn't clean up any threads. The problem is that - because of the output paths potentially being created - dynamically it's unclear if the writer thread will still be - needed in the future. - -2.1-626 | 2013-05-15 16:09:31 -0700 - - * Add "reservoir" sampler for SumStats framework. This maintains - a set of N uniquely distributed random samples. (Bernhard Amann) - -2.1-619 | 2013-05-15 16:01:42 -0700 - - * SQLite reader and writer combo. This allows to read/write - persistent data from on disk SQLite databases. The current - interface is quite low-level, we'll add higher-level abstractions - in the future. (Bernhard Amann) - -2.1-576 | 2013-05-15 14:29:09 -0700 - - * Initial version of new file analysis framework. This moves most of - the processing of file content from script-land into the core, - where it belongs. Much of this is an internal change, and at this - point the new code has essentially feature-equality with the old - one. More script-level changes to come. (Jon Siwek) - -2.1-502 | 2013-05-10 19:29:37 -0700 - - * Allow default function/hook/event parameters. Addresses #972. (Jon - Siwek) - - * Change the endianness parameter of bytestring_to_count() BIF to - default to false (big endian). (Jon Siwek) - -2.1-500 | 2013-05-10 19:22:24 -0700 - - * Fix to prevent merge-hook of SumStat's unique plugin from damaging - source data. (Bernhard Amann) - -2.1-498 | 2013-05-03 17:44:08 -0700 - - * Table lookups return copy of non-const &default vals. This - prevents unintentional modifications to the &default value itself. - Addresses #981. (Jon Siwek) - -2.1-496 | 2013-05-03 15:54:47 -0700 - - * Fix memory leak and unnecessary allocations in OpaqueVal. - Addresses #986. (Matthias Vallentin) - -2.1-492 | 2013-05-02 12:46:26 -0700 - - * Work-around for sumstats framework not propagating updates after - intermediate check in cluster environments. (Bernhard Amann) - - * Always apply tcp_connection_attempt. Before this change it was - only applied when a connection_attempt() event handler was - defined. (Robin Sommer) - - * Fixing coverage.bare-mode-errors test. (Robin Sommer) - -2.1-487 | 2013-05-01 18:03:22 -0700 - - * Always apply tcp_connection_attempt timer, even if no - connection_attempt() event handler is defined. (Robin Sommer) - -2.1-486 | 2013-05-01 15:28:45 -0700 - - * New framework for computing summary statistics in - base/framework/sumstats. This replaces the metrics frameworks, and - comes with a number of applications build on top, see NEWS. More - documentation to follow. (Seth Hall) - -2.1-397 | 2013-04-29 21:19:00 -0700 - - * Fixing memory leaks in CompHash implementation. Addresses #987. - (Robin Sommer) - -2.1-394 | 2013-04-27 15:02:31 -0700 - - * Fixed a bug in the vulnerable software script and added a test. - (Seth Hall) - - * Fix schedule statements used outside event handlers. Addresses - #974. (Jon Siwek) - - * Fix record coercion for default inner record fields. Addresses - #973. (Jon Siwek) - - * Add bytestring_to_count function to bro.bif. Addresses #968. (Yun - Zheng Hu) - -2.1-386 | 2013-03-22 12:41:50 -0700 - - * Added reverse() function to strings.bif. (Yun Zheng Hu) - -2.1-384 | 2013-03-22 12:10:14 -0700 - - * Fix record constructors in table initializer indices. Addresses - #660. (Jon Siwek) - -2.1-382 | 2013-03-22 12:01:34 -0700 - - * Add support for 802.1ah (Q-in-Q). Addresses #641. (Seth Hall) - -2.1-380 | 2013-03-18 12:18:10 -0700 - - * Fix gcc compile warnings in base64 encoder and benchmark reader. - (Bernhard Amann) - -2.1-377 | 2013-03-17 17:36:09 -0700 - - * Fixing potential leak in DNS error case. (Vlad Grigorescu) - -2.1-375 | 2013-03-17 13:14:26 -0700 - - * Add base64 encoding functionality, including new BiFs - encode_base64() and encode_base64_custom(). (Bernhard Amann) - - * Replace call to external "openssl" in extract-certs-pem.bro with - that encode_base64(). (Bernhard Amann) - - * Adding a test for extract-certs-pem.pem. (Robin Sommer) - - * Renaming Base64Decoder to Base64Converter. (Robin Sommer) - -2.1-366 | 2013-03-17 12:35:59 -0700 - - * Correctly handle DNS lookups for software version ranges. (Seth - Hall) - - * Improvements to vulnerable software detection. (Seth Hall) - - - Add a DNS based updating method. This needs to be tested - still. - - - Vulnerable version ranges are used now instead of only single - versions. This can deal with software with multiple stable - major versions. - - * Update software version parsing and comparison to account for a - third numeric subversion. Also, $addl is now compared numerically - if the value is actually numeric. (Seth Hall) - -2.1-361 | 2013-03-13 07:18:22 -0700 - - * Add check for truncated link frames. Addresses #962. (Jacob - Baines) - - * Fix large memory allocation in IP fragment reassembly. Addresses - #961. (Jacob Baines) - -2.1-357 | 2013-03-08 09:18:35 -0800 - - * Fix race-condition in table-event test. (Bernhard Amann) - - * s/bro-ids.org/bro.org/g. (Robin Sommer) - -2.1-353 | 2013-03-07 13:31:37 -0800 - - * Fix function type-equivalence requiring same parameter names. - Addresses #957. (Jon Siwek) - -2.1-351 | 2013-03-07 13:27:29 -0800 - - * Fix new/delete mismatch. Addresses #958. (Jacob Baines) - - * Fix compiler warnings. (Jon Siwek) - -2.1-347 | 2013-03-06 16:48:44 -0800 - - * Remove unused parameter from vector assignment method. (Bernhard Amann) - - * Remove the byte_len() and length() bifs. (Bernhard Amann) - -2.1-342 | 2013-03-06 15:42:52 -0800 - - * Moved the Notice::notice event and Notice::policy table to both be - hooks. See documentation and NEWS for information. (Seth Hall). - -2.1-338 | 2013-03-06 15:10:43 -0800 - - * Fix init of local sets/vectors via curly brace initializer lists. - (Jon Siwek) - -2.1-336 | 2013-03-06 15:08:06 -0800 - - * Fix memory leaks resulting from 'when' and 'return when' - statements. Addresses #946. (Jon Siwek) - - * Fix three bugs with 'when' and 'return when' statements. Addresses - #946. (Jon Siwek) - -2.1-333 | 2013-03-06 14:59:47 -0800 - - * Add parsing for GTPv1 extension headers and control messages. (Jon Siwek) - - This includes: - - - A new generic gtpv1_message() event generated for any GTP - message type. - - - Specific events for the create/update/delete PDP context - request/response messages. - - Addresses #934. - -2.1-331 | 2013-03-06 14:54:33 -0800 - - * Fix possible null pointer dereference in identify_data BIF. Also - centralized libmagic calls for consistent error handling/output. - (Jon Siwek) - - * Fix build on OpenBSD 5.2. (Jon Siwek) - -2.1-328 | 2013-02-05 01:34:29 -0500 - - * New script to query the ICSI Certificate Notary - (http://notary.icsi.berkeley.edu/) over DNS and add information - to the SSL log at runtime. (Matthias Vallentin) - - * Add delayed logging to SSL base scripts. (Matthias Vallentin) - -2.1-319 | 2013-02-04 09:45:34 -0800 - - * Update input tests to use exit_only_after_terminate. (Bernhard - Amann) - - * New option exit_only_after_terminate to prevent Bro from exiting. - If set, the main loop won't terminate before somebody calls - terminate(). (Robin Sommer) - -2.1-311 | 2013-02-01 08:03:01 -0800 - - * Updating submodule(s). - -2.1-310 | 2013-01-30 20:09:27 -0800 - - * Add an error for record coercions that would orphan a field. (Jon - Siwek) - - * Fixing several scripts where a field in an inlined record was - never removed after a code refactor. (Jon Siwek) - -2.1-307 | 2013-01-25 13:50:57 -0800 - - * Fix runaway reference counting bug in record coercion. (Jon Siwek) - - * Fix memory leak in some reporter messaging cases. (Jon Siwek) - -2.1-304 | 2013-01-23 19:43:27 -0800 - - * Making a test portable. (Robin Sommer) - -2.1-302 | 2013-01-23 16:17:29 -0800 - - * Refactoring ASCII formatting/parsing from loggers/readers into a - separate AsciiFormatter class. (Bernhard Amann) - - * Fix uninitialized locals in event/hook handlers from having a - value. Addresses #932. (Jon Siwek) - - * Add a null value check in CompositeHash::ComputeHash. Addresses - #930. (Jon Siwek) - - * Change reporter messages to more reliably print to stderr. - Addressed #930 (and revisits #836). (Jon Siwek) - - * Changing test=suite's btest call to use "-j" instead of "-j 5". - (Robin Sommer) - - * Require "case" blocks to end with either "break", "return", or a - new "fallthrough" statement that passes control on to the - subsequent case. This gives us the best mix of safety, - readability, and flexibility. Addresses #754. (Jon Siwek) - -2.1-279 | 2013-01-18 17:18:22 -0800 - - * Revert "Trick for parallelizing input framework unit tests." The - old way of doing the tests seems more reliable for now. (Jon - Siwek) - - * Fixing variable size issues with http response code in - ElasticSearch writer. (Gilbert Clark) - - * Removing unused class member. (Robin Sommer) - - * Add opaque type-ignoring for the accept_unsupported_types input - framework option. (Bernhard Amann) - -2.1-271 | 2013-01-08 10:18:57 -0800 - - * Change substring index notation to use a colon. String slice - notation is now written as `s[1:2]`. Addresses #422. (Jon Siwek) - -2.1-268 | 2013-01-07 09:43:44 -0800 - - * Fix memory leak in OpaqueType::DoUnserialize. (Jon Siwek) - -2.1-265 | 2012-12-20 17:38:42 -0800 - - * Add array-style index accessor for strings. Addresses #422. (Jon - Siwek) - - The index expression can take up to two indices for the start and - end index of the substring to return (e.g. "mystring[1,3]"). - Negative indices are allowed, with -1 representing the last - character in the string. The indexing is not cyclic -- if the - starting index is >= the length of the string an empty string is - returned, and if the ending index is >= the length of the string - then it's interpreted as the last index of the string. Assigning - to substrings accessed like this isn't allowed. - -2.1-263 | 2012-12-20 16:22:09 -0800 - - * Bro's language now has a new set of types "opaque of X". (Matthias - Vallentin) - - Opaque values can be passed around like other values but they can - only be manipulated with BiF functions, not with other operators. - Currently, the following opaque types are supported: - - - opaque of md5 - - opaque of sha1 - - opaque of sha256 - - opaquey of entropy. - - They go along with the corrsponding BiF functions md5_*, sha1_*, - sha256_*, and entropy_*, respectively. Note that these functions - have changed their signatures to work with opaques types rather - than global state as it was before. - -2.1-240 | 2012-12-20 15:21:07 -0800 - - * Improve error for invalid use of types as values. Addresses #923. - (Jon Siwek) - -2.1-238 | 2012-12-20 15:11:25 -0800 - - * Finish implementation of script-layer switch statement. Addresses - #754. (Jon Siwek) - - They behave like C-style switches except case labels can be - comprised of multiple literal constants delimited by commas. Only - atomic types are allowed for now. Case label bodies that don't - execute a "return" or "break" statement will fall through to - subsequent cases. A default case label is allowed. - - * Fix a case where c$resp$size is misrepresented. Addresses #730. - (Jon Siwek) - -2.1-234 | 2012-12-20 12:12:19 -0800 - - * Fix return value of hook calls that have no handlers. For this - case, the return value is always true. (Jon Siwek) - - * Fix to_port() BIF for port strings with a port number of zero. - (Jon Siwek) - -2.1-231 | 2012-12-14 14:51:35 -0800 - - * Make const variables actually constant. Both local and global - variables declared with "const" could be modified, but now - expressions that would modify them generate an error message at - parse-time. Addresses #922. (Jon Siwek) - -2.1-229 | 2012-12-14 14:46:12 -0800 - - * Fix memory leak in ASCII reader when encoutering errors in input. - (Bernhard Amann) - - * Improvements for the "bad checksums" detector to make it detect - bad TCP checksums. (Seth Hall) - -2.1-223 | 2012-12-12 14:25:15 -0800 - - * Trick for parallelizing input framework unit tests. Instead of - loading listen.bro to block until files are read, just read a pcap - file in pseudo-realtime. (Jon Siwek) - - * Fix reliability of a unit test that relies on when statements. - (Jon Siwek) - - * Remove unused attributes. (Daniel Thayer) - - Removed attributes &postprocessor and &match from documentation and source code. - - Removed undocumented attribute &attr from source code. - - Removed internal attribute "(&tracked)" from documentation. - -2.1-218 | 2012-12-10 14:45:04 -0800 - - * Add GPRS Tunnelling Protocol (GTPv1) decapsulation. This currently - supports automatic decapsulation of GTP-U packets on UDP port 2152. - The GTPv1 headers for such tunnels can be inspected by handling - the "gtpv1_g_pdu_packet" event, which has a parameter of type - "gtpv1_hdr". Addresses #690. (Jon Siwek; derived from patch by - Carsten Langer) - - * Change BinPAC exceptions in AYIYA/GTP analyzers to do - "protocol_violation". (Jon Siwek) - -2.1-212 | 2012-12-07 19:42:03 -0800 - - * Changing the HTTP parser to accept request methods in alignment - with the RFC. (Robin Sommer) - -2.1-209 | 2012-12-05 16:44:04 -0800 - - * Adapting the HTTP request line parsing to only accept methods - consisting of letters [A-Za-z]. (Robin Sommer) - -2.1-207 | 2012-12-05 15:47:32 -0800 - - * Reporting warnings if kill/waitpid fail in communication system. - (Bill Parker) - - * Replace() bzero with memset(). (Bill Parker) - - * Merge remote-tracking branch 'vlad/topic/vladg/http-verbs' - - * vlad/topic/vladg/http-verbs: - A test for HTTP methods, including some horribly illegal requests. - Remove hardcoded HTTP verbs from the analyzer (#741) - - I added a "bad_HTTP_request" weird for HTTP request lines that don't - have more than a single word. - - Closes #741. (Robin Sommer) - - * A test for HTTP methods, including some horribly illegal requests. (Vlad Grigorescu) - - * Remove hardcoded HTTP verbs from the analyzer (#741) (Vlad Grigorescu) - - -2.1-203 | 2012-12-05 14:36:56 -0800 - - * Fix segfault: Synchronization of state between connecting peers - now skips over identifiers that aren't initialized with a value - yet. Addresses #66. (Jon Siwek) - - * Fix segfault: Delete correct entry in error case in input - framework. (Bernhard Amann) - - * Bad record constructor initializers now give an error. Addresses - #34. (Jon Siwek) - - * Invalid vector indices now generate error message. Addresses #24. - (Jon Siwek) - - * Bump CPack RPM package requirement to Python >= 2.6.0. (Jon Siwek) - - * Interpreter exceptions occurring in "when" blocks are now handled. - Addresses #779 (Jon Siwek) - -2.1-195 | 2012-12-03 14:50:33 -0800 - - * Catching out-of-memory in patricia tree code. (Bill Parker) - -2.1-194 | 2012-12-03 14:36:26 -0800 - - * Renaming ASCII writer filter option 'only_single_header_row' to - 'tsv'. Also clarifying usage. Closes #912. (Robin Sommer) - -2.1-193 | 2012-12-03 14:11:14 -0800 - - * Fix a set of bugs with table/set attributes. (Jon Siwek) - - - Identifiers that are initialized with set()/table() constructor - expressions now inherit attributes from the expression. Before, - statements like - - const i: set[string] = set() &redef; - - associated the attribute with the set() constructor, but not the - "i" identifier, preventing redefinition. Addresses #866. - - - Allow &default attribute to apply to tables initialized as empty - (via either "{ }" or "table()") or if the expression supplied to it - can evaluate to a type that's promotable to the same yield type as - the table. - -2.1-191 | 2012-12-03 14:08:56 -0800 - - * Add test of record() constructor to table initializer unit test. - (Jon Siwek) - - * Fix table(), set(), vector() constructors in table initializer - lists. Also adds type checking of yield values to table() - constructor and fixes the type checking of yield values in - vector() constructor. Addresses #5. (Jon Siwek) - -2.1-188 | 2012-12-03 14:04:29 -0800 - - * Hook functions now callable with "hook" expression (i.e., hook is - no longer a statement). The return value of the call is an - implicit boolean value of T if all hook handlers ran, or F if one - hook handler exited as a result of a break statement and - potentially prevented other handlers from running. - - Scripts don't need to declare hooks with an explicit return type of bool - (internally, that's assumed), and any values given to (optional) return - statements in handler definitions are just ignored. - - Addresses #918. (Jon Siwek) - - * Clarification in hook documentation. (Jon Siwek) - -2.1-184 | 2012-12-03 13:59:50 -0800 - - * Slightly fix up file name extraction from Content-Disposition - headers. (Seth Hall) - - * Adding -b flag to bro in unit tests so they run faster. - - * Fixed a DNS attribute issue. Reported by Matt Thompson. (Seth - Hall) - - * Adding NEWS placeholder for hooks and CSV mode. (Robin Sommer) - -2.1-178 | 2012-11-23 19:35:32 -0800 - - * The ASCII writer now supports a new filter config option - "only_single_header_row" that turns the output into CSV format - when set to "T". (Carsten Langer) - - * Add new function flavor called a "hook". This new flavor of - function behaves like a "synchronous event". See - doc/scripts/builtins.rst more details on usage. (Jon Siwek) - - * Improve auto-generated enum documentation. The names of enum types - are tracked so that variables holding a value of a given enum type - can generate a reference to it instead of just listing the type as - a generic "enum". (Jon Siwek) - -2.1-171 | 2012-11-23 18:24:15 -0800 - - * Fix ambiguity between composite table index and record ctor - expressions. If a table type is "global t = table[conn_id, bool] - of count", then checking membership like "[c$id, is_orig] in t" - now works. Addresses #80. (Jon Siwek) - -2.1-169 | 2012-11-23 18:21:32 -0800 - - * Fix some warnings from sphinx when building docs. (Jon Siwek) - -2.1-167 | 2012-11-14 13:19:17 -0800 - - * Add a new BIF "bytestring_to_double" for converting from a binary - representation of a double. Addresses #908. (Carsten Langer/Daniel - Thayer) - -2.1-162 | 2012-11-13 17:29:00 -0800 - - * Fix modbus register array parsing. (Jon Siwek) - - * Adjustments to modbus test cases. (Jon Siwek) - -2.1-157 | 2012-11-08 16:22:00 -0800 - - * Fix for lookup_hostname BIF. (Jon Siwek) - - * Fix for modbus test portability. (Robin Sommer) - -2.1-152 | 2012-11-05 16:52:34 -0800 - - * Initial version of a completely reworked intelligence framework. - See doc/intel.rst for more information. (Seth Hall) - - * Experimental Modbus analyzer. See policy/protocols/modbus/* for - example policies. (Dina Hadziosmanovic, Seth Hall) - -2.1-112 | 2012-11-05 13:58:20 -0800 - - * New base script for detecting cases of checksum offloading. - Reporter messages will now tell if one has bad checksums. (Seth - Hall) - - * Clarifying ownership rules for BroString constructors. (Robin - Sommer) - -2.1-109 | 2012-11-05 13:39:34 -0800 - - * Add detection rate threshold for MHR. (Vlad Grigorescu) - - * lookup_hostname_txt fixes. (Vlad Grigorescu) - -2.1-104 | 2012-11-01 10:37:50 -0700 - - * A new built-in function lookup_hostname_txt() provides support for - DNS TXT queries. (Vlad Grigorescu) - -2.1-101 | 2012-10-31 14:30:26 -0700 - - * Documentation reorg: The install info has been consolidated into a - single document (INSTALL), the upgrade info has been moved from - the FAQ to a section in the install doc, and the "upgrading from - 1.5 to 2.0" document has been updated (and renamed) to also - include 2.0 to 2.1 upgrade info. (Daniel Thayer) - -2.1-96 | 2012-10-31 14:23:50 -0700 - - * Renaming option defining the frequency of alarm summary mails to - 'Logging::default_alarm_mail_interval'. (Daniel Thayer) - -2.1-91 | 2012-10-24 16:04:47 -0700 - - * Adding PPPoE support to Bro. (Seth Hall) - -2.1-87 | 2012-10-24 15:40:06 -0700 - - * Adding missing &redef for some TCP options. Addresses #905, #906, - #907. (Carsten Langer) - -2.1-86 | 2012-10-24 15:37:11 -0700 - - * Add parsing rules for IPv4/IPv6 subnet literal constants. - Addresses #888. (Jon Siwek) - -2.1-84 | 2012-10-19 15:12:56 -0700 - - * Added a BiF strptime() to wrap the corresponding C function. (Seth - Hall) - -2.1-82 | 2012-10-19 15:05:40 -0700 - - * Add IPv6 support to signature header conditions. (Jon Siwek) - - - "src-ip" and "dst-ip" conditions can now use IPv6 addresses/subnets. - They must be written in colon-hexadecimal representation and enclosed - in square brackets (e.g. [fe80::1]). Addresses #774. - - - "icmp6" is now a valid protocol for use with "ip-proto" and "header" - conditions. This allows signatures to be written that can match - against ICMPv6 payloads. Addresses #880. - - - "ip6" is now a valid protocol for use with the "header" condition. - (also the "ip-proto" condition, but it results in a no-op in that - case since signatures apply only to the inner-most IP packet when - packets are tunneled). This allows signatures to match specifically - against IPv6 packets (whereas "ip" only matches against IPv4 packets). - - - "ip-proto" conditions can now match against IPv6 packets. Before, - IPv6 packets were just silently ignored which meant DPD based on - signatures did not function for IPv6 -- protocol analyzers would only - get attached to a connection over IPv6 based on the well-known ports - set in the "dpd_config" table. - -2.1-80 | 2012-10-19 14:48:42 -0700 - - * Change how "gridftp" gets added to service field of connection - records. In addition to checking for a finished SSL handshake over - an FTP connection, it now also requires that the SSL handshake - occurs after the FTP client requested AUTH GSSAPI, more - specifically identifying the characteristics of GridFTP control - channels. Addresses #891. (Jon Siwek) - - * Allow faster rebuilds in certain cases. Previously, when - rebuilding with a different "--prefix" or "--scriptdir", all Bro - source files were recompiled. With this change, only util.cc is - recompiled. (Daniel Thayer) - -2.1-76 | 2012-10-12 10:32:39 -0700 - - * Add support for recognizing GridFTP connections as an extension to - the standard FTP analyzer. (Jon Siwek) - - This is enabled by default and includes: - - - An analyzer for GSI mechanism of GSSAPI FTP AUTH method. GSI - authentication involves an encoded TLS/SSL handshake over the - FTP control session. For FTP sessions that attempt GSI - authentication, the *service* field of the connection log will - include "gridftp" (as well as also "ftp" and "ssl"). - - - Add an example of a GridFTP data channel detection script. It - relies on the heuristics of GridFTP data channels commonly - default to SSL mutual authentication with a NULL bulk cipher - and that they usually transfer large datasets (default - threshold of script is 1 GB). The script also defaults to - skip_further_processing() after detection to try to save - cycles analyzing the large, benign connection. - - For identified GridFTP data channels, the *services* fields of - the connection log will include "gridftp-data". - - * Add *client_subject* and *client_issuer_subject* as &log'd fields - to SSL::Info record. Also add *client_cert* and - *client_cert_chain* fields to track client cert chain. (Jon Siwek) - - * Add a script in base/protocols/conn/polling that generalizes the - process of polling a connection for interesting features. The - GridFTP data channel detection script depends on it to monitor - bytes transferred. (Jon Siwek) - -2.1-68 | 2012-10-12 09:46:41 -0700 - - * Rename the Input Framework's update_finished event to end_of_data. - It will now not only fire after table-reads have been completed, - but also after the last event of a whole-file-read (or - whole-db-read, etc.). (Bernhard Amann) - - * Fix for DNS log problem when a DNS response is seen with 0 RRs. - (Seth Hall) - -2.1-64 | 2012-10-12 09:36:41 -0700 - - * Teach --disable-dataseries/--disable-elasticsearch to ./configure. - Addresses #877. (Jon Siwek) - - * Add --with-curl option to ./configure. Addresses #877. (Jon Siwek) - -2.1-61 | 2012-10-12 09:32:48 -0700 - - * Fix bug in the input framework: the config table did not work. - (Bernhard Amann) - -2.1-58 | 2012-10-08 10:10:09 -0700 - - * Fix a problem with non-manager cluster nodes applying - Notice::policy. This could, for example, result in duplicate - emails being sent if Notice::emailed_types is redef'd in local.bro - (or any script that gets loaded on all cluster nodes). (Jon Siwek) - -2.1-56 | 2012-10-03 16:04:52 -0700 - - * Add general FAQ entry about upgrading Bro. (Jon Siwek) - -2.1-53 | 2012-10-03 16:00:40 -0700 - - * Add new Tunnel::delay_teredo_confirmation option that indicates - that the Teredo analyzer should wait until it sees both sides of a - connection using a valid Teredo encapsulation before issuing a - protocol_confirmation. Default is on. Addresses #890. (Jon Siwek) - -2.1-50 | 2012-10-02 12:06:08 -0700 - - * Fix a typing issue that prevented the ElasticSearch timeout to - work. (Matthias Vallentin) - - * Use second granularity for ElasticSearch timeouts. (Matthias - Vallentin) - - * Fix compile issues with older versions of libcurl, which don't - offer *_MS timeout constants. (Matthias Vallentin) - -2.1-47 | 2012-10-02 11:59:29 -0700 - - * Fix for the input framework: BroStrings were constructed without a - final \0, which makes them unusable by basically all internal - functions (like to_count). (Bernhard Amann) - - * Remove deprecated script functionality (see NEWS for details). - (Daniel Thayer) - -2.1-39 | 2012-09-29 14:09:16 -0700 - - * Reliability adjustments to istate tests with network - communication. (Jon Siwek) - -2.1-37 | 2012-09-25 14:21:37 -0700 - - * Reenable some tests that previously would cause Bro to exit with - an error. (Daniel Thayer) - - * Fix parsing of large integers on 32-bit systems. (Daniel Thayer) - - * Serialize language.when unit test with the "comm" group. (Jon - Siwek) - -2.1-32 | 2012-09-24 16:24:34 -0700 - - * Fix race condition in language/when.bro test. (Daniel Thayer) - -2.1-26 | 2012-09-23 08:46:03 -0700 - - * Add an item to FAQ page about broctl options. (Daniel Thayer) - - * Add more language tests. We now have tests of all built-in Bro - data types (including different representations of constant - values, and max./min. values), keywords, and operators (including - special properties of certain operators, such as short-circuit - evaluation and associativity). (Daniel Thayer) - - * Fix construction of ip6_ah (Authentication Header) record values. - - Authentication Headers with a Payload Len field set to zero would - cause a crash due to invalid memory allocation because the - previous code assumed Payload Len would always be great enough to - contain all mandatory fields of the header. (Jon Siwek) - - * Update compile/dependency docs for OS X. (Jon Siwek) - - * Adjusting Mac binary packaging script. Setting CMAKE_PREFIX_PATH - helps link against standard system libs instead of ones that come - from other package manager (e.g. MacPorts). (Jon Siwek) - - * Adjusting some unit tests that do cluster communication. (Jon Siwek) - - * Small change to non-blocking DNS initialization. (Jon Siwek) - - * Reorder a few statements in scan.l to make 1.5msecs etc work. - Adresses #872. (Bernhard Amann) - -2.1-6 | 2012-09-06 23:23:14 -0700 - - * Fixed a bug where "a -= b" (both operands are intervals) was not - allowed in Bro scripts (although "a = a - b" is allowed). (Daniel - Thayer) - - * Fixed a bug where the "!=" operator with subnet operands was - treated the same as the "==" operator. (Daniel Thayer) - - * Add sleeps to configuration_update test for better reliability. - (Jon Siwek) - - * Fix a segfault when iterating over a set when using malformed - index. (Daniel Thayer) - -2.1 | 2012-08-28 16:46:42 -0700 - - * Make bif.identify_magic robust against FreeBSD's libmagic config. - (Robin Sommer) - - * Remove automatic use of gperftools on non-Linux systems. - --enable-perftools must now explicity be supplied to ./configure - on non-Linux systems to link against the tcmalloc library. - - * Fix uninitialized value for 'is_partial' in TCP analyzer. (Jon - Siwek) - - * Parse 64-bit consts in Bro scripts correctly. (Bernhard Amann) - - * Output 64-bit counts correctly on 32-bit machines (Bernhard Amann) - - * Input framework fixes, including: (Bernhard Amann) - - - One of the change events got the wrong parameters. - - - Escape commas in sets and vectors that were unescaped before - tokenization. - - - Handling of zero-length-strings as last element in a set was - broken (sets ending with a ,). - - - Hashing of lines just containing zero-length-strings was broken. - - - Make set_separators different from , work for input framework. - - - Input framework was not handling counts and ints out of - 32-bit-range correctly. - - - Errors in single lines do not kill processing, but simply ignore - the line, log it, and continue. - - * Update documentation for builtin types. (Daniel Thayer) - - - Add missing description of interval "msec" unit. - - - Improved description of pattern by clarifying the issue of - operand order and difference between exact and embedded - matching. - - * Documentation fixes for signature 'eval' conditions. (Jon Siwek) - - * Remove orphaned 1.5 unit tests. (Jon Siwek) - - * Add type checking for signature 'eval' condition functions. (Jon - Siwek) - - * Adding an identifier to the SMTP blocklist notices for duplicate - suppression. (Seth Hall) - -2.1-beta-45 | 2012-08-22 16:11:10 -0700 - - * Add an option to the input framework that allows the user to chose - to not die upon encountering files/functions. (Bernhard Amann) - -2.1-beta-41 | 2012-08-22 16:05:21 -0700 - - * Add test serialization to "leak" unit tests that use - communication. (Jon Siwek) - - * Change to metrics/basic-cluster unit test for reliability. (Jon - Siwek) - - * Fixed ack tracking which could overflow quickly in some - situations. (Seth Hall) - - * Minor tweak to coverage.bare-mode-errors unit test to work with a - symlinked 'scripts' dir. (Jon Siwek) - -2.1-beta-35 | 2012-08-22 08:44:52 -0700 - - * Add testcase for input framework reading sets (rather than - tables). (Bernhard Amann) - -2.1-beta-31 | 2012-08-21 15:46:05 -0700 - - * Tweak to rotate-custom.bro unit test. (Jon Siwek) - - * Ignore small mem leak every rotation interval for dataseries logs. - (Jon Siwek) - -2.1-beta-28 | 2012-08-21 08:32:42 -0700 - - * Linking ES docs into logging document. (Robin Sommer) - -2.1-beta-27 | 2012-08-20 20:06:20 -0700 - - * Add the Stream record to Log:active_streams to make more dynamic - logging possible. (Seth Hall) - - * Fix portability of printing to files returned by - open("/dev/stderr"). (Jon Siwek) - - * Fix mime type diff canonifier to also skip mime_desc columns. (Jon - Siwek) - - * Unit test tweaks/fixes. (Jon Siwek) - - - Some baselines for tests in "leaks" group were outdated. - - - Changed a few of the cluster/communication tests to terminate - more explicitly instead of relying on btest-bg-wait to kill - processes. This makes the tests finish faster in the success case - and makes the reason for failing clearer in the that case. - - * Fix memory leak of serialized IDs when compiled with - --enable-debug. (Jon Siwek) - -2.1-beta-21 | 2012-08-16 11:48:56 -0700 - - * Installing a handler for running out of memory in "new". Bro will - now print an error message in that case rather than abort with an - uncaught exception. (Robin Sommer) - -2.1-beta-20 | 2012-08-16 11:43:31 -0700 - - * Fixed potential problems with ElasticSearch output plugin. (Seth - Hall) - -2.1-beta-13 | 2012-08-10 12:28:04 -0700 - - * Reporter warnings and error now print to stderr by default. New - options Reporter::warnings_to_stderr and - Reporter::errors_to_stderr to disable. (Seth Hall) - -2.1-beta-9 | 2012-08-10 12:24:29 -0700 - - * Add more BIF tests. (Daniel Thayer) - -2.1-beta-6 | 2012-08-10 12:22:52 -0700 - - * Fix bug in input framework with an edge case. (Bernhard Amann) - - * Fix small bug in input framework test script. (Bernhard Amann) - -2.1-beta-3 | 2012-08-03 10:46:49 -0700 - - * Merge branch 'master' of ssh://git.bro-ids.org/bro (Robin Sommer) - - * Fix configure script to exit with non-zero status on error (Jon - Siwek) - - * Improve ASCII output performance. (Robin Sommer) - -2.1-beta | 2012-07-30 11:59:53 -0700 - - * Improve log filter compatibility with remote logging. Addresses - #842. (Jon Siwek) - -2.0-907 | 2012-07-30 09:13:36 -0700 - - * Add missing breaks to switch cases in - ElasticSearch::HTTPReceive(). (Jon Siwek) - -2.0-905 | 2012-07-28 16:24:34 -0700 - - * Fix log manager hanging on waiting for pending file rotations, - plus writer API tweak for failed rotations. Addresses #860. (Jon - Siwek and Robin Sommer) - - * Tweaking logs-to-elasticsearch.bro so that it doesn't do anything - if ES server is unset. (Robin Sommer) - -2.0-902 | 2012-07-27 12:42:13 -0700 - - * New variable in logging framework Log::active_streams to indicate - Log:ID enums which are currently active. (Seth Hall) - - * Reworked how the logs-to-elasticsearch scripts works to stop - abusing the logging framework. (Seth Hall) - - * Fix input test for recent default change on fastpath. (Robin - Sommer) - -2.0-898 | 2012-07-27 12:22:03 -0700 - - * Small (potential performance) improvement for logging framework. (Seth Hall) - - * Script-level rotation postprocessor fix. This fixes a problem with - writers that don't have a postprocessor. (Seth Hall) - - * Update input framework documentation to reflect want_record - change. (Bernhard Amann) - - * Fix crash when encountering an InterpreterException in a predicate - in logging or input Framework. (Bernhard Amann) - - * Input framework: Make want_record=T the default for events - (Bernhard Amann) - - * Changing the start/end markers in logs to open/close now - reflecting wall clock. (Robin Sommer) - -2.0-891 | 2012-07-26 17:15:10 -0700 - - * Reader/writer API: preventing plugins from receiving further - messages after a failure. (Robin Sommer) - - * New test for input framework that fails to find a file. (Robin - Sommer) - - * Improving error handling for threads. (Robin Sommer) - - * Tweaking the custom-rotate test to produce stable output. (Robin - Sommer) - -2.0-884 | 2012-07-26 14:33:21 -0700 - - * Add comprehensive error handling for close() calls. (Jon Siwek) - - * Add more test cases for input framework. (Bernhard Amann) - - * Input framework: make error output for non-matching event types - much more verbose. (Bernhard Amann) - -2.0-877 | 2012-07-25 17:20:34 -0700 - - * Fix double close() in FilerSerializer class. (Jon Siwek) - - * Fix build warnings. (Daniel Thayer) - - * Fixes to ElasticSearch plugin to make libcurl handle http - responses correctly. (Seth Hall) - - * Fixing FreeBSD compiler error. (Robin Sommer) - - * Silencing compiler warnings. (Robin Sommer) - -2.0-871 | 2012-07-25 13:08:00 -0700 - - * Fix complaint from valgrind about uninitialized memory usage. (Jon - Siwek) - - * Fix differing log filters of streams from writing to same - writer/path (which now produces a warning, but is otherwise - skipped for the second). Addresses #842. (Jon Siwek) - - * Fix tests and error message for to_double BIF. (Daniel Thayer) - - * Compile fix. (Robin Sommer) - -2.0-866 | 2012-07-24 16:02:07 -0700 - - * Correct a typo in usage message. (Daniel Thayer) - - * Fix file permissions of log files (which were created with execute - permissions after a recent change). (Daniel Thayer) - -2.0-862 | 2012-07-24 15:22:52 -0700 - - * Fix initialization problem in logging class. (Jon Siwek) - - * Input framework now accepts escaped ASCII values as input (\x##), - and unescapes appropiately. (Bernhard Amann) - - * Make reading ASCII logfiles work when the input separator is - different from \t. (Bernhard Amann) - - * A number of smaller fixes for input framework. (Bernhard Amann) - -2.0-851 | 2012-07-24 15:04:14 -0700 - - * New built-in function to_double(s: string). (Scott Campbell) - -2.0-849 | 2012-07-24 11:06:16 -0700 - - * Adding missing include needed on some systems. (Robin Sommer) - -2.0-846 | 2012-07-23 16:36:37 -0700 - - * Fix WriterBackend::WriterInfo serialization, reenable ascii - start/end tags. (Jon Siwek) - -2.0-844 | 2012-07-23 16:20:59 -0700 - - * Reworking parts of the internal threading/logging/input APIs for - thread-safety. (Robin Sommer) - - * Bugfix for SSL version check. (Bernhard Amann) - - * Changing a HTTP DPD from port 3138 to 3128. Addresses #857. (Robin - Sommer) - - * ElasticSearch logging writer. See logging-elasticsearch.rst for - more information. (Vlad Grigorescu and Seth Hall). - - * Give configure a --disable-perftools option to disable Perftools - support even if found. (Robin Sommer) - - * The ASCII log writer now includes "#start " and "#end - lines in the each file. (Robin Sommer) - - * Renamed ASCII logger "header" options to "meta". (Robin Sommer) - - * ASCII logs now escape '#' at the beginning of log lines. Addresses - #763. (Robin Sommer) - - * Fix bug, where in dns.log rcode always was set to 0/NOERROR when - no reply package was seen. (Bernhard Amann) - - * Updating to Mozilla's current certificate bundle. (Seth Hall) - -2.0-769 | 2012-07-13 16:17:33 -0700 - - * Fix some Info:Record field documentation. (Vlad Grigorescu) - - * Fix overrides of TCP_ApplicationAnalyzer::EndpointEOF. (Jon Siwek) - - * Fix segfault when incrementing whole vector values. Also removed - RefExpr::Eval(Val*) method since it was never called. (Jon Siwek) - - * Remove baselines for some leak-detecting unit tests. (Jon Siwek) - - * Unblock SIGFPE, SIGILL, SIGSEGV and SIGBUS for threads, so that - they now propagate to the main thread. Adresses #848. (Bernhard - Amann) - -2.0-761 | 2012-07-12 08:14:38 -0700 - - * Some small fixes to further reduce SOCKS false positive logs. (Seth Hall) - - * Calls to pthread_mutex_unlock now log the reason for failures. - (Bernhard Amann) - -2.0-757 | 2012-07-11 08:30:19 -0700 - - * Fixing memory leak. (Seth Hall) - -2.0-755 | 2012-07-10 16:25:16 -0700 - - * Add sorting canonifier to rotate-custom unit test. Addresses #846. - (Jon Siwek) - - * Fix many compiler warnings. (Daniel Thayer) - - * Fix segfault when there's an error/timeout resolving DNS requests. - Addresses #846. (Jon Siwek) - - * Remove a non-portable test case. (Daniel Thayer) - - * Fix typos in input framework doc. (Daniel Thayer) - - * Fix typos in DataSeries documentation. (Daniel Thayer) - - * Bugfix making custom rotate functions work again. (Robin Sommer) - - * Tiny bugfix for returning writer name. (Robin Sommer) - - * Moving make target update-doc-sources from top-level Makefile to - btest Makefile. (Robin Sommer) - -2.0-733 | 2012-07-02 15:31:24 -0700 - - * Extending the input reader DoInit() API. (Bernhard Amann). It now - provides a Info struct similar to what we introduced for log - writers, including a corresponding "config" key/value table. - - * Fix to make writer-info work when debugging is enabled. (Bernhard - Amann) - -2.0-726 | 2012-07-02 15:19:15 -0700 - - * Extending the log writer DoInit() API. (Robin Sommer) - - We now pass in a Info struct that contains: - - - the path name (as before) - - the rotation interval - - the log_rotate_base_time in seconds - - a table of key/value pairs with further configuration options. - - To fill the table, log filters have a new field "config: table[string] - of strings". This gives a way to pass arbitrary values from - script-land to writers. Interpretation is left up to the writer. - - * Split calc_next_rotate() into two functions, one of which is - thread-safe and can be used with the log_rotate_base_time value - from DoInit(). - - * Updates to the None writer. (Robin Sommer) - - - It gets its own script writers/none.bro. - - - New bool option LogNone::debug to enable debug output. It then - prints out all the values passed to DoInit(). - - - Fixed a bug that prevented Bro from terminating. - -2.0-723 | 2012-07-02 15:02:56 -0700 - - * Extract ICMPv6 NDP options and include in ICMP events. This adds - a new parameter of type "icmp6_nd_options" to the ICMPv6 neighbor - discovery events. Addresses #833. (Jon Siwek) - - * Set input frontend type before starting the thread. This means - that the thread type will be output correctly in the error - message. (Bernhard Amann) - -2.0-719 | 2012-07-02 14:49:03 -0700 - - * Fix inconsistencies in random number generation. The - srand()/rand() interface was being intermixed with the - srandom()/random() one. The later is now used throughout. (Jon - Siwek) - - * Changed the srand() and rand() BIFs to work deterministically if - Bro was given a seed file. Addresses #825. (Jon Siwek) - - * Updating input framework unit tests to make them more reliable and - execute quicker. (Jon Siwek) - - * Fixed race condition in writer and reader initializations. (Jon - Siwek) - - * Small tweak to make test complete quicker. (Jon Siwek) - - * Drain events before terminating log/thread managers. (Jon Siwek) - - * Fix strict-aliasing warning in RemoteSerializer.cc. Addresses - #834. (Jon Siwek) - - * Fix typos in event documentation. (Daniel Thayer) - - * Fix typos in NEWS for Bro 2.1 beta. (Daniel Thayer) - -2.0-709 | 2012-06-21 10:14:24 -0700 - - * Fix exceptions thrown in event handlers preventing others from running. (Jon Siwek) - - * Add another SOCKS command. (Seth Hall) - - * Fixed some problems with the SOCKS analyzer and tests. (Seth Hall) - - * Updating NEWS in preparation for beta. (Robin Sommer) - - * Accepting different AF_INET6 values for loopback link headers. - (Robin Sommer) - -2.0-698 | 2012-06-20 14:30:40 -0700 - - * Updates for the SOCKS analyzer (Seth Hall). - - - A SOCKS log! - - - Now supports SOCKSv5 in the analyzer and the DPD sigs. - - - Added protocol violations. - - * Updates to the tunnels framework. (Seth Hall) - - - Make the uid field optional since it's conceptually incorrect - for proxies being treated as tunnels to have it. - - - Reordered two fields in the log. - - - Reduced the default tunnel expiration interface to something - more reasonable (1 hour). - - * Make Teredo bubble packet parsing more lenient. (Jon Siwek) - - * Fix a crash in NetSessions::ParseIPPacket(). (Jon Siwek) - -2.0-690 | 2012-06-18 16:01:33 -0700 - - * Support for decapsulating tunnels via the new tunnel framework in - base/frameworks/tunnels. - - Bro currently supports Teredo, AYIYA, IP-in-IP (both IPv4 and - IPv6), and SOCKS. For all these, it logs the outher tunnel - connections in both conn.log and tunnel.log, and proceeds to - analyze the inner payload as if it were not tunneled, including - also logging it in conn.log (with a new tunnel_parents column - pointing back to the outer connection(s)). (Jon Siwek, Seth Hall, - Gregor Maier) - - * The options "tunnel_port" and "parse_udp_tunnels" have been - removed. (Jon Siwek) - -2.0-623 | 2012-06-15 16:24:52 -0700 - - * Changing an error in the input framework to a warning. (Robin - Sommer) - -2.0-622 | 2012-06-15 15:38:43 -0700 - - * Input framework updates. (Bernhard Amann) - - - Disable streaming reads from executed commands. This lead to - hanging Bros because pclose apparently can wait for eternity if - things go wrong. - - - Automatically delete disabled input streams. - - - Documentation. - -2.0-614 | 2012-06-15 15:19:49 -0700 - - * Remove an old, unused diff canonifier. (Jon Siwek) - - * Improve an error message in ICMP analyzer. (Jon Siwek) - - * Fix a warning message when building docs. (Daniel Thayer) - - * Fix many errors in the event documentation. (Daniel Thayer) - -2.0-608 | 2012-06-11 15:59:00 -0700 - - * Add more error handling code to logging of enum vals. Addresses - #829. (Jon Siwek) - -2.0-606 | 2012-06-11 15:55:56 -0700 - - * Fix summary lines for BIF documentation and corrected the - description of "fmt" and "floor" BIFs. (Daniel Thayer) - - * Fix val_size BIF tests and improve docs. (Daniel Thayer) - -2.0-602 | 2012-06-07 15:06:19 -0700 - - * Include header for usleep(), caused compile failure on Archlinux. (Jon Siwek) - - * Revert "Fixed a bug with the MIME analyzer not removing whitespace - on wrapped headers." Needs discussion. (Robin Sommer) - -2.0-598 | 2012-06-06 11:47:00 -0700 - - * Add @load-sigs directive for loading signature files (addresses - #551). This can be used to load signatures relative to the current - scripts (e.g., "@load-sigs ./foo.sig"). (Jon Siwek) - - -2.0-596 | 2012-06-06 11:41:00 -0700 - - * Fixes for some BiFs and their documentation. (Daniel Thayer) - - * Many new unit tests for BiFs. (Daniel Thayer) - -2.0-579 | 2012-06-06 11:04:46 -0700 - - * Memory leak fixes for bad usages of VectorVal ctor. (Jon Siwek) - - * Fixed a bug with the MIME analyzer not removing whitespace on - wrapped headers. (Seth Hall) - - * Change Input::update_finished lookup to happen at init time. (Jon Siwek) - - * Fix going through the internal_handler() function which will now - set the event as "used" (i.e. it's marked as being raised - somewhere). Addresses #823. (Jon Siwek) - - * Fix format specifier on RemoteSerializer::Connect. This caused - 32-bit systems to show a warning at compile-time, and fail when - connecting to peers. (Jon Siwek) - - * Fixes for running tests in parallel. (Robin Sommer) - -2.0-571 | 2012-05-30 19:12:43 -0700 - - * Updating submodule(s). - -2.0-570 | 2012-05-30 19:08:18 -0700 - - * A new input framework enables scripts to read in external data - dynamically on the fly as Bro is processing network traffic. - (Bernhard Amann) - - Currently, the framework supports reading ASCII input that's - structured similar as Bro's log files as well as raw blobs of - data. Other formats will come in the future. - - See doc/input.rst for more information (this will be extended - further soon). - -2.0-395 | 2012-05-30 17:03:31 -0700 - - * Remove unnecessary assert in ICMP analyzer which could lead to - aborts. Addresses #822. - - * Improve script debugger backtrace and print commands. (Jon Siwek) - - * Switching default DS compression to gzip. (Robin Sommer) - - * Improve availability of IPv6 flow label in connection records. - This adds a "flow_label" field to the "endpoint" record type, - which is used for both the "orig" and "resp" fields of - "connection" records. The new "connection_flow_label_changed" - event also allows tracking of changes in flow labels: it's raised - each time one direction of the connection starts using a different - label. (Jon Siwek) - - * Add unit tests for Broccoli SSL and Broccoli IPv6 connectivity. - (Jon Siwek) - - * Remove AI_ADDRCONFIG getaddrinfo hints flag for listening sockets. - (Jon Siwek) - - * Undo unnecessary communication protocol version bump. (Jon Siwek) - - * Add support to Bro for connecting with peers over IPv6. (Jon Siwek) - - - Communication::listen_ipv6 needs to be redef'd to true in order - for IPv6 listening sockets to be opened. - - - Added Communication::listen_retry option as an interval at which - to retry binding to socket addresses that were already in use. - - - Added some explicit baselines to check in the istate.events and - istate.events-ssl tests -- the SSL test was incorrectly passing - because it compared two empty files. (The files being empty - because "http/base" was given as an argument to Bro which it - couldn't handle because that script doesn't exist anymore). - - - Support for communication over non-global IPv6 addresses. This - usually requires specifying an additional zone identifier (see - RFC 4007). The connect() and listen() BIFs have been changed to - accept this zone identifier as an argument. - - -2.0-377 | 2012-05-24 16:46:06 -0700 - - * Documentation fixes. (Jon Siwek and Daniel Thayer) - -2.0-372 | 2012-05-17 13:59:45 -0700 - - * Fix compile errors. (Jon Siwek) - - * Linking in the DS docs. (Robin Sommer) - - * Fix mobility checksums unit test. (Jon Siwek) - -2.0-367 | 2012-05-17 12:42:30 -0700 - - * Adding support for binary output via DataSeries. See - logging-dataseries.rst for more information. (Gilbert Clark and - Robin Sommer) - - * Adding target update-doc-sources to top-level Makefile that runs - genDocSourcesList.sh. (Robin Sommer) - - * Moving trace for rotation test into traces directory. (Robin Sommer) - - * Fixing a rotation race condition at termination. (Robin Sommer) - - * Extending log post-processor call to include the name of the - writer. (Robin Sommer) - - * In threads, an internal error now immediately aborts. Otherwise, - the error won't make it back to the main thread for a while and - subsequent code in the thread would still execute. (Robin Sommer) - - * DataSeries cleanup. (Robin Sommer) - - * Fixing threads' DoFinish() method. It wasn't called reliably. Now, - it's always called before the thread is destroyed (assuming - processing has went normally so far). (Robin Sommer) - -2.0-341 | 2012-05-17 09:54:30 -0700 - - * Add a comment to explain the ICMPv6 error message types. (Daniel Thayer) - - * Quieting external test output somehwat. (Robin Sommer) - -2.0-336 | 2012-05-14 17:15:44 -0700 - - * Don't print the various "weird" events to stderr. Address #805. - (Daniel Thayer) - - * Generate icmp_error_message event for ICMPv6 error msgs. - Previously, icmp_sent was being generated, but icmp_error_message - contains more info. - - * Improved documentation comments for icmp-related events. (Daniel - Thayer) - -2.0-330 | 2012-05-14 17:05:56 -0700 - - * Add `addr_to_uri` script-level function that adds brackets to an - address if it's IPv6 and will be included in a URI or when a - ":" needs to be appended to it. (Jon Siwek) - - * Also add a test case for content extraction. (Jon Siwek) - - * Fix typos and improve INSTALL document. (Daniel Thayer) - - * Switching to new btest command TEST-SERIALIZE for communication - tests. (Robin Sommer) - -2.0-323 | 2012-05-04 21:04:34 -0700 - - * Add SHA1 and SHA256 hashing BIFs. Addresses #542. - - * Refactor all internal MD5 stuff to use OpenSSL's. (Jon Siwek) - - * Changes to open-file caching limits and uncached file unserialization. (Jon Siwek) - - - Unserializing files that were previously kicked out of the open-file - cache would cause them to be fopen'd with the original access - permissions which is usually 'w' and causes truncation. They - are now opened in 'a' mode. (addresses #780) - - - Add 'max_files_in_cache' script option to manually set the maximum - amount of opened files to keep cached. Mainly this just helped - to create a simple test case for the above change. - - - Remove unused NO_HAVE_SETRLIMIT preprocessor switch. - - - On systems that don't enforce a limit on number of files opened for - the process, raise default max size of open-file cache from - 32 to 512. - -2.0-319 | 2012-05-03 13:24:44 -0700 - - * SSL bugfixes and cleanup. (Seth Hall) - - - SSL related files and classes renamed to remove the "binpac" term. - - - A small fix for DPD scripts to make the DPD log more helpful if - there are multiple continued failures. - - - Fixed the SSL analyzer to make it stop doing repeated violation - messages for some handshake failures. - - - Added a $issuer_subject to the SSL log. - - - Created a basic test for SSL. - - - Fixed parsing of TLS server extensions. (Seth Hall) - -2.0-315 | 2012-05-03 11:44:17 -0700 - - * Add two more TLS extension values that we see in live traffic. - (Bernhard Amann) - - * Fixed IPv6 link local unicast CIDR and added IPv6 loopback to - private address space. (Seth Hall) - - * Fixed a problem where cluster workers were still processing - notices in some cases. (Seth Hall) - - * Added a configure option to specify the 'etc' directory. Addresses - #801. (Daniel Thayer) - - -2.0-306 | 2012-04-24 14:37:00 -0700 - - * Add further TLS extension values "extended_random" and - "heartbeat". (Seth Hall) - - * Fix problem with extracting FTP passwords and add "ftpuser" as - another anonymous username. (Seth Hall, discovered by Patrik - Lundin). - -2.0-303 | 2012-04-19 10:01:06 -0700 - - * Changes related to ICMPv6 Neighbor Discovery messages. (Jon Siwek) - - - The 'icmp_conn' record now contains an 'hlim' field since hop limit - in the IP header is an interesting field for at least these ND - messages. - - - Fixed and extended 'icmp_router_advertisement' event parameters. - - - Changed 'icmp_neighbor_advertisement' event parameters to add - more of the known boolean flags. - -2.0-301 | 2012-04-17 17:58:55 -0700 - - * Bro now support ICMPv6. (Matti Mantere, Jon Siwek, Robin Sommer, - Daniel Thayer). - - Overall, Bro now raises the following ICMP events for v4 and v6 as - appropiate: - - event icmp_sent(c: connection, icmp: icmp_conn); - event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string); - event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string); - event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context); - event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context); - event icmp_packet_too_big(c: connection, icmp: icmp_conn, code: count, context: icmp_context); - event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context); - event icmp_parameter_problem(c: connection, icmp: icmp_conn, code: count, context: icmp_context); - event icmp_router_solicitation(c: connection, icmp: icmp_conn); - event icmp_router_advertisement(c: connection, icmp: icmp_conn, hop_limit: count, managed: bool, router_lifetime: count, reachable_time: interval, retrans_timer: interval); - event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt:addr); - event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, tgt:addr); - event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr); - - The `icmp_conn` record got a new boolean field 'v6' that indicates - whether the ICMP message is v4 or v6. - - This change also includes further low-level work on existing IP - and ICMP code, including a reorganization of how ICMPv4 is - handled. - -2.0-281 | 2012-04-17 17:40:39 -0700 - - * Small updates for the bittorrent analyzer to support 64bit types - in binpac. (Seth Hall) - - * Removed the attempt at bittorrent resynchronization. (Seth Hall) - -2.0-276 | 2012-04-17 17:35:56 -0700 - - * Add more support for 's that lack some structure - definitions. (Jon Siwek) - -2.0-273 | 2012-04-16 18:08:56 -0700 - - * Removing QR flag from DNS log in response, which should not have - been there in the first place. (Seth Hall) - - * Sync up patricia.c/h with pysubnettree repo. (Daniel Thayer) - - * Adding missing leak groups to a couple tests. Also activating leak - checking for proxy in basic-cluster test. (Robin Sommer) - -2.0-267 | 2012-04-09 17:47:28 -0700 - - * Add support for mobile IPv6 Mobility Header (RFC 6275). (Jon - Siwek) - - - Enabled through a new --enable-mobile-ipv6 configure-time - option. If not enabled, the mobility header (routing type 2) and - Home Address Destination option are ignored. - - - Accessible at script-layer through 'mobile_ipv6_message' event. - - * Refactor IP_Hdr routing header handling, add MobileIPv6 Home - Address handling. Packets that use the Home Address Destination - option use that option's address as the connection's originator. - (Jon Siwek) - - * Revert TCP checksumming to cache common data, like it did before. - (Jon Siwek) - - * Improve handling of IPv6 routing type 0 extension headers. (Jon - Siwek) - - - flow_weird event with name argument value of "routing0_hdr" is raised - for packets containing an IPv6 routing type 0 header because this - type of header is now deprecated according to RFC 5095. - - - Packets with a routing type 0 header and non-zero segments left - now use the last address in that header in order to associate - with a connection/flow and for calculating TCP/UDP checksums. - - - Added a set of IPv4/IPv6 TCP/UDP checksum unit tests (Jon Siwek) - - * Fix table expiry for values assigned in bro_init() when reading - live. (Jon Siwek) - -2.0-257 | 2012-04-05 15:32:43 -0700 - - * Fix CMake from warning about unused ENABLE_PERFTOOLS_DEBUG - variable. (Jon Siwek) - - * Fix handling of IPv6 atomic fragments. (Jon Siwek) - - * Fix that prevents Bro processes that do neither local logging nor - request remote logs from spawning threads. (Robin Sommer) - - * Fixing perftools-debug support. (Robin Sommer) - - * Reverting SocketComm change tuning I/O behaviour. (Robin Sommer) - - * Adding notice_policy.log canonification for external tests. (Robin Sommer) - - -2.0-245 | 2012-04-04 17:25:20 -0700 - - * Internal restructuring of the logging framework: we now spawn - threads doing the I/O. From a user's perspective not much should - change, except that the OS may now show a bunch of Bro threads. - (Gilbert Clark and Robin Sommer). - - * When building Bro, we now always link in tcmalloc if it's found at - configure time. If it's installed but not picked up, - --with-perftools may help. (Robin Sommer) - - * Renaming the configure option --enable-perftools to - --enable-perftool-debug to indicate that the switch is only - relevant for debugging the heap. It's not needed to pick up - tcmalloc for better performance. (Robin Sommer) - -2.0-184 | 2012-03-28 15:11:11 -0700 - - * Improve handling of IPv6 Routing Type 0 headers. (Jon Siwek) - - - For RH0 headers with non-zero segments left, a - "routing0_segleft" flow_weird event is raised (with a - destination indicating the last address in the routing header), - and an "rh0_segleft" event can also be handled if the other - contents of the packet header are of interest. No further - analysis is done as the complexity required to correctly - identify destination endpoints of connections doesn't seem worth - it as RH0 has been deprecated by RFC 5095. - - - For RH0 headers without any segments left, a "routing0_header" - flow_weird event is raised, but further analysis still occurs as - normal. - -2.0-182 | 2012-03-28 15:01:57 -0700 - - * Remove dead tcp_checksum function from net_util. (Jon Siwek) - - * Change routing0_data_to_addrs BIF to return vector of addresses. - The order of addresses in type 0 routing headers is - interesting/important. (Jon Siwek) - - -2.0-179 | 2012-03-23 17:43:31 -0700 - - * Remove the default "tcp or udp or icmp" filter. In default mode, - Bro would load the packet filter script framework which installs a - filter that allows all packets, but in bare mode (the -b option), - this old filter would not follow IPv6 protocol chains and thus - filter out packets with extension headers. (Jon Siwek) - - * Update PacketFilter/Discarder code for IP version independence. - (Jon Siwek) - - * Fix some IPv6 header related bugs. (Jon Siwek) - - * Add IPv6 fragment reassembly. (Jon Siwek) - - * Add handling for IPv6 extension header chains. Addresses #531. - (Jon Siwek) - - - The script-layer 'pkt_hdr' type is extended with a new 'ip6' field - representing the full IPv6 header chain. - - - The 'new_packet' event is now raised for IPv6 packets. Addresses - #523. - - - A new event called 'ipv6_ext_header' is raised for any IPv6 - packet containing extension headers. - - - A new event called 'esp_packet' is raised for any packets using - ESP ('new_packet' and 'ipv6_ext_header' events provide - connection info, but that info can't be provided here since the - upper-layer payload is encrypted). - - - The 'unknown_protocol' weird is now raised more reliably when - Bro sees a transport protocol or IPv6 extension header it can't - handle. Addresses #522. - - * Add unit tests for IPv6 fragment reassembly, ipv6_ext_headers and - esp_packet events. (Jon Siwek) - - * Adapt FreeBSD's inet_ntop implementation for internal use. Now we - get consistent text representations of IPv6 addresses across - platforms. (Jon Siwek) - - * Update documentation for new syntax of IPv6 literals. (Jon Siwek) - - -2.0-150 | 2012-03-13 16:16:22 -0700 - - * Changing the regular expression to allow Site::local_nets in - signatures. (Julien Sentier) - - * Removing a line of dead code. Found by . Closes #786. (Julien - Sentier) - -2.0-146 | 2012-03-13 15:39:38 -0700 - - * Change IPv6 literal constant syntax to require encasing square - brackets. (Jon Siwek) - -2.0-145 | 2012-03-09 15:10:35 -0800 - - * Remove the match expression. 'match' and 'using' are no longer - keywords. Addressed #753. (Jon Siwek) - -2.0-143 | 2012-03-09 15:07:42 -0800 - - * Fix a BRO_PROFILER_FILE/mkstemp portability issue. Addresses #794. - (Jon Siwek) - -2.0-139 | 2012-03-02 09:33:04 -0800 - - * Changes to how script coverage integrates with test suites. (Jon Siwek) - - - BRO_PROFILER_FILE now passes .X* templated filenames to mkstemp - for generating unique coverage state files. - - - Rearranging Makefile targets. The general rule is that if the - all/brief target fails out due to a test failure, then the dependent - coverage target won't run, but can still be invoked directly later. - (e.g. make brief || make coverage) - - * Standardized on the &default function for SSL constants. (Seth - Hall) - - * Adding btest group "leaks" to leak tests. (Robin Sommer) - - * Adding btest group "comm" to communication tests for parallelizing - execution with new btest version. (Robin Sommer) - - * Sorting all output for diffing in the external tests. (Robin - Sommer) - - * Cleaned up dead code from the old SSL analyzers. Reported by - Julien Sentier. (Seth Hall) - - * Update/add tests for broccoli IPv6 addr/subnet support. Addresses - #448. (Jon Siwek) - - * Remove connection compressor. Addresses #559. (Jon Siwek) - - * Refactor IP_Hdr class ctors. Addresses #532. (Jon Siwek) - - -2.0-121 | 2012-02-24 16:34:17 -0800 - - * A number of smaller memory fixes and code cleanups. (Julien - Sentier) - - * Add to_subnet bif. Fixes #782). (Jon Siwek) - - * Fix IPAddr::Mask/ReverseMask not allowing argument of 0. (Jon - Siwek) - - * Refactor IPAddr v4 initialization from string. Fixes #775. (Jon Siwek) - - * Parse the dotted address string directly instead of canonicalizing - and passing to inet_pton. (Jon Siwek) - - -2.0-108 | 2012-02-24 15:21:07 -0800 - - * Refactoring a number of usages of new IPAddr class. (Jon Siwek) - - * Fixed a bug in remask_addr bif. (Jon Siwek) - -2.0-106 | 2012-02-24 15:02:20 -0800 - - * Raise minimum required CMake version to 2.6.3. (Jon Siwek) - -2.0-104 | 2012-02-24 14:59:12 -0800 - - * Add test case for FTP over IPv4. (Daniel Thayer) - - * Fix IPv6 URLs in ftp.log. (Daniel Thayer) - - * Add a test for FTP over IPv6 (Daniel Thayer) - - * Fix parsing of FTP EPRT command and EPSV response. (Daniel Thayer) - -2.0-95 | 2012-02-22 05:27:34 -0800 - - * GeoIP installation documentation update. (Seth Hall) - - * Decrease strictness of parsing IPv4 strings into addrs. Fixes #775. (Jon Siwek) - - * Fix memory leak in DNS manager. Fixes #777. (Jon Siwek) - - * Fix IPAddr/IPPrefix serialization bugs. (Jon Siwek) - - * Fix compile error. (Jon Siwek) - -2.0-86 | 2012-02-17 15:41:06 -0800 - - * Changing ARP detection to always kick in even if no analyzer is - activated. (Robin Sommer) - - * DNS name lookups performed by Bro now also query AAAA records. - DNS_Mgr handles combining the results of the A and AAAA queries - for a given hostname such that at the scripting layer, the name - resolution can yield a set with both IPv4 and IPv6 addresses. (Jon - Siwek) - - * Add counts_to_addr and addr_to_counts conversion BIFs. (Jon Siwek) - - * Change HashKey threshold for using H3 to 36 bytes. (Jon Siwek) - - * Remove mention of --enable-brov6 in docs. (Daniel Thayer) - - * Remove --enable-brov6 from configure usage text (Daniel Thayer) - - * Add a test and baseline for addr_to_ptr_name BiF. (Daniel Thayer) - - * Adding a test and baseline for ptr_name_to_addr BiF. (Seth Hall) - - * Fix the ptr_name_to_addr BiF to work with IPv6 (Daniel Thayer) - - * Fix a memory leak that perftools now complains about. (Jon Siwek) - - * Remove --enable-brov6 flag, IPv6 now supported by default. (Jon Siwek) - - Some script-layer changes of note: - - - dns_AAAA_reply event signature changed: the string representation - of an IPv6 addr is easily derived from the addr value, it doesn't - need to be another parameter. This event also now generated directly - by the DNS analyzer instead of being "faked" into a dns_A_reply event. - - - Removed addr_to_count BIF. It used to return the host-order - count representation of IPv4 addresses only. To make it more - generic, we might later add a BIF to return a vector of counts - in order to support IPv6. - - - Changed the result of enclosing addr variables in vertical pipes - (e.g. |my_addr|) to return the bit-width of the address type which - is 128 for IPv6 and 32 for IPv4. It used to function the same - way as addr_to_count mentioned above. - - - Remove bro_has_ipv6 BIF - -2.0-57 | 2012-02-10 00:02:35 -0800 - - * Fix typos in the documentation. (Daniel Thayer) - - * Fix compiler warning about Brofiler ctor init list order. (Jon Siwek) - - * Fix missing optional field access in webapp signature_match handler. (Jon Siwek) - -2.0-41 | 2012-02-03 04:10:53 -0500 - - * Updates to the Software framework to simplify the API. (Bernhard - Amann) - -2.0-40 | 2012-02-03 01:55:27 -0800 - - * Fix typos in documentation. (Daniel Thayer) - - * Fix sorting of lines in Brofiler coverage.log. (Daniel Thayer) - -2.0-38 | 2012-01-31 11:50:53 -0800 - - * Canonify sorting of lines in Brofiler coverage.log. (Daniel - Thayer) - -2.0-36 | 2012-01-27 10:38:14 -0800 - - * New "Brofiler" mode that tracks and records script statements - executed during runtime. (Jon Siwek) - - Use the BROFILER_FILE environment variable to point to a file in - which statement usage statistics from Bro script-layer can be - output. - - Script statements that should be ignored can be marked with a "# - @no-test" comment. For example: - - print "don't cover"; # @no-test - - if ( F ) - { # @no-test - ... - } - - * Integrated coverage measurement into test-suite. (Jon Siwek) - -2.0-20 | 2012-01-25 16:34:51 -0800 - - * BiF cleanup (Matthias Vallentin) - - - Rename NFS3::mode2string to a more generic file_mode(). - - - Unify do_profiling()/make_connection_persistent()/expect_connection() - to return any (i.e., nothing) instead of bools. - - - Perform type checking on count-to-port conversion. Related to #684. - - - Remove redundant connection_record() BiF. The same - functionality is provided by lookup_connection(). - - - Remove redundant active_connection() BiF. The same - functionality is provided by connection_exists(). - - - exit() now takes the exit code as argument. - - - to_port() now received a string instead of a count. - -2.0-9 | 2012-01-25 13:47:13 -0800 - - * Allow local table variables to be initialized with {} list - expressions. (Jon Siwek) - -2.0-7 | 2012-01-25 13:38:09 -0800 - - * Teach CompHash to allow indexing by records with vector/table/set - fields. Addresses #464. (Jon Siwek) - -2.0-5 | 2012-01-25 13:25:19 -0800 - - * Fixed a bug resulting in over-logging of detected webapps. (Seth Hall) - - * Make communication log baseline test more reliable. (Jon Siwek) - - * Fixed some broken links in documentation. (Daniel Thayer) - -2.0 | 2012-01-11 13:52:22 -0800 - - * Adding script reference documentation. (The Team). - -2.0-beta-194 | 2012-01-10 10:44:32 -0800 - - * Added an option for filtering out URLs before they are turned into - HTTP::Incorrect_File_Type notices. (Seth Hall) - - * Fix ref counting bug in BIFs that call internal_type. Addresses - #740. (Jon Siwek) - - * Adding back the stats.bro file. (Seth Hall) - - -2.0-beta-188 | 2012-01-10 09:49:29 -0800 - - * Change SFTP/SCP log rotators to use 4-digit year in filenames - Fixes #745. (Jon Siwek) - - * Adding back the stats.bro file. Addresses #656. (Seth Hall) - -2.0-beta-185 | 2012-01-09 18:00:50 -0800 - - * Tweaks for OpenBSD support. (Jon Siwek) - -2.0-beta-181 | 2012-01-08 20:49:04 -0800 - - * Add SFTP log postprocessor that transfers logs to remote hosts. - Addresses #737. (Jon Siwek) - - * Add FAQ entry about disabling NIC offloading features. (Jon Siwek) - - * Add a file NEWS with release notes. (Robin Sommer) - -2.0-beta-177 | 2012-01-05 15:01:07 -0800 - - * Replace the --snaplen/-l command line option with a - scripting-layer option called "snaplen" (which can also be - redefined on the command line, e.g. `bro -i eth0 snaplen=65535`). - - * Reduce snaplen default from 65535 to old default of 8192. Fixes - #720. (Jon Siwek) - -2.0-beta-174 | 2012-01-04 12:47:10 -0800 - - * SSL improvements. (Seth Hall) - - - Added the ssl_session_ticket_handshake event back. - - - Fixed a few bugs. - - - Removed the SSLv2.cc file since it's not used. - -2.0-beta-169 | 2012-01-04 12:44:39 -0800 - - * Tuning the pretty-printed alarm mails, which now include the - covered time range into the subject. (Robin Sommer) - - * Adding top-level "test" target to Makefile. (Robin Sommer) - - * Adding SWIG as dependency to INSTALL. (Robin Sommer) - -2.0-beta-155 | 2012-01-03 15:42:32 -0800 - - * Remove dead code related to record type inheritance. (Jon Siwek) - -2.0-beta-152 | 2012-01-03 14:51:34 -0800 - - * Notices now record the transport-layer protocol. (Bernhard Amann) - -2.0-beta-150 | 2012-01-03 14:42:45 -0800 - - * CMake 2.6 top-level 'install' target compat. Fixes #729. (Jon Siwek) - - * Minor fixes to test process. Addresses #298. - - * Increase timeout interval of communication-related btests. (Jon Siwek) - -2.0-beta-145 | 2011-12-19 11:37:15 -0800 - - * Empty fields are now logged as "(empty)" by default. (Robin - Sommer) - - * In log headers, only escape information when necessary. (Robin - Sommer) - -2.0-beta-139 | 2011-12-19 07:06:29 -0800 - - * The hostname notice email extension works now, plus a general - mechanism for adding delayed information to notices. (Seth Hall) - - * Fix &default fields in records not being initialized in coerced - assignments. Addresses #722. (Jon Siwek) - - * Make log headers include the type of data stored inside a set or - vector ("vector[string]"). (Bernhard Amann) - -2.0-beta-126 | 2011-12-18 15:18:05 -0800 - - * DNS updates. (Seth Hall) - - - Fixed some bugs with capturing data in the base DNS script. - - - Answers and TTLs are now vectors. - - - A warning that was being generated (dns_reply_seen_after_done) - from transaction ID reuse is fixed. - - * SSL updates. (Seth Hall) - - - Added is_orig fields to the SSL events and adapted script. - - - Added a field named last_alert to the SSL log. - - - The x509_certificate function has an is_orig field now instead - of is_server and its position in the argument list has moved. - - - A bit of reorganization and cleanup in the core analyzer. (Seth - Hall) - -2.0-beta-121 | 2011-12-18 15:10:15 -0800 - - * Enable warnings for malformed Broxygen xref roles. (Jon Siwek) - - * Fix Broxygen confusing scoped IDs at start of line as function - parameter. (Jon Siwek) - - * Allow Broxygen markup "##<" for more general use. (Jon Siwek) - -2.0-beta-116 | 2011-12-16 02:38:27 -0800 - - * Cleanup some misc Broxygen css/js stuff. (Jon Siwek) - - * Add search box to Broxygen docs. Fixes #726. (Jon Siwek) - - * Fixed major bug with cluster synchronization, which was not - working. (Seth Hall) - - * Fix missing action in notice policy for looking up GeoIP data. - (Jon Siwek) - - * Better persistent state configuration warning messages (fixes - #433). (Jon Siwek) - - * Renaming HTTP::SQL_Injection_Attack_Against to - HTTP::SQL_Injection_Victim. (Seth Hall). - - * Fixed DPD signatures for IRC. Fixes #311. (Seth Hall) - - * Removing Off_Port_Protocol_Found notice. (Seth Hall) - - * Teach Broxygen to more generally reference attribute values by name. (Jon Siwek) - - * SSH::Interesting_Hostname_Login cleanup. Fixes #664. (Seth Hall) - - * Fixed bug that was causing the malware hash registry script to - break. (Seth Hall) - - * Remove remnant of libmagic optionality. (Jon Siwek) - -2.0-beta-98 | 2011-12-07 08:12:08 -0800 - - * Adapting test-suite's diff-all so that it expands globs in both - current and baseline directory. Closes #677. (Robin Sommer) - -2.0-beta-97 | 2011-12-06 11:49:29 -0800 - - * Omit loading local-.bro scripts from base cluster framework. - Addresses #663 (Jon Siwek) - -2.0-beta-94 | 2011-12-03 15:57:19 -0800 - - * Adapting attribute serialization when talking to Broccoli. (Robin - Sommer) - -2.0-beta-92 | 2011-12-03 15:56:03 -0800 - - * Changes to Broxygen master script package index. (Jon Siwek) - - - Now only lists packages as those directories in the script hierarchy - that contain an __load__.bro file. - - - Script packages (dirs with a __load__.bro file), can now include - a README (in reST format) that will automatically be appended - under the link to a specific package in the master package - index. - -2.0-beta-88 | 2011-12-02 17:00:58 -0800 - - * Teach LogWriterAscii to use BRO_LOG_SUFFIX environemt variable. - Addresses #704. (Jon Siwek) - - * Fix double-free of DNS_Mgr_Request object. Addresses #661. - - * Add a remote_log_peer event which comes with an event_peer record - parameter. Addresses #493. (Jon Siwek) - - * Remove example redef of SMTP::entity_excerpt_len from local.bro. - Fixes error emitted when loading local.bro in bare mode. (Jon - Siwek) - - * Add missing doc targets to top Makefile; remove old doc/Makefile. - Fixes #705. (Jon Siwek) - - * Turn some globals into constants. Addresses #633. (Seth Hall) - - * Rearrange packet filter and DPD documentation. (Jon Siwek) - -2.0-beta-72 | 2011-11-30 20:16:09 -0800 - - * Fine-tuning the Sphinx layout to better match www. (Jon Siwek and - Robin Sommer) - -2.0-beta-69 | 2011-11-29 16:55:31 -0800 - - * Fixing ASCII logger to escape the unset-field place holder if - written out literally. (Robin Sommer) - -2.0-beta-68 | 2011-11-29 15:23:12 -0800 - - * Lots of documentation polishing. (Jon Siwek) - - * Teach Broxygen the ".. bro:see::" directive. (Jon Siwek) - - * Teach Broxygen :bro:see: role for referencing any identifier in - the Bro domain. (Jon Siwek) - - * Teach Broxygen to generate an index of Bro notices. (Jon Siwek) - - * Fix order of include directories. (Jon Siwek) - - * Catch if logged vectors do not contain only atomic types. - (Bernhard Amann) - -2.0-beta-47 | 2011-11-16 08:24:33 -0800 - - * Catch if logged sets do not contain only atomic types. (Bernhard - Amann) - - * Promote libz and libmagic to required dependencies. (Jon Siwek) - - * Fix parallel make from top-level to work on more platforms. (Jon - Siwek) - - * Add decode_base64_custom(). Addresses #670 (Jon Siwek) - - * A bunch of Sphinx-doc reorgs and polishing. (Jon Siwek) - -2.0-beta-28 | 2011-11-14 20:09:28 -0800 - - * Binary packaging script tweaks. We now require CMake 2.8.6. (Jon Siwek) - - * More default "weird" tuning for the "SYN_with_data" notice. (Seth - Hall) - - * Tiny bugfix for http file extraction along with test. (Seth Hall) - -2.0-beta-21 | 2011-11-06 19:27:22 -0800 - - * Quickstart doc fixes. (Jon Siwek) - -2.0-beta-19 | 2011-11-03 17:41:00 -0700 - - * Fixing packet filter test. (Robin Sommer) - -2.0-beta-12 | 2011-11-03 15:21:08 -0700 - - * No longer write to the PacketFilter::LOG stream if not reading - traffic. (Seth Hall) - -2.0-beta-10 | 2011-11-03 15:17:08 -0700 - - * Notice framework documentation update. (Seth Hall) - - * Fixing compiler warnings (addresses #388) (Jon Siwek) - -2.0-beta | 2011-10-27 17:46:28 -0700 - - * Preliminary fix for SSH login detection: we need a counted measure - of payload bytes (not ack tracking and not with the IP header - which is what we have now). (Seth Hall) - - * Fixing send_id() problem. We no longer update &redef functions. - Updating code on the fly isn't fully supported. (Robin Sommer) - - * Tuning the format of the pretty-printed alarm summaries. (Robin - Sommer) - -1.6-dev-1508 | 2011-10-26 17:24:50 -0700 - - * Updating submodule(s). (Robin Sommer) - -1.6-dev-1507 | 2011-10-26 15:10:18 -0700 - - * Baseline updates. (Robin Sommer) - -1.6-dev-1506 | 2011-10-26 14:48:43 -0700 - - * Updating submodule(s). (Robin Sommer) - -1.6-dev-1505 | 2011-10-26 14:43:58 -0700 - - * A new base script that pretty-prints alarms in the regular - summary. (Robin Sommer) - - * Adding a dummy log writer WRITER_NONE that just discards - everything. (Robin Sommer) - -1.6-dev-1498 | 2011-10-26 14:30:15 -0700 - - * Adding instructions to local.bro how to do ACTION_ALARM by - default. (Seth Hall) - -1.6-dev-1495 | 2011-10-26 10:15:58 -0500 - - * Updated unit test baselines. (Seth Hall) - -1.6-dev-1491 | 2011-10-25 20:22:56 -0700 - - * Updating submodule(s). (Robin Sommer) - -1.6-dev-1482 | 2011-10-25 19:08:32 -0700 - - * Fixing bug in log managers predicate evaluation. (Robin Sommer) - -1.6-dev-1481 | 2011-10-25 18:17:03 -0700 - - * Fix a problem with DNS servers being logged that aren't actually - servers. (Seth Hall) - - * Changed generated root cert DN format for RFC2253 compliance. (Jon - Siwek) - - * Removed :bro doc directives from notice documentation. (Seth Hall) - - * New notice framework docs. (Seth Hall) - - * Adding sub messages to emails. (Seth Hall) - - * Adding extra fields to smtp and http to track transaction depth. - (Seth Hall) - - * Fix for SSH login detection heuristic. (Seth Hall) - - * Removed some fields from http analysis that weren't commonly - needed or were wrong. (Seth Hall) - - * Updated/fixed MSIE version parsing in the software framework. - (Seth Hall) - - * Update Mozilla trust roots to index certs by subject distinguished - name. (Jon Siwek) - - * weird.bro rewrite. (Seth Hall) - - * More notice email tuning. (Seth Hall) - - * Slightly restructured http file hashing to fix a bug. (Seth Hall) - - * Changed the notice name for interesting ssh logins to correctly - reflect semantics of the notice. (Seth Hall) - - * Field name change to notice framwork. $result -> $action - - - $result is renamed to $action to reflect changes to the notice - framework since there is already another result-like field - ($suppress_for) and there may be more in the future. - - - Slipped in a change to add connection information to notice - emails too. (Seth Hall) - - * Small script refinements and documentation updates. (Seth Hall) - - * Pass over upgrade guide. (Robin Sommer) - - -1.6-dev-1430 | 2011-10-21 10:39:09 -0700 - - * Fixing crash with unknown debug streams. Closes #643. (Robin - Sommer) - - * Code to better handle interpreter errors, which can now be turned - into non-fatal runtime errors rather than immediate aborts. (Robin - Sommer). - - * Remove old make-src-packages script. (Jon Siwek) - - * Fixing a bunch of format strings. Closes #567. (Robin Sommer) - - * Cleaning up some distribution files. (Robin Sommer) - - * Various test, doc, and installation fixes/tweaks. (Seth Hall, Jon - Siwek and Robin Sommer). - - * Varios smaller policy fixes and tweaks (Seth Hall). - - * Moving docs from web server into distribution. (Robin Sommer) - - * Fixing more (small) memory leaks. (Robin Sommer) - - * Profiling support for DNS_Mgr and triggers. With - misc/profiling.bro, both now report a line in prof.log with some - counters on usage. (Robin Sommer) - - * Fixing DNS memory leaks. Closes #534. (Robin Sommer) - - * Fix code for disabling analyzers. Closes #577. (Robin Sommer) - - * Changed communication option from listen_encrypted to listen_ssl. - (Seth Hall) - - * Modification to the Communication framework API. (Seth Hall) - - - Simplified the communication API and made it easier to change - to encrypted connections by not having separate variables to - define encrypted and unencrypted ports. - - - Now, to enable listening without configuring nodes just - load the frameworks/communication/listen script. - - - If encrypted listening is desired set the following: - redef Communication::listen_encrypted=T; - - * Connection compressor now disabled by default. Addresses #559. - (Robin Sommer) - - -1.6-dev-1372 | 2011-10-06 18:09:17 -0700 - - * Filtering some potentially high-volume DNS weirds. (Robin Sommer) - - * DNS now raises DPD events. Closes #577. (Robin Sommer) - - * Fixing a bunch of compiler warnings. (Robin Sommer) - - * Remote logs are auto-flushed if the last write was longer than a - second ago. Addresses #498. (Robin Sommer) - - * Fix missing from previous MIME commit. (Robin Sommer) - -1.6-dev-1366 | 2011-10-06 17:05:21 -0700 - - * Make CompHash computation/recovery for functions deterministic. - Closes #636. (Jon Siwek) - - * Removing unnecessary @load in local.bro. (Robin Sommer) - - * Optimizing some MIME code. (Robin Sommer) - - * Speed improvements in logging code. (Robin Sommer) - - * Consolidating some node-specific functionality from scripts in - broctl repo. (Jon Siwek) - - * Another fix the for 1xx script code. (Robin Sommer) - -1.6-dev-1352 | 2011-10-05 16:20:51 -0700 - - * Fix for optional HTTP::Info status_code. (Jon Siwek) - - * Teaking some external testing scripts. (Jon Siwek) - - * HTTP bug fix reported by Martin Holste. (Seth Hall) - - * More script tuning. (Seth Hall) - - - Moved some of the weird events back to the base/ directory. - - - SSL fixes, updates, and performance optimization. - - * More adjustment to reduce Weird volumes. (Seth Hall) - - * Fixed an error when calculating x509 certificate hashes (reported - by Martin Holste). (Seth Hall) - - * Clean up to cluster framework to make event handling clearer. - (Seth Hall) - - * Fixed a bug in the notice framework. (Seth Hall) - - * Bug fix for FTP analysis script. (Seth Hall) - -1.6-dev-1333 | 2011-09-29 22:29:51 -0700 - - * Fixing a number of memory leaks. (Robin Sommer) - - * Loaded_scripts.log is indented with spaces now and makes more - sense to look at. (Seth Hall) - - * Teach HTTP parser to derive content length of multipart/byteranges - bodies. Addresses #488. (Jon Siwek) - - * Change logging of HTTP 1xx responses to occur in their own - columns. Addresses #411. (Jon Siwek) - - * Fix handling of HTTP 1xx response codes. Addresses #411). - - * Taking advantage of yet another trick to get installed browser - plugins. (Seth Hall) - - - With the software-browser-plugins script you can watch for Omniture - advertising servers to grab the list of installed plugins. - - - I reorganized the plugin detection a bit too to abstract it better. - - - Removed the WEB_ prefix from all of the Software::Type HTTP enums. - They were essentially redundant due to the full name already being - HTTP::SERVER (for example). - -1.6-dev-1316 | 2011-09-28 16:50:05 -0700 - - * Unit test cleanup. Updated README and collected coverage-related - tests in a common dir. (Jon Siwek) - - * Fixes for known-services. (Seth Hall) - - * Ported and 2.0ized the capture-loss script. (Seth Hall) - - * Communication fix and extension.(Robin Sommer) - - - Removing unnecessary log flushing. Closes #498. - - - Adding new BiF disconnect() that shuts a connection to a peer down. - - - terminate_connection() now first flushes any still buffered log - messages. - - * Fix for high SSL memory usage by adding &transient attribute to - top-level SSL pac array type. Closes #574. (Robin Sommer) - - * Fix a small bug in the metrics framework. (Seth Hall) - - * Temporarily removing scripts that aren't ready to be included. - Will return before next release. (Seth Hall) - - * New SSL policy scripts. (Seth Hall) - - - protocols/ssl/expiring-certs uses time based information from - certificates to determine if they will expire soon, have already - expired, or haven't yet become valid. - - - protocols/ssl/extract-certs-pem is a script for taking certs off - the line and converting them to PEM certificates with the openssl - command line tool then dumping them to a file. - - * Notice::type_suppression_intervals: table[Notice::Type] of - interval can be used to modify the suppression intervals for - entire types of notices. (Seth Hall) - - * EOF SSL protocol violations are only generated a single time now. - (Seth Hall) - - * Script level fixes. (Seth Hall) - - - Fixed a type name conflict in the Known namespace. - - - Fixed a DPD framework bug that was causing Reporter messages. - - - Fixed the notice_policy log. - - - Predicate functions are now logged. - - - Predicate functions are now optional. If not given, it's assumed that - the result should always apply. (Seth Hall) - - - Fix a problem with accidental and mistaken HTTP log lines. - -1.6-dev-1293 | 2011-09-22 19:44:37 -0700 - - * Smaller script tweaks. (Seth Hall) - - * Duplicate notice suppression. (Seth Hall) - - - Duplicate notices are discovered with the new Notice::Info - field $identifier. It's a string that is left up to the - notice implementor to define which would indicate a - fundamentally duplicate notice. The field is optional and - if it's not included it's not possible for notice - suppression to take place. - - - Duplicate notices are suppressed by default for the interval - defined by the Notice::default_suppression_interval variable - (1 hour by default). - - - A new notice action was defined ACTION_NO_SUPPRESS to prevent - suppression for a specific notice instance. A convenience set - named not_suppressed_types was also created to not suppress - entire notice types. - - - A new field was added to the PolicyItem type to modify the length - of time a notice should be suppressed if the predicate matches. - The field is named $suppress_for. This name makes the code more - readable like this: $suppress_for = 1day - - - New events were created to give visibility into the notice - framework's suppression activity. - - event Notice::begin_suppression(n: Notice::Info) - - event Notice::suppressed(n: Notice::Info) - - event Notice::end_suppression(n: Notice::Info) - - - The suppression.bro script doesn't have a baseline because - it is causing a segfault in Bro. This one test is the - reason that this is being integrated into a branch instead - of master. (Seth Hall) - - * Fix crash on exit. Addresses #607. (Jon Siwek) - - * Fix PktSrc setting next_timestamp even when no packet available. - (Jon Siwek) - - * Fix lack of NUL-termination in to_upper/to_lower BIF's return val. - (Jon Siwek) - - * Fixing unit tests and some minor bugs. (Jon Siwek) - - * Fix broctl cluster log rotation. Addresses #619. (Jon Siwek) - - * Added session ID to the SSL logging. (Seth Hall) - - * Adding "install-aux" target + updating bro-aux submodule. (Jon - Siwek) - - * Cleaning up INSTALL and README. (Jon Siwek) - - * Remove $Id$ tags. (Jon Siwek) - - * Remove policy.old directory. Addresses #511. (Jon Siwek) - - * Small rework with ssl base script to reduce memory usage. (Seth - Hall) - - * Updated the mozilla root certs. (Seth Hall) - -1.6-dev-1261 | 2011-09-15 17:13:55 -0700 - - * Memory leak fixes. Addresses #574 (Jon Siwek) - - * Add configure options for ruby/bindings integration. (Jon Siwek) - - * Fix filter path_func to allow record argument as a subset of - stream's columns. Addresses #600. (Jon Siwek) - - * Log rotation is now controlled directly through Filter records. (Jon Siwek) - - * Fix indexing for record types with optional fields. Addresses #378 - (Jon Siwek) - -1.6-dev-1248 | 2011-09-15 16:01:32 -0700 - - * Removed custom malloc() implementation for FreeBSD. Closes #557. - (Jon Siwek) - - * Testing/external scripts no longer compute MD5 checksums for SMTP - entities. (Robin Sommer) - - * External tests no longer include the full content of mismatching - files in the diagnostics output. (Robin Sommer) - -1.6-dev-1241 | 2011-09-14 22:51:52 -0400 - - * Fixing a major memory utilization issues with SSL analysis. (Seth - Hall) - - * Enhancements to HTTP analysis: (Seth Hall) - - - More options for the header-names.bro script. - - - New script for logging header names and values. Closes #519. - (Seth Hall) - - - HTTP body size measurement added to http.log. - - - The value of the content-length headers has now been removed - in the default output but it could be added back locally at an - installation by a user. - - - Added fields to indicate if some parsing interruption happened - during the body transfer. Closes #581 (Seth Hall) - - * Misc smaller usability and correctness updates: (Seth Hall) - - - Removed an notice definition from the base SSL scripts. - - - Moved a logging stream ID into the export section for known-services - and bumped priority for creating the stream. - - - Adding configuration knobs for the SQL injection attack detection - script and renaming the HTTP::SQL_Injection_Attack notice to - HTTP::SQL_Injection_Attack_Against - - - Bumped priority when creating Known::CERTS_LOG. - - - Fixing a warning from the cluster framework. (Seth Hall) - - * Bugfix for log writer, which didn't escape binary stuff in some - situations. Closes #585. (Robin Sommer) - - * A larget set of changes to the testing/external infrastructure. - The traces for external test-suites are no longer kept inside the - repositories themselves but downloaded separately via curl. This - is because git is pretty bad at dealing with large files. See the - README for more information. (Robin Sommer) - -1.6-dev-1221 | 2011-09-08 08:41:17 -0700 - - * Updates for documentation framework and script docs. (Jon Siwek) - - * The script level PF_RING support isn't working so removing it. - (Seth Hall) - - * Delete SSL certificates from memory after ssl_established event. - (Seth Hall) - - * Small fixes for SSL analysis. (Seth Hall) - -1.6-dev-1212 | 2011-09-07 16:15:28 -0700 - - * Internally, the UID generation can now return values from - different pool for better reproducability in testing mode. - (Gilbert Clark). - - * Added new BiF unique_id_from(pool: string, prefix: string) that - allows the user to specify a randomness pool. (Gilbert Clark) - -1.6-dev-1198 | 2011-09-07 11:03:36 -0700 - - * Extended header for ASCII log that make it easier for scripts to - parse Bro log files. (Gilbert Clark) - - * Potential fix for rotation crashes. Addresses #588. (Robin Sommer) - - * Added PF_RING load balancing support to the scripting layer, - enabled by loading the misc/pf-ring-load-balancing script. (Seth - Hall) - - * Added a BiF setenv() for setting environment variables. (Seth - Hall) - -1.6-dev-1184 | 2011-09-04 09:34:50 -0700 - - * FindPCAP now links against thread library when necessary (e.g. - PF_RING's libpcap). (Jon Siwek) - - * Install binaries with an RPATH. (Jon Siwek) - - * Fix for a case where nested records weren't coerced even though - possible. (Jon Siwek) - - * Changed ASCII writer to delay creation of log after rotation until - next write. - - * Changed default snaplen to 65535 and added a -l/--snaplen command - line option to set it explicitly. Addresses #447. (Jon Siwek) - - * Various updates to logging framework. (Seth Hall) - - * Changed presentation of enum labels to include namespace. (Jon - Siwek) - - * HTTP analyzer is now enabled with any of the HTTP events. (Seth - Hall) - - * Fixed missing format string that caused some segfaults. (Gregor - Maier) - - * ASCII writer nows prints time interval with 6 decimal places. - (Gregor Maier) - - * Added a Reporter::fatal BIF. (Jon Siwek) - - * Fixes for GeoIP support. Addresses #538. (Jon Siwek) - - * Fixed excessive memory usage of SSL analyzer on connections with - gaps. (Gregor Maier) - - * Added a log postprocessing function that can SCP rotated logs to - remote hosts. (Jon Siwek) - - * Added a BiF for getting the current Bro version string. (Jon - Siwek) - - * Misc. doc/script/test cleanup. (Jon Siwek) - - * Fixed bare-mode @load dependency problems. (Jon Siwek) - - * Fixed check_for_unused_event_handlers option. (Jon Siwek) - - * Fixing some more bare-mode @load dependency issues (Jon Siwek) - - * Reorganizing btest/policy directory to match new scripts/ - organization. Addresses #545 (Jon Siwek) - - * bro scripts generated from bifs now install to - $prefix/share/bro/base. Addresses #545 (Jon Siwek) - - * Changeed/fixed some cluster script error reporting. (Jon Siwek) - - * Various script normalization. (Jon Siwek) - - * Add a test that checks each individual script can be loaded in - bare-mode. Adressess #545. (Jon Siwek) - - * Tune when c$conn is set. Addresses #554. (Gregor Maier) - - * Add ConnSize_Analyzer's fields to conn.log. (Gregor Maier) - - * Fixing bug in "interesting hostnames" detection. (Seth Hall) - - * Adding metrics framework intermediate updates. (Seth Hall) - -1.6-dev-1120 | 2011-08-19 19:00:15 -0700 - - * Fix for the CompHash fix. (Robin Sommer) - -1.6-dev-1118 | 2011-08-18 14:11:55 -0700 - - * Fixing key size calculation in composite hash code. (Robin Sommer) - -1.6-dev-1116 | 2011-08-18 10:05:07 -0700 - - * Remove the 'net' type from Bro (addresses #535). - - * Fix H3 assumption of an 8-bit byte/char. (Jon Siwek) - - * Allow reading from interface without additional script arguments. - Explicitly passing in '-' as an additional command line argument - still allows reading a script from stdin. (Jon Siwek) - - * SSH bruteforcing detection now done with metrics framework. (Seth - Hall) - - * Updates for SQL injection attack detection to match the metrics - framework updates. (Seth Hall) - - * Metrics framework now works on cluster setups. (Seth Hall) - - * Reclassifying more DNS manager errors as non-fatal errors. (Robin - Sommer) - - * Fix ConnSize_Analyzer when used in conjunction with connection - compressor. (Gregor Maier) - - * Fix reporter using part of the actual message as a format string. - (Jon Siwek) - -1.6-dev-1095 | 2011-08-13 11:59:07 -0700 - - * A larger number of script documentation updates. Closes #543. (Jon - Siwek) - - * Workaround for FreeBSD CMake port missing debug flags. (Jon Siwek) - - * piped_exec() can now deal with null bytes. (Seth Hall) - - * Fix vector initialization for lists of records with optional - types. Closes #485. (Jon Siwek) - - * Fix redef'ing records with &default empty set fields. Closes #460. - (Jon Siwek) - - * Fix ConnSize_Analyzer when used in conjunction with the connection - compressor. (Gregor Maier) - - * Fix reporter using part of the actual message as a format string. - (Jon Siwek) - - * Fixing reporter's location tracking. Closes #492. (Robin Sommer) - - * Turning DNS errors into warnings. Closes #255. (Robin Sommer) - - * Logging's path_func now receives the log record as argument. - Closes #555. (Robin Sommer) - - * Functions can now be logged; their full body gets recorded. - Closes #506. (Robin Sommer) - - * Bugfix for hostname notice email extension. (Seth Hall) - - * Updates for notice framework. (Seth Hall) - - - New ACTION_ADD_GEODATA to add geodata to notices in an extension - field named remote_location. - - - Loading extend-email/hostnames by default now that it only does - anything when the ACTION_EMAIL action is applied (finally). - - * Updates to local.bro (Seth Hall) - - * Added the profiling script. (Seth Hall) - - * Updates for SSH scripts. (Seth Hall) - - * ConnSize analyzer is turned on by default now. (Seth Hall) - - * Updates for the build system and site local scripts for cluster. - (Seth Hall) - - * HTTP now uses the extract_filename_from_content_disposition function. (Seth Hall) - - * Major SMTP script refactor. Closes #509. (Jon Siwek and Seth Hall) - - * New variable Site::local_nets_table in utils/site for mapping - address to defined local subnet. - - * Metrics framework updates, more to come. (Seth Hall) - - -1.6-dev-1061 | 2011-08-08 18:25:27 -0700 - - * A set of new/changed tests regarding the new policy script - organisation. (Robin Sommer) - -1.6-dev-1058 | 2011-08-08 16:15:18 -0700 - - * Reorganisation of the scripts that Bro loads by default. (Seth - Hall) - - - policy/ renamed to scripts/ - - - By default BROPATH now contains: - - scripts/ - - scripts/policy - - scripts/site - - - The scripts in scripts/base/protocols/ only do logging and state - building. - - - All of scripts/base/ is loaded by by default. This can however - be disabled by switching Bro into "bare mode" using the new - command-line option --bare-mode (or -b). The cripts in - scripts/base/ don't use relative path loading to ease use of - bare mode (to copy and paste that script). - - - The scripts in scripts/base/frameworks/ add functionality - without causing any additional overhead. - - - All "detection" activity happens through scripts in - scripts/policy/. - - - bro.init was renamed to base/init-bare.bro, and base/all.bro was - renamed to init-default.bro. - - - local.bro now loads more functionality from policy/ and adds - more documentation. (Seth Hall) - - * Adding default_path_func() to the logging framework that makes the - default naming scheme script-level controlled. (Robin Sommer) - - * Reworking logging's postprocessor logic so that postprocessor - commands are no longer run by the log writers themselves, but - instead by a script level function. (Robin Sommer) - - * The communication subsystem is now by default off and must be - enabled explicitly with a new BiF, enable_communication(). Closes - #540. (Robin Sommer) - - * The hostname notice email extension now only add hostnames for - emailed noticed. (Seth Hall) - - * Cleaning up doc generation. (Seth Hall) - -1.6-dev-1044 | 2011-08-05 19:07:32 -0700 - - * Fixing memory (and CPU) leak in log writer. - - * Fixing crash in memory profiling. (Robin Sommer) - - * Fix compiler warning. (Robin Sommer) - - * Fixing missing sync in cluster setup. (Robin Sommer) - - -1.6-dev-1038 | 2011-08-05 18:25:44 -0700 - - * Smaller updates to script docs and their generation. (Jon Siwek) - - * When using a `print` statement to write to a file that has raw output - enabled, NUL characters in string are no longer interpreted into "\0", - no newline is appended afterwards, and each argument to `print` is - written to the file without any additional separation. (Jon Siwek) - - * Test portatibility tweaks. (Jon Siwek) - - * Fixing PktSrc::Statistics() which retured bogus information - offline mode. Closes #500. (Jon Siwek) - - * --with-perftools configure option now assumes --enable-perftools. - Closes #527. (Jon Siwek) - -1.6-dev-1018 | 2011-07-31 21:30:31 -0700 - - * Updating CHANGES. (Robin Sommer) - -1.6-dev-1016 | 2011-07-30 18:34:28 -0700 - - * Install example config files dynamically. They'll only get - installed when the distribution version differs from existing - version on disk. (Jon Siwek) - - * Fixed memory leak in SSL analyzer. (Seth Hall) - - * Beginning rework of metrics interface. (Seth Hall) - - * New/updated unit tests for scripts. (Jon Siwek) - - * New/updated documentstion for scripts. (Jon Siwek) - - * A number of fixes for scripts in utils/. (Jon Siwek) - -1.6-dev.244 Thu Jul 28 17:08:21 PDT 2011 - -- mask_addr() now returns subnet (addresses #512). (Jon Siwek) - -- Normalize Notice::Type identifiers per convention (closes #484). - (Jon Siwek) - -- Fixing default-loaded-scripts test for BSD systems. (Jon Siwek) - -- New piped_exec() BiF for pipeing data into an external command. (Jon - Siwek) - -1.6-dev.242 Mon Jul 25 21:42:39 PDT 2011 - -- Adding a documentation coverage test. (Jon Siwek) - -- The CMake targets for generating reST docs from policy scripts are - now automatically generated via the genDocSourcesList.sh script. - (Jon Siwek) - -- Fixed a number of script error. (Jon Siwek) - -- Fixes to relative @load'ing. (Jon Siwek) - -- Fixes to tests. (Robin Sommer) - -1.6-dev.240 Sun Jul 24 15:14:26 PDT 2011 - -- Updated tests and test baselines. (Jon Siwek) - -- ASCII log writer now prints time values w/ constant 6 digit - precision. (Jon Siwek) - -- Many policy script updates acrsso the board (Seth Hall). - -- Moving devel-tools to bro-aux. (Robin Sommer) - -- BugFix for disable_analyzer(), which could cause crashes with some - analyzers. (Robin Sommer) - -- Bugfix for potential segfault in DebugLogger. (Robin Sommer) - -1.6-dev.226 Thu Jul 21 15:23:39 PDT 2011 - -- Extensions to the @load and @unload process. (Jon Siwek) - - * Make @load statements recognize relative paths. For example a - script can do "@load ./foo" to load a script named foo.bro that - lives in the same directory or "@load ../bar" to load a script - named bar.bro in the parent directory, even if those directories - are not contained in BROPATH. - - * Reimplementation of the @prefixes statement. (Closes #486) - - Any added prefixes are now used *after* all input files have - been parsed to look for a prefixed, flattened version of the - input file somewhere in BROPATH and, if found, load it. For - example, if "lcl" is in @prefixes, and site.bro is loaded, then - a file named "lcl.site.bro" that's in BROPATH would end up being - automatically loaded as well. Packages work similarly, e.g. - loading "protocols/http" means a file named - "lcl.protocols.http.bro" in BROPATH gets loaded automatically. - - * Fix @unload'd files from generating bro_script_loaded event. - - * Updates to tests. - -1.6-dev.225 Wed Jul 20 17:10:41 PDT 2011 - -- IRC improvements (Jon Siwek). Including: - - * Shorten what's displayed in the IRC's log mime_type column for - DCC transfers. - - * Add IRC unit tests. - - * Fix IRC analyzer supplying wrong type to irc_dcc_message event. - - * Removed irc_client and irc_server events. - - * Added is_orig arguments to all other irc events. - - * Fix analyzer not recognizing Turbo DCC extension message format. - - * Fix analyzer not generating irc_dcc_message event when irc_privmsg_message - event doesn't have a handler registered. - -- Fixing tests that need a diff canonifier. (Jon Siwek) - -1.6-dev.223 Tue Jul 19 19:10:36 PDT 2011 - -- Adding a script to update CHANGES and VERSION. (Robin Sommer) - -1.6-dev.218 Tue Jul 19 18:16:44 PDT 2011 - -- Comprehensive policy script overhaul/rewrite. (Seth Hall) - - Changes are too extensive to list individually. - -- Removing undocumented -H command line flag. (Robin Sommer) - -- Fixing many tests. (Everybody) - -- Fixing 0-chunk bug in remote logging. (Robin Sommer) - -- $PATH is now appropriately set by the bro-path-dev.(sh|csh) scripts. - (Seth Hall) - -- Making valgrind a bit more happy. (Robin Sommer) - -- New BiF record_field_vals() that returns the fields of a record in a - table with meta-information. (Robin Sommer) - -- Adding a script in aux/devel-tools that extracts a connection from a - trace based on uid. (Robin Sommer) - -- Fixing bug causing crash when running without arguments. (Robin Sommer) - -- A new event bro_script_loaded() raised for each policy script - loaded. Also removing the -l command-line option as that can now be - done at the script-level. (Robin Sommer) - -- Fixing memory leaks. (Gilbert Clark, Seth Hall, Robin Sommer) - -- Many SSL analysis improvements and fixes. (Seth Hall) - -- Fixing bug with event priorities potentially being ignored for the - handler. (Robin Sommer) - -- Overhauling the internal reporting of messages to the user. The new - Reporter class is now in charge of reporting all errors, warnings, - informational messages, weirds, and syslogs; and it passes - everything through the script layer. (Robin Sommer) - -* Removed the alarm statement and the alarm_hook event. (Robin Sommer) - -- Adding new policy file test-all.bro that loads all other policies. - This is for testing only. (Robin Sommer) - -- A new framework for doing regression testing with larger traces and - more complex Bro configurations in testing/external. (Robin Sommer) - -- Many updates to script doc generation. (Jon Siwek) - -1.6-dev.146 Sat Jun 25 18:12:27 PDT 2011 - -- DNS mapping are now becoming invalid when an entry's TTL expires. - (Thomas Other) - -- Reworking how Bro tracks which scripts are already loaded. Rather - than paths, Bro now tracks inode numbers. (Jon Siwek) - -- New BiF netstats() to query packet capture statistics. The netstats - script now uses the new BiF to periocally report packets drops. The - net_stats_update() event and the heartbeat_interval global went - away. (Seth Hall) - -- Fixing bug with logging &optional records. Closes #476. (Robin - Sommer) - -- Fixing istate.events-ssl test failing because of expired cert. (Jon - Siwek) - -- A large number of improvements and fixes for Bro's doc mode. (Jon - Siwek) - -- Significant updates for RPC and NFS analyzers (Gregor Maier) - - * Unify semantics for UDP and TCP connections. - - * RPC can now log to a log file if desired. - - * Portmapper can now log general activity to a log file and also log - actual port mappings. - - * NFS analyzer now supports significantly more procedure calls as - as file name tracking and file content extraction. - -- NetBIOS fixes. (Jon Siwek) - -- A number of unit tests are more robust and portable. (Jon Siwek) - -- A new BiF unique_id() that returns a string that's unique across Bro - instaces with high probablity. (Robin Sommer) - -- Complete rewrite of the BinPAC SSL analyzer. (Seth Hall) - - * DER certificates are extracted as strings to be used with - corresponding BiFs. - - * x509_verify function to verify single certs and/or full - certificate chains. - - * Removed hand written SSL analyzer. - - * The ssl.bro script is just a place-holder for now. New version - will come with the other new scripts. - -- New syslog analyzer. (Seth Hall) - -- @load now supports loading a directory. With a directory "foo" - somewhere in BROPATH, "@load foo" now checks if there's a file - "foo/__load__.bro". If so, it reads that file in. (Robin Sommer) - -- ASCII logger now escapes non-printable characters. Closes #450. - (Robin Sommer) - -- Packaging tweaks and rewrite of 'dist' target. (Jon Siwek) - -- Changes to allow DEB packaging via CPack, addresses #458. (Jon - Siwek) - -- An extension to the ICMP analyzer to handle redirects. Julien - Sentier - -- Removing old istate test-suite. (Robin Sommer) - -- A hack to report missing GeoIP support only once. This closes #357, - but #455 captures the need for a more general solution. (Robin - Sommer) - -- Bugfix: vectors in records were not initalized. Closes #421. (Robin - Sommer) - -- If IPv6 default is not compiled in, the default BPF filters now - excludes IPv6 packets. (Robin Sommer) - -- New bif bro_has_ipv6() to check whether IPv6 support is compiled in. - (Robin Sommer) - -- Updating btests and a Makefile. "make" now runs all the tests. - (Robin Sommer) - -- Moving the test-scripts from the old test-suite over to btest. - (Robin Sommer) - -- Fix for major bug in POP3 analyzer, which didn't recognize '.' - terminators in multi-line replies if the terminator was bare (no - newline). This caused it to ignore the rest of the session that it's - analyzing. (Vern Paxson) - -- Fix compiler warning with gcc-4.4.4 (Gregor Maier) - -- Adding example documentation for a script's use of logging features. - (Jon Siwek) - -- Adding &log attribute to static attr_names array. (Jon Siwek) - -- Bro can now track packet and byte counts per connection. (Gregor - Maier) - - * If 'use_conn_size_analyzer' is true, the event engine tracks - number of packets and raw IP bytes per connection. If - report_conn_size_analyzer is true, these values are included as - four new columns into conn.log - - * I changed conn.bro so that the value of - report_conn_size_analyzer follows that of - use_conn_size_analyzer. For the new conn.log, we probably want - to get rid of report_conn_size_analyzer anyway. - -- Fixing numerous compiler warnings and portability issues. (All) - -- Switching vectors from being 1-based to 0-based. Note that this is a - change that break backwards-compatibility. (Robin Sommer) - -- Increasing serialization format version for the recent 64-bit - changes. (Robin Sommer) - -- Support for (mixed) MPLS and VLAN traffic, and a new default BPF - filter. (Seth Hall and Robin Sommer) - - * Merging in the patch from #264, which provides support for mixed - VLAN and MPLS traffic. - - * Changing Bro's default filter from being built dynamically to - being a static "ip or not ip". To get the old behaviour back - (i.e., the dynamically built filter), redef "all_packets" to - false. - - * print-filter.bro now always prints the filter that Bro is - actually using, even if overriden from the command line. (Robin - Sommer) - -- Changing the HTTP's analyzers internals to use 64-bit integers. - (Gregor Maier). - -- Fixing bug with deleting still unset record fields of table type. - (Robin Sommer) - -1.6-dev.99 Fri Apr 22 22:10:03 PDT 2011 - -- Extending the connection record with a unique identifier. (Robin - Sommer) - - type connection: record { - [...] - id: string; - }; - - These identifiers very likely unique even across independent Bro - runs. - -- Delete operator for record fields. (Robin Sommer) - - "delete x$y" now resets record field "x" back to its original state - if it is either &optional or has a &default. "delete" may not be - used with non-optional/default fields. - -- Fixing bug with nested record coercions. (Robin Sommer) - -- Fixing a do_split() bug. (Seth Hall) - - -1.6-dev.94 Thu Apr 21 19:51:38 PDT 2011 - -- Fixing generation of config.h. (Jon Siwek) - -- Updates and tests for NetBIOS name BiF. (Seth Hall) - -- Fixing do_split bug(), and adding a test. (Seth Hall) - -- When Bro is given a PRNG seed, it now uses its own internal random - number generator that produces consistent results across sytems. - Note that this internal generator isn't very good, so it should only - be used for testing purpses. (Robin Sommer) - -- The BTest configuration now sets the environemnt variables TZ=UTC - and LANG=C to ensure consistent results. (Robin Sommer) - -- Logging fixes. (Robin Sommer) - -1.6-dev.88 Wed Apr 20 20:43:48 PDT 2011 - -- Implementation of Bro's new logging framework. We will document this - separately. (Robin Sommer) - -- Already defined record types can now be further extended via the - '+=' operator. The added fields must be either &optional or have a - &default value. (Robin Sommer) - - Example: - - type Foo: record { - a: count; - b: count &optional; - }; - - redef record Foo += { - c: count &default=42; - d: count &optional; - }; - - global f: Foo = [$a=21]; - - print f; - - Output: - - [a=21, b=, c=42, d=] - -- Enabling assignment of empty vectors ("vector()"). (Robin Sommer) - -- Fixing attributes to allow &default attributes to be associated with - records fields of type tables/sets/vector. (Robin Sommer) - -- '[]' is now a valid record constructor. (Robin Sommer) - -- A instance of a record type A is now coercable into one of type B if - the fields of type A are a subset of those of type B. (Robin Sommer) - -- A number of bug fixes and enhancements for record/set/table/vector - coercion. (Robin Sommer) - -- Fixing a problem with records that have optional fields when used as - table/set indices. Addresses #367. (Robin Sommer) - -- Fixing an off-by-one error in join_string_vec(). (Seth Hall) - -- Updating to_count() to cope with 64bit ints. (Seth Hall) - -- A new BiF count_to_v4_addr() to turn a count into an IPv4 address. - (Seth Hall) - -1.6-dev.80 Mon Apr 18 14:50:54 PDT 2011 - -- New framework for generating documentation from Bro scripts. (Jon - Siwek) - - This includes: - - * Changes to Bro's scanner/parser to facilitate automatic - generation of Bro policy script documentation in - reStructuredText format. - - * New command line flags -Z/--doc-scripts to enable the new doc - generation mode. - - * Changes to bifcl to pass comments starting with "##" through - into the generated .bro script. - - * A "doc" build target for the top-level Makefile to first - generate reStructuredText for a defined set of Bro policy - scripts, and then run that through Sphinx to create HTML - documentation. - -1.6-dev.78 Mon Apr 18 12:52:55 PDT 2011 - -- Adding files to CMake build targets so they show up in generated IDE - projects. This addresses #413. (Jon Siwek) - -- Fix unnecessary config.h preprocessor (re)definitions. This - addresses #414. (Jon Siwek) - -- Updating istate tests. (Robin Sommer) - -- Adding files to CMake build targets so they show up in generated IDE - projects. - -- Adding new environment variable BRO_SEED_FILE to set the seed file - for the random number generator. (Robin Sommer) - -1.6-dev.71 Fri Apr 1 16:06:33 PDT 2011 - -- Removing code for the following no longer supported functionality. - - * Trace rewriting. - * DFA state expiration in regexp engine. - * Active mapping. - * Unused hash functions. - - (Robin Sommer) - -- Fixing crashes when SSL is not configured correctly. (Robin Sommer) - -1.6-dev.66 Tue Mar 29 21:52:01 PDT 2011 - -- Initial btest setup (Don Appleman and Robin Sommer) - -- Porting the istate tests to btest (not finished) (Robin Sommer) - -1.6-dev.63 Mon Mar 21 16:31:15 PDT 2011 - -- Changes to the way user-modifiable config files are installed (Jon Siwek) - - * Duplicates of the distribution's configuration files are now - always installed with a .example suffix - - * Added --binary-package configure option to toggle configure - logic specific to the creation of binary packages. - - * When not in binary packaging mode, `make install` never - overwrites existing configure files in case they've been - modified. The previous behavior (CMake's default) would only - avoid overwriting modified files if one consistently uses the - same build directory and doesn't reconfigure. - -- Fixed an issue with Mac package's pre-install script not preserving - ACLs. (Jon Siwek) - -- Minor cleanup/refactor of the make-mac/rpm-packages scripts. (Jon - Siwek) - -- Add explicit CMake check for compiler. (Jon Siwek) - -- Add alternative way to set BROPATH for running bro from build/ dir. - (Jon Siwek) - -- Fixing compiler warnings (Gregor Maier) - -- Remvoing leftover local variables that caused compile error on Mac - OS X. (Gregor Maier) - -1.6-dev.53 Fri Feb 25 17:03:05 PST 2011 - -- Fixing file detector leak in remote communication module. (Scott - Campbell) - -- Updating independent-state tests to work with new setup. (Robin - Sommer) - -1.6-dev.49 Fri Feb 25 15:37:28 PST 2011 - -- Enum IDs can have explicitly defined values. (Gregor Maier) - -- Extensions for the built-in function compiler, bifcl. (Gregor Maier) - - * Support for policy-layer namespaces. - * Support for type declarations in bif files (with access them - from C++) - * Extended const declarations in bif files. - - See http://bro.icir.org/devel/bif-doc for more information. - -1.6-dev.48 Fri Feb 25 10:53:04 PST 2011 - -- Preliminary TCP Reassembler fix: deliver data after 2GB by disabling - the unused seq_to_skip feature. (Gregor Maier) - -1.6-dev.47 Fri Feb 25 10:40:22 PST 2011 - -- Fixing endianess error in XDR when data is not 4-byte aligned. - (Gregor Maier) - -- Fix for Val constructor with new int64 typedefs. (Gregor Maier) - -- Updated fix for OS X 10.5 compile error wrt llabs(). (Gregor Maier) - -- Fix more compiler warning wrt printf format strings. (Gregor Maier) - -1.6-dev.45 Tue Feb 8 21:28:01 PST 2011 - -- Fixing a number of compiler warnings. (Seth Hall and Robin Sommer) - -1.6-dev.44 Tue Feb 8 20:11:44 PST 2011 - -- A number of updates to the SSL analyzer, including support for new - ciphers; SSL extensions; and bug fixes. The analyzer does not longer - throw weird for exceeding a predefined cipherspec_size anymore. - (Seth Hall and Rmkml). - -- The various split*() BiFs now handle strings containing null bytes - correctly. (Seth Hall) - -- Adding new aux/btest submodule. This is a framework we will use in - the future for doing unit tests. (Robin Sommer) - -1.6-dev.41 Mon Feb 7 13:43:56 PST 2011 - -- Smarter way to increase the parent/child pipe's socket buffer. - (Craig Leres). - -- Fixing bug with defining bro_int_t and bro_uint_t to be 64 bits wide - on some platforms. (Robin Sommer) - -1.6-dev.39 Mon Jan 31 16:42:23 PST 2011 - -- Login's confused messages now go through weird.bro. (Robin Sommer) - -1.6-dev.36 Mon Jan 31 08:45:35 PST 2011 - -- Adding more configure options for finding dependencies, (Jon Siwek) - - --with-flex=PATH path to flex executable - --with-bison=PATH path to bison executable - --with-perl=PATH path to perl executable - --with-python=PATH path to Python interpreter - --with-python-lib=PATH path to libpython - --with-python-inc=PATH path to Python headers - --with-swig=PATH path to SWIG executable - -- Fixing typo in PCAPTests.cmake (Jon Siwek) - - -1.6-dev.33 Mon Jan 24 15:29:04 PST 2011 - -- Fixing bug in SMB analyzer. (Robin Sommer) - -- Configure wrapper now deletes previous CMake cache (Jon Siwek) - -- Fix for the --with-binpac configure option. (Jon Siwek) - -1.6-dev.30 Thu Jan 20 16:32:43 PST 2011 - -- Changed configure wrapper to create config.status. (Jon Siwek) - -1.6-dev.29 Thu Jan 20 16:29:56 PST 2011 - -- Fixing little problem with initialization of Bro-to-Bro event - communication. (Christian Kreibich) - - -1.6-dev.27 Thu Jan 20 13:52:25 PST 2011 - -- Fine-tuning of the HTTP analyzer in terms of raising protocol - violations and interrupted transfers. (Gregor Maier) - - -1.6-dev.21 Wed Jan 19 17:36:02 PST 2011 - -- Added 4 new BiFs and a new record type for testing the entropy of - strings. (Seth Hall) - - find_entropy(data: string): entropy_test_result - This is a one shot function that accepts a string and - returns the result of the entropy calculations. - - entropy_test_init(index: any): bool - This and the next two functions are for calculating entropy - piece-wise. It only needs an index which can be any type of - variable. It needs to be something that uniquely identifies - the data stream that is currently having it's entropy - calculated. - - entropy_test_add(index: any, data: string): bool - This function is used to add data into the entropy - calculation. It takes the index used in the function above - and the data that you are adding and returns true if - everything seemed to work, false otherwise. - - entropy_test_finish(index: any): entropy_test_result - Calling this function indicates that all of the desired data - has been inserted into the entropy_test_add function and the - entropy should be calculated. This function *must* be called - in order to clean up an internal state tracking variable. - If this is never called on an index, it will result in a - memory leak. - - The entropy_test_result values have several measures of the - entropy, but a good one to work with is the "entropy" attribute. - It's a double and as the value approaches 8.0 it can be considered - more and more random. For example, a value of 7.832 would be - quite random but a value of 4.671 is not very random. - -1.6-dev.20 Wed Jan 19 17:30:11 PST 2011 - -- BRO_DNS_FAKE is now listed in the --help output. (Seth Hall) - - -1.6-dev.18 Wed Jan 19 16:37:13 PST 2011 - -- Removing unnecessary expire timer from http_sessions. (Gregor - Maier) - - -1.6-dev.16 Sat Jan 15 14:14:21 PST 2011 - -- Updates to the build system. (Jonathan Siwek) - - * ``make dist`` is now available to be used with the top-level - Makefile for creating source packages according to #344. - - * ``make-rpm-packages`` and ``make-mac-packages`` scripts can - now generate binary packages according to #295. - - * Additional configure options to change packaging behavior. - - * OS X builds will now prefer to link static libraries of - optional dependencies that don't come with the vanilla - operating system. - - * Fix for OS X 10.5 compile error dealing with the llabs() - function from stdlib. - - * Installing as a different user than the one that - configured/built now works (although, a harmless error message - about not being able to write the install manifest may occur). - - -1.6-dev.3 Wed Dec 8 04:09:38 PST 2010 - -- Merge with Subversion repository as of r7137. Incorporated change: - - * Fix for packet processing resumption when a remote Bro dies - during state synchronization (Robin Sommer). - -1.6-dev.2 Wed Dec 8 03:57:03 PST 2010 - -- Compatibility fix for OpenSSL 1.0.0 (Christian Kreibich, Gregor - Maier). - -1.6-dev.1 Sat Nov 27 12:19:47 PST 2010 - -- Merge with Subversion repository as of r7098. Incorporated changes: - - * Rotation post-processors are now passed an additional argument - indicating whether Bro is terminating (Robin Sommer). - - * Bro now consistently generates a file_opened event for all - fopen() calls. (Robin Sommer). - - * You can now redefine the email_notice_to function (Robin - Sommer). - -1.6-dev.0 Fri Nov 26 13:48:11 PST 2010 - -- The Bro source code is now developed in the new git repositories. - See the developer pages at http://www.bro-ids.org for more - information on the new development process. - -- Bro's build and installation setup has been moved from GNU - autotools to CMake. As a result of that, layout and specifics of - the distribution has changed significantly. - -- Lots of pieces have been removed from the distribution that are - either now unnecessary or are no longer maintained. - -- As part of the cleanup, a numbef of Bro configure options and - their corresponding functionality have been removed, including: - - * --disable-select-loop - * --with-dag - * --disable-nbdns - * --enable-activemapping - * --enable-activemapping - * --enable-shippedpcap - -- The previous configure option --enable-int64 is now enabled by default, - and can no longer be disabled. - -- ClamAV support has been removed, which has been non-functional for - a while already. - -1.5.2.7 Sun Sep 12 19:39:49 PDT 2010 - -- Addressed a number of lint nits (Vern Paxson). - - -1.5.2.6 Sun Sep 12 17:00:13 PDT 2010 - -- The SWIG file now explicitly lists those pieces from broccoli.h which it - wants to wrap, rather than just including all of broccoli.h (Robin Sommer). - This fixes the problem that the SWIG bindings depend on what configure - finds out about the availability of libpcap even though the corresponding - functions don't need to be wrapped anyway. - -- http-header.bro now includes a global include_header: set[string] - (Robin Sommer). If it contains any strings, then only those headers - will be processed. If left empty, then you continue to get the current - behavior of processing all headers. - -- Several changes to drop.bro (Robin Sommer): - - * If true, the new flag Drop::dont_drop_locals indicates that - local hosts should never be dropped. On by default. - - * If true, the new flag Drop::debugging activates extensive debugging - output for the catch-and-release logic. Off by default. - - * The timeout for tracking dropping information is now 1 day - rather than 7 days, to better echo the one-restart-a-day semantics - used in the past. - - * Bug fix for hosts once dropped by later cleared; some state - for them persisted. - -- Portability fix for Broccoli Python bindings on 64-bit platforms (Robin - Sommer). - -- The HTTP analyzer no longer attempts to track Server/User-Agent - versions, as these are hugely voluminous (Seth Hall). Ideally this - would still be available as an option for someone who truly wants - the full set. - -- HTTP and SMTP no longer have extra-short inactivity timeouts, as - these were too often leading to premature expiration of a connection - (Robin Sommer). - -- The "rst" tool (aux/rst/) now takes an optional "-I " argument - that instructs it to inject as payload rather than sending a RST - packet (Vern Paxson). must be NUL-terminated, and the NUL is not - included. - -- Bug fix for crashes in the DNS analyzer when processing replies for - which no request was seen (Robin Sommer). - - -1.5.2.5 Mon Jul 19 16:20:58 PDT 2010 - -- Removed now-quite-stale SSHv1 overflow detection, as it's more prone - to false positives than useful detection (Vern Paxson). - - -1.5.2.4 Fri Jun 4 16:02:11 PDT 2010 - -- Bug fixes for terminating connections (Tyler Schoenke and Vern Paxson). - - -1.5.2.3 Wed Mar 24 18:23:57 PDT 2010 - -- Bug fixes for --enable-int64 and for avoiding bogus statistics / - bad memory references when generating profiling information upon - exit (Vern Paxson). - - -1.5.2.2 Tue Jan 12 12:33:42 PST 2010 - -- Broccoli compiler warning fixes (Kevin Lo). - - -1.5.2.1 Sun Jan 10 16:59:01 PST 2010 - -- Bug fix for Active Mapping support (Kevin Lo). - - -1.5.2 Sat Dec 26 18:38:37 PST 2009 - -- Portability fixes for --enable-int64 (Vern Paxson). - - -1.5.1 Fri Dec 18 15:17:12 PST 2009 - -- Due to a Python configuration problem, the original 1.5 distribution - did not include the BroControl component, which also introduced a - portability problem for CentOS. These issues have now been fixed (Robin - Sommer and Vern Paxson). - - -1.5 Wed Dec 16 21:28:47 PST 2009 - -- Bro now comes with a new framework, BroControl, for managing an - operational Bro setup, including support for installation, configuration, - and maintainance tasks such a log archival and mail notification. The - framework transparently supports both traditional standalone setups as - well as cluster installations in which multiple Bro boxes coordinate to - analyze a high-volume network link. - - See aux/broctl/README for more information about BroControl. - - Note, BroControl supersedes the older BroLite system, which is no longer - supported and has been deprecated for a while now. - -- Numerous adjustments to DPD = dynamic protocol detection (Robin Sommer): - - o The Analyzer::ProtocolViolation?() method can now be passed the - offending data (which POP3, SMTP, and FTP now do). This information - is added to the "reason" string passed to the script level. - - o SMTP now more accurately reports violations. - - o FTP stops processing when client & server successfully negotiate - an AUTH scheme (leading to subsequent encryption). - - o Analyzer::ProtocolViolation() is virtual, and - TCP_ApplicationAnalyzer() overrides it to not report violations - for any partial connections, because very likely these arise just - due to the analyzer getting confused. - - o TCP::IsPartial() returns true if any side did not start with - a SYN packet (used to be just be for the originator). - - o The connection_state_remove handler in conn.bro now has a higher - &priority so that other handlers for the same event can use - determine_service() and see any changes it performs. - - o DynDisable:max_volume specifies a volume limit (default 10K). - Once a connection exceeds this limit, further protocol - limitations will neither raise ProtocolViolation notices nor - cause the analyzer to be disabled. - - o The event engine no longer raises protocol_violation events for - TCP connections which had gaps, as these have proven too unreliable. - (Note that, ideally, the *analyzers* should avoid reporting - protocol_violations when they can't reliably parse a connection - anymore after a gap; but many don't.) - -- A set of new script functions provide support for incrementally computing - MD5 checksums (Seth Hall). - - md5_hash_init(index: any): bool - Initializes an incremental hashing instance. "index" is - a value of arbitrary type, used to identify this particular - instance (you can have multiple concurrent instances by - using different index values). Returns T on success, - F on failure (such as the index is already in use). - - md5_hash_update(index: any, data: string): bool - For the given hashing instance, updates the hash - based on the given data. Returns T on success, F on - failure (such as the index has not been initialized). - - md5_hash_finish(index: any): string - Returns the MD5-printable hash for the given index - and terminates the instance, or the string "" if the - index was not active. - -- Bro now supports a believed-to-be-robust mechanism for estimating the - proportion of traffic that it failed to capture ("measurement drops"), - which can arise due to overload in either Bro itself, the kernel's - packet filter, or problems with the link tapping mechanism (Vern Paxson). - The event engine can generate estimates for either live traffic or what - was previously recorded in a trace file, though traces subject to some - forms of selective omission (such as skipping over parts of a connection - to reduce storage) can lead to erroneous values. - - The estimates are based on observing gaps in TCP data streams, and - come in two forms: the rate at which such gaps appear, and the relative - volume of data missing due to the gaps. (We've found however that the - volume-based estimator is not robust due to occasional packets with - incorrect sequence numbers, so this estimator is off by default.) - - The easy way to get the estimates is to load capture-loss.bro. - By default, it generates a CaptureLossSummary notice upon Bro's exit, - which can look like: - - 1130222759.344066 CaptureLossSummary estimated rate = 0.00089124 / 0.000970997 (events/bytes) - - If the estimated loss is none, however, it suppresses this notice, - unless you redef CaptureLoss::summary_if_none to T. - - You can also get finer-grained access by defining a "gap_report" - event handler and redef'ing gap_report_freq to a non-zero interval - (such as "10 sec"). This event allows you to pinpoint regions in - time that exhibit significant capture loss. See capture-loss.bro - for an example of a handler for this event. - - Finally, these changes include a number of fixes to Bro's - ack_above_hole/content_gap analysis, which is now significantly - more robust. - -- GeoIP support now supports ASN lookups via the built-in - function lookup_asn(a: addr): count (Scott Campbell and Seth Hall). - -- The GeoIP built-in's lookup_location() and lookup_asn() now - support IPv6 (Seth Hall). Note, the current GeoIP distribution - doesn't include any IPv6 databases, so for now these won't succeed, - but the hooks are in place for when databases become available. - -- lookup_location() now falls back back to the country database if - the city database isn't available (Seth Hall). - -- The new SuccessfulPasswordGuessing Notice is generated when a host - has been seen attempting password guessing (currently only for FTP - sessions) and then successfully logs in (Royal Chan). You can control the - threshold for such reports in terms of how many attempts the host must - have made by redef'ing the variable password_guessing_success_threshhold, - which defaults to 20. - -- The new script http-detect-passwd.bro analyzes the Web items returned - for fetches that appear to be accessing the passwd file (Akhil Dhar). - It generates a PasswordFullFetch Notice if it appears that the item - includes a full password file, and PasswordShadowFetch if it looks like - a shadowed password file. - -- The new built-in - - system_env(cmd: string, env: table[string] of string) - - works like system(), but puts the table entries into the environment - before invoking the command (Robin Sommer). Each in the table - creates an environment variable of the form "BRO_ARG_", whose - value is the corresponding table entry. - -- The new script function - - execute_with_notice(cmd: string, notice_info) - - executes "cmd" with an environment containing the fields of the - notice_info, i.e., the information associated with a Notice (Robin Sommer). - Per the new system_env() function above, the environment variables appear - as "BRO_ARG_", where is the field tag as it appears in - notice.log when you enable use_tagging. - -- The new built-in enable_raw_output(file) acts the same as - the attribute &raw_output (Seth Hall). - -- The new built-in file_opened(f: file) event is generated any time Bro - opens a script-level file (Justin Azoff). You can use this, for example, - if you want to ensure that a given file has a prelude in it such as - human-readable headers, even when the file is rotated. - -- The notice_info record has a new field - - aux: table[string] of string &optional - - which you can use for information specific to a given type of notice - (Robin Sommer). Entries in $aux appear as "aux_" tags in notice.log. - -- Another new notice_info record field is the boolean do_alarm (default=T), - which, if set to F, overides a notice action otherwise specifying to - generate an alarm (Robin Sommer). In other words, if do_alarm is F, no - alarm will be generated independent of the notice action. - - This is a work-around for the fact that we can't specify more than one - action. In particular, we couldn't NOTICE_DROP but then *not* alarm, - which we now can by returning NOTICE_DROP yet setting do_alarm to F. - -- The notice_info record field $dropped now appears in the tagged output - format if true (Robin Sommer). - -- NOTICEs relating to scan detection now no longer include the connection - that triggered the notice, as it really doesn't contain any useful - information, given that the particular trigger simply depends on the - detection algorithm and its parameters (Robin Sommer). However, we do - explicitly set $p (port number) in the notice, and also $n with the - number of attempts. - -- drop.bro now hardwires a Catch-and-Release redrop after seeing one - connection from a previously-dropped-but-already-released host - (Robin Sommer). - -- drop.bro now provides some new hooks (Robin Sommer): - - event address_dropped(a: addr) - Generated when an address has been dropped. - - event address_restored(a: addr) - Generated when connectivity to an address has been restored, - such as using the Catch-and-Release mechanism. - - event address_cleared(a: addr) - Generated when an address that was dropped in the past is - no longer being monitored looking for new connections - (as part of the Catch-and-Release mechanism). - -- The new built-in function - - hexdump(data_str: string) : string - - returns a hex dump representation of the given input data (Christian - Kreibich). The dump renders 16 bytes per line, with hex on the left and - ASCII (where printable) on the right. - -- Bro's notion of when a TCP connection begins now dastes to the first - instance of an initial SYN packet seen, rather than the last (Gregor Maier). - -- The Time Machine script tm-contents.bro now generates - - event contents_saved: event(c: connection, orig_file: string, - resp_file: string) - - when the content of a connection has been completely saved to disk - (Robin Sommer). - -- The mime.bro script now exports the MIME header callback table, and also - marks it as &redef'able so you can modify its entries (Matthias Vallentin). - The mime_log file is also now exported. - -- A new signature file, policy/sigs/http-bots.sig, contains signatures - to detect some of the current HTTP based controlled bot families (Seth Hall). - -- The signature engine's HTTP pattern matching has been fixed (Seth Hall) - to align with the documentation at: - - http://www.bro-ids.org/wiki/index.php/Reference_Manual:_Signatures#Content_conditions - - In particular, the content condition "http" is now referred to as - "http-request" (though "http" still works for backward compatibility), - "http-request-header" and "http-reply-header" now provide access to - headers seen in only one direction, and similarly for "http-request-body" - and "http-reply-body". (This latter is still accessible as "http-body" - for backwards compatibility.) - -- The new script variable max_remote_events_processed: count (default 10) - sets a limit on the number of remote events processed in each round, - before tending to other inputs (Robin Sommer). - -- If you set the new script variable dump_used_event_handlers to T, - then on startup Bro dumps out all of the event handlers that the - loaded set of scripts can invoke (Matthias Vallenti). - -- Summaries for DNS PTR scanning now use a separate Notice, - DNS_PTR_Scan_Summary, rather than overloading DNS_PTR_Scan (Robin Sommer). - -- scan.bro now provides a table skip_dest_server_ports: set[addr, port] - which lists servers (defined as an address and a port) excluded from - scan detection computations (Craig Leres and Jay Krous). - -- When redefining values on the command line directly (using var=value), - quotation marks are now implicit only if "var" is a variable of type - string (Christian Kreibich). This allows other string-like values - (such as enum's) to be passed as well. - -- scan.bro now explicitly loads conn.bro so that it can itself - be loaded independently (Robin Sommer). - -- login.bro depends on scan.bro (because of tracking authentication - "scans"), so now it explicitly loads it (Vern Paxson). - -- UDP_datagram_length_mismatch is now by default flagged just once per - originating host rather than once per connection, as it can generate - tons of messages (Vern Paxson). - -- Removed now-long-boring flagging of access to Solaris "listen" - service as "hot" (Vern Paxson). - -- Removal of libedit, since libreadline provides similar functionality - (Christian Kreibich). - -- Added scripts missing from distribution: dce.bro, ncp.bro, and smb.bro - (Vern Paxson). - -- ssh.bro now exports ssh_ports (Seth Hall) - -- A number of improvements to inter-Bro communication (Robin Sommer). - - (1) Remote communication now no longer includes location information for - serialized objects; that removes quite a bit of redundacy from the network - traffic. - - (2) The new option 'remote_check_sync_consistency" disables the cross-check - on the receiving side of &synchronized state of whether the current value - of a variable has the value expected by the sender. Transmitting the - original values in addition to the updates generates quite a bit CPU & - network load in some cases (in particular, a table of tables). The default - for remote_check_sync_consistency is off, and so far that in particular - seems to reduce the proxy's load quite a bit. - - (3) Complete overhaul of the internal caching of serialized objects. The - objective of the caching is avoid retransmitting already sent values over - and over again. It turns out, however, that some objects are very stable - and hardly change or get replaced (e.g., Bro types); while other change - all the time and are hardly reused some time later (e.g., Vals). Now - we maintain *two* caches independently for these types of objects; one - with a low turn-over one and another with a high one. This should reduce - CPU load on both sender and receiver sides. - - The new scheme is only used if both communicating Bros support it; with - older Bros, as well as with Broccoli, we continue using the old scheme. - -- Some reworking of remote printing (Robin Sommer), as follows. Bro now - uses a new interprocess message rather than print_hook events, to better - manage buffering and associated load (these can produce failures depending - on system configuration; see remote.log). A number of timeouts and - buffer sizes have been tuned. Internally, EINTR errors are now treated - separately from EAGAIN. Finally, even with remote_check_sync_consistency=F, - one type of consistency check was still being done; this is no longer - the case. - -- The DNS analyzer now generates events (dns_query_reply/dns_rejected) - for replies with zero questions (Robin Sommer). - -- Perftools support for incompatible changes in the 1.0 API (Robin Sommer). - -- Rearranged (generally reducing, though not always) some state timeouts - associated with scan detection (Robin Sommer). In addition, when a - scanning address crosses ignore_scanners_threshold (meaning that it will - be ignored from now on anyway), it gets discarded from all state-tracking - tables. Finally, the ignore_scanners_threshold now applies all kinds - of scans, not just address scans. - -- Substantial Broccoli updates, including a new initialization requirement - that breaks backward compatibility, support for enqueueing serialized - event data for transmission, and OpenSSL threadsafe initialization. - See aux/broccoli/ChangeLog for details (Christian Kreibich, Robin - Sommer, and Matthias Vallentin). - -- Broccoli hashtable optimisation. See aux/broccoli/ChangeLog for - details (Christian Kreibich & Matthias Vallentin). - -- Broccoli memory leak fixed, see aux/broccoli/ChangeLog for details - (Christian Kreibich). - -- Broccoli: updates to bropipe tool (Steve Chan and Robin Sommer). - -- Bug fixes for Broccoli Python bindings (Robin Sommer and Matthias Vallentin). - -- Fixed nasty bug due to module scoping that completely kept stepping-stone - detection from working (Vern Paxson). - -- A serious bug in the packet sorter has been fixed (Robin Sommer). - -- Bug fix for extra NULs getting embedded in escaped strings (Seth Hall). - -- Bug fix for HTTP messages that use "Connection: close" rather than length - headers, which yielded erroneous reassembled messages with \r\n's when - only \n's were present (Bernhard Ager). - -- Fix for reporting on ICMP flows that are expired from the flow table - (Vern Paxson). Previously there was a race condition if the flow - was flushed prior to its summary timer expiring. - -- The -l option (list the scripts that Bro loads) now correctly prints - scripts loaded by the prefix mechanism, and uses indentation to indicate - the load hierarchy (Robin Sommer). - -- A bug has been fixed (really, worked around) in drop.bro that prevented - dropped addresses from being properly restored (Robin Sommer). - -- Fixes for deadlocking problems in the Broccoli protocol. See - aux/broccoli/ChangeLog for details (Christian Kreibich & Robin Sommer). - -- Bug fix for DNS analyzer on 64-bit machines (Gregor Maier). - -- Bug fix for asynchronous DNS lookups to prevent some successful lookups - being reported as timed out (Robin Sommer). - -- Bug fix for tracking line numbers associated with compound statements - (Po-Ching Lin). - -- Fix for a rare condition in which the main Bro process couldn't kill - its child process (Robin Sommer). - -- Fix for file rotation when the underlying file is deleted before the - timer expires (Robin Sommer). - -- Fix for potential crash when communication connections break down, - and also for releasing cached objects (Robin Sommer). - -- Fix for default table entries computed by function invocation to not - cache previous results (Robin Sommer). - -- Fix for Bro's internal DNS resolution (Scott Campbell and Robin Sommer). - -- Portability fix for DAG packet capture (Gregor Maier). - -- Portability fix for --enable-brov6 (Robin Sommer). - -- Portability fixes for FreeBSD (Vern Paxson). - -- A work around for new_packet() crashing on IPv6 packets (Vern Paxson). - For now, IPv6 packets are skipped. Also, for fragments the event handler - is now only called for the fully reassembled packet. - -- The new configuration option --disable-nbdns supports disabling non-blocking - DNS at configure time (Sean McCreary). Note, there are some known problems - with it in some environments. - -- A number of configuration fixes and enhancements (Christian Kreibich - and Robin Sommer). - -- Consistency nit for the configuration process (Seth Hall). - -- A number of reference-counting and other memory management fixes - (Robin Sommer). - -- Bug fix for inter-Bro communication lockup (Seth Hall and Robin Sommer). - -- Bug fix for computing TCP payload length in new_packet event (Lothar Braun). - -- Bug fix for sending boolean True values via Broccoli (Seth Hall). - -- make distcheck fix to clean up .bif.bro files (Christian Kreibich). - -- Bug fix for DPD's recognition of SSLv2 connections (Seth Hall). - -- Bug fix for &default for tables indexed by subnets (Seth Hall). - -- A bug has been fixed that could crash Bro when you called get_event_peer() - after a remote connection had already disppeared (Robin Sommer). - -- Introduced a work-around for crashes that occur when Bro exits - due to handling a signal (Robin Sommer). - -- Bug fix for checkpoint.bro - don't schedule timers for times that - aren't actually in the future (Robin Sommer). - -- Hostname formatting fix for anon.bro (Fabian Schneider). - -- Bug fix for redundant .log extension in Time Machine log file - (reported by CS Lee). - -- Removed now-outdated special-casing of Linux reporting of packet filter - statistics (Peter Wurzinger and Robin Sommer). - -- A number of memory leaks fixed (Robin Sommer). - -- Addressed warnings from newer versions of g++ (Robin Sommer and Vern Paxson). - -- Fixed an invocation issue in the ca-create script that prevented it from - working with recent OpenSSL versions (Craig Leres & Christian Kreibich). - -- Comment fixed in drop-adapt (Justin Azoff). - -- Duplicate code removed from Val (Seth Hall). - - -1.4 Fri Oct 17 11:08:52 PDT 2008 - -- We are no longer supporting a previous Bro release as the "stable" - version. Rather, the model now is that the current public release will - aim for increasing stability (occasionally updated with fixes), and those - who wish to use a "bleeding-edge" snapshot can do so via access to the - public SVN source code repository, as explained at - - http://bro-ids.org/wiki/index.php/Subversion#Public_Access - - Note that all previous releases remain available from the download page; - what is changing is that we no longer commit to support for the most - recent of these. - -- We have clarified the copyright statement that covers most of the - code to remove the "advertising clause" that derived from older - BSD licenses, and we have removed copyright wording from most source - code files. See COPYING for the current wording and a list of - files that retain their own copyright notices. - -- Bro now supports analyzing NetFlow v5 data, i.e., from Cisco routers - (Bernhard Ager). NetFlow can be useful for intrusion detection as it - allows analysis of traffic from many different points in the network. - Bro can now read NetFlow data from a UDP socket, as well as (mostly - for debugging purposes) from a file in a specialized format. You can - create these files with the programs given in aux/nftools. - - Command line switches: - - -Y|--netflow :[=] | read flow from socket - - This is the usual way of getting NetFlow data into Bro by - opening a UDP socket on : and reading all incoming - packets. Setting the to 0.0.0.0 should work on most - platforms. Optionally you may set an identifier for the - source - useful if there are many different sources you want - to analyze in parallel. This might also be necessary if you - want to use this feature with a clustered Bro. - - Examples: - bro -Y 0.0.0.0:5555 netflow - bro -i eth0 -Y 10.0.0.1:1234=src1 brolite netflow - - -y|--flowfile [=] - - Used to read from a file. You can optionally include an - identifier for the source. - - Examples: - bro -y myflowfile netflow - bro -y myflowfile=src1 otherflowfile=src2 netflow - - Netflow Events: - - event netflow_v5_header(h: nf_v5_header) - - Generated upon reading a new NetFlow PDU, as summarized in the - argument. The field h_id gives the flow source identifier and - a serial number. You can use this field to associate subsequent - netflow_v5_record events with their header. - - event netflow_v5_record (r: nf_v5_record) - - Every record within a NFv5 PDU generates a corresponding - netflow_v5_record() event. The relatively complex timestamp - format of NFv5 is already converted to Bro's time type, and - the TCP header flags are separated into bools. - - The distribution includes an example analysis script, netflow.bro. - It simply dumps received NetFlow records. If netflow_restitch is T - (the default), then Bro performs flow restitching as well, and two - script variables become relevant: - - global netflow_finished_conn_expire = 310 sec &redef; - - specifies how long to wait for additional flow records after - a RST or FIN for - - const netflow_table_expire = 31 min; - - Its setting only affects table declarations, and therefore - cannot be usefully redef'd. - - Auxiliary programs: - - Bro uses a custom format for flow data stored in files, - to enable preserving timestamps of the PDU arrivals and the - exporter's IP address. The tools nfcollector and ftwire2bro - in aux/nftools/ provide ways to manipulate the Bro NF file - format. The first dumps NetFlow data from a UDP socket to - stdout or to a file in Bro format. The second converts NetFlow - data in "wire" format to Bro format, and, while doing so, - fakes up the exporter's IP address and timestamp. You can get - "wire" format from normal flow-tools files, e.g., by using - 'flow-export -f 4'. Please note that the Bro format is just - a hack to allow for easier debugging. Therefore the format - is not in fact platform independent, and not suitable for data - storage. - -- A new DHCP analyzer generates the following events (Po-Ching Lin): - - event dhcp_discover(c: connection, msg: dhcp_msg, req_addr: addr) - event dhcp_offer(c: connection, msg: dhcp_msg, mask: addr, - event dhcp_request(c: connection, msg: dhcp_msg, - event dhcp_decline(c: connection, msg: dhcp_msg) - event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, - event dhcp_nak(c: connection, msg: dhcp_msg) - event dhcp_release(c: connection, msg: dhcp_msg) - event dhcp_inform(c: connection, msg: dhcp_msg) - - where dhcp_msg values look like: - - type dhcp_msg: record { - op: count; # 1 = BOOTREQUEST, 2 = BOOTREPLY - m_type: count; # the type of DHCP message - xid: count; # transaction ID of a DHCP session - h_addr: string; # hardware address of the client - ciaddr: addr; # original IP address of the client - yiaddr: addr; # IP address assigned to the client - }; - - See dhcp.bro for the corresponding analysis script (which could - probably use some refinements). - - Note, this analyzer is implemented using BinPAC, so you will need - to specify --use-binpac to activate it. - -- A BitTorrent analyzer is now available (Nadi Sarrar). See the policy - scripts bittorrent.bro and bt-tracker.bro for the events generated for - analyzing transfers and tracker dialogs, respectively. - -- The "Bro Lite" configuration is now deprecated and will not in - general be supported (Robin Sommer & Vern Paxson). - -- "make install" now only installs a core set of files (Robin Sommer). - Policy files are now installed in /share/bro/* (or whatever - configure determines $datadir to be), which is now in Bro's default - search path. It creates a directory /share/bro/site for local - policy files, and the default BROPATH is extended to include this. The - default path no longer includes policy/local. You can install the - additional files used by the (now deprecated) "Bro Lite" configuration - using "make install-brolite". - -- Substantial updates to Broccoli, including support for container - types (tables and sets) as well as a new metadata structure for event - callbacks, facilitating truly generic event handler implementations - (Christian Kreibich, Seth Hall and Robin Sommer). See aux/broccoli/ChangeLog - for details. - -- Extensive changes to allow Bro to process packets captured in the - past intermingled with those captured in real-time (Matthias Vallentin - and Robin Sommer). This operation reflects combining Bro with use of - "Time Machine" functionality for packet capture. - -- We have unfortunately had to disable support for configuring Bro - to use ClamAV, since it turns out that the key interface we need - for processing blocks of memory directly rather than whole files - is no longer supported by the package, and in fact was buggy even - when it was (Robin Sommer). - -- The new signature option "http-body //" matches - on the body data of HTTP entities (Robin Sommer). The matching is - done after decompressing the body, if necessary. - -- The new built-in function identify_data(data: string, return_mime: bool) - analyzes the string "data" and returns its type according to libmagic, - if installed (Seth Hall). The second argument controls whether it should - be returned as a MIME-type or just an identifying string. For example, - identify_data("MZpofigu", F) returns the string "MS-DOS executable", and - print identify_data("MZpofigu", T) returns "application/x-dosexec". - -- The new analysis script http-identified-files.bro identifies the - type of items returned by Web servers using libMagic (if available) - and generates notices for interesting types and mismatches between - URLs and types (Seth Hall). - - You configure it using two variables. watched_mime_types is a pattern - (default /application\/x-dosexec/ | /application\/x-executable/ ) for - which any MIME type matching the pattern generates a HTTP_WatchedMIMEType - notice. - - mime_types_extensions is a table mapping strings to patterns specifying - how URLs for the given MIME type should appear. (Ideally, this would - be a table mapping patterns to patterns, but Bro doesn't currently support - that.) It defaults to: - - ["application/x-dosexec"] = /\.([eE][xX][eE]|[dD][lL][lL])/ - - i.e., do Windows executables end in .exe or .dll. - - You can also redef the pattern ignored_urls to specify URLs that should - not generate complaints. It defaults to matching Windows Update. - -- The new script http-extract-items.bro extracts the items from HTTP - traffic into individual files (Vern Paxson). Files are named: - - .._._. - - where is a redef'able prefix (default: "http-item"), is a - number uniquely identifying the item, the next four are describe the - connection tuple, and is "orig" if the item was transferred - from the originator to the responder, "resp" otherwise. - -- The workings of how Bro interfaces to external programs for dropping/ - restoring connectivity of misbehaving hosts has been significantly - reworked (Brian Tierney and Robin Sommer). - - First, dropping decisions used to be made directly by analyzer scripts, - such as scan.bro directly calling drop_address(). Now instead the - scripts generate Notices and then the notice policy can have an - action of NOTICE_DROP to codify that the response to the given Notice - is to drop the source. The new notice_action_filter of drop_source - drops the source of notices, and drop_source_and_terminate both - drops the source and terminates the corresponding connection. - - So, to drop all sources triggering a specific notice, one can now, e.g., - write: - - redef notice_action_filters += { [Hot::SSH_Overflow] = drop_source }; - - Related to this change, notice_info has a new field $dropped, set to - true if the Notice triggered a (successful) drop. - - Second, by redef'ing Drop::use_catch_release to T (default F) you can - activate "catch-and-release" logic. You use this mode when you need to - manage a limited number of possible blocks, or to build in automatic - "forgiveness" in situations where blocked sources might become benign - (such as due to dynamic IP addresses). If a source has been idle for - Drop::drop_time, then it is unblocked. However, if it is again seen as - block-worthy, then it is blocked for an interval of Drop::long_drop_time. - - Third, ICMP scanning is now reported by its own notice, ICMPAddressScan, - rather than Scan::AddressScan. - -- Google's perftools have replaced mpatrol for leak-checking and - heap-profiling (Robin Sommer). If Bro is compiled with --enable-perftools - and configure finds the perftools, there are two command-line options - available: - - -m turns on leak checking of the main packet loop, with some - uninteresting leaks are suppressed. Currently, with one - exception (the RPC analyzer; problem not yet found), it reports - no leaks when running the test suite. - - -M turns on heap profiling: Bro will take a snapshot of the heap - before starting the main packet loop and another one when - finished. These snapshots can then be analyzed with pprof. - - For more information about the perftools see - - http://code.google.com/p/google-perftools - -- Notice tags are now generated in a pseudo-unique fashion that, with high - probability, ensures that tags generated by separate Bro processes don't - clash when logged to a common location, such as for a Bro cluster (Robin - Sommer). Tags are now string's rather than count's, and are associated - with all notices, not just that are connection-related. You can however - redef the string notice_tag_prefix or the function new_notice_tag to - further control how such tags are generated. - -- Four new built-ins for type conversion (Robin Sommer): - - function double_to_interval(d: double): interval - function addr_to_count(a: addr): count - function port_to_count(p: port): count - function count_to_port(c: count, t: transport_proto): port - -- Many policy scripts have been modified to use modules & scoping - (Robin Sommer and Matthias Vallentin), which may require updates to - existing scripts/refinements. - -- The new script variable dpd_conn_logs (default F), if true, changes the - semantics of the service field in connection logs written to conn.log, - as follows (Robin Sommer). It becomes a comma-separated list of analyzers - confirmed by DPD to parse the connection's payload. If no analyzer could - confirm its protocol, but the connection uses a well-known port, the - service is the name of the port with "?" appended (e.g., "http?"), as - long as the corresponding analyzer has not declined the connection. - In addition, ftp-data sessions are labeled "ftp-data" and portmapper - connections are labeled with the specific method-call (just as before). - - dpd_conn_logs defaults to F because the change in semantics may break - scripts that parse conn.logs; but it will likely change to the default - in the future. With dpd_conn_logs turned off, conn logs are generated - as they used to be, with a few rare exceptions (with previous versions, - the service field was sometimes determined while the connection was still - alive; now it's always determined at the time when the conn.log entry - is written out). - -- The SSL analyzer has been rewritten using BinPAC, with a number of - robustness improvements (Tobias Kiesling). It currently is only used - if you execute with --use-binpac. - -- Python bindings for Broccoli are now available in - aux/broccoli/bindings/python/ (Robin Sommer). See README/README.html - in that director for details. - -- The new "auth" option in remote.bro indicates whether a given side is - considered "authoritative" for shared state, in which case it sends its - initial state to &sync'ed peers (Robin Sommer). When two peers synchronize - their state, one side sends its current set of state to the other as - soon as the remote connection is established. The one sending the state - used to be the one who has been running longer; now it can also be - explicitly set via the "auth" flag in the Remote::Destination. - -- Two new tuning parameters for scan.bro (Robin Sommer): - - ignore_scanners_threshold (default 0): - - If a host has scanned more than this many hosts, it is completely - excluded from further scan detection. 0 disables. - - addr_scan_trigger (default 0): - - A host is only tracked for address scanning once it has contacted - this many different hosts. Primarily intended for using a two-stage - scan detection with a Bro cluster: first, each node searches locally - for scanners by looking for hosts contacting more than - addr_scan_trigger destinations. Those hosts which do are then - globally tracked throughout the cluster by &synchronizing the scan - detector tables. - -- When Bro serializes functions, it now does so by default using only - their name, rather than their full value (Robin Sommer). This prevents - propagation of expiration functions associated with tables and sets. - Note, currently there is no mechanism provided to switch from the - default behavior, but the internal hooks are in place to do so. - -- The new built-in variable trace_output_file gives the name of the -w - output trace file (Robin Sommer). - -- Bro no longer installs new file rotation timers when shutting down - (Robin Sommer). - -- The new policy scripts remote-print-id{,-reply}.bro support convenient - access to printing the identifiers of a remote Bro (Robin Sommer). - You use the script remote-print-id.bro to request and receive the - printing; the remote Bro must have loaded remote-print-id-reply.bro - in order to process the request. - - Example use: - - bro -e 'redef PrintID::dst="" PrintID::id=""' - remote-print-id - -- scan.bro has been heavily modified to better support distributed scan - analysis (Matthias Vallentin and Robin Sommer). - -- The check for unused event handlers is now turned off by default - (Robin Sommer). To enable, use "redef check_for_unused_event_handlers = T". - -- The new script drop.bro has been split off from scan.bro to isolate - the logic concerning dropping addresses to block scans (Robin Sommer). - -- The new -l flag lists each script as it is loaded (Robin Sommer). - -- Textual descriptions of identifiers now include their attributes - (Robin Sommer). - -- The new predefined function prefixed_id() returns a session identifier with - its peer-ID prepended if it's associated with a remote Bro (Robin Sommer). - This is now used when generating writing log files. - -- remote.bro now assigns a priority of -10 to its bro_init() event handler - to allow others a chance to modify destinations (Robin Sommer). - -- A large number of BinPAC updates (Ruoming Pang and Robin Sommer). - -- The new built-in type_name(v): string returns the name of the type - of the value v (Vern Paxson). For example, "typename(5.2)" returns - "double". This function is mainly for internal debugging (i.e., - finding mismatches between values generated by the event engine - versus how their type is expected by the script layer). - -- The new built-in str_shell_escape() does some basic escaping on strings - that will be passed to system() (Christian Kreibich). Note, this function - isn't ready (robust enough) for routine use, however. - -- The new built-in disable_print_hook(file) acts the same as - the attribute &disable_print_hook (Robin Sommer). - -- The new script terminate-connection.bro factors out the terminate_connection() - functionality that used to be in conn.bro (Robin Sommer). - -- The new attribute &group= can be associated with event handlers - to group them together into a set that can be manipulated as a whole - (Robin Sommer). is a string reflecting the name given to the group. - - The built-in enable_event_group(group: string) turns on all the analyzers - in a given group, and disable_event_group(group: string) deactivates them. - -- The new attribute &raw_output applies to variables of type file, disabling - escaping of non-printable characters (Seth Hall). - -- You can now iterate over the characters in a string value using - a "for" loop, e.g., "for ( c in str ) ..." (Robin Sommer). - -- The new built-in - - function cat_sep%(sep: string, def: string, ...%): string - - works similarly to cat(), except that it (a) separates the values - by "sep" and (b) substitutes "def" for empty strings (Seth Hall). - -- The function string_escape() now takes a string of characters to escape - rather than a single character (Robin Sommer). Each character in the - string is preceded by '\' in the return value (also any embedded '\'s, - as before). - -- The new built-in function global_ids() returns a table of all global - identifiers along with associated information (Robin Sommer). The - return value has type table[string] of script_id, indexed by the name - of the identifier and yielding records with the following fields: - - type script_id: record { - type_name: string; - exported: bool; - constant: bool; - enum_constant: bool; - redefinable: bool; - value: any &optional; - }; - -- The new script function find_last(str: string, re: pattern) returns - the last occurrence of the given pattern in the given string, or - an empty string if no match (Robin Sommer). Note that this function - returns the match that starts at the largest index in the string, which - is not necessarily the longest match. For example, a pattern of /.*/ - will return just the final character in the string. - -- The new script variable record_all_packets, if redef'd to T (default F), - instructs Bro to record every packet it processes (Robin Sommer). - Prior to introducing this variable, Bro applied a few heuristics to - reduce recording volume. Setting this variable also causes packets - to be recorded very early in processing, which can be helpful for - debugging crashes. - -- If the new script flag ssl_log_ciphers is set to T (default), ssl.bro - logs the ciphers seen (Robin Sommer). - -- Much more expanded Time Machine support, now located in - policy/time-machine/ (Robin Sommer), - -- The new command line option --status-file (alias -U) specifies - the name of a file into which Bro will write an indicator of its current - processing status (Robin Sommer). Possible values include "INITIALIZING", - "RUNNING", "TERMINATING", "TERMINATED". - -- The new policy script targeted-scan.bro looks for repeated access from - the same source to the same server, to detect things like SSH - password-guessing attacks (Jim Mellander). - -- The "alternative" style for printing strings (i.e., a fmt() argument - of "%As") now renders the raw string, other than escape-expanding - embedded NULs (Vern Paxson). This change may be temporary, pending - development of more fine-grained control over string rendering. - -- For now we have removed the %S functionality for fmt() (Robin Sommer). - %S was meant to print "raw" strings, but later processing of such - printing still introduces artifacts. - -- GeoIP information now includes latitude and longitude (Seth Hall). - -- ssh.bro now supports the variable skip_processing_after_handshake - which directs the event engine to omit any further processing of an - SSH connection after its initial handshake (Seth Hall and Robin Sommer). - This can help with performance for large file transfers but precludes - some kinds of analyses (e.g., tracking connection size). This change - also adds a scope of "SSH". - -- Email notification of notices now allows for separate destinations - depending on notice type (in particular, a regular mail destination - versus a pager destination), and also escapes the notice to prevent - injection attacks (Seth Hall and Robin Sommer). - -- The new policy script conn-flood.bro is a simple connection-flooding - detector, mainly meant as a demonstration (Robin Sommer). - -- A large number of additions to the TLS/SSL known-ciphers suite (Seth Hall). - -- Serialization now uses 64-bit IDs to cache items rather than 32-bit, - for robustness during long-running execution (Robin Sommer). - -- The new script variable tcp_max_initial_window specifies, for flows - for which ACKs have never been seen, the maximum volume of initial - data after which Bro will assume that it is seeing only one side - of the connection and will not buffer data for consistency checking - awaiting the later arrival of ACKs (Robin Sommer). It defaults to 4 KB. - (Note, this used to be an internal value, so the behavior is not new.) - Set to 0 to turn off this functionality and have Bro attempt to - track all such flows. - -- The new script variable tcp_max_above_hole_without_any_acks specifies, - for flows for which ACKs have never been seen, the maximum volume of - data above a sequence hole that Bro will tolerate for a connection - before giving up on tracking the flow (Robin Sommer). It defaults to 4 KB. - (Note, this differs from tcp_max_initial_window in that this threshold - applies to sequence holes rather than the beginning of flows. Like - tcp_max_initial_window this used to be an internal value.) Set to 0 to - turn off this functionality. - -- The new script variable tcp_excessive_data_without_further_acks specifies - a threshold similar to tcp_max_above_hole_without_any_acks, but for - flows for which Bro has seen ACKs (Robin Sommer). It defaults to 10 MB. - Set to 0 to turn off the functionality. - -- Equal signs ("=") in text for notices are now escaped when using the - tagged format to keep them unambiguous from the "=" delimiters - (Robin Sommer). - -- The final tallies for notices are now processed as NoticeTally - NOTICE's rather than directly alarm'd (Robin Sommer). - -- WeirdActivity notices now include an associated connection when appropriate - (Robin Sommer). - -- Support for large (> 2^32 bytes) pcap trace files (Po-Ching Lin). - -- Scoped names ("...::...") are now allowed in signature "eval" - constructs (Christian Kreibich). - -- scan.bro is now decoupled from conn.bro, i.e., you can @load the - latter without getting the former (Vern Paxson). As part of this - change, the logic to invoke TRW is now in scan.bro. - -- weird.bro has been updated with a number of missing Weird's (Vern Paxson). - -- If when using inter-Bro communication the child Bro process terminates, - it now also terminates the parent process (Robin Sommer). - -- BinPAC analyzers now interoperate with DPD (Robin Sommer). - -- Some http.bro processing options are now exported so they can be - accessed in other scripts (Robin Sommer). - -- SMTP analysis now applies to port 587/tcp as well as 25/tcp (Robin Sommer). - -- $conn is now set in ServerFound notices (Robin Sommer). - -- You can now create empty sets and tables using set() and table(), - i.e., the usual set/table constructors with no arguments (Vern Paxson). - By themselves, these have an unspecified type - you can't use them - directly other than to assign them. For example, - - local bad_guys: set[addr]; - ... - bad_guys = set(); # start over assuming no bad guys - -- A number of scripts have been (slightly) simplified to use the - new empty set()/table() constructors (Vern Paxson). Note that - these still aren't usable for field assignments in record constructors, - nor for attributes like &default = ... - -- Removed unused syntax for declaring sets based on a list of initial - values (Vern Paxson). - -- set() and table() can now be used as arguments to function calls - (Vern Paxson). - -- The vestigial &match attribute has been removed. - -- POP3 is now recognized using Dynamic Protocol Detection (Seth Hall). - -- The new event expected_connection_seen(c: connection, a: AnalyzerTag) - is generated whenever a connection is seen for which we have previously - scheduled an analyzer via expect_connection() (Robin Sommer). - -- The new built-in capture_state_updates logs all changes applied to - &synchronized variables, in a fashion similar to the capture_events() - built-in (Robin Sommer). An accompanying policy script, - capture-state-updates.bro, turns this on to the file state-updates.bst. - -- If the new script variable suppress_local_output is set (default: F), - Bro suppresses printing to local files if there's a receiver for - print_hook events (Robin Sommer). This option is however ignored - for files with a &disable_print_hook attribute. - -- The new notice action filter function file_if_remote specifies - that notices from sent from remote source addresses should - have an action NOTICE_FILE (Robin Sommer). - -- The new notice action filter function file_local_bro_notices specifies - that notices generated by the local Bro instance (as opposed to a - remote peer) should have an action NOTICE_FILE (Robin Sommer). - -- An arbitrary tag can now be past to post-processors for log rotation - (Robin Sommer). - -- Default inactivity timeouts for interactive services shortened to - 1 hour (Robin Sommer). - -- The scanning variables distinct_{peers,ports,low_ports} are now - redef'able (Robin Sommer). - -- The new -S (--summary-only) option for site-report.pl directs to - only generate connection summaries (Brian Tierney) - -- More useful default config file for edit-brorule.pl (Brian Tierney). - -- Bro now includes a test suite in testing/istate/ for its "independent - state" functionality (Robin Sommer). - -- Support for parallel builds via make -j (Christian Kreibich). - -- Bro's default search path now includes includes policy/sigs/ and - policy/time-machine/ (Robin Sommer). - -- Bro's internal processing of interprocess communication has been - significantly overhauled to prevent potentially fatal race conditions - (Robin Sommer). - -- Bro now checks calls to fmt() at compile-time to ensure that the - correct number of arguments are present (Vern Paxson). This is useful - in addition to Bro's run-time checking for arguments matching their - corresponding format-specifiers in the case of rarely-executed statements - that might not generate such run-time checks in routine testing. - -- The ports associated with Telnet and Rlogin are now redef'able (Robin Sommer). - -- MIME processing now removes leading whitespace from MIME headers - (Sanmeet Bhatia and Robin Sommer). - -- TCP "weird" events reported by the connection compressor now match - (other than a few rare corner-cases) those produced for normal TCP - processing (rmkml and Robin Sommer). - -- Added Scan::suppress_UDP_scan_checks to control false positives - on scan detection in environments with P2P protocols that use UDP - (Vern Paxson). - -- The internal analyzer interface now includes an EndOfData() method that - analyzers can use to report that all of a message has been delivered - (Robin Sommer). - -- Fix for a significant memory leak in processing UDP when using -w - (Robin Sommer). Note: this change turns off by default trace rewriting - for generic UDP traffic. - -- Two serious regular expression bugs fixed (Vern Paxson). In the - first, searching for a regular expression inside a string would - fail if the pattern occurred only after an embedded newline. In - the second, insufficient buffer was allocated when compiling regular - expressions, leading to memory corruption. - -- Base64 decoding bug fixes (Christian Kreibich and Ruoming Pang). - -- Automatic rotation of files is now disabled for contents files written - by the TCP reassembler, which otherwise leads to mangled files - (Robin Sommer). - -- Bro now ships with an updated version of libpcap (0.9.8), which hopefully - fixes problems managing trace files > 4 GB in size. - -- Significant bug fixes for gzip- and deflate-encoded Web items (Robin Sommer). - -- Bug fix for secondary-filter.bro (Vern Paxson). - -- Removed a naming ambiguity regarding TCP states (Vern Paxson). - -- Bug fix for signature scanner not matching all of its input (Vern Paxson). - -- Bug fix for using port values in signatures (Robin Sommer). - -- Minor policy script tweaks: state management for weird's, processing - of Notice tags associated with connections, and dependencies for - irc-bot.bro (Robin Sommer). - -- aux/ portability fixes (Vern Paxson). - -- Workarounds added for a BinPAC deficiency, which is that code in %cleanup - clauses can also be executed during recovery from exceptions when parsing - new data. This means that any delete's or Unref()'s need to also set the - corresponding pointer to nil (Vern Paxson). - -- Bug fix for crashes with the non-BinPAC SSL analyzer (Robin Sommer). - -- Tweak to peer-status.bro since Bro now requires events to be - declared prior to reference in a "schedule" statement (Robin Sommer). - -- The signature keyword "enable" now optionally accepts the syntax - "foo:bar" to specify "activate analyzer bar as a child of analyzer foo" - (Robin Sommer). This is used for example for an XML-over-HTTP analyzer - that's in the works. - -- irc-bot-syslog.bro now uses open_log_file() for its log file (including - the logging suffix) rather than a direct open (Vern Paxson). - -- Bug fix for tracking Blaster across a Bro Cluster (Robin Sommer). - -- Bug fix for the HTTP BinPAC analyzer chopping the trailing character - off of HTTP headers when generating the http_all_headers event (Gregor Maier). - -- Bug fix for HTTP chunked items for which the chunk size line was terminated - by CRLF but the CR and LF came in separate packets (Gregor Maier). - -- A bug has been fixed that would cause partial lines (for line-oriented - protocols) to fail to be processed when a connection terminated - (Robin Sommer). - -- Bro no longer treats a signal arriving before a previous signal has - been processed as fatal, nor does it attempt processing of a termination - signal if seemingly there are no race conditions to worry about - (Robin Sommer). Both of these changes are an attempt to improve - Bro's robustness. - -- Fix for attributes such as &encrypt not working in initial declarations - but only in later redef's (Seth Hall and Robin Sommer). - -- Fixes for memory leaks in SSL processing (Seth Hall and Robin Sommer). - -- Fix for POP3 analyzer to not treat lines like "." as message - terminators (Robin Sommer). - -- Bug fix for crashes arising from nil pointers in list expressions - (Seth Hall and Robin Sommer). - -- Bug fix: a signature's "enable" would activate the corresponding analyzer - even if no event handlers were defined for it (Robin Sommer). - -- Bug fixes to prevent crashes when mixing set_contents_file() with - subsequent explicit close(), and to ensure all data written to - file upon connection tear-down (Gert Doering and Robin Sommer). - -- Configuration support for MacPorts and Fink package management systems - (Christian Kreibich & Vern Paxson). - -- Communication-only Bro's now send out email alarms (Robin Sommer). - -- Writes to a file that fail due are now run-time errors rather than - fatal internal errors, since often these occur due to the disk - being full (Robin Sommer). - -- Byte-order bug fix for lookup_location() (Robin Sommer). - -- BinPAC portability fix for 64-bit machines (Bernhard Ager and Robin Sommer). - -- Portability fixes for newer versions of gcc (Jan Gerrit Goebel and - Robin Sommer). - -- Some support for porting to Solaris (Stephan Toggweiler). - -- Connection compressor bug fix for source and destination having the - same IP address, such as when monitoring loopback (Robin Sommer). - -- Connection compressor bug fix for connections with multiple SYNs - (Robin Sommer). - -- Bug fix for using already-declared local variables for looping - over vectors in a "for" loop (Robin Sommer & Vern Paxson). - -- Bug fix for not processing truncated UDP packets (Tom Kho and Robin Sommer). - -- Bounds-check added to BinPAC-generated code (Tom Kho and Robin Sommer). - -- Bug fix for checking whether an IPv6 address is part of a subnet - (Seth Hall). - -- Bug fixes for crashes relating to asynchronous DNS lookups performed - at start-up (Robin Sommer). These changes also lowered the timeout - before assuming failure from 20 seconds down to 5 seconds. - -- Portability and const-ness fixes (Kevin Lo and Robin Sommer). - -- Suppression of some content-gap complaints when running on traces - that have been filtered down to only TCP control packets (Robin Sommer). - -- Removed unnecessary dependency in notice-action-filters.bro - that led to errors when loading icmp.bro by itself (Vern Paxson). - -- Bug fix for potential infinite loop in client communiation (Robin Sommer). - -- Bug fix in reference counting that could eventually lead to roll-over - (Robin Sommer). - -- Bug fix in communication initialization (Robin Sommer). - -- Internal documentation fix: timers are specified using absolute time, - not relative (Robin Sommer). - -- Performance improvement for built-in find_all() function when running - on large strings (Robin Sommer). - -- Memory leak fixes (Robin Sommer, Bernhard Ager, Christian Kreibich). - -- Bug fix for error recovery when encountering an unknown link layer - (Bernhard Ager). - -- Bug fix for reversing client & server in a connection (Po-Ching Lin). - -- Bug fix for packet_contents when capture length exceeds the IP payload - length due to Ethernet frame padding (Christian Kreibich). - -- Bug fix for tcp_packet event erroneously including Ethernet padding - in its contents (Vern Paxson). - -- Bug fix for lookup_connection built-in (Seth Hall). - -- Portability nit for libedit tarball (Vern Paxson). - -- Broccoli portability fix for NetBSD (Christoph Leuzinger). - -- Type-checking for script-level event invocation was completedly broken - - now fixed (Vern Paxson). - -- Portability fixes for different versions of g++/STL (Nicholas Weaver - and Vern Paxson). - -- Fix for dynamic detection of SSL via DPD (Robin Sommer). - -- IPv6 portability fix for BinPAC-based DNS analyzer (Vern Paxson). - Note, more portability work is needed for it. - -- Bug fix for bifcl error messages (Vern Paxson). - -- Minor bug fix for remote communication, plus some improved communication - logging (Robin Sommer). - -- Bug fix for &printhook (Robin Sommer). - -- Bug fix for error message output (Robin Sommer). - -- Bug fix for termination cleanup (Robin Sommer). - -- Bug fix for some Rlogin corner cases (Robin Sommer & Vern Paxson). - -- Bug fix for bifcl generation of "interval" types (Vern Paxson). - -- Bug fix for getting connection memory statistics when Bro is - exiting (Robin Sommer). - -- Config fix: --enable-debug now turns off -O2 for gcc (Robin Sommer). - -- Bug fixes for "heavy" analysis (Vern Paxson). - -- Broccoli bug fixes for types net and port (Robin Sommer). - -- Bug fixes for Telnet environment options (Robin Sommer). - -- Bug fix for accessing remote peer description (Robin Sommer). - -- A fix for the connection compressor generating new_connection too - late (Robin Sommer). - -- Fixes for DAG support, including configuration and multiple - interfaces (Robin Sommer). - -- Bug fix for serializing time-stamps of table entries (Robin Sommer). - -- Bug fix for dealing with peer IDs for remote communication (Robin Sommer). - -- Bug fix to avoid installing timers when timers have already - been canceled (Robin Sommer). - -- Bug fix for interplay between serializing connections and - connection compressor (Robin Sommer). - -- Memory leak fix for enum's (Robin Sommer). - -- Bug fix for files being closed prior to bro_done() (Vern Paxson). - -- aux/broccoli/contrib was not included in distribution (Robin Sommer). - -- Auto-configuration bug fix for BinPAC (Craig Leres). - -- Bug fix for dynamic protocol detection (Robin Sommer). - -- A number of configuration fixes for installation and portability - (Christian Kreibich, Brian Tierney, Robin Sommer, Dan Kopecek). - - -1.3 Mon Jul 16 22:11:00 PDT 2007 - -- The Bro manual has been wikified at: - - http://www.bro-ids.org/wiki/index.php/User_Manual - - and this is the format in which it will evolve in the future - (Christian Kreibich). - -- Much more extensive support for SMB, NetBIOS and NCP (Chris Grier). - -- The new attribute &priority=n defines the order of execution for handlers - of the same event (Robin Sommer). Handlers with higher priority are - executed first. n is an integer expression that must evaluate to a - constant when the script is loaded. - - Example: - > cat foo.bro - event bro_init() &priority = -5 { print -5; } - event bro_init() &priority = 5 { print 5; } - event bro_init() { print 0; } # default priority=0 - > ./bro foo.bro - 5 - 0 - -5 - - The connection_state_remove() handler in conn.bro now has priority - -10 and therefore executes after all other handlers for this event. - This fixes a long-standing problem of sometimes $addl fields not showing - up in connection summaries. - -- The new expressions record(...), table(...), set(...) and vector(...) - are constructors for the corresponding aggregate types (Vern Paxson). - For example, - - record($foo = "hi", $bar = -6) - - is the same as the existing constructor - - [$foo = "hi", $bar = -6] - - For tables, sets, and vectors, the "..." values within the ()'s have - the same syntax as those that you can list in variable initializations. - For example, - - table([1, T] = "black", [4, F] = "red") - - returns a table of type "table[count, bool] of string". - - set(4, 3, -1) - - is a value of type "set[int]". - -- You can associate attributes with table() and set() constructors - (Robin Sommer). For example: - - local s = set(1.2.3.4) &read_expire = 5 secs; - - associates a 5-second read expiration with the set assigned to s. - -- Bro now explicitly supports port numbers reflecting a transport protocol - type of "unknown" (Christian Kreibich). Currently, this means "not TCP, - UDP or ICMP". The numerical value of such a port is the IP protocol, - so ranges from 0..255. For example: - - global p: port = 0/unknown; - - print fmt("%s", p); - print fmt("p is TCP? %s", get_port_transport_proto(p) == tcp); - print fmt("p is unknown? %s", - get_port_transport_proto(p) == unknown_transport); - - yields - - 0/unknown - p is TCP? F - p is unknown? T - - In comparisons of different protocol types, the following holds: - unknown < TCP < UDP < ICMP. - -- If your system supports "GeoIP" (see http://www.maxmind.com/app/geolitecity - for a corresponding city database), then the new script function - - lookup_location(a: addr): geo_location - - returns a record of geographic information associated with an address - (Seth Hall). The geo_location record has $country_code, $region and - $city fields. If no information is available, each of these will be - set to empty strings. - - If Bro hasn't been configured with GeoIP support, or if the address is - IPv6 that cannot be directly converted to IPv4, then Bro produces a - run-time error and likewise returns empty strings. - -- Signature-matching on HTTP components now processes the URI with - escape sequences expanded (Robin Sommer). Ideally, there would be - two signature keywords, one for decoded URIs (corresponding to this - case) and one that allows matching against the URI as originally - transmitted. - -- The connection compressor is no longer considered experimental, and - is used by default (Robin Sommer). - -- The new function lookup_hostname(host: string): addr_set asychronously - looks up the IPv4 address(es) of the given host via DNS (Robin Sommer). - Like lookup_addr(), this function can only be used within a "when" - statement. - -- The new built-in - - raw_bytes_to_v4_addr(s: string): addr - - takes a string that points to at least 4 bytes, and returns an address - corresponding to interpreting these as being an IPv4 address in network - order (Vern Paxson; suggested by Mike Dopheide). - -- Trace-rewriting support for DNS, SMB (Chris Grier). - -- The new script function find_all(str: string, re: pattern): string_set - returns a string_set giving all occurrences of the pattern "re" in - the string "str" (Robin Sommer). (Note that string_set's are unordered.) - -- The new policy script save-peer-status.bro generates a log - to peer_status.$BRO_LOG_SUFFIX of updates received from - communication peers (Robin Sommer). - -- The policy script print-filter.bro now includes two (scoped) variables, - terminate_bro and to_file, which control whether to exit after printing - the filter (default T) and whether to write to the log file - pcap_filter.$BRO_LOG_SUFFIX or (default) to stdout (Robin Sommer). - -- The new script variable check_for_unused_event_handlers controls whether - Bro checks for unused event handlers (Robin Sommer). It defaults to T, - which was the past behavior (always report). - -- Bro now terminates if the only pending activity is future timers - (Robin Sommer). It used to wait for those timers to expire, but this - can cause fundamental problems if the timers are associated with table - management (since these might never completely drain). - -- Tables and sets inside of records are now initialized to empty - values rather than uninitialized (Vern Paxson). - -- A new variable allow_services_from (in hot.bro) complements the - existing allow_service_to variable (Brian Tierney). It specifies - that access to the given service from the given originator is - allowed. - -- global_sizes() no longer reports internal variables (Robin Sommer). - -- The IRC analyzer is now activated if any of the (many) IRC event - handlers are defined (Robin Sommer). - -- The default value for tcp_close_delay is now 5 sec rather than 0 sec - (Robin Sommer). This prevents some spurious connection events. - -- Improved logic for dealing with "reversed" connections such - as backscatter (Vern Paxson). - -- You can now left-justify fields when using fmt() with "%-" like - in sprintf (Christian Kreibich). - -- Updates to DNS query types (Larry Leviton). - -- Added mechanism to http-header.bro to skip printing some HTTP headers - (Larry Leviton). - -- The IrcHotWord notice now sets the associated connection (Robin Sommer). - -- If a notice has a tag, it's no longer overridden (Robin Sommer). - -- ServerFound notices now set the port field (Robin Sommer). - -- The built-in lookup_ID() now returns the string "" if the - ID does not exist, rather than a run-time error (Robin Sommer). - -- The new tuning option ProtocolDetector::suppress_servers specifies a - set of analyzers for which Bro generates ServerFound notices, but not - ProtocolFound (Robin Sommer). This both reduces log file size and - conserves memory. - -- A new notice_action_filter, tally_notice_type_and_ignore, works the same - as tally_notice_type but returns IGNORE (Robin Sommer) - -- Setting summary_interval == 0 disables the creation of irc-bots.summary.log - (Robin Sommer). - -- If you @load foo and a directory "foo" is in your path, Bro no longer - tries to load it (Robin Sommer). - -- A number of BinPAC fixes and enhancements (Ruoming Pang, Chris Grier - and Vern Paxson). - -- BinPAC now resides in aux/binpac rather than src/binpac (Ruoming Pang - and Christian Kreibich). This reflects a decoupling of it from Bro so - that it can be used to generate protocol analyzers for other projects too. - -- Removed example Inktomi entries from skip_scan_sources initialization, - since they no longer exist (Vern Paxson). - -- The variable make notice_once_per_orig_tally_interval is now - redef'able (Brian Tierney). - -- SIGPROF to the communication child process now logs resource stats to - remote.log (Matthias Vallentin). - -- The new built-in getpid(): count returns Bro's process ID (Robin Sommer). - -- Patterns for detecting IRC-based bots updated (Robin Sommer). - -- irc-bot-syslog now logs just bots, not all IRC client/servers (Robin Sommer). - -- The new variable suppress_notice_actions in notice.bro suppresses - notice_actions events for selected notice types (Robin Sommer). - -- Files opened during operation now rotate just like those opened at - startup (Robin Sommer). - -- ResourceStats now also logs elapsed time and the reported number of - packets-on-the-link (Mark Dedlow). - -- Printing a "file" value now produces its name (Robin Sommer). - -- Removed deliberate truncation of payload in port 80 FIN packets - (Vern Paxson). - -- remote.log now includes received peer_descriptions (Robin Sommer). - -- Significant POP3 analyzer speed-ups (Vern Paxson). - -- Updated README (Vern Paxson). - -- Fix for "@load a" followed by "@load a.bro" not loading the same file - twice (Robin Sommer). - -- Bug fixes for propagating state operations to uninitialized variables - and for spurious state inconsistency messags (Robin Sommer). - -- Bug fix for sending final sync-points during pseudo-realtime mode - (Robin Sommer). - -- Fix for possible buffer overflow (Christian Kreibich). - -- Bug fix for spurious end-of-file's during inter-Bro communication - (Robin Sommer). - -- Bug fix for dpd_match_only_beginning=F (Robin Sommer). - -- Bug fix for updating timestamps (Christian Kreibich). - -- Bug fix for skipping ADU processing in adu.bro (Christian Kreibich - and Zhichun Li). - -- Fix for ICMPs that carry ICMP headers (or non-TCP/UDP/ICMP headers) - within them (Vern Paxson). - -- Fix for files being rotated after the timer queue has been deleted - (Vern Paxson). - -- Bug fix for signature-matching with IPv6 subnets (Vern Paxson). - -- Bug fix for connection compressor setting connection origin (Robin Sommer). - -- Bug fix for interconn.bro when processing peculiar connections (Vern Paxson). - -- Fix for off-by-one buffer in sscanf call (Christian Kreibich). - -- Fixed inefficiency/warning flagged by g++ (Vern Paxson). - -- Bug fix for NUL string termination in SMB processing (Zhichun Li). - -- Fix for over-ref'ing of file Val's (Vern Paxson). - -- Fixes for some g++ warnings (Christian Kreibich, Vern Paxson). - -- gcc 3.4.2 portability fixes (Robin Sommer). - -- Minor build fixes for Broccoli, including a version bump to match that - of Bro. See aux/broccoli/ChangeLog for details. - -- distcheck fixes (Christian Kreibich). - -- Configuration portability fixes (Matthias Vallentin, Jean-philippe Luiggi). - -- OpenBSD portability fixes (Jean-philippe Luiggi, Christian Kreibich). - - -1.2.1 Mon Dec 11 16:22:58 PST 2006 - -- Fixed delayed triggering of new_connection events when using the - connection compressor. - -- Fixed tracking of first packet in TCP analyzer. (Reported by Guohan Lu) - -- The syslog built-in got lost during some previous merge. - -- Fixed crash if local variable is given as timeout value for table. - (Reported by Mike Wood.) - -- Fixed using "time" values as table indices. - -- Added ssh to default brolite DPD configuration. - -- Fixed catching up to real-time in case of lull. - -- Fixed Broccoli "BRO_DATA_FORMAT_VERSION" to match version in Bro. - -- Fixed Makefile problem in doc directory. - -- Fixed Makefile dependency problem in binpac directory. - -- Added Linux tuning to brolite install script. - -- Modified Makefile to include broccoli/contrib. - -- Adding missing initialization to remote serializer. - -- Minor documentation updates for reference manual and Broccoli. - - -1.2 Tue Oct 17 12:09:49 PDT 2006 - -- Bro now supports DPD, dynamic protocol detection (Robin Sommer, Holger - Dreger, and Michael Mai). With DPD, Bro can analyze protocols regardless - of what port numbers they use: it infers the protocol based on which - application analyzers can parse it without error. Adding this functionality - involved extensive changes to Bro's internals, but also now enables - multiple Bro analyzers to work on the same connection, either concurrently - or one nested inside the other (we have not taken much advantage of this - latter capability yet, but see the FTP events discussed below). - - There are a number of new policy scripts, events, and variables associated - with DPD processing, as follows. - - Scripts: - - You activate DPD by @load'ing dpd.bro. It in turn instructs Bro - to load the signature file policy/sigs/dpd.sig. Note that Bro - uses signatures to expedite deciding which analyzers to try on - a given connection; it does *not* simply use the signatures to - make the determination of which protocol is in use, as this is - insufficiently robust. (At this point, Bro provides signatures - for FTP, IRC, HTTP, SMTP, and SSH. In the future we plan to add - other protocols.) - - Along with dpd.bro, you need to @load detect-protocols.bro or - detect-protocols-http.bro. The former enables general detection - of application-layer protocols, while the latter does further - inspection of HTTP sessions to characterize applications running - on top of HTTP such as Gnutella or SOAP. (Loading dpd.bro - is separate from loading one of these scripts because in principle - Bro could use a different means than signatures to activate - the analyzers, although currently it does not.) - - If you @load dyn-disable.bro, then once an analyzer determines - that it does not match a given connection, it is deactivated - (and a Notice is generated). Otherwise, it still proceeds to try - its best to analyze the connection (to possibly be more robust - against evasion). - - The scripts dce.bro and smb.bro enable DPD for the Windows DCE and - SMB protocols, respectively. (Note that analysis of these protocols - is undergoing a major expansion, not yet complete.) - - Events: - - event protocol_confirmation(c: connection, atype: count, aid: count) - Generated when the given connection has been confirmed as - conforming with the application type (protocol) specified - by atype. aid is a globally unique analyzer ID that identifies - a particular analyzer instance. - - The values for atype are symbolic names associated with - each of Bro's analyzers, such as ANALYZER_IRC. See the - initialization at the beginning of Analyzer.cc for the - full set of names. - - The function analyzer_name(atype: count): string translates - these symbolic names into text. For example, - - analyzer_name(ANALYZER_IRC) - - yields "IRC". - - event protocol_violation(c: connection, atype: count, aid: count, - reason: string) - Generated when the given connection has been found to - violate the protocol of the given application type, with - "reason" giving details. - - Variables: - - dpd_buffer_size: count (default 1024) - Specifies how much pending data Bro keeps for connections - that have not been classified yet. Once this fills, the - data is deleted, though classification can still continue - (see below). - - dpd_match_only_beginning: bool (default T) - If set, specifies that Bro should stop signature matching - if it has processed dpd_buffer_size bytes. - - dpd_ignore_ports: bool (default F) - If set, then Bro does not take into consideration the port - numbers associated with connections when attempting to - classify them (which can otherwise help the process in - some cases). - - dpd_reassemble_first_packets: bool (default T) - If set, then Bro does TCP stream reassembly before applying - signature-matching to detect protocols. - - likely_server_ports: set[port] - Specifies a list of ports that Bro will consider as likely - used by servers. For example, if Bro sees a connection - that has already been established (so it does not know - which side sent the initial SYN), and one side uses a port - in this set, then it will assume that that side is the - server (connection responder). The set is empty unless - you populate it or @load server-ports.bro, which specifies - a large number of values. - - dpd_config: table[AnalyzerTag] of dpd_protocol_config - Specifies the DPD configuration associated with each tag. - The type dpd_protocol_config is simply: - - type dpd_protocol_config: record { - ports: set[port] &optional; - }; - - i.e., an optional $ports field specifying a set of ports - associatd with the tag. For example, ftp.bro now includes - the equivalent of: - - redef dpd_config += { - [ANALYZER_FTP] = [$ports = 21/tcp] - }; - - Functions: - - The function - - expect_connection(orig: addr, resp: addr, resp_p: port, - analyzer: count, tout: interval) - - is called to alert Bro that a new connection is expected, initiated - by orig to a server running on resp's port resp_p (note: orig's port - is not specified) which will correspond to the specified analyzer - (e.g., "FILE", which is used to analyze files transferred by FTP - - see next item). "tout" is a timeout to associate with the waiting. - - The function - - function disable_analyzer(cid: conn_id, aid: count) - - instructs Bro to disable the analyzer that generated the current - event, assuming the analyzer is associated with the given connection - ID. This is used by the dyn-disable.bro script discussed above. - -- A much more complete BinPAC compiler, along with new HTTP, DNS, and - RPC/Portmap analyzers in binpac (Ruoming Pang). The flag "--use-binpac" - activates the BinPAC-based analyzers (currently for HTTP and DNS). - See www.cs.princeton.edu/~rpang/binpac-paper.pdf for a description of - BinPAC, and let Ruoming know if you are interested in using BinPAC to build - new analyzers. - -- A new type of analyzer, FILE, analyzes the contents of a connection as - though it were a data file (Robin Sommer). Currently, it can generate - two events: - - event file_transferred(c: connection, prefix: string, descr: string, - mime_type: string) - Indicates that the connection transferred a file. "prefix" - is the beginning of the file's data; "descr" and "mime_type" - are indicators of the file's type, as reported by the - "libmagic" library. - - descr/mime_type are only set if Bro is configured on a - system that includes the "libmagic" library. - - event file_virus(c: connection, virname: string) - Indicates the connection transferred an executable - corresponding to a known virus of the given name. - - This functionality is only available if Bro is configured - on a system that includes the "libclamav" library. - - Note, this analyzer is enabled via a call to expect_connection by - the FTP analyzer. - -- New events relating to IRC analysis (Robin Sommer): - - event irc_client(c: connection, prefix: string, data: string) - Generated upon seing a client message sent over the given - IRC connection. "prefix" is the command's prefix as defined - by the IRC protocol. It is used by servers to indicate the - true origin of the message; it may be empty. "data" contains - the message. - - event irc_server(c: connection, prefix: string, data: string) - Same for server messages. - - event irc_user_message(c: connection, user: string, host: string, - server: string, real_name: string) - Generated upon seeing an IRC "USER" command. - - event irc_password_message(c: connection, password: string) - Generated upon seeing an IRC "PASS" command. - - event irc_channel_topic(c: connection, channel: string, topic: string) - Generated upon seeing an IRC server reply that includes - the channel topic. - - event irc_global_users(c: connection, prefix: string, msg: string) - Generated upon seeing an IRC server reply that includes - a count of the number of IRC users. - -- The new experimental script irc-bot.bro tracks IRC-based bots (Robin Sommer). - The accompanying script irc-bot-syslog.bro syslog's the state of the - bot analysis every IrcBot::summary_interval seconds (default 1 minute). - -- The new script proxy.bro looks for open Web proxies by matching incoming - requests to a server with outgoing requests it makes (Robin Sommer). It - generates HTTPProxyFound Notices when it finds one. - -- Changes to notices.bro (Robin Sommer): - - - notice_policy_item's now have a default $result of - NOTICE_FILE and a default $priority of 1. - - - The new notice_action_filter, notice_alarm_per_orig, alarms - on the first NoticeType from a specific source. Subsequent - instances are tallied. - - - notice_action_filters now reside in the new script - notice-action-filter.bro (automatically loaded by notice.bro). - - - The notice actions NOTICE_ALARM_PER_CONN, NOTICE_ALARM_PER_ORIG, - and NOTICE_ALARM_ONCE have been removed, as they were never - actually implemented. - - - If the notice_policy returns IGNORE or FILE, the action_filters - filters are no longer consulted. - -- A new attribute for tables and sets, &mergeable, changes the semantics - of assignments, as follows (Robin Sommer). Given two &mergeable tables/sets - A and B, an assignment "A = B" becomes actually a join "A = A \cup B" - (i.e., union). The envisoned use is to help avoid race conditions - when doing remote state synchronization. - -- The semantics of &synchronized expire_funcs has changed (Robin Sommer). - Now, when a table entry is expired and the operation is propagated to a - a peer, the peer will call its expire_function. - -- TRW analysis now skips UDP traffic because it currently treats - all UDP connections as failures (Robin Sommer). - -- trw.bro has been split into trw-impl.bro (the algorithm) and - trw.bro (which simply activates the analysis), to facilitate writing - scripts that have hooks into TRW analysis but don't presume it's - active (Robin Sommer). - -- The option report_remote_notices in remote.bro has been replaced - by a new script you include, remote-report-notices.bro (Robin Sommer). - -- The new function connect_peer() explicitly connects to a remote host - (Robin Sommer). - -- The new script remote-send-id.bro sends the current value of an ID - to a remote Bro and then terminates processing (Robin Sommer). It's - intended for use from the command-line, as in - - bro -e "redef dst="" id="" remote-send-id - - The other scripts must set up the connection. is an index into - Remote::destinations corresponding to the destination. - -- New built-ins {suspend,resume}_state_updates() can be called to - temporarily avoid propagating updates to &sync'ed values (Robin Sommer). - This can avoid duplicated activity. - -- The new function terminate_communication() instructs Bro to end its - communication with remote peers (Robin Sommer). - -- The new event remote_state_access_performed is raised when remote state - access has been performed (Robin Sommer). This is primarily for debugging. - -- The log() built-in has been renamed to ln() to avoid conflict (Vern Paxson). - -- bifcl now generates event generation wrapper functions from event.bif - (Ruoming Pang). For example, to generate event http_reply, currently - one writes: - - val_list* vl = new val_list; - vl->append(BuildConnVal()); - vl->append(new StringVal(fmt("%.1f", reply_version))); - vl->append(new Val(reply_code, TYPE_COUNT)); - if ( reply_reason_phrase ) - vl->append(reply_reason_phrase); - else - vl->append(new StringVal("")); - ConnectionEvent(http_reply, vl); - - In the future, one will be able to just call bro_event_http_reply(), and - the code generated by bifcl looks like: - - void bro_event_http_reply(Connection* c, StringVal* version, - bro_uint_t code, StringVal* reason) - { - val_list* vl = new val_list; - - vl->append(c->BuildConnVal()); - vl->append(version); - vl->append(new Val(code, TYPE_COUNT)); - vl->append(reason); - - mgr.QueueEvent(http_reply, vl, SOURCE_LOCAL, c); - } - - Accompanying this change is a semantic shift to types "string" and "port" - in .bif files. They used to be translated to C++ types BroString* and - uint32, respectively. Now they are translated to StringVal* and PortVal*. - The functions in bro.bif are changed accordingly, and please be aware - of this change when you write built-in functions in future. - - Also for this change, the parameter 'new' for rsh_request has been renamed - 'new_session', as 'new' is a reserved word for C++. - -- Some ICMP "connections" now have services identified ("icmp-echo", - "icmp-unreach") rather than just listing the service as "other" - (Ruoming Pang). - -- The new option remote_trace_sync_interval specifies an interval after - which each Bro will stop processing its trace and wait for all others - to signal that they have reached the same time (Robin Sommer). The - intent is support for operating Bro in a distributed cluster fashion - (and in particular for debugging such clusters when running off-line - on traces). - - This option only works in pseudo-realtime mode, and requires the new - global remote_trace_sync_peers to give the total number of remote peers - (not including self). Signaling is done via a new communication message - type. - -- Extensions for DNS transformation/anonymization, including introduction - of trace transformation for protocols other than TCP (Jason Lee). - Not yet fully developed/debugged. - -- Extensions for HTTP transformation/anonymization (Martin Casado). - Not yet fully developed/debugged. - -- The $conn field is now included in HTTPProxyFound notices (Robin Sommer). - -- Changed service inference algorithm to favor lower-numbered - likely-servers over higher-numbered ones (Vern Paxson). - -- In pseudo-realtime mode, Bro now uses real-time for deciding which - peer should send state (Robin Sommer). - -- Time synchronization for Bro's running on traces in pseudo-realtime mode - added (Robin Sommer). - -- Avoidance of false content gaps improved when sorting packets with - out-of-order timestamps (Ruoming Pang). - -- Packets from the packet sorter are now more robustly drained upon - termination of input (Ruoming Pang). - -- Documentation for deep-copy updated (Christian Kreibich). - -- Nasty fragment reassembly bug fixed (Vern Paxson). - -- Serious bugs in EDNS0 processing fixed (Vern Paxson). - -- Fixed significant misfeature of interconn.bro that stopped all processing - of a connection once it makes a detection (Vern Paxson). - -- Fixes for &read_expire operation across synchronizes tables (Robin Sommer). - -- Fixes for multiple peers exchanging initial &sync state simultaneously - (Robin Sommer). - -- Improvements to graceful termination of Bro when communicating with - remote peers (Robin Sommer). - -- Fix for ICMP analyzer not always generating icmp_sent events - (Robin Sommer). This appears to still need some work, as now - it generates redundant events. - -- Fix for initial exchange of &sync state which could lead to - referencing unknown IDs (Robin Sommer). - -- Fix to scan detection for differing semantics of connection compressor - vs. non-compressor (Robin Sommer). - -- Bug fix for distinguishing regular expression matches of length 0 from - those of length 1 (Ruoming Pang). - -- Fix for SSH version parsing in the presence of content gaps (Robin Sommer). - -- Bug fix for IRC that could lead to crashes (Robin Sommer). - -- Bug fix to refrain from adding new timers when a connection has - already been removed from the connection table (Robin Sommer). - -- Bug fix for packet_contents not including the transport-layer header - (Robin Sommer). - -- Some memory leaks fixed (Robin Sommer). - -- A bunch of portability and distribution problems fixed (Christian - Kreibich, Robin Sommer, Vern Paxson). - - -1.1 Mon May 15 10:50:33 PDT 2006 - -- Bro now supports a "when" statement for taking action upon something - becoming true asynchronously (Robin Sommer). This provides a powerful - new mechanism with numerous applications. - - Syntax: - - when '(' ')' [timeout '{ '}'] - - where the first can be a single statement or a block enclosed - in {}'s, but the set associated with "timeout" must be enclosed in - {}'s (to reduce ambiguities in Bro's grammar). - - Bro executes the first statement when becomes true. If you give - a timeout and the condition has not been satisfied before it expires, Bro - executes the second statement instead. - - A simple example: - - global t: table[addr] of count; - event connection_established(c: connection) - { - local orig = c$id$orig_h; - if ( orig !in t ) - { - t[orig] = 1; - - when ( t[orig] == 5 ) - print fmt("%s has established 5 connections", orig); - timeout 1 hr - { - print fmt("%s has NOT established 5 connections", orig); - delete t[orig]; - } - } - else - ++t[orig]; - } - - Notes: - - The condition may be evaluated more than once, and at arbitrary - times. - - - When the when-body is executed, the condition is guaranteed to be - still satisfied. - - - Expression reevaluation is primarily triggered by modifications - to globals. However, reevaluations do not take place immediately - but potentially at a later point. This means that if we change a - global to a value which would execute the trigger but then change - it back, the change may go unnoticed. - - - Inside the condition you may introduce new locals. For example, - - when ( (local x = foo()) && x == 42 ) ... - - Such an assignment always yields true as its expression value - (but the assignment might be delayed, for example if foo() is - a delayed function call - see below). - - Delaying function calls - ======================= - - Functions called inside the condition of a when-clause may delay their - results until they're ready. This works for both script-level and built-in - functions. - - For script-level functions, there is a new construct, "return ", - to delay a function's result. When used, the function returns at the - time the when-stmt's condition becomes true, and it yields the value - that the when-stmt's body then returns. Toy example: - - global X: table[string] of count; - - function a() : count - { - # This delays until condition becomes true. - return when ( "a" in X ) - { - return X["a"]; - } - timeout 5 min - { - return 0; - } - } - - event bro_init() - { - # Installs a trigger which fires if a() returns 42. - when ( a() == 42 ) { print "Yippie!"; } - - X["a"] = 42; - } - - There's also a new built-in function which can delay - - lookup_addr(host: addr) - - performs asynchronous DNS address->hostname lookups. Example: - - local h; addr; - [...] - when (local name = lookup_addr(h)) { print h, name; } - - See the function gen_hot_notice_with_hostnames() in conn.bro for - a more worked-out example of using the "when" clause to translate the - local address in SensitiveConnection notices to a hostname (contributed - by Brian Tierney). This functionality is activated by redef'ing - xlate_hot_local_addr to T. - - Here is the full evaluation model of a when's condition: - - - The condition may be evaluated more than once, at arbitrary times. - - - It is always fully evaluated, no matter whether some former - evaluation has been suspended by a delaying function call. - - - All function calls which do not delay are always *fully* executed - each time the condition is evaluated. - - - Function calls which delay are only executed *once*; their result is - cached and re-used in the case the condition is evaluated again. - - - The condition is guaranteed to be true when the body is executed - (potentially using cached function results) - -- By default Bro now uses a configuration similar to what used to be - activated using reduce-memory.bro, along with some additional state - timeouts that are new (Robin Sommer and Vern Paxson). This allows for - better state management out-of-the-box, at the cost of some precision - of analysis and resilience to evasion. In particular, the intent is to - move towards being able to run Bro continuously without inexorably growing - the amount of memory used until exhaustion. - - You can access a configuration similar to the previous default state - management settings by loading heavy-analysis.bro. It turns on a - load-prefix of "heavy", so when you load XXX.bro, a file heavy.XXX.bro - will also be automatically loaded if present. Note that, as was the - case for reduce-memory, you need to load heavy-analysis prior to other - files for it to have effect. - -- The new module clear-passwords.bro monitors login/FTP/IRC/POP traffic - for cleartext passwords (Jason Lee). - -- The new script service-probe.bro looks for remote hosts that repeatedly - connect to the same service on local hosts (for a configurable set of - services and connection sizes) in order to detect brute-forcing attacks - such as password-guessing (Jim Mellander). - -- A new ARP analyzer generates three events: - - event arp_request(mac_src: string, mac_dst: string, - SPA: addr, SHA: string, TPA: addr, THA: string); - - event arp_reply(mac_src: string, mac_dst: string, - SPA: addr, SHA: string, TPA: addr, THA: string); - - event bad_arp(SPA: addr, SHA: string, TPA: addr, THA: string, - explanation: string); - - with a corresponding policy script arp.bro (Chema Gonzalez and Vern Paxson). - It writes logs to arp.$BRO_LOG_SUFFIX. It has not been tested much yet. - -- Bro Lite changes (Jason Lee): - - default user for is now user 'bro' - - now uses the correct sysctl on FreeBSD 6 - - now uses the correct Perl path if site-report.pl not installed - into '/usr/local/bro' - - no longer prompts to encrypt email unless you pick to email reports - -- The default Bro Lite install now only checkpoints Bro once a week - (Brian Tierney). - -- Implicit Bro file extensions (such as .bro for policy scripts and .sig - for signatures) are now searched for first rather than only if the - non-extension-version of the file doesn't exist (Vern Paxson). For - example, running "bro -r trace mt" now first searches $BROPATH for - "mt.bro" before searching for "mt", whereas it used to do these in - the other order. - -- There's now a simpler mechanism for redef'ing variables on the command-line - (Christian Kreibich). Any command line arguments of the form = - are now expanded into policy code of the form "redef var=val;", where - is wrapped in quotation marks if the value appears to be a string - and doesn't have quotation marks already. This works with strings with - whitespace such as foo="Hello World"; however, note that it means you - can't use the mechanism to redef an enum value. - -- The Bro distribution now includes (and builds by default) Christian - Kreibich's Broccoli library (Bro C Client Library), which enables programs - to communicate with running Bro's (Christian Kreibich and Jason Lee). - Configure with --disable-broccoli to turn this off. - -- Built-in functions log(x: double): double and exp(x: double): double - which do natural logarithms and their inverses (Jaeyeon Jung). - -- The new built-in function gethostname() returns the local host's name - (Jason Lee & Robin Sommer). - -- The new built-in function reading_traces() returns true if Bro - is reading trace files (Robin Sommer). - -- The new built-ins suspend_processing() and continue_processing() provide - script-level control for instructing the event engine to stop or resume - processing packets (Robin Sommer). This is useful for coordinating - simultaneous processing by multiple Bro's. - -- Email notices are now by default sent via /bin/mail, with "[Bro Alarm]" - in the subject. - -- redef'ing a function now replaces the existing body rather than - supplementing it (Robin Sommer), which was a bug. - -- You can now configure Bro to process encapsulated IP packets either - by setting, as before, a fixed encap_hdr_size (for VLANs), or setting - parse_udp_tunnels to T (Ruoming Pang). For the latter, you specify a - UDP tunnel port using udp_tunnel_port (the previous variable "tunnel_port" - has gone away); or you can leave it set to its default of 0/udp, in which - case Bro will look for IP encapsulated in UDP packets on any port. - -- Added a simple form of profiling based on sampling the work done - per-packet (Vern Paxson). The event engine generates a - - event load_sample(samples: load_sample_info, CPU: interval, dmem: int) - - event every load_sample_freq packets (roughly; it's randomized), where - load_sample_freq defaults to 20. "samples" is simply a set[string]; it - contains the names of the functions, event handlers, and their source - files that were accessed during the processing of the sampled packet, - along with an estimate of the CPU cost of processing the packet and - (currently broken) memory allocated/freed. - -- Bro now includes experimental support for Endace DAG cards (Gregor Maier - and Robin Sommer). To activate, configure with - - --with-DAG=/path/to/dagtool/installation - - and use "dag0" as the network interface. You may need to configure the - card with the dagtools first. In general, if dagsnap works, Bro should - work as well. - -- Log rotation has changed in a number of ways (Mark Dedlow & Robin Sommer): - - * The new variable log_rotate_base_time: string, if defined, - specifies that logs should be rotated at log_rotate_base_time + - i * rotate_interval intervals. Format is as a string in - 24-hour time, "%H:%M", e.g, "12:00". This format may change - in the future to instead be a Bro time type. - - * RotateLogs::date_format can be redefined to change format of - timestamps in rotated files. - - * RotateLogs::build_name() can be redefined to implement an - arbitrary naming scheme for rotated files. - - Note, this code has not been extensively tested. - -- Bro now by default builds a version of malloc bundled with its - distribution (Vern Paxson & Brian Tierney). - -- The syntax for the clone operator now looks like a function call, - "copy(x)" (Vern Paxson). - -- The new flag DNS::logging (default F), if T, disables generation of - dns.log (which is often uninteresting and very large), though it - still performs analysis leading to NOTICEs (Robin Sommer). - -- A new global, hostile_domain_list, has been added to dns.bro which - lists domains to be flagged if A or MX records are queried (Scott Campbell). - -- Added globals dns_skip_all_{auth,addl} to skip all DNS AUTH/ADDL processing - (Vern Paxson). Skipping these is on (true) by default, because such - processing is quite expensive. - -- backdoor.bro now turns off by default some detectors that from experience - have too many false positives, or (such as for HTTP) too many uninteresting - true positives (Brian Tierney). In addition: - - - the module now generates a BackdoorFound notice for each backdoor - - - the new variable dump_backdoor_packets (default F) if set causes - the packet that triggered the backdoor detection to be written to - backdoor-packets/: